如何让printf在STM32F103上工作?

How to make printf work on STM32F103?

我是STM32F103世界的新手。我有一个 STM32F103 的演示代码,我正在使用 arm-none-eabi 来编译它。

我尝试了在 Google 上可以找到的内容,但目前没有任何效果。我已经花了三天时间解决这个问题。

谁能给我一个运行良好的 printf 演示代码?

我的 makefile 的一部分:

CFLAG   = -mcpu=$(CPU) -mthumb -Wall -fdump-rtl-expand -specs=nano.specs --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group
LDFLAG  = -mcpu=$(CPU) -T ./stm32_flash.ld -specs=nano.specs --specs=rdimon.specs   -Wl,--start-group -lgcc -lc -lm -lrdimon -Wl,--end-group

Look there。这是来自 glibprintf。但是你有微控制器。所以你应该写自己的 printf,其中 vfprintf 将 return 结果放入缓冲区,接下来你将数据从缓冲区发送到 UART。有点

void printf( const char * format, ... )
{
  char buffer[256];
  va_list args;
  va_start (args, format);
  vsprintf (buffer,format, args);
  send_via_USART1 (buffer);
  va_end (args);
}

你也可以自己写vsprintf。标准 vsprintf 很重。通常使用 vsprintf 特征的一小部分。

编写自己的 printf 实现是一个选项,而且可能是我最推荐的选项。从标准库实现中获得一些灵感并编写您自己的版本,只为满足您的要求。通常,您要做的是,首先重新定位一个 putc 函数以通过您的串行接口发送 char 。然后使用 putc 自定义实现覆盖 printf 方法。也许,一种非常简单的方法是通过递归调用 putc 函数来按字符发送字符串。

最后但同样重要的是,您可以找到一些轻量级 printf 实现。这些轻量级实现提供的代码大小和功能集介于自定义编写的 printf 函数和常用标准 printf 函数(又名野兽)之间。我最近尝试了这个 Tiny Printf 并且非常满意它在 ARM 内核上的内存占用和所需执行周期数方面的性能。

-PS

前一段时间从我自己的 writings 复制而来。

Link:

尝试像这样劫持 _write 函数:

#define STDOUT_FILENO   1
#define STDERR_FILENO   2

int _write(int file, char *ptr, int len)
{
    switch (file)
    {
    case STDOUT_FILENO: /*stdout*/
        // Send the string somewhere
        break;
    case STDERR_FILENO: /* stderr */
        // Send the string somewhere
        break;
    default:
        return -1;
    }
    return len;
}

原始的 printf 将通过此功能(当然取决于您使用的库)。

通过包含以下链接器标志:

LDFLAGS   += --specs=rdimon.specs -lc -lrdimon

您似乎正在尝试使用所谓的 半主机。您是在告诉链接器包含系统调用库。

Semihosting is a mechanism that enables code running on an ARM target to communicate and use the Input/Output facilities on a host computer that is running a debugger.

Examples of these facilities include keyboard input, screen output, and disk I/O. For example, you can use this mechanism to enable functions in the C library, such as printf() and scanf(), to use the screen and keyboard of the host instead of having a screen and keyboard on the target system.

由于您使用开源工具进行 STM32 开发(Makefile 和 arm-none-eabi),我假设您也在使用 openOCD 来对您的程序进行编程微控制器。 openOCD 还要求您使用以下命令启用半主机:

arm semihosting enable

您可以在 openOCD 脚本的命令中确保终止配置阶段并使用 'init' 命令进入 运行 阶段。下面是一个openOCD脚本的例子(适用于STM32F103):

 source [find target/stm32f1x.cfg]
 init
 arm semihosting enable

此处提到的其他解决方案,其中您将 fputc() 函数重新定位到 UART 接口也将起作用并且可能。半主机将适用于所有最新的 ARM Cortex-M,但需要一些编译器和调试器配置(见上文)。将 fputc() 函数重新定位到 UART 接口将适用于任何编译器,但您必须检查每个板的引脚配置。