samd5x_e5x: ETM trace support for same54_xplained

The populated 20-pin Cortex Debug+ETM header carries 4-bit trace
(TRACECLK=PC27, D0-3=PC28/PC26/PC25/PC24, mux H). TRACE_ETM builds mux
the pins and enable GCLK channel 47 (GCLK_CM4_TRACE) from GCLK0 - without
that gate the port stays silent with pins and TPIU armed. Chip-max
120 MHz core / 60 MHz TRACECLK validated (3x 280M-fetch captures).
This commit is contained in:
hathach
2026-07-24 15:28:53 +07:00
parent e90d232b77
commit 853f7e8f70
2 changed files with 116 additions and 0 deletions

View File

@ -0,0 +1,89 @@
/*********************************************************************
*
* OnProjectLoad
*
* Function description
* Project load routine. Required.
*
* Notes
* SAM E54 Xplained Pro carries a populated 20-pin Cortex Debug+ETM
* connector (Table 5-11): TRACECLK=PC27, D0=PC28, D1=PC26, D2=PC25,
* D3=PC24 - no rework needed. Firmware must be built with TRACE_ETM=1
* (mux function H on those pins in board_init); TPIU/ETM are
* ROM-table-discoverable so no J-Link script is required.
* Trace clock is CPU/2 = 60 MHz at the stock 120 MHz core.
*
**********************************************************************
*/
void OnProjectLoad (void) {
Project.SetTraceSource ("Trace Pins");
Project.SetTracePortWidth (4);
Project.SetSWO (0);
Edit.SysVar (VAR_TRACE_CORE_CLOCK, 120000000);
Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M4F.svd");
Project.SetDevice ("ATSAME54P20");
Project.SetHostIF ("USB", "");
Project.SetTargetIF ("SWD");
Project.SetTIFSpeed ("4 MHz");
File.Open ("../../../../../../examples/cmake-build-same54_xplained/device/cdc_msc/cdc_msc.elf");
}
/*********************************************************************
*
* AfterTargetReset
*
* Function description
* Event handler routine.
* - Sets the PC register to program reset value.
* - Sets the SP register to program reset value on Cortex-M.
*
**********************************************************************
*/
void AfterTargetReset (void) {
unsigned int SP;
unsigned int PC;
unsigned int VectorTableAddr;
VectorTableAddr = Elf.GetBaseAddr();
if (VectorTableAddr == 0xFFFFFFFF) {
Util.Log("Project file error: failed to get program base");
} else {
SP = Target.ReadU32(VectorTableAddr);
Target.SetReg("SP", SP);
PC = Target.ReadU32(VectorTableAddr + 4);
Target.SetReg("PC", PC);
}
}
/*********************************************************************
*
* AfterTargetDownload
*
* Function description
* Event handler routine.
* - Sets the PC register to program reset value.
* - Sets the SP register to program reset value on Cortex-M.
*
**********************************************************************
*/
void AfterTargetDownload (void) {
unsigned int SP;
unsigned int PC;
unsigned int VectorTableAddr;
VectorTableAddr = Elf.GetBaseAddr();
if (VectorTableAddr == 0xFFFFFFFF) {
Util.Log("Project file error: failed to get program base");
} else {
SP = Target.ReadU32(VectorTableAddr);
Target.SetReg("SP", SP);
PC = Target.ReadU32(VectorTableAddr + 4);
Target.SetReg("PC", PC);
}
}

View File

@ -87,6 +87,31 @@ void USB_3_Handler(void) { USB_Any_Handler(); }
static void max3421_init(void);
#endif
#if defined(TRACE_ETM)
// same54_xplained routes 4-bit trace to its 20-pin Cortex Debug+ETM header:
// TRACECLK=PC27, D0=PC28, D1=PC26, D2=PC25, D3=PC24 - all peripheral
// function H (CM4 trace). TPIU/ETM are ROM-table-discoverable; the debugger
// arms them, firmware only muxes the pins.
static void trace_etm_init(void) {
// the CM4 trace unit runs from its own GCLK channel (47): feed it GCLK0
// (CPU clock) - without this the pins mux fine but the port stays silent
GCLK->PCHCTRL[47].reg = GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN;
while (!(GCLK->PCHCTRL[47].reg & GCLK_PCHCTRL_CHEN)) {}
const uint8_t pin[] = {24, 25, 26, 27, 28};
for (unsigned i = 0; i < 5; i++) {
PORT->Group[2].PINCFG[pin[i]].reg = PORT_PINCFG_PMUXEN | PORT_PINCFG_DRVSTR;
if (pin[i] & 1) {
PORT->Group[2].PMUX[pin[i] >> 1].bit.PMUXO = 7; // function H
} else {
PORT->Group[2].PMUX[pin[i] >> 1].bit.PMUXE = 7;
}
}
}
#else
#define trace_etm_init()
#endif
void board_init(void) {
// Clock init ( follow hpl_init.c )
hri_nvmctrl_set_CTRLA_RWS_bf(NVMCTRL, 0);
@ -104,6 +129,8 @@ void board_init(void) {
// Init 1ms tick timer (samd SystemCoreClock may not correct)
SystemCoreClock = CONF_CPU_FREQUENCY;
trace_etm_init();
#if CFG_TUSB_OS == OPT_OS_NONE
SysTick_Config(CONF_CPU_FREQUENCY / 1000);
#elif CFG_TUSB_OS == OPT_OS_FREERTOS