openocd/tcl/target/psoc4.cfg

153 lines
4.2 KiB
INI

# script for Cypress PSoC 41xx/42xx family
#
# 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
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m -chain-position $_TARGETNAME
$_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_khz 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.
# TEST_MODE flag is set before reset instead. It worked for tested chips
# despite it is not guaranteed by specification.
#
# 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 ocd_process_reset_inner { MODE } {
if { 0 != [string compare psoc4.cpu [target names]] } {
return -code error "PSoC 4 reset can handle only one psoc4.cpu target";
}
set t psoc4.cpu
# 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";
}
#$t invoke-event reset-start
$t invoke-event reset-assert-pre
set TEST_MODE 0x40030014
if { $halt == 1 } {
mww $TEST_MODE 0x80000000
} else {
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 [ocd_reg pc]
regsub {pc[^:]*: } $pc "" pc
if { $pc < 0x10000000 || $pc > 0x1000ffff } {
return -code error [format "TARGET: %s - Not halted is system ROM" $t]
}
# Set registers to reset vector values
mem2array value 32 0 2
reg pc [expr $value(1) & 0xfffffffe ]
reg msp $value(0)
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
}