[信息] 实战经验 | KEIL环境下printf导致程序无法执行的解决方案

[复制链接]
1503|4
STM新闻官 发表于 2025-10-15 23:56 | 显示全部楼层 |阅读模式
本帖最后由 STM新闻官 于 2025-10-15 23:57 编辑

1. 问题描述
在开发过程中,开发者常用printf函数进行串口输出调试信息,在MDK Keil环境下,客户在调试开发过程中发现,只要程序添加了printf函数调用,就会出现程序无法执行。通过调试,查看汇编,发现程序没有进入到main函数,而是停在了下面BKPT语句。当单步执行的时候,程序可以运行下去,但是全速执行,程序一直停在了BKPT语句。察看用户工程设置,没有选用MicroLIB选项。
7861768efc3d78049d.png
▲ 图1. 调试信息


显然,这是一个与应用代码无关的问题,本文介绍产生该问题的原因并给出解决方案。

2. Semihosting简介
Semihosting是一种调试技术,主要用于嵌入式系统开发。它允许嵌入式设备在运行时通过调试器与主机系统(通常是开发者的计算机)进行通信,从而实现一些复杂的输入输出操作。在STM32开发中,最常见的Semihosting应用是通过printf函数输出信息到PC的串口终端。其常规的调用路径如下图所示。

3080968efc3e66a18a.png
▲ 图2. Semihosting
当应用程序调用了printf函数,则编译器会默认启用的Semihosting功能,从而在初始化C库的时候,会执行与调试器进行交互操作的动作,应用程序是通过SVC或者BKPT这些指令与调试器进行交互,如果初始化过程中得不到调试器的响应,那么应用程序就不会往下执行。结合ARM的参考文档,既然是Semihosting引起的问题,那么ARM也提供了解决问题的方法,可以参考文档ARM: Application Builds Without Error, But Does Not Run。

3. 问题解决
针对Semihosting导致的问题,通常情况下,在编译的过程中,不使用C标准库,而使用MicroLIB库是可以解决的,但是由于客户应用程序限制,不能使用MicroLIB库,而为了调试方便,又需要使用printf函数,所以只能采取其他的解决办法,在上述ARM提供的文档中,给出使用CMSIS-Compiler pack解决该问题,经过实验,该方法方便有效,按照如下步骤即可。
使能CMSIS-Compiler设置
在Run-Time Environment窗口中,使能CMSIS-Compiler CORE组件并设置STDOUT为Custom选项,如下图所示。

2113968efc3f834e22.png
▲ 图3. 使能CMSIS-Compiler CORE component

STDOUT 输出到用户定义的接口
这种方式应该是不调用底层的标准输出接口而是调用用户定义的接口,从而避免Semihosting导致的问题。既然不再调用底层标准库的接口,那么我们需要按照ARM提供的模板实现用户接口,如下所示

3110168efc4034d14e.png
▲ 图4. 生成STDOUT用户接口


重新编译代码,下载即可正常运行。

4. 总结
本文根据客户反馈的问题,结合ARM的帮助文档,给出了printf函数导致的程序不执行的解决方案,以供参考。


 楼主| STM新闻官 发表于 2025-10-15 23:57 | 显示全部楼层
 楼主| STM新闻官 发表于 2025-10-15 23:57 | 显示全部楼层
gejigeji521 发表于 2025-10-22 10:33 | 显示全部楼层
huangcunxiake 发表于 2025-10-25 08:57 | 显示全部楼层
这方案不错
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:意法半导体(中国)投资有限公司
简介:您的嵌入式应用将得益于意法半导体领先的产品架构、技术、多源产地和全方位支持。意法半导体微控制器和微处理器拥有广泛的产品线,包含低成本的8位单片机和基于ARM® Cortex®-M0、M0+、M3、M4、M33、M7及A7内核并具备丰富外设选择的32位微控制器及微处理器。

1428

主题

1758

帖子

25

粉丝
快速回复 在线客服 返回列表 返回顶部