定时器裸机程序

时间:2021-02-17 23:35:58

硬件平台: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