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

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

[复制链接]
STMCU小助手 发布时间:2022-1-9 20:00
1 前言     
8 Z- ]3 n5 X$ s5 J9 P* ]  客户反馈在使用STM32F412的时候,擦除sector 8~11发现时间过长,从而导致意外触发IWDG复位。3 h9 [0 I  {) B# K8 X" d, O

' f+ y, E0 o3 X1 U0 A/ O7 e2 问题分析
( Y3 q- z. h$ V& \) q9 @- r# ~2.1 问题详情
6 U* J. ?* L$ ]' `     通过与客户邮件和电话沟通,了解到客户主要是想使用内部FLASH暂时保存IAP升级时的程序数据,在IAP升级的过程中,需要首先擦除内部FLASH中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到IWDG,喂狗间隔大约1.5S,客户的通过SysTick的方式计算出擦除Sector8大约需要2ms,因此认为若一次擦除sector8~11大约需要8ms,于是在代码中一次性擦除sector8~11后最后再来喂狗,但是,这样会触发IWDG复位,这个与预期不一致,固此产生疑问。
( B" M9 E- \  a6 P" |. N3 c0 s) r& @0 t1 _) ]
2.2 问题重现
! d6 X4 D  q3 n- K, c      使用NUCLEO-F412ZG板尝试重现客户问题,主要代码如下:
  1. int main(void)) N% B$ t7 v8 r3 d4 ~
  2. {% H5 Q/ O3 z4 l5 v
  3.   /* USER CODE BEGIN 1 */$ l4 C5 Z7 k2 ?" Y  Z
  4. uint32_t beginTick =0,endTick =0;: C9 }6 m# {. Q( O3 E# |, z
  5. uint32_t curSysTick=0,endSysTick =0;
    " @. i$ u" O# A* r$ [9 E
  6.   /* USER CODE END 1 *// G  h3 U# Y' x" |* n9 m$ o; l! Z# c
  7.   /* MCU Configuration----------------------------------------------------------*/5 n% ~( s. s$ x8 ]3 F  j
  8.   /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    8 j4 F4 K8 d$ s! {6 b( S, _$ l
  9.   HAL_Init();4 n. a9 B. J/ P2 g9 i3 Y! D' M
  10.   /* Configure the system clock */
    6 J; m8 V/ v$ c# r
  11.   SystemClock_Config();
    . h" X( }" D7 z1 E  L( F2 Y
  12.   /* Initialize all configured peripherals */
    0 a7 ^1 M; o5 m! L1 B
  13.   MX_GPIO_Init();
    2 |$ {5 d1 P# K4 F+ M7 W; m; P
  14.   MX_IWDG_Init();) S/ _; e; Q& \# r* Y6 Y0 h' r
  15.   /* USER CODE BEGIN 2 */
    ) n  ~+ L+ E% O5 H; {
  16. if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) //如果是看门狗复位" @9 A& E( b, l
  17.   {* Z3 R  l# V2 I' c( `3 A- @8 v4 Y
  18.     /* Clear reset flags */
    & T/ r- j/ s/ u5 C# ]
  19. HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);, B# {3 q& r6 {. C  _! \! r% |
  20.     __HAL_RCC_CLEAR_RESET_FLAGS();: A2 X$ A/ O; D. d# x% k
  21. Error_Handler();' r5 Y7 n2 a7 D2 Y* f& N
  22.   }& ~9 Y  a$ D+ X8 g
  23.     HAL_FLASH_Unlock();
    7 Q$ ~2 t2 _! C* V8 I: F
  24.   /* Fill EraseInit structure*/
    0 O2 U) \( j) n% X5 f8 h1 X
  25.   EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;$ T6 C8 \$ [& x1 y' o
  26.   EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3;2 f. [0 L  D5 \; ]& }+ B
  27.   EraseInitStruct.Sector        = FLASH_SECTOR_8;
    * J$ V6 W& [! H( Z
  28.   EraseInitStruct.NbSectors     = 1;5 p; d" [: h* R: b& ?! ]' L) w+ V
  29. //  if(HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)* }9 S/ S2 U8 i# v+ j! N
  30. //  {- K9 l+ }1 N- f, q. h5 h
  31. //      Error_Handler();( C- ^9 W3 v( K) U2 R" W
  32. //  }
    ) b) G# A  J$ Z  ?/ c1 S/ P
  33. beginTick =HAL_GetTick();
    4 i9 `( V! r" i
  34. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
    0 g4 P& ^8 U2 T# C5 @
  35. curSysTick =SysTick->VAL;
    8 D5 ?6 u9 a8 o$ p; |: q# b
  36. if(HAL_FLASHEx_Erase_IT(&EraseInitStruct)!= HAL_OK) //擦除sector8/ x3 @4 P( z; z5 y- S7 T; T
  37. {
    ! O) h, B5 M. f! ?; L
  38.     Error_Handler();$ b. M: I6 O3 j
  39. }; a" {. {: q2 e3 r2 P4 O
  40. endSysTick =SysTick->VAL; // curSysTick, endSysTick保存着SysTick寄存器的值
      K1 Y* F8 r. F* b& q
  41. HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); //PC8波形表示擦除FLASH的时间间隔
    6 s# I. a9 r, m. ]8 t# \/ Z
  42. endTick =HAL_GetTick();     // beginTick, endTick保存着全局变量Tick的值) P/ S9 J. T* F2 ?' y  j
  43. g_TickCount =endTick -beginTick; //变量Tick的时间差3 O8 [- T5 T4 C* h( j% B* q
  44. HAL_IWDG_Refresh(&hiwdg);5 D' g8 t5 \% M
  45.   /* USER CODE END 2 */* _% M+ F" f: F) d5 h0 u# n
  46.   /* Infinite loop */2 {# M. K( h3 I7 z5 J* l1 N+ z
  47.   /* USER CODE BEGIN WHILE */
      O: m2 ?) s* p9 S
  48.   while (1)
    ) y& L$ C0 s  }: i/ O
  49.   {4 L$ K4 q5 N5 ~) D& J9 h3 Q9 H+ I
  50.   /* USER CODE END WHILE */
    : g% c3 h4 X* a  U+ d/ |7 G
  51.   /* USER CODE BEGIN 3 */9 n. a6 W7 j- j+ [" h) x
  52. if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK)& B8 m1 K2 y& R) M; A- @7 v( z2 Q* v
  53.     {
    % E' `# r5 S. y. C7 y
  54.       /* Refresh Error */
    : Z) ]1 ?6 B. P3 t4 ?
  55.       Error_Handler();
    # H) R2 b3 b8 @/ x$ ~
  56.     }
    8 I8 Y8 ^0 T" W: N; d1 I
  57. HAL_Delay(10);3 y  A/ @4 D* z& Z( o" a. K
  58.   }( F* a* q* b8 F$ M' w/ s/ q
  59.   /* USER CODE END 3 */& t; y, u; s, J% x* A
  60. }
