QQ登录

只需一步,快速开始

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 4251|回复: 0

Learn lumit Step 5 : 实现 printf

[复制链接]
发表于 2005-5-27 01:21:32 | 显示全部楼层 |阅读模式
Learn lumit Step 5 : 实现 printf 输出
++++++++++++++++++++++++++++++++++++++++++++++++++++++

    串口能够驱动起来之后,按照惯例我们就要 helloworld 了。其实格式化输出
printf 的作用在嵌入式开发中的地位远不止此,它不仅是一个非常重要的调试手段,
也是一个无法回避的技术细节。这一节对于很多做 ARM 开发的我相信都很重要,
特别是对于使用 ADS1.2 上 ARMCC 编译器的开发者来说,这里提到的一个技巧也许
能帮上你不少忙。

    我在知道怎么用技巧实现 printf 输出之前,一直都是用 SkyEye 里面的一个被
起名为 skyeye_printf.c 的文件,它实际上是实现了一个自制简易可用的 printf ,
其简单实用的程度好比 Wiggler Jtag 仿真调试头。这个文件是从水木清华 BBS 上
wohaha 大侠的一篇帖子里面找出来的,虽然它在嵌入式应用场合也足够好用,不过
还是有很多不足,我把它也放到附件里面,有兴趣的朋友可以下载来看。

    上面的 skyeye_printf.c 主要是自己实现了格式化输出那些 % 的输出格式,
最终通过字符输出函数 skyeye_putc 这样一个 low-level 的输出接口获得实现的。
但在 ARM ADS1.2 里面已经有了足够好的 C 库来实现格式化字符串的工作,它所缺的
仅仅就是一个底层的输出接口函数。通常这个最底层的输出接口就是通过某一个串口
把字符发送出来,在另一端用超级终端这样的工具显示出来就可以。

    在 ADS1.2 的安装目录下 ( 我的机器上是 C:\Program Files\ARM\ADSv1_2\PDF )
有一篇非常好的文档教你怎么实现这个接口,文档名是 ADS_CompilerGuide_D.pdf ,
在 The C and C++ Library 章节 4-76 (page166) 位置处,这是一个经典的不能再经典
的关于 printf 实现的例子,我们所要做的就是把 fputc 实现为我们上一节里面已经做
好的 uart_sendchar ,其他还有 ferror 和 __stdout 的声明也不可少。

    具体实现的代码如下:

/* retarget code of printf low-level function */
/* *************************************************************** */
#include <stdio.h>
struct __FILE { int handle;   /* Add whatever you need here */};
FILE __stdout;

int fputc(int ch, FILE *f)
{
        if( ch == '\n' )
        {
                uart_putchar( UART0_BASE, '\r' );
                uart_putchar( UART0_BASE, '\n' );
        }
        else
                uart_putchar( UART0_BASE, ch );
        return ch;
}

int ferror(FILE *f)
{
        return EOF;
}
/* *************************************************************** */

    只要把上面这一段代码嵌入到你的 main 之上,然后在调用 printf 之前把串口
按照需要的波特率初始化好,就可以方便地使用 printf 提供的标准格式化输出功能了。

    附件里面是一个现成的例子,可以在 lumit4510 的板子上烧进去,运行输出的结果
如下:
printf
hello, lumiter!
test_rw = 0x2468, test_ro = 0x1357, test_bss = 0x0
printf
hello, lumiter!
test_rw = 0x2468, test_ro = 0x1357, test_bss = 0x0

    特别要说明的是,它完成了从加电启动到实现 printf 的全部过程,不需要借助
任何的系统调用,和 bootloader 无关。有点板子不需要这样实现也可以用 printf 输出,
那主要是借助了板子上 SWI 软中断接口,其实我倒觉得这个顺序应该反过来,printf 是
实现一个 bootloader 前必须经过的一个环节,不知大家是否赞同?

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
您需要登录后才可以回帖 登录 | 注册

本版积分规则

GMT+8, 2024-3-28 18:20 , Processed in 0.071589 second(s), 16 queries .

© 2021 Powered by Discuz! X3.5.

快速回复 返回顶部 返回列表