Переопределение функции 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() внутренне.

Другие вопросы по тегам