diff options
| author | hathach <[email protected]> | 2026-07-24 15:28:54 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-24 15:56:14 +0700 |
| commit | 2a2d5f65ad61dc43d20ff479db9a27510592b50c (patch) | |
| tree | 026ab74d553acf6be78d83091ba59afaf856331d | |
| parent | 853f7e8f70caf4df9786001e84eca048d2664de7 (diff) | |
same7x: ETM trace support for same70_xplained
J403 (bottom-side Cortex Debug+ETM footprint, header required):
TRACECLK=PD8 peripheral D, TRACED0-3=PD4-7 peripheral C. TRACE_ETM builds
hold the KSZ8081 PHY in reset (PD4-7 are its RMII receive outputs and it
drives against the trace stream), clock the TPIU from PCK3 (MCK/2) and
mux the pins; the ozone reference starts PCK3 in the post-reset/download
hooks - TPIU programming while PCK3 is stopped is silently lost. Width-1
validated at the stock 300 MHz core; width 4 blocked on a dead D1 line
(suspect probe channel, h743eval crosscheck pending).
| -rw-r--r-- | hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug | 103 | ||||
| -rw-r--r-- | hw/bsp/same7x/family.c | 28 |
2 files changed, 131 insertions, 0 deletions
diff --git a/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug b/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug new file mode 100644 index 000000000..0fde09716 --- /dev/null +++ b/hw/bsp/same7x/boards/same70_xplained/ozone/same70.jdebug @@ -0,0 +1,103 @@ +/********************************************************************* +* +* OnProjectLoad +* +* Function description +* Project load routine. Required. +* +* Notes +* SAM E70 Xplained: solder a 20-pin 50-mil header on the J403 ETM footprint +* (bottom side). TRACECLK=PD8 (peripheral D), TRACED0-3=PD4-7 (peripheral C), +* shared with the Ethernet PHY - no Ethernet while tracing. TRACE_ETM=1 +* builds mux the pins and clock the TPIU from PCK3=MCK; TPIU/ETM are +* ROM-table-discoverable so no J-Link script is required. +* Trace clock pin is PCK3/2 = 75 MHz at the stock 300 MHz core (MCK 150). +* +********************************************************************** +*/ +void OnProjectLoad (void) { + Project.SetTraceSource ("Trace Pins"); + Project.SetTracePortWidth (4); + Project.SetSWO (0); + Edit.SysVar (VAR_TRACE_CORE_CLOCK, 300000000); + Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M7F.svd"); + + Project.SetDevice ("ATSAME70Q21B"); + Project.SetHostIF ("USB", ""); + Project.SetTargetIF ("SWD"); + Project.SetTIFSpeed ("4 MHz"); + + File.Open ("../../../../../../examples/cmake-build-same70_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); + } + + // TPIU trace clock = PCK3; it must run BEFORE Ozone arms the trace + // components (TPIU programming while PCK3 is stopped is lost and the port + // emits unformatted garbage). A target reset wipes the PMC, so this runs + // in the post-reset/post-download hooks, not AfterTargetConnect. + Target.WriteU32 (0x400E064C, 0x00000014); // PMC_PCK3: CSS=MCK, PRESS=/2 + Target.WriteU32 (0x400E0600, 0x00000800); // PMC_SCER: PCK3 on +} + +/********************************************************************* +* +* 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); + } + + // TPIU trace clock = PCK3; it must run BEFORE Ozone arms the trace + // components (TPIU programming while PCK3 is stopped is lost and the port + // emits unformatted garbage). A target reset wipes the PMC, so this runs + // in the post-reset/post-download hooks, not AfterTargetConnect. + Target.WriteU32 (0x400E064C, 0x00000014); // PMC_PCK3: CSS=MCK, PRESS=/2 + Target.WriteU32 (0x400E0600, 0x00000800); // PMC_SCER: PCK3 on +} diff --git a/hw/bsp/same7x/family.c b/hw/bsp/same7x/family.c index d02e6c5f1..6a3466354 100644 --- a/hw/bsp/same7x/family.c +++ b/hw/bsp/same7x/family.c @@ -62,6 +62,34 @@ void board_init(void) { /* Disable Watchdog */ hri_wdt_set_MR_WDDIS_bit(WDT); +#if defined(TRACE_ETM) + // same70_xplained J403 (Cortex Debug+ETM footprint, bottom side) carries + // 4-bit trace: TRACECLK=PD8 (peripheral D), TRACED0-3=PD4-7 (peripheral C). + // The trace pins double as the Ethernet PHY's RMII receive lines + // (PD4=CRS_DV, PD5/6=RXD0/1, PD7=RXER - PHY OUTPUTS): hold the KSZ8081 in + // reset (PHY_RESET=PC10 low) or it drives against the trace stream. + _pmc_enable_periph_clock(ID_PIOC); + gpio_set_pin_level(GPIO(GPIO_PORTC, 10), false); + gpio_set_pin_direction(GPIO(GPIO_PORTC, 10), GPIO_DIRECTION_OUT); + gpio_set_pin_function(GPIO(GPIO_PORTC, 10), GPIO_PIN_FUNCTION_OFF); + + // The TPIU is clocked from PCK3 (datasheet 16.7.4) - run it from MCK. + // skip if the debugger already started PCK3 (reprogramming glitches the + // clock mid-stream and desyncs the decoder) + uint32_t const pck3 = PMC_PCK_CSS_MCK | PMC_PCK_PRES(1); // MCK/2 = 75 MHz -> 37.5 MHz pin + if (PMC->PMC_PCK[3] != pck3 || !(PMC->PMC_SR & PMC_SR_PCKRDY3)) { + PMC->PMC_PCK[3] = pck3; + PMC->PMC_SCER = PMC_SCER_PCK3; + while (!(PMC->PMC_SR & PMC_SR_PCKRDY3)) {} + } + uint32_t const clk_pin = PIO_PD8D_TPIU_TRACECLK; + uint32_t const dat_pin = PIO_PD4C_TPIU_TRACED0 | PIO_PD5C_TPIU_TRACED1 | + PIO_PD6C_TPIU_TRACED2 | PIO_PD7C_TPIU_TRACED3; + PIOD->PIO_ABCDSR[0] = (PIOD->PIO_ABCDSR[0] | clk_pin) & ~dat_pin; // D=11, C=01 + PIOD->PIO_ABCDSR[1] |= clk_pin | dat_pin; + PIOD->PIO_PDR = clk_pin | dat_pin; // hand the pins to the peripheral +#endif + #ifdef LED_PIN _pmc_enable_periph_clock(LED_PORT_CLOCK); gpio_set_pin_level(LED_PIN, LED_STATE_OFF); |
