1 前言 : b/ O8 V: W5 q' z; F
客户反馈在使用 STM32F412 的时候,擦除 sector 8~11 发现时间过长,从而导致意外触发IWDG 复位。
/ {$ u; b' s' V
8 `; r& V% F8 R$ f! G! x2 s7 r( t, V- `3 n6 @
2 问题分析 : b. p9 k" G& H& A
2.1 问题详情5 k" l5 B; A9 D! `" b
通过与客户邮件和电话沟通,了解到客户主要是想使用内部 FLASH 暂时保存 IAP 升级时的程序数据,在 IAP 升级的过程中,需要首先擦除内部 FLASH 中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到 IWDG,喂狗间隔大约 1.5S,客户的通过 SysTick 的方式计算出擦除 Sector8大约需要 2ms,因此认为若一次擦除 sector8~11 大约需要 8ms,于是在代码中一次性擦除 sector8~11后最后再来喂狗,但是,这样会触发 IWDG 复位,这个与预期不一致,固此产生疑问。; ~ {* V* ?: ?
2 k, m* k/ {4 u# S, D U
5 d! ?9 P* D& K3 r2.2 问题重现 1 K7 W3 [8 d" K1 j) z
使用 NUCLEO-F412ZG 板尝试重现客户问题,主要代码如下:- int main(void)6 o8 f4 e: d( z% y3 S
- {7 _& t; ^9 u; b5 f' i
- /* USER CODE BEGIN 1 *// l! A7 b2 h8 O8 m) x
- uint32_t beginTick =0,endTick =0;, k' N p8 Q" e; L. X0 p
- uint32_t curSysTick=0,endSysTick =0;8 T/ D2 }, D6 _: E
- /* USER CODE END 1 */6 r* x( U, M% q5 |7 v" F: \
- /* MCU Configuration----------------------------------------------------------*/& _8 y* w$ K$ m
- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */3 O, }) g2 W' {' ~0 g
- HAL_Init();
) m. B' k' x6 O- ^) U - /* Configure the system clock */1 F* i5 @ r" ]! c5 w
- SystemClock_Config();5 `# c* S$ K3 l; m/ P1 p0 f
- /* Initialize all configured peripherals */7 ?& R2 I6 L" ], E
- MX_GPIO_Init();! K( {9 v: K3 X
- MX_IWDG_Init();
- d' ?8 m7 f9 w8 o - /* USER CODE BEGIN 2 */
9 T3 N9 y0 _6 x' S- W" P - if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) //如果是看门狗复位
! i3 g& a* Y" c - {
3 E; E2 J; v5 K+ e' |4 J - /* Clear reset flags */! U' F3 G9 z9 ~/ h
- HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);
" m. Z2 z) w1 R% }/ x: D: D - __HAL_RCC_CLEAR_RESET_FLAGS();
0 f) E3 G; r, ]& K0 j% C" T, T - Error_Handler();; g9 {& n, L9 u2 C& c- S: h5 M
- }
) `& `" }! C3 R$ P! b - HAL_FLASH_Unlock();
& }3 t' r' T. `" s8 T - /* Fill EraseInit structure*/3 p }3 o" e. W+ `1 A2 _" u; U
- EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
- o6 S8 B4 U" q4 }0 D - EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
4 n( u" I$ _5 w4 w3 D z8 ] - EraseInitStruct.Sector = FLASH_SECTOR_8;
$ f" m2 S( i2 h$ U ? - EraseInitStruct.NbSectors = 1;+ W% I9 W4 W6 v( `* A* o) J9 E
- // if(HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
& m$ Q* }0 T8 a - // {
3 S% I) F/ |$ E P$ Q9 S - // Error_Handler();
! M9 M% h: M3 G9 R - // }
: L# W% T/ R7 i2 G( V m } - beginTick =HAL_GetTick();3 x" U7 ]: j7 }5 W$ N5 m1 c( B2 [3 D( L
- HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
9 y5 `% ~- M, D3 F9 f+ w - curSysTick =SysTick->VAL;
- F( `1 e: |, V8 ~6 t) h - if(HAL_FLASHEx_Erase_IT(&EraseInitStruct)!= HAL_OK) //擦除 sector8' v( ^, V7 d7 l8 Q# b
- {" L) ?8 X$ g( Y. a$ A, x
- Error_Handler();
1 R" O9 R" J( @8 A1 d# P - }9 H: `0 |" b0 R8 _
- endSysTick =SysTick->VAL; // curSysTick, endSysTick 保存着 SysTick 寄存器的值
1 e; x& Q# C* F! _. Y L - HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); //PC8 波形表示擦除 FLASH 的时间间隔3 d# \2 I) q, v* @- I
- endTick =HAL_GetTick(); // beginTick, endTick 保存着全局变量 Tick 的值: T2 v- V/ w: N# i* \) g3 C: e _
- g_TickCount =endTick -beginTick; //变量 Tick 的时间差0 {& Q( |7 ^: d) g
- HAL_IWDG_Refresh(&hiwdg);
3 M3 Q. D; j* K6 {5 f# F - /* USER CODE END 2 */% O0 Z# D5 ^4 m' E
- /* Infinite loop */
: T3 u/ z0 P4 v) F# q# _! I" l2 | - /* USER CODE BEGIN WHILE */
/ e6 L) x+ `4 [ - while (1)) M6 V% t+ @5 h$ a4 w
- {- f$ A, s% K: d0 e0 t a
- /* USER CODE END WHILE *// ~+ _$ T; W4 t y, M& E0 p
- /* USER CODE BEGIN 3 */1 U+ g# Q& u, q6 C- g0 m9 J
- if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK)
: c/ M+ h/ @% k) @8 }; x& y - {
, V6 r" |8 B' ~; l8 x - /* Refresh Error */
5 r& O, X' ~3 g! D9 p0 W - Error_Handler();& f( A- f6 Q; f5 K5 k9 M
- }
$ Q) C$ M$ x/ O1 n0 t, j0 I( {) J' c - HAL_Delay(10);
" ?! {' D7 L) {8 H) v. G - }, d# w `2 W7 Z* B
- /* USER CODE END 3 */
( N# j- B& t" G$ e - }
复制代码 8 u* l0 U& T: F! h1 p
7 x# N, B2 X7 k- V1 |此外,同时在每个 SysTick 中断输出一个波形,用来检测 SysTick 是否正常:9 B% H# b9 h* L( H& I' q% s
- <font face="Tahoma"><font size="3"><font color="#000000">void HAL_SYSTICK_Callback(void)</font></font></font>
: {& U. E% O/ T7 D - <font face="Tahoma"><font size="3"><font color="#000000">{</font></font></font>
: g& i D# @ x" y3 X - <font face="Tahoma"><font size="3"><font color="#000000">HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);//用 PA11 来检测 SysTick 波形</font></font></font>5 l9 y' a, p2 A4 e2 G
- <font face="Tahoma"><font size="3"><font color="#000000">}</font></font></font>
复制代码 2 K( W) X) O* _+ [3 q
最终得出的波形如下:0 I9 ?# P; }- G1 N; _+ q0 N! S
$ Z' S' C" R! d7 X( k
/ r) B& Z- u7 q) Y+ Q) o @, z* C- v# q
8 {9 f$ k- q, E. V5 Y! ]( f
0 B- q! q. s7 J5 s. m如上图,黄色为 PC8 脚波形,表示擦除 FLASH 的时间,下面蓝色为 PA11 管脚波形,表示 SysTick 波形。
% v9 O$ k8 |7 P' L# T1 b1 Y' N6 ^" w' C* T9 E5 B5 i: }
完整版请查看:附件
/ {5 a, S1 f6 y5 o* M# Q& T1 O( H5 M9 E- [& I# m, C5 L
9 `! K8 w3 s8 v2 d6 i4 l$ [) T. ?5 W3 |$ C
|