经过前几个实验的基础,做这个实验就轻松多了。
本实验的功能是:通过timer0每0.5s产生一个中断,在中断服务程序里改变LED的状态。
实验源程序:
启动程序:
.text
.global _start
_start:
b Reset
HandleUndef:
b HandleUndef @未定义指令终止模式
HandleSWI:
b HandleSWI @管理模式
HandlePrefetchAbort:
b HandlePrefetchAbort @指令预取终止模式
HandleDataAbort:
b HandleDataAbort @数据预取终止模式
HandleNotUsed:
b HandleNotUsed @保留
b HandleIRQ @中断
HandleFIQ:
b HandleFIQ @快速中断
Reset:
ldr sp,=1024*4 @设置堆栈
bl watch_dog @关闭看门狗
bl clock_init @时钟初始化
bl memery_init @设置存储器
bl copy_stepping_sdram
ldr pc,=on_sdram
on_sdram:
msr cpsr_c,#0xd2 @进入中断模式
ldr sp,=4096 @设置堆栈
msr cpsr_c,#0xdf @进入系统模式
ldr sp,=0x30400000 @设置堆栈
bl led_init @IO口初始化
bl timer_init @定时器初始化
bl interrupt_init @中断初始化
msr cpsr_c,#0x5f @开启中断
ldr lr,=loop
ldr pc,=main
loop:
b loop
HandleIRQ:
sub lr,lr,#4 @计算返回地址
stmdb sp!,{r0-r12,lr}
ldr lr,=int_return
ldr pc,=timer_server
int_return:
ldmia sp!,{r0-r12,pc}^ @中断返回
初始化程序:
#include "s3c2410.h"
#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
#define STOP 0
#define START 1
#define GPB0_out (1<<(0*2))
#define GPB1_out (1<<(1*2))
void watch_dog() //关闭看门狗
{
WTCON = 0;
}
void clock_init() //时钟设置
{
MPLLCON = S3C2410_MPLL_200MHZ; //设置时钟
CLKDIVN = 0X03; //FCLK:HCLK:PCLK = 1:2:4
//改变总线模式
__asm__(
"mrc p15,0,r1,c1,c0,0\n"
"orr r0,r0,#0xc0000000\n"
"mcr p15,0,r0,c1,c0,0\n"
);
}
void memery_init() //设置存储器
{
volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
p[0] = 0x22111110;
p[1] = 0x00000700;
p[2] = 0x00000700;
p[3] = 0x00000700;
p[4] = 0x00000700;
p[5] = 0x00000700;
p[6] = 0x00000700;
p[7] = 0x00018005;
p[8] = 0x00018005;
/*
HCLK = 12MHZ
p[9] = 0x008C08A3;
HCLK = 100MHZ
REFRESH = 0X008C0000+R_CNT
R_CNT = 2^11+1-SDRAM的时钟频率*SDRAM的刷新周期(us)
p[9] = 0x008C04F4;
*/
p[9] = 0x008C04F4;
p[10] = 0x000000b1;
p[11] = 0x00000030;
p[12] = 0x00000030;
}
void copy_stepping_sdram() //拷贝代码
{
volatile unsigned long *p = (unsigned long *)SDRAM_BASE;
unsigned long *step_p=(unsigned long *)0;
while(step_p<((unsigned long *)4096))
{
*p = *step_p;
step_p ++;
p++;
}
}
void led_init()
{
GPBCON = GPB0_out | GPB1_out;
}
void timer_init()
{
TCFG0 = 99; //50mhz /100/16 = 31250hz
TCFG1 = 0x03;
TCNTB0 = 31250;
// TCON = (((1<<3) | (1<<1))& (~START));
TCON |= (1<<1); // 手动更新
TCON = 0x09; // 自动加载,清“手动更新”位,启动定时器0
//TCON = ((1<<3) | (1<<1) | START);
}
void interrupt_init()
{
INTMSK &= ~(1<<10);
}
中断服务程序:
#include "s3c2410.h"
void timer_server()
{
static unsigned char count = 0;
unsigned char int_tag = INTOFFSET;
count ++;
if(count == 4)
count = 0;
GPBDAT = (GPBDAT & 0xFC) | count;
SRCPND = 1< INTPND = 1<}
主程序:
void main()
{
while(1);
return 0;
}
makefile文件:
objs := head.o init.o main.o timer_server.o
timer.bin : $(objs)
arm-linux-ld -Ttext 0x30000000 -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 -Wall -c -O2 -o $@ $<
%.o:%.S
arm-linux-gcc -Wall -c -O2 -o $@ $<
clean:
rm -f *.o timer_elf timer.dis timer.bin
阅读(2664) | 评论(5) | 转发(0) |