不使用Microlib导致卡死的原理
在使用CubeMX初始化代码时,生成的工程默认是使用Microlib的,正常情况下,在STM32CubeMX通过成的.s文件里可以看到一个__main函数,这个就是microlib的入口地址,他会完成创建栈空间,创建堆空间,初始化用户可能用到的系统库等初始化动作,最后跳转到我们熟悉的main,当使用Microlib时,__main链接的是Microlib,当不使用Microlib时,__main链接的是标准库的C/C++;
至此,还并没有出现什么问题,但是,一旦在程序中调用printf等函数时,会让MCU进入半主机模式,进而程序会在__main位置卡死,这也就是为什么程序正常编译正常烧录正常调试,但是运行不起来而且Debug卡死在__main位置的原因。
使用C标准库(stdio.h)中的函数,例如printf()之类的函数,会进入半主机模式,发生软件异常,会导致程序无法运行。半主机是这么一种机制,它使得在ARM目标上跑的代码,如果主机电脑运行了调试器,那么该代码可以使用该主机电脑的输入输出设备。 这点非常重要,因为开发初期,可能开发者根本不知道该 ARM 器件上有什么输入输出设备,而半主基机制使得你不用知道ARM器件的外设,利用主机电脑的外设就可以实现输入输出调试。 所以要利用目标 ARM器件的输入输出设备,首先要关掉半主机机制。然后再将输入输出重定向到 ARM 器件上。
解决办法:
1、使用Microlib
2、关闭标准库下的半主机模式
这里我们就学习一下如何不使用Microlib,关闭半主机模式
在main.c文件或者其他任何一个文件中添加如下代码段
#pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x = x; }
void _ttywrch(int ch)
{
ch = ch;
}
//重定义fputc函数 int fputc(int ch, FILE *f) { HAL_UART_Transmit(&DEBUG_UART, (uint8_t *)&ch, 1, 0x200); //根据使用的库重定向 return ch; }