由于去年的缺芯潮,原本基于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函数后再打开。
修改后运行了几个月,暂未再重新出现问题。