S3C2440定时器

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/plm199513100/article/details/79370903

/*
名称: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       

猜你喜欢

转载自blog.csdn.net/plm199513100/article/details/79370903