Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301629
  • 博文数量: 86
  • 博客积分: 2050
  • 博客等级: 大尉
  • 技术积分: 1215
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-29 10:29
文章分类

全部博文(86)

文章存档

2011年(2)

2010年(77)

2009年(7)

我的朋友

分类: 嵌入式

2010-01-06 16:36:36

文件: timer.rar
大小: 31KB
下载: 下载
¥¥¥¥¥¥¥  head.S  ¥¥¥¥¥¥¥¥¥¥
 
;*******************************************
; File:head.S
; 功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
;*****************************************      
           IMPORT      Main                         ;声明外部函数,后面要使用
           IMPORT      disable_watch_dog  
           IMPORT      clock_init         
           IMPORT      memsetup          
           IMPORT      init_led           
           IMPORT      timer0_init      
           IMPORT      init_irq  
           IMPORT      Timer0_Handle
     
           AREA HEAD, CODE, READONLY
           ENTRY                                    
           CODE32
        
START
;*****************************************      
; 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
;******************************************      
      b   Reset
; 0x04: 未定义指令中止模式的向量地址
HandleUndef
      b   HandleUndef
 
; 0x08: 管理模式的向量地址,通过SWI指令进入此模式
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, =0x32000000     ; 设置栈指针,以下都是C函数,调用前需要设好栈
        bl  disable_watch_dog   ; 关闭WATCHDOG,否则CPU会不断重启
                    bl  clock_init          ; 设置MPLL,改变FCLK、HCLK、PCLK
        bl  memsetup            ; 设置存储控制器以使用SDRAM
    
        msr cpsr_c, #0xd2       ; 进入中断模式
        ldr sp, =0x33000000     ; 设置中断模式栈指针
        msr cpsr_c, #0xdf       ; 进入系统模式
        ldr sp, =0x34000000     ; 设置系统模式栈指针,
        bl  init_led            ; 初始化LED的GPIO管脚
        bl  timer0_init         ; 初始化定时器0  
        bl  init_irq            ; 调用中断初始化函数,在init.c中
                  
                    msr cpsr_c, #0x5f       ; 设置I-bit=0,开IRQ中断     
       
        ldr lr, =halt_loop      ; 设置返回地址
        ldr pc, =Main           ; 调用main函数
halt_loop
        b   halt_loop
HandleIRQ
        sub lr, lr, #4                  ; 计算返回地址
        stmdb   sp!,    { r0-r12,lr }   ; 保存使用到的寄存器
                                        ; 注意,此时的sp是中断模式的sp
                                        ; 初始值是上面设置的4096
       
        ldr lr, =int_return             ; 设置调用ISR即EINT_Handle函数后的返回地址 
        ldr pc, =Timer0_Handle          ; 调用中断服务函数,在interrupt.c中
int_return
        ldmia   sp!,    { r0-r12,pc }^  ; 中断返回, ^表示将spsr的值复制到cpsr
       
        END
 
***************  init.c  ***************
/*
 * init.c: 进行一些初始化
 */
#include "s3c2440.h"
 
void disable_watch_dog(void);
void clock_init(void);
void memsetup(void);
void init_led(void);
void timer0_init(void);
void init_irq(void);
/*
 * 关闭WATCHDOG,否则CPU会不断重启
 */
void disable_watch_dog(void)
{
    WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可
}
#define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
/*
 * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
 * 有如下计算公式:
 *  S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
 *  其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
 * 对于本开发板,Fin = 12MHz
 * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
 * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
 */
void clock_init(void)
{
    // LOCKTIME = 0x00ffffff;   // 使用默认值即可
    CLKDIVN  = 0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
    /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
__asm{
       mrc    p15, 0, r1, c1, c0, 0        /* 读出控制寄存器 */
       orr    r1, r1, #0xc0000000          /* 设置为“asynchronous bus mode” */
       mcr    p15, 0, r1, c1, c0, 0        /* 写入控制寄存器 */
     }
       MPLLCON = S3C2440_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
}
/*
 * 设置存储控制器以使用SDRAM
 */
void memsetup(void)
{
    volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
    /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
     * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
     * SDRAM之前就可以在steppingstone中运行
     */
    /* 存储控制器13个寄存器的值 */
    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
}
/*
 * LED1-4对应GPB5、GPB6、GPB7、GPB8
 */
#define GPB5_out        (1<<(5*2))      // LED1
#define GPB6_out        (1<<(6*2))      // LED2
#define GPB7_out        (1<<(7*2))      // LED3
#define GPB8_out        (1<<(8*2))      // LED4
void init_led(void)
{
     GPBCON = GPB5_out | GPB6_out | GPB7_out | GPB8_out ;  //设置为输出功能
}

/*
 * Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
 * {prescaler value} = 0~255
 * {divider value} = 2, 4, 8, 16
 * 本实验的Timer0的时钟频率=100MHz/(99+1)/(16)=62500Hz
 * 设置Timer0 0.5秒钟触发一次中断:
 */
void timer0_init(void)
{
    TCFG0  = 99;        // 预分频器0 = 99       
    TCFG1  = 0x03;      // 选择16分频
    TCNTB0 = 31250;     // 0.5秒钟触发一次中断
    TCMPB0 = 0;
    TCON   |= (1<<1);   // 手动更新
    TCON   = 0x09;      // 自动加载,清“手动更新”位,启动定时器0
}
/*
 * 定时器0中断使能
 */
void init_irq(void)
{       
    // 定时器0中断使能
    INTMSK   &= (~(1<<10));
}
 
 
********  interrupt.h  ***************
 
void EINT_Handle();
 
*********** interrupt.c   ***********
 
#include "s3c2440.h"
void Timer0_Handle(void)
{
    /*
     * 每次中断令4个LED改变状态
     */
    if(INTOFFSET == 10)   //判断是否是时钟中断,时钟中断使用IRQ10
    {
        GPBDAT = ~(GPBDAT & (0xf << 5));  
    }
     //清中断
    SRCPND = 1 << INTOFFSET;
    INTPND = INTPND;    
}
 
^^^^^^^^^^^^^^  main.c   ^^^^^^^^^^^^^
 
int Main(void)
{
    while(1);    //死循环,等待时钟中断;当中断到来时跳到中断处理函数处执行
    return 0;
}
 
~~~~~~~~~~~~~~~ s3c2440.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)
 
阅读(1493) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~