ARM开发步步深入之定时加速
★PLCK 先经过8位预分频器后再被分成4种频率(16/32/64/128分频)。使用看门狗定时器的一个最主要目的当然是让它给你看门了。程序正常执行时,必须 不断重新设置WTCNT寄存器使其不为0,这样可以保证系统不被重启,称为“喂狗”;程序崩溃时不能按时“喂狗”,则计数值到达0后系统重启,使得程序可 以重新正常运行。
★Watchdog存在的意义:开启Watchdog之后程序必须定时向其反馈信息,这看似麻烦又耗资源,其实是很重要的行为, 是程序向硬件传递自身运行状态的一种方法。如果程序运行良好则它应该可以在规定的时间间隔内向Watchdog反馈信息,借此来说明程序运行正常;若程序 由于某个不当的操作而进入死循环等,则无法向Watchdog反馈信息,Watchdog将发生记时超时,从而引起硬件重起。如果没有Watchdog, 程序死掉就死掉了,只能等待用户自己发现去吧。
★相关寄存器:
●WTCON寄存器:用于设置预分频系数,选择工作频率,决定是否使能中断,是否启用WATDOG功能等。
●WTDAT寄存器:用以决定Watchdog定时器的超时周期,值自动写入WTCNT。
●WTCNT寄存器:在启动WATDOG定时器前,必须往这个寄存器写入初始计数值,启动定时器后,它做减1操作,当计数器值达到0时,如果中断被使能的话,就发出中断,如果Watchdog功能被使能的话就发出复位信号,装载WTDAT寄存器的值并重新计数。
关键代码解析:
★head.S头文件来初始化,设置中断模式、系统模式的栈,设置好中断处理函数
.text
.global _start
_start:
@中断向量表处理函数,只给出复位和普通中断模式的处理函数,其它异常未使用
b Reset
......
@0x18: 中断模式的向量地址
b HandleIRQ
@0x1c: 快中断模式的向量地址
HandleFIQ:
b HandleFIQ
Reset: @复位处理
bl disable_watch_dog @关门喂狗
ldr sp,=0x4096 @clock初始化栈地址
bl clock_init @设置MPLL,改变FCLK、HCLK、PCLK
bl mem_control_setup @设置存储控制器以使用SDRAM
bl copy_steppingstone_to_sdram @复制代码到SDRAM中
ldr pc, =on_sdram @跳到SDRAM中继续执行
on_sdram:
msr cpsr_c, #0xd2 @进入中断模式
ldr sp, =0x32000000 @设置中断模式栈指针
msr cpsr_c, #0xdf @进入系统模式
ldr sp, =0x34000000 @设置系统模式栈指针
bl init_led @初始化LED
bl init_timer0 @初始化定时器0
bl enable_timer0 @使能定时器0
bl init_watchdog @初始化Watchdog
bl enable_watchdog @使能Watchdog
msr cpsr_c, #0x5f @设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @设置返回地址
ldr pc, =main @调用main函数
halt_loop:
b halt_loop
★init.c文件实现时钟、GPIO、中断及定时的初始化,主要代码:
/*
* 时钟初始化
*/
#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
void init_clock(void)
{
CLKdivN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HdivN=1,PdivN=1
/* 如果HdivN非0,CPU的总线模式应该从"fast bus mode"变为"asynchronous bus mode"*/
__asm__(
"mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
"orr r1, r1, #0xc0000000\n" /* 设置为"asynchronous bus mode" */
"mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
);
MPLLCON = S3C2410_MPLL_200MHZ; /* FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
}
/*
* 定时器0初始化
*/
void init_timer0(void)
{
TCFG0 = 99; // 预分频器0 = 99
TCFG1 = 0x03; // 选择16分频
TCNTB0 = 31250; // 0.5秒钟触发一次中断
TCON |= (1<<1); // 手动更新
TCON = 0x09; // 自动加载,清“手动更新”位,启动定时器0
}
/*
* 定时器0中断使能
*/
void enable_timer0(void)
{
INTMSK &= (~(1<<10)); // 定时器0中断使能
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于ARM体系的嵌入式系统BSP的程序设计方案(04-11)
- 在Ubuntu上建立Arm Linux 开发环境(04-23)
- 达芬奇数字媒体片上系统的架构和Linux启动过程(06-02)
- SQLite嵌入式数据库系统的研究与实现(02-20)
- 革新2410D开发板试用手记(04-21)