Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1056143
  • 博文数量: 573
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 66
  • 用 户 组: 普通用户
  • 注册时间: 2016-06-28 16:21
文章分类

全部博文(573)

文章存档

2018年(3)

2016年(48)

2015年(522)

分类: C/C++

2015-12-02 17:24:23

//本实验主要实验 看门狗定时 复位用的功能
2440init.h文件

点击(此处)折叠或打开

  1. #ifndef _2440INIT_H_
  2. #define _2440INIT_H_

  3. /* WATCHDOG寄存器 */
  4. #define WTCON (*(volatile unsigned long *)0x53000000)
  5. /* SDRAM寄存器 */
  6. #define     MEM_CTL_BASE        0x48000000


  7. /*系统时钟相关寄存器*/
  8. #define    MPLLCON        (*(volatile unsigned long *)0x4c000004)
  9. #define    CLKDIVN        (*(volatile unsigned long *)0x4c000014)
  10. #define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))


  11. /**************************************************************************/
  12. //中断相关寄存器
  13. #define EXTINT0 (*(volatile unsigned long *)0x56000088)
  14. #define EINTMASK (*(volatile unsigned long *)0x560000A4)
  15. #define EINTPEND (*(volatile unsigned long *)0x560000A8)

  16. #define SRCPND (*(volatile unsigned long *)0x4A000000)
  17. #define INTMOD (*(volatile unsigned long *)0x4A000004)
  18. #define INTMSK (*(volatile unsigned long *)0x4A000008)
  19. #define PRIORITY (*(volatile unsigned long *)0x4A00000C)
  20. #define INTPND (*(volatile unsigned long *)0x4A000010)
  21. #define INTOFFSET (*(volatile unsigned long *)0x4A000014)

  22. #define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
  23. #define INTSUBMSK (*(volatile unsigned long *)0x4A00001C)
  24. /**************************************************************************/

  25. /**************************************************************************/
  26. //看门狗相关寄存器
  27. #define WTCON (*(volatile unsigned long *)0x53000000)
  28. #define WTDAT (*(volatile unsigned long *)0x53000004)
  29. #define WTCNT (*(volatile unsigned long *)0x53000008)

  30. #define SRCPND (*(volatile unsigned long *)0x4A000000)
  31. #define INTMOD (*(volatile unsigned long *)0x4A000004)
  32. #define INTMSK (*(volatile unsigned long *)0x4A000008)
  33. #define PRIORITY (*(volatile unsigned long *)0x4A00000C)
  34. #define INTPND (*(volatile unsigned long *)0x4A000010)
  35. #define INTOFFSET (*(volatile unsigned long *)0x4A000014)

  36. #define SUBSRCPND (*(volatile unsigned long *)0x4A000018)
  37. #define INTSUBMSK (*(volatile unsigned long *)0x4A00001C)
  38. /**************************************************************************/

  39. /**************************************************************************/
  40. //按键相关的GPIO
  41. #define GPFCON (*(volatile unsigned long *)0x56000050)
  42. #define GPFDAT (*(volatile unsigned long *)0x56000054)
  43. #define GPFUP (*(volatile unsigned long *)0x56000058)
  44. /*注意:这个程序没有mmu,所以寄存器的地址是物理地址*/

  45. #define GPF0_EINT (2<<(0*2))
  46. #define GPF1_EINT (2<<(1*2))
  47. #define GPF2_EINT (2<<(2*2))
  48. #define GPF4_EINT (2<<(4*2))
  49. /**************************************************************************/

  50. /**************************************************************************/
  51. //LED相关的GPIO
  52. #define GPBDAT (*(volatile unsigned long *)0x56000014)
  53. #define GPBCON (*(volatile unsigned long *)0x56000010)
  54. #define GPBUP (*(volatile unsigned long *)0x56000018)
  55. /*注意:这个程序没有mmu,所以寄存器的地址是物理地址*/

  56. #define GPB5_OUT (1<<(5*2))
  57. #define GPB6_OUT (1<<(6*2))
  58. #define GPB7_OUT (1<<(7*2))
  59. #define GPB8_OUT (1<<(8*2))

  60. #define GPB5_ON (~(1<<5))
  61. #define GPB6_ON (~(1<<6))
  62. #define GPB7_ON (~(1<<7))
  63. #define GPB8_ON (~(1<<8))

  64. #define GPB5_OFF (1<<5)
  65. #define GPB6_OFF (1<<6)
  66. #define GPB7_OFF (1<<7)
  67. #define GPB8_OFF (1<<8)
  68. /**************************************************************************/


  69. /**************************************************************************/
  70. //串口相关寄存器
  71. #define rULCON0 (*(volatile unsigned *)0x50000000)
  72. #define rUCON0 (*(volatile unsigned *)0x50000004)
  73. #define rUFCON0 (*(volatile unsigned *)0x50000008)
  74. #define rUMCON0 (*(volatile unsigned *)0x5000000c)
  75. #define rUTRSTAT0 (*(volatile unsigned *)0x50000010)
  76. #define rUBRDIV0 (*(volatile unsigned *)0x50000028)

  77. #define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
  78. #define RdURXH0() (*(volatile unsigned char *)0x50000024)

  79. #define rGPHCON (*(volatile unsigned *)0x56000070)
  80. #define rGPHUP (*(volatile unsigned *)0x56000078)

  81. #define PCLK 50000000 // init.c中的clock_init函数设置PCLK为50MHz
  82. #define UART_CLK PCLK // UART0的时钟源设为PCLK
  83. #define UART_BAUD_RATE 115200 // 波特率
  84. #define UART_BRD ((UART_CLK / (UART_BAUD_RATE * 16)) - 1)

  85. void init_uart(void);
  86. void uart_sendByte(int data);
  87. void uart_sendString(char *p);
  88. void uart_sendByte_hex(unsigned long val);
  89. char uart_getch(void);
  90. void uart_getString(char *string);
  91. /**************************************************************************/

  92. void disable_watch_dog();
  93. void memsetup();
  94. void clock_init(void);
  95. void init_led();
  96. void init_irq();

  97. #endif
init.c文件

点击(此处)折叠或打开

  1. #include "2440init.h"

  2. /*
  3.  * 功能:初始化watchdog相关寄存器
  4.  * 注意:watchdog是内部2级中断
  5.  */
  6. void init_watchdog()
  7. {
  8.     //2级源挂起寄存器:第13位是表示看门狗中断发生的
  9.     SUBSRCPND |= (1<<13);
  10.     
  11.     //源挂起寄存器:第9位是表示看门狗中断发生的
  12.     SRCPND |= (1<<9);
  13.     INTPND |= (1<<9);
  14.     
  15.     //2级中断屏蔽寄存器:第13位是表示看门狗中断使能
  16.     INTSUBMSK &= ~(1<<13);
  17.     INTMSK &= ~(1<<9);
  18.     
  19.     /*看门狗控制寄存器 :WTCON
  20.     *[15:8]=0x60,预分频系数
  21.     *[5] 0:看门狗停止 1:看门狗启动
  22.     *[4:3]=(11)b 分频系数:0b00:16,0b01:32,0b10:64,0b11:128
  23.     *[2]=0:禁止中断,1:使能中断
  24.     *[0]=1:当定时器达到0时输出复位信号 0:当定时器达到0时不输出复位信号
  25.     *看门狗的工作频率 f_dog = PCLK/((预分频系数+1)*分频系数)
  26.     *WTCNT每减1所消耗的时间 t_dog = 1/f_dog
  27.     */
  28.     WTCON |= ((0x60 << 8) | (1<<3) | (1<<0));
  29.     WTCON &= (~(1<<2));
  30.     //上面的配置:将看门狗定时器做复位用的,需要不停的喂狗。
  31.     
  32.     /*看门狗控制数据寄存器 :WTDAT 只有16位
  33.     *决定看门狗的超时周期 即定时周期,定时时间 T = t_dog * WTDAT
  34.     *在定时器启动后,当计数器达到0时,WTDAT的值会自动赋值给WTCNT。
  35.     *但是,第一次启动看门狗时,WTDAT的值不会自动赋值给WTCNT,需要程序员自己赋值。
  36.     */
  37.     WTDAT = 0x6000;
  38.     /*看门狗控制计数寄存器 :WTCNT
  39.     *第一次启动时,程序员必须手工向这个寄存器赋值。
  40.     *之后,每次计数达到0,WTDAT的值会自动赋值给WTCNT。
  41.     *看门狗启动之后,这个寄存器就开始自动减1.
  42.     */
  43.     WTCNT = 0x6000;
  44.     
  45.     //WTCON &= ~(1<<0); //不输出复位信号
  46.     //WTCON |= (1<<2); //看门狗当做普通定时器时候,一般需要上面一行+这一行
  47.     WTCON |= (1<<5); //一般把看门狗启动单独列出来,放在初始化程序的最后
  48. }

  49. /*
  50.  * 功能:初始化按键相关的GPIO引脚为外部中断
  51.  * 本程序:
  52.  * K1 : EINT1,引脚是GPF1
  53.  * K2 : EINT4,引脚是GPF4
  54.  * K3 : EINT2,引脚是GPF2
  55.  * K4 : EINT0,引脚是GPF0
  56.  */
  57. void init_irq()
  58. {
  59.      GPFCON = (GPF0_EINT | GPF1_EINT | GPF2_EINT | GPF4_EINT); /*设置这几个引脚为中断功能*/
  60.     GPFUP = 0x00;
  61.     
  62.     EXTINT0 = 0x00; /*设置外部中断控制寄存器,低电平触发,默认也是0x00,所以这句可以不要*/
  63.         
  64.         /*设置外部中断屏蔽寄存器,EINT4~EINT24,共20个需要在这个寄存器中使能他们,
  65.          *EINTMASK只能使能EINT4, EINT0,EINT1,EINT2,EINT3 不受EINTMASK控制
  66.          *EINTMASK[4]:禁止/使能EINT4
  67.          */
  68.         EINTMASK &= (~(1<<4));
  69.         
  70.         /*设置模式寄存器 :在IRQ模式中处理,默认也是0x00,所以这句可以不要*/
  71.         INTMOD = 0x00;
  72.         
  73.         /*设置中断优先级寄存器
  74.         *仲裁租0和6,优先级不轮换使能,每个仲裁组下优先级顺序:0-1-2-3-4-5-6,默认也是这个顺序
  75.         *最终按键产生中断的优先级顺序:K4(EINT0) > K1(EINT1) > K3(EINT2) > K2(EINT4)
  76.         */
  77.         PRIORITY &= (~(1<<0)) & (~(1<<6)) ;
  78.         
  79.         /*设置中断屏蔽寄存器,一级中断
  80.         *INTMSK[0]:禁止/使能EINT0
  81.         *INTMSK[1]:禁止/使能EINT1
  82.         *INTMSK[2]:禁止/使能EINT2
  83.         *INTMSK[4]:禁止/使能EINT4~EINT7
  84.         */
  85.         INTMSK &= (~(1<<0)) & (~(1<<1)) & (~(1<<2)) & (~(1<<4)); /*其实到这里,中断仍未完全开启,CPSR的I位还要清0*/
  86. }

  87. /*
  88.  * 功能:初始化LED的GPIO引脚
  89.  */
  90. void init_led()
  91. {
  92.      GPBCON = (GPB5_OUT | GPB6_OUT | GPB7_OUT | GPB8_OUT);
  93.     GPBUP = 0x1e0;
  94.     GPBDAT = (GPB5_OFF | GPB6_OFF | GPB7_OFF | GPB8_OFF);
  95. }

  96. /*
  97.  * 对于MPLLCON寄存器,[19:12]为MDIV,[9:4]为PDIV,[1:0]为SDIV
  98.  * 有如下计算公式:
  99.  * S3C2440: MPLL(FCLK) = (2 * m * Fin)/(p * 2^s)
  100.  * 其中: m = MDIV + 8 = 92+8, p = PDIV + 2 = 1+2, s = SDIV = 2
  101.  * 对于本开发板,Fin = 12MHz
  102.  * 设置CLKDIVN,令分频比为:FCLK:HCLK:PCLK=1:2:4,
  103.  * FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
  104.  */
  105. void clock_init(void)
  106. {
  107.     // LOCKTIME = 0x00ffffff; // 使用默认值即可
  108.     CLKDIVN = 0x03; // FCLK:HCLK:PCLK=1:2:4, HDIVN=1,PDIVN=1
  109.     /* 如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode” */
  110. __asm__(
  111.     "mrc p15, 0, r1, c1, c0, 0\n" /* 读出控制寄存器 */
  112.     "orr r1, r1, #0xc0000000\n" /* 设置为“asynchronous bus mode” */
  113.     "mcr p15, 0, r1, c1, c0, 0\n" /* 写入控制寄存器 */
  114.     );

  115.     MPLLCON = S3C2440_MPLL_200MHZ;
  116.     /* 现在,FCLK=200MHz,HCLK=100MHz,PCLK=50MHz
  117.     并不保证你的任何设置都是合适的。所以,如果想要工作在200MHz,还是按照vivi的推荐值((0x5c<<12)|(0x01<<4)|(0x02))即可。
  118.     */
  119. }
  120. /*
  121.  * 关闭WATCHDOG,否则CPU会不断重启
  122.  */
  123. void disable_watch_dog(void)
  124. {
  125.     WTCON = 0; // 关闭WATCHDOG很简单,往这个寄存器写0即可
  126. }

  127. /*
  128. *功能:设置存储控制器以使用SDRAM
  129. *注意:REFRESH寄存器有特殊
  130. * 未开启PLL时:HCLK=12MHz: REFRESH寄存器值取: 0x008C07A3,
  131. * 开启PLL时:HCLK=100MHz: REFRESH寄存器值取: 0x008C04F4
  132. */
  133. void memsetup(void)
  134. {
  135.     /* SDRAM 13个寄存器的值 */
  136.     unsigned long const mem_cfg_val[]={ 0x22011110, //BWSCON
  137.                                             0x00000700, //BANKCON0
  138.                                             0x00000700, //BANKCON1
  139.                                             0x00000700, //BANKCON2
  140.                                             0x00000700, //BANKCON3
  141.                                             0x00000700, //BANKCON4
  142.                                             0x00000700, //BANKCON5
  143.                                             0x00018005, //BANKCON6
  144.                                             0x00018005, //BANKCON7
  145.                                             0x008C04F4, //REFRESH
  146.                                             0x000000B1, //BANKSIZE
  147.                                             0x00000030, //MRSRB6
  148.                                             0x00000030, //MRSRB7
  149.                                     };
  150.     int i = 0;
  151.     volatile unsigned long *p = (volatile unsigned long *)MEM_CTL_BASE;
  152.     for(; i < 13; i++)
  153.         p[i] = mem_cfg_val[i];
  154. }









  155. /***********************************************************************************/
  156. //串口相关函数
  157. /*功能:初始化串口UART0
  158. *轮询方式来使用串口
  159. */
  160. void init_uart(void)
  161. {
  162.      /*GPHCON寄存器
  163.     [7:6]=10,GPH2作为TXD0,串口发送数据引脚
  164.     [5:4]=10,GPH3作为RXD0,串口接受数据引脚
  165.     GPH2,GPH3控制串口通道0
  166.     GPH4,GPH5控制串口通道1
  167.     GPH6,GPH7控制串口通道2
  168.     */
  169.         rGPHCON = ((2<<6)|(2<<4)|(0<<2)|(0<<0));
  170.         rGPHUP = ((1<<3)|(1<<2)); /*禁止上拉*/
  171.         
  172.         /*ULCON0串口线路控制寄存器:设置传输格式
  173.         [6]=0,普通模式,非红外工作模式
  174.         [5:3]=000,无奇偶校验位,100=奇校验,101=偶校验,110=固定校验位为1,111=固定校验位为0
  175.         [2]=0,每帧1个停止位,1:每帧2个停止位
  176.         [1:0]=11,8位,每帧发送或接受的数据位的个数。00=5位,01=6位,10=7位
  177.         */
  178.         rULCON0 = 0x3;
  179.         
  180.         /*UCON0:串口控制寄存器:用于选择UART时钟源,设置UART中断方式
  181.         [15:12]:[11:10]选择PCLK时,这4位无效。选择FCLK/n时,表示n值。
  182.         [11:10]=00: 选择PCLK给UART比特率,10:PCLK, 01:UEXTCLK, 11:FCLK/n。
  183.         [9]=1: 中断请求类型
  184.         [8]=0: 中断请求类型
  185.         [7]=0: 禁止超时中断,1:使能超时中断
  186.         [6]=1: 产生接受错误状态中断,1:不产生接受错误状态中断
  187.         [5]=0: 正常操作,非回环模式。发送引脚发送的数据,直接到达接受引脚,一般是测试用。
  188.         [4]=0: 正常操作,不发送断电信号
  189.         [3:2]=01: 发送模式,中断或者轮询,如果中断寄存器不设置,就是轮询。
  190.         [1:0]=01: 接受模式,中断或者轮询
  191.         */
  192.         rUCON0 = 0x5;
  193.         
  194.         /*UFCON:串口FIFO控制寄存器:用于设置是否使用FIFO,设置各FIFO的触发阀值。
  195.         [7:6]=发送FIFO的触发深度,即在发送时,发送FIFO中还剩有多少个数据时,才触发中断,告诉CPU可以继续发送了。
  196.         [5:4]=接受FIFO的触发深度,即在接受时,接受FIFO中接受了多少个数据后,才触发中断,告诉CPU已经有接受到的数据了。
  197.         [3]=
  198.         [2]=TX的FIFO是否复位
  199.         [1]=RX的FIFO是否复位
  200.         [0]=0,不使用FIFO,非FIFO模式,相当于接受和发送时,不使用缓冲寄存器,上面的设置无效。如果这里是1,则上面的位肯定有对应的设置。
  201.         */
  202.         rUFCON0 = 0x0;
  203.         
  204.         /*UMCON:串口MODEM控制寄存器:用于流量控制
  205.         [7:5]=000,规定必须为0
  206.         [4]=0:禁止自动流控制(AFC),即不使用流控。一般不使用这种硬件自动流控制手段。
  207.         [3:1]=000:规定必须为0
  208.         [0]=0:高电平(撤销nRTS),1:低电平(激活nRTS),因为,AFC位禁止,nRTS必须由软件控制。如果AFC使能,则忽略这个位。
  209.         */
  210.         rUMCON0 = 0x0;
  211.         
  212.         /*UBRDIV:波特率分频寄存器:用于设置波特率
  213.         [15:0],波特率分频值。使用UEXTCLK作为输入时钟时,可以设置UBRDIV为0.
  214.         UBRDIV = (int)(UART时钟/(波特率*16))-1
  215.         */
  216.         rUBRDIV0 = UART_BRD;
  217. }

  218. /*功能:向串口发送一个字符
  219. *参数:待发送的字符

  220. UTRSTAT0:用来表明数据是否已经发送完毕,是否已经接受到数据
  221. 串口收发TX/RX状态寄存器,是CPU自动更新的,程序员检测它的状态就行。
  222. [2]:发送移位寄存器空标志。
  223. 检测为0:表示发送移位寄存器非空,或发送缓冲寄存器非空。
  224. 检测为1:表示发送移位寄存器为空,且发送缓冲寄存器为空,程序员可以继续发送数据了。
  225. [1]:发送缓冲区空标志位。
  226. 检测为0:表示发送缓冲寄存器非空,即上次要发送的数据还没有发完。不能太快,否则会覆盖掉。
  227. 检测为1:表示发送缓冲寄存器为空,程序员可以继续发送数据了。(非FIFO模式,非请求中断,非DMA)
  228. 注意:如果UART使用FIFO,用户应该使用UFSTAT寄存器中的Rx FIFO计数位 和 Rx FIFO满位取代对此位的检查。
  229. [0]:接收缓冲器数据就绪标志位。
  230. 检测为0:表示接收缓冲器为空。
  231. 检测为1:表示接收缓冲器接收到有效数据,程序员可以取数据了。(非FIFO模式,非请求中断,非DMA)
  232. 注意:如果UART使用FIFO,用户应该使用UFSTAT寄存器中的Rx FIFO计数位 和 Rx FIFO满位取代对此位的检查。

  233. UTXH0:串口发送缓冲寄存器
  234. [7:0]:串口要发送的数据
  235. */
  236. void uart_sendByte(int data)
  237. {
  238.     if(data == '\n')
  239.     {
  240.         while(!(rUTRSTAT0 &0x2));
  241.         WrUTXH0('\r'); /*回车不换行*/
  242.     }
  243.     /*等待,直到发送缓冲区中的数据已经全部发送出去
  244.     这里也可以检测UTRSTAT0[2]*/
  245.     while(!(rUTRSTAT0 &0x2));
  246.     /*向UTXH0寄存器中写入数据,UART即自动将它发送出去
  247.     #define rUTXH0 (*(volatile unsigned char *)0x50000020)    //UART 0 Transmission Hold
  248.     #define WrUTXH0(ch) (*(volatile unsigned char *)0x50000020)=(unsigned char)(ch)
  249.     所以:WrUTXH0(data); 相当于 rUTXH0 = data;
  250.     */
  251.     WrUTXH0(data);
  252. }

  253. /*功能:向串口打印一个字符串
  254. *参数:待打印的字符串
  255. */
  256. void uart_sendString(char *p)
  257. {
  258.     while(*p)
  259.         uart_sendByte(*p++);
  260. }

  261. /*功能:向串口打印一个字符的16进制格式
  262. *参数:待打印的字符
  263. * 数字0=0x30,数字9=0x39
  264. */
  265. void uart_sendByte_hex(unsigned long val)
  266. {
  267.     /* val = 0x1234ABCD */
  268.     unsigned char c;
  269.     int i = 0;
  270.     
  271.     uart_sendByte('0');
  272.     uart_sendByte('x');

  273.     for (i = 0; i < 8; i++)
  274.     {
  275.         c = (val >> ((7-i)*4)) & 0xf;
  276.         if((c >= 0) && (c <= 9))
  277.         {
  278.             c = '0' + c;
  279.         }
  280.         else if ((c >= 0xA) && (c <= 0xF))
  281.         {
  282.             c = 'A' + (c - 0xA);
  283.         }
  284.         uart_sendByte(c);
  285.     }
  286. }

  287. /*功能:向串口格式化打印一个字符串
  288. *参数:格式化的字符串
  289. 这个函数编译不过去,不知道什么原因?????????????
  290. void uart_printf(char* fmt,...)
  291. {
  292.     va_list args; //动态参数列表
  293.     char string[256];
  294.     
  295.     va_start(args,fmt);
  296.     vsprintf(string,fmt, args);
  297.     uart_sendString(string);
  298.     va_end(args);
  299. }
  300. */

  301. /*功能:从串口接受一个字符
  302. *返回值:接受到的字符

  303. UTRSTAT0: 串口收发TX/RX状态寄存器
  304. [0]:接收缓冲器数据就绪标志位。
  305. 0:接收缓冲器为空
  306. 1:接收缓冲器接收到有效数据(非FIFO模式,非请求中断,非DMA)
  307. 注意:如果UART使用FIFO,用户应该使用UFSTAT寄存器中的Rx FIFO计数位 和 Rx FIFO满位取代对此位的检查。

  308. URXH0:串口接受缓冲寄存器
  309. [7:0]:串口接受到的数据
  310. */
  311. char uart_getch(void)
  312. {
  313.     /*等待,直到接受缓冲区中有数据*/
  314.     while(!(rUTRSTAT0 & 0x1));
  315.     /*直接读取URXH0寄存器,即可以获得接受到的数据
  316.     #define rURXH0 (*(volatile unsigned char *)0x50000024)    //UART 0 Receive buffer
  317.     #define RdURXH0() (*(volatile unsigned char *)0x50000024)
  318.     所以:return RdURXH0(); 相当于:return rURXH0;
  319.     */
  320.     return RdURXH0();
  321. }

  322. /*功能:从串口接受一个字符串
  323. *参数:输入的字符串
  324. */
  325. void uart_getString(char *string)
  326. {
  327.     char *string2 = string;
  328.     char c;
  329.     while((c=uart_getch()) != '\r')
  330.     {
  331.         if(c == '\b')
  332.         {
  333.             if((int)string2 < (int)string)
  334.             {
  335.                 //uart_printf("\b\b");
  336.                 string--;
  337.             }
  338.         }
  339.         else
  340.         {
  341.             *string++ = c;
  342.             uart_sendByte(c);
  343.         }
  344.     }
  345.     *string = '\0';
  346.     uart_sendByte('\n');
  347. }
  348. /***********************************************************************************/
