Chinaunix首页 | 论坛 | 博客
  • 博客访问: 302059
  • 博文数量: 63
  • 博客积分: 1482
  • 博客等级: 上尉
  • 技术积分: 1185
  • 用 户 组: 普通用户
  • 注册时间: 2011-03-12 19:06
个人简介

hello world!

文章分类

全部博文(63)

分类: LINUX

2011-03-15 23:38:26

一、s3c2440 UAR通用异步接收器知识要点

       The S3C2440A Universal Asynchronous Receiver and Transmitter (UART) 

provide three independent asynchronous serial I/O (SIO) ports, each of which 

can operate in Interrupt-based or DMA based mode. In other words, the UART can generate an interrupt or a DMA

 request to transfer data between CPU and the UART. The UART can support

 bit rates up to 115.2K bps using system clock. If an external device provides 

the UART with UEXTCLK, then the UART can operate at higher speed. Each UART

channel contains two 64byte FIFOs for receiver and transmitter. The S3C2440A 

UART includes programmable baud rates, infrared (IR) transmit/receive, one or 

two stop bit insertion, 5-bit, 6-bit, 7-bit or 8-bit data width.

Interrupt/DMA Request Generatio

        Each UART of the S3C2440A has seven status (Tx/Rx/Error) signals:

 Overrun error, Parity error, Frame error, Break, Receive buffer data ready, 

Transmit buffer empty, and Transmit shifter empty, all of which are indicated

 by the corresponding UART status register (UTRSTATn/UERSTATn). The overrun error,

 parity error, frame error and break condition are referred to as the receive error status. 

Each of which can cause the receive error status interrupt request, if the receive error

status-interrupt-enable bit is set to one in the control register, UCONn. When a receive error status interrupt_request is detected, the signal causing the request can be identified by reading

 the value of UERSTSTn.

    When the receiver transfers the data of the receive shifter to the receive FIFO register in FIFO

mode and the numberof received data reaches Rx FIFO Trigger Level, Rx interrupt is generated. 

If the Receive mode is in control register (UCONn) and is selected as 1 (Interrupt request or polling

 mode). In the Non_FIFO mode, transferring the data of the receive shifter to receive holding

register will cause Rx interrupt under the Interrupt request and polling mode.

When the transmitter transfers data from its transmit FIFO register to its transmit shifter and 

the number of data left in transmit FIFO reaches Tx FIFO Trigger Level, Tx interrupt is generated,

 if Transmit mode in control register is selected as Interrupt request or polling mode. In the Non-FIFO mode, transferring data from the transmit holding register to the transmit shifter will cause

 Tx interrupt under the Interrupt request and polling mode. If the Receive mode and Transmit

 mode in control register are selected as the DMAn request mode then DMAn request occurs .

Baud-rate Generation

        Each UART's baud_rate generator provides the serial clock for the transmitter and the receiver.

 The source clock for the baud_rate generator can be selected with the S3C2440A's internal system 

clock or UEXTCLK. In other words, dividend is selectable by setting Clock Selection of UCONn. 

The baud_rate clock is generated by dividing the source clock (PCLK, FCLK/n or UEXTCLK) by 16 and 

a 16_bit divisor specified in the UART baud_rate divisor register (UBRDIVn). The UBRDIVn can be

 determined by the following expression:

       UBRDIVn = (int)( UART clock / ( buad rate x 16) ) –1

       ( UART clock: PCLK, FCLK/n or UEXTCLK )

Where, UBRDIVn should be from 1 to (216_1), but can be set 0 (bypass mode) only using the UEXTCLK 

which should be smaller than PCLK.

For example, if the baud-rate is 115200 bps and UART clock is 40 MHz, UBRDIVn is:

        UBRDIVn = (int)(40000000 / (115200 x 16) ) -1

        = (int)(21.7) -1 [round to the nearest whole number]

        = 22 -1 = 21

       Baud-Rate Error Tolerance

UART Frame error should be less than 1.87%(3/160).

tUPCLK = (UBRDIVn + 1) x 16 x 1Frame / PCLK tUPCLK: Real UART Clock

tUEXACT = 1Frame / baud-rate tUEXACT: Ideal UART Clock

UART error = (tUPCLK – tUEXACT) / tUEXACT x 100%

NOTES

1. 1Frame = start bit + data bit + parity bit + stop bit.

2. In specific condition, we can support the UART baud rate up to 921.6K bps. 

Example, when PCLKis 60MHz, you can use 921.6K bps under UART error of 1.69%.

