2

I'm trying to initialize the debug trace SWO output pin on STM32H743. I have tried various code snippets for initializing the port, currently this one:

void SWD_Init(void)
{
  *(__IO uint32_t*)(0x5C001004) |= 0x00700000; // DBGMCU_CR D3DBGCKEN D1DBGCKEN TRACECLKEN
 
  //UNLOCK FUNNEL
  *(__IO uint32_t*)(0x5C004FB0) = 0xC5ACCE55; // SWTF_LAR
  *(__IO uint32_t*)(0x5C003FB0) = 0xC5ACCE55; // SWO_LAR
 
  //SWO current output divisor register
  //This divisor value (0x000000C7) corresponds to 400Mhz
  //To change it, you can use the following rule
  // value = (CPU Freq/sw speed )-1
   *(__IO uint32_t*)(0x5C003010) = ((SystemCoreClock / 2000000) - 1); // SWO_CODR
 
  //SWO selected pin protocol register
   *(__IO uint32_t*)(0x5C0030F0) = 0x00000002; // SWO_SPPR
 
  //Enable ITM input of SWO trace funnel
   *(__IO uint32_t*)(0x5C004000) |= 0x00000001; // SWFT_CTRL
 
  //RCC_AHB4ENR enable GPIOB clock
   *(__IO uint32_t*)(0x580244E0) |= 0x00000002;
 
  // Configure GPIOB pin 3 as AF
   *(__IO uint32_t*)(0x58020400) = (*(__IO uint32_t*)(0x58020400) & 0xffffff3f) | 0x00000080;
 
  // Configure GPIOB pin 3 Speed
   *(__IO uint32_t*)(0x58020408) |= 0x00000080;
 
  // Force AF0 for GPIOB pin 3
   *(__IO uint32_t*)(0x58020420) &= 0xFFFF0FFF;
}

However whatever I do, the CPU hangs during the SWO register access. This also causes debugger to lose connection. If I comment the SWO register initialization lines, the code runs ok but of course SWO output doesn't work.

jpa
  • 6,804
  • 17
  • 32

2 Answers2

3

After a lot of testing, I happened to try it with the boot configuration that uses 64 MHz HSI oscillator. That worked!

So after further testing, it finally saw this piece of the clock tree documentation:

STM32H7 clock tree diagram

Whenever STM32H7 is configured to use PLL1 P channel as the CPU clock, the trace clock is automatically switched to PLL1 R. I had the R channel disabled because I'm not using it for anything else, which then caused any access to the trace components to hang.

jpa
  • 6,804
  • 17
  • 32
  • 1
    Nice sleuthing and thanks for following up. Feel free to eventually accept your own answer if it is the best answer (which seems likely in this case). – user57037 Apr 09 '21 at 17:14
2

GDB throws the connection if the clock configuration is not correct and SWO is enabled. I also tried the method above and got SWO working at the initial HSI 64 MHz frequency but SWO was lost when the frequency was changed to using the PLL output. The solution works for STM32H745 to enable SWO output (SWV in STM32CubeIDE). A simple method is to keep PLL1_R output frequency the same as PLL1_P output so the clock rate matches SYSCLK. The PLL1_R only goes to Trace clock and even if disabled needs a matching value to use with STM32CubeIDE. The GDB setup in STM32CubeIDE must set up the SWO similar to SWD_Init() above. To use SWO standalone (in STLink SWO viewer for example) SWD_Init() should be called and called again after the SystemClock_Config to follow the frequency change. The SWD_Init() should perhaps be called SWO_Init(). The latest STM32CubeIDE 1.7 allows higher SWO speeds than the nominal 2 MHz so the setup would have to change to match or keep it at 2 MHz.