Chinaunix首页 | 论坛 | 博客
  • 博客访问: 139375
  • 博文数量: 49
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 515
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-08 10:33
文章分类

全部博文(49)

文章存档

2010年(2)

2009年(30)

2008年(17)

我的朋友

分类:

2009-01-05 20:31:49

经过前几个实验的基础,做这个实验就轻松多了。
本实验的功能是:通过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
 
阅读(1159) | 评论(5) | 转发(0) |
给主人留下些什么吧!~~