问题现象:
每次程序下载后至FLASH 后程序无法运行。连接仿真器后每次运行会停在固定一段汇编代码上。点击继续运行后可以继续运行后续代码。
每次会停在固定的一条指令上,通过反汇编确定,停在了如下代码上:
发现这条语句来自于编译器库函数 _sys_command_string()。
问题原因:
1.半主机模式
编译器之所以链接了这段函数,是因为MCU进入一种被称为半主机( semihosting )的状态。允许目标应用程序与主机I / O设备进行交互(因此被称为半主机)。
如下的工作流程,就是MCU在半主机状态下的流程:
每次程序调用任何I / O时,都会有supervisor 调用异常,该异常由主机端的调试器(半主机服务器)处理。
这种方法有两个缺点:
- 当处理器处于超级用户模式时,用户应用程序将暂停并等待执行完成。这对于实时应用是不可接受的。
- 没有调试器(通过EDCL或从ROM加载独立的应用程序),就没有半主机服务器。每次调用I / O函数都会导致崩溃。而在程序初始化期间,始终会有对服务器的调用,这意味着程序将一直会崩溃。
因此常见的处理方法会禁用半主机模式。arm compiler V5 编译器提供的库函数提供了禁用接口。
2. arm compiler V5/V6
其实在出问题的工程中也调用了这个接口,但是依然存在这种问题。分析发现,是arm compiler V5/V6 编译器版本接口不一致导致的问题。
在原来的禁用代码中添加对编译器的适配语句即可解决这个问题。
#if __ARMCC_VERSION >= 6000000
__asm(".global __use_no_semihosting");
#elif __ARMCC_VERSION >= 5000000
#pragma import(__use_no_semihosting)
#else
#error Unsupported compiler
#endif
参考资料:
https://mklimenko.github.io/english/2018/11/02/disable-semihosting/