你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

stm32F401RC的芯片操作Flash后调NVIC_SystemReset() 卡死

[复制链接]
飞奔的皮卡丘 提问时间:2021-3-31 19:52 / 未解决
最近在做 stm32F401RC 开发时发现,在操作Flash后直接调用NVIC_SystemReset() 会极大概率卡死,不能正常复位。代码是基于stm32Cubemx,利用Hal库开发的。

为了调查,找了一个官方的demo 简单试了下擦除Flash,然后调NVIC_SystemReset()

void EraseFlash_Sample()
{
        uint32_t FirstSector = 0, NbOfSectors = 0, Address = 0;
        uint32_t SectorError = 0;
        __IO uint32_t data32 = 0 , MemoryProgramStatus = 0;

        /*Variable used for Erase procedure*/
        static FLASH_EraseInitTypeDef EraseInitStruct;
       
          /* Unlock the Flash to enable the flash control register access *************/
  HAL_FLASH_Unlock();

  /* Erase the user Flash area
    (area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/

  /* Get the 1st sector to erase */
  FirstSector = GetSector(0x08008000);
  /* Get the number of sector to erase from 1st sector*/
  NbOfSectors = GetSector(0x08008033) - FirstSector + 1;

  /* Fill EraseInit structure*/
  EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
  EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  EraseInitStruct.Sector = FirstSector;
  EraseInitStruct.NbSectors = NbOfSectors;
  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError) != HAL_OK)
  {
    /*
      Error occurred while sector erase.
      User can add here some code to deal with this error.
      SectorError will contain the faulty sector and then to know the code error on this sector,
      user can call function 'HAL_FLASH_GetError()'
    */
    /*
      FLASH_ErrorTypeDef errorcode = HAL_FLASH_GetError();
    */
    Error_Handler();
  }

  /* Note: If an erase operation in Flash memory also concerns data in the data or instruction cache,
     you have to make sure that these data are rewritten before they are accessed during code
     execution. If this cannot be done safely, it is recommended to flush the caches by setting the
     DCRST and ICRST bits in the FLASH_CR register. */
  __HAL_FLASH_DATA_CACHE_DISABLE();
  __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();

  __HAL_FLASH_DATA_CACHE_RESET();
  __HAL_FLASH_INSTRUCTION_CACHE_RESET();

  __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
  __HAL_FLASH_DATA_CACHE_ENABLE();
}


int main(void)
{
//初始化代码这里省略了xxx
    /* USER CODE BEGIN WHILE */
        HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
        Delayms(1000);
        EraseFlash_Sample();
//        //__set_FAULTMASK(1); //这行代码加与不加效果相同
        //Delayms(1000);   //这只是用while循环加计数的方式写的一个简单的延时函数
        NVIC_SystemReset()
        while(1)
        {}
    /* USER CODE END WHILE */

}



发现几乎是百分百会卡死,无法正常复位。(验证是否正常重启的方法是控制一个LED灯闪烁,这里没有体现)
在调用NVIC_SystemReset()之前,看过Flash的寄存器,没有发现异常。
此外,如果把main函数中的  Delayms(1000); 解除注释,也就是在擦除Flash后等待1s,再调NVIC_SystemReset() ,发生卡死的概率就变得很小。
请问题大佬有遇到过类似的问题么?

谢谢!
收藏 评论8 发布时间:2021-3-31 19:52

举报

8个回答
废鱼 回答时间:2021-4-1 14:13:05
楼主,您好。先确定关闭擦除后,是不是正常复位?
如果关闭后正常,说明擦除的地址不对,0x08008033这个地址是不是还在程序的代码范围内。建议看一下HEX文件或者BIN文件的大小。确定擦除FLASH的地址不要在程序的范围内。
飞奔的皮卡丘 回答时间:2021-4-1 20:44:16
飞羽一条 发表于 2021-4-1 14:13
楼主,您好。先确定关闭擦除后,是不是正常复位?
如果关闭后正常,说明擦除的地址不对,0x08008033这个地 ...

您好, 这个擦除的地址是在程序地址以外的。 而且我尝试过 擦除flash之后,延时等待1s,然后再调用reset接口,就是可以正常复位的。 也就是说本身这个复位接口也没问题。 我怀疑是不是可能调用擦除flash接口后,即使返回了OK,但是实际硬件状态还没有恢复正常,对复位产生了影响?    我不是很了解软复位的根本原理,但是我发现NRST引脚的电平发生了变化,因此用示波器进行了监测。“擦除flash后延时1s再调reset,正常复位” , “擦除flash后立刻调reset,复位异常”的情况分别进行了截图


正常.png
飞奔的皮卡丘 回答时间:2021-4-1 20:47:51
飞奔的皮卡丘 发表于 2021-4-1 20:44
您好, 这个擦除的地址是在程序地址以外的。 而且我尝试过 擦除flash之后,延时等待1s,然后再调用reset ...

补发示波器监测NRST引脚图片

擦除flash后立刻调reset,复位异常

擦除flash后立刻调reset,复位异常

擦除flash后延时1s再调reset,复位正常

擦除flash后延时1s再调reset,复位正常
butterflyspring 回答时间:2021-4-2 14:29:12
一般来说,FLASH 擦除执行会需要一段时间,楼主可以先不用调用复位函数,在后面翻转一个IO看看能不能测试出执行多长时间
废鱼 回答时间:2021-4-2 17:58:06
从现象上分析,像是擦除以后导致程序复位。建议在线仿真模式下,看看复位以后,进入哪种错误导致异常复位。
飞奔的皮卡丘 回答时间:2021-4-5 15:28:57
butterflyspring 发表于 2021-4-2 14:29
一般来说,FLASH 擦除执行会需要一段时间,楼主可以先不用调用复位函数,在后面翻转一个IO看看能不能测试出 ...

感谢回复。 我使用的是HAL库的API,API返回OK后,不是就代表擦除完成了么... 不过后面我会试下的
飞奔的皮卡丘 回答时间:2021-4-5 15:30:44
飞羽一条 发表于 2021-4-2 17:58
从现象上分析,像是擦除以后导致程序复位。建议在线仿真模式下,看看复位以后,进入哪种错误导致异常复位。 ...

波形上看,擦除后直接调reset 接口,出现了多次复位波形(写多个字节时也是相似的现象),但是如果只擦除,不调reset,mcu却并没有真的被reset

后门我在线仿真实施
飞奔的皮卡丘 回答时间:2021-4-13 11:47:17
这个问题目前还没有解决。 如果打断点进行单步调试,问题就很几乎不发生了(所以我之前才尝试进行了delay延时操作)


根据我附件上传的图片来看,刚擦除flash就立刻调用reset接口,NRST管脚的电平降低又拉高,但没有拉倒正常高电平之前又重新降低,再拉高,反复多次后,在拉高。  这时就已经卡死了...   现象上感觉看非常奇怪...
(擦除flash后 delay 1s 再调用reset接口,NRST管脚的电平就只有一次降低又拉高,且拉高到正常高电平,问题不发生)


关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版