summaryrefslogtreecommitdiff
path: root/src/target/startup.tcl
diff options
context:
space:
mode:
Diffstat (limited to 'src/target/startup.tcl')
-rw-r--r--src/target/startup.tcl165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/target/startup.tcl b/src/target/startup.tcl
new file mode 100644
index 00000000..d480f335
--- /dev/null
+++ b/src/target/startup.tcl
@@ -0,0 +1,165 @@
+#########
+
+# This reset logic may be overridden by board/target/... scripts as needed
+# to provide a reset that, if possible, is close to a power-up reset.
+#
+# Exit requirements include: (a) JTAG must be working, (b) the scan
+# chain was validated with "jtag arp_init" (or equivalent), (c) nothing
+# stays in reset. No TAP-specific scans were performed. It's OK if
+# some targets haven't been reset yet; they may need TAP-specific scans.
+#
+# The "mode" values include: halt, init, run (from "reset" command);
+# startup (at OpenOCD server startup, when JTAG may not yet work); and
+# potentially more (for reset types like cold, warm, etc)
+proc init_reset { mode } {
+ jtag arp_init-reset
+}
+
+
+global in_process_reset
+set in_process_reset 0
+
+# Catch reset recursion
+proc ocd_process_reset { MODE } {
+ global in_process_reset
+ if {$in_process_reset} {
+ set in_process_reset 0
+ return -code error "'reset' can not be invoked recursively"
+ }
+
+ set in_process_reset 1
+ set success [expr [catch {ocd_process_reset_inner $MODE} result]==0]
+ set in_process_reset 0
+
+ if {$success} {
+ return $result
+ } else {
+ return -code error $result
+ }
+}
+
+proc ocd_process_reset_inner { MODE } {
+ set targets [target names]
+
+ # 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 -error "Invalid mode: $MODE, must be one of: halt, init, or run";
+ }
+
+ # Target event handlers *might* change which TAPs are enabled
+ # or disabled, so we fire all of them. But don't issue any
+ # target "arp_*" commands, which may issue JTAG transactions,
+ # unless we know the underlying TAP is active.
+ #
+ # NOTE: ARP == "Advanced Reset Process" ... "advanced" is
+ # relative to a previous restrictive scheme
+
+ foreach t $targets {
+ # New event script.
+ $t invoke-event reset-start
+ }
+
+ # Use TRST or TMS/TCK operations to reset all the tap controllers.
+ # TAP reset events get reported; they might enable some taps.
+ init_reset $MODE
+
+ # Examine all targets on enabled taps.
+ foreach t $targets {
+ if {[jtag tapisenabled [$t cget -chain-position]]} {
+ $t arp_examine
+ }
+ }
+
+ # Assert SRST, and report the pre/post events.
+ # Note: no target sees SRST before "pre" or after "post".
+ foreach t $targets {
+ $t invoke-event reset-assert-pre
+ }
+ foreach t $targets {
+ # C code needs to know if we expect to 'halt'
+ if {[jtag tapisenabled [$t cget -chain-position]]} {
+ $t arp_reset assert $halt
+ }
+ }
+ foreach t $targets {
+ $t invoke-event reset-assert-post
+ }
+
+ # Now de-assert SRST, and report the pre/post events.
+ # Note: no target sees !SRST before "pre" or after "post".
+ foreach t $targets {
+ $t invoke-event reset-deassert-pre
+ }
+ foreach t $targets {
+ # Again, de-assert code needs to know if we 'halt'
+ if {[jtag tapisenabled [$t cget -chain-position]]} {
+ $t arp_reset deassert $halt
+ }
+ }
+ foreach t $targets {
+ $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 } {
+ foreach t $targets {
+ if {[jtag tapisenabled [$t cget -chain-position]] == 0} {
+ continue
+ }
+
+ # Wait upto 1 second for target to halt. Why 1sec? Cause
+ # the JTAG tap reset signal might be hooked to a slow
+ # resistor/capacitor circuit - and it might take a while
+ # to charge
+
+ # 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 -error [format "TARGET: %s - Not halted" $t]
+ }
+ }
+ }
+
+ #Pass 2 - if needed "init"
+ if { 0 == [string compare init $MODE] } {
+ foreach t $targets {
+ if {[jtag tapisenabled [$t cget -chain-position]] == 0} {
+ continue
+ }
+
+ set err [catch "$t arp_waitstate halted 5000"]
+ # Did it halt?
+ if { $err == 0 } {
+ $t invoke-event reset-init
+ }
+ }
+ }
+
+ foreach t $targets {
+ $t invoke-event reset-end
+ }
+}
+
+#########
+
+# Temporary migration aid. May be removed starting in January 2011.
+proc armv4_5 params {
+ echo "DEPRECATED! use 'arm $params' not 'armv4_5 $params'"
+ arm $params
+}