設備驅動的藝術之旅 - Watch Dog 的 NMI 應用場景

From: 設備驅動的藝術之旅

一、硬件描述

1、器件品牌

意法半導體 – STM706T/S/R

2、硬件原理連接圖

wdt
信號管教描述:
MR :低有效收到復位!
WDI:遇到一個上升沿/下降沿,內部定時器將清零。1.6s不發生跳變,溢出,WDO輸出。
WDO:WDI1.6s不發生跳變,輸出低。VCC低於1.2V 輸出低。
RST:高有效,復位信號只能被VCC或者MR觸發,WDO輸出低不能觸發。
RST:同上,低有效。
PFI:電壓監控管腳,小於3.3V,PFO輸出低。
PFO:同上,未使用,懸空。

根據上述電路圖獲取到的信息:
a.復位信號爲低有效。
b.輸入小於3.3V,,復位。
c>WDO爲低時候,也復位(通過MR信號)。
Note:
上述WD_MR、WD_WDO、WD_RESET、WD_WDI信號都和CPLD連接起來,進行一些功能擴展。

3、功能設計

將watch dog結合CPLD進行了一些管腳功能擴展!
結合硬件給出的功能軟件功能分爲三點:
A>CPLD控制餵狗輸入。
B>WDO輸出後MR有效(復位)。
C>WDO輸出後也要做爲NMI中斷上報給CPU。

二、驅動框架

1、CPLD處理簡單流程

CPLD_wdt

2、NMI上報記錄異常流程

NMI

3、僞代碼

3.1、CPLD 硬件僞代碼以及驅動僞代碼
/********** wdt cpld manul simulation *********/
cpu_nmi     =   wd_nmi | wd_mr; //上報中斷線
wd_mr       =   wd_wdo; //復位管腳
wd_wdi      =   rst_en_r;//餵狗輸入
if (!wdt_cls)            //清除計數
begin
wdt_cr_120s = 0;        
wdt_cr_30s  = 0;        
end
begin
    if(time_cs==0)
    begin
    wdt_cr_120s = wdt_cr_120s + 1;
    wdt_cr_30s = 0;
    end
    else
    begin
    wdt_cr_30s = wdt_cr_30s + 1;
    wdt_cr_120s = 0;    
    end
end
if(~(sys_rstn))        //  系統復位
begin
    wd_nmi = 1;         //清除nmi       
    rst_en_r = 0;           //關狗,8hz輸出                                                        
    wdt_rboot_r = 0;    //清除本地計數器                                                          
end
else                                    //解除系統復位
begin
        if(wd_nmi == 0) //產生了系統nmi中斷
        begin
                if(wdt_rboot_r == 6)    //after 36s then hold nmi==1
                begin
                    rst_en_r = 1;   //total time is 32+4+1.6 seconds.
                end
                else
                begin
                    wdt_rboot_r = wdt_rboot_r + 1;
                    rst_en_r = 0;
                end
        end
        else        //no nmi
            begin
                if((wdt_cr_120s == 120)||(wdt_cr_30s == 30))//大約120s 或者 30s
                    begin
                        wd_nmi = 0;
                        rst_en_r = 0;
                    end
                else
                    begin
                        wd_nmi = 1; 
                        rst_en_r = 0;   
                    end
            end                                     
end 
/********** CPLD 採用打拍子計數*********/
flag_wtd_reg_couter[0] = flag_wtd_reg;
flag_wtd_reg_couter[2:1] = flag_wtd_reg_couter[1:0];
wdt_cls = ((flag_wtd_reg_couter[2:1] == 0x10)|(flag_wtd_reg_couter[2:1] == 0x91))? 0:1;   //cls Low 有效
3.1、驅動代碼
/********** 驅動代碼 *********/
/*  1、通過Localbus 對CPLD進行操作!
 *  2、上報上來的中斷硬件連線連在GPIO 39!
 *  3、上報中斷類型必須配置爲NMI!
 */
 function wdt_cls()
 {
    //需和硬件CPLD代碼進行對接。
    g_cpld_locabus->reg[x] = 0x55;
    g_cpld_locabus-->reg[y] = 0xaa;
 }

 function __init init_wls()
 {
    for (;;)
    {
        wdt_cls();
        msleep(10); //加一點延時
    }
 }
 function nmi_wdog_init()
 {
    gpio[0xxx] = 0xxx; //根據手冊配置GPIO相關寄存器,注意配置爲NMI
 }
 function init_process();
 {
    thread_create(init_wls,NULL,"watchdog");
    run_thread();
    nmi_wdog_init()
 }

 /*NMI中斷在哪裏處理,根據體系結構不同入口也不一樣。關鍵處理字爲except_vec_nmi*/

三、Q & A

1、明明已經餵狗了,上報上去的信號卻一直爲低?

注意verilog語言中管腳端口,賦值不正確。

2、NMI異常EPC如何確定並開啓?

關於MIPS異常處理會在其他地方進行總結,這裏只簡單說明異常向量如何跳轉。
NMI處理異常向量全局變量:except_vec_nmi 向量表初始化在genex.S 文件中

/*
 * NMI debug exception handler for MIPS reference boards.
 * The NMI debug exception entry point is 0xbfc00000, which
 * normally is in the boot PROM, so the boot PROM must do a
 * unconditional jump to this vector.
 */
NESTED(except_vec_nmi, 0, sp)
    j   nmi_handler
    END(except_vec_nmi)


如果有必要,需要自己指定handler函數。

#ifdef CONFIG_CPU_XLP
/*
 * Common SMP definitions
 */
#define RESET_VEC_PHYS      0x1fc00000
#define RESET_VEC_SIZE      8192        /* 8KB reset code and data */
#define RESET_DATA_PHYS     (RESET_VEC_PHYS + (1<<10))

/* Offsets of parameters in the RESET_DATA_PHYS area */
#define BOOT_THREAD_MODE    0
#define BOOT_NMI_LOCK       4
#define BOOT_NMI_HANDLER    8


static inline void *
tmp_nlm_get_boot_data(int offset)
{
    return (void *)(CKSEG1ADDR(RESET_DATA_PHYS) + offset);
}
static inline void
tmp_nlm_set_nmi_handler(void *handler)
{
    void *nmih = tmp_nlm_get_boot_data(BOOT_NMI_HANDLER);
    *(int64_t *)nmih = (long)handler;
}
#endif

NMI初始化我們暫時放在kernel_init

#ifdef CONFIG_CPU_XLP
    {
        void except_vec_nmi(void);
        tmp_nlm_set_nmi_handler(except_vec_nmi);
    }
#endif

By: Keven - 點滴積累

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章