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通道0 接收发送状态寄存器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通道0 错误状态寄存器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 REGISTER(UBRDIVn)
在UART 模块中有三个UART 波特率除数寄存器UBRDIV0,UBRDIV1 和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 //启动代码
- /*
- *************************************************************************
- *
- * lcl bootloader
- *
- *************************************************************************
- */
- .globl _start
- _start: b start_code
- start_code:
- /*
- * set the cpu to SVC32 mode
- */
- mrs r0, cpsr
- bic r0, r0, #0x1f
- orr r0, r0, #0xd3
- msr cpsr, r0
- bl clock_init
- bl cpu_init_crit
- bl copy_code_to_sdram
- /*
- *run in sdram
- */
- ldr sp, =0x34000000
- ldr lr, =halt_loop @璁剧疆杩斿洖鍦板潃
- ldr pc, = Main //0x30100034
- halt_loop:
- b halt_loop
- /*
- * copy code from interal 4K sdram to sdram
- */
- copy_code_to_sdram:
- #define SDRAM_BASE 0x30000000
- mov r1,#2048
- ldr r2,=0x30100000
- mov r3,#4*1024
- 1:
- ldr r4,[r1],#4
- str r4,[r2],#4
- cmp r1,r3
- bne 1b
- mov pc,lr
- /*
- *clock initialize. Mpll=405MHZ 1:4:8
- */
- clock_init:
- #define pWTCON 0x53000000
- #define INTMSK 0x4A000008 /* Interupt-Controller base addresses */
- #define INTSUBMSK 0x4A00001C
- #define CLKDIVN 0x4C000014 /* clock divisor register */
- #define CLK_CTL_BASE 0x4C000000 /* clock base address */
- #define MDIV_405 0x7f << 12 /* MDIV 0x7f*/
- #define PSDIV_405 0x21 /* PDIV SDIV 0x2 0x1 */
- /* turn off the watchdog */
- ldr r0, =pWTCON
- mov r1, #0x0
- str r1, [r0]
- /*
- * mask all IRQs by setting all bits in the INTMR - default
- */
- ldr r1, =0x7fff
- ldr r0, =INTSUBMSK
- str r1, [r0]
- /* FCLK:HCLK:PCLK = 1:4:8 */
- ldr r0, =CLKDIVN
- mov r1, #5 //1:4:8
- str r1, [r0]
- mrc p15, 0, r1, c1, c0, 0 //切换到实时总线HCLK
- orr r1, r1, #0xc0000000
- mcr p15, 0, r1, c1, c0, 0
- mov r1, #CLK_CTL_BASE
- mov r2, #MDIV_405
- add r2, r2, #PSDIV_405
- str r2, [r1, #0x04] /* MPLLCON address Mpll=405MHZ */
- mov pc,lr
- /*
- *MMU and SDRAM initialize
- */
- cpu_init_crit:
- /*
- * flush v4 I/D caches
- */
- mov r0, #0
- mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
- mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
- /*
- * disable MMU stuff and caches
- */
- mrc p15, 0, r0, c1, c0, 0
- bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
- bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
- orr r0, r0, #0x00000002 @ set bit 2 (A) Align
- orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
- mcr p15, 0, r0, c1, c0, 0
- /*
- * before relocating, we have to setup RAM timing
- * because memory timing is board-dependend, you will
- * find a lowlevel_init.S in your board directory.
- */
- mov ip, lr
- bl memsetup /* memory control configuration */
- mov lr, ip
- mov pc, lr
- memsetup:
- /* memory control configuration */
- /* make r0 relative the current location so that it */
- /* reads SMRDATA out of FLASH rather than memory ! */
- #define MEM_CTL_BASE 0x48000000
- mov r1,#MEM_CTL_BASE
- adr r2,mem_cfg_val
- add r3,r1,#52
- 1:
- ldr r4, [r2], #4
- str r4, [r1], #4
- cmp r1, r3
- bne 1b
- mov pc,lr
- .align 4
- /* the literal pools origin */
- mem_cfg_val:
- .long 0x22011110
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700
- .long 0x00000700 @BANK5
- .long 0x00018005
- .long 0x00018005
- .long 0x00ac03f4 @REFRESH // 12MHZ 0x00ac07a3
- .long 0x000000B1
- .long 0x00000030
- .long 0x00000030
def.h
- #ifndef __DEF_H__
- #define __DEF_H__
- #define U32 unsigned int
- #define U16 unsigned short
- #define S32 int
- #define S16 short int
- #define U8 unsigned char
- #define S8 char
- #define __REGb(x) (*(volatile unsigned char *)(x))
- #define __REGw(x) (*(volatile unsigned short *)(x))
- #define __REGi(x) (*(volatile unsigned int *)(x))
- #endif /*__DEF_H__*/
s3c2440_addr.h
- /***********uart address*********************/
- #define UART_CTL_BASE 0x50000000
- #define UART0_CTL_BASE UART_CTL_BASE
- #define UART1_CTL_BASE UART_CTL_BASE + 0x4000
- #define UART2_CTL_BASE UART_CTL_BASE + 0x8000
- #define ULCON0 __REGi(UART0_CTL_BASE + 0x00) /* R/W, UART line control register */
- #define UCON0 __REGi(UART0_CTL_BASE + 0x04) /* R/W, UART control register */
- #define UFCON0 __REGi(UART0_CTL_BASE + 0x08) /* R/W, UART FIFO control register */
- #define UMCON0 __REGi(UART0_CTL_BASE + 0x0C) /* R/W, UART modem control register */
- #define UTRSTAT0 __REGi(UART0_CTL_BASE + 0x10) /* R , UART Tx/Rx status register */
- #define UERSTAT0 __REGi(UART0_CTL_BASE + 0x14) /* R , UART Rx error status register */
- #define UFSTAT0 __REGi(UART0_CTL_BASE + 0x18) /* R , UART FIFO status register */
- #define UMSTAT0 __REGi(UART0_CTL_BASE + 0x1C) /* R , UART Modem status register */
- #define UTXH0 __REGb(UART0_CTL_BASE + 0x20) /* W 8bit , UART transmit(little-end) buffer */
- #define URXH0 __REGb(UART0_CTL_BASE + 0x24) /* R 8bit , UART receive(little-end) buffer */
- #define UBRDIV0 __REGi(UART0_CTL_BASE + 0x28) /* R/W, Baud rate divisor register */
- /* ... */
- #define UTRSTAT_TX_EMPTY (1 << 2)
- #define UTRSTAT_RX_READY (1 << 0)
- #define UART_ERR_MASK 0xF
- #define UART_BAUD_RATE 115200
- #define UART_PCLK_405_148 50625000
- #define UART_PCLK UART_PCLK_405_148
- #define UART_BRD ((UART_PCLK / (UART_BAUD_RATE * 16)) - 1)
-
- /***********GPB GPG GPH GPIO address*********************/
- #define GPBCON (*(volatile unsigned long *) 0x56000010)
- #define GPBDAT (*(volatile unsigned long *) 0x56000014)
- #define GPBUP (*(volatile unsigned long *) 0x56000018)
- #define GPGCON (*(volatile unsigned long *) 0x56000060)
- #define GPGDAT (*(volatile unsigned long *) 0x56000064)
- #define GPGUP (*(volatile unsigned long *) 0x56000068)
- #define GPHCON __REGi(0x56000070) //R/W Configures the pins of port H 0x0
- #define GPHDAT __REGi(0x56000074) //R/W The data register for port H Undef.
- #define GPHUP __REGi(0x56000078) //R/W pull-up disable register for port H
- /* .. */
- #define GPX_up 0x00000000 // up
- #define GPX_mask(pin) (~(3<<((pin)*2)))
-
-
- #define GPH_tx0 (2<<(2*2)) //10 = TXD[0]
- #define GPH_rx0 (2<<(3*2)) //10 = RXD[0]
- #define GPB5_out (1<<(5*2))
- #define GPB6_out (1<<(6*2))
- #define GPB7_out (1<<(7*2))
- #define GPB8_out (1<<(8*2))
- #define GPG0_in (0<<(0*2))
- #define GPG3_in (0<<(3*2))
- #define GPG5_in (0<<(5*2))
- #define GPG6_in (0<<(6*2))
- /*****************timer register*****************/
- #define TCFG0 (*(volatile unsigned long *) 0x51000000)
- #define TCFG1 (*(volatile unsigned long *) 0x51000004)
- #define TCON (*(volatile unsigned long *) 0x51000008)
- #define TCNTB0 (*(volatile unsigned long *) 0x5100000C)
- #define TCMPB0 (*(volatile unsigned long *) 0x51000010)
- #define TCNTO0 (*(volatile unsigned long *) 0x51000014)
- /* .. */
- #define GPB0_pwm (2<<(0*2))
uart0_init.h
- #ifndef __UART0_INIT_H__
- #define __UART0_INIT_H__
- void uart0_init();
- void Uart_SendString(char *pt);
- #endif
uart0_init.c
- /*
- * uart0 lib
- */
- #include "s3c2440_addr.h"
- void uart0_init()
- {
- GPHCON &= (GPX_mask(2) & GPX_mask(3));
- GPHCON |= GPH_tx0 | GPH_rx0;
- GPHUP |= 0x0c;
- ULCON0 = (0<< 3) | (0<< 2) | (3<< 0); // 8N1 ;normal mode , no parity , 1stop bit,8bit
- UCON0 = (0<<10) | (1<< 9) | (1<< 6) | (1<< 2) | (1<< 0); // Select PCLK for the UART baud rate,polling mode, [9][6]:1 1
- UFCON0 = 0x00; // disable FIFO
- UMCON0 = 0x00; // disable AFC
- UBRDIV0 = UART_BRD; // baud rate divisior 115200
- }
- static inline void putc(char data)
- {
- while (!(UTRSTAT0 & 0x4)) ; //Wait until THR is empty.
- UTXH0 = data;
- }
- static inline unsigned char getc(void)
- {
- while (!(UTRSTAT0 & (1))) ; //Wait until THx is empty.
- return URXH0;
- }
- void Uart_SendString(char *pt)
- {
- while (*pt)
- putc(*pt++);
- }
main.c
- /*
- GPBCON 0x56000010 Port B control
- GPBDAT 0x56000014 Port B data
- GPBUP 0x56000018 Pull-up control B
- LED1 GPB5 LED2 GPB6 LED3 GPB7 LED4 GPB8
- */
- #include "uart0_init.h"
- #include "s3c2440_addr.h"
- void leds_init()
- {
- GPBCON &=(GPX_mask(5) & GPX_mask(6) & GPX_mask(7) & GPX_mask(8));
- GPBCON |= (GPB5_out | GPB6_out | GPB7_out | GPB8_out);
- GPBUP = GPX_up;
- }
- void buttons_init()
- {
- GPGCON &= (GPX_mask(0) & GPX_mask(3) & GPX_mask(5) & GPX_mask(6));
- GPGCON |= (GPG0_in & GPG3_in & GPG5_in & GPG6_in);
- GPGUP = GPX_up;
- }
-
- void pwm_init()
- {
- GPBCON &= GPX_mask(0);
- GPBCON |= GPB0_pwm;
- }
- void timer0_init()
- {
- TCFG0 = 99; //prescaler0 value = 99
- TCFG1 = 0x03; // MUX 1/16
- TCNTB0 = 11640; //63280
- TCMPB0 = 11640/2;
- TCON |= (1<<1); //update TCNTB0&TCNMB0
- TCON = 0x09; // auto reload, inverter off ,clear 0 ,start for timer0
-
- }
- int Main()
- {
- unsigned long dwDat;
- leds_init();
- buttons_init();
- //pwm_init();
- //timer0_init();
- uart0_init();
- while (1)
- {
- dwDat=GPGDAT;
- if(dwDat & (1<<0))
- {
- GPBDAT |=(1<<5);
- Uart_SendString("\r LED1 is ON. \r\n");
- }
- else
- {
- GPBDAT &=~(1<<5);
- Uart_SendString("\r LED1 is OFF.\r\n");
- }
- if(dwDat & (1<<3))
- GPBDAT |=(1<<6);
- else
- GPBDAT &=~(1<<6);
- if(dwDat & (1<<5))
- GPBDAT |=(1<<7);
- else
- GPBDAT &=~(1<<7);
- if(dwDat & (1<<6))
- GPBDAT |=(1<<8);
- else
- GPBDAT &=~(1<<8);
- }
- return 0;
- }
mem.lds
- /*
- *lcl bootloader mem.lds
- */
- OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
- OUTPUT_ARCH(arm)
- ENTRY(_start)
- SECTIONS {
- . = 0x00000000;
- . = ALIGN(4);
- .init : AT(0) {start.o}
- . = 0x30100000;
- .text : AT(2048) { *(.text) }
-
- .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) { *(.rodata*) }
- .data ALIGN(4) : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
-
- . = ALIGN(4);
- __bss_start = .;
- .bss :{ *(.bss) *(COMMON)}
- __bss_end = .;
- }
Makefile
- objs := start.o main.o uart0_init.o
- sdram.bin : $(objs)
- arm-linux-ld -Tmem.lds -o sdram_elf $^
- arm-linux-objcopy -O binary -S sdram_elf $@
- arm-linux-objdump -D -m arm sdram_elf > sdram.dis
- arm-linux-objdump -dx sdram_elf > mem_bin.map
- rm -f sdram.dis sdram_elf *.o
- %.o:%.c
- arm-linux-gcc -Wall -c -O2 -o $@ $<
- %.o:%.S
- arm-linux-gcc -Wall -c -O2 -o $@ $<
- clean:
- rm -f sdram.bin mem_bin.map
以下为能直接运行的二进制文件,下载到Nand Flash 的 Black0 直接以Nand Flash运行