bootloader---15.串口

串口时钟使用了PCLK,所以在初始化串口之前需要先将系统时钟初始化,(除非想一直使用默认时钟)。

一、代码
1. start.S 主要功能是:
     a.关闭看门狗
     b. 初始化系统时钟
     c. 设置堆栈
     d. 跳到main函数

点击(此处)折叠或打开

  1. .text
  2. .global _start
  3. _start:
  4.     /*disable watchdog*/
  5.     ldr r0, =0x53000000    
  6.     mov r1, #0x0
  7.     str r1, [r0]
  8.     
  9. #define COCKTIME    0x4C000000    
  10. #define MPLLCON        0x4C000004
  11. #define UPLLCON        0x4C000008
  12. #define CLKCON        0x4C00000C
  13. #define CLKSLOW        0x4C000010
  14. #define CLKDIVN     0x4C000014
  15. #define CAMDIVN     0x4C000018
  16.     /*FCLK:HCLK:PCLK=1:4:8*/
  17.     ldr r0, =CLKDIVN
  18.     mov r1, #0x05
  19.     str r1, [r0]

  20.     mrc p15, 0, r0, c1, c0, 0
  21.     orr r0, r0, #0xc0000000
  22.     mcr p15, 0, r0, c1, c0,0

  23.     /*MPLL=(2*m*Fin)/(P*(1<<S)), m=(MDIV+8), p=PDIV+2 s=SDIV*/
  24.     ldr r0, =MPLLCON 
  25.     ldr r1, =((0x5C<<12)|(0x01<<4)|(0x01))
  26.     str r1, [r0]
  27.     
  28.     ldr r0, =0x10000
  29. 1:
  30.     sub r0, r0, #1
  31.     bne 1b

  32.     /*UPLL=(m*Fin)/(P*(1<<S)), m=(MDIV+8), p=(PDIV+2), s=SDIV*/
  33.     ldr r0, =UPLLCON
  34.     ldr r1, =((0x10<<12)|(0x01<<4)|(0x01))
  35.     str r1, [r0]

  36.     ldr r0, =0x10000
  37. 1:
  38.     sub r0, r0, #1
  39.     bne 1b

  40.     /* set up the stack    */
  41.     ldr sp, =1024*4
  42.     bl main

  43. loop:
  44.     b loop
2. main.c 主要功能是:
a. 初始化串口
b. 进入死循环,每次点亮一个led灯,顺便打印一个字母'a'

点击(此处)折叠或打开

  1. #include "uart.h"
  2. #define GPBCON (*(volatile unsigned int *) 0x56000010)
  3. #define GPBDAT (*(volatile unsigned int *) 0x56000014)

  4. static inline void delay (unsigned long loops)
  5. {
  6.     __asm__ volatile ("1:\n"
  7.             "subs %0, %1, #1\n"
  8.             "bne 1b":"=r" (loops):"0" (loops));
  9. }

  10. void main()
  11. {
  12.     int i = 1;
  13.     GPBCON = 0x15400;
  14.     init_uart();
  15.     while(1)
  16.     {
  17.         GPBDAT = 0x7FF&(~i<<5);
  18.         i *= 2;
  19.         if(16==i)
  20.             i = 1;
  21.         delay(400000);
  22.         putc('a');
  23.     }
  24.     return ;
  25. }
3.uart.c 主要功能:
a. 初始化串口
b. 实现发送与接收函数getc与putc

点击(此处)折叠或打开

  1. #define GPHCON (* (volatile unsigned int *) 0x56000070)
  2. #define GPHUP (* (volatile unsigned int *) 0x56000078)

  3. #define ULCON0 (* (volatile unsigned int *) 0x50000000)
  4. #define UCON0 (* (volatile unsigned int *) 0x50000004)
  5. #define UFCON0 (* (volatile unsigned int *) 0x50000008)
  6. #define UMCON0 (* (volatile unsigned int *) 0x5000000C)
  7. #define UTRSTAT0 (* (volatile unsigned int *) 0x50000010)
  8. #define UERSTAT0 (* (volatile unsigned int *) 0x50000014)
  9. #define UFSTAT0 (* (volatile unsigned int *) 0x50000018)
  10. #define UMSTAT0 (* (volatile unsigned int *) 0x5000001C)
  11. #define UTXH0 (* (volatile unsigned char *) 0x50000020)
  12. #define URXH0 (* (volatile unsigned char *) 0x50000024)
  13. #define UBRDIV0 (* (volatile unsigned int *) 0x50000028)

  14. #define BAUD_RATE 115200

  15. void uart_init(void)
  16. {
  17.     GPHCON = 0x000000A0;
  18.     GPHUP = 0x000007FF;
  19.     ULCON0 = (0x03); //8N1        
  20.     UCON0 = (0x01<<2)|(0x01);
  21.     UFCON0 = 0;
  22.     UMCON0 = 0;
  23.     UBRDIV0 = (int)((50*1000*1000)/(BAUD_RATE*16))-1;
  24. }

  25. unsigned char uart_getc(void)
  26. {
  27.     while(!(UTRSTAT0 & 0x01))
  28.         ;
  29.     return (URXH0 & 0xff);
  30. }

  31. void uart_putc(char c)
  32. {
  33.     while (!(UTRSTAT0&0x02))
  34.         ;
  35.     UTXH0 = c;
  36.     if('\n' == c)
  37.         uart_putc('\r');
  38. }

  39. void uart_puts(char *s)
  40. {
  41.     while (*s)
  42.     {
  43.         uart_putc(*s++);
  44.     }
  45. }
注: uart.c中的uart_putc函数( ascii中:  \n__换行__LF__0x10   \r__回车__CR__0x13  )
1. 当键盘敲下 Enter键时,从串口收到的按键是0x0d(即:\r 回车符:将光标移动到行首,而不换行)。
2. 当调用puts("hello\n");时putc收到\n后,将换行但光标的列不变,然后再输出\r,将光标移动到换行之后的行首,这样 效果 就跟平常的回车一样了。
4. uart.h

点击(此处)折叠或打开

  1. void uart_init(void);
  2. unsigned char uart_getc(void);
  3. void uart_putc(char c);

编译时只需要在Makefile的OBJS中添加uart.o就可以了。

二、测试一下getc函数
2.1 将main中主循环改为接收一个字符然后打印

点击(此处)折叠或打开

  1. uart_init();
  2. while(1)
  3.     {
  4.         c=uart_getc();
  5.         uart_putc(c);
  6.     }

你可能感兴趣的:(linux开发)