cancel
Showing results for 
Search instead for 
Did you mean: 

Trace ITM using STM32L4 Discovery Board not working

Naresh R
Associate II
Posted on June 02, 2018 at 16:23

Hi all,

I am working with a discovery board having STM32L476 on board. I am trying to retarget 'printf()' using ITM port 0 but having difficulties in making it work.

This is what I have done till now:

a) There is a solder bridge, SB14 which was not connected to the ST-Link-V2/1 on the discovery board; I have connected this bridge.

b) I have updated firmware version of on-board ST-Link-V2/1 to the latest using ST-LinkUpgrade software.

c) I am using Keil-MDK for my development where I am getting 'internal command error' as soon as I click on debug icon. After I click 'ok' on this error box, another error window pops up saying 'Target DLL has been cancelled. Debugger Aborted!'

d) I have also tried using STM32 ST-Link Utility software, I did enter the core clock frequency correctly as 8 MHz and selected the ITM port 0 in the SWO printf viewer window but once I click on the start button, the same error window 'internal command error' appears.

e) I did enable 'connect under reset' and 'debug even in low power mode' in ST-Link Utility just as a fail safe correction but no avail.

f) I did double check that I was using SWD and not JTAG while I was working on the above mentioned things.

By the way, when I don't enable Trace in Keil-MDK, SWD works fine; no issues at all.

Any leads on how to make this work?

#itm-swo-trace

Note: this post was migrated and contained many threaded conversations, some content may be missing.
9 REPLIES 9
Posted on June 03, 2018 at 16:50

Make sure you software is not reconfiguring the SWD pins, especially PB3, and not going into a low power mode (ie via WFI)

Use the USART/VCP connectivity to output basic diagnostic information to confirm the core settings and speeds.

Using L4/L4+ parts here successfully with Keil uV5 with trace, and debug printf

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 03, 2018 at 17:37

I am not using SWD pins or PB3 pin in my code, not using low power mode too. Checked the core clock using MCO signal on the Oscilloscope, frequency is correctly set 8 MHz.

I am using uV5, I am using target options dialog to enable SWD and SWO. I am not mapping any pins for these functions nor changing any control registers related to them. Are there any registers I need to control using my code for SWO? For SWD, all I have done is used the target options dialog and board is working (single stepping, halting etc) as it should.

When you are talking about core settings, can you be a bit more specific?

Posted on June 03, 2018 at 17:46

>>When you are talking about core settings, can you be a bit more specific?

AHB, APB1 and APB2 clocks and SystemCoreClock as understood from a system side perspective.

Register settings visible inside DWT, ITM and DBGMCU, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 05, 2018 at 10:54

I cross-checked everything, i.e. clocks (all required clocks are enabled and set to correct values) and debug registers (checked  if I am modifying their values but I am actually not even mentioning them anywhere in my code) .  Ofcourse, after trying for last 3/4 days I have raised an ST ticket and waiting for their response.

>>

Using L4/L4+ parts here successfully with Keil uV5 with trace, and debug printf

Meanwhile, since you have mentioned the above statement in one of your posts, is it possible for you yo send the minimum basic code, code doesn't need to do any work other than using the 'printf' function?

SWO is very important for my application and I am just unable to move forward without making this work. Ofcourse, alternatively I can retarget via UART etc but I badly need SWO to work. 

Posted on June 05, 2018 at 14:21

Forking the example project, making SB14, running 4 MHz

#include <stdio.h>
#include ''stm32l4xx_hal.h''
static void SystemClock_Config(void);
//****************************************************************************
/**
 * @brief Main program
 * @param None
 * @retval None
 */
int main(void)
{
 HAL_Init();
 /* Configure the System clock to have a frequency of 4 MHz */
 SystemClock_Config();
 printf(''

STM32L476-DISCO
'');
 printf(''Core=%d, %d MHz
'', SystemCoreClock, SystemCoreClock / 1000000);
 printf(''APB1=%d
'', HAL_RCC_GetPCLK1Freq());
 printf(''APB2=%d
'', HAL_RCC_GetPCLK2Freq());
 /* Add your application code here
 */
 /* Infinite loop */
 while (1)
 {
 }
}
//****************************************************************************
/**
 * @brief System Clock Configuration
 * The system Clock is configured as follows :
 * System Clock source = MSI
 * SYSCLK(Hz) = 4000000
 * HCLK(Hz) = 4000000
 * AHB Prescaler = 1
 * APB1 Prescaler = 1
 * APB2 Prescaler = 1
 * MSI Frequency(Hz) = 4000000
 * Flash Latency(WS) = 0
 * @param None
 * @retval None
 */
