STM32 擦除内部 FLASH 时间过长导致IWDG 复位
# }; v. w$ a x) w& p
: p) l1 s- V& L7 q1 前言
& r% X: O. }# t) X0 O2 a$ m/ _: Y2 u* f; U/ Q8 `) }1 p
客户反馈在使用 STM32F412 的时候,擦除 sector 8~11 发现时间过长,从而导致意外触发IWDG 复位。
" E# {% n# e) \8 n! h5 v8 X" {4 D( Q( j+ h
2 问题分析 * I2 _/ l* f4 f' v$ v4 o
+ N) x6 d. h6 \( J0 i) w
2.1 问题详情 6 _( S' e( |4 J: d2 \0 {
* {7 r0 K3 }! }2 I2 E3 }5 ~: J% X
通过与客户邮件和电话沟通,了解到客户主要是想使用内部 FLASH 暂时保存 IAP 升级时的程序数据,在 IAP 升级的过程中,需要首先擦除内部 FLASH 中一块足够大的空间,然后再写入升级数据。客户的工程中有使用到 IWDG,喂狗间隔大约 1.5S,客户的通过 SysTick 的方式计算出擦除 Sector8大约需要 2ms,因此认为若一次擦除 sector8~11 大约需要 8ms,于是在代码中一次性擦除 sector8~11后最后再来喂狗,但是,这样会触发 IWDG 复位,这个与预期不一致,固此产生疑问。( V$ `3 i& t4 Y* M
9 y: L }/ ^3 f. I6 T5 k7 \6 n- v
2.2 问题重现 2 g8 z% f8 H* `$ ?1 i3 C6 K
$ e/ g# D+ o% V使用 NUCLEO-F412ZG 板尝试重现客户问题,主要代码如下:
. G* y" b' [4 T3 I
: \9 h( W) D7 }6 F7 m3 b5 _int main(void)
& r; i( b1 {7 V# ^/ A8 N C1 L{" n, v$ u% R; n% q4 G; ?: m
/* USER CODE BEGIN 1 */
+ V. D8 r$ J$ duint32_t beginTick =0,endTick =0;
. p' U; }0 q* z& C& D* o0 Euint32_t curSysTick=0,endSysTick =0;5 A* X: r2 ?# k9 z. d" I
/* USER CODE END 1 */
) m0 t' h. o8 n /* MCU Configuration----------------------------------------------------------*/
/ c3 R. q; r) E( M* C! w( F$ G /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
, z$ Q' n: ]7 L% b* G/ V HAL_Init();
, u9 e [& q# s3 o- J5 I! ^ /* Configure the system clock */
7 m4 p5 e0 a1 j% B& c SystemClock_Config();
Z: U* [+ V7 K0 u. g, N" W8 r/ N0 \ /* Initialize all configured peripherals */+ `' _9 p6 M& }+ Y; o
MX_GPIO_Init();
/ \0 M: i: m: z: V. K# | MX_IWDG_Init();: v/ p; u+ i: |6 }
/* USER CODE BEGIN 2 *// J* t$ d: b/ Q- H
if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET) //如果是看门狗复位
) a. [/ p/ ]2 R" {) v {8 g1 B# b" Q. J2 h2 v' \
/* Clear reset flags */& w! [- _7 U; D7 m. h
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET);6 J/ P8 b; c. P5 M$ W. P
__HAL_RCC_CLEAR_RESET_FLAGS();
+ b( r* y3 b+ yError_Handler();
8 Q! k7 m! {$ m1 h% A6 V O }8 u& h; [; G6 C1 q+ F" |( l
HAL_FLASH_Unlock();& U3 ^: K9 O" l6 S3 C# Z# G
/* Fill EraseInit structure*/
1 s6 f7 o2 K2 a# }. z EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
" z$ E$ W/ p5 Y& n" I EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;5 V+ v8 k* F# z/ c1 ]; ]4 R4 c
EraseInitStruct.Sector = FLASH_SECTOR_8;4 R1 S$ C5 y O+ t6 w1 l: x
EraseInitStruct.NbSectors = 1;' ]4 [: R$ s. G6 D( x, T5 m+ x
// if(HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
- z! V; u, L( T7 ]/ G$ S! k// {! E Q9 }* z+ K5 T. R
// Error_Handler();
6 R& [7 G. v6 F4 I// }
7 ]: U+ Q7 H8 i& P) [2 obeginTick =HAL_GetTick();2 u. e! Q e1 P* Q; T
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_SET);
4 @' c, Q" m) x5 b, YcurSysTick =SysTick->VAL;
! @" ~% l& A! ]+ h5 e4 Rif(HAL_FLASHEx_Erase_IT(&EraseInitStruct)!= HAL_OK) //擦除 sector8& X7 p, P2 [* F9 w3 E
{0 r4 R6 y6 P3 A% \9 }2 f* x( ~
Error_Handler();# ?2 r; i( v( m$ M
}
/ k' H* D4 i7 o( x, Y2 ` O9 R8 NendSysTick =SysTick->VAL; // curSysTick, endSysTick 保存着 SysTick 寄存器的值7 ~" s- P% A0 s! g
HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); //PC8 波形表示擦除 FLASH 的时间间隔% _7 y. _1 ?; K* l- @" |9 D
endTick =HAL_GetTick(); // beginTick, endTick 保存着全局变量 Tick 的值
6 M. ?$ }' M5 x% z5 c* l! \ Jg_TickCount =endTick -beginTick; //变量 Tick 的时间差7 b" P$ U( V0 B
HAL_IWDG_Refresh(&hiwdg);
8 @& f2 \8 @" _8 ^ /* USER CODE END 2 */
+ ?' g! N* z; q i" O% i: U. |/ q /* Infinite loop */4 ]8 G! C! [# k
/* USER CODE BEGIN WHILE */
# n4 T1 _0 T: L2 |! A while (1)8 C3 h$ W- W) a- x" G) Z
{
$ J0 W$ w* `5 r/ u$ _ /* USER CODE END WHILE */- P9 h2 ^+ T9 z# _8 Q
/* USER CODE BEGIN 3 */$ W6 k: Y8 A( |' w6 F7 R: d6 e
if (HAL_IWDG_Refresh(&hiwdg) != HAL_OK). T- ?! {" | A# H2 j$ K
{
6 ^: I( {6 F A g$ I: p /* Refresh Error */5 [$ W6 I7 ]! [* g% q: k5 P
Error_Handler();6 _8 W5 C. Z2 h: n7 L" A
}6 u$ u) }8 I& J: u% V( l$ {5 B3 @' D
HAL_Delay(10);, P$ e$ g$ ~( r' Z$ @; ?
}0 a5 g# _( M1 u3 v9 y: R3 C) D
/* USER CODE END 3 */
+ ^7 d b/ p/ h& B& R4 p此外,同时在每个 SysTick 中断输出一个波形,用来检测 SysTick 是否正常4 L9 |& r; i9 O6 t1 t" P' h: }, m. o
2 ^/ ~0 i* C; h4 T, v. Uvoid HAL_SYSTICK_Callback(void)
7 {/ t) V9 g* C# P( V0 r2 [{( @$ P+ o3 W( E# f0 L1 ~9 g
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_11);//用 PA11 来检测 SysTick 波形
: W$ v/ w6 H( Y9 W} % C* a9 d/ v. B9 k# b! ^/ [5 o
最终得出的波形如下:
. E- ~& Z8 p1 g H: w w F* c7 }" O
............
9 B# |. }, q3 K. X想了解更多,请下载原文阅读
9 h* h' o/ d5 ]/ A5 v3 K % N/ X, H ~2 c+ f6 Q2 G3 Q
|