Skip to main content
Associate
January 11, 2025
Question

Viewing SWO without STM32CubeIDE

  • January 11, 2025
  • 1 reply
  • 677 views

For reasons described in this post, I cannot run a program from the IDE. Nevertheless, I found a workaround. I start a ST-LINK_gdbserver and connect to it from another terminal:

$ opt/st/stm32cubeide_1.17.0/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.linux64_2.2.0.202409170845/tools/bin/ST-LINK_gdbserver -p 61234 -l 1 -d -z 61235 -a 4000000 -b 2 -t -s -cp /opt/st/stm32cubeide_1.17.0/plugins/com.st.stm32cube.ide.mcu.externaltools.cubeprogrammer.linux64_2.2.0.202409170845/tools/bin -m 0 -k -v
$ arm-none-eabi-gdb STM32CubeIDE/smoke_alarm_2/wave/Debug/wave.elf

(gdb) target remote localhost:61234
(gdb) monitor reset
(gdb) continue

The program works fine, but I cannot seem to succeed in viewing SWO.

I tried using netcat, telnet and wireshark to see port 61235:

$ nc localhost 61235
$ telnet localhost 61235

I got no output.

 

I also tried using STM32CubeProgrammer with GUI. The connection works fine. I go to Serial Wire Viewer tab, set clock frequency, press Start, but nothing is printed.

 

This is my main.c:

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file : main.c
 * @brief : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define NS 128

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
DAC_HandleTypeDef hdac;
DMA_HandleTypeDef hdma_dac_out1;

TIM_HandleTypeDef htim2;

/* USER CODE BEGIN PV */

uint32_t Wave_LUT[NS] = {
 2048, 2149, 2250, 2350, 2450, 2549, 2646, 2742, 2837, 2929, 3020, 3108, 3193, 3275, 3355,
 3431, 3504, 3574, 3639, 3701, 3759, 3812, 3861, 3906, 3946, 3982, 4013, 4039, 4060, 4076,
 4087, 4094, 4095, 4091, 4082, 4069, 4050, 4026, 3998, 3965, 3927, 3884, 3837, 3786, 3730,
 3671, 3607, 3539, 3468, 3394, 3316, 3235, 3151, 3064, 2975, 2883, 2790, 2695, 2598, 2500,
 2400, 2300, 2199, 2098, 1997, 1896, 1795, 1695, 1595, 1497, 1400, 1305, 1212, 1120, 1031,
 944, 860, 779, 701, 627, 556, 488, 424, 365, 309, 258, 211, 168, 130, 97,
 69, 45, 26, 13, 4, 0, 1, 8, 19, 35, 56, 82, 113, 149, 189,
 234, 283, 336, 394, 456, 521, 591, 664, 740, 820, 902, 987, 1075, 1166, 1258,
 1353, 1449, 1546, 1645, 1745, 1845, 1946, 2047
};

uint8_t toggleSound = 0;
uint8_t isSoundEnabled = 0;

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_DAC_Init(void);
static void MX_TIM2_Init(void);
/* USER CODE BEGIN PFP */
static void Debug_Init(void);
/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

int _write(int file, char *ptr, int len) {
 for (int i = 0; i < len; i++) {
 ITM_SendChar((*ptr++));
 }
 return len;
}


/* USER CODE END 0 */

/**
 * @brief The application entry point.
 * @retval int
 */
int main(void)
{

 /* USER CODE BEGIN 1 */

 /* USER CODE END 1 */

 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

 /* USER CODE BEGIN Init */

 /* USER CODE END Init */

 /* Configure the system clock */
 SystemClock_Config();

 /* USER CODE BEGIN SysInit */

 /* USER CODE END SysInit */

 /* Initialize all configured peripherals */
 MX_GPIO_Init();
 MX_DMA_Init();
 MX_DAC_Init();
 MX_TIM2_Init();
 /* USER CODE BEGIN 2 */
 Debug_Init();
 HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)Wave_LUT, 128, DAC_ALIGN_12B_R);
 HAL_TIM_Base_Start(&htim2);
 LL_TIM_DisableUpdateEvent(htim2.Instance);

 printf("Hello World!\n");

 /* USER CODE END 2 */

 /* Infinite loop */
 /* USER CODE BEGIN WHILE */

 uint8_t press = 0;
 while (1)
 {
	 printf("Hello!\n");
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */
	 if (toggleSound) {
		 toggleSound = 0;
		 if (isSoundEnabled)
			 LL_TIM_DisableUpdateEvent(htim2.Instance);
		 else
			 LL_TIM_EnableUpdateEvent(htim2.Instance);
		 isSoundEnabled = !isSoundEnabled;
		 press++;
	 }
 }
 /* USER CODE END 3 */
}

/**
 * @brief System Clock Configuration
 * @retval None
 */
