Line 27... |
Line 27... |
#
|
#
|
# Author(s):
|
# Author(s):
|
# - Olivier Girard, olgirard@gmail.com
|
# - Olivier Girard, olgirard@gmail.com
|
#
|
#
|
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
# $Rev: 124 $
|
# $Rev: 158 $
|
# $LastChangedBy: olivier.girard $
|
# $LastChangedBy: olivier.girard $
|
# $LastChangedDate: 2011-10-27 09:38:36 +0200 (Thu, 27 Oct 2011) $
|
# $LastChangedDate: 2012-10-15 23:49:09 +0200 (Mon, 15 Oct 2012) $
|
#------------------------------------------------------------------------------
|
#------------------------------------------------------------------------------
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
|
###############################################################################
|
###############################################################################
|
Line 94... |
Line 94... |
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Read CPU registers #
|
# Read CPU registers #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_g {} {
|
proc rsp_g {} {
|
|
|
|
global CpuNr
|
|
|
# Read register value
|
# Read register value
|
set reg_val [ReadRegAll]
|
set reg_val [ReadRegAll $CpuNr]
|
|
|
# Format answer
|
# Format answer
|
set rsp_answer ""
|
set rsp_answer ""
|
for {set i 0} {$i < [llength $reg_val]} {incr i} {
|
for {set i 0} {$i < [llength $reg_val]} {incr i} {
|
|
|
Line 113... |
Line 115... |
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Write CPU registers #
|
# Write CPU registers #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_G {cmd} {
|
proc rsp_G {cmd} {
|
|
|
|
global CpuNr
|
|
|
# Format register value
|
# Format register value
|
set num_reg [expr [string length $cmd]/4]
|
set num_reg [expr [string length $cmd]/4]
|
|
|
set reg_val ""
|
set reg_val ""
|
for {set i 0} {$i < $num_reg} {incr i} {
|
for {set i 0} {$i < $num_reg} {incr i} {
|
Line 125... |
Line 129... |
set msb "[string index $cmd [expr $i*4+2]][string index $cmd [expr $i*4+3]]"
|
set msb "[string index $cmd [expr $i*4+2]][string index $cmd [expr $i*4+3]]"
|
lappend reg_val "0x$msb$lsb"
|
lappend reg_val "0x$msb$lsb"
|
}
|
}
|
|
|
# Write registers
|
# Write registers
|
WriteRegAll $reg_val
|
WriteRegAll $CpuNr $reg_val
|
|
|
return "OK"
|
return "OK"
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Kill request. #
|
# Kill request. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_k {cmd} {
|
proc rsp_k {cmd} {
|
|
|
|
global CpuNr
|
|
|
# Reset & Stop CPU
|
# Reset & Stop CPU
|
ExecutePOR_Halt
|
ExecutePOR_Halt $CpuNr
|
|
|
return "-1"
|
return "-1"
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Write length bytes of memory. #
|
# Write length bytes of memory. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_M {cmd} {
|
proc rsp_M {cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
global CpuNr
|
|
|
# Parse command
|
# Parse command
|
regexp {(.*),(.*):(.*)} $cmd match addr length data
|
regexp {(.*),(.*):(.*)} $cmd match addr length data
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
set length [format %d "0x$length"]
|
set length [format %d "0x$length"]
|
Line 162... |
Line 169... |
}
|
}
|
|
|
# Write memory
|
# Write memory
|
if {$length==2} {
|
if {$length==2} {
|
regexp {(..)(..)} $data match data_lo data_hi
|
regexp {(..)(..)} $data match data_lo data_hi
|
WriteMem 0 "0x$addr" "0x${data_hi}${data_lo}"
|
WriteMem $CpuNr 0 "0x$addr" "0x${data_hi}${data_lo}"
|
} else {
|
} else {
|
WriteMemQuick8 "0x$addr" $mem_val
|
WriteMemQuick8 $CpuNr "0x$addr" $mem_val
|
}
|
}
|
|
|
# Eventually re-set the software breakpoints in case they have been overwritten
|
# Eventually re-set the software breakpoints in case they have been overwritten
|
set addr_start [format %d "0x$addr"]
|
set addr_start [format %d "0x$addr"]
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
set brk_addr_dec [format %d "0x$brk_addr"]
|
set brk_addr_dec [format %d "0x$brk_addr"]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
set brk_addr_offset [expr $brk_addr_dec-$addr_start]
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
|
set mem_breakpoint($brk_addr) [lindex $mem_val $brk_addr_offset]
|
set mem_breakpoint($brk_addr) [lindex $mem_val $brk_addr_offset]
|
WriteMem 0 "0x$brk_addr" 0x4343
|
WriteMem $CpuNr 0 "0x$brk_addr" 0x4343
|
}
|
}
|
}
|
}
|
|
|
return "OK"
|
return "OK"
|
}
|
}
|
Line 188... |
Line 195... |
# Read length bytes from memory. #
|
# Read length bytes from memory. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_m {cmd} {
|
proc rsp_m {cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
global CpuNr
|
|
|
# Parse command
|
# Parse command
|
regexp {(.*),(.*)} $cmd match addr length
|
regexp {(.*),(.*)} $cmd match addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
set length [format %d "0x$length"]
|
set length [format %d "0x$length"]
|
|
|
# Read memory
|
# Read memory
|
set data [ReadMemQuick8 "0x$addr" $length]
|
set data [ReadMemQuick8 $CpuNr "0x$addr" $length]
|
|
|
|
|
# Eventually replace read data by the original software breakpoint value
|
# Eventually replace read data by the original software breakpoint value
|
set addr_start [format %d "0x$addr"]
|
set addr_start [format %d "0x$addr"]
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
foreach {brk_addr brk_val} [array get mem_breakpoint] {
|
Line 222... |
Line 230... |
# Insert breakpoint. #
|
# Insert breakpoint. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_Z {sock cmd} {
|
proc rsp_Z {sock cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
global CpuNr
|
|
|
# Parse command
|
# Parse command
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
|
|
switch -exact -- $type {
|
switch -exact -- $type {
|
"0" {# Memory breakpoint
|
"0" {# Memory breakpoint
|
set mem_breakpoint($addr) [ReadMem 0 "0x$addr"]
|
set mem_breakpoint($addr) [ReadMem $CpuNr 0 "0x$addr"]
|
WriteMem 0 "0x$addr" 0x4343
|
WriteMem $CpuNr 0 "0x$addr" 0x4343
|
return "OK"
|
return "OK"
|
}
|
}
|
|
|
"1" {# Hardware breakpoint
|
"1" {# Hardware breakpoint
|
if {[SetHWBreak 1 [format "0x%04x" 0x$addr] 1 0]} {
|
if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"2" {# Write watchpoint
|
"2" {# Write watchpoint
|
if {[SetHWBreak 0 [format "0x%04x" 0x$addr] 0 1]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 0 1]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"3" {# Read watchpoint
|
"3" {# Read watchpoint
|
if {[SetHWBreak 0 [format "0x%04x" 0x$addr] 1 0]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 0]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"4" {# Access watchpoint
|
"4" {# Access watchpoint
|
if {[SetHWBreak 0 [format "0x%04x" 0x$addr] 1 1]} {
|
if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 1]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
Line 272... |
Line 281... |
# Remove breakpoint. #
|
# Remove breakpoint. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_z {sock cmd} {
|
proc rsp_z {sock cmd} {
|
|
|
global mem_breakpoint
|
global mem_breakpoint
|
|
global CpuNr
|
|
|
# Parse command
|
# Parse command
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
regexp {(.),(.*),(.*)} $cmd match type addr length
|
set addr [format %04x "0x$addr"]
|
set addr [format %04x "0x$addr"]
|
|
|
switch -exact -- $type {
|
switch -exact -- $type {
|
"0" {# Memory breakpoint
|
"0" {# Memory breakpoint
|
WriteMem 0 "0x$addr" $mem_breakpoint($addr)
|
WriteMem $CpuNr 0 "0x$addr" $mem_breakpoint($addr)
|
unset mem_breakpoint($addr)
|
unset mem_breakpoint($addr)
|
return "OK"
|
return "OK"
|
}
|
}
|
|
|
"1" {# Hardware breakpoint
|
"1" {# Hardware breakpoint
|
if {[ClearHWBreak 1 [format "0x%04x" 0x$addr]]} {
|
if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"2" {# Write watchpoint
|
"2" {# Write watchpoint
|
if {[ClearHWBreak 0 [format "0x%04x" 0x$addr]]} {
|
if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"3" {# Read watchpoint
|
"3" {# Read watchpoint
|
if {[ClearHWBreak 0 [format "0x%04x" 0x$addr]]} {
|
if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
"4" {# Access watchpoint
|
"4" {# Access watchpoint
|
if {[ClearHWBreak 0 [format "0x%04x" 0x$addr]]} {
|
if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
|
return "OK"
|
return "OK"
|
}
|
}
|
return ""
|
return ""
|
}
|
}
|
|
|
Line 321... |
Line 331... |
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Continue. #
|
# Continue. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_c {sock cmd} {
|
proc rsp_c {sock cmd} {
|
|
|
|
global CpuNr
|
|
|
# Set address if required
|
# Set address if required
|
if {$cmd!=""} {
|
if {$cmd!=""} {
|
set cmd [format %04x "0x$cmd"]
|
set cmd [format %04x "0x$cmd"]
|
SetPC "0x$cmd"
|
SetPC $CpuNr "0x$cmd"
|
}
|
}
|
|
|
# Clear status
|
# Clear status
|
ClrStatus
|
ClrStatus $CpuNr
|
|
|
# Continue
|
# Continue
|
ReleaseCPU
|
ReleaseCPU $CpuNr
|
|
|
|
|
return [rsp_stop_reply $sock "c"]
|
return [rsp_stop_reply $sock "c"]
|
}
|
}
|
|
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
# Step. #
|
# Step. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_s {sock cmd} {
|
proc rsp_s {sock cmd} {
|
|
|
|
global CpuNr
|
|
|
# Set address if required
|
# Set address if required
|
if {$cmd!=""} {
|
if {$cmd!=""} {
|
set cmd [format %04x "0x$cmd"]
|
set cmd [format %04x "0x$cmd"]
|
SetPC "0x$cmd"
|
SetPC $CpuNr "0x$cmd"
|
}
|
}
|
|
|
# Clear status
|
# Clear status
|
ClrStatus
|
ClrStatus $CpuNr
|
|
|
# Read current PC value
|
# Read current PC value
|
set pc [ReadReg 0]
|
set pc [ReadReg $CpuNr 0]
|
|
|
# Incremental step
|
# Incremental step
|
StepCPU
|
StepCPU $CpuNr
|
|
|
return [rsp_stop_reply $sock "s" $pc]
|
return [rsp_stop_reply $sock "s" $pc]
|
}
|
}
|
|
|
|
|
Line 368... |
Line 382... |
# packets can receive any of the below as a reply. Except for `?' and #
|
# packets can receive any of the below as a reply. Except for `?' and #
|
# `vStopped', that reply is only returned when the target halts. #
|
# `vStopped', that reply is only returned when the target halts. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_stop_reply {sock cmd {opt_val "0"}} {
|
proc rsp_stop_reply {sock cmd {opt_val "0"}} {
|
|
|
|
global CpuNr
|
|
|
# Wait until halted
|
# Wait until halted
|
while {![IsHalted]} {
|
while {![IsHalted $CpuNr]} {
|
|
|
# Wait a few milliseconds to prevent the gui from freezing
|
# Wait a few milliseconds to prevent the gui from freezing
|
after 100 {set end 1}
|
after 100 {set end 1}
|
vwait end
|
vwait end
|
|
|
Line 382... |
Line 398... |
set break_char [read -nonewline $sock]
|
set break_char [read -nonewline $sock]
|
fconfigure $sock -blocking 1
|
fconfigure $sock -blocking 1
|
binary scan $break_char H* break_char
|
binary scan $break_char H* break_char
|
if {$break_char=="03"} {
|
if {$break_char=="03"} {
|
putsVerbose "--> BREAK"
|
putsVerbose "--> BREAK"
|
HaltCPU
|
HaltCPU $CpuNr
|
}
|
}
|
}
|
}
|
|
|
# Read some important registers
|
# Read some important registers
|
set pc [ReadReg 0]
|
set pc [ReadReg $CpuNr 0]
|
regexp {0x(..)(..)} $pc match pc_hi pc_lo
|
regexp {0x(..)(..)} $pc match pc_hi pc_lo
|
set r4 [ReadReg 4]
|
set r4 [ReadReg $CpuNr 4]
|
regexp {0x(..)(..)} $r4 match r4_hi r4_lo
|
regexp {0x(..)(..)} $r4 match r4_hi r4_lo
|
|
|
# In case of a single step command, make sure that the PC
|
# In case of a single step command, make sure that the PC
|
# value changes. If not, return an error otherwise GDB will
|
# value changes. If not, return an error otherwise GDB will
|
# end-up in an infinite loop.
|
# end-up in an infinite loop.
|
Line 431... |
Line 447... |
# that providing access to a stubs's interpreter may have security #
|
# that providing access to a stubs's interpreter may have security #
|
# implications. #
|
# implications. #
|
#-----------------------------------------------------------------------------#
|
#-----------------------------------------------------------------------------#
|
proc rsp_qRcmd {sock cmd} {
|
proc rsp_qRcmd {sock cmd} {
|
|
|
|
global CpuNr
|
|
|
regsub {^Rcmd,} $cmd {} cmd
|
regsub {^Rcmd,} $cmd {} cmd
|
set cmd [binary format H* $cmd]; # Convert hex to ascii
|
set cmd [binary format H* $cmd]; # Convert hex to ascii
|
|
|
switch -exact -- $cmd {
|
switch -exact -- $cmd {
|
"erase all" {;# Convert ascii to hex
|
"erase all" {;# Convert ascii to hex
|
binary scan "Erasing target program memory..." H* text1
|
binary scan "Erasing target program memory..." H* text1
|
binary scan " Erased OK\n" H* text2
|
binary scan " Erased OK\n" H* text2
|
;# Execute erase command
|
;# Execute erase command
|
sendRSPpacket $sock "O$text1"
|
sendRSPpacket $sock "O$text1"
|
EraseROM
|
EraseROM $CpuNr
|
sendRSPpacket $sock "O$text2"
|
sendRSPpacket $sock "O$text2"
|
set rsp_answer "OK"
|
set rsp_answer "OK"
|
}
|
}
|
default {set rsp_answer "OK"}
|
default {set rsp_answer "OK"}
|
}
|
}
|