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

STM32F412擦除内部FLASH时间过长

[复制链接]
aimejia 发布时间:2018-5-22 14:36
本帖最后由 aimejia 于 2018-5-23 11:31 编辑

1 前言     
  客户反馈在使用STM32F412的时候,擦除sector 8~11发现时间过长,从而导致意外触发IWDG复位。

2 问题分析
2.1 问题详情
     通过与客户邮件和电话沟通,了解到客户主要是想使用内部FLASH暂时保存IAP升级时的程序数据,在IAP升级的过程中,需要首先擦除内部FLASH中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到IWDG,喂狗间隔大约1.5S,客户的通过SysTick的方式计算出擦除Sector8大约需要2ms,因此认为若一次擦除sector8~11大约需要8ms,于是在代码中一次性擦除sector8~11后最后再来喂狗,但是,这样会触发IWDG复位,这个与预期不一致,固此产生疑问。

2.2 问题重现
      使用NUCLEO-F412ZG板尝试重现客户问题,主要代码如下:
  1. int main(void)
  2. {

  3.   /* USER CODE BEGIN 1 */
  4. uint32_t beginTick =0,endTick =0;
  5. uint32_t curSysTick=0,endSysTick =0;
  6.   /* USER CODE END 1 */

  7.   /* MCU Configuration----------------------------------------------------------*/

  8.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  9.   HAL_Init();

  10.   /* Configure the system clock */
  11.   SystemClock_Config();

  12.   /* Initialize all configured peripherals */
  13.   MX_GPIO_Init();
  14.   MX_IWDG_Init();

  15.   /* USER CODE BEGIN 2 */
  16. if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) //如果是看门狗复位
  17.   {
  18.     /* Clear reset flags */
  19. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
  20.     __HAL_RCC_CLEAR_RESET_FLAGS();
  21. Error_Handler();
  22.   }

  23.     HAL_FLASH_Unlock();
  24.   /* Fill EraseInit structure*/
  25.   EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
  26.   EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;
  27.   EraseInitStruct.Sector        = FLASH_SECTOR_8;
  28.   EraseInitStruct.NbSectors     = 1;

  29. //  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
  30. //  {
  31. //      Error_Handler();
  32. //  }

  33. beginTick =HAL_GetTick();
  34. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
  35. curSysTick =SysTick->VAL;
  36. if(HAL_FLASHEx_Erase_IT(&EraseInitStruct)!= HAL_OK) //擦除sector8
  37. {
  38.     Error_Handler();
  39. }
  40. endSysTick =SysTick->VAL; // curSysTick, endSysTick保存着SysTick寄存器的值
  41. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); //PC8波形表示擦除FLASH的时间间隔
  42. endTick =HAL_GetTick();     // beginTick, endTick保存着全局变量Tick的值
  43. g_TickCount =endTick -beginTick; //变量Tick的时间差
  44. HAL_IWDG_Refresh(&hiwdg);
  45.   /* USER CODE END 2 */

  46.   /* Infinite loop */
  47.   /* USER CODE BEGIN WHILE */
  48.   while (1)
  49.   {
  50.   /* USER CODE END WHILE */

  51.   /* USER CODE BEGIN 3 */
  52. if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK)
  53.     {
  54.       /* Refresh Error */
  55.       Error_Handler();
  56.     }
  57. HAL_Delay(10);
  58.   }
  59.   /* USER CODE END 3 */
  60. }
复制代码
   此外,同时在每个SysTick中断输出一个波形,用来检测SysTick是否正常:
  1. void HAL_SYSTICK_Callback(void)
  2. {
  3.     HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);//用PA11来检测SysTick波形
  4. }
复制代码
   
   最终得出如下波形
1.jpg
图1 擦除FLASH时间与SysTick输出波形

        如上图,黄色为PC8脚波形,表示擦除FLASH的时间,下面蓝色为PA11管脚波形,表示SysTick波形。
   从上图可以看出擦除sector8所需要的时间是800ms,这个与客户认为的2ms是不一致的。查看STM32F412的数据手册,在第6.3.12节中可以看到如下信息:


2.png
图2 擦除FLASH扇区所需要的时间

        如上图,在PSIZE=32时,擦除一个128K的扇区需要大概1S(典型值)的时间,而我们从图1中实际测出的为800ms,这个基本相差不大,单与客户认为的2ms相去甚远,基本上我们认为这里的800ms是正确的结果,但是这个又是什么原因导致客户通过SysTick测出的值是错误的呢?

   实际上,从图1我们也可以看出,在擦除FLASH的期间,SysTick是没有波形的(见图1下面蓝色波形),同时在参考手册3.5节中有如下信息:

3.png
图3 参考手册中关于擦除扇区的描述

      这句话的意思是说,在擦除FLASH的期间,若尝试读取FLASH,则会被暂停,实际这个”读取”是指取指,我们都知道,程序的执行首先得通过从FLASH中通过I-BUS取出指令后才可以执行。这里SysTick之所以会被暂停掉,就是因为在擦除FLASH期间,为了执行SysTick中断例程,内核会尝试从FLASH取指,从而导致被暂停掉,进而全局变量uwTick的值没有机会增加。下图是调试界面:

4.png
图4 调试

       如上图,在执行擦除扇区后,SysTick的全局变量uwTick就增加了1,但SysTick在内核中的寄存器还是有变化的。这个与我们的预想一致。

   最后客户通过每擦除一个扇区喂一次狗的方式解决了问题,而在此期间不能依靠SysTick的值来计算时间。

3 结论
       在擦除FLASH期间,取指操作会被暂停掉,且SysTick所对应的全局变量uwTick值是不会增加的。另外,通过函数HAL_FLASHEx_Erase_IT()来执行擦除FLASH和通过函数HAL_FLASHEx_Erase()所花费时间没有差别,只不过前者在擦除完成后会产生一个中断,而后者没有。可以通过外设RTC来计算擦除FLASH的时间,从而绕开限制。



转载自flydream0














1 收藏 1 评论8 发布时间:2018-5-22 14:36

举报

8个回答
Inc_brza 回答时间:2018-5-22 15:32:21
我觉得有必要修改一下排版
aimejia 回答时间:2018-5-22 16:16:34
Inc_brza 发表于 2018-5-22 15:32
我觉得有必要修改一下排版

好的,已经进行一下调整了。
队长shiwo 回答时间:2018-5-22 17:50:37
这附的代码看得好慌,看不下去
kylongmu 回答时间:2018-5-22 23:02:32
2ms,这是超新手吧?开发用keil下一次的时间没感觉吗?
aimejia 回答时间:2018-5-23 13:02:40
队长shiwo 发表于 2018-5-22 17:50
这附的代码看得好慌,看不下去

已经调整了一下哦
kkbralack 回答时间:2019-11-22 17:06:31
之前也遇到同样的问题,SysTick感觉不是1ms变加,文章受益啦,谢谢。
kkbralack 回答时间:2019-11-22 17:07:23
队长shiwo 发表于 2018-5-22 17:50
这附的代码看得好慌,看不下去

这个应该就是官网提供的
liganchina 回答时间:2020-7-17 10:54:39
mark一下

所属标签

STM32团队

意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器


最新内容

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
微信公众号二维码 微信公众号
手机版二维码 手机版