Chinaunix首页 | 论坛 | 博客
  • 博客访问: 260598
  • 博文数量: 128
  • 博客积分: 65
  • 博客等级: 民兵
  • 技术积分: 487
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-24 17:43
个人简介

人生境界:明智、中庸、诚信、谦逊

文章分类

全部博文(128)

文章存档

2014年(12)

2013年(116)

我的朋友

分类: 嵌入式

2013-03-04 15:48:00

原文地址:S3C2410系统时钟和定时器 作者:stuyou

主机环境:UBUNTU10.04LTS+arm-linux-gcc 2.95.3
开发板环境:EdukitIII实验箱+s3c2410子板
问题描述:首先初始化S3C2410系统时钟,然后通过定时器中断来控制LED的点亮、熄灭情况
【1.系统时钟硬件原理】
EdukitIII实验箱上一共有两个时钟,都是通过外接晶振实现,一个是实时时钟RTC,主要为系统计时使用,其晶振X101频率为32.768kHz;另一个是系统时钟,为硬件设备提供时钟信号使用,其晶振X102为12MHz,系统时钟都是在X102的基础上通过时钟寄存器的控制来生成不同的时钟信号,为不同的硬件设备提供工作时钟信号。
S3C2410的时钟控制逻辑可以外接晶振,然后通过内部的电路产生时钟源,也可以直接使用外部提供的时钟源,通过引脚设置来选择。时钟逻辑为整个系统提供3种时钟:FCLK用于CPU核;HCLK用于AHB总线上的设备,如存储控制器、中断控制器、LCD控制器、DMA、USB主机模块等;PCLK用于APB总线上的设备,如WATCHDOG、IIS、I2C、PWM定时器、MMC接口、ADC、UART、GPIO、RTC、SPI等。
开发板上的外接时钟(晶振X102为12MHz)通过相位锁相环(PLL)电路来提高频率,S3C2410有两个PLL,一个MPLL,用于设置FCLK、HCLK、PCLK;另一个为UPLL,用于USB设备。
上电时,PLL没有启动,FCLK等于外部输入时钟Fin,若要提高系统频率,通过软件来启用PLL(设置相关寄存器),图1为PLL上电后的启动过程

           图1 上电后MPLL的启动过程
图中的OSC即是外接晶振X102,频率为12MHz,上电后需要等待一段时间(Lock Time),MPLL才能输出稳定,Lock Time的值由寄存器LOCITIME设置。Lock Time之前,FCLK=Fin,Lock Time之后,MPLL输出正常,CPU工作在新的FCLK之下。
启动S3C2410的MPLL,要设置3个相关寄存器:
1.LOCITIME寄存器,用于设置Lock Time的长度,地址和各位含义如图2所示
               图2 LOCKTIME地址和各位含义
LOCKTIME[0:11]用于设置MPLL的Lock Time,LOCKTIME[12:23]用于设置UPLL的Lock Time,使用默认值0x00FFFFFF即可。
2.MPLLCON寄存器(Main PLL Control):用于设置FCLK与Fin的倍数,地址和各位含义如图3所示
             图3 MPLLCON地址和各位含义
MPLLCON[0:1]称为SDIV,MPLLCON[4:9]称为PDIV,MPLLCON[12:19]称为MDIV,FCLK的计算公式如下:
   S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)
   S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
   其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
   对于本开发板,Fin = 12MHz(晶振X102的频率)
本例要产生的FCLK为200MHz,因此MDIV=0x5C=92;PDIV=0x04=4;SDIV=0x00=0,所以m=100,p=6,s=0,把Fin=12MHz代入S3C2410的MPLL(FCLK)计算公式,可以得到FCLK=200MHz,因此该寄存器的值可以设置为((0x5c<<12)|(0x04<<4)|(0x00))。图4是一些常用的PLL值,设置MPLLCON寄存器时可以参考该表。
                图4:MPLLCON常用设置值
3.CLKDIVN寄存器,用于设置FCLK、HCLK、PCLK的比例,地址和各位含义如图5所示

              图5 CLKDIVN地址和各位含义
