您的位置:首页 > 其它

设备驱动的艺术之旅 - Watch Dog 的 NMI 应用场景

2015-12-08 20:58 197 查看
From: 设备驱动的艺术之旅

一、硬件描述

1、器件品牌

意法半导体 – STM706T/S/R

2、硬件原理连接图



信号管教描述:

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处理简单流程



2、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_nm
i 向量表初始化在
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 - 点滴积累
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: