硬件平台:JZ2440
实现功能:以定时器来控制led闪烁
start.s --> 关闭看门狗,设置中断向量表,初始化中断定时器0
init.c --> 初始化函数
interrupt.c --> 中断服务函数
main.c --> 死循环
s3c2440.h --> 寄存器映射
start.s 源码:
.extern main timer0_interrupt .text .global _start _start: @ 异常向量表 @0x00 reset b Reset @0x04 未定义指令异常 Handle_Undef: b Handle_Undef @0x08 软件中断异常 Handle_SWI: b Handle_SWI @0x0c 预取指令异常 Handle_PrefectchAbort: b Handle_PrefectchAbort @0x10 数据访问异常 Handle_DateAbort: b Handle_DateAbort @0x14 保留异常 Handle_NotUsed: b Handle_NotUsed @0x18 外部中断请求异常 b Handle_IRQ @0x1c 快速中断请求异常 Handle_FIQ: b Handle_FIQ Reset: @复位进入超级用户模式 ldr sp,=4096 bl watchdog_init bl clock_init bl sdram_init bl copy_steppingstone_to_sdram ldr pc,=on_sdram on_sdram: msr cpsr_c,#0xd2 @进入中断模式 ldr sp,=4096 msr cpsr_c, #0xdf @ 进入系统模式 ldr sp, =0x34000000 bl led_init bl timer0_init bl interrupt_init msr cpsr_c,#0x5f @进入系统模式 ldr lr,=main_loop ldr pc,=main main_loop: b main_loop Handle_IRQ: sub lr,lr,#4 stmdb sp!,{r0-r12,lr} ldr lr,=IRQ_return ldr pc,=timer0_interrupt IRQ_return: ldmia sp!,{r0-r12,pc}^
init.c 源码:
#include"s3c2440.h" void watchdog_init(void) { WTCON=0; } void clock_init(void) { LOCKTIME=0x00ffffff; MPLLCON=((0x5c<<12)|(0x01<<4)|(0x02)); //fclk 200MHZ hclk 100MHZ pclk 50MHZ CLKDIVN=0x03; __asm__ ( "mrc p15,0,r0,c1,c0,0\n" "orr r0,r0,#0xc0000000\n" "mcr p15,0,r0.c1,c0,0\n" ); } void sdram_init(void) { unsigned long *p=(unsigned long *)0x8000000; p[0]=0x22011110; p[1]=0x00000700; p[2]=0x00000700; p[3]=0x00000700; p[4]=0x00000700; p[5]=0x00000700; p[6]=0x00000700; p[7]=0x00018005; p[8]=0x00018005; p[9]=0x008c04f4; p[10]=0x0000000b1; p[11]=0x000000030; p[12]=0x000000030; } void copy_steppingstone_to_sdram(void) { unsigned int *sour=(unsigned int *)0x00000000; unsigned int *dest=(unsigned int *)0x30000000; while(sour<(unsigned int *)4096) { *dest=*sour; dest++; sour++; } } void led_init(void) { GPFCON=(1<<8)|(1<<10)|(1<<12); } void timer0_init(void) { TCFG0=99; TCFG1=0x03; TCON=11; TCNTB0=31250; TCMPB0=0; } void interrupt_init(void) { INTMASK&=(~(1<<10)); }
interrupt.c 源码:
#include"s3c2440.h" void timer0_interrupt(void) { if(INTOFFSET==10) GPFDAT=~(GPFDAT&(0x7<<4)); SRCPND=1<<INTOFFSET; INTPND=INTPND; }
main.c 源码:
int main(void) { while(1);return 0; }
s3c2440.h 源码:
#ifndef _S3C2440_H_ #define _S3C2440_H_ //看门狗 #define WTCON (*(unsigned long *)0x53000000) //时钟 #define LOCKTIME (*(unsigned long *)0x4c000000) #define MPLLCON (*(unsigned long *)0x4c000004) #define UPLLCON (*(unsigned long *)0x4c000008) #define CLKCON (*(unsigned long *)0x4c00000c) #define CLKSLOW (*(unsigned long *)0x4c000010) #define CLKDIVN (*(unsigned long *)0x4c000014) #define CAMDIVN (*(unsigned long *)0x4c000018) //sdram #define BWSCON (*(unsigned long *)0x48000000) #define BANKCON0 (*(unsigned long *)0x48000004) #define BANKCON1 (*(unsigned long *)0x48000008) #define BANKCON2 (*(unsigned long *)0x4800000C) #define BANKCON3 (*(unsigned long *)0x48000010) #define BANKCON4 (*(unsigned long *)0x48000014) #define BANKCON5 (*(unsigned long *)0x48000018) #define BANKCON6 (*(unsigned long *)0x4800001C) #define BANKCON7 (*(unsigned long *)0x48000020) #define REFRESH (*(unsigned long *)0x48000024) #define BANKSIZE (*(unsigned long *)0x48000028) #define MRSRB6 (*(unsigned long *)0x4800002C) #define MRSRB7 (*(unsigned long *)0x48000030) //GPIO #define GPFCON (*(unsigned long *)0x56000050) #define GPFDAT (*(unsigned long *)0x56000054) //TIMER0 #define TCFG0 (*(unsigned long *)0x51000000) #define TCFG1 (*(unsigned long *)0x51000004) #define TCON (*(unsigned long *)0x51000008) #define TCNTB0 (*(unsigned long *)0x5100000c) #define TCMPB0 (*(unsigned long *)0x51000010) #define TCNTO0 (*(unsigned long *)0x51000014) //INTERRUPT #define INTMASK (*(unsigned long *)0x4a000008) #define SRCPND (*(unsigned long *)0x4a000000) #define INTPND (*(unsigned long *)0x4a000010) #define INTOFFSET (*(unsigned long *)0x4a000014) #endif
连接脚本 timer.lds:
SECTIONS { . =0x30000000; .text : {*(.text)} .rodata ALIGN(4) : {*(.rodata)} .data ALIGN(4) : {*(.data)} .bss ALIGN(4) : {*(.bss) *(COMMON)} }
Makefile:
objs:=start.o init.o main.o interrupt.o timer.bin:$(objs) arm-linux-ld -Ttimer.lds -o timer_elf $^ arm-linux-objcopy -O binary -S timer_elf $@ arm-linux-objdump -D -m arm timer_elf > timer.dis %.o:%.c arm-linux-gcc -o $@ -c $< %.o:%.s arm-linux-gcc -o $@ -c $< clean: rm -f *.o *.bin *.dis timer_elf