实验七--时钟

一。平台

  系统: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\n"        /* 读出控制寄存器 */ 

 43     "orr    r1, r1, #0xc0000000\n"          /* 设置为“asynchronous bus mode” */

 44     "mcr    p15, 0, r1, c1, c0, 0\n"        /* 写入控制寄存器 */

 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实验说明,否则实验不会成功。

 

你可能感兴趣的:(实验七--时钟)