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

STM32CubeIDE的独立看门狗IWDG经验分享

[复制链接]
攻城狮Melo 发布时间:2023-4-6 15:25
一、STM32 的IWDG简介( Z$ f: G3 T5 e1 U
        2.1 看门狗原理
, q) I- [: b3 s- l0 A* A
        看门狗本质上就是一种计数器,和我们现实生活中一炷香现象、沙漏现象等是同理的,计数器一般有两种做法,一种是递增,超过固定阀值报警;一种是递减,通常值降到0时报警。后面一种比较贴切生活场景,因此较常用,STM32的独立看门狗(Independent Watchdog,IWDG)就是采用后面这一种做法。
+ N8 W1 g8 n8 i# V6 @) X

+ [3 I6 B1 ?" S4 d$ e4 a( a        如下图所示,假设我们设定一个初始值RL,设定一个计数变量V在开始时等于RL,然后每经过一个时钟周期就减1,如果减到为0值时,触发报警。如果在V值降为0前,重新设定一下V值等于RL,然后V值又重新计算,从而又争取到一段时间,定期去反复设定V值(喂狗),保持V值不降为0,就能一直保持正常态势。8 S5 i* B3 l- g

# s0 s" s. W8 Y. K( X- \
c708eb36bab945b3b5ad567f7fefa7c7.png 6 i; D6 q- o" C& Q: S, M6 E+ j5 ?$ r

- N+ J8 P/ t- J: [( q! H. W         STM32中的看门狗有两种,一个是独立看门狗(Independent Watchdog,IWDG),就是本博文要分析学习的,另一种是窗口看门狗wwdg(window Watchdog,WWDG)。
6 h. R  U/ L- p# N6 a, {/ O  o2 `( b. G
  p8 S( p( `6 a9 Q6 L/ j7 V
        1.2 STM32独立看门狗时钟计算- p& g/ }" W& N; c8 r/ L
        Iwdg由独立时钟(内部低速时钟LSI)计时,所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。而wwdg由系统时钟计时,如果系统时钟不走了,它也就失去作用了,主要用于监视软件错误。1 }9 F* o) z' F0 x# M4 W9 R: h
" f$ ]7 z4 C7 z. o1 m0 s6 ~7 `' I2 R3 B
        前面提到看门狗的计数是每经过一个时钟周期减1,那么时钟周期CT是如何获得计算呢。STM32内,IWDG依赖于内部低速时钟LSI,采用该时钟的频率来计时。频率是单位时间内完成周期性变化的次数,是描述周期运动频繁程度的量,常用符号f或ν表示,单位为秒分之一。为了纪念德国物理学家赫兹的贡献,人们把频率的单位命名为赫兹,简称“赫”,符号为Hz。2 X! {7 C' R1 B

6 h- }% ^/ P8 k* Z: D4 h        而时钟周期CT和频率成反比,即f=1/CT(其中f为频率,CT为时钟周期)。
' o0 M! b6 B0 @( I  o; k2 n* N* G+ E% e3 V6 S
        在STM32CubeMX上,我们开启IWDT后,用户可以设置的数值依次是计数时钟分频值,窗口值及重装载值,其中计数时钟分频值取值是固定的枚举值(2<n<8),即4、8、16、32、64、128、256,而窗口值及重装载值的设置范围12bit的数据,即0X000~0XFFF,如下图所示:) h9 u+ k1 e) ~7 m
% w+ h$ I! T0 y. h$ {; Y9 {
cc3ddf4f836547b186df86f69e68358b.png 6 n5 i( [5 f1 r

- c- |: ^9 d; F' h7 U. a         而IWDG的最终输出时钟频率是直接依赖于LSI,MCU芯片的内部低速时钟是多少,它就是多少。0 u, r  V# l0 D. y2 b, O& P
% \  @2 V3 r2 T+ s) M. z7 P9 Q
0d7f5ca31c8d4b409c494f135e8cfdf5.png
% M6 ?0 s( a( b% ]% g7 b$ M  ?$ j7 j" ?) G5 E
        那么,看门狗时钟频率=LSI(内部低速时钟)的频率F/计数时钟分频值P;2 c! [  b3 S1 H( m* H, X  A
  C; A$ @  B9 v& v  J  B
         如上述两图设置的数值,RL=4095,F=32KHz,P=32,那么时钟周期:; n4 N3 K% c6 N. V

# u; l/ U$ A/ p2 c# a. m        ct = 1s/f32KHz/32=1000ms/32000HZ/32=1ms,也就大概一个时钟周期是1毫秒,喂狗要求在4095*1ms以内。
& Y6 I2 F7 i! V" L9 c* ?
7 M- ?' [5 W+ C5 J* t" _: D3 ~

+ n+ f2 ~  S( H; A  j3 x        1.3 STM32的IWDT使用注意
6 M; O5 ^; e- E5 c- t        需要注意的是,看门狗的时钟计算不是精确的,所以在喂狗的时候,最好不要太晚了,否则,有可能发生看门狗复位。另外应该还注意到窗口值的存在,通常窗口值和重装载值一致的,如果Window参数(WV)与Window寄存器值相同,只需重新加载计数器值即可退出,具有精确时基函数。否则修改窗口寄存器。这将自动重新加载看门狗计数器:9 b8 J8 [; }% b; G

) J( q/ ]/ \6 G  S2 z+ M+ s9 B        窗口计数值WV决定什么时候喂狗。狗喂早了,复位就“早”,即在重装载值(V)>窗口值(WV),也就是计数器值还没有减到窗口值以下,当 0x0 < 计数器值(V) < 窗口值(WV) 时,这时候最适合喂狗了,也只有在这时候喂狗才合适。$ B8 w/ S4 I# ^% W. b

+ |8 T1 k% S* d2 }( w        另外IWDG可以通过软件或硬件启动(可通过选项字节配置),由于是低速内部时钟(LSI)计时,因此即使主时钟发生故障,IWDG仍保持活动状态。并IWDG是在VDD电压域中实现,在STOP(停止)和STANDBY(待机)模式下仍可正常工作(IWDG重置可将CPU从STANDBY唤醒)。RCC控制状态寄存器中的IWDGRST标志可用于通知何时发生IWDG重置。
8 T( G7 x0 `& I: Q! V4 y# N% T* D9 [: O2 J) A* q8 o
( z4 l; l& O! {' Z' \9 z
二、IWDG工程创建
% G* I. J2 ^  r; u# f, a        2.1 创建工程及配置IWDG
$ J, l5 a! P( J: t1 {: _
        本文采用的是STM32L496VGT6-ali开发板,是基于前面工程的.ioc在CubeIDE开发平台创建了新工程,并移植了前面工程已经实现的按键、LED灯及lpuart1串口调试功能,可参考前面博文:$ Y7 D6 S2 L. ?$ D1 y5 [1 y2 G
/ Y/ v& M2 K" d) i# y+ o5 e
        假设已经完成了按键、LED灯及lpuart1串口调试功能后,双击.ioc文件打开cubeMX界面,配置IWDG,如下图所示,开启IWDG并设置参数32、4095,另外IWDT时钟频率是32KHz。
; U( f) I) ^; I1 c/ j7 S) h' O/ O! c3 h  B( d" [
281b87bfc5ee4f4fbe88b16cf33ad22e.png
5 r4 l) w- j$ y! T1 P  a
! t/ p5 _8 q6 w+ Y* l- z
cc81cf262d694fd1a1ac797b0d6bdac7.png 7 C5 b) R3 J' W7 w8 @$ H

' {, \% ]4 l3 Y, L9 ^         配置很简单,完成配置后,单击保存或生成代码按钮,输出生成代码。
8 X4 L+ N4 ?5 m7 E0 T: X9 K1 j. v5 \2 O: w
        2.2 IWDG的HAL实现源码分析
+ x% O* u: ]" ^3 M        cubeMX会为IWDG在Core/Inc和Core/Src生成独立看门狗的头文件及源文件,实现源码也很简单,定义独立看门狗句柄(IWDG寄存器)及初始化函数MX_IWDG_Init。( }6 b  R/ s+ X2 w3 d  e  m
5 B9 F0 {' T5 e
8fa2531489084644a4099f646ab25682.png * Y3 Y( n2 K: a. ?( v" H! j. V
/ i+ h; b9 [+ o
         在MX_IWDG_Init函数中,只做了两件事,将在cubeMX上配置的参数传递给IWDG参数缓存区及实例化IWDG寄存器,调用HLA看门狗初始化函数(HAL_IWDG_Init)实现真正的初始化。) n$ L1 {/ l' s" b
! p9 y4 `0 b' [
80d432ea8cac40f7b06211686c6f036e.png
% u2 c+ s# @5 i; O( l, X9 z4 u6 }) U/ r; ~
1c6d166622c3453ab7aba32ef805f17a.png + ~  D! M  }7 d- W+ N0 u
) O/ V2 k3 h6 x- C3 x
        在stm32L4xx_HLA_iwdg.c驱动文件中,HAL_IWDG_Init函数内,首先对cubeMX上配置参数的合理性诊断,然后开启IWDG和使能写入访问,将已经缓存的配置参数写入IWDG寄存器,并检查设置是否合理,在HAL_IWDG_DEFAULT_TIMEOUT内完成寄存器更新,最后设置计数器值V等于重装载值RL,开启真正计数。
3 X% ~7 ]2 }/ Q! Q: S
  1. HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
    4 t+ g! s$ M4 ~, J: a1 \3 _
  2. {1 N2 o3 U( ~5 o6 C( {
  3.   uint32_t tickstart;) G9 w  O( Y. n4 O
  4. + T- f  A% \. H9 u
  5.   /* Check the IWDG handle allocation */
    2 D1 g9 E# I- |5 ~% A; w
  6.   if (hiwdg == NULL)
    5 I& t; F/ K5 g5 N3 B
  7.   {2 E9 u% i8 P9 c( E
  8.     return HAL_ERROR;
    ! T% I2 }. z" z
  9.   }
    2 e7 m; z9 d( C) B
  10. 4 A* E- w% y/ X0 f# u
  11.   /* Check the parameters */
    + x: V+ }0 K6 S; S2 f! s
  12.   assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
    3 G8 D5 D. B9 @+ m# X) ]6 @, c
  13.   assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));% K& j1 d+ K$ d+ I3 c7 q( T
  14.   assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
    + b/ E) C. ?: O/ F, l6 {
  15.   assert_param(IS_IWDG_WINDOW(hiwdg->Init.Window));
    7 t2 |( e- P+ i8 T/ [" J
  16. , i7 D9 y5 g0 ?: F  X4 L
  17.   /* Enable IWDG. LSI is turned on automatically */, ], i6 Q) x0 x; Z$ B3 {. I* Q
  18.   __HAL_IWDG_START(hiwdg);
    5 T/ ?* w/ g0 c! S

  19. 5 q* d2 w/ X' L3 u8 M+ Z% ]
  20.   /* Enable write access to IWDG_PR, IWDG_RLR and IWDG_WINR registers by writing
    4 j' k! D6 n; y* ~+ S2 y
  21.   0x5555 in KR */! O( Q! H/ y: ~3 k
  22.   IWDG_ENABLE_WRITE_ACCESS(hiwdg);; d* ?1 k. d7 D% u
  23. $ n$ |7 l2 \. E9 |& u/ U/ O/ B! f
  24.   /* Write to IWDG registers the Prescaler & Reload values to work with */
    6 w$ v+ t. r! f) `$ A+ t
  25.   hiwdg->Instance->PR = hiwdg->Init.Prescaler;4 J( ?" Q! o6 |1 S
  26.   hiwdg->Instance->RLR = hiwdg->Init.Reload;  M4 p& d9 p1 t2 E4 `8 c3 e

  27. $ }! o+ _! e5 C# H1 D
  28.   /* Check pending flag, if previous update not done, return timeout */3 N: Y& w0 o4 z; \1 ?6 c, ^  x1 r2 B
  29.   tickstart = HAL_GetTick();
    7 x# Z9 _" \: s, c2 D3 [# k

  30.   S5 X% c  O( C$ \
  31.   /* Wait for register to be updated */! S* a" \  u5 C4 q4 m2 v
  32.   while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)- `3 ~$ m% \% ?+ c5 K9 j: |, d* J
  33.   {7 q4 ~) a0 d! d, n: m( o9 y
  34.     if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)5 u1 I( _" W! L' c3 j& M0 E6 Z
  35.     {3 _0 O% o6 C1 s. H. V5 E0 |
  36.       if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
    % t* O0 t: w* k8 t7 F- {: i
  37.       {5 O) N- }# p* p5 ]8 a' n, U3 v
  38.         return HAL_TIMEOUT;
    % _) k3 R  S# c; U6 u
  39.       }$ U. w( y2 h; _; [$ R( I6 I& \
  40.     }: K# Y2 l5 E  c5 |+ p
  41.   }' l( K2 ?) ]; e. @: e

  42. ' ]2 r8 X7 M! ~. i
  43.   /* If window parameter is different than current value, modify window
    : u- ~. _% o. v% t: m$ u5 g. v
  44.   register */
    9 |6 }$ @: N/ ~* R0 I1 V
  45.   if (hiwdg->Instance->WINR != hiwdg->Init.Window)
    / `$ u# @8 e1 d6 J4 Y/ j% V/ `
  46.   {
    ' L# w) @# o5 h7 e* D
  47.     /* Write to IWDG WINR the IWDG_Window value to compare with. In any case,; C$ o/ Z0 Z% e8 u! K; U
  48.     even if window feature is disabled, Watchdog will be reloaded by writing
    1 O; Z4 M" m& p3 y
  49.     windows register */
    9 o/ ?6 B+ N2 r9 e, w
  50.     hiwdg->Instance->WINR = hiwdg->Init.Window;2 M$ B7 G  a6 M
  51.   }
    - g- ~  @, R: }$ r
  52.   else$ H9 F- ~7 I7 S. W  `" `
  53.   {: S% x6 G- K" E5 F+ w2 c
  54.     /* Reload IWDG counter with value defined in the reload register */5 e& i! l: m) i  Z
  55.     __HAL_IWDG_RELOAD_COUNTER(hiwdg);
    * V! \# ?* \& W7 Z, o1 b6 \3 k' e
  56.   }
    , _9 r' u5 D+ h) G9 h; E5 V

  57. , f) Z7 Q2 @& [$ O
  58.   /* Return function status */: c- V0 m' W9 O! v) k
  59.   return HAL_OK;
    ' p" Y) V2 J1 x( A& t
  60. }
复制代码
) |+ [" ?1 ?/ R! f
        同样,在stm32L4xx_HLA_iwdg.c驱动文件中,HLA库提供了喂狗函数HAL_IWDG_Refresh,需要我们在规定时间内(由在cubeMX上配置的参数和时钟频率来决定),使用中调用该函数喂狗,就可以防止看门狗复位。
1 X+ e$ ^" E1 M) \% A) ]$ u
  1. /**/ o  C; H0 J  q6 z
  2.   * @brief  Refresh the IWDG.
    : n; m) T; C1 ]4 R2 P' @6 z
  3.   * @param  hiwdg  pointer to a IWDG_HandleTypeDef structure that contains
    * q  X# C. n6 F' @! O( |$ F
  4.   *                the configuration information for the specified IWDG module.2 ]2 `* j% l6 @( C1 ^# l8 t
  5.   * @retval HAL status
    # P2 T% X/ u* g3 V, l, J
  6.   */, p" Q8 z! d. l3 C
  7. HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
    0 Q8 ?1 ]+ M# g! w4 O0 q# r
  8. {; L" O" l8 s3 A2 I
  9.   /* Reload IWDG counter with value defined in the reload register */0 c$ `1 n' ]9 }. u
  10.   __HAL_IWDG_RELOAD_COUNTER(hiwdg);
    0 {1 a% f2 e: ?1 e

  11. & W9 @8 j# x1 k8 }
  12.   /* Return function status */, r/ I5 m+ w  J5 }4 b7 f3 N
  13.   return HAL_OK;
    9 Y9 C- [, l% c- b$ U2 m: _2 M% a
  14. }
复制代码
5 C! \9 [+ L/ S/ w
         2.3 IWDG使用
: ~9 Q' w* k2 {/ `        本文在IWDG使用设计是,通过按键输入触发不再喂狗,这时是否系统复位,通过lpuart1调试信息确认是否成功。5 O$ T% T4 P$ ~: {6 @2 N
  {, X  j, Q8 X5 {' _5 V
        在main.c文件中,引入按键、LED灯及串口驱动头文件。5 @- }  m9 w% F1 X- ^0 U0 b
  1. /* Private includes ----------------------------------------------------------*/8 J. }  y" C" [) `8 P! p
  2. /* USER CODE BEGIN Includes */
    * ^* k, |! I1 W0 Q" P8 S; T% O
  3. #include "../../ICore/key/key.h"
    " y% |0 J& O! @' [& A
  4. #include "../../ICore/led/led.h"5 W# M; Z! q8 A& C
  5. #include "../../ICore/print/print.h"# T) g  Q$ D5 R" S' A( U1 k
  6. #include "../../ICore/usart/usart.h"" @( o1 }" `# l& z" f! H0 `
  7. /* USER CODE END Includes */
复制代码
# b: I# d( l  _* ?% R
        在main.c文件中,extern声明IWDG寄存器句柄。
2 {3 Y8 x6 H. Z7 g# q5 l' v* ]
  1. /* Private user code ---------------------------------------------------------*/
    , _/ {3 H6 p' j- t. [* V. d
  2. /* USER CODE BEGIN 0 */4 `( r& c9 u: W
  3. extern IWDG_HandleTypeDef hiwdg;( b0 s% ^  `0 Z+ M
  4. /* USER CODE END 0 */
复制代码

7 x' N- S2 a9 n, S6 e         在main主函数中,初始化串口,开启中断接收。
) A+ I9 Y) Y4 S; Q% B: M
  1. /* Initialize all configured peripherals */
    - \' f- D0 D9 F
  2.   MX_GPIO_Init();6 Q% P/ q; ]; g7 K) I
  3.   MX_LPUART1_UART_Init();
    $ f" t; _' d% C9 V/ L- [1 u- P
  4.   MX_IWDG_Init();  
    ) n7 R( Q7 t3 g" J0 o+ O
  5. /* USER CODE BEGIN 2 */4 w/ v' ^& e4 v; j4 t7 f7 d
  6.   ResetPrintInit(&hlpuart1);5 ~& O4 d' J+ J4 X5 ]3 q* W$ P- ^
  7.   HAL_UART_Receive_IT(&hlpuart1,(uint8_t *)&HLPUSART_NewData, 1); //再开启接收中断& T0 e' z2 E$ C# y
  8.   HLPUSART_RX_STA = 0;
    3 {" C$ n: `3 `/ o+ T1 `
  9.   //
    9 n6 N5 x  B, L$ @
  10.   uint8_t wdt_flag = 1;    //是否继续喂狗标记8 d+ c2 A; e2 z6 b9 W
  11.   printf("app restart now!\r\n");
    ; S  e% l9 s% @* v
  12.   /* USER CODE END 2 */
复制代码

9 M# w! W' y4 y7 d7 @3 l3 T        在main主函数中,实现喂狗功能。% y8 e% ^! _- l/ F* J. x7 Y7 K
  1. /* USER CODE BEGIN WHILE */
    8 Z$ {2 H- J0 C: b/ m( [  j* `
  2.   while (1)
    8 K/ E& D* N: C+ j& c! J0 p
  3.   {
    , d. W5 b+ n# Y" P! I) u9 O/ D
  4.           if(KEY_2())" y! I0 R- ^4 d* B( X
  5.             {) H. R  b' a$ Z* d0 ^, v/ ^) g
  6.                   wdt_flag = 0;
    ! ?, ?7 o6 D& }
  7.                   printf("IWDG_Refresh stop!\r\n");
    / N1 Y% D( X: e$ P( c
  8.             }
    * \- c6 y, S& T$ E! `
  9.           if(wdt_flag){+ R- A; ?: r, n" N' N
  10.                   HAL_IWDG_Refresh(&hiwdg);6 ~% l% {( C8 q: o  k) d( Y6 t, @
  11.                   HAL_Delay(10);//等待+ n, u1 f6 J7 X; v
  12.           }% O: D* P8 E3 q  l6 c' z2 ^+ q  E
  13.     Toggle_led1();4 m2 o9 {' B. ]4 b8 Z# J5 ^. Y# R
  14.     /* USER CODE END WHILE */
复制代码

& T+ o) O, }5 z* E: B$ d三、编译及测试/ S7 j! I* S- N
        3.1 编译
2 {" F) j1 C& j( u
        编译通过
  T$ m; y9 r0 G; W+ n1 [
4 c6 H2 Q0 x% J- g' F0 P
941b1813ba6e4f9485781ff30eba6095.png , a* F2 t* s. Z' }

# P5 L. ~% X% |# J+ \         下载程序
0 l/ p* i& D* ]7 U
4 v& b5 ]9 R! ]: I2 k7 t# z! t
fbb1d2243e204abcbe191414b62962b5.png ) Q  W+ H* ?# B- W6 D: A% v

* @# l" j* i* Y: R

  P* o" c/ v' B. A; c  u- Y        3.2 测试, B& I7 [3 ^+ f# v
        打开串口工具,连接上串口,观察窗口日志输出情况,按键KEY2测试如下:
" ]/ N1 @0 z) m; [0 y' d1 P4 O/ v! v
08a682b40dd648539d5d852b94115a74.png
3 e& N3 Z3 I) Q! S2 l2 P
  v. }. a6 k( h$ |8 v( O+ ?: x         测试成功,不在喂狗时,等待一、两秒系统重启。4 o6 l) p- ?8 u6 p1 t
————————————————
8 l) W5 T/ i$ C4 n8 B版权声明:py_free-物联智能6 z4 p4 h' ~6 N4 S
如有侵权请联系删除
" n, n/ F+ O( Y6 i: Z" b  {* E4 z  x; s1 h
+ {6 g' @# m8 }* o2 J0 J6 E
收藏 评论0 发布时间:2023-4-6 15:25

举报

0个回答

所属标签

相似分享

官网相关资源

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