stlink: Add PID for V3 device without MSD
[fw/openocd] / tcl / target / psoc4.cfg
index d443b014499e1838ba26ba9c4f535e932a3ca989..cffcbc7538fa6763212593f68099541f9293e3cb 100644 (file)
@@ -1,4 +1,4 @@
-# script for Cypress PSoC 41xx/42xx family
+# script for Cypress PSoC 4 devices
 
 #
 # PSoC 4 devices support SWD transports only.
@@ -26,16 +26,17 @@ if { [info exists CPUTAPID] } {
 }
 
 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 -chain-position $_TARGETNAME
+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_khz 1500
+adapter speed 1500
 
 # Reset, bloody PSoC 4 reset
 #
@@ -53,8 +54,14 @@ adapter_khz 1500
 # 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.
+# 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.
@@ -66,11 +73,34 @@ if {![using_hla]} {
    cortex_m reset_config sysresetreq
 }
 
+proc psoc4_get_family_id {} {
+       set err [catch "mem2array romtable_pid 32 0xF0000FE0 3"]
+       if { $err } {
+               return 0
+       }
+       if { [expr {$romtable_pid(0) & 0xffffff00 }]
+         || [expr {$romtable_pid(1) & 0xffffff00 }]
+         || [expr {$romtable_pid(2) & 0xffffff00 }] } {
+               echo "Unexpected data in ROMTABLE"
+               return 0
+       }
+       set designer_id [expr {(( $romtable_pid(1) & 0xf0 ) >> 4) | (( $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 {( $romtable_pid(0) & 0xff ) | (( $romtable_pid(1) & 0xf ) << 8 ) }]
+       return $family_id
+}
+
 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";
+       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 psoc4.cpu
+       set t $_TARGETNAME
 
        # If this target must be halted...
        set halt -1
@@ -87,17 +117,42 @@ proc ocd_process_reset_inner { MODE } {
                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
 
-       set TEST_MODE 0x40030014
-       if { $halt == 1 } {
-               mww $TEST_MODE 0x80000000
+       if { $halt && $PSOC4_USE_ACQUIRE } {
+               catch { [adapter name] acquire_psoc }
+               $t arp_examine
        } else {
-               mww $TEST_MODE 0
+               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 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
@@ -124,18 +179,27 @@ proc ocd_process_reset_inner { MODE } {
                }
 
                # Check if PSoC CPU is stopped in system ROM
-               set pc [ocd_reg pc]
+               set pc [reg pc]
                regsub {pc[^:]*: } $pc "" pc
                if { $pc < 0x10000000 || $pc > 0x1000ffff } {
-                       return -code error [format "TARGET: %s - Not halted in system ROM, use 'reset_config none'" $t]
+                       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
                mem2array value 32 0 2
-               reg pc [expr $value(1) & 0xfffffffe ]
+               reg pc [expr {$value(1) & 0xfffffffe} ]
                reg msp $value(0)
 
-               mww $TEST_MODE 0
+               if { $PSOC4_TEST_MODE_WORKAROUND } {
+                       catch { mww $TEST_MODE 0 }
+               }
        }
 
        #Pass 2 - if needed "init"