interrupt.c文件

点击(此处)折叠或打开

  1. #include "2440init.h"

  2. /*
  3. *功能:中断服务子程序
  4. *注意:1,按键产生中断的优先级顺序:K4(EINT0) > K1(EINT1) > K3(EINT2) > K2(EINT4)
  5. * 所以,同时按下其中2个,3个或者4个,只有优先级最高的哪个LED会被点亮
  6. * 2,如果硬件接线有LED连接了EINT4,EINT5,由于他们的中断优先级相同,EINTPEND[4:5]都是1,但都只会让SRCPND[4]=1,
  7. * 如果他们同时按下,则INTPND[4]=1,且INTOFFSET=4,走到case 4,EINTPEND[4:5]=11b,2个if都成立,所以,最后这2个LED会被同时点亮。
  8. */
  9. void EINT_Handle()
  10. {
  11.             /*INTOFFSET:中断偏移寄存器,INTPND寄存器中的值被置1之后,中断偏移寄存器的值=32个一级中断的编号*/
  12.             unsigned long offset = INTOFFSET;
  13.             unsigned long eintval;
  14.             
  15.             uart_sendString("\n\nINTOFFSET=");
  16.             uart_sendByte_hex(offset);
  17.             uart_sendByte('\n');
  18.             
  19.             switch(offset)
  20.             {
  21.                     /*EINT0中断:K4被按下*/
  22.                     case 0:
  23.                     {
  24.                                 uart_sendString("K4 ON!->LED4 ON!\n");
  25.                                 GPBDAT = (GPB5_OFF | GPB6_OFF | GPB7_OFF | GPB8_OFF);
  26.                                 GPBDAT = GPB8_ON; /*LED4亮*/
  27.                                 break;
  28.                     }
  29.                     /*EINT1中断:K1被按下*/
  30.                     case 1:
  31.                     {
  32.                                 uart_sendString("K1 ON!->LED1 ON!\n");
  33.                                 GPBDAT = (GPB5_OFF | GPB6_OFF | GPB7_OFF | GPB8_OFF);
  34.                                 GPBDAT = GPB5_ON; /*LED1亮*/
  35.                                 break;
  36.                     }
  37.                     /*EINT2中断:K3被按下*/
  38.                     case 2:
  39.                     {
  40.                                 uart_sendString("K3 ON!->LED3 ON!\n");
  41.                                 GPBDAT = (GPB5_OFF | GPB6_OFF | GPB7_OFF | GPB8_OFF);
  42.                                 GPBDAT = GPB7_ON; /*LED3亮*/
  43.                                 break;
  44.                     }
  45.                     /*EINT4~EINT7中断:虽然这里可以肯定是,EINT4,K2被按下,但是还是做一下判断:具体是EINT4到EINT7中的哪一个?*/
  46.                     case 4:
  47.                     {
  48.                                 GPBDAT = (GPB5_OFF | GPB6_OFF | GPB7_OFF | GPB8_OFF);
  49.                                 
  50.                                 /*EINTPEND:外部中断挂起寄存器
  51.                                 *EINTPEND低4位保留
  52.                                 *EINTPEND[4]=1 : 表示EINT4发生
  53.                                 *EINTPEND[5]=1 : 表示EINT5发生
  54.                                 */
  55.                                 eintval = EINTPEND;
  56.                                 if(eintval & (1<<4))
  57.                                 {
  58.                                         uart_sendString("K2 ON!->LED2 ON!\n");
  59.                                         GPBDAT = GPB6_ON; /*LED2亮*/
  60.                                 }
  61.                                 if(eintval & (1<<5))
  62.                                 {
  63.                                         
  64.                                 }
  65.                                 break;
  66.                     }
  67.                     default:
  68.                     {
  69.                                 break;
  70.                     }
  71.             }
  72.             /*中断处理完成之后:必须清除所有的挂起寄存器
  73.             *注意:向挂起寄存器中写1,即可令此位为0;写入0是没有效果的,若写入0,挂起寄存器中的数据保持不变。
  74.             */
  75.             if(offset == 4) /*二级外部中断,还必须清除 EINTPEND*/
  76.             {
  77.                      EINTPEND = (1<<4);
  78.             }
  79.             SRCPND = (1<<offset);
  80.             uart_sendString("SRCPND=");
  81.             uart_sendByte_hex(SRCPND);
  82.             uart_sendByte('\n');
  83.             
  84.             INTPND = (1<<offset);
  85.             uart_sendString("INTPND=");
  86.             uart_sendByte_hex(SRCPND);
  87.             uart_sendString("\n*************************************");
  88.             /*在清除 SRCPND INTPND时,INTOFFSET会被自动清除*/
  89. }
