问题现象:
每次程序下载后至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/
程序在下载到FLASH后无法运行,原因是MCU进入了半主机模式,每次调用I/O时会触发超级用户模式异常,导致程序暂停。半主机模式在没有调试器时会导致崩溃。解决方案是禁用半主机模式,但发现armcompilerV5/V6版本间接口不一致导致禁用失效。通过适配不同版本的禁用代码解决了问题。
1656

被折叠的 条评论
为什么被折叠?



