zoukankan      html  css  js  c++  java
  • [smart210] 裸板移植printf()与scanf()的步骤

    平台:smart210

    CPU:S5PV210

    目标:在smart210裸板上移植stdio(标准输入输出)的两个核心函数,printf()与scanf()。

    知识储备:

    1.这里我们直接从主目录下的Makefile分析移植所需要的一系列操作

    CC      = arm-linux-gcc
    LD      = arm-linux-ld
    AR      = arm-linux-ar
    OBJCOPY = arm-linux-objcopy
    OBJDUMP = arm-linux-objdump
    
    INCLUDEDIR     := $(shell pwd)/include
    CFLAGS         := -Wall -O2 -fno-builtin
    CPPFLAGS       := -nostdinc -I$(INCLUDEDIR)
    
    export     CC AR LD OBJCOPY OBJDUMP INCLUDEDIR CFLAGS CPPFLAGS 
    
    objs := start.o main.o uart.o clock.o lib/libc.a
    
    stdio.bin: $(objs)
        ${LD} -Tstdio.lds -o stdio.elf $^
        ${OBJCOPY} -O binary -S stdio.elf $@
        ${OBJDUMP} -D stdio.elf > stdio.dis
    
    .PHONY : lib/libc.a
    lib/libc.a:
        cd lib; make; cd ..
        
    %.o:%.c
        ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
    
    %.o:%.S
        ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
    
    clean:
        make clean -C lib
        rm -f *.bin *.elf *.dis *.o
    关键点在于stdio.bin,是我们最终生成的二进制文件,它依赖于start.o,main.o,uart.o,clock.o与lib/libc.a这些文件,其中.o的来源是经过arm-linux-gcc -c -o 命令生成的,libc.a是通过进入lib目录下静态编译生成的库文件,为什么要使用静态编译,主要是因为我们所需要的printf()和scanf()移植依赖于linux内核提供的内核函数,而我们现在是属于裸板无操作系统的状态下,即使采用动态编译成功生成了.bin文件,也无法在裸板开发板上运行。所以,我们需要手动建一个库,把linux内核支持的printk()函数的相关.c .h文件经过修改后都移植过来,于是我们采用了静态编译的方法生成libc.a库(可以注意到CPPFLAGS带了-nostdinc选项的意思就是不使用标准库,即不动态链接标准库,而是采用当前主目录下的include文件夹里面的.h)。在main.c程序里面包含的“stdio.h"文件里,我们能发现如下代码
    extern int vsnprintf(char *buf, size_t size, const char *fmt, va_list args);
    extern int snprintf(char * buf, size_t size, const char *fmt, ...);
    extern int vsprintf(char *buf, const char *fmt, va_list args);
    extern int sprintf(char * buf, const char *fmt, ...);
    extern int vsscanf(const char * buf, const char * fmt, va_list args);
    extern int sscanf(const char * buf, const char * fmt, ...);
    
    extern void putc(unsigned char c);
    extern unsigned char getc(void);
    
    int printf(const char *fmt, ...);
    int scanf(const char * fmt, ...);
    这说明了一系列与printf()和scanf()相关的子函数都是外部函数,在编译器在链接的时候,就能把libc.a里面的各.o文件内的相关函数链接过来。强大的链接器帮我们把各个独立的.o文件根据函数名(地址)链接起来,生成链接文件elf,该文件又可以进一步改造成适用于开发板使用.bin文件!

    2.从/lib/Makefile分析lib/libc.a库文件的生成

    objs := div64.o lib1funcs.o ctype.o muldi3.o printf.o string.o vsprintf.o
    
    libc.a: $(objs)
        ${AR} -r -o $@ $^
        
    %.o:%.c
        ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
    
    %.o:%.S
        ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
    
    clean:
        rm -f libc.a *.o
    可知,libc.a文件依赖于div64.o lib1funcs.o ctype.o muldi3.o printf.o string.o vsprintf.o ,由于采用了主目录下的Makefile所输出的CPPFLAGS与CFLAGS配置,届时arm-linux-cpp在编译.c文件的时候,就会自动跑去主目录的include库下去找需要的函数了。这些.o文件中,最核心的是printf.o,对应的.c文件实现的最关键的两个函数如下:
    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] = '';
                break;
            }
            else
            {
                g_pcInBuf[i++] = c;
            }
        }
        
        va_start(args,fmt);
        i = vsscanf(g_pcInBuf,fmt,args);
        va_end(args);
    
        return i;
    }
    拿printf()做分析,我们能发现程序内容先对变参数进行处理,把我们输入给printf的每一个参数都做字符串分析,比如%d和数字之类的,然后拷贝对应参数变量的值结合第一个字符串参数里的指令输出到g_pcOutBuf这个字符缓冲区里面,最后循环调用我们的串口单字符打印函数putc()来输出。最终我们就达到了printf()的使用效果了!而scanf()也是类似的!
  • 相关阅读:
    加密与解密学习笔记3-Windows与Unicode
    加密与解密学习笔记2-windows API函数
    加密与解密学习笔记1-文本编码方式
    python3基础知识自学笔记4-流程控制、迭代器、生成器
    python3基础知识自学笔记3-集合字典元组
    python3基础知识自学笔记2-列表
    在单链表按升序插入一个值
    [转]设置好ftp后用xftp连接提示无法打开,无法显示远程文件夹
    删除底部"自豪地采用 WordPress"
    win7一体机放音乐时只有音乐,人声特别小怎么回事
  • 原文地址:https://www.cnblogs.com/tinyfeather/p/3260469.html
Copyright © 2011-2022 走看看