本教程基于韋東山百問網(wǎng)出的 DShanMCU-RA6M5開發(fā)板 進(jìn)行編寫,需要的同學(xué)可以在這里獲?。?https://item.taobao.com/item.htm?id=728461040949
配套資料獲取:https://renesas-docs.100ask.net
瑞薩MCU零基礎(chǔ)入門系列教程匯總: https://blog.csdn.net/qq_35181236/article/details/132779862
第26章 獨(dú)立看門狗定時(shí)器-IWDT
本章目標(biāo)
- 了解A6M5處理器的看門狗定時(shí)器及其工作原理;
- 學(xué)會(huì)使用RASC配置看門狗定時(shí)器,使用其接口函數(shù);
26.1 RA6M5的WDT外設(shè)
26.1.1 WDT的特性
IWDT (Independent Watchdog Timer)由一個(gè)14位的向下計(jì)數(shù)器組成,可以將應(yīng)用程序從錯(cuò)誤中恢復(fù)處理(比如重啟系統(tǒng))。應(yīng)用程序必須在允許的計(jì)數(shù)窗口內(nèi)進(jìn)行刷新計(jì)時(shí)器,如果計(jì)數(shù)器下溢了,IWDT將復(fù)位MCU或生成不可屏蔽中斷(NMI)。
瑞薩RA6M5處理器的看門狗定時(shí)器的特性見下表:
獨(dú)立看門狗的時(shí)鐘源是一個(gè)獨(dú)立的時(shí)鐘IWDTCLK,PCLKB最大的時(shí)鐘頻率是15kHz,可以使用RASC在BSP中設(shè)置IWDTCLK的分頻系數(shù)。
26.1.2 IWDT的系統(tǒng)框圖
IWDT的系統(tǒng)框圖如下圖所示:
26.1.3 IWDT和WDT的異同
- 差異點(diǎn)
瑞薩RA6M5的獨(dú)立看門狗(IWDT)與看門狗(WDT)的不同點(diǎn)如下:
- 時(shí)鐘源不一樣,WDT使用外部時(shí)鐘電路作為時(shí)鐘源,而IWDT自帶時(shí)鐘源;
- WDT有寄存器啟動(dòng)和自啟動(dòng)兩種模式,IWDT只有自啟動(dòng)這一種模式;
- 相同點(diǎn)
獨(dú)立看門狗(IWDT)與看門狗(WDT)也有很多相似點(diǎn),主要如下:
- 都可以選擇復(fù)位的范圍(窗口值);
- 都可以設(shè)置在睡眠模式下是否啟動(dòng);
- 都可以設(shè)置NMI中斷和復(fù)位重啟;
26.1.4 IWDT的工作原理
- 超時(shí)時(shí)間計(jì)算
以IWDTCLK=15kHz為例,假設(shè)對(duì)IWDT進(jìn)行了以下配置:
- 分頻系數(shù)位256
- 超時(shí)時(shí)間周期為2048cycles
那么IWDT的超時(shí)時(shí)間為:
- 運(yùn)行狀態(tài)分析
在“Option Function Select Register 0”寄存器中,對(duì)于IWDT有一個(gè)模式選擇位[OFS0.IWDTSTRT]:它被寫為0時(shí),IWDT的自動(dòng)啟動(dòng)模式被使能;寫為1就是關(guān)閉IWDT的計(jì)數(shù)。
只有在復(fù)位狀態(tài)下,以下對(duì)IWDT在OFS0中的設(shè)置才會(huì)有效:
- 配置OFS0.IWDTCKS[3:0]來配置IWDT的時(shí)鐘分頻系數(shù);
- 配置OFS0.IWDTRPSS[1:0]和OFS0.IWDTRPES[1:0]來設(shè)置IWDT的窗口監(jiān)測(cè)始末位置;
- 配置OFS0.IWDTTOPS[1:0]來設(shè)置IWDT的超時(shí)周期值cycles;
- 配置OFS0.IWDTRSTIRQS來使能IWDT的重置輸出和中斷請(qǐng)求;
當(dāng)復(fù)位狀態(tài)結(jié)束后,IWDT的計(jì)數(shù)器將會(huì)立刻向下計(jì)數(shù)。在RA6M5的用戶手冊(cè)中展示了一個(gè)IWDT的窗口刷新例圖:
總結(jié)下來就是:
- 在窗口期內(nèi)刷新看門狗會(huì)讓IWDT計(jì)數(shù)器重新計(jì)數(shù)且不會(huì)觸發(fā)任何事件或中斷;
- 在沒有到窗口期起始位置刷新會(huì)觸發(fā)刷新錯(cuò)誤事件,并觸發(fā)NMI中斷;
- 在超過窗口結(jié)束位置但是計(jì)數(shù)沒有溢出期間刷新,會(huì)觸發(fā)刷新錯(cuò)誤事件,并觸發(fā)NMI中斷;
- 如果IWDT計(jì)數(shù)溢出了,會(huì)觸發(fā)技術(shù)溢出事件,觸發(fā)NMI中斷;
也就是說,如果使用了窗口監(jiān)測(cè),只有在窗口期刷新定時(shí)器才會(huì)讓系統(tǒng)正常運(yùn)行,否則都會(huì)觸發(fā)NMI中斷。
26.2 IWDT模塊的使用
26.2.1 模塊配置
- 添加IWDT Stack
在FSP的Stacks中添加IWDT模塊的步驟如下圖所示:
- 在BSP中配置IWDT
從前文對(duì)IWDT的工作原理分析中可以看到,對(duì)于IWDT的所有操作都是在OFS0寄存器中進(jìn)行配置的,而OFS0是在BSP板塊里面的“RA6F5 Family”中,如下圖所示:
- Start Mode Select:IWDT啟動(dòng)模式選擇
1.1 IWDT is automatically activated after a reset (Autostart mode)(自啟動(dòng))
1.2 IWDT is Disabled
- Timeout Period:IWDT計(jì)數(shù)周期值
1.1 128 cycles
1.2 512 cycles
1.3 1024 cycles
1.4 2048 cycles
- Dedicated Clock Frequency Divisor:IWDT時(shí)鐘分頻系數(shù)(1/16/32/64/128/256),默認(rèn)128;
- Window End Position:窗口監(jiān)測(cè)結(jié)束位置,默認(rèn)0%,沒有結(jié)束位置
- Window Start Position:窗口監(jiān)測(cè)開始位置,默認(rèn)100%,沒有開始位置
- Reset Interrupt Request:選擇使能觸發(fā)復(fù)位的中斷請(qǐng)求(NMI或Reset)
- Stop Control:停止對(duì)WDT控制的條件
1.1 Stop counting when in Sleep, Snooze mode, or Software Standby
1.2 Counting continues (Note: Device will not enter Deep Standby Mode when selected. Device will enter Software Standby Mode)
如果用戶選擇使用了NMI中斷,還需要去RASC的Stacks中找到IWDG Stack模塊,設(shè)置NMI的中斷回調(diào)函數(shù)名,如下圖所示:
26.2.2 配置信息解讀
在RASC中配置IWDT并生成工程后,會(huì)在hal_data.c中生成結(jié)構(gòu)體全局常量g_iwdt,它被用來表示IWDT設(shè)備,代碼如下:
const wdt_instance_t g_wdt =
{
.p_ctrl = &g_iwdt_ctrl,
.p_cfg = &g_iwdt_cfg,
.p_api = &g_wdt_on_iwdt
};
- p_ctrl:iwdt_instance_ctrl_t類型指針成員,用來記錄設(shè)備狀態(tài),記錄一些重要信息(比如回調(diào)函數(shù));
- p_cfg:指向IWDT的配置結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體的數(shù)值來自在RASC中對(duì)IWDT的配置,代碼如下:
const wdt_cfg_t g_iwdt_cfg =
{
.timeout = 0,
.clock_division = 0,
.window_start = 0,
.window_end = 0,
.reset_control = 0,
.stop_control = 0,
.p_callback = nmi_callback,
};
- p_api:指向了一個(gè)wdt_api_t結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體在r_iwdt.c中實(shí)現(xiàn),它封裝了IWDT設(shè)備的接口函數(shù),代碼如下:
const wdt_api_t g_wdt_on_iwdt =
{
.open = R_IWDT_Open,
.refresh = R_IWDT_Refresh,
.statusGet = R_IWDT_StatusGet,
.statusClear = R_IWDT_StatusClear,
.counterGet = R_IWDT_CounterGet,
.timeoutGet = R_IWDT_TimeoutGet,
.callbackSet = R_IWDT_CallbackSet,
};
26.2.3 中斷回調(diào)函數(shù)
在RASC中配置了IWDT的中斷回調(diào)函數(shù)名字,會(huì)在hal_data.h中聲明此回調(diào)函數(shù):
#ifndef nmi_callback
void nmi_callback(wdt_callback_args_t * p_args);
#endif
用戶需要實(shí)現(xiàn)這個(gè)回調(diào)函數(shù),例如:
void nmi_callback(wdt_callback_args_t * p_args)
{
(void)p_args;
}
26.2.4 API接口及其用法
前文已經(jīng)說過,在FSP庫(kù)函數(shù)中是使用wdt_api_t結(jié)構(gòu)體來封裝IWDT的操作方法,原型如下:
typedef struct st_wdt_api
{
fsp_err_t (* open)(wdt_ctrl_t * const p_ctrl, wdt_cfg_t const * const p_cfg);
fsp_err_t (* refresh)(wdt_ctrl_t * const p_ctrl);
fsp_err_t (* statusGet)(wdt_ctrl_t * const p_ctrl, wdt_status_t * const p_status);
fsp_err_t (* statusClear)(wdt_ctrl_t * const p_ctrl, const wdt_status_t status);
fsp_err_t (* counterGet)(wdt_ctrl_t * const p_ctrl, uint32_t * const p_count);
fsp_err_t (* timeoutGet)(wdt_ctrl_t * const p_ctrl,
wdt_timeout_values_t * const p_timeout);
fsp_err_t (* callbackSet)(wdt_ctrl_t * const p_api_ctrl,
void (* p_callback)(wdt_callback_args_t *),
void const * const p_context,
wdt_callback_args_t * const p_callback_memory);
} wdt_api_t;
瑞薩在r_iwdt.c中實(shí)現(xiàn)一個(gè)wdt_api_t結(jié)構(gòu)體,IWDT和WDT共用一套操作接口,讀者請(qǐng)參考《25.2.4 API接口及其用法》了解這些函數(shù)的用法。
26.3 獨(dú)立看門狗定時(shí)器實(shí)驗(yàn)
26.3.1 設(shè)計(jì)目的
讓用戶學(xué)會(huì)使用瑞薩RA6M5的IWDT,并觀察是否刷新看門狗的現(xiàn)象。
26.3.2 硬件連接
本實(shí)驗(yàn)會(huì)用到板載串口和按鍵,請(qǐng)讀者參考前文配置。
26.3.3 驅(qū)動(dòng)程序
- 初始化IWDT
調(diào)用open函數(shù)即可初始化IWDT,并啟動(dòng)它,代碼如下:
void IWDTDrvInit(void)
{
fsp_err_t err = g_iwdt.p_api->open(g_iwdt.p_ctrl, g_iwdt.p_cfg);
assert(FSP_SUCCESS == err);
}
- 刷新IWDT
刷新IWDT比較簡(jiǎn)單,直接調(diào)用其refresh函數(shù)即可:
void IWDTDrvRefresh(void)
{
fsp_err_t err = g_iwdt.p_api->refresh(g_iwdt.p_ctrl);
assert(FSP_SUCCESS == err);
}
- NMI中斷回調(diào)函數(shù)
在RASC中使能了IWDT的NMI中斷,需要自己實(shí)現(xiàn)NMI回調(diào)函數(shù),代碼如下:
__WEAK void DataSaveProcess(void)
{
}
void nmi_callback(wdt_callback_args_t * p_args)
{
(void)p_args;
printf("\r\nWarning!Do your most important save working!!\r\n");
DataSaveProcess();
}
- 按鍵刷新定時(shí)器
在按鍵消抖處理后,刷新看門狗定時(shí)器,代碼如下:
void KeyProcessEvents(void)
{
struct IODev *ptLedDev = IOGetDecvice("UserLed");
struct IODev *ptKeyDev = IOGetDecvice("UserKey");
ptLedDev->Write(ptLedDev, ptKeyDev->Read(ptKeyDev));
IWDTDrvRefresh();
}
26.3.4 測(cè)試程序
在本次實(shí)驗(yàn)中,初始化了各個(gè)外設(shè)后,主循環(huán)中不用做任何事情,所有的操作都是在中斷中完成的:
- 按鍵中斷
- 滴答定時(shí)器消除按鍵抖動(dòng)
- NMI中斷處理用戶的緊急事件
測(cè)試函數(shù)代碼如下:
void IWDTAppTest(void)
{
SystickInit();
UARTDrvInit();
struct IODev *ptdev = IOGetDecvice("UserKey");
if(NULL != ptdev)
ptdev->Init(ptdev);
ptdev = IOGetDecvice("UserLed");
if(NULL != ptdev)
ptdev->Init(ptdev);
IWDTDrvInit();
while(1)
{
/* The code that is watched by iwdt */
}
}
26.3.5 測(cè)試結(jié)果
將編譯出來的二進(jìn)制可執(zhí)行文件燒錄到板子上并運(yùn)行,如果不按按鍵的話會(huì)得到例如下圖這樣的打印信息:文章來源:http://www.zghlxwxcb.cn/news/detail-719564.html
文章來源地址http://www.zghlxwxcb.cn/news/detail-719564.html
到了這里,關(guān)于第26章_瑞薩MCU零基礎(chǔ)入門系列教程之獨(dú)立看門狗定時(shí)器-IWDT的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!