static void SystemClock_Config(void)
{
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 /* The following clock configuration sets the Clock configuration sets after System reset */
 /* It could be avoided but it is kept to illustrate the use of HAL_RCC_OscConfig and HAL_RCC_ClockConfig */
 /* and to be eventually adapted to new clock configuration */
 /* MSI is enabled after System reset at 4Mhz, PLL not used */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
 RCC_OscInitStruct.MSIState = RCC_MSI_ON;
 RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
 RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
 /* Select MSI as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */
 /* Set 0 Wait State flash latency for 4Mhz */
 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | 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;
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
 /* The voltage scaling allows optimizing the power consumption when the device is
 clocked below the maximum system frequency, to update the voltage scaling value
 regarding system frequency refer to product datasheet. */
 /* Enable Power Control clock */
 __HAL_RCC_PWR_CLK_ENABLE();
 if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
 /* Disable Power Control clock */
 __HAL_RCC_PWR_CLK_DISABLE();
}
//****************************************************************************
// Hosting of stdio functionality through SWV (Make SB14)
//****************************************************************************
/* Implementation of putchar (also used by printf function to output data) */
int SendChar(int ch) /* Write character to Serial Port */
{
 ITM_SendChar(ch); // From core_cm4.c
 return(ch);
}
//****************************************************************************
#include <rt_misc.h>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) { return (SendChar(ch)); }
int ferror(FILE *f)
{
 /* Your implementation of ferror */
 return EOF;
}
void _ttywrch(int ch) { SendChar(ch); }
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
//****************************************************************************
#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(char *file, uint32_t line)
{
 /* User can add his own implementation to report the file name and line number,
 ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
 /* Infinite loop */
 while (1)
 {
 }
}
#endif
//****************************************************************************
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

0690X00000604YhQAI.jpg 0690X00000604eTQAQ.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 05, 2018 at 15:36

At 80 Mhz, and supporting the VCP via USART2 (PD5, PD6)

