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

【经验分享】 STM32F412擦除内部FLASH时间过长

[复制链接]
STMCU小助手 发布时间:2022-1-9 20:00
1 前言     
9 V$ F7 C5 D. n- l- p- n+ t- y  客户反馈在使用STM32F412的时候,擦除sector 8~11发现时间过长,从而导致意外触发IWDG复位。
$ w  h! T4 N! ?. M9 O  D6 v. B* n7 z1 H# d% ]4 y+ ]
2 问题分析/ @5 o4 A! o# |( f7 ]
2.1 问题详情
8 O; e+ E) W$ B: s( W     通过与客户邮件和电话沟通,了解到客户主要是想使用内部FLASH暂时保存IAP升级时的程序数据,在IAP升级的过程中,需要首先擦除内部FLASH中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到IWDG,喂狗间隔大约1.5S,客户的通过SysTick的方式计算出擦除Sector8大约需要2ms,因此认为若一次擦除sector8~11大约需要8ms,于是在代码中一次性擦除sector8~11后最后再来喂狗,但是,这样会触发IWDG复位,这个与预期不一致,固此产生疑问。+ N* \! l) `( n! k7 W2 l
) `# ~! I! ~% C+ E
2.2 问题重现
+ Y; Y8 ^/ q, k      使用NUCLEO-F412ZG板尝试重现客户问题,主要代码如下:
  1. int main(void)
    6 D* P# r, R& X5 j* B$ v
  2. {+ K4 k% L5 _0 }  y/ L+ |
  3.   /* USER CODE BEGIN 1 */; e% U, ~1 p5 ]% F; O* S
  4. uint32_t beginTick =0,endTick =0;. J( o7 s6 @' Y
  5. uint32_t curSysTick=0,endSysTick =0;3 s1 Z# f) T; z+ s$ s! w" m
  6.   /* USER CODE END 1 */; q; V7 ]" [+ a2 |: L
  7.   /* MCU Configuration----------------------------------------------------------*/- ]7 G* p- t- `1 N" C% {; A0 ~
  8.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    " y* @4 {7 @/ p; l! Z3 R) A: |& W+ n
  9.   HAL_Init();
    & t- e9 z# l3 @5 s+ \+ g
  10.   /* Configure the system clock */
    % D$ y# }$ B" p7 o+ ?
  11.   SystemClock_Config();
    # u" ^0 y8 E5 R, x; D
  12.   /* Initialize all configured peripherals */
    + u9 a; E; r# r1 \
  13.   MX_GPIO_Init();, _. H: D3 L  k* |5 n' ^: I2 C- O
  14.   MX_IWDG_Init();" j/ n0 H" b& `4 C- H% v
  15.   /* USER CODE BEGIN 2 */3 X% Y7 \; S' i9 @( B
  16. if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) //如果是看门狗复位8 k' t1 S; o- m: l" U4 O
  17.   {
    7 `6 p% O! W% c' T$ p4 A) j
  18.     /* Clear reset flags */
    % w- |. V4 p, l0 N
  19. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);8 C3 Y8 l* P8 v6 O) P6 ^) ^- g8 y
  20.     __HAL_RCC_CLEAR_RESET_FLAGS();( ~1 l0 [/ m5 v: b1 @8 J8 T) _
  21. Error_Handler();1 Q; U& s: o( i( [2 A7 M
  22.   }
    ! }* M$ j8 e/ V5 E8 [
  23.     HAL_FLASH_Unlock();7 b5 L4 H& f) n1 ^
  24.   /* Fill EraseInit structure*/# _1 R- J8 u+ A- r* n
  25.   EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
    / M# V* k) x  x$ G) w/ V. R: x
  26.   EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;
    ! B. w$ `# P* \6 \8 f; O
  27.   EraseInitStruct.Sector        = FLASH_SECTOR_8;  {. i( w5 l5 q, C
  28.   EraseInitStruct.NbSectors     = 1;
    9 o. G1 x# P: H" \: f
  29. //  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)1 h1 k% M. [& i4 C& y4 `
  30. //  {
    ( c: K  {4 n6 [% {" E! Y
  31. //      Error_Handler();
    $ A4 C# j5 W) W
  32. //  }- i0 B; W7 r* T: H) |0 E
  33. beginTick =HAL_GetTick();8 q$ }* v5 {) M2 H' C& @- N+ Z; G7 a, T
  34. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);* x4 {# b9 ]" ^( S, ?0 G1 ~0 W  W; H
  35. curSysTick =SysTick->VAL;  t8 A1 s/ U6 O4 x; F: J
  36. if(HAL_FLASHEx_Erase_IT(&EraseInitStruct)!= HAL_OK) //擦除sector8* N: `' r; s& p1 P7 O
  37. {
    7 F2 _' w# q9 _) K9 x, ~
  38.     Error_Handler();3 q' `' t) w% o" D# a
  39. }
    0 q4 X8 F+ g6 y0 y+ P: c
  40. endSysTick =SysTick->VAL; // curSysTick, endSysTick保存着SysTick寄存器的值" G0 i/ P3 a# I* c$ ?; Z7 {/ _
  41. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); //PC8波形表示擦除FLASH的时间间隔2 C+ c. k/ g& s5 _! F
  42. endTick =HAL_GetTick();     // beginTick, endTick保存着全局变量Tick的值
    0 E" b8 N' {% Z1 s1 [
  43. g_TickCount =endTick -beginTick; //变量Tick的时间差6 `' [/ ]( O, I1 d6 A8 }5 x1 S: X
  44. HAL_IWDG_Refresh(&hiwdg);
    ( D) o4 F5 m5 u, P' O  \  m
  45.   /* USER CODE END 2 */
    : ^1 K" Y9 k( Z- K1 h
  46.   /* Infinite loop */; N. V  A6 o7 Y! t
  47.   /* USER CODE BEGIN WHILE */
    " w+ W+ a7 b6 E; L, I8 T* g' W
  48.   while (1)
    & H( _( s! c; z- \  |$ v$ }
  49.   {
    3 m) I* T7 o' S. v: x$ I6 m' S2 b
  50.   /* USER CODE END WHILE */
    5 e7 d4 ]' n2 G" f( c
  51.   /* USER CODE BEGIN 3 */
    ; I2 `2 {  E7 ^; H4 p. r: e
  52. if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK)
    " g, f* s! y- M; Y' q' t
  53.     {" P) ]6 `- A% l& c
  54.       /* Refresh Error */' N0 p% H9 T" ^
  55.       Error_Handler();: T  X5 k5 f( N6 J, N( e
  56.     }0 u+ O) C/ a- g! ~! f
  57. HAL_Delay(10);
    2 }% K0 e" h$ }  B' d
  58.   }
    5 K% x% R8 `' F. ~
  59.   /* USER CODE END 3 */
      G7 W. c# h+ a& C1 j/ @6 N" G
  60. }
复制代码
  {& i7 [9 u/ D
   此外,同时在每个SysTick中断输出一个波形,用来检测SysTick是否正常:

' T& Q+ t/ B# j
  1. void HAL_SYSTICK_Callback(void): p. T, _' e5 C
  2. {
    + _9 N! g/ ]8 K7 ?0 ^
  3.     HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);//用PA11来检测SysTick波形
    1 j/ B5 J; o) m7 D# L  S0 _
  4. }
复制代码

) S3 T0 K8 f: ~! e3 k2 |   % Q  s2 o9 w8 z8 C
   最终得出如下波形
; l& X. c1 V! N) P7 ^  O# h
图1 擦除FLASH时间与SysTick输出波形
2 ]: O8 c4 X  E( A
        如上图,黄色为PC8脚波形,表示擦除FLASH的时间,下面蓝色为PA11管脚波形,表示SysTick波形。
8 D, _2 C! @* U6 A7 F4 _   从上图可以看出擦除sector8所需要的时间是800ms,这个与客户认为的2ms是不一致的。查看STM32F412的数据手册,在第6.3.12节中可以看到如下信息:
$ u- }) I3 @6 i# j# R/ O8 m
5 m8 Z  M% _9 S) n7 @
图2 擦除FLASH扇区所需要的时间
) W8 L$ |8 a" q+ j- _
        如上图,在PSIZE=32时,擦除一个128K的扇区需要大概1S(典型值)的时间,而我们从图1中实际测出的为800ms,这个基本相差不大,单与客户认为的2ms相去甚远,基本上我们认为这里的800ms是正确的结果,但是这个又是什么原因导致客户通过SysTick测出的值是错误的呢?
2 L# e2 s- N; Y7 \4 B* G5 I1 k7 ?6 Y6 d
   实际上,从图1我们也可以看出,在擦除FLASH的期间,SysTick是没有波形的(见图1下面蓝色波形),同时在参考手册3.5节中有如下信息:
; {* ~! _" x: \% s1 M" e7 v

2 W- Z' u  Q7 C5 F& W+ P
图3 参考手册中关于擦除扇区的描述

# Q; r# W4 C9 b2 l$ l      这句话的意思是说,在擦除FLASH的期间,若尝试读取FLASH,则会被暂停,实际这个”读取”是指取指,我们都知道,程序的执行首先得通过从FLASH中通过I-BUS取出指令后才可以执行。这里SysTick之所以会被暂停掉,就是因为在擦除FLASH期间,为了执行SysTick中断例程,内核会尝试从FLASH取指,从而导致被暂停掉,进而全局变量uwTick的值没有机会增加。下图是调试界面:8 z; i! I6 |6 \2 W2 H5 c5 c6 |
; M, M8 F. X) L
图4 调试
/ ]" Y4 m* x/ Q+ B5 y* Q- v
       如上图,在执行擦除扇区后,SysTick的全局变量uwTick就增加了1,但SysTick在内核中的寄存器还是有变化的。这个与我们的预想一致。* w& k2 t) T. t) K7 u" Y7 r
6 C$ A  J3 G: I2 p4 p4 G
   最后客户通过每擦除一个扇区喂一次狗的方式解决了问题,而在此期间不能依靠SysTick的值来计算时间。
* L# r3 x$ V) a! y$ Z- h
* [' Q$ T0 E1 A. y
3 结论
! k' t) C. f; k- o2 _7 p! r+ {  V       在擦除FLASH期间,取指操作会被暂停掉,且SysTick所对应的全局变量uwTick值是不会增加的。另外,通过函数HAL_FLASHEx_Erase_IT()来执行擦除FLASH和通过函数HAL_FLASHEx_Erase()所花费时间没有差别,只不过前者在擦除完成后会产生一个中断,而后者没有。可以通过外设RTC来计算擦除FLASH的时间,从而

+ y9 Z/ M9 `/ }2 e* d5 b9 ?6 V% [" r/ V+ n5 _0 z
收藏 评论0 发布时间:2022-1-9 20:00

举报

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