void SystemClock_Config(void)
{
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

 /** Configure the main internal regulator output voltage
 */
 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

 /** Initializes the CPU, AHB and APB buses clocks
 */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
 RCC_OscInitStruct.MSIState = RCC_MSI_ON;
 RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 Error_Handler();
 }

 /** Configure the SYSCLKSource, HCLK, PCLK1 and PCLK2 clocks dividers
 */
 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK3|RCC_CLOCKTYPE_HCLK
 |RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1
 |RCC_CLOCKTYPE_PCLK2;
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.AHBCLK3Divider = RCC_SYSCLK_DIV1;

 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
 {
 Error_Handler();
 }
}

/**
 * @brief DAC Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_DAC_Init(void)
{

 /* USER CODE BEGIN DAC_Init 0 */

 /* USER CODE END DAC_Init 0 */

 DAC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN DAC_Init 1 */

 /* USER CODE END DAC_Init 1 */

 /** DAC Initialization
 */
 hdac.Instance = DAC;
 if (HAL_DAC_Init(&hdac) != HAL_OK)
 {
 Error_Handler();
 }

 /** DAC channel OUT1 config
 */
 sConfig.DAC_SampleAndHold = DAC_SAMPLEANDHOLD_DISABLE;
 sConfig.DAC_Trigger = DAC_TRIGGER_T2_TRGO;
 sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
 sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_DISABLE;
 sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
 if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN DAC_Init 2 */

 /* USER CODE END DAC_Init 2 */

}

/**
 * @brief TIM2 Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_TIM2_Init(void)
{

 /* USER CODE BEGIN TIM2_Init 0 */

 /* USER CODE END TIM2_Init 0 */

 TIM_ClockConfigTypeDef sClockSourceConfig = {0};
 TIM_MasterConfigTypeDef sMasterConfig = {0};

 /* USER CODE BEGIN TIM2_Init 1 */

 /* USER CODE END TIM2_Init 1 */
 htim2.Instance = TIM2;
 htim2.Init.Prescaler = 0;
 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim2.Init.Period = 200;
 htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
 if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
 {
 Error_Handler();
 }
 sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
 if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
 {
 Error_Handler();
 }
 sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
 sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
 {
 Error_Handler();
 }
 /* USER CODE BEGIN TIM2_Init 2 */

 /* USER CODE END TIM2_Init 2 */

}

/**
 * Enable DMA controller clock
 */
static void MX_DMA_Init(void)
{

 /* DMA controller clock enable */
 __HAL_RCC_DMAMUX1_CLK_ENABLE();
 __HAL_RCC_DMA1_CLK_ENABLE();

 /* DMA interrupt init */
 /* DMA1_Channel1_IRQn interrupt configuration */
 HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);

}

/**
 * @brief GPIO Initialization Function
 * @PAram None
 * @retval None
 */
static void MX_GPIO_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

 /* GPIO Ports Clock Enable */
 __HAL_RCC_GPIOA_CLK_ENABLE();

 /*Configure GPIO pin : PA0 */
 GPIO_InitStruct.Pin = GPIO_PIN_0;
 GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING_FALLING;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

 /* EXTI interrupt init*/
 HAL_NVIC_SetPriority(EXTI0_IRQn, 0, 0);
 HAL_NVIC_EnableIRQ(EXTI0_IRQn);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
static void Debug_Init(void){
	CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // Enable ITM and DWT
	ITM->LAR = 0xC5ACCE55; // Unlock ITM
	ITM->TCR = ITM_TCR_ITMENA_Msk // Enable ITM
	 | ITM_TCR_SWOENA_Msk; // Enable SWO output
	ITM->TER = 0x01; // Enable stimulus port 0
}

/* USER CODE END 4 */

/**
 * @brief This function is executed in case of error occurrence.
 * @retval None
 */
void Error_Handler(void)
{
 /* USER CODE BEGIN Error_Handler_Debug */
 /* User can add his own implementation to report the HAL error return state */
 __disable_irq();
 while (1)
 {
 }
 /* USER CODE END Error_Handler_Debug */
}

#ifdef USE_FULL_ASSERT
/**
 * @brief Reports the name of the source file and the source line number
 * where the assert_param error has occurred.
 * @PAram file: pointer to the source file name
 * @PAram line: assert_param error line source number
 * @retval None
 */
void assert_failed(uint8_t *file, uint32_t line)
{
 /* USER CODE BEGIN 6 */
 /* User can add his own implementation to report the file name and line number,
 ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
 /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

 

 

1 reply

Andrew Neil
Super User
January 28, 2025

The ARM standard supports UART signalling on SWO - so, with that, maybe you could just use a UART and terminal?

https://community.st.com/t5/stm32-mcus-boards-and-hardware/uart-signal-on-swo-pin-from-st-link-v2-3/m-p/742817/highlight/true#M22588

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.