cffcbc7538fa6763212593f68099541f9293e3cb
[fw/openocd] / tcl / target / psoc4.cfg
1 # script for Cypress PSoC 4 devices
2
3 #
4 # PSoC 4 devices support SWD transports only.
5 #
6 source [find target/swj-dp.tcl]
7
8 if { [info exists CHIPNAME] } {
9    set _CHIPNAME $CHIPNAME
10 } else {
11    set _CHIPNAME psoc4
12 }
13
14 # Work-area is a space in RAM used for flash programming
15 # By default use 4kB
16 if { [info exists WORKAREASIZE] } {
17    set _WORKAREASIZE $WORKAREASIZE
18 } else {
19    set _WORKAREASIZE 0x1000
20 }
21
22 if { [info exists CPUTAPID] } {
23    set _CPUTAPID $CPUTAPID
24 } else {
25    set _CPUTAPID 0x0bb11477
26 }
27
28 swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
29 dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
30
31 set _TARGETNAME $_CHIPNAME.cpu
32 target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap
33
34 $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
35
36 set _FLASHNAME $_CHIPNAME.flash
37 flash bank $_FLASHNAME psoc4 0 0 0 0 $_TARGETNAME
38
39 adapter speed 1500
40
41 # Reset, bloody PSoC 4 reset
42 #
43 # 1) XRES (nSRST) resets also SWD DP so SWD line reset and DP reinit is needed.
44 # High level adapter stops working after SRST and needs OpenOCD restart.
45 # If your hw does not use SRST for other circuits, use sysresetreq instead
46 #
47 # 2) PSoC 4 executes initialization code from system ROM after reset.
48 # This code subsequently jumps to user flash reset vector address.
49 # Unfortunately the system ROM code is protected from reading and debugging.
50 # Protection breaks vector catch VC_CORERESET used for "reset halt" by cortex_m.
51 #
52 # Cypress uses TEST_MODE flag to loop CPU in system ROM before executing code
53 # from user flash. Programming specifications states that TEST_MODE flag must be
54 # set in time frame 400 usec delayed about 1 msec from reset.
55 #
56 # OpenOCD have no standard way how to set TEST_MODE in specified time frame.
57 # As a workaround the TEST_MODE flag is set before reset instead.
58 # It worked for the oldest family PSoC4100/4200 even though it is not guaranteed
59 # by specification.
60 #
61 # Newer families like PSoC 4000, 4100M, 4200M, 4100L, 4200L and PSoC 4 BLE
62 # clear TEST_MODE flag during device reset so workaround is not possible.
63 # Use a KitProg adapter for these devices or "reset halt" will not stop
64 # before executing user code.
65 #
66 # 3) SWD cannot be connected during system initialization after reset.
67 # This might be a reason for unconnecting ST-Link v2 when deasserting reset.
68 # As a workaround arp_reset deassert is not called for hla
69
70 if {![using_hla]} {
71    # if srst is not fitted use SYSRESETREQ to
72    # perform a soft reset
73    cortex_m reset_config sysresetreq
74 }
75
76 proc psoc4_get_family_id {} {
77         set err [catch "mem2array romtable_pid 32 0xF0000FE0 3"]
78         if { $err } {
79                 return 0
80         }
81         if { [expr {$romtable_pid(0) & 0xffffff00 }]
82           || [expr {$romtable_pid(1) & 0xffffff00 }]
83           || [expr {$romtable_pid(2) & 0xffffff00 }] } {
84                 echo "Unexpected data in ROMTABLE"
85                 return 0
86         }
87         set designer_id [expr {(( $romtable_pid(1) & 0xf0 ) >> 4) | (( $romtable_pid(2) & 0xf ) << 4 ) }]
88         if { $designer_id != 0xb4 } {
89                 echo [format "ROMTABLE Designer ID 0x%02x is not Cypress" $designer_id]
90                 return 0
91         }
92         set family_id [expr {( $romtable_pid(0) & 0xff ) | (( $romtable_pid(1) & 0xf ) << 8 ) }]
93         return $family_id
94 }
95
96 proc ocd_process_reset_inner { MODE } {
97         global PSOC4_USE_ACQUIRE PSOC4_TEST_MODE_WORKAROUND
98         global _TARGETNAME
99
100         if { 0 != [string compare $_TARGETNAME [target names]] } {
101                 return -code error "PSoC 4 reset can handle only one $_TARGETNAME target";
102         }
103         set t $_TARGETNAME
104
105         # If this target must be halted...
106         set halt -1
107         if { 0 == [string compare $MODE halt] } {
108                 set halt 1
109         }
110         if { 0 == [string compare $MODE init] } {
111                 set halt 1;
112         }
113         if { 0 == [string compare $MODE run ] } {
114                 set halt 0;
115         }
116         if { $halt < 0 } {
117                 return -code error "Invalid mode: $MODE, must be one of: halt, init, or run";
118         }
119
120         if { ! [info exists PSOC4_USE_ACQUIRE] } {
121                 if { 0 == [string compare [adapter name] kitprog ] } {
122                         set PSOC4_USE_ACQUIRE 1
123                 } else {
124                         set PSOC4_USE_ACQUIRE 0
125                 }
126         }
127         if { $PSOC4_USE_ACQUIRE } {
128                 set PSOC4_TEST_MODE_WORKAROUND 0
129         } elseif { ! [info exists PSOC4_TEST_MODE_WORKAROUND] } {
130                 if { [psoc4_get_family_id] == 0x93 } {
131                         set PSOC4_TEST_MODE_WORKAROUND 1
132                 } else {
133                         set PSOC4_TEST_MODE_WORKAROUND 0
134                 }
135         }
136
137         #$t invoke-event reset-start
138         $t invoke-event reset-assert-pre
139
140         if { $halt && $PSOC4_USE_ACQUIRE } {
141                 catch { [adapter name] acquire_psoc }
142                 $t arp_examine
143         } else {
144                 if { $PSOC4_TEST_MODE_WORKAROUND } {
145                         set TEST_MODE 0x40030014
146                         if { $halt == 1 } {
147                                 catch { mww $TEST_MODE 0x80000000 }
148                         } else {
149                                 catch { mww $TEST_MODE 0 }
150                         }
151                 }
152
153                 $t arp_reset assert 0
154         }
155
156         $t invoke-event reset-assert-post
157         $t invoke-event reset-deassert-pre
158         if {![using_hla]} {     # workaround ST-Link v2 fails and forcing reconnect
159                 $t arp_reset deassert 0
160         }
161         $t invoke-event reset-deassert-post
162
163         # Pass 1 - Now wait for any halt (requested as part of reset
164         # assert/deassert) to happen.  Ideally it takes effect without
165         # first executing any instructions.
166         if { $halt } {
167                 # Now PSoC CPU should loop in system ROM
168                 $t arp_waitstate running 200
169                 $t arp_halt
170
171                 # Catch, but ignore any errors.
172                 catch { $t arp_waitstate halted 1000 }
173
174                 # Did we succeed?
175                 set s [$t curstate]
176
177                 if { 0 != [string compare $s "halted" ] } {
178                         return -code error [format "TARGET: %s - Not halted" $t]
179                 }
180
181                 # Check if PSoC CPU is stopped in system ROM
182                 set pc [reg pc]
183                 regsub {pc[^:]*: } $pc "" pc
184                 if { $pc < 0x10000000 || $pc > 0x1000ffff } {
185                         set hint ""
186                         set family_id [psoc4_get_family_id]
187                         if { $family_id == 0x93 } {
188                                 set hint ", use 'reset_config none'"
189                         } elseif { $family_id > 0x93 } {
190                                 set hint ", use a KitProg adapter"
191                         }
192                         return -code error [format "TARGET: %s - Not halted in system ROM%s" $t $hint]
193                 }
194
195                 # Set registers to reset vector values
196                 mem2array value 32 0 2
197                 reg pc [expr {$value(1) & 0xfffffffe} ]
198                 reg msp $value(0)
199
200                 if { $PSOC4_TEST_MODE_WORKAROUND } {
201                         catch { mww $TEST_MODE 0 }
202                 }
203         }
204
205         #Pass 2 - if needed "init"
206         if { 0 == [string compare init $MODE] } {
207                 set err [catch "$t arp_waitstate halted 5000"]
208
209                 # Did it halt?
210                 if { $err == 0 } {
211                         $t invoke-event reset-init
212                 }
213         }
214
215         $t invoke-event reset-end
216 }