HDIVN1=CLKDIVN[2]=0,表示保留,HDIVN1=CLKDIVN[2]=1,表示FCLK:HCLK:PCLK=1:4:4,此时HDIVN和PDIVN均要设置为0。HDIVN=CLKDIVN[1]=0,表示HCLK=FCLK,HDIVN=CLKDIVN[1]=1,示HCLK=FCLK/2;PDIVV=CLKDIVN[0]=0,表示PCLK=HCLK,PDIVV=CLKDIVN[0]=1,表示PCLK=FCLK/2。对于本例程,要求FCLK:HCLK:PCLK=1:2:4,所以CLKDIVN[0:2]=0b110=0x3。如果HDIVN=1,那么CPU要从fast bus mode转换为asynchronous bus mode,可以通过如下指令完成:

mrc p15, 0, r1, c1, c0, 0\n       /* 读出控制寄存器 */
orr r1, r1, #0xc0000000\n      /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0\n      /* 写入控制寄存器 */


【2.PWM定时器硬件原理】
S3C2410共有5个16位的定时器,其中定时器0、1、2、3具有脉宽调制PWM(Pulse Width Modulation)功能,它们都有一个输出引脚TOUTi,可以通过定时器来控制输出引脚周期性的高、低电平变化,定时器4没有输出引脚,定时器结构如图6所示


                 图6 PWM定时器结构图
PWM定时器使用的时钟是PCLK,先通过两个8位的预分频器(使用TCFG0寄存器来设置)降低频率,定时器0、1公用一个预分频器,定时器2、3、4公用第二个预分频器。预分频器的输出进入到第二级分频器,可以产生2分频、4分频、8分频、16分频或者外部时钟TCLK0/TCLK1,每个定时器的工作频率可以从这5种频率中选择(使用TCFG1寄存器来设置)。
PWM定时器工作流程如下:参考图7



                       图7 PWM定时器操作流程
(1).定时器有TCMPBn、TCNTBn寄存器,用于设置定时器n的初始比较值和初始计数值
(2).然后设置TCONn寄存器启动定时器n,
TCMPBn、TCNTBn寄存器的值分别装入TCMPn、TCNTn寄存器,TCMPn、TCNTn是定时器内部寄存器,在定时器n的工作频率下,TCNTn开始减1计数,其值可以通过读取TCNTOn得到
(3).当TCNTn的值等于TCMPn的值时,定时器n的输出TOUTn电平反转,TCNTn继续减数
(4).当TCNTn的值到达0时,输出引脚TOUTn电平再次反转(这样就实现了PWM),并触发定时器n的定时中断(如果定时中断使能)
(5).TCNTn到达0时,如果在TCON寄存器中将定时器n设为“自动加载”,则TCMPBn和TCNTBn自动重新装入TCMPn和TCNTn寄存器,下一个计数流程开始,
PWM定时器常用寄存器,以定时器0为例
1.TCFG0寄存器(TIMER CONFIGURATION),用于控制预分频器,其地址和各位含义如图8所示

                                   图8 TCFG0寄存器地址和各位含义
定时器的输入频率计算公式为:定时器工作频率=PCLK/(prescaler value+1)/(divider value)其中prescaler value的值(预分频器)通过TCFG0寄存器设置,TCFG0[0:7]设置定时器0和定时器1的prescaler value值,TCFG0[8:15]设置定时器2、3、4的prescaler value的值,该值的范围为0~255,本例程选择定时器0的该值为99,因此该寄存器的值设置为99。divider value的值(第二级分频器)为2、4、8、16,由TCFG1寄存器设置
2.TCFG1寄存器(TIMER CONFIGURATION),经预分频器得到的时钟被输入到第二级分频器,可以再次被2分频、4分频、8分频和16分频,由图6可知,定时器0、1还可以工作在外接时钟TCLK0下,定时器2、3、4还可以工作在外接时钟TCLK1下,使用TCFG1寄存器来设置这5个定时器的第二级分频器的分频数,其地址和各位含义如图9所示

                                    图9 TCFG1寄存器地址和各位含义
