SmartOS之(C++)------看门狗类WatchDog

 

 

  SmartOS (C++)的GPIO驱动,兼容STM32F0/F1/F4/GD32F10x/GD32F1x0

 

  头文件

  1 #ifndef __WatchDog_H__

  2 #define __WatchDog_H__

  3 

  4 #include "Sys.h"

  5 

  6 // 看门狗

  7 class WatchDog

  8 {

  9 private:

 10 

 11 public:

 12     WatchDog(uint ms = 3000);

 13     ~WatchDog();

 14     

 15     uint Timeout; // 当前超时时间

 16     

 17     bool Config(uint ms);    // 配置看门狗喂狗重置时间,超过该时间讲重启MCU

 18     void ConfigMax();        // 看门狗无法关闭,只能设置一个最大值

 19     void Feed(); // 喂狗

 20 };

 21 

 22 #endif源码实现

 23 

 24 #include "WatchDog.h"

 25 

 26 /*

 27 独立看门狗IWDG——有独立时钟(内部低速时钟LSI---40KHz),所以不受系统硬件影响的系统故障探测器。主要用于监视硬件错误。 

 28 窗口看门狗WWDG——时钟与系统相同。如果系统时钟不走了,这个狗也就失去作用了,主要用于监视软件错误。 

 29 

 30 独立看门狗

 31 看门狗定时时限=IWDG_SetReload()的值 / 看门狗时钟频率

 32 看门狗时钟频率=LSI(内部低速时钟)的频率(40KHz)/ 分频数

 33 

 34 独立看门狗(IWDG)由专用的40kHz的低速时钟为驱动。因此,即使主时钟发生故障它也仍然有效。

 35 窗口看门狗由从APB1时钟分频后得到的时钟驱动,通过可配置的时间窗口来检测应用程序非正常的过迟或过早的行为。

 36 IWDG_SetPrescaler()        分频,4~256

 37 IWDG_SetReload()        计数值12位 0~0x0FFF

 38 IWDG_ReloadCounter()    喂狗,必须在计数值减到1之前喂狗

 39 

 40 IWDG_PR和IWDG_RLR寄存器具有写保护功能。要修改这两个寄存器的值,必须先向IWDG_KR寄存器中写入0x5555。

 41 以不同的值写入这个寄存器将会打乱操作顺序,寄存器将重新被保护。重装载操作(即写入0xAAAA)也会启动写保护功能。

 42 

 43 #define IWDG_WriteAccess_Enable     ((uint16_t)0x5555)

 44 #define IWDG_WriteAccess_Disable    ((uint16_t)0x0000)

 45 

 46 void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)

 47 {

 48   assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));

 49   IWDG->KR = IWDG_WriteAccess;

 50 }

 51 

 52 void IWDG_ReloadCounter(void)

 53 {

 54   IWDG->KR = KR_KEY_Reload;

 55 }

 56 void IWDG_Enable(void)

 57 {

 58   IWDG->KR = KR_KEY_Enable;

 59 }

 60 

 61 void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)

 62 {

 63   assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));

 64   IWDG->PR = IWDG_Prescaler;

 65 }

 66 void IWDG_SetReload(uint16_t Reload)

 67 {

 68   assert_param(IS_IWDG_RELOAD(Reload));

 69   IWDG->RLR = Reload;

 70 }

 71 

 72 */

 73 

 74 WatchDog::WatchDog(uint ms)

 75 {

 76     Timeout = ms;

 77     Config(ms);

 78 }

 79 

 80 WatchDog::~WatchDog()

 81 {

 82     ConfigMax();

 83 }

 84 

 85 bool WatchDog::Config(uint ms)

 86 {

 87     if(ms == 0)

 88     {

 89         debug_printf("WatchDog msTimeout %dms must larger than 0ms\r\n", ms);

 90         return false;

 91     }

 92     RCC_LSICmd(ENABLE);

 93     /* 检查系统是否从IWDG重置恢复 */

 94     if (RCC_GetFlagStatus(RCC_FLAG_IWDGRST) != RESET)

 95     {

 96         /* 清除重置标识 */

 97         RCC_ClearFlag();

 98     }

 99     /* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */

100     IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

101 

102     byte pre = IWDG_Prescaler_4;

103     int mul = 4;

104     // 计数器12位 0~0x0FFF,有reload = ms/1000 / (1/(LSI/mul)) = ms * LSI / (mul*1000) = ms * 40 / mul

105     // 考虑到reload溢出的可能,每种分频最大ms = reload * mul / 40 ~= 102 * mul

106     int i=0;

107     /*

108     #define IWDG_Prescaler_4            ((uint8_t)0x00)

109     #define IWDG_Prescaler_8            ((uint8_t)0x01)

110     #define IWDG_Prescaler_16           ((uint8_t)0x02)

111     #define IWDG_Prescaler_32           ((uint8_t)0x03)

112     #define IWDG_Prescaler_64           ((uint8_t)0x04)

113     #define IWDG_Prescaler_128          ((uint8_t)0x05)

114     #define IWDG_Prescaler_256          ((uint8_t)0x06)

115     */

116     for(i = IWDG_Prescaler_4; i <= IWDG_Prescaler_256; i++)

117     {

118         pre = i;

119         mul = 1 << (i + 2);

120 

121         // 判断是否在范围之内

122         if(ms * 40 / mul < 0x0FFF) break;

123     }

124     if(i > IWDG_Prescaler_256)

125     {

126         debug_printf("WatchDog msTimeout must smaller than %dms\r\n", 0x0FFF * 256 / 40);

127         return false;

128     }

129     IWDG_SetPrescaler(pre);

130     /*if(ms < (0x0FFF * 32 / 40))

131     {

132         // IWDG计数器时钟: LSI/32=40KHz/32=1250Hz,每周期0.8ms

133         IWDG_SetPrescaler(IWDG_Prescaler_32);

134     }

135     else

136     {

137         // IWDG计数器时钟: LSI/64=40KHz/64=625Hz,每周期0.4ms

138         IWDG_SetPrescaler(IWDG_Prescaler_64);

139 

140         // 直接除以2,后面不用重复计算

141         ms >>= 2;

142     }*/

143 

144     /* 设置计数器重载值为超时时间

145      Counter Reload Value = ms / 1000 / IWDG计数器时钟周期

146                           = ms / 1000 / (1/(LSI/mul))

147                           = ms * LSI / (mul * 1000)

148                           = ms * 40k / (mul * 1000)

149                           = ms * 40 / mul

150     */

151     IWDG_SetReload(ms * 40 / mul);

152 

153     /* 重载 IWDG 计数器 */

154     IWDG_ReloadCounter();

155 

156     /* 打开 IWDG (LSI将由硬件打开) */

157     IWDG_Enable();

158 

159     Timeout = ms;

160 

161     return true;

162 }

163 

164 void WatchDog::ConfigMax()

165 {

166     /* 打开IWDG_PR和IWDG_RLR寄存器的写访问 */

167     IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);

168 

169     // 独立看门狗无法关闭

170     IWDG_SetPrescaler(IWDG_Prescaler_256);

171     IWDG_SetReload(0x0FFF);

172     IWDG_ReloadCounter();

173 }

174 

175 void WatchDog::Feed()

176 {

177     IWDG_ReloadCounter();

178 }

 

End!
欢迎大家一起交流 ,分享程序员励志故事。   幸福的程序员 QQ群:幸福的程序员 智能硬件群中国嵌入式物联网群

 

你可能感兴趣的:(C++)