Skip to main content
Visitor II
July 14, 2026
Question

STM32H7 ETM configuration

  • July 14, 2026
  • 0 replies
  • 38 views

I am into configuring a STM32H750VBT6 and I want to configure ETMv4 inside the code of the program and my objective is to detect and capture data on 5 trace pins.
I configured all trace pipeline including, CSTF,ETF,ETM,DWT and TPIU. also I considered opening Locks, enabling TRCENA in CoreDebug_:DEMCR and enabling required clock domains in DBGMCU_CR.
After all I am just sighting clock signal on TRACECLK pin. I also checked TPIU unit if it successfully outputs test patterns like AA55 and FF00. Test patterns worked properly but when disabling test pattern only clock comes out through the trace pins.
I am looking for someone who configured that before to help me prevail it.

here are my functions:

#include "ETMv4.h"
#include "core_cm7.h"

uint32_t startAddr = 0;
uint32_t stopAddr = 0;

void Parallel_Trace_configure(){
TraceGPIO_Configure();
Disable_ETM();
TPIU_Configure();
ETF_Configure();
CSTF_Configure();
ETM_Configure();
SetupStartStopAddr();
DWT_Configure();
Enable_ETM();
}

void TPIU_Configure(void)
{

TPIU->LAR = CORESIGHT_UNLOCK;
TPIU->CURPSIZE = 8;
//TPIU->CURTPM = (1<<17)|(1<<2);//Test in continuous AA/55 pattern
TPIU->CURTPM = (1<<17);
TPIU->FFCR = 0x2;
TPIU->FSCR = 0x40;
while (TPIU->FFSR & (1 << 0)) {
// Wait until FLINPROG (Flush In Progress) bit clears
}
}
void ETF_Configure(void) {
ETF->LAR = CORESIGHT_UNLOCK;
ETF->CTL &= ~(1U << 0);
while ((ETF->STS & (1U << 2)) == 0) {
// Wait for READY == 1
}
ETF->MODE = 0x2;
ETF->FFCR = 0;
ETF->CTL |= (1U << 0);
}

void ETM_Configure(void){

Disable_ETM();
ETM->CONFIG |= 0x18;
ETM->STALLCTL |= 0x30c;
ETM->CCCTL |= 1;
ETM->TRACEID = 0x3E;
ETM->VICTL = 0x00000001;
ETM->VIPCSSCTL = (1U << 17) | (1U << 0);
Enable_ETM();
}

void CSTF_Configure(void){
CSTF->LAR = CORESIGHT_UNLOCK; // Unlock Funnel access
CSTF->CTRL = 0x01; // Enable Slave Port 0 (ETM traffic)
}

void TraceGPIO_Configure(void){
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // Equivalent to (1U << 24)
RCC->AHB4ENR |= RCC_AHB4ENR_GPIOEEN;
GPIOE->MODER &= ~(GPIO_MODER_MODE2 | GPIO_MODER_MODE3 |
GPIO_MODER_MODE4 | GPIO_MODER_MODE5 | GPIO_MODER_MODE6);
GPIOE->MODER |= (2U << GPIO_MODER_MODE2_Pos) | (2U << GPIO_MODER_MODE3_Pos) |
(2U << GPIO_MODER_MODE4_Pos) | (2U << GPIO_MODER_MODE5_Pos) |
(2U << GPIO_MODER_MODE6_Pos);
GPIOE->OSPEEDR |= (3U << GPIO_OSPEEDR_OSPEED2_Pos) | (3U << GPIO_OSPEEDR_OSPEED3_Pos) |
(3U << GPIO_OSPEEDR_OSPEED4_Pos) | (3U << GPIO_OSPEEDR_OSPEED5_Pos) |
(3U << GPIO_OSPEEDR_OSPEED6_Pos);

GPIOE->AFR[0] &= ~((0xFU << (4 * 2)) | (0xFU << (4 * 3)) |
(0xFU << (4 * 4)) | (0xFU << (4 * 5)) | (0xFU << (4 * 6)));
DBGMCU->CR |= DBGMCU_CR_DBG_TRACECKEN|DBGMCU_CR_DBG_CKD1EN|DBGMCU_CR_DBG_CKD3EN;

}

void DWT_Configure() {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; // Equivalent to (1U << 24)
DWT->LAR = CORESIGHT_UNLOCK;
DWT->CTRL = (1<<10)|(1<<0);
DWT->COMP0 = startAddr;
DWT->MASK0 = 0; // Exact address match
DWT->FUNCTION0 = 8; // Match on instruction address execution
// 3. Configure DWT Comparator 1 as the STOP trigger
#undef COMP1
DWT->COMP1 = stopAddr;
DWT->MASK1 = 0; // Exact address match
DWT->FUNCTION1 = 8; // Match on instruction address execution
}

void Enable_ETM(){
ETM->PRGCTL |= 1U;
// Wait for ETM to be active
while ((ETM->STAT & 0x01) != 0);
}

void Disable_ETM(){

ETM->LAR = CORESIGHT_UNLOCK;
// Wait for the ETM to be unlocked by checking the Lock Status Register (LSR)
while ((ETM->LSR & 0x02) != 0); // Bit 1 is the Lock Status bit (0 = Unlocked)
ETM->PRGCTL &= ~1U;

// Wait for ETM to be turned off (idle)
while ((ETM->STAT & 0x01) != 1);
}

__attribute__((noinline)) void StartPoint(void){
__asm("nop");
}
__attribute__((noinline)) void StopPoint(void){
__asm("nop");
}

void SetupStartStopAddr()
{
// Cast to uint32_t and mask off the Thumb bit (bit 0)
startAddr = (uint32_t)&StartPoint & ~1UL;
stopAddr = (uint32_t)&StopPoint & ~1UL;
}