解决GD32F105休眠后无法唤醒的问题

由于去年的缺芯潮,原本基于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函数后再打开。

修改后运行了几个月,暂未再重新出现问题。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值