zoukankan      html  css  js  c++  java
  • 实验七--时钟

    一。平台

      系统:ubuntu12.04

      开发板:jz2440

      编译器:gcc

    二。时钟系统

         后补上

    三。代码

    Makefile:

     1 objs := head.o init.o interrupt.o main.o
     2 
     3 timer.bin: $(objs)
     4     arm-linux-ld -Ttimer.lds -o timer_linux $^
     5     arm-linux-objcopy -O binary -S timer_linux $@
     6     arm-linux-objdump -D -m arm timer_linux > timer.dis
     7     
     8 %.o:%.c
     9     arm-linux-gcc -Wall -O2 -c -o $@ $<
    10 
    11 %.o:%.S
    12     arm-linux-gcc -Wall -O2 -c -o $@ $<
    13 
    14 clean:
    15     rm -f timer.bin timer_linux timer.dis *.o        
    16     

    head.S

     1 @******************************************************************************
     2 @ File:head.S
     3 @ 功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
     4 @******************************************************************************       
     5    
     6 .extern     main
     7 .text 
     8 .global _start 
     9 _start:
    10 @******************************************************************************       
    11 @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
    12 @******************************************************************************       
    13     b   Reset
    14 
    15 @ 0x04: 未定义指令中止模式的向量地址
    16 HandleUndef:
    17     b   HandleUndef 
    18  
    19 @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
    20 HandleSWI:
    21     b   HandleSWI
    22 
    23 @ 0x0c: 指令预取终止导致的异常的向量地址
    24 HandlePrefetchAbort:
    25     b   HandlePrefetchAbort
    26 
    27 @ 0x10: 数据访问终止导致的异常的向量地址
    28 HandleDataAbort:
    29     b   HandleDataAbort
    30 
    31 @ 0x14: 保留
    32 HandleNotUsed:
    33     b   HandleNotUsed
    34 
    35 @ 0x18: 中断模式的向量地址
    36     b   HandleIRQ
    37 
    38 @ 0x1c: 快中断模式的向量地址
    39 HandleFIQ:
    40     b   HandleFIQ
    41 
    42 Reset:                  
    43     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
    44     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
    45     bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK
    46     bl  memsetup            @ 设置存储控制器以使用SDRAM
    47     bl  copy_steppingstone_to_sdram     @ 复制代码到SDRAM中
    48     ldr pc, =on_sdram                   @ 跳到SDRAM中继续执行
    49 on_sdram:
    50     msr cpsr_c, #0xd2       @ 进入中断模式
    51     ldr sp, =4096           @ 设置中断模式栈指针
    52 
    53     msr cpsr_c, #0xdf       @ 进入系统模式
    54     ldr sp, =0x34000000     @ 设置系统模式栈指针,
    55 
    56     bl  init_led            @ 初始化LED的GPIO管脚
    57     bl  timer0_init         @ 初始化定时器0   
    58     bl  init_irq            @ 调用中断初始化函数,在init.c中
    59     msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断
    60     
    61     ldr lr, =halt_loop      @ 设置返回地址
    62     ldr pc, =main           @ 调用main函数
    63 halt_loop:
    64     b   halt_loop
    65 
    66 HandleIRQ:
    67     sub lr, lr, #4                  @ 计算返回地址
    68     stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器
    69                                     @ 注意,此时的sp是中断模式的sp
    70                                     @ 初始值是上面设置的4096
    71     
    72     ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  
    73     ldr pc, =Timer0_Handle          @ 调用中断服务函数,在interrupt.c中
    74 int_return:
    75     ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr
    76     

    init.c

      1 /*
      2  * init.c: 进行一些初始化
      3  */ 
      4 
      5 #include "s3c24xx.h"
      6  
      7 void disable_watch_dog(void);
      8 void clock_init(void);
      9 void memsetup(void);
     10 void copy_steppingstone_to_sdram(void);
     11 void init_led(void);
     12 void timer0_init(void);
     13 void init_irq(void);
     14 
     15 /*
     16  * 关闭WATCHDOG,否则CPU会不断重启
     17  */
     18 void disable_watch_dog(void)
     19 {
     20     WTCON = 0;  // 关闭WATCHDOG很简单,往这个寄存器写0即可
     21 }
     22 
     23 #define S3C2410_MPLL_200MHZ     ((0x5c<<12)|(0x04<<4)|(0x00))
     24 #define S3C2440_MPLL_200MHZ     ((0x5c<<12)|(0x01<<4)|(0x02))
     25 /*
     26  * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
     27  * 有如下计算公式:
     28  *  S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)
     29  *  S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
     30  *  其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
     31  * 对于本开发板,Fin = 12MHz
     32  * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
     33  * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
     34  */
     35 void clock_init(void)
     36 {
     37     // LOCKTIME = 0x00ffffff;   // 使用默认值即可
     38     CLKDIVN  = 0x03;            // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
     39 
     40     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
     41 __asm__(
     42     "mrc    p15, 0, r1, c1, c0, 0
    "        /* 读出控制寄存器 */ 
     43     "orr    r1, r1, #0xc0000000
    "          /* 设置为“asynchronous bus mode” */
     44     "mcr    p15, 0, r1, c1, c0, 0
    "        /* 写入控制寄存器 */
     45     );
     46 
     47     /* 判断是S3C2410还是S3C2440 */
     48     if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
     49     {
     50         MPLLCON = S3C2410_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
     51     }
     52     else
     53     {
     54         MPLLCON = S3C2440_MPLL_200MHZ;  /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
     55     }       
     56 }
     57 
     58 /*
     59  * 设置存储控制器以使用SDRAM
     60  */
     61 void memsetup(void)
     62 {
     63     volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
     64 
     65     /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
     66      * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
     67      * SDRAM之前就可以在steppingstone中运行
     68      */
     69     /* 存储控制器13个寄存器的值 */
     70     p[0] = 0x22011110;     //BWSCON
     71     p[1] = 0x00000700;     //BANKCON0
     72     p[2] = 0x00000700;     //BANKCON1
     73     p[3] = 0x00000700;     //BANKCON2
     74     p[4] = 0x00000700;     //BANKCON3  
     75     p[5] = 0x00000700;     //BANKCON4
     76     p[6] = 0x00000700;     //BANKCON5
     77     p[7] = 0x00018005;     //BANKCON6
     78     p[8] = 0x00018005;     //BANKCON7
     79     
     80     /* REFRESH,
     81      * HCLK=12MHz:  0x008C07A3,
     82      * HCLK=100MHz: 0x008C04F4
     83      */ 
     84     p[9]  = 0x008C04F4;
     85     p[10] = 0x000000B1;     //BANKSIZE
     86     p[11] = 0x00000030;     //MRSRB6
     87     p[12] = 0x00000030;     //MRSRB7
     88 }
     89 
     90 void copy_steppingstone_to_sdram(void)
     91 {
     92     unsigned int *pdwSrc  = (unsigned int *)0;
     93     unsigned int *pdwDest = (unsigned int *)0x30000000;
     94     
     95     while (pdwSrc < (unsigned int *)4096)
     96     {
     97         *pdwDest = *pdwSrc;
     98         pdwDest++;
     99         pdwSrc++;
    100     }
    101 }
    102 
    103 /*
    104  * LED1-4对应GPB5、GPB6、GPB7、GPB8
    105  */
    106 #define GPB5_out        (1<<(5*2))      // LED1
    107 #define GPB6_out        (1<<(6*2))      // LED2
    108 #define GPB7_out        (1<<(7*2))      // LED3
    109 #define GPB8_out        (1<<(8*2))      // LED4
    110 
    111 #define GPFCON              (*(volatile unsigned long *)0x56000050)
    112 
    113 #define    GPF4_out    (1<<(4*2))
    114 #define    GPF5_out    (1<<(5*2))
    115 #define    GPF6_out    (1<<(6*2))
    116 
    117 
    118 /*
    119  * K1-K4对应GPG11、GPG3、GPF2、GPF3
    120  */
    121 #define GPG11_eint      (2<<(11*2))     // K1,EINT19
    122 #define GPG3_eint       (2<<(3*2))      // K2,EINT11
    123 #define GPF3_eint       (2<<(3*2))      // K3,EINT3
    124 #define GPF2_eint       (2<<(2*2))      // K4,EINT2
    125  
    126 void init_led(void)
    127 {
    128     GPFCON = GPF4_out|GPF5_out|GPF6_out;        // 将LED1,2,4对应的GPF4/5/6三个引脚设为输出
    129 }
    130 
    131 /*
    132  * Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
    133  * {prescaler value} = 0~255
    134  * {divider value} = 2, 4, 8, 16
    135  * 本实验的Timer0的时钟频率=100MHz/(99+1)/(16)=62500Hz
    136  * 设置Timer0 0.5秒钟触发一次中断:
    137  */
    138 void timer0_init(void)
    139 {
    140     TCFG0  = 99;        // 预分频器0 = 99        
    141     TCFG1  = 0x03;      // 选择16分频
    142     TCNTB0 = 31250;     // 0.5秒钟触发一次中断
    143     TCON   |= (1<<1);   // 手动更新
    144     TCON   = 0x09;      // 自动加载,清“手动更新”位,启动定时器0
    145 }
    146 
    147 /*
    148  * 定时器0中断使能
    149  */ 
    150 void init_irq(void)
    151 {        
    152     // 定时器0中断使能
    153     INTMSK   &= (~(1<<10));
    154 }

    interrupt.h

    1 void EINT_Handle();

    interrupt.c

     1 #include "s3c24xx.h"
     2 
     3 void Timer0_Handle(void)
     4 {
     5     /*
     6      * 每次中断令4个LED改变状态
     7      */
     8     if(INTOFFSET == 10)
     9     {
    10         GPFDAT = ~(GPFDAT & (0x7 << 4));
    11     }
    12     //清中断
    13     SRCPND = 1 << INTOFFSET;
    14     INTPND = INTPND;     
    15 }

    链接脚本:

    1 SECTIONS {
    2     . = 0x30000000;
    3     .text          :   { *(.text) }
    4     .rodata ALIGN(4) : {*(.rodata)} 
    5     .data ALIGN(4) : { *(.data) }
    6     .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
    7 }

    main.c  和 s3c24xx.h上面都有,这里省去

    上个实验是中断,里面没有用到SDRAM,那么这个实验是否也可以呢?当然

    首先删掉timer.lds

    然后在Makefile 里面timer.lds  改为-Ttext 0x00000000

    然后head.S修改如下:

     1 @******************************************************************************
     2 @ File:head.S
     3 @ 功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
     4 @******************************************************************************       
     5    
     6 .extern     main
     7 .text 
     8 .global _start 
     9 _start:
    10 @******************************************************************************       
    11 @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
    12 @******************************************************************************       
    13     b   Reset
    14 
    15 @ 0x04: 未定义指令中止模式的向量地址
    16 HandleUndef:
    17     b   HandleUndef 
    18  
    19 @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
    20 HandleSWI:
    21     b   HandleSWI
    22 
    23 @ 0x0c: 指令预取终止导致的异常的向量地址
    24 HandlePrefetchAbort:
    25     b   HandlePrefetchAbort
    26 
    27 @ 0x10: 数据访问终止导致的异常的向量地址
    28 HandleDataAbort:
    29     b   HandleDataAbort
    30 
    31 @ 0x14: 保留
    32 HandleNotUsed:
    33     b   HandleNotUsed
    34 
    35 @ 0x18: 中断模式的向量地址
    36     b   HandleIRQ
    37 
    38 @ 0x1c: 快中断模式的向量地址
    39 HandleFIQ:
    40     b   HandleFIQ
    41 
    42 Reset:                  
    43     ldr sp, =4096           @ 设置栈指针,以下都是C函数,调用前需要设好栈
    44     bl  disable_watch_dog   @ 关闭WATCHDOG,否则CPU会不断重启
    45     bl  clock_init          @ 设置MPLL,改变FCLK、HCLK、PCLK
    46 
    47     msr cpsr_c, #0xd2       @ 进入中断模式
    48     ldr sp, =4096           @ 设置中断模式栈指针
    49 
    50     msr cpsr_c, #0xdf       @ 进入系统模式
    51     ldr sp, =0x34000000     @ 设置系统模式栈指针,
    52 
    53     bl  init_led            @ 初始化LED的GPIO管脚
    54     bl  timer0_init         @ 初始化定时器0   
    55     bl  init_irq            @ 调用中断初始化函数,在init.c中
    56     msr cpsr_c, #0x5f       @ 设置I-bit=0,开IRQ中断
    57     
    58     ldr lr, =halt_loop      @ 设置返回地址
    59     ldr pc, =main           @ 调用main函数
    60 halt_loop:
    61     b   halt_loop
    62 
    63 HandleIRQ:
    64     sub lr, lr, #4                  @ 计算返回地址
    65     stmdb   sp!,    { r0-r12,lr }   @ 保存使用到的寄存器
    66                                     @ 注意,此时的sp是中断模式的sp
    67                                     @ 初始值是上面设置的4096
    68     
    69     ldr lr, =int_return             @ 设置调用ISR即EINT_Handle函数后的返回地址  
    70     ldr pc, =Timer0_Handle          @ 调用中断服务函数,在interrupt.c中
    71 int_return:
    72     ldmia   sp!,    { r0-r12,pc }^  @ 中断返回, ^表示将spsr的值复制到cpsr
    73     

    那么就和上个实验--中断一致了。

    本实验一方面重点是时钟,另一个注意是位置无关码;

    参照SDRAM实验说明,否则实验不会成功。

  • 相关阅读:
    java基础之冒泡排序和选择排序
    从今天开始写博客、托管代码到 Github
    九度 Online Judge 之《剑指 Offer》一书相关题目解答
    Window.ShowModalDialog使用手册
    模态窗体刷新父窗体
    彻底卸载sql2008后重新安装
    servlet 学习笔记(二)
    查看本地安装的sql server是什么版本
    servlet 学习笔记(三)
    struts2 国际化
  • 原文地址:https://www.cnblogs.com/hulig7/p/4106557.html
Copyright © 2011-2022 走看看