IMX6ULL串口实验之printf格式化函数移植

一.   串口格式化函数

上一章实验我们实现了 UART1 基本的数据收发功能,虽然可以用来调试程序,但是功能太单一了,只能输出字符。
本章我们就来学习:如何将 printf 这样的格式化函数移植到 I.MX6U-ALPHA 开发板上。

串口格式化函数

格式化函数说的是 printfsprintf scanf 这样的函数,分为格式化输入和格式化输出两类
函数。 学习 C 语言的时候常常通过 printf 函数在屏幕上显示字符串,通过 scanf 函数从键盘获取
输入。这样就有了输入和输出了,实现了最基本的人机交互。

I.MX6U-ALPHA 开发板上也可以使用此方法,将 printfscanf 映射到串口上,这样就可以使用串口调试助手(如 xshell工具)作为开发板的终端,完成与开发板的交互。

二.   printf格式化函数的移植

本文是对正点原子提供的 printf格式化函数代码进行移植。

本章实验所需要移植的源码已经放到了开发板光盘中,路径为: 1 、例程源码 ->5 、模块驱动源
->2 、格式化函数源码 ->stdio ,文件夹 stdio 里面的文件就是我们要移植的源码文件。

本次实验在上一个 “串口实验” 代码工程的基础上完成,将 stdio 文件夹复制到实验工程根目录中。

stdio 文件夹复制到代码工程的根目录,如下目录:

stdio 里面的所有文件, stdio 里面的文件其实是从 uboot 里面移植过来的。后面学习 uboot 以后大家有兴趣的话可以自行从 uboot 源码里面“扣”出相应的文件,完成格式化 函数的移植。

注意:

本次实验前提是,之前串口收发函数名分别需要设置为 putc(),puts(),与 getc() 名字。

因为待移植的代码 stdio 文件夹中的 printf scanf 函数,会调用到含有以上名字的串口收发函数。

主函数更改如下:

int main(void)
{
    int a = 0, b = 0;

    int_init();          //中断初始化
    imux6ull_clk_init(); //初始化系统时钟
    GPT1_delay_init();   //GPT1定时器初始化
    uart_init();         //串口初始化
    clk_enable();        //使能外设时钟
    led_init();          //Led初始化
    beep_init();         //蜂鸣器初始化
    key_init();          //key按键初始化
    key_filter_init();

    while(1)
    {
        printf("请输入两个整数,使用空格隔开:");
        scanf("%d %d", &a, &b);
        printf("\r\n 数据%d+%d=%d\r\n", a, b, a+b);
    }

    return 0;
}

更改 Makefile文件,添加 所移植的 stdio 文件。 

CROSS_COMPILE ?= arm-linux-gnueabihf-
TARGET        ?= printf

CC            := $(CROSS_COMPILE)gcc
LD            := $(CROSS_COMPILE)ld
OBJCOPY       := $(CROSS_COMPILE)objcopy
OBJDUMP       := $(CROSS_COMPILE)objdump   

LIBPATH       := -lgcc -L /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4

INCUDIRS      := imx6ull   \
                 bsp/clk   \
                 bsp/led   \
                 bsp/delay \
				 bsp/beep  \
				 bsp/key   \
				 bsp/gpio  \
				 bsp/int   \
				 bsp/exterint \
				 bsp/epit  \
				 bsp/key_filter \
				 bsp/uart  \
				 stdio/include

SRCDIRS       := project   \
                 bsp/clk   \
                 bsp/led   \
                 bsp/delay \
				 bsp/beep  \
				 bsp/key   \
				 bsp/gpio  \
				 bsp/int   \
				 bsp/exterint \
				 bsp/epit  \
				 bsp/key_filter \
				 bsp/uart  \
				 stdio/lib

INCLUDE       := $(patsubst %, -I %, $(INCUDIRS)) 

SFILES        := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.S))
CFILES        := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.c))

SFILENDIR     := $(notdir $(SFILES))
CFILENDIR     := $(notdir $(CFILES))

SOBJS         := $(patsubst %, obj/%, $(SFILENDIR:.S=.o))
COBJS         := $(patsubst %, obj/%, $(CFILENDIR:.c=.o))

OBJS          := $(SOBJS)$(COBJS)

VPATH         := $(SRCDIRS)

.PHONY:clean


$(TARGET).bin: $(OBJS)
	$(LD) -Timx6ull.lds -o $(TARGET).elf $^ $(LIBPATH)
	$(OBJCOPY) -O binary -S $(TARGET).elf $@
	$(OBJDUMP) -D -m arm $(TARGET).elf > $(TARGET).dis

$(SOBJS) : obj/%.o : %.S
	$(CC) -Wall -nostdlib -c -O2 $(INCLUDE) -o $@ $< 

$(COBJS) : obj/%.o : %.c
	$(CC) -Wall -Wa,-mimplicit-it=thumb -nostdlib -fno-builtin -c -O2 $(INCLUDE) -o $@ $< 


clean:
	rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).dis $(OBJS)

print:
	@echo INCLUDE   = $(INCLUDE)

Makefile文件添加如下:

1.  添加头文件路径与 .c 文件路径:stdio/include 与  stdio/lib

2.  添加编译选项:-nostdlib

-nostdlib作用: 不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。这个选项常用于编译内核、bootloader等程序,它们不需要启动文件、标准库文件。

C语言程序执行的第一条指令。并不是 main()函数。生成一个C程序的可执行文件时编译器通常会在我们的代码上加上几个被称为启动文件的文件,他们是标准库文件,这些代码设置 C 程序的堆栈等,然后调用 main() 函数。他们依赖于操作系统。

在裸板上无法执行,所以我们自己写一个。我们自己写的 *.s 汇编文件(例如我们写的 start.S)就是一个启动文件,它设置好堆栈后调用 main() 函数。因此,我们不需要系统自带的启动文件。
 

3.  添加编译选项: -fno-builtin

这里作用的调用代码中实现的串口收发接口:putc()、puts()与 getc()函数,而不调用C库函数中的这几个函数。

在我们的代码中,有时可能会定义一个函数,函数名字和 语言运行库里的函数名冲突的情况。-fno-builtin选项用来设置选择自己定义的函数,而不使用C语言库中的函数。

4.  添加编译选项:-Wa,-mimplicit-it=thumb 。

如果不加 这个编译选项,编译会出现以下问题:

/tmp/ccKkHd3g.s: Assembler messages:
/tmp/ccKkHd3g.s:42: 错误: thumb conditional instruction should be in IT block -- `addcs r5,r5,#65536'
make: *** [Makefile:68:obj/muldi3.o] 错误 1

printf 格式化函数移植实验,至此完成。

在自己的世界里能静下心学习。静与定,是专注的前提。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值