由于去年的缺芯潮,原本基于STM32F105的设备需要pin对pin换成GD32F105。代码直接使用的ST库微修改。
设备装在重柴车上,开始一两个月是没啥问题的。后面出现了休眠后无法唤醒的问题。设置stop模式前,振动传感器中断引脚和CAN的RX引脚设置为外部中断。结果都无法唤醒。使用ST时,不会出现这个问题。
和GD的FAE现场调试,最终确认问题出在stop休眠函数上。
而且在GD的官网上,找到了一份《关于 deep-sleep 模式的使用说明》,GD32系列MCU都有这个问题???也是挺无语的。
原ST的stop函数如下:
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDS bits */
tmpreg &= CR_DS_MASK;
/* Set LPDS bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
修改后:
//GD32F105
void GD_PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
static uint32_t reg_snap[ 4 ];
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDS bits */
tmpreg &= CR_DS_MASK;
/* Set LPDS bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
reg_snap[ 0 ] = (*(volatile uint32_t *)(0xE000E010));//REG32( 0xE000E010 );
reg_snap[ 1 ] = (*(volatile uint32_t *)(0xE000E100));//REG32( 0xE000E100 );
reg_snap[ 2 ] = (*(volatile uint32_t *)(0xE000E104));//REG32( 0xE000E104 );
reg_snap[ 3 ] = (*(volatile uint32_t *)(0xE000E108));//REG32( 0xE000E108 );
(*(volatile uint32_t *)(0xE000E010)) &= 0x00010004; //( 0xE000E010 )
(*(volatile uint32_t *)(0xE000E180)) = 0XFF7FF83D; //( 0xE000E180 )
(*(volatile uint32_t *)(0xE000E184)) = 0XBFFFF8FF; //( 0xE000E184 )
(*(volatile uint32_t *)(0xE000E188)) = 0xFFFFFFFF; //( 0xE000E188 )
/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__SEV();
__WFE();
__WFE();
}
(*(volatile uint32_t *)(0xE000E010)) = reg_snap[ 0 ] ;
(*(volatile uint32_t *)(0xE000E100)) = reg_snap[ 1 ] ;
(*(volatile uint32_t *)(0xE000E104)) = reg_snap[ 2 ] ;
(*(volatile uint32_t *)(0xE000E108)) = reg_snap[ 3 ] ;
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
注意,使用GD芯片时,stop函数前,需要关闭滴答定时器,stop函数后再打开。
修改后运行了几个月,暂未再重新出现问题。