S3C2440裸板程序之定时器

本实例首先启动MPLL提高系统时钟,初始化内存控制器,使SDRAM工作在新的HCLK下,然后将定时器0设为0.5秒产生一次中断,在中断程序里改变LED的状态。

 

head.S

      
.extern     main
.text 
.global _start 
_start:    
    b   Reset

@ 0x04: 
HandleUndef:
    b   HandleUndef 
 
@ 0x08: 
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   @ 关闭watch dog,否者CPU会不断重启
    bl  clock_init          @ 
    bl  memsetup            @ 
    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  init_led            @ 
    bl  timer0_init         @   
    bl  init_irq            @ 
    msr cpsr_c, #0x5f       @ 
    
    ldr lr, =halt_loop      @ 
    ldr pc, =main           @ 
halt_loop:
    b   halt_loop

HandleIRQ:
    sub lr, lr, #4                  @ 计算返回地址
    stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器
                                    @ 注意,此时的sp是中断模式的sp
                                    @ 
    
    ldr lr, =int_return             @ 设置调用ISR函数(即EINT_Handle)后的返回地址
    ldr pc, =Timer0_Handle          @ 调用定时器中断处理函数
int_return:
    ldmia   sp!,    { r0-r12,pc }^  @ 中断返回,^表示将spsr的值复制到cpsr

    

init.c

#include "s3c24xx.h"

#define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))

void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void copy_steppingstone_to_sdram(void);
void init_led(void);
void timer0_init(void);
void init_irq(void);

void disable_watch_dog(void)
{
	WTCON = 0;
}

