# SPDX-License-Identifier: GPL-2.0-or-later # script for Cypress PSoC 4 devices # # PSoC 4 devices support SWD transports only. # source [find target/swj-dp.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { set _CHIPNAME psoc4 } # Work-area is a space in RAM used for flash programming # By default use 4kB if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { set _WORKAREASIZE 0x1000 } if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID } else { set _CPUTAPID 0x0bb11477 } swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 set _FLASHNAME $_CHIPNAME.flash flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME adapter speed 1500 # Reset, bloody PSoC 4 reset # # 1) XRES (nSRST) resets also SWD DP so SWD line reset and DP reinit is needed. # High level adapter stops working after SRST and needs OpenOCD restart. # If your hw does not use SRST for other circuits, use sysresetreq instead # # 2) PSoC 4 executes initialization code from system ROM after reset. # This code subsequently jumps to user flash reset vector address. # Unfortunately the system ROM code is protected from reading and debugging. # Protection breaks vector catch VC_CORERESET used for "reset halt" by cortex_m. # # Cypress uses TEST_MODE flag to loop CPU in system ROM before executing code # from user flash. Programming specifications states that TEST_MODE flag must be # set in time frame 400 usec delayed about 1 msec from reset. # # OpenOCD have no standard way how to set TEST_MODE in specified time frame. # As a workaround the TEST_MODE flag is set before reset instead. # It worked for the oldest family PSoC4100/4200 even though it is not guaranteed # by specification. # # Newer families like PSoC 4000, 4100M, 4200M, 4100L, 4200L and PSoC 4 BLE # clear TEST_MODE flag during device reset so workaround is not possible. # Use a KitProg adapter for these devices or "reset halt" will not stop # before executing user code. # # 3) SWD cannot be connected during system initialization after reset. # This might be a reason for unconnecting ST-Link v2 when deasserting reset. # As a workaround arp_reset deassert is not called for hla if {![using_hla]} { # if srst is not fitted use SYSRESETREQ to # perform a soft reset cortex_m reset_config sysresetreq } proc psoc4_get_family_id {} { set err [catch {set romtable_pid [read_memory 0xF0000FE0 32 3]}] if { $err } { return 0 } if { [expr {[lindex $romtable_pid 0] & 0xffffff00 }] || [expr {[lindex $romtable_pid 1] & 0xffffff00 }] || [expr {[lindex $romtable_pid 2] & 0xffffff00 }] } { echo "Unexpected data in ROMTABLE" return 0 } set designer_id [expr {(( [lindex $romtable_pid 1] & 0xf0 ) >> 4) | (( [lindex $romtable_pid 2] & 0xf ) << 4 ) }] if { $designer_id != 0xb4 } { echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id] return 0 } set family_id [expr {( [lindex $romtable_pid 0] & 0xff ) | (( [lindex $romtable_pid 1] & 0xf ) << 8 ) }] return $family_id } proc ocd_process_reset_inner { MODE } { global PSOC4_USE_ACQUIRE PSOC4_TEST_MODE_WORKAROUND global _TARGETNAME if { 0 != [string compare $_TARGETNAME [target names]] } { return -code error "PSoC 4 reset can handle only one $_TARGETNAME target"; } set t $_TARGETNAME # If this target must be halted... set halt -1 if { 0 == [string compare $MODE halt] } { set halt 1 } if { 0 == [string compare $MODE init] } { set halt 1; } if { 0 == [string compare $MODE run ] } { set halt 0; } if { $halt < 0 } { return -code error "Invalid mode: $MODE, must be one of: halt, init, or run"; } if { ! [info exists PSOC4_USE_ACQUIRE] } { if { 0 == [string compare [adapter name] kitprog ] } { set PSOC4_USE_ACQUIRE 1 } else { set PSOC4_USE_ACQUIRE 0 } } if { $PSOC4_USE_ACQUIRE } { set PSOC4_TEST_MODE_WORKAROUND 0 } elseif { ! [info exists PSOC4_TEST_MODE_WORKAROUND] } { if { [psoc4_get_family_id] == 0x93 } { set PSOC4_TEST_MODE_WORKAROUND 1 } else { set PSOC4_TEST_MODE_WORKAROUND 0 } } #$t invoke-event reset-start $t invoke-event reset-assert-pre if { $halt && $PSOC4_USE_ACQUIRE } { catch { [adapter name] acquire_psoc } $t arp_examine } else { if { $PSOC4_TEST_MODE_WORKAROUND } { set TEST_MODE 0x40030014 if { $halt == 1 } { catch { mww $TEST_MODE 0x80000000 } } else { catch { mww $TEST_MODE 0 } } } $t arp_reset assert 0 } $t invoke-event reset-assert-post $t invoke-event reset-deassert-pre if {![using_hla]} { # workaround ST-Link v2 fails and forcing reconnect $t arp_reset deassert 0 } $t invoke-event reset-deassert-post # Pass 1 - Now wait for any halt (requested as part of reset # assert/deassert) to happen. Ideally it takes effect without # first executing any instructions. if { $halt } { # Now PSoC CPU should loop in system ROM $t arp_waitstate running 200 $t arp_halt # Catch, but ignore any errors. catch { $t arp_waitstate halted 1000 } # Did we succeed? set s [$t curstate] if { 0 != [string compare $s "halted" ] } { return -code error [format "TARGET: %s - Not halted" $t] } # Check if PSoC CPU is stopped in system ROM set pc [reg pc] regsub {pc[^:]*: } $pc "" pc if { $pc < 0x10000000 || $pc > 0x1000ffff } { set hint "" set family_id [psoc4_get_family_id] if { $family_id == 0x93 } { set hint ", use 'reset_config none'" } elseif { $family_id > 0x93 } { set hint ", use a KitProg adapter" } return -code error [format "TARGET: %s - Not halted in system ROM%s" $t $hint] } # Set registers to reset vector values set value [read_memory 0x0 32 2] reg pc [expr {[lindex $value 1] & 0xfffffffe}] reg msp [lindex $value 0] if { $PSOC4_TEST_MODE_WORKAROUND } { catch { mww $TEST_MODE 0 } } } #Pass 2 - if needed "init" if { 0 == [string compare init $MODE] } { set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { $t invoke-event reset-init } } $t invoke-event reset-end }