提要:costdown
前言:本以爲能很順利的移植,結果130這顆芯片雖然是M3的core,實際上外部PIN與GPIO等寄存器結構與M0一致,NVIC部分又與M3一致,簡言之,130即有M3的“基因”,也有M0的“基因”,主要這顆芯片是爲了與ST的M0芯片搶市場。由於剛上市,所以Library從ST M0的Library基礎稍作修改。寄存器名稱雖然不一樣,但是實際地址與功能是完全一樣。下面重點列出在移植過程中,我遇到的問題:
A0:在Keil中,Device選型:
A0:GD32f130c6應當選擇STM32F101C6/8,因爲該系列寄存器與GD130最接近。左圖爲100,右圖爲101,實際130的SPI包含I2SCFGR與I2SPR寄存器。
另外使用STLINK讀取的Device,如圖:
Q1、EXTI中斷無效?
A1:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
SYSCFG_EXTILineConfig(PWR_EXTI_PORT_SOURCE, PWR_EXTI_PIN_SOURCE);
其中在操作SYSCFG寄存器時,必須先使能SYSCFG的CLK,這個問題在M0上也是一樣的,但是我在移植過程中,忽略了這點。
導致花了一些時間才找到這個問題。找類似這種bug,兩方面着手,一用硬件仿真,看外設寄存器是否與預設一直;二設置完後直接串口打印出來。
Q2、NVIC配置部分需要增加下面兩句,M0無此配置,M3則有。
A2:
/* NVIC configuration for priority grouping */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
/*定位中斷向量表*/
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0);
另外中斷優先級配置因爲有組的概念,所以也有所不同,如;
STM32F051:
<span style="font-family: Arial, Helvetica, sans-serif;">NVIC_InitStructure.NVIC_IRQChannelPriority = 0x03; //0x03,與IRRec保持一致</span>
GD130:
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
Q3、EXTI在handler mode進入stop mode後不能喚醒,在thread mode中進入可以喚醒?
A3:
如果在Handler mode進入STOP mode,需要喚醒,則喚醒源的中斷優先級必須必進入stop mode的handler 優先級更高。否則同級或更低級的中斷無法喚醒,除非退出中斷。這也是在thread mode進入可以被喚醒的原因。如在timer2中進入stopmode,在exti按鍵喚醒。demo:
static void PWR_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTIx global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = PWR_EXTI_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
static void TIM2_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = KEY_TIM_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Q4:SPI寄存器區別:
A4:SPIx_CR1 Bit11,051中該bit(CRCL)是CRC length,130是FF16(FF16)是data frame formate;
SPIx_CR2 bit15-bit8,130中高8位爲保留字節,051則有其他定義,如fifo觸發值與data size。因此130中沒有該庫函數:
SPI_RxFIFOThresholdConfig(LT8900SPI, SPI_RxFIFOThreshold_QF); //8bitsize->QF,16bit->HF
通訊庫函數區別:
M0:
/* Send byte through the SPI1 peripheral */
SPI_SendData8(LT8900SPI, *pu32Data);
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(LT8900SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_ReceiveData8(LT8900SPI);
GD130:
/* Send byte through the SPI1 peripheral */
SPI_I2S_SendData(LT8900SPI, *pu32Data);
/* Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(LT8900SPI, SPI_I2S_FLAG_RXNE) == RESET);
/* Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(LT8900SPI);
Q5:使用HSE時,有效採樣數的區別:
A5:
ST
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x0500) /*!< Time out for HSE start up */
GD130:
#define HSE_STARTUP_TIMEOUT ((uint16_t)0x5000) /*!< Time out for HSE start up */
Q6:中斷向量表區別,GD兼容051,但又涵蓋M3的中斷入口。另外051不支持自定義中斷入口偏移地址。
A6:
/* 自動重定位中斷向量表 */
// NVIC_SetVectorTable(NVIC_VectTab_FLASH, (BaseOfROM - NVIC_VectTab_FLASH)); //CM0不支持該功能
Q7:GPIO區別:
A7:雖然130爲M3,但是GPIO部分與M0的寄存器結構完全一致。
Q8:Flash區別:
A8:雖然130爲M3,但是Flash部分與M0結構大概相同,包含對OB區域的讀寫與讀保護等級,多了一個燒斷功能,此時不能還原爲保護或無保護狀態。
加讀保護功能與M0一致,在使用JLink Flash中使用去除讀保護是,device必須選擇STM32F101系列,否則去除保護功能無效。
但有部分寄存器位有所不同,如:
FLASH->ACR = FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY; //M3不支持該設置
A9:M0中只有APB總線給外設提供CLK,但是M3中分了兩組不同的CLK對應不同的外設,分別爲APB1,APB2。如下:
M0:
uint32_t SYSCLK_Frequency;
uint32_t HCLK_Frequency;
uint32_t PCLK_Frequency;
uint32_t ADCCLK_Frequency;/* PCLK = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE_DIV1;
GD130:
uint32_t SYSCLK_Frequency; /*!< returns SYSCLK clock frequency expressed in Hz */
uint32_t HCLK_Frequency; /*!< returns HCLK clock frequency expressed in Hz */
uint32_t PCLK1_Frequency; /*!< returns PCLK1 clock frequency expressed in Hz */
uint32_t PCLK2_Frequency; /*!< returns PCLK2 clock frequency expressed in Hz */
uint32_t ADCCLK_Frequency; /*!< returns ADCCLK clock frequency expressed in Hz <span style="font-family: Arial, Helvetica, sans-serif;"> </span>
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
Q10:ID讀取位置:
Flashsize位置不同,130與M3一致,但UID卻與M0一致。如:
M0:
#define rFlashSizeReg (*((uint16_t *)(0x1ffff7cc)))
#define Stm32_UIDBase (uint8_t *)(0x1ffff7ac)
GD130:
#define rFlashSizeReg (*((uint16_t *)(0x1ffff7e0)))
#define Stm32_UIDBase (uint8_t *)(0x1ffff7ac)
Q11:電源特性區別:
A11:
(1)工作電壓2.6-3.6V,待機時電流爲250uA;;
(2)由於mcu啓動功耗大於st,因此mcu穩壓電容驗證將1uF改爲47uF,解決上電瞬間電流過大,電源特性不穩定,電壓輸出被拉低至2V被強制關機問題;
如下圖:
(1)進入stopmode休眠後,sensorpwr關閉,中斷喚醒後啓動,下圖爲電源端與sensorpwr端電壓圖形。GD32端穩壓電容爲1uF。
同樣由於上電瞬間電壓不穩導致無法啓動芯片,區別圖(3)。
(2)進入stopmode休眠後,sensorpwr關閉,中斷喚醒後啓動,下圖爲電源端與sensorpwr端電壓圖形。STM32端穩壓電容爲1uF。
3、GD130睡眠後被外部中斷喚醒的SensorPwr,SensorPwr端加47uF穩壓電容,可以正常啓動,但是睡眠後喚醒會出現電壓過低關機的現象。
(4)進入stopmode休眠後,sensorpwr關閉,中斷喚醒後啓動,下圖爲電源端與sensorpwr端電壓圖形。GD32端穩壓電容爲47uF,Sensor端爲1uF電容。
綜上,由於GD32啓動電壓較ST高0.6V,導致開機或休眠被喚醒瞬間電壓不穩導致關機,圖中多次啓動是因爲按鍵開關抖動導致多次觸發。
(5)待機功耗,如圖: