一、背景
1、介绍
通用异步收发器简称 UART,即 UNIVERSAL ASYNCHRONOUS RECEIVER AND TRANSMITTER,它用来传输串行数据。发送数据时,CPU 将并行数据写入 UART,UART 按照一定的格式在一根电线上串
行发出;接收数据时,UART 检测另一根电线的信号,将串行收集在缓冲区中,CPU 即可读取 UART获得这些数据。 在 S5PV210 中,UART 提供了 4 对独立的异步串口 I/O 端口,有 4 个独立的通道,每个通道可以工作于 DMA 模式或者中断模式。 其中, 通道 0 有 256byte 的的发送 FIFO 和 256byte 的接收FIFO,通道 1 有 64byte 的的发送 FIFO 和 64byte 的接收 FIFO, 而通道 2 和 3 只有 16byte 的的发送 FIFO和 16byte 的接收 FIFO。
uart结构图:
2、主要寄存器
GPA0CON 0xE020_0000
GPA1CON 0xE020_0020
UFCON0 0xE290_0008
UMCON0 0xE290_000C
ULCON0 0xE290_0000
UCON0 0xE290_0004
UBRDIV0 0xE290_0028
UDIVSLOT0 0xE290_002C
UTRSTAT0 0xE290_0010
UTXH0 0xE290_0020
URXH0 0xE290_0024
二、代码
1、start.s
/*
* 代码:初始化uart输出输入一个字符
* 日期:2020.7.13
* 作者:glass love
*
*/
.globl _start
_start:
/**********************关看门狗*******************************/
//通过查阅数据手册知道控制看门狗开关的寄存器是:
//Watchdog Timer Control Register (WTCON, R/W, Address =0xE2700000 )
//WTCON寄存器的bit[0]位是启用或禁用复位信号的看门狗定时器输出位
//1为启用,0为禁止
//因此只需要往WTCON中写入0x0即可
ldr r0, =0x00000000
ldr r1, =0xE2700000
str r0, [r1]
/***********************设置栈****************************/
//IROM 里的固定代码设置的 sp 就等于 0xD003_7D80,
//所以我们设置栈一般就指向0xD003_7D80,以调用c函数
ldr sp, =0xD0037D80
/**********************初始化时钟***********************/
bl clock_init
/*********初始化uart并输出输入一个字符************/
bl main
//汇编死循环
b .
2、uart.c
#define rGPA0CON ( *((volatile unsigned long *)0xE0200000) )
#define rGPA1CON ( *((volatile unsigned long *)0xE0200020) )
// UART相关寄存器
#define rULCON0 ( *((volatile unsigned long *)0xE2900000) )
#define rUCON0 ( *((volatile unsigned long *)0xE2900004) )
#define rUFCON0 ( *((volatile unsigned long *)0xE2900008) )
#define rUMCON0 ( *((volatile unsigned long *)0xE290000C) )
#define rUTRSTAT0 ( *((volatile unsigned long *)0xE2900010) )
#define rUERSTAT0 ( *((volatile unsigned long *)0xE2900014) )
#define rUFSTAT0 ( *((volatile unsigned long *)0xE2900018) )
#define rUMSTAT0 ( *((volatile unsigned long *)0xE290001C) )
#define rUTXH0 ( *((volatile unsigned long *)0xE2900020) )
#define rURXH0 ( *((volatile unsigned long *)0xE2900024) )
#define rUBRDIV0 ( *((volatile unsigned long *)0xE2900028) )
#define rUDIVSLOT0 ( *((volatile unsigned long *)0xE290002C) )
#define rUINTP ( *((volatile unsigned long *)0xE2900030) )
#define rUINTSP ( *((volatile unsigned long *)0xE2900034) )
#define rUINTM ( *((volatile unsigned long *)0xE2900038) )
#define UART_UBRDIV_VAL 0x23
#define UART_UDIVSLOT_VAL 0x0888
void uart_init(void)
{
//初始化GPIO引脚,配置RX和TX功能
rGPA0CON = 0x22222222;
rGPA1CON = 0x2222;
//设置数据格式
//禁用FIFO
rUFCON0 = 0x0;
//禁用流控
rUMCON0 = 0x0;
// 数据位:8, 无校验, 停止位: 1
rULCON0 = 0x3;
//时钟:PCLK,禁止中断
rUCON0 = 0x5;
//设置波特率
rUBRDIV0 = UART_UBRDIV_VAL;
rUDIVSLOT0 = UART_UDIVSLOT_VAL;
}
void putch(char c)
{
// 如果TX满,等待
while (!(rUTRSTAT0 & (1<<2)));
// 写数据
rUTXH0 = c;
}
char getch(void)
{
// 如果RX 空,等待
while (!(rUTRSTAT0 & (1<<0)));
// 取数据
return rURXH0;
}
3、main.c
void uart_init(void);
void main(void)
{
//UART初始化
uart_init();
while(1)
{
char c;
//接收一个字符
c = getch();
//发送一个字符
putch(c+1);
}
}
4、Makefile
uart_init: start.o clock.o uart.o main.o
arm-linux-ld -Ttext 0x20000000 -o uart_init.elf $^
arm-linux-objcopy -O binary uart_init.elf uart_init.bin
arm-linux-objdump -D uart_init.elf > uart_init_elf.dis
gcc mkv210_image.c -o mk210
./mk210 uart_init.bin 210.bin
%.o : %.S
arm-linux-gcc -o $@ $< -c -nostdlib
%.o : %.c
arm-linux-gcc -o $@ $< -c -nostdlib
clear:
rm *.o *.elf *.bin *.dis mk210 -f
5、clock.S
clock.S较上一节没有改变。