Embedded Tutorials Logo

Contents:

  • Getting Started
  • Arduino Basics Tutorial
  • STM32 Basics Tutorial
    • Basic Setup
    • GPIO
    • USB
    • SWD
      • Debug using SWD
      • Print using SWD
    • UART
    • Timer
  • Intermediate Tutorial
  • Highlights
Embedded Tutorials
  • STM32 Basics Tutorial
  • SWD
  • Print using SWD
  • Edit on GitHub

Print using SWD

Contents

  • 1. Introduction

  • 2. Overwrite printf Callback Function

  • 3. Update Makefile or CMakeLists.txt

  • 4. Update main.c

  • 5. Open SWV on STM32CubeProgrammer

    • 5.1. Using STM32CubeProgrammer GUI

    • 5.2. Using STM32CubeProgrammer CLI

Attention

ITM SWV Console does not work using our duplicate ST-Link V2 adapter. So using bluepill, USB is used for printf in our case.

Warning

SWV does not work in STM32F407VG-DISC1 board if you use PB3 pin because it is connected to SWO pin of ST-Link.

1. Introduction

SWD also can be used to print data. But we cannot get them normally. We need speacial program to see which is Serial Wire Viewer (SWV). STM32CubeProgrammer has SWV. Download it from installation.

In order to trace information, Instrumentation Trace Macrocell (ITM) is used in ARM processors. It uses SWO pin for tracing.

2. Overwrite printf Callback Function

  • Generate baisc code.

Important

ITM uses SWO, so select Debug option as Trace Asynchronous SW in STM32CubeMX.

swo_config_cubemx.webp
  • Create a new file printf_conf.c in Core/Src folder.

  • Add the following code to the file:

    printf_conf.c
     1#include "stm32f4xx_hal.h" // for stm32f4
     2
     3 int _write(int file, char *data, int len)
     4 {
     5   for (int i = 0; i < len; ++i)
     6   {
     7     ITM_SendChar(data[i]);
     8   }
     9   return len;
    10 }
    

3. Update Makefile or CMakeLists.txt

  • Add printf_config.c to source.

    C_SOURCES = \
    ... \
    ... \
    Core/Src/printf_conf.c
    
    # Add sources to executable
    target_sources(${CMAKE_PROJECT_NAME} PRIVATE
       # Add user sources here
       Core/Src/printf_conf.c
    )
    
  • Add -u _printf_float flag.

    Add to LDFLAGS.

    LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections
    LDFLAGS += -u _printf_float
    

    Create target_link_options at the bottom.

    # Add compiler flags
    target_link_options(${CMAKE_PROJECT_NAME} PRIVATE
        -u _printf_float
    )
    

4. Update main.c

  • Open Core > Src > main.c. Add stdio.h header.

    /* Private includes ----------------------------------------------------------*/
    /* USER CODE BEGIN Includes */
    #include <stdio.h>
    /* USER CODE END Includes */
    
  • Update main function to print “Hello World” over SWD.

    /* USER CODE BEGIN 2 */
    uint32_t n = 0;
    /* USER CODE END 2 */
    /* Infinite loop */
    /* USER CODE BEGIN WHILE */
    while (1)
    {
      printf ("Hello World! %lu\n", n++);
      HAL_Delay(100);
      /* USER CODE END WHILE */
      /* USER CODE BEGIN 3 */
    }
    /* USER CODE END 3 */
    
  • Build and flash.

5. Open SWV on STM32CubeProgrammer

5.1. Using STM32CubeProgrammer GUI

  • Open STM32CubeProgrammer.

  • Connect your microcontroller to your PC using USB cable through ST-Link. If you use external debugger like JLink or ST-Link adapter, connect it as:

    • SWCLK of microcontroller to SWCLK of debugger.

    • SWDIO of microcontroller to SWDIO of debugger.

    • SWO of microcontroller to SWO of debugger.

    • NRST of microcontroller to NRST of debugger. (Optional, only if you want to hard reset microcontroller using debugger)

    • GND of microcontroller to GND of debugger.

    • 3V3 of microcontroller to 3V3 of debugger.

  • Click on Connect.

  • Click on SWV.

  • Set Core Clock to the microcontroller clock frequency configured in STM32CubeMx. It is 168MHz in this case.

  • Click on Start.

You can see the message “Hello World” on the SWV continously.

swv_on_cubeprogrammer.webp

Do not be confused that I used 80MHz in clock frequency. I used different device at the time of this demo. Use your own.

5.2. Using STM32CubeProgrammer CLI

  • Use the following command to open SWV:

    # STM32_Programmer_CLI -c port=swd -swv freq=<HCLK_freq_in_MHz> portnumber=0
    STM32_Programmer_CLI -c port=swd -swv freq=168 portnumber=0
    
  • Then press R to reset and start. You can see the message “Hello World” on the terminal continously.

  • Press S to stop and E to exit.

  • Add STM32_Programmer_CLI command at the bottom of Makefile or CMakeLists.txt.

    1# Open SWV
    2swv:
    3	STM32_Programmer_CLI -c port=swd -swv freq=168 portnumber=0
    
    # Open SWV
    add_custom_target(swv
       COMMAND STM32_Programmer_CLI -c port=swd -swv freq=168 portnumber=0
    )
    
Previous Next

© Copyright 2024 - 2025, Robotics Club, Pulchowk Campus.

Built with Sphinx using a theme provided by Read the Docs.