模塊介紹
N32L40XCL 內(nèi)置獨立看門狗(IWDG)和窗口看門狗(WWDG)定時器,解決軟件錯誤導(dǎo)致的問題??撮T狗定時器使用非常靈活,提高了系統(tǒng)的安全性和定時控制的準(zhǔn)確性。
獨立看門狗(IWDG)由運行在 40KHz 的低速內(nèi)部時鐘(LSI 時鐘)驅(qū)動,在死循環(huán)事件或 MCU 卡死發(fā)生時,它仍然可以運行。這可以提供更高的安全級別、定時精度和看門狗的靈活性。它可以通過重置來解決由于軟件故障引起的系統(tǒng)故障。IWDG 最適合需要看門狗在主應(yīng)用程序之外作為完全獨立進程運行但時序精度限制較低的應(yīng)用程序。
窗口看門狗(WWDG)的時鐘是由 APB1 時鐘頻率除以 4096 得到的,通過時間窗口的配置來檢測程序運行是否異常。因此,WWDG 適用于精確定時,常用于監(jiān)控因外部干擾或無法預(yù)見的邏輯條件導(dǎo)致應(yīng)用程序偏離其正常操作順序的軟件故障。當(dāng) WWDG 遞減計數(shù)器在達到窗口寄存器值之前或 WWDG_CTRL.T6 位變?yōu)?0 之后刷新時,系統(tǒng)復(fù)位發(fā)生。
官方WDT驅(qū)動實現(xiàn)的是獨立看門狗(IWDG)。
開發(fā)軟件
開發(fā)環(huán)境:
RT-Thread Studio 2.2.6
RT-Thread版本:4.0.2
下載工具:pyocd
步驟說明
新建工程
打開RT-Thread settings,使能Watchdog Timer,如下圖所示。
添加保存后,進行編譯,若無問題,則進行下一步。
編寫測試程序
編寫測試程序如下:
#include
#include
#include
/* defined the LED3 pin: PB5 /
#define LED3_PIN GET_PIN(B, 5)
#define WDT_DEVICE_NAME "wdt" / 看門狗設(shè)備名稱 /
static rt_device_t wdg_dev; / 看門狗設(shè)備句柄 /
static void idle_hook(void)
{
/ 在空閑線程的回調(diào)函數(shù)里喂狗 /
rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
//rt_kprintf("feed the dog!n ");
}
int main(void)
{
/ set LED3 pin mode to output /
rt_pin_mode(LED3_PIN, PIN_MODE_OUTPUT);
rt_err_t ret = RT_EOK;
rt_uint32_t timeout = 3000; / 溢出時間,單位:毫秒 /
char device_name[RT_NAME_MAX];
rt_strncpy(device_name, WDT_DEVICE_NAME, RT_NAME_MAX);
/ 根據(jù)設(shè)備名稱查找看門狗設(shè)備,獲取設(shè)備句柄 /
wdg_dev = rt_device_find(device_name);
if (!wdg_dev)
{
rt_kprintf("find %s failed!n", device_name);
return RT_ERROR;
}
/ 設(shè)置看門狗溢出時間 /
ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
if (ret != RT_EOK)
{
rt_kprintf("set %s timeout failed!n", device_name);
return RT_ERROR;
}
/ 啟動看門狗 /
ret = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_START, RT_NULL);
if (ret != RT_EOK)
{
rt_kprintf("start %s failed!n", device_name);
return -RT_ERROR;
}
/ 根據(jù)設(shè)備名稱查找看門狗設(shè)備,獲取設(shè)備句柄 /
wdg_dev = rt_device_find(device_name);
if (!wdg_dev)
{
rt_kprintf("find %s failed!n", device_name);
return RT_ERROR;
}
/ 設(shè)置空閑線程回調(diào)函數(shù) */
rt_thread_idle_sethook(idle_hook);
while (1)
{
rt_pin_write(LED3_PIN, PIN_HIGH);
rt_thread_mdelay(500);
rt_pin_write(LED3_PIN, PIN_LOW);
rt_thread_mdelay(500);
}
}
代碼驗證
程序很簡單,初始化看門狗后,在空閑線程回調(diào)函數(shù)中不斷喂狗即可。在正式使用看門狗時,取消回調(diào)函數(shù)中的打印。
下載程序后運行。
如果終端打印提示“warning: tidle0 stack is close to end of stack address.”,請在rtconfig.h文件中搜索IDLE_THREAD_STACK_SIZE,并擴大該??臻g。默認值是256,可以擴大到512。
程序中使用RT_DEVICE_CTRL_WDT_SET_TIM命令設(shè)置超時時間,需要注意對于N32L40XCL開發(fā)板的驅(qū)動程序而言,這個超時時間的單位是毫秒,而有些RT-Thread的驅(qū)動程序這個超時時間的單位是秒。
此外,這個超時時間不能設(shè)置過長,因為過長會超過N32L40XCL寄存器的范圍。對于默認配置,這個超時時間不能超過376ms。否則程序會打印如下錯誤信息:
[W/DBG] wdg set timeout parameter too large, please less than 3276 ms
set wdt timeout failed!
具體的工作原理可以參考下面這段drv_wdt.c的代碼:
case RT_DEVICE_CTRL_WDT_SET_TIMEOUT:
{
RT_ASSERT(*(uint16_t *)args != 0);
reload_value = *(uint16_t *)args;
if(reload_value > 0xFFF * 32 *1000 / LsiFreq)
{
LOG_W("wdg set timeout parameter too large, please less than %d msn", 0xFFF * 32 *1000 / LsiFreq);
return -RT_EINVAL;
}
/* Enable write access to IWDG_PR and IWDG_RLR registers */
IWDG_WriteConfig(IWDG_WRITE_ENABLE);
/* IWDG counter clock: LSI/32 */
IWDG_SetPrescalerDiv(IWDG_PRESCALER_DIV32);
reload_value = ((uint32_t)reload_value * LsiFreq / 1000) / 32;
IWDG_CntReload(reload_value);
IWDG_WriteConfig(IWDG_WRITE_DISABLE);
}
如果注釋掉上面idle_hook中的喂狗語句,則可以看到程序每3秒重啟一次。
章節(jié)總結(jié)
通過測試,可以驗證N32L40XCL芯片的WDT驅(qū)動程序可以正常運行。
-
寄存器
+關(guān)注
關(guān)注
31文章
5295瀏覽量
119832 -
RT-Thread
+關(guān)注
關(guān)注
31文章
1261瀏覽量
39841 -
MCU控制器
+關(guān)注
關(guān)注
0文章
27瀏覽量
6867 -
WWDG
+關(guān)注
關(guān)注
0文章
19瀏覽量
5485 -
IWDG
+關(guān)注
關(guān)注
0文章
21瀏覽量
5191
發(fā)布評論請先 登錄
相關(guān)推薦
評論