Este projeto é uma POC (Prova de Conceito) para demonstrar o uso de semihosting em microcontroladores ARM usando a plataforma STM32CubeIDE (versão 1.19.0).
Para este exemplo, foi utilizada a placa NUCLEO-F446RE, mas o guia pode ser utilizado para outras famílias ARM da ST.
O objetivo do projeto é mostrar:
- A configuração necessária para habilitar semihosting;
- Exemplos de leitura e escrita de arquivos no host PC via semihosting;
- Uso de
printf()para logging no console do host.
⚠️ AVISO: Este recurso de semihosting destina-se apenas a testes e depuração. Como depende do debugger, pode travar o programa e reduzir significativamente o desempenho. Use com cautela.
Semihosting é um mecanismo que permite que um microcontrolador ARM envie solicitações de entrada e saída para um computador host rodando o depurador.
Isso possibilita que funções da biblioteca C, como printf() e scanf(), usem a tela e o teclado do host, sem depender de periféricos físicos no MCU.
É especialmente útil durante o desenvolvimento, quando o hardware pode não possuir todos os recursos de entrada/saída do sistema final.
O semihosting é implementado por instruções especiais (ex.: BKPT ou SVC) que geram exceções. O depurador intercepta essas chamadas e realiza a operação no host.
Geralmente, o semihosting é invocado internamente por funções da biblioteca C, mas também pode ser chamado diretamente pela aplicação.
Referência: ARM Semihosting Documentation
Antes de iniciar, certifique-se de ter um projeto CubeIDE criado e com build sem erros.
Para habilitar semihosting, são necessários três ajustes principais, cada um acompanhado de imagem ilustrativa:
No projeto padrão do STM32CubeIDE, as funções de sistema (_write, _read, _open, _close, _lseek) estão implementadas em syscalls.c.
Para semihosting, essas funções serão sobrescritas pela biblioteca rdimon, portanto é necessário excluir syscalls.c do build:
- Clique com o botão direito no arquivo
syscalls.c; - Vá em Resource Configurations → Exclude from Build;
- Marque
DebugeReleasee confirme.
⚠️ Por que é necessário?
O arquivosyscalls.cpadrão tenta acessar periféricos inexistentes (UART, filesystem do MCU).
Removê-lo evita conflitos, permitindo que o semihosting (viardimon) implemente_write,_read,_open,_fclose, etc., corretamente.
O rdimon implementa a interface de semihosting para o linker. Para habilitar:
-
Vá em Propriedades → C/C++ Build → Settings → MCU/MPU GCC Linker → Miscellaneous;
-
No campo Other flags, adicione:
-specs=rdimon.specs -lc -lrdimon
Isso indica ao linker que a aplicação deve usar a biblioteca de semihosting e sobrescrever as funções padrão de I/O.
Para habilitar o semihosting corretamente durante a depuração, siga os passos abaixo:
- Selecionar o depurador ST-LINK (OpenOCD)
- Abra Run → Debug Configurations → Debugger;
- Escolha ST-LINK (OpenOCD) como depurador.
- Adicionar comando de inicialização para semihosting
-
Na mesma janela, vá para a aba Startup;
-
No campo Initialization Commands, adicione o comando e aplique as alterações:
monitor arm semihosting enable
-
Esse comando instrui o GDB a habilitar o semihosting durante toda a sessão de depuração, permitindo que funções como
printf()efopen()interajam com o host PC.
Este firmware demonstra o uso do semihosting para comunicação entre o MCU e o PC host, permitindo que o microcontrolador interaja diretamente com o sistema de arquivos do computador durante a execução.
O projeto realiza as seguintes operações:
- Utiliza
printf()para enviar mensagens ao console do host; - Lê um arquivo de texto localizado no PC host e carrega seu conteúdo na RAM do MCU;
- Grava um novo arquivo de texto no PC host, utilizando dados armazenados na flash do MCU.
Tudo isso é feito de forma transparente, sem necessidade de interfaces físicas de comunicação adicionais — apenas com o semihosting habilitado durante o debug.
⚠️ Importante:
Antes de executar este exemplo, é necessário configurar corretamente a macroROOT_PATH
com o caminho absoluto da pasta raiz do seu projeto no PC host.Exemplo:
#define ROOT_PATH "C:/Users/SeuUsuario/Projects/semihosting-example/"Isso garante que o firmware consiga localizar e abrir/gravar o arquivo de texto durante a execução.
Abaixo está a saída esperada no console do CubeIDE durante a execução:

Esta função demonstra como o MCU, utilizando semihosting, pode abrir e ler um arquivo de texto armazenado no PC host.
Ela tenta abrir o arquivo definido em NAME_FILE_READ, lê seu conteúdo linha por linha e exibe tudo no console por meio de printf().
Se o arquivo não for encontrado, a função mostra uma mensagem de erro e interrompe a execução para facilitar o debug.
Esta função demonstra como o MCU, por meio do semihosting, é capaz de criar e escrever um arquivo de texto diretamente no PC host.
O arquivo definido em NAME_FILE_WRITE é aberto (ou criado, caso não exista) e recebe os dados armazenados no array data[].
Após a conclusão da escrita, o arquivo pode ser encontrado na pasta Output — especificada pela macro NAME_DIR_WRITE — dentro do diretório raiz do projeto.




