【问题标题】:How do you Implement printf in GCC from Newlib?你如何在 Newlib 的 GCC 中实现 printf?
【发布时间】:2019-07-27 14:00:27
【问题描述】:

我正在努力使用 GCC 将 newlib 中的 printf 正确实施到我的 esp32 中。

我浏览了 newlib 文档,它为我提供了有关如何调用 printf 的一般信息,但没有向我解释后端实现。

根据我目前的研究,我确定 printf 将格式化的字符串输出到 STDOUT。在 PC 上这对我来说更容易理解,因为有一个控制台窗口可以显示 printf 的格式化输出,但是在嵌入式系统上,我知道你必须告诉库将 printf 的格式化输出重定向到哪里,这就是我在想办法。

再次,根据我的研究,我了解到需要一些函数来完成此操作,特别是函数 _write

我发现如何弥合 printf 和使用 _write 函数之间的差距非常困难。我希望这里有人可以帮助我了解如何正确实现 printf。

如果我错过了一些清楚解释这一点的文档,请重定向我。我尝试阅读 newlib 文档以及 GCC 相关文档,但没有真正提及如何使用 printf,但是有很多关于如何调用 printf 和格式化字符串的文档,但这部分很容易。我需要知道如何从 MCU 的 STDOUT 中获取格式化字符串。

谢谢大家!

【问题讨论】:

  • 您可以在 Web 上找到 printf() 的实现及其或多或少复杂性的亲戚。如果你找到int printf(const char * restrict fmt, ...) { va_list args; va_start(args, fmt); int rc = vfprintf(stdout, fmt, args); va_end(args); return rc; },那么你有一个中继功能,你需要找到vfprintf() 的实现。但这也是可用的……
  • @JonathanLeffler :除非使用 Newlib,否则已经有一个 printf() 实现。我认为的问题应该是关于如何retarget Newlib 以便its printf() 工作,而不是如何实施 printf

标签: c gcc embedded printf newlib


【解决方案1】:

在 Newlib 中,您没有实现库中包含的 printf()。您只需实现一组最小的系统调用来支持该库。流设备系统调用 API 包括 openclosereadwrite(或带有 _r 后缀的可重入版本) - 如果您使用多线程并且需要每个线程errno(在任何实现特定的重入要求中)。

如果您正在实现的只是stdoutprintf()putchar()puts() 等使用的流)并且只支持单个设备(通常是 UART)并且不关心功能重定向或重入,则opencloseread 可以为空,write 可以简单地将提供的缓冲区直接输出到您的低级串行 I/O API:

int _write(int handle, char *data, int size ) 
{
    int count ;

    handle = handle ; // unused

    for( count = 0; count < size; count++) 
    {
        outputByte( data[count] ) ;  // Your low-level output function here.
    }

    return count;
}

请注意,此处的handle 未使用。对于stdout,它将为 1(stdin = 0 和 stderr = 2)。如果您想要为stdoutstderr 提供单独的输出设备,或者如果您支持其他设备或文件系统以及fopenstdout 重定向,则将使用handle 参数。它用于识别open 打开的蒸汽。通过忽略它所有的流输出(比如fprintf()会以同样的方式处理并输出到同一个设备);在许多情况下(printf() 只是获取调试输出的一种方式,或者您的应用程序没有您不会关心的文件系统。

鉴于 write 函数,printf() 将“正常工作”(以最简单的方式),因为在后台所有 stdio 输出函数都调用 write)。建议使用缓冲和非阻塞的低级输出函数(例如,中断驱动的 UART 驱动程序)。

显然,如果您也想在stdin 上接受输入,您将实现类似的read 函数。

如果你想要一个堆(malloc() 等),你还需要实现 sbrk / sbrk_r。我建议您至少在 Newlib 系统调用中实现这一点。

Bill Gaitliff 在Porting and Using Newlib in Embedded Systems 讨论了更复杂的系统调用实现处理,而在here 讨论了基本实现,而Newlib documentation 本身提供了与上述类似的最小实现存根示例。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 2017-12-04
    相关资源
    最近更新 更多