TA的每日心情 | 无聊 2015-2-5 09:31 |
---|
签到天数: 1 天 连续签到: 1 天 [LV.1]初来乍到
|
[table=98%,#cccccc][tr][td]雁塔菜农 发表于 2006-12-26 21:36:00 [/td][/tr][tr][td][table=98%][tr][td]/*-----------------------------------------------------------------------------------------------------------
LPCARM中断喂狗正确方法及异常模拟裸奔程序详解(别名ARM疯狗)
雁塔菜农HotPower 2006.12.26 21:32 于菜地Http://HotPower.21ic.org/
------------------------------------------------------------------------------------------------------------*/
#i nclude //ARM菜鸟HotPower创建定义文件(最新为倒塌版)
/*---------------------------------------------------------------------------------
注意:(今天是菜农时代伟人的113年诞辰日,特发此帖!!!)
(姊妹篇--LPCARM主程序喂狗正确方法及异常模拟裸奔程序详解)---随后发布
菜农累了,不想多费口舌,先自己看明白吧。欢迎拍砖有利于菜农进一步改进
参见N驳"中断喂狗缺点论"http://bbs.21ic.com/club/bbs/ShowAnnounce.asp?id=2385486
LPC213XDEF.H文件请在user1/46/archives/2006/16994.html下载
可将LPC213XDEF.H拷贝到Keil\ARM\INC\PHILIPS目录下
点击下栽本裸奔程序详解完整包:uploadfile-/2006-12/1226389582.rar
----------------------------------------------------------------------------------*/
/*---------------------------------------------------------
时钟参数定义
---------------------------------------------------------*/
#define Fosc 11059200
#define Fcclk (Fosc * 4)
#define Fcco (Fcclk * 4)
#define Fpclk (Fcclk / 4) * 1
/*---------------------------------------------------------
申请系统变量
---------------------------------------------------------*/
__noinit__ volatile unsigned int PFCount;//申请掉电计数器(复位不初始化)
__noinit__ volatile unsigned int WdtCount;//申请软狗计数器(复位不初始化)
__noinit__ volatile unsigned int MainLoopAddr;//主程序循环地址寄存器(用于模拟主程序飞后的随机地址)
__noinit__ volatile unsigned int SystemRamTest;//RAM不初始化(用于判别是否是首次上电或内存完好情况)
/*---------------------------------------------------------
系统函数声明
---------------------------------------------------------*/
void SystemInit(void);//系统初始化
void VicInit(void);//向量中断初始化
void PortInit(void);//IO初始化
void Timer0Init(void);//定时器初始化
void KeyInit(void);//键盘初始化
void VicIntSetup(void);//向量中断设置
void Enable_WDT(unsigned int);//使能看门狗(并设置复位参数)
void Reset_WDT(void);//复位看门狗(首次实际是启动看门狗)
void MainLoop(void);
void __swi(0) Enable_IRQ(void);//开放向量中断总开关
void __SWI_0 (void) {
int tmp;
__asm
{
MRS tmp, SPSR
BIC tmp, tmp, #0x80
MSR SPSR_c, tmp
}
}
void __swi(1) Disable_IRQ(void);//关闭向量中断总开关
void __SWI_1 (void) {
int tmp;
__asm
{
MRS tmp, SPSR
ORR tmp, tmp, #0x80
MSR SPSR_c, tmp
}
}
void __swi(2) Enable_FIQ(void);//开放快速中断总开关
void __SWI_2 (void) {
int tmp;
__asm
{
MRS tmp, SPSR
BIC tmp, tmp, #0x40
MSR SPSR_c, tmp
}
}
void __swi(3) Disable_FIQ(void);//关闭快速中断总开关
void __SWI_3 (void) {
int tmp;
__asm
{
MRS tmp, SPSR
ORR tmp, tmp, #0x40
MSR SPSR_c, tmp
}
}
void __swi(4) Enable_VIC(void);//开放对VIC的写入保护
void __SWI_4 (void) {
VIC->rotection = 0;//开放对VIC的写入保护
}
#define Disable_VIC() VIC->rotection = 1;//关闭在用户级对VIC的一些写操作,保护在用户级VIC不被以外改写
/*----------------------------------------------------------------------
外部中断0异常处理程序(按P0.1关闭定时器0,使定时器0中断不能喂硬狗!)
----------------------------------------------------------------------*/
extern void FIQ_EINT0 (void) __irq
{
T0->TIMER_TCR &= ~0x01;//关闭定时器0(使定时器0中断不能喂狗)
VIC->SoftIntClr = (1 EXT_INT = (1 VectAddr = 0;
}
/*-----------------------------------------------------------------------------
外部中断1异常处理程序(按P0.3改写定时器0中断地址,使定时器0中断不能喂硬狗!)
------------------------------------------------------------------------------*/
void IRQ_EINT1 (void) __irq
{
VIC->VectAddrs[2] = (unsigned int)PFCount;//修改中断服务程序地址,制造中断程序飞
VIC->SoftIntClr = (1 EXT_INT = (1 VectAddr = 0;
}
/*----------------------------------------------------------------------------
外部中断2异常处理程序(按P0.7改写主循环地址,定时器0中断正常也不能喂硬狗!)
-----------------------------------------------------------------------------*/
void IRQ_EINT2 (void) __irq
{
MainLoopAddr = (unsigned int)T0->TIMER_TC;//修改主循环程序地址,制造主程序飞
VIC->SoftIntClr = (1 EXT_INT = (1 VectAddr = 0;
}
/*----------------------------------------------------------------------
定时器0中断
----------------------------------------------------------------------*/
void IRQ_Timer0 (void) __irq
{
if (WdtCount > 0) {//说明主程序在运行中,即程序正常。
WdtCount = 0;//软狗计数器复位
Reset_WDT();//复位看门狗,首次实际是启动看门狗
}
T0->TIMER_IR = 0x01;//清除中断标志,相当于VIC->IRQStatus &= ~(1 SoftIntClr = (1 VectAddr = 0x00; //通知VIC中断处理结束
}
/*----------------------------------------------------------------------
系统默认中断处理
----------------------------------------------------------------------*/
void IRQ_Default (void) __irq
{
unsigned int status;
status = VIC->IRQStatus | VIC->FIQStatus;//合并2种中断一起处理
switch(status) {
case (1 EXT_INT = (1 SoftIntClr = (1 IODIR = 0x00000000;//设置P0口为输入
P1->IODIR = 0x00000000;//设置P1口为输入
}
/*----------------------------------------------------------------------
定时器初始化函数
----------------------------------------------------------------------*/
void Timer0Init(void)
{
T0->TIMER_TC = 0; //时器设置为0
T0->TIMER_PR = 0; //时钟不分频
T0->TIMER_MCR = 0x03; //设置T0MR0匹配后复位T0TC,并产生中断标志
T0->TIMER_MR0 = Fpclk / 200; //5mS定时
T0->TIMER_TCR = 0x01; //启动定时器
T0->TIMER_IR = 0x01; //清除中断标志
}
/*----------------------------------------------------------------------
向量中断设置函数
----------------------------------------------------------------------*/
void VicIntSetup(void)
{
unsigned int i;
VIC->VectCntls[0] = VICIntSel_Enable | VICIntSel_EINT1;//设置外部中断1分配VIC最高优先级
VIC->VectAddrs[0] = (unsigned int)IRQ_EINT1;//设置中断服务程序地址
VIC->IntEnable |= (1 VectCntls[1] = VICIntSel_Enable | VICIntSel_EINT2;//设置外部中断2分配VIC次优先级
VIC->VectAddrs[1] = (unsigned int)IRQ_EINT2;//设置中断服务程序地址
VIC->IntEnable |= (1 VectCntls[2] = VICIntSel_Enable | VICIntSel_Time0;//设置定时器0中断通道分配最高优先级
VIC->VectAddrs[2] = (unsigned int)IRQ_Timer0;//设置中断服务程序地址
VIC->IntEnable |= (1 IntSelect = (1 DefVectAddr = (unsigned int)IRQ_Default;//定义除VIC->VectAddrs[0]~VIC->VectAddrs[15]外的中断函数
for (i = 0; i < 16; i ++) {
if ((VIC->VectCntls & VICIntSel_Enable) == 0) {//该中断向量未使能
VIC->VectAddrs = (unsigned int)IRQ_Default;//全部以默认中断来处理
// VIC->VectAddrs = (unsigned int)0;//全部以复位来处理
}
}
INTCON->EXT_INT = (1 |
|