diff options
| author | hathach <[email protected]> | 2026-07-24 15:28:53 +0700 |
|---|---|---|
| committer | hathach <[email protected]> | 2026-07-24 15:56:14 +0700 |
| commit | e90d232b7718656a627775e3ecde63c6fc7c2e84 (patch) | |
| tree | 2c67c5d955d826665d40eea18d8bdcce6462e49b /hw/bsp | |
| parent | 4d9e4c9e3895b0c15a04763028d1becd27bbf89c (diff) | |
rp2040: RP2350/pico2 ETM trace over fly-wired MIPI-20
J-Link's built-in RP2350 script owns the whole chip-side path (component
map is not ROM-table-discoverable; a custom JLinkScript replaces the
built-in one and kills pin trace), re-arming at every resume - firmware
does no trace setup. TRACE_ETM builds pin clk_sys to 48 MHz from crt0
(fly-wire seating-proof; the port is DDR at clk_sys/2 and the J-Trace PRO
V2 cliff sits just above 40 MHz TRACECLK - SEGGER requires V3.0+ for this
chip), clear TIMER0/1 DBGPAUSE (default freezes the us-timer while any
core is debug-halted and sleep_ms spins forever), and run the UART console
TX-only (GPIO1 = default UART0 RX = TRACECLK).
Diffstat (limited to 'hw/bsp')
| -rw-r--r-- | hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake | 14 | ||||
| -rw-r--r-- | hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug | 70 | ||||
| -rw-r--r-- | hw/bsp/rp2040/family.c | 24 |
3 files changed, 107 insertions, 1 deletions
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake index 0a7dd4d23..08384b0cd 100644 --- a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake @@ -1,3 +1,17 @@ set(PICO_PLATFORM rp2350-arm-s) set(PICO_BOARD pico2) #set(OPENOCD_SERIAL E6614103E77C5A24) + +if (TRACE_ETM STREQUAL "1") + # TRACECLK is clk_sys/2 and must stay constant once trace is armed (a step + # desyncs the decoder), so the trace clock is pinned from crt0 onwards. + # 48 MHz (24 MHz TRACECLK) holds full-width trace on a typical fly-wire + # seating; a fresh, tight seating supports up to 72-80 MHz (re-qualify per + # the etm-trace skill), and >80 MHz needs a V3 probe + real trace board. + add_compile_definitions( + SYS_CLK_KHZ=48000 + PLL_SYS_VCO_FREQ_HZ=1440000000 + PLL_SYS_POSTDIV1=6 + PLL_SYS_POSTDIV2=5 + ) +endif () diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug b/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug new file mode 100644 index 000000000..ff48eb673 --- /dev/null +++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/ozone/rp2350.jdebug @@ -0,0 +1,70 @@ +/********************************************************************* +* +* OnProjectLoad +* +* Function description +* Project load routine. Required. +* +* Notes +* Pico 2 has no trace connector - fly-wire GPIO1-5 to the MIPI20: +* TRACECLK=GPIO1->12, D0=GPIO2->14, D1=GPIO3->16, D2=GPIO4->18, +* D3=GPIO5->20 (SEGGER validates this board the same way). Firmware must +* be built with TRACE_ETM=1: it pins clk_sys to 48 MHz (board.cmake) so +* the 4-bit port never saturates and the clock never steps mid-stream, +* and keeps the us-timer free of TIMER DBGPAUSE (family.c). The whole +* chip-side trace path (ETM/funnel/TPIU/pin mux) is armed by J-Link's +* built-in RP2350 script at every resume - do NOT set a custom +* JLinkScript here: it would replace that script and J-Link then fails +* with "Required trace components for pin trace not found". +* GPIO1 is the default UART0 RX: console TX still works, RX is lost. +* +********************************************************************** +*/ +void OnProjectLoad (void) { + Project.SetTraceSource ("Trace Pins"); + Project.SetTracePortWidth (4); + Project.SetSWO (0); + Edit.SysVar (VAR_TRACE_CORE_CLOCK, 48000000); + Project.AddSvdFile ("$(InstallDir)/Config/CPU/Cortex-M33F.svd"); + + Project.SetDevice ("RP2350_M33_0"); + Project.SetHostIF ("USB", ""); + Project.SetTargetIF ("SWD"); + Project.SetTIFSpeed ("25 MHz"); + + File.Open ("../../../../../../examples/cmake-build-raspberry_pi_pico2/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) { + // intentionally empty: the RP2350 bootrom must run to validate the + // IMAGE_DEF and hand over to the app - setting SP/PC from the vector + // table bypasses it and the pico-sdk runtime never comes up +} + +/********************************************************************* +* +* 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) { + // intentionally empty: the RP2350 bootrom must run to validate the + // IMAGE_DEF and hand over to the app - setting SP/PC from the vector + // table bypasses it and the pico-sdk runtime never comes up +} diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c index 15f179656..f0d6ba245 100644 --- a/hw/bsp/rp2040/family.c +++ b/hw/bsp/rp2040/family.c @@ -161,6 +161,20 @@ static void stdio_rtt_init(void) { //--------------------------------------------------------------------+ // //--------------------------------------------------------------------+ +#if defined(TRACE_ETM) && defined(PICO_RP2350) && PICO_RP2350 == 1 +// J-Link's built-in RP2350 device script re-arms the whole chip-side trace +// path (ETM/funnel/TPIU/pins) via OnTraceStart at every resume, so firmware +// must NOT touch it - it only keeps the us-timer running while cores sit +// debug-halted (default TIMER DBGPAUSE freezes it, and sleep_ms() then spins +// forever after any debugger session). +static void trace_etm_init(void) { + *(volatile uint32_t*) 0x400B002Cu = 0; // TIMER0 DBGPAUSE + *(volatile uint32_t*) 0x400B802Cu = 0; // TIMER1 DBGPAUSE +} +#else + #define trace_etm_init() +#endif + void board_init(void) { #if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB) @@ -199,10 +213,18 @@ void board_init(void) #endif #ifdef UART_DEV - bi_decl(bi_2pins_with_func(UART_TX_PIN, UART_RX_PIN, GPIO_FUNC_UART)); uart_inst = uart_get_instance(UART_DEV); +#if defined(TRACE_ETM) && defined(PICO_RP2350) && PICO_RP2350 == 1 + // GPIO1 (default UART RX) is TRACECLK: TX-only console, and never touch + // GPIO1 - even a brief re-mux gaps the trace clock and desyncs the probe + bi_decl(bi_1pin_with_name(UART_TX_PIN, "UART TX")); + stdio_uart_init_full(uart_inst, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, -1); +#else + bi_decl(bi_2pins_with_func(UART_TX_PIN, UART_RX_PIN, GPIO_FUNC_UART)); stdio_uart_init_full(uart_inst, CFG_BOARD_UART_BAUDRATE, UART_TX_PIN, UART_RX_PIN); #endif +#endif + trace_etm_init(); #if defined(LOGGER_RTT) stdio_rtt_init(); |