void clock_init(void)
{
	//LOCKTIME = 0x00ffffff;/*default value*/
	CLKDIVN = 0x03; /*FCLK:HCLK:PCLK=1:2:4*/

	__asm__(
		"mrc p15, 0, r1, c1, c0, 0\n"
		"orr r1, r1, #0xc0000000\n"
		"mcr p15, 0, r1, c1, c0, 0\n"
	);

	if((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
		MPLLCON = S3C2410_MPLL_200MHZ;
	else
		MPLLCON = S3C2440_MPLL_200MHZ;
}

void memsetup(void)
{
	volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
	
	p[0] = 0x22011110;     //BWSCON
    p[1] = 0x00000700;     //BANKCON0
    p[2] = 0x00000700;     //BANKCON1
    p[3] = 0x00000700;     //BANKCON2
    p[4] = 0x00000700;     //BANKCON3  
    p[5] = 0x00000700;     //BANKCON4
    p[6] = 0x00000700;     //BANKCON5
    p[7] = 0x00018005;     //BANKCON6
    p[8] = 0x00018005;     //BANKCON7
    
    /* REFRESH,
     * HCLK=12MHz:  0x008C07A3,
     * HCLK=100MHz: 0x008C04F4
     */ 
    p[9]  = 0x008C04F4;
    p[10] = 0x000000B1;     //BANKSIZE
    p[11] = 0x00000030;     //MRSRB6
    p[12] = 0x00000030;     //MRSRB7
}

void copy_steppingstone_to_sdram(void)
{
    unsigned int *pdwSrc  = (unsigned int *)0;
    unsigned int *pdwDest = (unsigned int *)0x30000000;
    
    while (pdwSrc < (unsigned int *)4096)
    {
        *pdwDest = *pdwSrc;
        pdwDest++;
        pdwSrc++;
    }
}

#define	GPF4_out	(1<<(4*2))
#define	GPF5_out	(1<<(5*2))
#define	GPF6_out	(1<<(6*2))
void init_led(void)
{
	GPFCON = GPF4_out|GPF5_out|GPF6_out;		/*设置为输出*/
}

void timer0_init(void)
{
	TCFG0 = 99; /*Prescaler 0 = 99*/
	TCFG1 = 0x03; /*16 divide*/
	/*FCLK:HCLK:PCLK = 1:2:4, FCLK = 200Mhz*/
	/*timer 0 clk = 50Mhz/(99+1)/16 = 31500 hz*/
	TCNTB0 = 31250; /*1s occur interrupt*/
	TCON  |= 1<<1; /*update TCNTB0 & TCMPB0*/
	TCON = 0x09;/*auto reload , start for timer0*/
}

void init_irq(void)
{
	INTMSK &= (~(1<<10));
}

interrupt.c

#include "s3c24xx.h"

void Timer0_Handle(void)
{
    if(INTOFFSET == 10)
    {
        GPFDAT = ~(GPFDAT & (0x7 << 4));
    }
    SRCPND = 1 << INTOFFSET;
    INTPND = INTPND;     
}

main.c

int main(void)
{
	while(1);
	return 0;
}

s3c24xx.h 

/* WOTCH DOG register */
#define     WTCON           (*(volatile unsigned long *)0x53000000)

/* SDRAM regisers */
#define     MEM_CTL_BASE    0x48000000
#define     SDRAM_BASE      0x30000000

/* NAND Flash registers */
#define NFCONF              (*(volatile unsigned int  *)0x4e000000)
#define NFCMD               (*(volatile unsigned char *)0x4e000004)
#define NFADDR              (*(volatile unsigned char *)0x4e000008)
#define NFDATA              (*(volatile unsigned char *)0x4e00000c)
#define NFSTAT              (*(volatile unsigned char *)0x4e000010)

/*GPIO registers*/
#define GPBCON              (*(volatile unsigned long *)0x56000010)
#define GPBDAT              (*(volatile unsigned long *)0x56000014)

#define GPFCON              (*(volatile unsigned long *)0x56000050)
#define GPFDAT              (*(volatile unsigned long *)0x56000054)
#define GPFUP               (*(volatile unsigned long *)0x56000058)

#define GPGCON              (*(volatile unsigned long *)0x56000060)
#define GPGDAT              (*(volatile unsigned long *)0x56000064)
#define GPGUP               (*(volatile unsigned long *)0x56000068)

#define GPHCON              (*(volatile unsigned long *)0x56000070)
#define GPHDAT              (*(volatile unsigned long *)0x56000074)
#define GPHUP               (*(volatile unsigned long *)0x56000078)



/*UART registers*/
#define ULCON0              (*(volatile unsigned long *)0x50000000)
#define UCON0               (*(volatile unsigned long *)0x50000004)
#define UFCON0              (*(volatile unsigned long *)0x50000008)
#define UMCON0              (*(volatile unsigned long *)0x5000000c)
#define UTRSTAT0            (*(volatile unsigned long *)0x50000010)
#define UTXH0               (*(volatile unsigned char *)0x50000020)
#define URXH0               (*(volatile unsigned char *)0x50000024)
#define UBRDIV0             (*(volatile unsigned long *)0x50000028)


/*interrupt registes*/
#define SRCPND              (*(volatile unsigned long *)0x4A000000)
#define INTMOD              (*(volatile unsigned long *)0x4A000004)
#define INTMSK              (*(volatile unsigned long *)0x4A000008)
#define PRIORITY            (*(volatile unsigned long *)0x4A00000c)
#define INTPND              (*(volatile unsigned long *)0x4A000010)
#define INTOFFSET           (*(volatile unsigned long *)0x4A000014)
#define SUBSRCPND           (*(volatile unsigned long *)0x4A000018)
#define INTSUBMSK           (*(volatile unsigned long *)0x4A00001c)

/*external interrupt registers*/
#define EINTMASK            (*(volatile unsigned long *)0x560000a4)
#define EINTPEND            (*(volatile unsigned long *)0x560000a8)

/*clock registers*/
#define	LOCKTIME		(*(volatile unsigned long *)0x4c000000)
#define	MPLLCON		(*(volatile unsigned long *)0x4c000004)
#define	UPLLCON		(*(volatile unsigned long *)0x4c000008)
#define	CLKCON		(*(volatile unsigned long *)0x4c00000c)
#define	CLKSLOW		(*(volatile unsigned long *)0x4c000010)
#define	CLKDIVN		(*(volatile unsigned long *)0x4c000014)


/*PWM & Timer registers*/
#define	TCFG0		(*(volatile unsigned long *)0x51000000)
#define	TCFG1		(*(volatile unsigned long *)0x51000004)
#define	TCON		(*(volatile unsigned long *)0x51000008)
#define	TCNTB0		(*(volatile unsigned long *)0x5100000c)
#define	TCMPB0		(*(volatile unsigned long *)0x51000010)
#define	TCNTO0		(*(volatile unsigned long *)0x51000014)

#define GSTATUS1    (*(volatile unsigned long *)0x560000B0)

timer.lds

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)} 
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

Makefile

objs := head.o init.o interrupt.o main.o

timer.bin: $(objs)
	arm-linux-ld -Ttimer.lds -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		

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值