我们有一个STM32
C / C ++项目,并且我们重新定义了弱的fputc(int, FILE *)
函数,以便将printf
的输出重定向到某个UART
通道。
到目前为止,我们正在使用IAR compiler在 IAR 下构建项目。通过UART
的日志记录工作正常。
我们现在已切换到arm-none-eabi toolchain
,并且正在使用g++
构建项目。但是看来fputc
函数的重新定义不再链接了,因此UART
日志记录不起作用。
如何强制printf
使用重新定义的功能?
答案 0 :(得分:2)
arm-none-eabi-
工具链使用的是newlib,它使您可以重新定义_write(int fd, const void *buf, size_t count)
,然后所有stdio输出函数都将使用该接口。 fd==1
对应于stdout
,fd==2
至stderr
。您必须提供更多的存根函数,例如
void _exit(int) {
while(1)
;
}
等其中大多数都是微不足道的,但是printf()
也需要有效的_sbrk()
,因为它在内部使用malloc()
。
答案 1 :(得分:1)
将项目从Keil转换为Cube时遇到了同样的问题。在GitHub上找到了这种优雅的STM32 printf retarget to UART解决方案(请原谅复制粘贴):
iterator_base<T>::p
这可能会或可能不会在您的特定情况下起作用,但是您会收到想法...
就我而言,我必须在函数类型前面加上/*# 7- Retarget printf to UART (std library and toolchain dependent) #########*/
#if defined(__GNUC__)
int _write(int fd, char * ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
return len;
}
#elif defined (__ICCARM__)
#include "LowLevelIOInterface.h"
size_t __write(int handle, const unsigned char * buffer, size_t size)
{
HAL_UART_Transmit(&huart1, (uint8_t *) buffer, size, HAL_MAX_DELAY);
return size;
}
#elif defined (__CC_ARM)
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
#endif
// OR:
// Add syscalls.c with GCC
#ifdef __GNUC__
#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
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
return ch;
}
:
extern "C"