ARM uart stdio 的移植

一、uart stdio的移植1 1. 什么是 stdio
(1) #
(2) stdio: input ,标准输入输出
(3) 标准输入输出就是操作系统定义的默认的输入和输出通道 。一般在 PC 机的情况下,标准输入指的是键盘,标准输出指的是屏幕 。
(4)函数和 scanf 函数可以和底层输入/输出函数绑定,然后这两个函数就可以和 stdio 绑定起来 。也就是说我们直接调用函数输出,内容就会被从标准输出输出出去 。
(5) 在我们这里,标准输出当然不是屏幕了,而是串口 。标准输出也不是键盘,而是串口 。
2.函数的工作原理
【ARM uart stdio 的移植】(1)函数工作时,内部实际调用了 2 个关键函数:一个是函数(主要功能是格式化打印信息,最终得到纯字符串格式的打印信息等待输出),另一个就是真正的输出函数 putc(操控标准输出的硬件,将信息发送出去)
3. 移植函数的三种思路
(1) 我们希望在我们的开发板上使用函数进行(串口)输出,使用 scanf 函数进行(串口)输入,就像在 PC 机上用键盘和屏幕进行输入输出一样 。因此需要移植函数/ scanf 函数 。
(2) 我们说的移植而不是编写,我们不希望自己完全重新编写,而是想尽量借用已有的代码(叫移植) 。
(3) 一般移植函数可以有 3 个途径获取的实现源码:最原始最原本的来源就是 linux 内核中的。难度较大、关键是麻烦;稍微简单些的方法是从 uboot 中移植;更简单的方法就是直接使用别人移植好的 。

ARM uart stdio 的移植

文章插图
(3) 我们课程中使用第三种方法,别人移植好的函数,来自于友善之臂的的裸机教程中提供的 。
4. 移植好的介绍
lib/.c 文件的内容:
#include "vsprintf.h"#include "string.h"#include "printf.h"extern void putc(unsigned char c);extern unsigned char getc(void);#define OUTBUFSIZE 1024#define INBUFSIZE 1024// 自己定义了2个全局变量数组,分别作为发送/接收缓冲区 。// 将来发送时先将要发送的信息格式化送入发送缓冲区,然后putc函数直接从发送缓冲区取// 数据发送出去 。static char g_pcOutBuf[OUTBUFSIZE];static char g_pcInBuf[INBUFSIZE];// putc函数真正和输出设备绑定,这个函数需要我们自己去实现,这就是移植的关键// printf("a = %d, b = %s.\n", a, p);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;}
vsprintf 函数详解printf->vsprintf->vsnprintf->number
函数的作用是:按照我们的传进去的格式化标本,对变参进行处理,然后将之格式化后缓存在一个事先分配好的缓冲区中 。
后半段调用 putc 函数,将缓冲区中格式化好的字符串直接输出到标准输出 。
二、uart stdio的移植2 1. 修改进行移植
顶层文件:
CC= arm-linux-gccLD= arm-linux-ldOBJCOPY = arm-linux-objcopyOBJDUMP = arm-linux-objdumpAR= arm-linux-arINCDIR := $(shell pwd)# C预处理器的flag,flag就是编译器可选的选项CPPFLAGS := -nostdlib -nostdinc -I$(INCDIR)/include# C编译器的flagCFLAGS:= -Wall -O2 -fno-builtin#导出这些变量到全局,其实就是给子文件夹下面的 Makefile 使用export CC LD OBJCOPY OBJDUMP AR CPPFLAGS CFLAGSobjs := start.o led.o clock.o uart.o main.o objs += lib/libc.auart.bin: $(objs)$(LD) -Tlink.lds -o uart.elf $^$(OBJCOPY) -O binary uart.elf uart.bin$(OBJDUMP) -D uart.elf > uart_elf.disgcc mkv210_image.c -o mkx210./mkx210 uart.bin 210.binlib/libc.a:cd lib; make; cd ..%.o : %.S$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $