X210串口配置与stdio移植
串口控制器初始化关键步骤
(1)初始化串口的Tx和Rx引脚所对应的GPIO(查原理图可知Rx和Rx分别对应GPA0_1和GPA0_0)
(2)GPA0CON(0xE0200000),bit[3:0] = 0b0010 bit[7:4] = 0b0010
(3)初始化这几个关键寄存器UCON0 ULCON0 UMCON0 UFCON0 UBRDIV0 UDIVSLOT0
主要的几个寄存器
(1)ULCON0 = 0x3 // 0校验位、8数据位、1停止位
(2)UCON = 0x5 // 发送和接收都是polling mode
(3)UMCON0 = 0x0 // 禁止modem、afc
(4)UFCON0 = 0x0 // 禁止FIFO模式
(5)UBRDIV0和UDIVSLOT0和波特率有关,要根据公式去算的
波特率的计算和设置
(1)第一步,用PCLK_PSYS和目标波特率去计算DIV_VAL: DIV_VAL = (PCLK / (bps x 16)) ?1
(2)第二步,UBRDIV0寄存器中写入DIV_VAL的整数部分
(3)第三步,用小数部分*16得到1个个数,查表得uBDIVSLOT0寄存器的设置值
#define GPA0CON 0xE0200000 #define UCON0 0xE2900004 #define ULCON0 0xE2900000 #define UMCON0 0xE290000C #define UFCON0 0xE2900008 #define UBRDIV0 0xE2900028 #define UDIVSLOT0 0xE290002C #define UTRSTAT0 0xE2900010 #define UTXH0 0xE2900020 #define URXH0 0xE2900024 #define rGPA0CON (*(volatile unsigned int *)GPA0CON) #define rUCON0 (*(volatile unsigned int *)UCON0) #define rULCON0 (*(volatile unsigned int *)ULCON0) #define rUMCON0 (*(volatile unsigned int *)UMCON0) #define rUFCON0 (*(volatile unsigned int *)UFCON0) #define rUBRDIV0 (*(volatile unsigned int *)UBRDIV0) #define rUDIVSLOT0 (*(volatile unsigned int *)UDIVSLOT0) #define rUTRSTAT0 (*(volatile unsigned int *)UTRSTAT0) #define rUTXH0 (*(volatile unsigned int *)UTXH0) #define rURXH0 (*(volatile unsigned int *)URXH0) //串口初始化 void uart_init() { //初始化rx tx对应GPIO引脚 rGPA0CON&=~(0xff<<0);//将 bit0~7清零 rGPA0CON|=0x22; //设置 _0 _1引脚为RX TX //串口相关寄存器 rULCON0=0x3; rUCON0=0x5; rUMCON0=0; rUFCON0=0; //波特率计算相关 /* //9600 rUBRDIV0=433; rUDIVSLOT0=0x2222; */ //用66.7MHZ算 //115200 //66700000/(115200*16)-1 rUBRDIV0=35; // rUBRDIV0余数*16 然后查表 rUDIVSLOT0=0x0888; } //串口发送一字节 void uart_putc(char c) { while(!(rUTRSTAT0&(1<<1)));//等待发送结束 rUTXH0=c; } char uart_getc() { while(!(rUTRSTAT0&(1<<0)));//等待发送结束 return rURXH0; }
2.移植stdio(部分代码展示)
int printf(const char *fmt, ...) { int i; int len; va_list args; va_start(args, fmt); len = vsprintf(g_pcOutBuf,fmt,args); va_end(args); for (i = 0; i < strlen(g_pcOutBuf); i++) { putc(g_pcOutBuf[i]); } return len; } int scanf(const char * fmt, ...) { int i = 0; unsigned char c; va_list args; while(1) { c = getc(); putc(c); if((c == 0x0d) || (c == 0x0a)) { g_pcInBuf[i] = '\0'; break; } else { g_pcInBuf[i++] = c; } } va_start(args,fmt); i = vsscanf(g_pcInBuf,fmt,args); va_end(args); return i; }
Makefile
CC = arm-linux-gcc LD = arm-linux-ld OBJCOPY = arm-linux-objcopy OBJDUMP = arm-linux-objdump AR = arm-linux-ar INCDIR := $(shell pwd) # C预处理器的flag,flag就是编译器可选的选项 CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include # C编译器的flag CFLAGS := -Wall -O2 -fno-builtin #导出这些变量到全局,其实就是给子文件夹下面的Makefile使用 export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGS objs := start.o led.o clock.o uart.o main.o objs += lib/libc.a uart.bin: $(objs) $(LD) -Tlink.lds -o uart.elf $^ $(OBJCOPY) -O binary uart.elf uart.bin $(OBJDUMP) -D uart.elf > uart_elf.dis gcc mkv210_image.c -o mkx210 ./mkx210 uart.bin 210.bin lib/libc.a: cd lib; make; cd .. %.o : %.S $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c %.o : %.c $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $< -c clean: rm *.o *.elf *.bin *.dis mkx210 -f cd lib; make clean; cd ..