- Introdução ao microcontrolador ARM Cortex M3
- O design do Processador Cortex-M3 e seus periféricos
- Usando o STM32CubeIDE criaremos nosso projeto Hello World
- Usando o STM32CubeIDE como imprimiremos “Hello World” no Target?
- Modos Operacionais do Processador ARM Cortex-M3
- Níveis de Acesso ao Processador ARM Cortex-M3
- Os Registradores do Núcleo (Core) do Processador ARM Cortex-M3
- Alguns Registradores do Núcleo (Core) do Processador ARM Cortex-M3 na Pratica
- Usando a GNU Compiler Collection (GCC) para ARM Cortex-M3
- Memória do Microcontrolador STM32F103C8T6
Esse é o quarto artigo de uma nova série escrita pelo engenheiro Ismael Lopes da Silva, exclusivamente para o Portal Embarcados. Nessa série focarei no Microcontrolador da STMicroelectronics, o MCU STM32F103C8T6, que é um ARM Cortex-M3. Os pré-requisitos para uma boa compreensão dos artigos é ter o domínio da Linguagem C Embedded e conceitos de eletrônica.
Usando o STM32CubeIDE como imprimiremos “Hello World” no Target?
Como vamos imprimir uma mensagem no dispositivo target (MCU), se não temos um Display conectado a placa/MCU? Isso será explicado detalhadamente nesse artigo, então, vamos editar o arquivo main.c para termos uma aplicação mínima, conforme mostrado a seguir. Apenas adicionamos um cabeçalho para funções padrões em “C”, e também a função “printf”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
/******************************************************************************** * @file : main.c * @author : Auto-generated by STM32CubeIDE * @brief : Main program body ****************************************************************************** * @attention * * <h2><center>© Copyright (c) 2019 STMicroelectronics. * All rights reserved.</center></h2> * * This software component is licensed by ST under BSD 3-Clause license, * the "License"; You may not use this file except in compliance with the * License. You may obtain a copy of the License at: * opensource.org/licenses/BSD-3-Clause * *******************************************************************************/ #if !defined(__SOFT_FP__) && defined(__ARM_FP) #warning "FPU is not initialized, but the project is compiling for an FPU. Please initialize the FPU before use." #endif #include<stdio.h> int main(void) { printf("Hello World\n"); for(;;); } |
A solução vem do processador ARM Cortex-M3/M4/M7 ou mais recente. Nesses processadores podemos fazer a função “printf” trabalhar, usando o pino SWO da interface de depuração SWD. SWO significa “Serial Wire Output” e SWD significa “Serial Wire Debug”. SWD é um protocolo a dois fios (SWIO e SWCLK) para acessar a interface ARM de depuração, e um fio para acessar o recurso de rastrear (Trace), usando a linha SWO.
Dentro do nosso processador ARM Cortex-M3, há um periférico chamado ITM (Instrumentation Trace Macrocell). ITM é uma fonte para rastrear, usando a função “printf”. Podemos rastrear eventos da aplicação e também pode gerar diagnóstico de informação do sistema.
O conector SWD tem três pinos, na qual dois pinos são usados para depurar e um é usado para rastrear (trace). Rastrear (trace) significa obter informação/mensagem do processador. Usando a interface SWD podemos programar a memória Flash do MCU, podemos acessar regiões de memória, adicionar breakpoints, rodar e parar a CPU e também podemos usar a SWV (Serial Wire Viewer) para usar “printf” no processo de rastreamento (tracing).
Dentro do ITM há um buffer serial (FIFO), então, o que faremos é escrever uma mensagem (alguns bytes) usando a função “printf”, e colocaremos dentro desse buffer. A saída desse buffer é conectada ao pino SWO, que está conectado ao circuito do ST Link V2, e que está conectado ao target (MCU), então, podemos capturar a mensagem usando nosso STM32CubeIDE. Nem todas as ferramentas de depuração permitem usar esse recurso, mas, o STM32CubeIDE tem disponível essa funcionalidade.
Modificações de software para capturar “printf”
Na pasta “Src”, no “Project Explorer”, temos um arquivo denominado syscalls.c, que deve ser editado para que podemos usar a função “printf”, portanto, após as diretivas dessa função adicione o seguinte trecho de programa. Basicamente nesse trecho temos outras diretivas e a função ITM_SendChar, que habilitará o uso da função “printf”.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////////// // Implementation of printf like feature using ARM Cortex M3/M4/ ITM functionality // This function will not work for ARM Cortex M0/M0+ // If you are using Cortex M0, then you can use semihosting feature of openOCD ////////////////////////////////////////////////////////////////////////////////////////////////////// //Debug Exception and Monitor Control Register base address #define DEMCR *((volatile uint32_t*) 0xE000EDFCU ) /* ITM register addresses */ #define ITM_STIMULUS_PORT0 *((volatile uint32_t*) 0xE0000000 ) #define ITM_TRACE_EN *((volatile uint32_t*) 0xE0000E00 ) void ITM_SendChar(uint8_t ch) { //Enable TRCENA DEMCR |= ( 1 << 24); //enable stimulus port 0 ITM_TRACE_EN |= ( 1 << 0); // read FIFO status in bit [0]: while(!(ITM_STIMULUS_PORT0 & 1)); //Write to ITM stimulus port0 ITM_STIMULUS_PORT0 = ch; } |
O trecho acima encaixamos conforme ilustrado na figura 1.
Ainda no arquivo syscalls.c, temos que modificar a função “_write”, conforme mostrado a seguir, e ilustrado na figura 2.
1 2 3 4 5 6 7 8 9 10 11 |
__attribute__((weak)) int _write(int file, char *ptr, int len) { int DataIdx; for (DataIdx = 0; DataIdx < len; DataIdx++) { //__io_putchar(*ptr++); ITM_SendChar(*ptr++); } return len; } |
Após as modificações salve o arquivo syscalls.c.
Então, como funcionará? A biblioteca padrão implementada chamará a função “_write” que foi modificada em syscalls.c. A função “_write” é chamada, e a mensagem é recebida através de um ponteiro, portanto, apenas enviamos os dados para o FIFO do ITM. A função escreve para dentro do buffer (FIFO) e do FIFO os dados vem através da linha SWO, passando pelo circuito do ST-LINK V2 e capturada pelo STM32CubeIDE, sendo imprimida no console do SWV (Serial Wire Viewer).
Na janela “Projetc Explorer”, clique com o botão direito do mouse sobre o projeto “01HelloWorld” e selecione “Debug As” e depois “Debug Configuration”. Selecione a aba [Debbuger] e habilite a Serial Wire Viewer (SWV), conforme ilustrado na figura 3. O core clock deve ser 8,0MHz, porque ainda não configuramos o clock do sistema. Depois clique no botão [Apply] e no [Debug].
Modificações de hardwarepara capturar “printf”
O ST-LINK V2 é um programador/depurador para os microcontroladores STM8 e STM32. As interfaces SWIM (Single Wire Interface Module) e JTAG/SWD (Serial Wire Debugging) facilitam a comunicação com qualquer microcontrolador STM8 ou STM32.
A figura 5 ilustra os conectores e o LED que indica atividade de comunicação.
- A = Conector JTAG e SWD para MCU STM32
- B = Conector SWIM para MCU STM8
- C = LED de atividade de comunicação
Pino | Função ST LINK V2 | Função SWD |
1 | MCU VDD (3,3V) | |
2 | MCU VDD (3,3V) | |
3 | JTAG TRST | |
4 | GND | |
5 | JTAG TDO | |
6 | GND | |
7 | JTAG TMS, SW IO | Depurar (Debugging) |
8 | GND | |
9 | JTAG TCK, SW CLK | Depurar (Debugging) |
10 | GND | |
11 | Não conectado | |
12 | GND | |
13 | JTAG TDI, SWO | Rastrear (Tracing) |
14 | GND | |
15 | NRST | |
16 | GND | |
17 | Não conectado | |
18 | GND | |
19 | VDD (3,3V) | |
20 | GND |
Tabela 1 – Pinos do conector JTAG e SWD
O projeto da placa Blue Pill, que contém o nosso MCU STM32F103C8T6, não vem com a ligação da linha SWO entre o dispositivo target e o ST Link V2, portanto, temos que implementá-la para que a função “printf” seja capturada pelo STM32CubeIDE. Conectaremos o pino PB3 do MCU, que é o pino 39 do STM32F103C8T6, ao pino 13 do ST Link V2, conforme ilustrado na figura 6.
Modificações de sofware e hardwareprontas! Ajustes finais para capturar “printf”
As mensagens que são capturadas através da função “printf” não são visualizadas na janela “Console”. Temos que habilitar a visualização da janela “SWV ITM Console”, e depois fazer algumas configurações finais para depurar e capturar as mensagens oriundas do “printf”.
Para habilitar a janela “SWV ITM Console” a aplicação deve ser sendo depurada (debbuging), porque se não estivermos nesse contexto, o STM32CubeIDE não nos dá as opções para configurá-la. Vamos novamente limpar, compilar e depurar a aplicação para finalizar os passos por completo.
Segue a sequencia para deixarmos a aplicação em ordem:
- Na janela “Projetc Explorer”, clique com o botão direito do mouse sobre o projeto “01HelloWorld” e selecione “Clean Project”. Isso limpa a compilação anterior;
- Na janela “Projetc Explorer”, clique com o botão direito do mouse sobre o projeto “01HelloWorld” e selecione “Build Project”. Isso compila a aplicação;
- Na janela “Projetc Explorer”, clique com o botão direito do mouse sobre o projeto “01HelloWorld” e selecione “Debug As” e depois “STM32 Cortex-M C/C++ Application”. Isso faz com que o STM32CubeIDE chavear para a perspectiva de depuração, conforme ilustrado na figura 7. Lembrando que já configuramos a ferramenta de depuração, sendo assim, habilitamos o SWV, conforme ilustrado na figura 3. Clique no botão [Switch] para depurar.
- Na janela de código será mostrada o arquivo main.c, já destacando um breakpoint na linha onde temos a função ‘printf(“Hello World\n”);’. No menu “Window”, parte superior da tela, selecione “Show View”, depois “SWV” e “SWV ITM Data Console”. Observe que na parte inferior da tela, foi aberto a janela “SWV ITM Data Console”;
- Na janela “SWV ITM Data Console” tem um botão chamado “configure trace”. É o primeiro botão. Clique nesse botão para configurarmos a SWV.
Na janela “SWV Serial Wire Viewer Settings”, na seção inferior chamada “ITM Stimulus Ports”, apenas selecione a porta 0, habilitando-a, conforme ilustrado na figura 8. Clique no botão [OK] para concluir a configuração;
- Na janela “SWV ITM Data Console” tem um botão chamado “start trace”. É o segundo botão. Clique nesse botão para iniciar o rastreamento (tracing), portanto, capturar a mensagem de “prinft”.
- Para capturamos a mensagem pressione a tecla [F8] ou clique no botão “Resume”, parte superior da tela. O processo de depuração será resumido, então, podemos ver que a mensagem foi capturada. Na janela “SWV ITM Data Console” podemos ver “Hello World”, conforme ilustrado na figura 10.
- Para encerrar o processo de depuração pressione a tecla [CTRL+F2] ou clique no botão “terminate”, parte superior da tela.