深究ARM串口重定向问题

在使用一块stm32开发板时,取消勾选microlib 后,使用标准c 库,发现串口重定向失效,串口不再输出printf 字符串, 感觉很奇怪,这边理清下问题的原因:

microlib 是经过优化过的c lib 库,通过microlib进行重定向的方法很简单:

#ifdef __GNUC__
  /* With GCC, small printf (option LD Linker->Libraries->Small printf
     set to 'Yes') calls __io_putchar() */
  #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
  #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */

/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE
{
  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&UartHandle, (uint8_t *)&ch, 1, 0xFFFF); 

  return ch;
}

至于为什么可以被重定向,这边找到了fputc 的源码:

int
fputc (int c, FILE *fp)
{
  int result;
  CHECK_FILE (fp, EOF);
  if (!_IO_need_lock (fp))
  result = _IO_putc_unlocked (c, fp);
  _IO_release_lock (fp);
  return result;
}

#ifndef _IO_MTSAFE_IO
#undef fputc_unlocked
weak_alias (fputc, fputc_unlocked)
#endif

其中定义了弱类型,编译器会用用户最新定义的函数覆盖掉此函数,具体可以参考3 文档。

但是如果使用ARM libc, 根据arm 官网给出的解释:

ARM provides a number of runtime C and C++ libraries, including the ARM C libraries, the Rogue Wave Standard C++ Library, and ARM C libraries.
The following runtime C and C++ libraries are provided:
The ARM C libraries
The ARM C libraries provide standard C functions, and helper functions used by the C and C++ libraries. The C libraries also provide target-dependent functions that implement the standard C library functions such as printf() in a semihosted environment. The C libraries are structured so that you can redefine target-dependent functions in your own code to remove semihosting dependencies.
The ARM libraries comply with:
The C Library ABI for the ARM Architecture (CLIBABI).
The C++ ABI for the ARM Architecture (CPPABI).

只需要在开头加上以下声明:

#pragma import(__use_no_semihosting)  
void _sys_exit(int x)
{
	x = x;

}
FILE __stdout;

struct __FILE
{
	int handle;
};

关于semihost 模式,找到一篇文章(2), 其中解释如下:

The way it is actually implemented by the tools depends upon which target CPU you are running on. With Cortex-M based MCUs, the bottom level of the C library contains a special BKPT instruction. The execution of this is trapped by the debug tools which determine what operation is being requested - in the case of a printf, for example, this will effectively be a “write character to stdout”. The debug tools will then read the character from the memory of the target board - and display it in the console window within the IDE.

简单说,就是arm 提供了一种通过debug 探针传递目标信息到host 的方式,即在开发环境中与目标平台交换信息,对于printf 来说,就是获取字符串,这种模式默认情况是开启的,如果需要重定向,需要显示声明不启用这种模式,告知编译器。

最后,关于semohost的使用:
Important notes about using semihosting

When you have linked with the semihosting library, your application will no longer work standalone - it will only work when connected to the debugger.
Semihosting operations cause the CPU to drop into “debug state”, which means that for the duration of the data transfer between the target and the host PC no code (including interrupts) will get executed on the target. Thus if you application uses interrupts, then it is normally advisable to avoid the use of semihosting whilst interrupts are active. If you still need to use printf, then you can retarget the bottom level of the C library to use an alternative communication channel, such as a UART.

Reference:

  1. http://www.keil.com/support/man/docs/armcc/armcc_chr1359124896927.htm
  2. https://community.nxp.com/thread/389156
  3. https://www.cnblogs.com/justinyo/archive/2013/03/12/2956438.html
  4. http://www.keil.com/support/man/docs/armlib/armlib_chr1358938938431.htm
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值