如何让printf在STM32F103上运行?

时间:2016-09-23 15:08:44

标签: makefile microcontroller stm32 newlib

我是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

4 个答案:

答案 0 :(得分:2)

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

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

-PS

某个时候从我自己的writings复制。

答案 1 :(得分:1)

Look there。这是来自printf的{​​{1}}。但你有微控制器。因此,您可以编写自己的glib,其中printf将结果返回缓冲区,然后您将数据从缓冲区发送到UART。

vfprintf

你也可以写自己的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); } 。 Standart vsprintf非常沉重。通常使用vsprintf功能的一小部分。

答案 2 :(得分:1)

链接:How to retarget printf() on an STM32F10x?

尝试劫持_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将通过此功能(取决于您使用的库当然)。

答案 3 :(得分:0)

包含以下链接器标志:

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

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

  

半主机是一种机制,它使在ARM目标上运行的代码能够在运行调试器的主机上进行通信和使用输入/输出功能。

     

这些设施的示例包括键盘输入,屏幕输出和磁盘I / O.例如,您可以使用此机制启用C库中的函数,例如printf()和scanf(),以使用主机的屏幕和键盘,而不是在目标系统上使用屏幕和键盘。

由于您正在使用openSource工具进行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接口将适用于任何编译器,但您必须检查每个板的引脚配置。