#include <stdio.h>
#include ''stm32l4xx_hal.h''
static void SystemClock_Config(void);
/* UART handler declaration */
static UART_HandleTypeDef UartHandle = { 0 };
//****************************************************************************
void USART2_Init(void)
{
 GPIO_InitTypeDef GPIO_InitStruct = { 0 };
 __USART2_CLK_ENABLE();
 __GPIOD_CLK_ENABLE();
 /* UART RX/TX GPIO pin configuration */
 GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6;
 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
 GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
 /*## Configure the UART peripheral ######################################*/
 /* Put the USART peripheral in the Asynchronous mode (UART Mode) */
 /* UART1 configured as follow:
 - Word Length = 8 Bits
 - Stop Bit = One Stop bit
 - Parity = NO parity
 - BaudRate = 9600 baud
 - Hardware flow control disabled (RTS and CTS signals) */
 UartHandle.Instance = USART2;
 UartHandle.Init.BaudRate = 115200;
 UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
 UartHandle.Init.StopBits = UART_STOPBITS_1;
 UartHandle.Init.Parity = UART_PARITY_NONE;
 UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
 UartHandle.Init.Mode = UART_MODE_TX_RX;
 UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
#ifdef UART_ONE_BIT_SAMPLE_DISABLE
 UartHandle.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
#endif
 if (HAL_UART_Init(&UartHandle) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
}
//****************************************************************************
/**
 * @brief Main program
 * @param None
 * @retval None
 */
int main(void)
{
 HAL_Init();
 /* Configure the System clock to have a frequency of 80 MHz */
 SystemClock_Config();
 USART2_Init();
 printf(''

STM32L476G-DISCO
'');
 printf(''Core=%d, %d MHz
'', SystemCoreClock, SystemCoreClock / 1000000);
 printf(''APB1=%d
'', HAL_RCC_GetPCLK1Freq());
 printf(''APB2=%d
'', HAL_RCC_GetPCLK2Freq());
 /* Add your application code here
 */
 /* Infinite loop */
 while (1)
 {
 }
}
//****************************************************************************
/**
 * @brief System Clock Configuration
 * The system Clock is configured as follow :
 * System Clock source = PLL (MSI)
 * SYSCLK(Hz) = 80000000
 * HCLK(Hz) = 80000000
 * AHB Prescaler = 1
 * APB1 Prescaler = 1
 * APB2 Prescaler = 1
 * MSI Frequency(Hz) = 4000000
 * PLL_M = 1
 * PLL_N = 40
 * PLL_R = 2
 * PLL_P = 7
 * PLL_Q = 4
 * Flash Latency(WS) = 4
 * @param None
 * @retval None
 */
static void SystemClock_Config(void)
{
 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
 /* MSI is enabled after System reset, activate PLL with MSI as source */
 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
 RCC_OscInitStruct.MSIState = RCC_MSI_ON;
 RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_6;
 RCC_OscInitStruct.MSICalibrationValue = RCC_MSICALIBRATION_DEFAULT;
 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_MSI;
 RCC_OscInitStruct.PLL.PLLM = 1;
 RCC_OscInitStruct.PLL.PLLN = 40;
 RCC_OscInitStruct.PLL.PLLR = 2;
 RCC_OscInitStruct.PLL.PLLP = 7;
 RCC_OscInitStruct.PLL.PLLQ = 4;
 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
 /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2
 clocks dividers */
 RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
 RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
 RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
 RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
 {
 /* Initialization Error */
 while(1);
 }
}
//****************************************************************************
// Hosting of stdio functionality through SWV (Make SB14) and USART
//****************************************************************************
/* Implementation of putchar (also used by printf function to output data) */
int SendChar(int ch) /* Write character to Serial Port */
{
#if 1 // SWV
 ITM_SendChar(ch); // From core_cm4.c
#endif
#if 1 // USART
 while((USART2->ISR & USART_ISR_TXE) == 0); // Wait for Empty
 USART2->TDR = ch; // Send Char
#endif
 return(ch);
}
//****************************************************************************
#include <rt_misc.h>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f) { return (SendChar(ch)); }
int ferror(FILE *f)
{
 /* Your implementation of ferror */
 return EOF;
}
void _ttywrch(int ch) { SendChar(ch); }
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
//****************************************************************************
#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(char *file, uint32_t line)
{
 /* User can add his own implementation to report the file name and line number,
 ex: printf(''Wrong parameters value: file %s on line %d

'', file, line) */
 /* Infinite loop */
 while (1)
 {
 }
}
#endif
//****************************************************************************
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

0690X00000604esQAA.jpg
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 05, 2018 at 18:09

Thank you very much! But I am getting same error in both the cases which I was getting earlier. I am a bit surprised especially with the first code you have sent, it isn't doing any work  other than printing. Apart from setting target options as shown in your attached images, all I am doing is bridge 'SB14'.

But still it doesn't work. Now, I have no clue.

Posted on June 05, 2018 at 18:56

>>But still it doesn't work. Now, I have no clue.

I can't fix that. Perhaps you work with some other people who can walk through the implementation and connectivity with you.

The USART/VCP stuff should work irrespective of the SB14 wiring. You could check the continuity of the SB14 link at the STM32 pins, it definitely won't work in SWV mode without the connection.

Make sure your ST-LINK has reasonably current firmware, like J29, or J30

Use the ST-LINK Utilities, and the SWV Viewer windows, I'd expect this to work also.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on June 06, 2018 at 11:39

I reckon I have eventually found the issue, it's because the revision of the board you are using and the one I have are different.

0690X00000604d2QAA.jpg

Note the revision changes above. What's more peculiar is PB3 is connected (or can be connected) not only to SWO but it's already connected to 3V3_REG_ON as can be seen in the below images. This signal is connected to mutliple points in the board.

0690X00000604g5QAA.jpg

0690X00000604gPQAQ.jpg

I tried changing the jumper JP6 from 3V3_REG_ON to CR1 battery but the problem is ST-Link is getting completely disconnected from STM32L4 Hence, all I can do is use it only for SWD. My quest ends here I guess.

If I am right, the more interesting question is why would ST guys do such a thing? Why can't they use any other pin other than PB3? Hope someone from ST would comment on this.