stm32 不使用MircoLib情况下使用printf方法

不使用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;
}

 

posted @ 2021-12-16 11:48  小小小p鱼  阅读(2161)  评论(0编辑  收藏  举报