TCFG1[20:23]用于设置5个定时器的DMA模式,TCFG1[0:3]设置定时器0的分频数。本例程中不使用定时器的DMA模式,定时器0的第二级分频选择1/16,所以该寄存器的值为0x3
3.TCON寄存器(TIMER CONTROL),其地址和各位含义如图10所示

                         图10 TCON地址和各位含义
TCON[0]设置定时器0的开启和停止;TCON[1]设置定时器0“手动更新”,将TCMPB0/TCNTB0的值装入内部寄存器TCMP0/TCNT0中;TCON[2]设置TOUT0是否反转;TCON[3]设置自动加载。对于本例程,使用定时器0,开启定时器、手动更新、反转、自动加载。
4.TCNTB0/TCMPB0/TOUT0寄存器,TCNTB0用于保存定时器初始计数值,TCMPB0用于保存比较值,TOUT0用来观察TCNT0的数值;其地址和各位含义如图11所示

                             图11 TCNTB0/TCMPB0/TOUT0寄存器地址和各位含义
对与本例程,TCMPB0=0,TCNTB0=15625。
【3.程序实现】
该例程一共包含8个文件,描述如下:
文件名
 描述
Head.s
 ARM启动代码,设置异常向量,只实现了复位异常和普通中断异常;调用存储器设置函数、调用关闭看门狗定时器函数、调用时钟初始化函数、调用定时器初始化函数、调用LED初始化函数、调用中断初始化函数,调用把代码从Step Stone拷贝到SDRAM的拷贝函数,最后调用C语言的Main函数。
init.c
 初始化函数的实现,包括关闭看门狗函数的实现、时钟初始化函数的实现、存储器初始化函数的实现、把代码从Step Stone拷贝到SDRAM函数的实现、LED初始化函数的实现、定时器初始化函数的实现、中断初始化函数的实现
interrupt.c
 定时器中断的中断服务程序的实现,中断服务程序的功能是每次中断改变4个LED灯的状态
interrupt.h
 定时器中断的中断服务程序的头文件
s3c24xx.h
 s3c2410A的头文件,主要是相关寄存器地址的定义。
main.c
 主函数
Makefile
 Makefile文件