head.S文件

点击(此处)折叠或打开

  1. @********************************************************************************
  2. @功能:初始化,设置中断模式,系统模式的栈,设置中断处理函数
  3. @********************************************************************************
  4. .text
  5. .global _start
  6. _start:

  7. @设置异常向量表,本程序只使用2个异常
  8. @复位 : Reset 地址:0x00
  9.         b Reset
  10.         
  11. @未定义指令终止 : HandleUndef 地址:0x04
  12. HandleUndef:
  13.         b HandleUndef
  14.         
  15. @软件中断 : HandleSWI 地址:0x08
  16. HandleSWI:
  17.         b HandleSWI
  18.         
  19. @指令欲取指终止 : HandlePrefetchAbort 地址:0x0C
  20. HandlePrefetchAbort:
  21.         b HandlePrefetchAbort
  22.         
  23. @数据访问终止 : HandleDataAbort 地址:0x10
  24. HandleDataAbort:
  25.         b HandleDataAbort

  26. @保留 : HandleNotUsed 地址:0x14
  27. HandleNotUsed:
  28.         b HandleNotUsed
  29.         
  30. @普通中断 : HandleIRQ 地址:0x18
  31.         b HandleIRQ

  32. @快速中断 : HandleFIQ 地址:0x1C
  33. HandleFIQ:
  34.         b HandleFIQ

  35. @产生复位异常时,跳转到这里来
  36. Reset:
  37.         LDR SP, =4096                    @设置栈指针,下面调用的是c函数,调用前需要设好栈。复位时,cpu进去系统模式,所以是系统模式栈指针
  38.         BL disable_watch_dog    @关看门狗
  39.         BL memsetup                        @初始化SDRAM寄存器,这个程序在4K内跑,没有用到SDRAM,所以这里可以没有
  40.         BL clock_init                    @设置系统时钟
  41.         BL init_uart                    @初始化串口
  42.         
  43.         MSR cpsr_c, #0xD2            @进入IRQ模式,I位,F位置1:不开中断
  44.         LDR SP, =3072                    @设置IRQ模式的栈指针,sp是sp_irq
  45.         
  46.         MSR cpsr_c, #0xDF            @进入sys模式,I位,F位置1:不开中断
  47.         LDR SP, =4096                    @设置sys模式的栈指针,sp是sp_sys
  48.         
  49.         BL init_led                        @初始化LED的GPIO引脚
  50.         BL init_irq                        @初始化外部中断相关的寄存器
  51.         BL init_watchdog @初始化看门狗相关的寄存器
  52.         MSR cpsr_c, #0x5F            @设置 I位=0,F位=1:开IRQ中断,不开FIQ
  53.         LDR LR, =my_loop            @设置Reset函数的返回地址
  54.         LDR PC, =main                    @调用main函数
  55.         
  56. my_loop:
  57.         B my_loop

  58. @产生普通中断时,跳转到这里来
  59. HandleIRQ:
  60.         SUB LR, LR, #4 @计算中断处理完毕之后的返回地址
  61.         STMDB { r0-r12, LR } @保存中断程序的运行环境,即保存使用到的寄存器,sp是中断模式的栈sp_irq
  62.         
  63.         LDR LR, =int_return @设置EINT_Handle函数执行完后的返回地址
  64.         LDR PC, =EINT_Handle @调用IRQ中断服务函数
  65. int_return:
  66.         LDMIA { r0-r12, PC }^ @中断返回,^表示将SPSR的值复制到CPSR
  67.                                                                 @上面这句:将恢复中断程序的运行环境。
  68.                                                                 @进入中断模式时,CPU自动将原来的CPSR值保存到SPSR中,这里会将SPSR的值复制到CPSR,这会导致CPU切换到原来的工作模式(即调用中断前的工作模式)