复制代码

7 q: Q$ I( ~2 N  P( {/ R" M   此外,同时在每个SysTick中断输出一个波形,用来检测SysTick是否正常:
& G; D1 R3 M. x6 b/ S& R
  1. void HAL_SYSTICK_Callback(void)( X+ g0 \  k6 e: b' _. |
  2. {9 n9 P6 r% W4 v" v$ v; s( `8 S
  3.     HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);//用PA11来检测SysTick波形9 E1 P* r! z& C0 y' S1 ~
  4. }
复制代码

' U- V6 x: `* B* D- ?   0 o6 D' ?/ _8 U  C& H6 D6 |
   最终得出如下波形: J% i1 U0 L9 j) F5 U+ a
图1 擦除FLASH时间与SysTick输出波形

0 f% y( e. u; |1 C* V" }- ?        如上图,黄色为PC8脚波形,表示擦除FLASH的时间,下面蓝色为PA11管脚波形,表示SysTick波形。  n9 U, Q) A; y3 C, q" d% B8 K
   从上图可以看出擦除sector8所需要的时间是800ms,这个与客户认为的2ms是不一致的。查看STM32F412的数据手册,在第6.3.12节中可以看到如下信息:

% ?( E" C9 B2 I; y7 M7 f7 c
8 v2 g/ ]9 J6 N* o
图2 擦除FLASH扇区所需要的时间
6 \7 E' H- U& C- C" s
        如上图,在PSIZE=32时,擦除一个128K的扇区需要大概1S(典型值)的时间,而我们从图1中实际测出的为800ms,这个基本相差不大,单与客户认为的2ms相去甚远,基本上我们认为这里的800ms是正确的结果,但是这个又是什么原因导致客户通过SysTick测出的值是错误的呢?. ?. X! Z( y! G4 n. I0 K
. V, M& x  \+ Y- Z% `  m
   实际上,从图1我们也可以看出,在擦除FLASH的期间,SysTick是没有波形的(见图1下面蓝色波形),同时在参考手册3.5节中有如下信息:
$ j& O: T) h6 {9 T

2 X! A1 R3 I! e( M3 Z% B; B: A0 s
图3 参考手册中关于擦除扇区的描述

+ k7 K6 Q' X" m: D3 {      这句话的意思是说,在擦除FLASH的期间,若尝试读取FLASH,则会被暂停,实际这个”读取”是指取指,我们都知道,程序的执行首先得通过从FLASH中通过I-BUS取出指令后才可以执行。这里SysTick之所以会被暂停掉,就是因为在擦除FLASH期间,为了执行SysTick中断例程,内核会尝试从FLASH取指,从而导致被暂停掉,进而全局变量uwTick的值没有机会增加。下图是调试界面:- T, v* n( U. B& z5 m9 P
7 b$ O, x' i' M3 t7 K* M
图4 调试

. U3 d. f( V, H& E* U       如上图,在执行擦除扇区后,SysTick的全局变量uwTick就增加了1,但SysTick在内核中的寄存器还是有变化的。这个与我们的预想一致。
  X8 P" x5 ~8 K! q3 Z  y  o
2 e/ ]  h2 h( Q. V! v+ {   最后客户通过每擦除一个扇区喂一次狗的方式解决了问题,而在此期间不能依靠SysTick的值来计算时间。
+ ~4 o2 p, }, L2 j, m) [

$ Z2 r+ w% x- h' a3 结论
% S+ R5 w( {$ n1 ^       在擦除FLASH期间,取指操作会被暂停掉,且SysTick所对应的全局变量uwTick值是不会增加的。另外,通过函数HAL_FLASHEx_Erase_IT()来执行擦除FLASH和通过函数HAL_FLASHEx_Erase()所花费时间没有差别,只不过前者在擦除完成后会产生一个中断,而后者没有。可以通过外设RTC来计算擦除FLASH的时间,从而

& f( ?7 z8 v* J! C+ h0 V0 O! T1 i( @/ D/ F& o3 g0 s
赞 收藏 评论0 发布时间:2022-1-9 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版