我正在努力使用GCC将printf从newlib正确地实现到我的esp 32。
我已经看过newlib文档,它给了我关于如何调用printf的一般信息,但没有向我解释后端实现。
根据我目前的研究,我确定printf向STDOUT输出格式化的字符串。在PC机上,这对我来说更容易理解,因为有一个控制台窗口可以显示printf的格式化输出,但是在嵌入式系统上,我理解你必须告诉库将printf的格式化输出重定向到哪里,这就是我试图弄清楚的。
同样,根据我的研究,我已经了解到需要一些函数来实现这一点,特别是函数_write
。
我发现如何弥合printf和使用_write
函数之间差距非常困难。我希望这里有人能帮助我理解如何正确地实现printf。
如果我错过了一些文档,清楚地解释了这一点,那么请重定向我。我试着阅读newlib文档,以及GCC相关文档,但没有真正提到如何使用printf,但有很多关于如何调用printf和格式化字符串的文档,但这部分很容易。我需要知道如何从MCU的STDOUT中获取格式化字符串。
感谢大家!
1条答案
按热度按时间jhkqcmku1#
在Newlib中,您不实现库中包含的
printf()
。您只需实现一组最小的系统调用来支持库。流设备sycalls API包括open
、close
、read
和write
(或带有_r
后缀的可重入版本)-如果您使用多线程并需要每个线程errno
(在任何特定于实现的可重入要求中),则其中的可重入性非常有用。如果你只实现
stdout
(printf()
、putchar()
、puts()
等使用的流),并且只支持单个设备(通常是UART),并且不关心重定向或重入的能力,那么open
、close
和read
可以为空,write
可以直接将提供的缓冲区输出到你的低级串行I/O API:请注意,此处的
handle
未使用。对于stdout
,它将是1(stdin
= 0和stderr
= 2)。如果您希望为stdout
和stderr
使用单独的输出设备,或者如果您支持其他设备或文件系统以及fopen
或stdout
重定向,则将使用handle
参数。用于识别open
打开的蒸汽。通过忽略它所有的流输出(如fprintf()
将以相同的方式处理并输出到相同的设备);在许多情况下(其中printf()
只是获取调试输出的一种方式,或者您的应用程序没有文件系统),您不会关心。假设
write
函数,printf()
将“正常工作”(以最简单的方式),因为在引擎盖下,所有的stdio输出函数都调用write
)。缓冲和非阻塞的低电平输出功能(例如中断驱动的UART驱动器)。显然,如果你也想在
stdin
上接受 input,你应该实现一个类似的read
函数。如果你想要一个堆(
malloc()
等),你还需要实现sbrk
/sbrk_r
。我建议您至少在Newlib系统调用中实现它。Bill Gaitliff在Porting and Using Newlib in Embedded Systems中讨论了系统调用实现的更复杂的处理,而基本实现在here中讨论,而类似于上面的示例最小实现存根在Newlib documentation本身中提供。