STM32 printf() 重定向

STM32 printf() redirect

我有一个 STM32VL 探索板,它使用 STM32F100RB 微控制器。我正在使用 Keil uVision 5.24.2.0。我正在使用编译器选项“ARM 编译器 'Use default compiler version 5'”。

我正在想办法 use/redirect printf() 函数。

我了解 UART 初始化过程,但我真的很难理解如何重新定向 printf()。我已经阅读了多个我需要的来源。

考虑 http://www.keil.com/forum/60531/ 处的以下示例:

#include <stdio.h>

struct __FILE
{
  int handle;
  /* Whatever you require here. If the only file you are using is */
  /* standard output using printf() for debugging, no file handling */
  /* is required. */
};

/* FILE is typedef’d in stdio.h. */
FILE __stdout;

int fputc(int ch, FILE *f)
{
  /* Your implementation of fputc(). */
  return ch;
}

int ferror(FILE *f)
{
  /* Your implementation of ferror(). */
  return 0;
}

void test(void)
{
  printf("Hello world\n");
}
  1. __FILE 究竟是做什么的?我没有看到它被使用。
  2. 为什么__stdout前面有两个'_'?
  3. 为什么 FILE typedef 数据类型被分配给 __stdout
  4. 是否需要添加代码到/* Your implementation of fputc(). */

... how to re-direct printf(). I have read multiple sources that I need to.

如果您正在使用需要重新定位的函数(printf() 是其中之一),您只需要重新定位库。

  1. What exactly does __FILE do? I do not see it used?

在这种情况下,什么都没有;它只需要在那里符合标准库 stdio 函数签名。并解析对FILE类型对象的引用(例如标准库中的stdout)。

如果您要支持多个流设备,则需要此结构并且可以自定义。

  1. Why does __stdout have two '_' before it?

因为它是 compiler/system 保留符号,这是 ISO C 标准为此类符号定义的约定。在内部,库通过该符号引用 stdout 流,但不实例化它 - 这是您的重定向层所做的,因此有必要为库定义它 link.

  1. Why is the FILE typedef'd data type get assigned to __stdout?

参见上面的 (2)。

标准流是 stdout、stdin 和 stderr,printf 输出到 stdout,(本质上 printf()fprintf() 的包装器,但隐含地带有 FILE 参数作为预定义的 stdout 流;这是实例化预定义流的地方。

  1. Does code need to be added to /* Your implementation of fputc(). */?

这就是评论所暗示的!这是您需要显式实现以支持 printf() 的唯一函数。例如,如果您已经有串行 I/O 代码输出到 UART,一个可行的极简实现是:

int fputc(int ch, FILE *f)
{
  f = f ; // unused warning prevention

  uartOutCh( ch ) ;  // your character output function.

  return ch;
}

就这么简单 - 所有 FILE__stdout 等东西只有在您需要使用多个流设备 I/O 实现对 stdio 的完全支持时才重要例如,可以使用 fopen() 打开。它们确实需要至少存在于这些最小的实现中,但是因为标准库引用它们并且如果它们丢失则不会 link (尽管库中可能有 weak-link 实现如果使用不存在替代实现)。

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0378g/chr1358938930366.html 中描述了重定向 C 库的基础知识。

http://www.keil.com/pack/doc/compiler/RetargetIO/html/index.html 中描述了包括 UART 支持在内的更复杂的重定向实现。通过 "DevPacks" 的大量开箱即用支持可用于许多 iof 目标。与以前的 uVision/MDK-ARM 版本相比,它可能要简单得多,您或多或少都是自己做的;我没有尝试过描述的 DevPacks 方法,因为在提供所有支持之前我已经使用 ARM-MDK 和 STM32 很长时间了。