timer.lds
 链接脚本文件

  1. @******************************************************************************
  2. @Name: head.S
  3. @Desc: 初始化,设置中断模式、系统模式的栈,设置好中断处理函数
  4. @Parameter:
  5. @Return:
  6. @Author: yoyoba(stuyou@126.com)
  7. @Date: 2011-5-26
  8. @Modify: 2011-5-26
  9. @*******************************************************************************

  10. .extern main
  11. .text
  12. .global _start
  13. _start:
  14. @******************************************************************************
  15. @ 中断向量,本程序中,除Reset和HandleIRQ外,其它异常都没有使用
  16. @******************************************************************************
  17. b Reset

  18. @ 0x04: 未定义指令中止模式的向量地址
  19. HandleUndef:
  20. b HandleUndef

  21. @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
  22. HandleSWI:
  23. b HandleSWI

  24. @ 0x0c: 指令预取终止导致的异常的向量地址
  25. HandlePrefetchAbort:
  26. b HandlePrefetchAbort

  27. @ 0x10: 数据访问终止导致的异常的向量地址
  28. HandleDataAbort:
  29. b HandleDataAbort

  30. @ 0x14: 保留
  31. HandleNotUsed:
  32. b HandleNotUsed

  33. @ 0x18: 中断模式的向量地址
  34. b HandleIRQ

  35. @ 0x1c: 快中断模式的向量地址
  36. HandleFIQ:
  37. b HandleFIQ

  38. Reset:
  39. ldr sp, =4096 @ 设置栈指针,以下都是C函数,调用前需要设好栈
  40. bl disable_watch_dog @ 关闭WATCHDOG,否则CPU会不断重启
  41. bl clock_init @ 设置MPLL,改变FCLK、HCLK、PCLK
  42. bl memsetup @ 设置存储控制器以使用SDRAM
  43. bl copy_steppingstone_to_sdram @ 复制代码到SDRAM中
  44. ldr pc, =on_sdram @ 跳到SDRAM中继续执行
  45. on_sdram:
  46. msr cpsr_c, #0xd2 @ 进入中断模式
  47. ldr sp, =4096 @ 设置中断模式栈指针

  48. msr cpsr_c, #0xdf @ 进入系统模式
  49. ldr sp, =0x34000000 @ 设置系统模式栈指针,

  50. bl init_led @ 初始化LED的GPIO管脚
  51. bl timer0_init @ 初始化定时器0
  52. bl init_irq @ 调用中断初始化函数,在init.c中
  53. msr cpsr_c, #0x5f @ 设置I-bit=0,开IRQ中断

  54. ldr lr, =halt_loop @ 设置返回地址
  55. ldr pc, =Main @ 调用Main主函数
  56. halt_loop:
  57. b halt_loop

  58. HandleIRQ:
  59. sub lr, lr, #4 @ 计算返回地址
  60. stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
  61. @ 注意,此时的sp是中断模式的sp
  62. @ 初始值是上面设置的4096

  63. ldr lr, =int_return @ 设置调用ISR即EINT_Handle函数后的返回地址
  64. ldr pc, =Timer0_Handle @ 调用中断服务函数,在interrupt.c中
  65. int_return:
  66. ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr

  1. /******************************************************************************
  2. *Name: init.c
  3. *Desc: ARM处理器硬件初始化函数实现
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. #include "s3c24xx.h"
  11.  
  12. void disable_watch_dog(void);
  13. void clock_init(void);
  14. void memsetup(void);
  15. void copy_steppingstone_to_sdram(void);
  16. void init_led(void);
  17. void timer0_init(void);
  18. void init_irq(void);

  19. /*
  20.  * 关闭WATCHDOG,否则CPU会不断重启
  21.  */
  22. void disable_watch_dog(void)
  23. {
  24.     WTCON = 0; // 关闭WATCHDOG很简单,往这个寄存器写0即可
  25. }

  26. #define S3C2410_MPLL_200MHZ ((0x5c<<12)|(0x04<<4)|(0x00))
  27. #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
  28. /*
  29.  * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
  30.  * 有如下计算公式:
  31.  * S3C2410: MPLL(FCLK) = (m * Fin)/(p * 2^s)
  32.  * S3C2410: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
  33.  * 其中: m = MDIV + 8, p = PDIV + 2, s = SDIV
  34.  * 对于本开发板,Fin = 12MHz
  35.  * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
  36.  * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
  37.  */
  38. void clock_init(void)
  39. {
  40.     // LOCKTIME = 0x00ffffff; // 使用默认值即可
  41.     CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1

  42.     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
  43. __asm__(
  44.     "mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
  45.     "orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
  46.     "mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
  47.     );

  48.     /* 判断是S3C2410还是S3C2440
  49.     GSTATUS1寄存器为通用状态寄存器,用来描述芯片ID(标识),可以通过读取GSTATUS1寄存器
  50.     的值来确定处理器的类型:
  51.     0x32410000=S3C2410
  52.     0x32410002=S3C2410A
  53.     0x32440000=S3C2440
  54.     0x32440002=S3C2440a
  55.     EdukitIII实验箱使用的是S3C2410A芯片*/
  56.     if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
  57.     {
  58.         MPLLCON = S3C2410_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
  59.     }
  60.     else
  61.     {
  62.         MPLLCON = S3C2440_MPLL_200MHZ; /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz */
  63.     }
  64. }

  65. /*
  66.  * 设置存储控制器以使用SDRAM
  67.  */
  68. void memsetup(void)
  69. {
  70.     volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;

  71.     /* 这个函数之所以这样赋值,而不是像前面的实验(比如mmu实验)那样将配置值
  72.      * 写在数组中,是因为要生成”位置无关的代码”,使得这个函数可以在被复制到
  73.      * SDRAM之前就可以在steppingstone中运行
  74.      */
  75.     /* 存储控制器13个寄存器的值 */
  76.     p[0] = 0x22011110; //BWSCON
  77.     p[1] = 0x00000700; //BANKCON0
  78.     p[2] = 0x00000700; //BANKCON1
  79.     p[3] = 0x00000700; //BANKCON2
  80.     p[4] = 0x00000700; //BANKCON3
  81.     p[5] = 0x00000700; //BANKCON4
  82.     p[6] = 0x00000700; //BANKCON5
  83.     p[7] = 0x00018005; //BANKCON6
  84.     p[8] = 0x00018005; //BANKCON7
  85.     
  86.     /* REFRESH,
  87.      * HCLK=12MHz: 0x008C07A3,
  88.      * HCLK=100MHz: 0x008C04F4
  89.      */
  90.     p[9] = 0x008C04F4;
  91.     p[10] = 0x000000B1; //BANKSIZE
  92.     p[11] = 0x00000030; //MRSRB6
  93.     p[12] = 0x00000030; //MRSRB7
  94. }

  95. void copy_steppingstone_to_sdram(void)
  96. {
  97.     unsigned int *pdwSrc = (unsigned int *)0;
  98.     unsigned int *pdwDest = (unsigned int *)0x30000000;
  99.     
  100.     while (pdwSrc < (unsigned int *)4096)
  101.     {
  102.         *pdwDest = *pdwSrc;
  103.         pdwDest++;
  104.         pdwSrc++;
  105.     }
  106. }

  107. /*
  108.  * LED1-4对应GPF5、GPF6、GPF7、GPF8
  109.  */
  110. #define GPF5_out (1<<(5*2)) // LED1
  111. #define GPF6_out (1<<(6*2)) // LED2
  112. #define GPF7_out (1<<(7*2)) // LED3
  113. #define GPF8_out (1<<(8*2)) // LED4

  114.  
  115. void init_led(void)
  116. {
  117.     GPFCON = GPF5_out | GPF6_out | GPF7_out | GPF8_out ;
  118. }

  119. /*
  120.  * Timer input clock Frequency = PCLK / {prescaler value+1} / {divider value}
  121.  * {prescaler value} = 0~255
  122.  * {divider value} = 2, 4, 8, 16
  123.  * 本实验的Timer0的时钟频率=100MHz/(99+1)/(16)=62500Hz
  124.  * 设置Timer0 0.5秒钟触发一次中断:
  125.  */
  126. void timer0_init(void)
  127. {
  128.     TCFG0 = 99; // 预分频器0 = 99
  129.     TCFG1 = 0x03; // 选择16分频
  130.     TCNTB0 = 31250; // 0.5秒钟触发一次中断
  131.     TCON |= (1<<1); // 手动更新
  132.     TCON = 0x09; // 自动加载,清“手动更新”位,启动定时器0
  133. }

  134. /*
  135.  * 定时器0中断使能
  136.  */
  137. void init_irq(void)
  138. {
  139.     // 定时器0中断使能
  140.     INTMSK &= (~(1<<10));
  141. }

  1. /******************************************************************************
  2. *Name: interrupt.c
  3. *Desc: 定时器0的终端服务程序
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. #include "s3c24xx.h"

  11. void Timer0_Handle(void)
  12. {
  13.     /*
  14.      * 每次中断令4个LED改变状态
  15.      */
  16.     if(INTOFFSET == 10)
  17.     {
  18.         GPFDAT = ~(GPFDAT & (0xf << 5));
  19.     }
  20.     //清中断
  21.     SRCPND = 1 << INTOFFSET;
  22.     INTPND = INTPND;
  23. }

  1. /******************************************************************************
  2. *Name: interrupt.h
  3. *Desc: 中断处理函数头文件
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. void EINT_Handle();

  1. /******************************************************************************
  2. *Name: Main.c
  3. *Desc: 主函数
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. int Main(void)
  11. {
  12.     while(1);
  13.     return 0;
  14. }

  1. /******************************************************************************
  2. *Name: Makefile
  3. *Desc: 该例程的Makefile文件,使用了timer.lds链接脚本
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/

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

  11. timer.bin: $(objs)
  12.     arm-linux-ld -Ttimer.lds -o timer_elf $^
  13.     arm-linux-objcopy -O binary -S timer_elf $@
  14.     arm-linux-objdump -D -m arm timer_elf > timer.dis
  15.     
  16. %.o:%.c
  17.     arm-linux-gcc -Wall -O2 -c -o $@ $<

  18. %.o:%.S
  19.     arm-linux-gcc -Wall -O2 -c -o $@ $<

  20. clean:
  21.     rm -f timer.bin timer_elf timer.dis *.o

  1. /******************************************************************************
  2. *Name: s3c24xx.h
  3. *Desc: 本例程使用到的s3c2410外围寄存器地址定义
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. /* WOTCH DOG register */
  11. #define WTCON (*(volatile unsigned long *)0x53000000)

  12. /* SDRAM regisers */
  13. #define MEM_CTL_BASE 0x48000000
  14. #define SDRAM_BASE 0x30000000

  15. /*GPIO registers*/

  16. #define GPFCON (*(volatile unsigned long *)0x56000050)
  17. #define GPFDAT (*(volatile unsigned long *)0x56000054)
  18. #define GPFUP (*(volatile unsigned long *)0x56000058)

  19. /*interrupt registes*/
  20. #define SRCPND (*(volatile unsigned long *)0x4A000000)
  21. #define INTMOD (*(volatile unsigned long *)0x4A000004)
  22. #define INTMSK (*(volatile unsigned long *)0x4A000008)
  23. #define PRIORITY (*(volatile unsigned long *)0x4A00000c)
  24. #define INTPND (*(volatile unsigned long *)0x4A000010)
  25. #define INTOFFSET (*(volatile unsigned long *)0x4A000014)
  26. #define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
  27. #define INTSUBMSK (*(volatile unsigned long *)0x4A00001c)

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

  31. /*clock registers*/
  32. #define    LOCKTIME        (*(volatile unsigned long *)0x4c000000)
  33. #define    MPLLCON        (*(volatile unsigned long *)0x4c000004)
  34. #define    UPLLCON        (*(volatile unsigned long *)0x4c000008)
  35. #define    CLKCON        (*(volatile unsigned long *)0x4c00000c)
  36. #define    CLKSLOW        (*(volatile unsigned long *)0x4c000010)
  37. #define    CLKDIVN        (*(volatile unsigned long *)0x4c000014)


  38. /*PWM & Timer registers*/
  39. #define    TCFG0        (*(volatile unsigned long *)0x51000000)
  40. #define    TCFG1        (*(volatile unsigned long *)0x51000004)
  41. #define    TCON        (*(volatile unsigned long *)0x51000008)
  42. #define    TCNTB0        (*(volatile unsigned long *)0x5100000c)
  43. #define    TCMPB0        (*(volatile unsigned long *)0x51000010)
  44. #define    TCNTO0        (*(volatile unsigned long *)0x51000014)

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

  1. /******************************************************************************
  2. *Name: timer.lds
  3. *Desc: 链接脚本文件,该程序的运行地址为0x30000000,该地址为SDRAM的起始地址,即该程序最终是放在SDRAM中执行
  4. *Parameter:
  5. *Return:
  6. *Author: yoyoba(stuyou@126.com)
  7. *Date: 2011-5-26
  8. *Modify: 2011-5-26
  9. ********************************************************************************/
  10. SECTIONS {
  11.     . = 0x30000000;
  12.     .text : { *(.text) }
  13.     .rodata ALIGN(4) : {*(.rodata)}
  14.     .data ALIGN(4) : { *(.data) }
  15.     .bss ALIGN(4) : { *(.bss) *(COMMON) }
  16. }
使用Makefile编译,生成timer.bin可执行程序,把该程序通过实验箱配套的FLASH编程器写入到NAND FLASH中(注意:SW104短接),NAND FLASH配置文件可以使用NAND FLASH烧写VIVI的配置文件,FLASH扇区设置为1-2。烧写完成,重新启动开发板,head.s中的代码首先被运行,第一条指令为b reset,跳转到reset标号所在位置,首先调用函数对ARM所用的硬件进行初始化,初始化完成后,进入Main函数,Main函数是一个死循环,不做什么工作,这个时候如果定时器0从设定值减少到0时,就会产生定时器0中断,然后进入到定时器中断服务程序,定时器中断服务程序的功能是改变4个LED的状态,这样每次定时器0中断,LED灯的状态都会被改变一次。






阅读(606) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~