main.c文件

点击(此处)折叠或打开

  1. #include "2440init.h"

  2. int main()
  3. {
  4.      //本实验主要实验 看门狗定时 复位用的功能
  5.         uart_sendString("\n main begin: \n"); //如果这一句不停的打印出现,将表示系统一直在复位。
  6.         while(1)
  7.         {
  8.             //喂狗:在WTCNT减少到0之前,即在定时时间到来之前,给下面2个寄存器赋值,否则定时时间到,系统将复位。
  9.             //WTDAT = 0x6000;
  10.             //WTCNT = 0x6000;
  11.         }
  12.         return 0;
  13. }
makefile文件

点击(此处)折叠或打开

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

  2. watchdog.bin: $(objs)
  3.     arm-linux-ld -Ttext 0x00000000 -o watchdog_elf $^
  4.     arm-linux-objcopy -O binary -S watchdog_elf $@
  5.     arm-linux-objdump -D -m arm watchdog_elf > watchdog.dis
  6.     
  7. %.o:%.c
  8.     arm-linux-gcc -Wall -O2 -c -o $@ $<

  9. %.o:%.S
  10.     arm-linux-gcc -Wall -O2 -c -o $@ $<

  11. clean:
  12.     rm -f watchdog.bin watchdog_elf watchdog.dis *.o

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