【问题标题】:STM32 printf() redirectSTM32 printf() 重定向
【发布时间】:2017-08-06 18:13:58
【问题描述】:

我有一块 STM32VL 探索板,它使用 STM32F100RB 微控制器。我正在使用 Keil uVision 5.24.2.0。我正在使用编译器选项'ARM 编译器'使用默认编译器版本 5''。

我正在尝试弄清楚如何使用/重定向它上面的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(). */

【问题讨论】:

  • 重定向到什么?
  • 抱歉 - 删除了我的答案,因为我不使用 Keil 和 Keil 库。
  • @duskwuff 有关系吗?
  • @PeterJ 是的!例如,如果 OP 想要将 printf() 重定向到半主机 I/O,那么有一个特定的过程可以完成这与将其定向到 USART 或其他什么不同的过程。
  • 更容易避免使用 printf,其次是找到一个专为这种工作设计的 printf,它没有那么重的系统后端。

标签: c embedded printf stm32


【解决方案1】:

... 如何重定向 printf()。我已经阅读了多个我需要的资料。

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

  1. __FILE 到底是做什么的?我没有看到它被使用过?

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

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

  1. 为什么__stdout 前面有两个“_”?

因为它是编译器/系统保留符号,并且这是 ISO C 标准为此类符号定义的约定。库在内部通过该符号引用标准输出流,但不实例化它 - 这是您的重定向层所做的,因此有必要定义它以供库链接。

  1. 为什么将FILE typedef 的数据类型分配给__stdout

参见上面的 (2)。

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

  1. 是否需要将代码添加到/* 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 等内容只有在您需要使用多个流设备实现对 stdio 的完全支持时才重要 可以使用 fopen() 打开的 I/O 设备例子。它们确实需要至少存在于这些最小实现中,但是因为标准库引用它们并且如果它们丢失将不会链接(尽管如果不存在替代实现,则库中可能会使用弱链接实现)。

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 版本相比,它可能要简单得多,在这种情况下,您或多或少是靠自己的;在提供所有支持之前,我已经使用 ARM-MDK 和 STM32 很长时间了,所以我没有尝试过所描述的 DevPacks 方法。

【讨论】:

  • 非常感谢您的详细回答,内容丰富且有用!
猜你喜欢
  • 1970-01-01
  • 2011-04-24
  • 2018-09-24
  • 2015-04-04
  • 2019-05-27
  • 2019-09-23
  • 2017-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多