二、寄存器设置

ULCON0 0x50000000 R/W UART channel 0 line control register 0x00

ULCON1 0x50004000 R/W UART channel 1 line control register 0x00

 

UCON0 0x50000004 R/W UART channel 0 control register 0x00

 

UFCON0 0x50000008 R/W UART channel 0 FIFO control register 0x0

UFCON1 0x50004008 R/W UART channel 1 FIFO control register 0x0

UFCON2 0x50008008 R/W UART channel 2 FIFO control register 0x0

 

UTRSTAT0 0x50000010 R/W UART通道接收发送状态寄存器0x00

UTRSTAT1 0x50004010 R UART channel 1 Tx/Rx status register 0x6

UTRSTAT2 0x50008010 R UART channel 2 Tx/Rx status register 0x6

 

UERSTAT0 0x50000014 R/W UART通道错误状态寄存器0x00

 

UFSTAT0 0x50000018 R/W UART通道0FIFO状态寄存器0x00

UBRDIV0 0x50000028 R/W 波特率除数寄存器0 -

UBRDIV1 0x50004028 R/W 波特率除数寄存器1 -

UBRDIV2 0x50008028 R/W 波特率除数寄存器2 -

UART BAUD RATE DIVISOR REGISTERUBRDIVn

    在UART 模块中有三个UART 波特率除数寄存器UBRDIV0UBRDIV1 UBRDIV2。存储在波特率

除数寄存器UBRDIVn 中的值用于决定串行发送接收时钟率(波特率)如下:

UBRDIVn = (int) ( UART clock / ( buad rate x 16) ) –1

(UART clock: PCLK, FCLK/n or UEXTCLK)

UBRDIVn 应该从1 到(216-1),仅当使用小于PCLK 的UEXTCLK 时可以设为0。例如:如果波特率为115200bps

 且UART 时钟为40MHz,UBRDIVn 是:

UBRDIVn = (int) (40000000 / (115200 x 16) ) -1

= (int) (21.7) -1 [round to the nearest whole number]

= 22 -1 = 21

寄存器地址读写描述复位值.

三、串口通信源程序

    start.S //启动代码

  1. /*
  2. *************************************************************************
  3. *
  4. * lcl bootloader
  5. *
  6. *************************************************************************
  7. */
  8. .globl _start
  9. _start: b start_code
  10. start_code:
  11. /*
  12. * set the cpu to SVC32 mode
  13. */
  14. mrs r0, cpsr
  15. bic r0, r0, #0x1f
  16. orr r0, r0, #0xd3
  17. msr cpsr, r0
  18. bl clock_init
  19. bl cpu_init_crit
  20. bl copy_code_to_sdram
  21. /*
  22. *run in sdram
  23. */
  24. ldr sp, =0x34000000
  25. ldr lr, =halt_loop @璁剧疆杩斿洖鍦板潃
  26. ldr pc, = Main //0x30100034
  27. halt_loop:
  28. b halt_loop
  29. /*
  30. * copy code from interal 4K sdram to sdram
  31. */
  32. copy_code_to_sdram:
  33. #define SDRAM_BASE 0x30000000
  34. mov r1,#2048
  35. ldr r2,=0x30100000
  36. mov r3,#4*1024
  37. 1:
  38. ldr r4,[r1],#4
  39. str r4,[r2],#4
  40. cmp r1,r3
  41. bne 1b
  42. mov pc,lr
  43. /*
  44. *clock initialize. Mpll=405MHZ 1:4:8
  45. */
  46. clock_init:
  47. #define pWTCON 0x53000000
  48. #define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
  49. #define INTSUBMSK 0x4A00001C
  50. #define CLKDIVN 0x4C000014 /* clock divisor register */
  51. #define CLK_CTL_BASE 0x4C000000 /* clock base address */
  52. #define MDIV_405 0x7f << 12 /* MDIV 0x7f*/
  53. #define PSDIV_405 0x21 /* PDIV SDIV 0x2 0x1 */
  54. /* turn off the watchdog */
  55. ldr r0, =pWTCON
  56. mov r1, #0x0
  57. str r1, [r0]
  58. /*
  59. * mask all IRQs by setting all bits in the INTMR - default
  60. */
  61. ldr r1, =0x7fff
  62. ldr r0, =INTSUBMSK
  63. str r1, [r0]
  64. /* FCLK:HCLK:PCLK = 1:4:8 */
  65. ldr r0, =CLKDIVN
  66. mov r1, #5 //1:4:8
  67. str r1, [r0]
  68. mrc p15, 0, r1, c1, c0, 0 //切换到实时总线HCLK
  69. orr r1, r1, #0xc0000000
  70. mcr p15, 0, r1, c1, c0, 0
  71. mov r1, #CLK_CTL_BASE
  72. mov r2, #MDIV_405
  73. add r2, r2, #PSDIV_405
  74. str r2, [r1, #0x04] /* MPLLCON address Mpll=405MHZ */
  75. mov pc,lr
  76. /*
  77. *MMU and SDRAM initialize
  78. */
  79. cpu_init_crit:
  80. /*
  81. * flush v4 I/D caches
  82. */
  83. mov r0, #0
  84. mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
  85. mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
  86. /*
  87. * disable MMU stuff and caches
  88. */
  89. mrc p15, 0, r0, c1, c0, 0
  90. bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
  91. bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
  92. orr r0, r0, #0x00000002 @ set bit 2 (A) Align
  93. orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
  94. mcr p15, 0, r0, c1, c0, 0
  95. /*
  96. * before relocating, we have to setup RAM timing
  97. * because memory timing is board-dependend, you will
  98. * find a lowlevel_init.S in your board directory.
  99. */
  100. mov ip, lr
  101. bl memsetup /* memory control configuration */
  102. mov lr, ip
  103. mov pc, lr
  104. memsetup:
  105. /* memory control configuration */
  106. /* make r0 relative the current location so that it */
  107. /* reads SMRDATA out of FLASH rather than memory ! */
  108. #define MEM_CTL_BASE 0x48000000
  109. mov r1,#MEM_CTL_BASE
  110. adr r2,mem_cfg_val
  111. add r3,r1,#52
  112. 1:
  113. ldr r4, [r2], #4
  114. str r4, [r1], #4
  115. cmp r1, r3
  116. bne 1b
  117. mov pc,lr
  118. .align 4
  119. /* the literal pools origin */
  120. mem_cfg_val:
  121. .long 0x22011110
  122. .long 0x00000700
  123. .long 0x00000700
  124. .long 0x00000700
  125. .long 0x00000700
  126. .long 0x00000700
  127. .long 0x00000700 @BANK5
  128. .long 0x00018005
  129. .long 0x00018005
  130. .long 0x00ac03f4 @REFRESH // 12MHZ 0x00ac07a3
  131. .long 0x000000B1
  132. .long 0x00000030
  133. .long 0x00000030

 

def.h

  1. #ifndef __DEF_H__
  2. #define __DEF_H__

  3. #define U32 unsigned int
  4. #define U16 unsigned short
  5. #define S32 int
  6. #define S16 short int
  7. #define U8 unsigned char
  8. #define    S8 char

  9. #define __REGb(x)    (*(volatile unsigned char *)(x))
  10. #define __REGw(x)    (*(volatile unsigned short *)(x))
  11. #define __REGi(x)    (*(volatile unsigned int *)(x))

  12. #endif /*__DEF_H__*/

 

s3c2440_addr.h

  1. /***********uart address*********************/

  2. #define UART_CTL_BASE        0x50000000
  3. #define UART0_CTL_BASE        UART_CTL_BASE
  4. #define UART1_CTL_BASE        UART_CTL_BASE + 0x4000
  5. #define UART2_CTL_BASE        UART_CTL_BASE + 0x8000


  6. #define ULCON0            __REGi(UART0_CTL_BASE + 0x00)    /* R/W, UART line control register */
  7. #define UCON0            __REGi(UART0_CTL_BASE + 0x04)    /* R/W, UART control register */
  8. #define UFCON0            __REGi(UART0_CTL_BASE + 0x08)    /* R/W, UART FIFO control register */
  9. #define UMCON0            __REGi(UART0_CTL_BASE + 0x0C)    /* R/W, UART modem control register */
  10. #define UTRSTAT0        __REGi(UART0_CTL_BASE + 0x10)    /* R , UART Tx/Rx status register */
  11. #define UERSTAT0        __REGi(UART0_CTL_BASE + 0x14)    /* R , UART Rx error status register */
  12. #define UFSTAT0            __REGi(UART0_CTL_BASE + 0x18)    /* R , UART FIFO status register */
  13. #define UMSTAT0            __REGi(UART0_CTL_BASE + 0x1C)    /* R , UART Modem status register */
  14. #define UTXH0            __REGb(UART0_CTL_BASE + 0x20)    /* W 8bit , UART transmit(little-end) buffer */
  15. #define URXH0            __REGb(UART0_CTL_BASE + 0x24)    /* R 8bit , UART receive(little-end) buffer */
  16. #define UBRDIV0            __REGi(UART0_CTL_BASE + 0x28)    /* R/W, Baud rate divisor register */

  17. /* ... */
  18. #define UTRSTAT_TX_EMPTY    (1 << 2)
  19. #define UTRSTAT_RX_READY    (1 << 0)
  20. #define UART_ERR_MASK        0xF

  21. #define UART_BAUD_RATE        115200
  22. #define UART_PCLK_405_148 50625000
  23. #define UART_PCLK UART_PCLK_405_148
  24. #define UART_BRD ((UART_PCLK / (UART_BAUD_RATE * 16)) - 1)
  25.   

  26. /***********GPB GPG GPH GPIO address*********************/

  27. #define GPBCON (*(volatile unsigned long *) 0x56000010)
  28. #define GPBDAT (*(volatile unsigned long *) 0x56000014)
  29. #define GPBUP (*(volatile unsigned long *) 0x56000018)

  30. #define GPGCON (*(volatile unsigned long *) 0x56000060)
  31. #define GPGDAT (*(volatile unsigned long *) 0x56000064)
  32. #define GPGUP (*(volatile unsigned long *) 0x56000068)

  33. #define GPHCON         __REGi(0x56000070)             //R/W      Configures the pins of port H                             0x0

  34. #define GPHDAT          __REGi(0x56000074)             //R/W      The data register for port H                             Undef.

  35. #define GPHUP     __REGi(0x56000078)             //R/W      pull-up disable register for port H


  36. /* .. */    
  37. #define GPX_up              0x00000000 // up

  38. #define GPX_mask(pin) (~(3<<((pin)*2)))

  39.     
  40.     
  41. #define GPH_tx0         (2<<(2*2))                     //10 = TXD[0]

  42. #define GPH_rx0         (2<<(3*2))                     //10 = RXD[0]


  43. #define GPB5_out          (1<<(5*2))
  44. #define GPB6_out          (1<<(6*2))
  45. #define GPB7_out          (1<<(7*2))
  46. #define GPB8_out          (1<<(8*2))

  47. #define GPG0_in          (0<<(0*2))
  48. #define GPG3_in          (0<<(3*2))
  49. #define GPG5_in          (0<<(5*2))
  50. #define GPG6_in          (0<<(6*2))

  51. /*****************timer register*****************/

  52. #define TCFG0 (*(volatile unsigned long *) 0x51000000)
  53. #define TCFG1 (*(volatile unsigned long *) 0x51000004)
  54. #define TCON (*(volatile unsigned long *) 0x51000008)
  55. #define TCNTB0 (*(volatile unsigned long *) 0x5100000C)
  56. #define TCMPB0 (*(volatile unsigned long *) 0x51000010)
  57. #define TCNTO0 (*(volatile unsigned long *) 0x51000014)
  1. /* .. */
  2. #define GPB0_pwm         (2<<(0*2))

 

uart0_init.h

  1. #ifndef __UART0_INIT_H__
  2. #define __UART0_INIT_H__

  3. void uart0_init();
  4. void Uart_SendString(char *pt);

  5. #endif

uart0_init.c

  1. /*
  2.   * uart0 lib
  3.   */

  4. #include "s3c2440_addr.h"

  5. void uart0_init()
  6. {
  7.     GPHCON &= (GPX_mask(2) & GPX_mask(3));
  8.     GPHCON |= GPH_tx0 | GPH_rx0;
  9.     GPHUP |= 0x0c;

  10.     ULCON0 = (0<< 3) | (0<< 2) | (3<< 0); // 8N1 ;normal mode , no parity , 1stop bit,8bit

  11.    UCON0 = (0<<10) | (1<< 9) | (1<< 6) | (1<< 2) | (1<< 0); // Select PCLK for the UART baud rate,polling mode, [9][6]:1 1

  12.    UFCON0 = 0x00;                          // disable FIFO

  13.    UMCON0 = 0x00;                          // disable AFC


  14.     UBRDIV0 = UART_BRD;                      // baud rate divisior 115200



  15. }

  16. static inline void putc(char data)
  17. {
  18.     while (!(UTRSTAT0 & 0x4)) ;                //Wait until THR is empty.

  19.     UTXH0 = data;
  20. }

  21. static inline unsigned char getc(void)
  22. {
  23.     while (!(UTRSTAT0 & (1))) ;                //Wait until THx is empty.

  24.     return URXH0;
  25. }

  26. void Uart_SendString(char *pt)
  27. {
  28.     while (*pt)
  29.         putc(*pt++);
  30. }

main.c

 

  1. /*
  2. GPBCON 0x56000010 Port B control
  3. GPBDAT 0x56000014 Port B data
  4. GPBUP 0x56000018 Pull-up control B

  5. LED1 GPB5 LED2 GPB6 LED3 GPB7 LED4 GPB8

  6. */

  7. #include "uart0_init.h"
  8. #include "s3c2440_addr.h"


  9. void leds_init()
  10. {
  11.     GPBCON &=(GPX_mask(5) & GPX_mask(6) & GPX_mask(7) & GPX_mask(8));
  12.     GPBCON |= (GPB5_out | GPB6_out | GPB7_out | GPB8_out);
  13.     GPBUP = GPX_up;
  14. }
  15. void buttons_init()
  16. {
  17.     GPGCON &= (GPX_mask(0) & GPX_mask(3) & GPX_mask(5) & GPX_mask(6));
  18.     GPGCON |= (GPG0_in & GPG3_in & GPG5_in & GPG6_in);
  19.     GPGUP = GPX_up;
  20. }
  21.     
  22. void pwm_init()
  23. {
  24.     GPBCON &= GPX_mask(0);
  25.     GPBCON |= GPB0_pwm;
  26. }
  27. void timer0_init()
  28. {
  29.     TCFG0 = 99; //prescaler0 value = 99

  30.     TCFG1 = 0x03; // MUX 1/16

  31.     TCNTB0 = 11640; //63280

  32.     TCMPB0 = 11640/2;
  33.     TCON |= (1<<1); //update TCNTB0&TCNMB0

  34.     TCON = 0x09; // auto reload, inverter off ,clear 0 ,start for timer0

  35.     
  36. }    

  37. int Main()
  38. {
  39.     unsigned long dwDat;
  40.     leds_init();
  41.     buttons_init();
  42.     //pwm_init();

  43.     //timer0_init();

  44.     uart0_init();

  45.     while (1)
  46.     {
  47.         dwDat=GPGDAT;
  48.         if(dwDat & (1<<0))
  49.         {
  50.             GPBDAT |=(1<<5);
  51.          Uart_SendString("\r LED1 is ON. \r\n");    
  52.         }        
  53.         else    
  54.         {
  55.             GPBDAT &=~(1<<5);    
  56.             Uart_SendString("\r LED1 is OFF.\r\n");
  57.         }    

  58.         if(dwDat & (1<<3))
  59.             GPBDAT |=(1<<6);    
  60.         else
  61.             GPBDAT &=~(1<<6);    

  62.         if(dwDat & (1<<5))
  63.             GPBDAT |=(1<<7);
  64.         else
  65.             GPBDAT &=~(1<<7);    

  66.         if(dwDat & (1<<6))
  67.             GPBDAT |=(1<<8);    
  68.         else
  69.             GPBDAT &=~(1<<8);                
  70.     }

  71.     return 0;
  72. }

mem.lds

  1. /*
  2.  *lcl bootloader mem.lds
  3.  */

  4. OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  5. OUTPUT_ARCH(arm)
  6. ENTRY(_start)

  7. SECTIONS {
  8.   . = 0x00000000;

  9.   . = ALIGN(4);
  10.   .init : AT(0) {start.o}

  11.   . = 0x30100000;
  12.   .text : AT(2048) { *(.text) }
  13.     
  14.   .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) { *(.rodata*) }

  15.   .data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
  16.   
  17.   . = ALIGN(4);
  18.   __bss_start = .;
  19.   .bss :{ *(.bss) *(COMMON)}
  20.   __bss_end = .;
  21. }

Makefile

  1. objs := start.o main.o uart0_init.o

  2. sdram.bin : $(objs)
  3.     arm-linux-ld -Tmem.lds    -o sdram_elf $^
  4.     arm-linux-objcopy -O binary -S sdram_elf $@
  5.     arm-linux-objdump -D -m arm sdram_elf > sdram.dis
  6.     arm-linux-objdump -dx sdram_elf > mem_bin.map
  7.     rm -f sdram.dis sdram_elf *.o

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

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

  12. clean:
  13.     rm -f sdram.bin mem_bin.map
 
以下为能直接运行的二进制文件,下载到Nand Flash 的 Black0 直接以Nand Flash运行
阅读(2098) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~