STM32 Microcontrolador - Redirecionando printf para a porta serial

Em sistemas baseados no microcontrolador STM32, redirecionar funções de saída padrão como printf para uma porta serial permite a depuração em tempo real através de um terminal ou software de monitoramento. Este processo envolve a modificação de funções da biblioteca C padrão para que a saída seja enviada via UART em vez do console padrão.

Verificação da porta serial

Para confirmar que a comunicação serial está funcional, envie um comando como *IDN?\r\n para o microcontrolador usando um software de debug serial. Ao receber os dados, o buffer de recepção deve exibir os bytes corretos. Se o dispositivo responder com uma string como "123" dentro da rotina de interrupção de recepção, a porta serial (por exemplo, USART4) está operando corretamente.

Problemas com printf no MDK-ARM

Ao utilizar a função printf no ambiante de desenvolvimento MDK-ARM, é necessário redirecionar a saída padrão e desabilitar o modo Semihosting. Por padrão, as funções da biblioteca C apontam para dispositivos de saída do host, como o monitor do computador. Para enviar a saída para uma porta serial ou display, a função fputc deve ser redefinida.

Exemplo de redirecionamento de fputc para UART1:

#ifdef __GNUC__
  #define SAIDA_CARACTERE int __io_putchar(int caractere)
#else
  #define SAIDA_CARACTERE int fputc(int caractere, FILE *arquivo)
#endif

SAIDA_CARACTERE
{
  USART_SendData(USART2, (uint8_t) caractere);
  while (USART_GetFlagStatus(USART2, USART_FLAG_TC) == RESET);
  return caractere;
}

Soluções para desabilitar o Semihosting

O Semihosting é um mecanismo que permite que o microcontrolador comunique-se com o host durante a depuração, redirecionando operações de I/O. No entanto, ele interfere no redirecionamento de printf. Para solucionar isso, existem duas abordagens principais:

1. Usar a MicroLIB

Ativar a MicroLIB nas configurações do projeto (Target → Code Generation → Use MicroLIB) evita a inclusão de código Semihosting, simplificando o redirecionamento.

2. Adicionar código para desabilitar Semihosting manualmente

Inclua as seguintes diretivas e definições no código:

#pragma import(__use_no_semihosting)
struct __FILE
{
  int manipulador;
  // Estrutura necessária para evitar chamadas Semihosting
};

FILE __stdout;

// Definir _sys_exit() para prevenir o uso do modo Semihosting
void _sys_exit(int codigo)
{
  codigo = codigo; // Evitar avisos do compilador
}

// Redefinir fputc para UART2, assumindo que USART2 é a porta desejada
int fputc(int caractere, FILE *arquivo)
{
  USART2->DR = (uint8_t) caractere;
  while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
  return caractere;
}

Papel do Semihosting

O Semihosting é um mecanismo que permite que código em execução no microcontrolador utilize os recursos de I/O do host, como teclado e tela, através de um depurador. Isso é útil durante o desenvolvimento, pois evita a necessidade de hardware adicional para entrada e saída. No entanto, ele substitui as rotinas padrão de I/O, tornando necessário o redirecionamento explícito de funções como printf quando se deseja saída via serial.

Resumo da implementação

Para habilitar o uso de printf em um STM32 com saída via UART:

  1. Redirecione a função fputc para enviar caracteres pela porta serial desejada.
  2. Desabilite o Semihosting usando a MicroLIB ou código adicional para evitar conflitos.
  3. Garanta que a definição de __stdout e __stdin esteja correta para o ambiente.

Em projetos com múltiplas portas UART, certifique-se de que a redirecionamento aponte para a porta correta (por exemplo, USART1 em vez de USART3) para evitar travamentos. Adicione sempre sequências de fim de linha como \r\n ao usar printf para formatação adequada no terminal.

Tags: STM32 UART MDK-ARM Semihosting MicroLIB

Publicado em 6-11 21:21 por Thomas