/*
名称:S3C2440定时器
说明:对于S3C2440来说,其定时器的部件完全一样,共有5个16位定时器。和STM32比较,那就显得较少了(STM32细算起来有10个定时器呢)。就功能来说,S3C2440的定时器比起STM32也简单不少(STM32定时器有定时、捕获输入等等),它只有定时和PWM功能(或者还有其他的,但我现在还不清楚)。
对于具体的程序来说,采用的是韦东山老师嵌入式linux开发里timer一节的实验:定时器中断控制LED灯循环点亮和熄灭。但是做了点小改动。原实验的思路是:一上电,由硬件部分把NandFlash中的代码拷贝至内部RAM,然后在从内部RAM中把代码拷贝到外部SDRAM。通过配置MPLL来控制PCLK的时钟,进而控制定时器。但我想,这不是有点麻烦吗?直接配置MPLL控制HCLK,然后直接在内部RAM中运行程序不是一样吗(省去了初始化SDRAM和把代码拷贝至SDRAM的环节)? 经过长时间的分析代码,最终是被我弄出来了。其实改动的地方也不大,就是启动文件的一些部分。去掉了初始化SDRAM的部分和把内部SRAM代码拷贝至外部SDRAM的部分。哦,还有makefile文件,连接时的地址改为0就可以了。
*/
这是改动后的启动文件
@******************************************************************************
@ File:head.S
@ 功能:初始化,设置中断模式、管理模式的栈,设置好中断处理函数
@******************************************************************************
.extern main
.text
.global _start
_start:
@******************************************************************************
@ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
@******************************************************************************
b Reset
@ 0x04: 未定义指令中止模式的向量地址
HandleUndef:
b HandleUndef
@ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
b HandleSWI
@ 0x0c: 指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
b HandlePrefetchAbort
@ 0x10: 数据访问终止导致的异常的向量地址
HandleDataAbort:
b HandleDataAbort
@ 0x14: 保留
HandleNotUsed:
b HandleNotUsed
@ 0x18: 中断模式的向量地址
b HandleIRQ
@ 0x1c: 快中断模式的向量地址
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
bl clock_init
msr cpsr_c, #0xd2 @ 进入中断模式
ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xd3 @ 进入管理模式
ldr sp, =4096 @ 设置管理模式栈指针,
@ 其实复位之后,CPU就处于管理模式,
@ 前面的“ldr sp, =4096”完成同样的功能,此句可省略
bl init_led @ 初始化LED的GPIO管脚
bl timer0_init
bl init_irq @ 调用中断初始化函数,在init.c中
msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @ 计算返回地址
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
@ 注意,此时的sp是中断模式的sp
@ 初始值是上面设置的3072
ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的返回地址
ldr pc, =Timer0_Handle @ 调用中断服务函数,在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr
这是修改后的makefile
objs := head.o init.o interrupt.o main.o
timer.bin: $(objs)
arm-linux-ld -Ttext 0x00000000 -o timer_linux $^
arm-linux-objcopy -O binary -S timer_linux $@
arm-linux-objdump -D -m arm timer_linux > timer.dis
%.o:%.c
arm-linux-gcc -Wall -O2 -c -o $@ $<
%.o:%.S
arm-linux-gcc -Wall -O2 -c -o $@ $<
clean:
rm -f timer.bin timer_linux timer.dis *.o