summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhathach <[email protected]>2026-07-24 15:28:54 +0700
committerhathach <[email protected]>2026-07-24 15:56:14 +0700
commit2a2d5f65ad61dc43d20ff479db9a27510592b50c (patch)
tree026ab74d553acf6be78d83091ba59afaf856331d
parent853f7e8f70caf4df9786001e84eca048d2664de7 (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.jdebug103
-rw-r--r--hw/bsp/same7x/family.c28
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);