#!/usr/bin/tclsh8.4
-if {[llength $argv] != 3} { error "need args: serial port, map file, picno" }
-set port [lindex $argv 0]
-set map [lindex $argv 1]
-set slave [lindex $argv 2]
-
-set m [open $map]
-set block preable
-set headings unknown
-set inblk 3
+proc debug {s} { puts "$s" }
proc manyset {list args} {
foreach val $list var $args { upvar 1 $var my; set my $val }
default { error "unknown $thing lockind $lockind in $l" }
}
-while {[gets $m l] >= 0} {
- if {![regexp {\S} $l]} {
- set inblk 0
- set section unknown
- set headings n/a
- } elseif {$inblk==0 && [regexp {^\s+(\S.*\S)\s*$} $l dummy block]} {
- incr inblk
- } elseif {$inblk==1} {
- set headings [string trim $l]
- incr inblk
- } elseif {$inblk==2 && [regexp {^[- \t]+$} $l]} {
- incr inblk
- } elseif {[inblk {^Section Info$} \
- {^Section\s+Type\s+Address\s+Location\s+Size\(Bytes\)$}]} {
- manyset $l sec type addr lockind size
- switch -exact $type code { continue } udata { } \
- default { error "unknown section type $type in $l" }
- if {[wantlockind $lockind section $l]<=0} continue
- set addr [format 0x%08x $addr]
- lappend sections [list $addr $sec [format 0x%08x $size]]
- } elseif {[inblk {^Symbols$} \
- {^Name\s+Address\s+Location\s+Storage\s+File$}]} {
- manyset $l sym addr lockind storage file
- if {![wantlockind $lockind symbol $l]} continue
- switch -exact $storage {
- extern { set sym [list {} $sym] }
- static {
- regexp {^(.*)\.asm$} $file dummy file
- set sym [list $file: $sym]
- }
- default { error "unknown storage $storage in $l" }
- }
- set addr [format 0x%08x $addr]
- if {[string compare $lockind data]} {
- set sv symbolsbylockind($lockind)
- } else {
- set sv symbols
- }
- lappend $sv [list $addr $sym]
- } elseif {$inblk==3} {
- } else {
- error "unknown $inblk <$block> <$headings> $l"
- }
-}
-
-set ok {
- INTCON* FSR2*
- OSCCON LVDCON WDTCON RCON
- T1CON T2CON
- SSPADD SSPSTAT SSPCON1 SSPCON2
- ADRESH ADRESL ADCON*
- CCPR1* CCP1CON
- ECCPR1* ECCP1DEL ECCPAS
- CMCON CVRCON T3CON
- SPBRG TXSTA RXSTA
- EEADR EEDATA
- IPR* PIR* PIE*
- TRIS* LAT*
-}
-
-set h [open /usr/share/gputils/header/p18f458.inc]
-set section unknown
-set lastaddr -1
-while {[gets $h l]>=0} {
- if {[regexp {^\;\-\-+\s+(\S.*\S)\s+\-\-+$} $l dummy section]} {
- continue
- } elseif {![regexp {^Register Files$} $section]} {
- continue
- } elseif {[regexp -nocase \
- {^([a-z][a-z0-9]*)\s+equ\s+h\'0(f[0-9a-f]{2})\'\s*$} \
- $l dummy sym loc]} {
- set addr [format 0x%08x 0x$loc]
- foreach pat $ok {
- if {[string match $pat $sym]} {
- if {$addr != $lastaddr} {
- lappend sections [list $addr =SFRs= 0x1]
- set lastaddr $addr
- }
- lappend symbols [list $addr [list SFR $sym]]
- }
- }
- } elseif {[regexp -nocase {^\;\s*reserved} $l]} {
- } elseif {![regexp {\S} $l]} {
- } else {
- error "unknown <$section> $l"
- }
+proc addendlast {v ev evn} {
+ upvar #0 $v syms
+ lappend syms [list [lindex [lindex $syms end] 0] [list {} (lastsymbol)]]
+ lappend syms [list [format 0x%08lx $ev] [list {} $evn]]
}
-lappend sections [list 0x1000 =END= 0]
-set sections [lsort $sections]
-set symbols [lsort $symbols]
-
-set p [open $port {RDWR NONBLOCK} 0]
-exec stty -F $port min 1 time 0 -istrip -ocrnl -onlcr -onocr -opost \
- -ctlecho -echo -echoe -echok -echonl -iexten -isig \
- -icanon -icrnl \
- 9600 clocal cread -crtscts -hup -parenb cs8 -cstopb \
- -ixoff bs0 cr0 ff0 nl0 -ofill -olcuc
-
-fconfigure $p -blocking yes -buffering none \
- -translation binary -encoding binary
-
-fconfigure stdout -buffering none
-
-set ms [expr {
- $slave < 0 ? "t" :
- $slave ? "s" :
- "m"
-}]
-
proc xmit {b} {
global p
-#puts stderr >xmit|$b<
+ #debug >xmit|$b<
set b [expr $b]
set c [binary format c* $b]
puts -nonewline $p [format %c $b]
set c [read $p 1]
binary scan $c c* d
if {![llength $d]} { error "comms eof" }
- lappend l $d
+ lappend l [expr {$d & 0x0ff}]
incr n -1
}
return $l
}
+proc junkrecv {} {
+ global p
+ fconfigure $p -blocking no
+ while {[string length [read $p 1024]]} { }
+ fconfigure $p -blocking yes
+}
+
+proc selectslave_slave {slave} {
+ xmit "$slave ^ 0x30"
+}
proc selectslave_s {} {
global slave
- xmit "$slave ^ 0x30"
+ selectslave_slave $slave
}
-proc xmit_s {b} {
+proc xmit_slave {slave b} {
xmit "$b | 0x80"
- selectslave_s
+ selectslave_slave $slave
recv 1
}
-proc setup_m {} { xmit 0 }
-proc setup_s {} { xmit 0; xmit_s 0 }
+proc xmit_s {b} {
+ global slave
+ xmit_slave $slave $b
+}
+
+proc pause {t} {
+ global pause_var
+ catch { unset pause_var }
+ after $t {set pause_var y}
+ vwait pause_var
+}
+
+proc setup_m {} { xmit 0; xmit 0; xmit 0; pause 250; junkrecv }
+proc setup_s {} { setup_m; xmit 128; pause 256; junkrecv; xmit_s 0; xmit_s 0 }
proc setup_t {} { }
proc selectaddr_ms {xmit a} {
return $l
}
-set readcursor -1
-
proc readbytes {addr n} {
global readcursor ms
if {$readcursor != $addr} {
thingbynum $thing $num
}
+
+proc p {s} { puts -nonewline $s }
+
+proc reset_s {val min max} {
+ for {set slave $min} {$slave < $max} {incr slave} {
+ xmit_slave $slave $val
+ }
+}
+
+proc reset_m {arg} {
+ if {[regexp {^(\d+)\.(\d+)} $arg min max]} {
+ } elseif {[regexp {^(\d+)} $arg max]} {
+ set min 1
+ } else {
+ error "--reset arg $arg wrong"
+ }
+ setup_m
+ reset_s 0x00 $min $max
+ reset_s 0x00 $min $max
+ reset_s 0x09 $min $max
+ xmit 0x09
+}
+
+proc badusage {m} {
+ set m "bad usage: $m"
+ append m {
+usage: .../crashread <port> <map-file> <picno>
+ pass `-1' for <picno> for test (data memory map) mode only
+ pass `reset' for <map-file> to reset pics (then
+ <picno> should be <lastpicno+1> or <firstslave>-<lastpicno+1>)
+}
+ error $m
+}
+
+if {[llength $argv] != 3} { badusage "wrong # args" }
+
+set port [lindex $argv 0]
+set map [lindex $argv 1]
+set slave [lindex $argv 2]
+
+set p [open $port {RDWR NONBLOCK} 0]
+exec stty -F $port min 1 time 0 -istrip -ocrnl -onlcr -onocr -opost \
+ -ctlecho -echo -echoe -echok -echonl -iexten -isig \
+ -icanon -icrnl \
+ 9600 clocal cread -crtscts -hup -parenb cs8 -cstopb \
+ -ixoff bs0 cr0 ff0 nl0 -ofill -olcuc
+
+fconfigure $p -blocking yes -buffering none \
+ -translation binary -encoding binary
+
+fconfigure stdout -buffering none
+
+if {![string compare reset $map]} {
+ reset_m $slave
+ exit 0
+}
+
+set m [open $map]
+set block preable
+set headings unknown
+set inblk 3
+
+while {[gets $m l] >= 0} {
+ if {![regexp {\S} $l]} {
+ set inblk 0
+ set section unknown
+ set headings n/a
+ } elseif {$inblk==0 && [regexp {^\s+(\S.*\S)\s*$} $l dummy block]} {
+ incr inblk
+ } elseif {$inblk==1} {
+ set headings [string trim $l]
+ incr inblk
+ } elseif {$inblk==2 && [regexp {^[- \t]+$} $l]} {
+ incr inblk
+ } elseif {[inblk {^Section Info$} \
+ {^Section\s+Type\s+Address\s+Location\s+Size\(Bytes\)$}]} {
+ manyset $l sec type addr lockind size
+ switch -exact $type code { continue } udata { } \
+ default { error "unknown section type $type in $l" }
+ if {[wantlockind $lockind section $l]<=0} continue
+ set addr [format 0x%08x $addr]
+ lappend sections [list $addr $sec [format 0x%08x $size]]
+ } elseif {[inblk {^Symbols$} \
+ {^Name\s+Address\s+Location\s+Storage\s+File$}]} {
+ manyset $l sym addr lockind storage file
+ if {![wantlockind $lockind symbol $l]} continue
+ switch -exact $storage {
+ extern { set sym [list {} $sym] }
+ static {
+ regexp {^(.*)\.asm$} $file dummy file
+ set sym [list $file: $sym]
+ }
+ default { error "unknown storage $storage in $l" }
+ }
+ set addr [format 0x%08x $addr]
+ if {[string compare $lockind data]} {
+ set sv symbolsbylockind($lockind)
+ } else {
+ set sv symbols
+ set smap($sym) $addr
+ }
+ lappend $sv [list $addr $sym]
+ } elseif {$inblk==3} {
+ } else {
+ error "unknown $inblk <$block> <$headings> $l"
+ }
+}
+
+set ok {
+ INTCON* FSR2*
+ OSCCON LVDCON WDTCON RCON
+ T1CON T2CON
+ SSPADD SSPSTAT SSPCON1 SSPCON2
+ ADRESH ADRESL ADCON*
+ CCPR1* CCP1CON
+ ECCPR1* ECCP1DEL ECCPAS
+ CMCON CVRCON T3CON
+ SPBRG TXSTA RXSTA
+ EEADR EEDATA
+ IPR* PIR* PIE*
+ TRIS* LAT*
+}
+
+set h [open /usr/share/gputils/header/p18f458.inc]
+set section unknown
+set lastaddr -1
+while {[gets $h l]>=0} {
+ if {[regexp {^\;\-\-+\s+(\S.*\S)\s+\-\-+$} $l dummy section]} {
+ continue
+ } elseif {![regexp {^Register Files$} $section]} {
+ continue
+ } elseif {[regexp -nocase \
+ {^([a-z][a-z0-9]*)\s+equ\s+h\'0(f[0-9a-f]{2})\'\s*$} \
+ $l dummy sym loc]} {
+ set addr [format 0x%08x 0x$loc]
+ foreach pat $ok {
+ if {[string match $pat $sym]} {
+ if {$addr != $lastaddr} {
+ lappend sections [list $addr =SFRs= 0x1]
+ set lastaddr $addr
+ }
+ lappend symbols [list $addr [list SFR $sym]]
+ }
+ }
+ } elseif {[regexp -nocase {^\;\s*reserved} $l]} {
+ } elseif {![regexp {\S} $l]} {
+ } else {
+ error "unknown <$section> $l"
+ }
+}
+
+lappend symbols {0x00000060 {=udata,!acs=}}
+#lappend symbols {0x00000f00 {=SFRs,!acs=}}
+lappend symbols {0x00000f60 {=SFRs,acs= {}}}
+lappend sections {0x00000f00 {=SFRs=} 0}
+#lappend sections {0x00000060 {==========UDATA,!ACS===========} 0}
+#lappend sections {0x00000f60 {==========SFRs,ACS===========} 0}
+
+lappend sections [list 0x1000 =END= 0]
+
+proc sortthings {} {
+ foreach tosort {sections symbols symbolsbylockind(program)} {
+ upvar #0 $tosort ts
+ set ts [lsort [set ts]]
+ }
+}
+set readcursor -1
+
+set ms [expr {
+ $slave < 0 ? "t" :
+ $slave ? "s" :
+ "m"
+}]
+
thingbynum section 0
thingbynum symbol 0
set shownsection {}
set insection 0
set addr 0
set now_max 4
-set inline -1
set displine 0
-
-proc p {s} { puts -nonewline $s }
+set inline 0
+set shownsection {}
setup_$ms
+proc queue_show {kind value} {
+ upvar #0 q_$kind queued
+ lappend queued $value
+}
+
+proc p_addr_symbol {a s} {
+ global inline
+ endline
+ p [format "%08x %-15s %-20s" $a [lindex $s 0] [lindex $s 1]]
+ set inline 1
+}
+
proc endline {} {
- global inline displine
- if {$inline} { p "\n"; incr displine }
+ global inline
+ if {!$inline} return
+ p "\n"
set inline 0
}
+proc do_show {} {
+ global addr inline insection q_symbol q_section shownss
+ global shownsection
+ #debug "do_show [format %x $addr] $insection $q_symbol $q_section"
+ if {$inline} { error "do_show inline $addr" }
+ foreach s $q_section {
+ if {![string compare $s $shownsection]} continue
+ p "---------- $s ----------\n"
+ set shownsection $s
+ }
+ set shownss {}
+ foreach s $q_symbol {
+ p_addr_symbol $addr $s
+ set shownss [concat $s]
+ }
+ #debug "shownss>$shownss<"
+ if {!$insection && ![string compare =SFRs= $shownsection]} {
+ endline
+ p "\n"
+ reset_show
+ return
+ }
+ if {![llength $q_symbol]} { p_addr_symbol $addr {} }
+ if {!$insection} {
+ endline
+# p "------------------------------\n"
+ set shownsection {}
+ }
+ reset_show
+}
+
+proc reset_show {} {
+ foreach v {q_section q_symbol} {
+ global $v
+ set $v {}
+ }
+}
+
proc show {sym} {
global insection section displine addr shownsection inline shownss
set showsectionend 0
if {$insection && [string compare $section $shownsection]} {
endline
- p "---------- $section ----------\n"
set shownsection $section
set displine 0
} elseif {!$insection && [string length $shownsection]} {
endline
- p "------------------------------\n"
set shownsection {}
set displine 0
}
endline
}
if {!$inline} {
- p [format "%08x %-15s %-20s" $addr \
- [lindex $sym 0] [lindex $sym 1]]
set inline 1
set shownss $shownsection-$sym
}
}
-set stkptr {panic_vars_section-panic: psave_stkptr}
-set stack {panic_vars_section-panic: panic_stack}
+if {[info exists smap(misc:\ debugp)] && [info exists smap(misc:\ debug)]} {
+ set debugpval [readbytes $smap(misc:\ debugp) 1]
+# puts y1-$debugpval
+# puts y2-$smap(misc:\ debug)
+ set debugpaddr [format 0x%08x [expr {$debugpval+$smap(misc:\ debug)}]]
+# puts y3-$debugpaddr
+ lappend symbols [list $debugpaddr [list "" (debugp)]]
+}
+
+sortthings
+addendlast symbolsbylockind(program) 0x8000 (end)
+set stkptr {panic: psave_stkptr}
+set stack {panic: panic_stack}
+
+reset_show
foreach ss [list $stkptr $stack] { set ccontents($ss) {} }
while {$sectionnum < [llength $sections]} {
+ # So what happens at this address ?
+
set now_section [expr {$sectionchange - $addr}]
- set now_symbol [expr {$symboladdr - $addr}]
if {!$now_section && !$insection} {
+ queue_show section $section
set insection 1
set sectionchange $sectionend
continue
}
- if {!$now_symbol} {
- show $symbol
- thingnext symbol
- continue
- }
if {!$now_section && $insection} {
- if {[string compare $section =SFRs=]} {
- show { }
- }
thingnext section
set insection 0
set sectionchange $sectionaddr
+ continue
+ }
+
+ set now_symbol [expr {$symboladdr - $addr}]
+ if {!$now_symbol} {
+ queue_show symbol $symbol
+ thingnext symbol
+ continue
}
+
+ # OK, that's all the things that we need to say
+ # about this addr.
+
+ # Decide how much to do:
set now $now_symbol
if {$now > $now_section} { set now $now_section }
+
+ #debug "now $now"
+ do_show
+
if {!$insection} {
incr addr $now
continue
}
- if {$now > $now_max} { set now $now_max }
- show {}
- set bytes [readbytes $addr $now]
- foreach b $bytes {
- set h [format "%02x" [expr {$b & 0xff}]]
- p " $h"
- if {[info exists ccontents($shownss)]} {
- append ccontents($shownss) $h
+
+ while {$now > 0} {
+ set nownow $now
+ if {$nownow > $now_max} { set nownow $now_max }
+ set bytes [readbytes $addr $nownow]
+ foreach b $bytes {
+ set h [format "%02x" [expr {$b & 0xff}]]
+ p " $h"
+ if {[info exists ccontents($shownss)]} {
+ append ccontents($shownss) $h
+ }
+ incr addr
}
- incr addr
+ incr now -$nownow
}
- set inline 1
+ endline
}
-endline
set stackdepth 31
if {$si == $stkptr+1} { p " - - - - -\n" }
}
-foreach v {stkptr stack} { set $v $ccontents([set $v]) }
+foreach v {stkptr stack} {
+ #debug ">$v|[set $v]|$ccontents([set $v])<"
+ set $v $ccontents([set $v])
+}
-p "\n---------- =Execution Stack= ----------\n"
+endline
+p "---------- =Execution Stack= ----------\n"
set stkptr [expr "0x$stkptr & $stackdepth"]
for {set si 1} {$si <= $stackdepth} {incr si} {