嵌入式bootloader开发之七---裸机watchdog中断开发(Tiny 6410)
2013-11-05 21:46
489 查看
概要:
本节主要记录watchdog的复位和时钟中断配置方法。
S3C6410中和S3C2410,S3C2440中断管理方法不太一样,它有2个硬件中断控制器VIC0和VIC1来进行中断向量地址的保存和自动跳转,从一定程度上方便了开发者,但是对于我这个小白来说这无疑没什么优势,看的是2440的中断控制方法,却要在6410上使用。而且自己没有实际接触过ARM中断控制。。。
watchdog在嵌入式系统中用的比较多,主要用于防止系统跑飞,同时也可以作定时器使用。在6410中原理图如下:
PCLK是APB总线时钟,经过8-bit的预分频后,再次进行1/16,1/32,1/64或者1/128的分频后,在WTCNT中进行计时,到时后发出RESET或者INTERRUPT信号。
WTDAT在计时器中使用,当超时后自动装入WTCNT中,初始时候不能自动装入WTCNT寄存器,必须指定WTCNT的初始值.
复位信号配置比较简单,不做细述,源码如下:
但中断的配置就没那么好实现了,需要配置相应的VIC控制器,同时要对中断处理机制有着比较清晰的认识。
首先,由S3C6410开发手册中可以找到有关VIC的相关叙述,查出Watchdog对应的中断号,具体如下:
26 INT_WDT Watchdog timer interrupt VIC0
VIC0处理流程图如下图:
watchdog中断控制中用到的控制寄存器主要有:
#define VIC0_BASE 0x71200000//VIC0基址
#define VIC0VECTADDR ((volatile unsigned *)( VIC0_BASE + 0x100))//中断处理函数表地址
#define VIC0ADDRESS (*(volatile unsigned long *)0x71200F00)//正在处理的中断函数地址
#define VIC0INTENABLE (*(volatile unsigned long *)(VIC0_BASE+0x010))//中断允许
#define VIC0INTSELECT (*(volatile unsigned long *)(VIC0_BASE+0x00C))//中断选择,irq或fiq
#define VIC0INTENCLEAR (*(volatile unsigned long*)(VIC0_BASE+0x014))//中断清除
默认情况下VIC0是不启用的,若要使用必须进行相应的配置,代码如下:
配置完成后记得要清除IRQ或者FIQ标志,使得系统允许中断。代码如下:
另外中断处理中需要进行程序现场的保存和恢复,若在中断处理函数中想要使用uboot提供的函数,就必须使用堆栈,而默认情况下IRQ模式下堆栈是未设置的,所以必须使用sp进行堆栈的正确设置.代码如下:
设置完成后,配置watchdog寄存器使其允许向系统发出中断,配置代码如下:
接着初始化中断控制器,关闭所有中断,清除中断函数寄存器,并设置使用IRQ模式进行中断。
最后允许watchdog中断,并使用一个while循环等待中断的到来。
VIC配置中,设置了中断服务程序的入口地址,中断服务程序主要流程是:
1.修改pc指针
2.保存程序执行现场
3.设置中断处理函数的返回地址
4.跳转到中断处理函数中进行中断服务
5.中断处理函数完成后恢复现场
在中断处理函数中记得要清除相应的中断标志位,否则会一直调用中断。
具体代码如下:
如此,便OK了!编写对应的makefile如下:
编译并下载到开发板上运行,即可看到每个一段时间输出一行消息,说明中断已经成功。运行情况如下:
本节主要记录watchdog的复位和时钟中断配置方法。
S3C6410中和S3C2410,S3C2440中断管理方法不太一样,它有2个硬件中断控制器VIC0和VIC1来进行中断向量地址的保存和自动跳转,从一定程度上方便了开发者,但是对于我这个小白来说这无疑没什么优势,看的是2440的中断控制方法,却要在6410上使用。而且自己没有实际接触过ARM中断控制。。。
watchdog在嵌入式系统中用的比较多,主要用于防止系统跑飞,同时也可以作定时器使用。在6410中原理图如下:
PCLK是APB总线时钟,经过8-bit的预分频后,再次进行1/16,1/32,1/64或者1/128的分频后,在WTCNT中进行计时,到时后发出RESET或者INTERRUPT信号。
WTDAT在计时器中使用,当超时后自动装入WTCNT中,初始时候不能自动装入WTCNT寄存器,必须指定WTCNT的初始值.
复位信号配置比较简单,不做细述,源码如下:
//watch dog #define WTCON (*(volatile unsigned long *)0x7E004000 ) #define WTDAT (*(volatile unsigned long *)0x7E004004 ) #define WTCNT (*(volatile unsigned long *)0x7E004008 ) #define WTCLRINT (*(volatile unsigned long *)0x7E00400C ) int main(void) { WTCNT = 0x8000; WTDAT = 0x8000; WTCON = 1 | (1 << 5) | (0x80 << 8) ; return 0; }
但中断的配置就没那么好实现了,需要配置相应的VIC控制器,同时要对中断处理机制有着比较清晰的认识。
首先,由S3C6410开发手册中可以找到有关VIC的相关叙述,查出Watchdog对应的中断号,具体如下:
26 INT_WDT Watchdog timer interrupt VIC0
VIC0处理流程图如下图:
watchdog中断控制中用到的控制寄存器主要有:
#define VIC0_BASE 0x71200000//VIC0基址
#define VIC0VECTADDR ((volatile unsigned *)( VIC0_BASE + 0x100))//中断处理函数表地址
#define VIC0ADDRESS (*(volatile unsigned long *)0x71200F00)//正在处理的中断函数地址
#define VIC0INTENABLE (*(volatile unsigned long *)(VIC0_BASE+0x010))//中断允许
#define VIC0INTSELECT (*(volatile unsigned long *)(VIC0_BASE+0x00C))//中断选择,irq或fiq
#define VIC0INTENCLEAR (*(volatile unsigned long*)(VIC0_BASE+0x014))//中断清除
默认情况下VIC0是不启用的,若要使用必须进行相应的配置,代码如下:
" mrc p15,0,r0,c1,c0,0 \n" " orr r0,r0,#(1<<24)\n" " mcr p15,0,r0,c1,c0,0\n" //使能vic0
配置完成后记得要清除IRQ或者FIQ标志,使得系统允许中断。代码如下:
" mrs r0,cpsr \n" " bic r0,r0,#0x80\n" " msr cpsr_c ,r0\n"//open the I-bit
另外中断处理中需要进行程序现场的保存和恢复,若在中断处理函数中想要使用uboot提供的函数,就必须使用堆栈,而默认情况下IRQ模式下堆栈是未设置的,所以必须使用sp进行堆栈的正确设置.代码如下:
" bic r0,r0,#0x1F\n" " orr r1,r0,#0x12\n" " msr cpsr,r1\n "//switch to IRQ Mode " ldr sp,=0x52000000\n"//set sp in IRQ Mode
设置完成后,配置watchdog寄存器使其允许向系统发出中断,配置代码如下:
WTCNT = 0x8000; WTDAT = 0x8000; WTCON = 0;//关闭watchdog reset WTCON = (1 << 5) | (0x80 << 8) | (1 << 2);//set watchdog can interrupt and disable the reset function
接着初始化中断控制器,关闭所有中断,清除中断函数寄存器,并设置使用IRQ模式进行中断。
//interrupt init VIC0INTENCLEAR = 0xFFFFFFFF;//close the interrupt VIC0INTSELECT = 0 ;//使用IRQ中断 VIC0ADDRESS = 0;//initialize the VIC0 ISR address VIC0VECTADDR[INT_WDT] = irq_handler;//设置中断处理函数地址
最后允许watchdog中断,并使用一个while循环等待中断的到来。
VIC配置中,设置了中断服务程序的入口地址,中断服务程序主要流程是:
1.修改pc指针
2.保存程序执行现场
3.设置中断处理函数的返回地址
4.跳转到中断处理函数中进行中断服务
5.中断处理函数完成后恢复现场
在中断处理函数中记得要清除相应的中断标志位,否则会一直调用中断。
具体代码如下:
//ISR Entry void irq_handler(void) { __asm__ volatile ( " sub lr,lr,#4\n"//修改返回地址 " stmfd sp,{r0-r14}\n"//保存程序执行现场 " sub sp,sp,#60\n"//修改sp指针,若直接使用stmfd sp!,{r0-r14}会提示warning " mov lr,pc\n"//设置中断处理程序的返回地址 " ldr pc,=do_irq\n"//调用中断处理函数do_irq " ldmfd sp,{r0-r13,pc}^\n"//中断处理完毕,恢复程序执行现场 ); } //interrupt handling function void do_irq(void) { show("watchdog irq.%d\n",cnt++);//打印中断 WTCLRINT &= 0x1;//清除watchdog中断 VIC0ADDRESS = 0;//清除中断处理程序中断 }
如此,便OK了!编写对应的makefile如下:
CC = arm-linux-gcc LD = arm-linux-ld OBJDUMP = arm-linux-objdump OBJCOPY = arm-linux-objcopy SRC = main.c OBJ = main.o main.bin : main $(OBJCOPY) -O binary -I elf32-littlearm main main.bin cp main.bin /var/lib/tftpboot main : $(OBJ) $(LD) -o main -Ttext=0x50000000 $(OBJ) $(OBJ): $(CC) -c $(SRC) -o $(OBJ) clean : rm $(OBJ) main.bin main
编译并下载到开发板上运行,即可看到每个一段时间输出一行消息,说明中断已经成功。运行情况如下:
相关文章推荐
- 面向对象语言三大特征
- NetBeans更改默认JDK路径
- 2013.11.05
- VC++连接SQL Server2005 数据库
- Android之Inflate()方法用途+setContentView和inflate区别
- MongoDB 单机
- linux 下6款 git 图形客户端
- Git图形用户工具介绍及比较
- linux cat命令
- 开源镜像站
- SpringMVC和Struts的区别
- svn - 冲突及解决方案
- ios 证书相关
- Android终端配置isatap隧道使用IPV6的方法
- 连续整数和问题
- 三元顺序表基本加法以及减法
- linux下core文件调试方法
- UML
- JavaScript-1
- C++设计模式之六--Facade门面模式