Переопределение функции fputc при использовании набора инструментов arm-none-eabi
У нас есть STM32
C/C++ проект, и мы пересмотрели слабый fputc(int, FILE *)
функция для перенаправления printf
вывод на некоторые UART
канал.
До сих пор мы строили проект под IAR с помощью компилятора IAR. Вход через UART
работал нормально.
Теперь мы перешли к arm-none-eabi toolchain
и строим проект с g++
, Но похоже, что переопределение fputc
функция больше не связана и поэтому UART
регистрация не работает.
Как я могу заставить использование переопределенной функции printf
?
1 ответ
Просто была такая же проблема с преобразованием проекта из Keil в Cube. Нашел этот элегантный STM32 printf retarget для решения UART на GitHub (и, пожалуйста, простите копипасту):
/*# 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"
:
extern "C" int _write(int fd, char * ptr, int len)
{
HAL_UART_Transmit(&huart1, (uint8_t *) ptr, len, HAL_MAX_DELAY);
return len;
}
arm-none-eabi-
toolchain использует 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()
внутренне.