# SPDX-License-Identifier: GPL-2.0-or-later # RP2350 is a microcontroller with dual Cortex-M33 cores or dual Hazard3 RISC-V cores. # https://www.raspberrypi.com/documentation/microcontrollers/silicon.html#rp2350 transport select swd source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME rp2350 } if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x10000 } # Nonzero FLASHSIZE supresses QSPI flash size detection if { [info exists FLASHSIZE] } { set _FLASHSIZE $FLASHSIZE } else { # Detect QSPI flash size based on flash ID or SFDP set _FLASHSIZE 0 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x00040927 } # Set to '1' to start rescue mode if { [info exists RESCUE] } { set _RESCUE $RESCUE } else { set _RESCUE 0 } # Set to 'cm0' or 'cm1' for Cortex-M33 single core configuration # To keep compatibility with RP2040 aliases '0' and '1' are provided for Cortex-M33 cores # Use 'rv0' or 'rv1' for RISC-V single core configuration # List more for a multicore configuration if { [info exists USE_CORE] } { set _USE_CORE $USE_CORE } else { # defaults to both Cortex-M33 cores set _USE_CORE { cm0 cm1 } } swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID if { [info exists SWD_MULTIDROP] } { dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu -dp-id 0x0040927 -instance-id 0 } else { dap create $_CHIPNAME.dap -adiv6 -chain-position $_CHIPNAME.cpu } # Cortex-M33 core 0 if { [lsearch $_USE_CORE cm0] >= 0 || [lsearch $_USE_CORE 0] >= 0 } { set _TARGETNAME_CM0 $_CHIPNAME.cm0 set _TARGETNAME_0 $_TARGETNAME_CM0 } # RISC-V core 0 if { [lsearch $_USE_CORE rv0] >= 0 } { set _TARGETNAME_RV0 $_CHIPNAME.rv0 if { ![info exists _TARGETNAME_0] } { set _TARGETNAME_0 $_TARGETNAME_RV0 } } # Cortex-M33 core 1 if { [lsearch $_USE_CORE cm1] >= 0 || [lsearch $_USE_CORE 1] >= 0 } { set _TARGETNAME_CM1 $_CHIPNAME.cm1 set _TARGETNAME_1 $_TARGETNAME_CM1 } # RISC-V core 1 if { [lsearch $_USE_CORE rv1] >= 0 } { set _TARGETNAME_RV1 $_CHIPNAME.rv1 if { ![info exists _TARGETNAME_1] } { set _TARGETNAME_1 $_TARGETNAME_RV1 } } if { [info exists _TARGETNAME_CM0] } { target create $_TARGETNAME_CM0 cortex_m -dap $_CHIPNAME.dap -ap-num 0x2000 # srst does not exist; use SYSRESETREQ to perform a soft reset $_TARGETNAME_CM0 cortex_m reset_config sysresetreq # After a rescue reset the cache requires invalidate to allow SPI flash # reads from the XIP cached mapping area $_TARGETNAME_CM0 configure -event reset-init { rp2xxx rom_api_call FC } } if { [info exists _TARGETNAME_RV0] } { target create $_TARGETNAME_RV0 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 0 $_TARGETNAME_RV0 riscv virt2phys_mode off $_TARGETNAME_RV0 configure -event reset-init "_rv_reset_init" if { [info exists _TARGETNAME_CM0] } { # just for setting after init when the event become-available is not fired $_TARGETNAME_RV0 configure -event examine-end "rp2xxx _switch_target $_TARGETNAME_CM0 $_TARGETNAME_RV0" } } if { [info exists _TARGETNAME_CM1] } { target create $_TARGETNAME_CM1 cortex_m -dap $_CHIPNAME.dap -ap-num 0x4000 $_TARGETNAME_CM1 cortex_m reset_config sysresetreq } if { [info exists _TARGETNAME_RV1] } { target create $_TARGETNAME_RV1 riscv -dap $_CHIPNAME.dap -ap-num 0xa000 -coreid 1 $_TARGETNAME_RV1 riscv virt2phys_mode off } if { [info exists USE_SMP] } { set _USE_SMP $USE_SMP } elseif { [info exists _TARGETNAME_CM0] == [info exists _TARGETNAME_CM1] && [info exists _TARGETNAME_RV0] == [info exists _TARGETNAME_RV1] } { set _USE_SMP 1 } else { set _USE_SMP 0 } if { $_USE_SMP } { if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_CM1] } { $_TARGETNAME_CM0 configure -rtos hwthread $_TARGETNAME_CM1 configure -rtos hwthread target smp $_TARGETNAME_CM0 $_TARGETNAME_CM1 } if { [info exists _TARGETNAME_RV0] && [info exists _TARGETNAME_RV1] } { $_TARGETNAME_RV0 configure -rtos hwthread $_TARGETNAME_RV1 configure -rtos hwthread target smp $_TARGETNAME_RV0 $_TARGETNAME_RV1 } } if { [info exists _TARGETNAME_0] } { set _FLASH_TARGET $_TARGETNAME_0 } if { ![info exists _FLASH_TARGET] && [info exists _TARGETNAME_1] } { set _FLASH_TARGET $_TARGETNAME_1 if { [info exists _TARGETNAME_CM1] && [info exists _TARGETNAME_RV1] } { echo "Info : $_CHIPNAME.flash will be handled by $_TARGETNAME_1 without switching" } } if { [info exists _FLASH_TARGET] } { # QSPI flash size detection during gdb connect requires to back-up RAM set _WKA_BACKUP [expr { $_FLASHSIZE == 0 }] $_FLASH_TARGET configure -work-area-phys 0x20010000 -work-area-size $_WORKAREASIZE -work-area-backup $_WKA_BACKUP if { [info exists _TARGETNAME_CM0] && [info exists _TARGETNAME_RV0] } { $_TARGETNAME_RV0 configure -work-area-phys 0x20010000 \ -work-area-size $_WORKAREASIZE -work-area-backup $_WKA_BACKUP echo "Info : $_CHIPNAME.flash will be handled by the active one of $_FLASH_TARGET and $_TARGETNAME_RV0 cores" } set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME rp2xxx 0x10000000 $_FLASHSIZE 0 0 $_FLASH_TARGET } if { [info exists _TARGETNAME_1] } { # Alias to ensure gdb connecting to core 1 gets the correct memory map flash bank $_CHIPNAME.alias virtual 0x10000000 0 0 0 $_TARGETNAME_1 $_FLASHNAME } if { [info exists _TARGETNAME_0] } { # Select core 0 targets $_TARGETNAME_0 } # Cold reset resets everything except DP proc cold_reset { { __CHIPNAME "" } } { if { $__CHIPNAME == "" } { global _CHIPNAME set __CHIPNAME $_CHIPNAME } poll off # set CDBGRSTREQ (and keep set CSYSPWRUPREQ and CDBGPWRUPREQ) $__CHIPNAME.dap dpreg 4 0x54000000 set dpstat [$__CHIPNAME.dap dpreg 4] if { [expr { $dpstat & 0xcc000000 }] != 0xcc000000 } { echo "Warn : dpstat_reset failed, DP STAT $dpstat" } $__CHIPNAME.dap dpreg 4 0x50000000 dap init poll on } # Rescue reset resets everything except DP and RP_AP # Both Cortex-M33 cores stop in bootrom proc rescue_reset { { __CHIPNAME "" } } { if { $__CHIPNAME == "" } { global _CHIPNAME set __CHIPNAME $_CHIPNAME } poll off # set bit RESCUE_RESTART in RP_AP: CTRL register $__CHIPNAME.dap apreg 0x80000 0 0x80000000 $__CHIPNAME.dap apreg 0x80000 0 0 dap init poll on if { [lsearch [target names] $__CHIPNAME.cm0] < 0 } { echo "Info : restart OpenOCD with 'set USE_CORE { cm0 cm1 }' to debug after rescue" } } if { $_RESCUE } { init rescue_reset } proc _rv_reset_init { } { set chip_id [format 0x%08x [read_memory 0x40000000 32 1]] # Version related workarounds switch $chip_id { 0x00004927 { # A0 # remove IO_QSPI isolation mww 0x40030014 0 mww 0x4003001c 0 mww 0x40030024 0 mww 0x4003002c 0 mww 0x40030034 0 mww 0x4003003c 0 } } rp2xxx rom_api_call FC }