OpenCores
URL https://opencores.org/ocsvn/openmsp430/openmsp430/trunk

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [tools/] [openmsp430-gdbproxy/] [commands.tcl] - Blame information for rev 172

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 olivier.gi
#!/usr/bin/wish
2
#------------------------------------------------------------------------------
3
# Copyright (C) 2001 Authors
4
#
5
# This source file may be used and distributed without restriction provided
6
# that this copyright statement is not removed from the file and that any
7
# derivative work contains the original copyright notice and the associated
8
# disclaimer.
9
#
10
# This source file is free software; you can redistribute it and/or modify
11
# it under the terms of the GNU Lesser General Public License as published
12
# by the Free Software Foundation; either version 2.1 of the License, or
13
# (at your option) any later version.
14
#
15
# This source is distributed in the hope that it will be useful, but WITHOUT
16
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18
# License for more details.
19
#
20
# You should have received a copy of the GNU Lesser General Public License
21
# along with this source; if not, write to the Free Software Foundation,
22
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
#
24
#------------------------------------------------------------------------------
25
# 
26
# File Name: commands.tcl
27
# 
28 15 olivier.gi
# Author(s):
29
#             - Olivier Girard,    olgirard@gmail.com
30
#
31 2 olivier.gi
#------------------------------------------------------------------------------
32 15 olivier.gi
# $Rev: 172 $
33
# $LastChangedBy: olivier.girard $
34
# $LastChangedDate: 2012-12-28 00:06:56 +0100 (Fri, 28 Dec 2012) $
35
#------------------------------------------------------------------------------
36 2 olivier.gi
 
37
global mem_breakpoint
38 172 olivier.gi
global mem_mapping
39
global breakSelect
40 2 olivier.gi
 
41
###############################################################################
42
#                                                                             #
43
#                              RSP COMMAND PARSER                             #
44
#                                                                             #
45
###############################################################################
46
 
47 172 olivier.gi
proc rspParse {CpuNr sock rsp_cmd} {
48 2 olivier.gi
 
49
    set rsp_answer ""
50
    set cmd_tail [string range $rsp_cmd 1 [string length $rsp_cmd]]
51
 
52
    switch -exact -- [string index $rsp_cmd 0] {
53 158 olivier.gi
        "!"     {set rsp_answer "OK"}
54 172 olivier.gi
        "?"     {set rsp_answer [rsp_stop_reply $CpuNr $sock "?"]}
55 158 olivier.gi
        "A"     {}
56
        "b"     {}
57 172 olivier.gi
        "c"     {set rsp_answer [rsp_c $CpuNr $sock $cmd_tail]}
58
        "C"     {set rsp_answer [rsp_c $CpuNr $sock $cmd_tail]}
59 158 olivier.gi
        "D"     {}
60
        "F"     {}
61 172 olivier.gi
        "g"     {set rsp_answer [rsp_g $CpuNr]}
62
        "G"     {set rsp_answer [rsp_G $CpuNr $cmd_tail]}
63 158 olivier.gi
        "H"     {set rsp_answer ""}
64
        "i"     {}
65
        "I"     {}
66 172 olivier.gi
        "k"     {set rsp_answer [rsp_k $CpuNr $cmd_tail]}
67
        "m"     {set rsp_answer [rsp_m $CpuNr $cmd_tail]}
68
        "M"     {set rsp_answer [rsp_M $CpuNr $cmd_tail]}
69 158 olivier.gi
        "p"     {}
70
        "P"     {}
71 172 olivier.gi
        "q"     {set rsp_answer [rsp_q $CpuNr $sock $cmd_tail]}
72 158 olivier.gi
        "Q"     {}
73
        "R"     {}
74 172 olivier.gi
        "s"     {set rsp_answer [rsp_s $CpuNr $sock $cmd_tail]}
75
        "S"     {set rsp_answer [rsp_s $CpuNr $sock $cmd_tail]}
76 158 olivier.gi
        "t"     {}
77
        "T"     {}
78
        "v"     {}
79
        "X"     {}
80 172 olivier.gi
        "z"     {set rsp_answer [rsp_z $CpuNr $sock $cmd_tail]}
81
        "Z"     {set rsp_answer [rsp_Z $CpuNr $sock $cmd_tail]}
82 158 olivier.gi
        default {}
83 2 olivier.gi
    }
84
 
85
 
86
    return $rsp_answer
87
}
88
 
89
 
90
###############################################################################
91
#                                                                             #
92
#                                   RSP COMMANDS                              #
93
#                                                                             #
94
###############################################################################
95
 
96
#-----------------------------------------------------------------------------#
97
# Read CPU registers                                                          #
98
#-----------------------------------------------------------------------------#
99 172 olivier.gi
proc rsp_g {CpuNr} {
100 2 olivier.gi
 
101
    # Read register value
102 158 olivier.gi
    set reg_val [ReadRegAll $CpuNr]
103 2 olivier.gi
 
104
    # Format answer
105
    set rsp_answer ""
106
    for {set i 0} {$i < [llength $reg_val]} {incr i} {
107
 
108 158 olivier.gi
        regexp {0x(..)(..)} [lindex $reg_val $i] match msb lsb
109
        append rsp_answer "$lsb$msb"
110 2 olivier.gi
    }
111
 
112
    return $rsp_answer
113
}
114
 
115
#-----------------------------------------------------------------------------#
116
# Write CPU registers                                                         #
117
#-----------------------------------------------------------------------------#
118 172 olivier.gi
proc rsp_G {CpuNr cmd} {
119 2 olivier.gi
 
120
    # Format register value
121
    set num_reg [expr [string length $cmd]/4]
122
 
123
    set reg_val ""
124
    for {set i 0} {$i < $num_reg} {incr i} {
125
 
126 158 olivier.gi
        set lsb "[string index $cmd [expr $i*4+0]][string index $cmd [expr $i*4+1]]"
127
        set msb "[string index $cmd [expr $i*4+2]][string index $cmd [expr $i*4+3]]"
128
        lappend reg_val "0x$msb$lsb"
129 2 olivier.gi
    }
130
 
131
    # Write registers
132 158 olivier.gi
    WriteRegAll $CpuNr $reg_val
133 2 olivier.gi
 
134
    return "OK"
135
}
136
 
137
#-----------------------------------------------------------------------------#
138
# Kill request.                                                               #
139
#-----------------------------------------------------------------------------#
140 172 olivier.gi
proc rsp_k {CpuNr cmd} {
141 2 olivier.gi
 
142
    # Reset & Stop CPU
143 158 olivier.gi
    ExecutePOR_Halt $CpuNr
144 2 olivier.gi
 
145
    return "-1"
146
}
147
 
148
#-----------------------------------------------------------------------------#
149
# Write length bytes of memory.                                               #
150
#-----------------------------------------------------------------------------#
151 172 olivier.gi
proc rsp_M {CpuNr cmd} {
152 2 olivier.gi
 
153
    global mem_breakpoint
154 172 olivier.gi
    global mem_mapping
155
    global breakSelect
156 2 olivier.gi
 
157
    # Parse command
158
    regexp {(.*),(.*):(.*)} $cmd match addr length data
159
    set addr   [format %04x "0x$addr"]
160
    set length [format %d   "0x$length"]
161
 
162
    # Format data
163
    set mem_val ""
164
    for {set i 0} {$i<$length} {incr i} {
165 158 olivier.gi
        lappend mem_val "0x[string range $data [expr $i*2] [expr $i*2+1]]"
166 2 olivier.gi
    }
167
 
168
    # Write memory
169 119 olivier.gi
    if {$length==2} {
170 158 olivier.gi
        regexp {(..)(..)} $data match data_lo data_hi
171
        WriteMem       $CpuNr 0 "0x$addr" "0x${data_hi}${data_lo}"
172 119 olivier.gi
    } else {
173 158 olivier.gi
        WriteMemQuick8 $CpuNr   "0x$addr" $mem_val
174 119 olivier.gi
    }
175 2 olivier.gi
 
176
    # Eventually re-set the software breakpoints in case they have been overwritten
177 172 olivier.gi
    if {$breakSelect==0} {
178
        set addr_start [format %d "0x$addr"]
179
        foreach {brk_addr brk_val} [array get mem_breakpoint] {
180
            regsub {,} $brk_addr { } brk_addr_lst
181
            if {[lindex $brk_addr_lst 0]==$mem_mapping($CpuNr)} {
182
                set brk_addr_dec    [format %d "0x[lindex $brk_addr_lst 1]"]
183
                set brk_addr_offset [expr $brk_addr_dec-$addr_start]
184
                if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
185
                    set mem_breakpoint($brk_addr) [lindex $mem_val $brk_addr_offset]
186
                    WriteMem $CpuNr 0 "0x[lindex $brk_addr 1]" 0x4343
187
                }
188
            }
189
        }
190 2 olivier.gi
    }
191
 
192
    return "OK"
193
}
194
 
195
 
196
#-----------------------------------------------------------------------------#
197
# Read length bytes from memory.                                              #
198
#-----------------------------------------------------------------------------#
199 172 olivier.gi
proc rsp_m {CpuNr cmd} {
200 2 olivier.gi
 
201
    global mem_breakpoint
202 172 olivier.gi
    global mem_mapping
203
    global breakSelect
204 2 olivier.gi
 
205
    # Parse command
206
    regexp {(.*),(.*)} $cmd match addr length
207
    set addr   [format %04x "0x$addr"]
208
    set length [format %d   "0x$length"]
209
 
210
    # Read memory
211 158 olivier.gi
    set data [ReadMemQuick8  $CpuNr "0x$addr" $length]
212 119 olivier.gi
 
213 2 olivier.gi
 
214
    # Eventually replace read data by the original software breakpoint value
215 172 olivier.gi
    if {$breakSelect==0} {
216
        set addr_start [format %d "0x$addr"]
217
        foreach {brk_addr brk_val} [array get mem_breakpoint] {
218
            regsub {,} $brk_addr { } brk_addr_lst
219
            if {[lindex $brk_addr_lst 0]==$mem_mapping($CpuNr)} {
220
                set brk_addr_dec    [format %d "0x[lindex $brk_addr_lst 1]"]
221
                set brk_addr_offset [expr $brk_addr_dec-$addr_start]
222
                if {(0<=$brk_addr_offset) && ($brk_addr_offset<=$length)} {
223
                    set data [lreplace $data $brk_addr_offset $brk_addr_offset "0x$mem_breakpoint($brk_addr)"]
224
                }
225
            }
226
        }
227 2 olivier.gi
    }
228
 
229
    # Format data
230
    regsub -all {0x} $data {} data
231
    regsub -all { }  $data {} data
232
 
233
    return $data
234
}
235
 
236
 
237
#-----------------------------------------------------------------------------#
238
# Insert breakpoint.                                                          #
239
#-----------------------------------------------------------------------------#
240 172 olivier.gi
proc rsp_Z {CpuNr sock cmd} {
241 2 olivier.gi
 
242
    global mem_breakpoint
243 172 olivier.gi
    global mem_mapping
244
    global breakSelect
245 2 olivier.gi
 
246
    # Parse command
247
    regexp {(.),(.*),(.*)} $cmd match type addr length
248
    set addr   [format %04x "0x$addr"]
249
 
250
    switch -exact -- $type {
251 172 olivier.gi
        "0"     {# Soft Memory breakpoint
252
                 if {$breakSelect==0} {
253
                     if {![info exists mem_breakpoint($mem_mapping($CpuNr),$addr)]} {
254
                         set mem_breakpoint($mem_mapping($CpuNr),$addr) [ReadMem $CpuNr 0 "0x$addr"]
255
                         WriteMem $CpuNr 0 "0x$addr" 0x4343
256
                     }
257
                     return "OK"
258
 
259
                 # Hard Memory breakpoint
260
                 } else {
261
                     if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
262
                         #putsLog "CORE $CpuNr: --- INFO --- SET HARDWARE MEMORY BREAKPOINT. "
263
                         return "OK"
264
                     }
265
                     putsLog "CORE $CpuNr: --- ERROR --- NO MORE HARDWARE MEMORY BREAKPOINT AVAILABLE. "
266
                     return ""
267
                 }
268 2 olivier.gi
                }
269
 
270 158 olivier.gi
        "1"     {# Hardware breakpoint
271
                 if {[SetHWBreak $CpuNr 1 [format "0x%04x" 0x$addr] 1 0]} {
272
                     return "OK"
273
                 }
274 172 olivier.gi
                 putsLog "CORE $CpuNr: --- ERROR --- NO MORE HARDWARE BREAKPOINT AVAILABLE. "
275 158 olivier.gi
                 return ""
276 2 olivier.gi
                }
277
 
278 158 olivier.gi
        "2"     {# Write watchpoint
279
                 if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 0 1]} {
280
                     return "OK"
281
                 }
282 172 olivier.gi
                 putsLog "CORE $CpuNr: --- ERROR --- NO MORE WRITE WATCHPOINT AVAILABLE. "
283 158 olivier.gi
                 return ""
284 2 olivier.gi
                }
285
 
286 158 olivier.gi
        "3"     {# Read watchpoint
287
                 if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 0]} {
288
                     return "OK"
289
                 }
290 172 olivier.gi
                 putsLog "CORE $CpuNr: --- ERROR --- NO MORE READ WATCHPOINT AVAILABLE. "
291 158 olivier.gi
                 return ""
292 2 olivier.gi
                }
293
 
294 158 olivier.gi
        "4"     {# Access watchpoint
295
                 if {[SetHWBreak $CpuNr 0 [format "0x%04x" 0x$addr] 1 1]} {
296
                     return "OK"
297
                 }
298 172 olivier.gi
                 putsLog "CORE $CpuNr: --- ERROR --- NO MORE ACCESS WATCHPOINT AVAILABLE. "
299 158 olivier.gi
                 return ""
300 2 olivier.gi
                }
301
 
302 158 olivier.gi
        default {return ""}
303 2 olivier.gi
    }
304
}
305
 
306
#-----------------------------------------------------------------------------#
307
# Remove breakpoint.                                                          #
308
#-----------------------------------------------------------------------------#
309 172 olivier.gi
proc rsp_z {CpuNr sock cmd} {
310 2 olivier.gi
 
311
    global mem_breakpoint
312 172 olivier.gi
    global mem_mapping
313
    global breakSelect
314 2 olivier.gi
 
315
    # Parse command
316
    regexp {(.),(.*),(.*)} $cmd match type addr length
317
    set addr   [format %04x "0x$addr"]
318
 
319
    switch -exact -- $type {
320 172 olivier.gi
        "0"     {# Soft Memory breakpoint
321
                 if {$breakSelect==0} {
322
                     if {[info exists mem_breakpoint($mem_mapping($CpuNr),$addr)]} {
323
                         WriteMem $CpuNr 0 "0x$addr" $mem_breakpoint($mem_mapping($CpuNr),$addr)
324
                         unset mem_breakpoint($mem_mapping($CpuNr),$addr)
325
                     }
326
                     return "OK"
327
 
328
                 # Hard Memory breakpoint
329
                 } else {
330
                     if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
331
                         #putsLog "CORE $CpuNr: --- INFO --- RELEASE HARDWARE MEMORY BREAKPOINT. "
332
                         return "OK"
333
                     }
334
                     putsLog "CORE $CpuNr: --- ERROR --- COULD NOT REMOVE HARDWARE MEMORY BREAKPOINT. "
335
                     return ""
336
                 }
337 2 olivier.gi
                }
338
 
339 158 olivier.gi
        "1"     {# Hardware breakpoint
340
                 if {[ClearHWBreak $CpuNr 1 [format "0x%04x" 0x$addr]]} {
341
                     return "OK"
342
                 }
343
                 return ""
344 2 olivier.gi
                }
345
 
346 158 olivier.gi
        "2"     {# Write watchpoint
347
                 if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
348
                     return "OK"
349
                 }
350
                 return ""
351 2 olivier.gi
                }
352
 
353 158 olivier.gi
        "3"     {# Read watchpoint
354
                 if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
355
                     return "OK"
356
                 }
357
                 return ""
358 2 olivier.gi
                }
359
 
360 158 olivier.gi
        "4"     {# Access watchpoint
361
                 if {[ClearHWBreak $CpuNr 0 [format "0x%04x" 0x$addr]]} {
362
                     return "OK"
363
                 }
364
                 return ""
365 2 olivier.gi
                }
366
 
367 158 olivier.gi
        default {return ""}
368 2 olivier.gi
    }
369
}
370
 
371
#-----------------------------------------------------------------------------#
372
# Continue.                                                                   #
373
#-----------------------------------------------------------------------------#
374 172 olivier.gi
proc rsp_c {CpuNr sock cmd} {
375 2 olivier.gi
 
376
    # Set address if required
377
    if {$cmd!=""} {
378 158 olivier.gi
        set cmd [format %04x "0x$cmd"]
379
        SetPC $CpuNr "0x$cmd"
380 2 olivier.gi
    }
381
 
382
    # Clear status
383 158 olivier.gi
    ClrStatus  $CpuNr
384 2 olivier.gi
 
385
    # Continue
386 158 olivier.gi
    ReleaseCPU $CpuNr
387 2 olivier.gi
 
388
 
389 172 olivier.gi
    return [rsp_stop_reply $CpuNr $sock "c"]
390 2 olivier.gi
}
391
 
392
#-----------------------------------------------------------------------------#
393
# Step.                                                                       #
394
#-----------------------------------------------------------------------------#
395 172 olivier.gi
proc rsp_s {CpuNr sock cmd} {
396 2 olivier.gi
 
397
    # Set address if required
398
    if {$cmd!=""} {
399 158 olivier.gi
        set cmd [format %04x "0x$cmd"]
400
        SetPC $CpuNr "0x$cmd"
401 2 olivier.gi
    }
402
 
403
    # Clear status
404 158 olivier.gi
    ClrStatus $CpuNr
405 2 olivier.gi
 
406 124 olivier.gi
    # Read current PC value
407 158 olivier.gi
    set pc [ReadReg $CpuNr 0]
408 124 olivier.gi
 
409 2 olivier.gi
    # Incremental step
410 158 olivier.gi
    StepCPU $CpuNr
411 2 olivier.gi
 
412 172 olivier.gi
    return [rsp_stop_reply $CpuNr $sock "s" $pc]
413 2 olivier.gi
}
414
 
415
 
416
#-----------------------------------------------------------------------------#
417
# The `C', `c', `S', `s', `vCont', `vAttach', `vRun', `vStopped', and `?'     #
418
# packets can receive any of the below as a reply. Except for `?' and         #
419
# `vStopped', that reply is only returned when the target halts.              #
420
#-----------------------------------------------------------------------------#
421 172 olivier.gi
proc rsp_stop_reply {CpuNr sock cmd {opt_val "0"}} {
422 2 olivier.gi
 
423
    # Wait until halted
424 158 olivier.gi
    while {![IsHalted $CpuNr]} {
425 2 olivier.gi
 
426 158 olivier.gi
        # Wait a few milliseconds to prevent the gui from freezing
427
        after 100 {set end 1}
428
        vwait end
429 2 olivier.gi
 
430 158 olivier.gi
        # Check if we are interrupted by GDB
431
        fconfigure $sock -blocking 0
432
        set break_char [read -nonewline $sock]
433
        fconfigure $sock -blocking 1
434
        binary scan $break_char H* break_char
435
        if {$break_char=="03"} {
436
            putsVerbose "--> BREAK"
437
            HaltCPU $CpuNr
438
        }
439 2 olivier.gi
    }
440
 
441
    # Read some important registers
442 158 olivier.gi
    set pc [ReadReg $CpuNr 0]
443 2 olivier.gi
    regexp {0x(..)(..)} $pc match pc_hi pc_lo
444 158 olivier.gi
    set r4 [ReadReg $CpuNr 4]
445 2 olivier.gi
    regexp {0x(..)(..)} $r4 match r4_hi r4_lo
446
 
447 158 olivier.gi
        # In case of a single step command, make sure that the PC
448
        # value changes. If not, return an error otherwise GDB will
449
        # end-up in an infinite loop.
450
        if {$cmd == "s"} {
451
                if {$opt_val == $pc} {
452
                        return "E05"
453
                }
454
        }
455
        #return "S05"
456
        return "T0500:$pc_lo$pc_hi;04:$r4_lo$r4_hi;"
457 2 olivier.gi
}
458
 
459
 
460
#-----------------------------------------------------------------------------#
461
#                                                                             #
462
#-----------------------------------------------------------------------------#
463 172 olivier.gi
proc rsp_q {CpuNr sock cmd} {
464 2 olivier.gi
 
465
       switch -regexp -- $cmd {
466
 
467 158 olivier.gi
        "C"       {set rsp_answer ""}
468
        "Offsets" {set rsp_answer "Text=0;Data=0;Bss=0"}
469 172 olivier.gi
        "Rcmd,.+" {set rsp_answer [rsp_qRcmd $CpuNr $sock $cmd]}
470 158 olivier.gi
        default   {set rsp_answer ""}
471 2 olivier.gi
    }
472
    return $rsp_answer
473
}
474
 
475
#-----------------------------------------------------------------------------#
476
# qRcmd,command'                                                              #
477
#    command (hex encoded) is passed to the local interpreter for execution.  #
478
#    Invalid commands should be reported using the output string. Before the  #
479
#    final result packet, the target may also respond with a number of        #
480
#    intermediate `Ooutput' console output packets. Implementors should note  #
481
#    that providing access to a stubs's interpreter may have security         #
482
#    implications.                                                            #
483
#-----------------------------------------------------------------------------#
484 172 olivier.gi
proc rsp_qRcmd {CpuNr sock cmd} {
485 2 olivier.gi
 
486
    regsub {^Rcmd,} $cmd {} cmd
487
    set cmd [binary format H* $cmd];  # Convert hex to ascii
488
 
489
    switch -exact -- $cmd {
490 158 olivier.gi
        "erase all" {;# Convert ascii to hex
491
                     binary scan "Erasing target program memory..." H* text1
492
                     binary scan " Erased OK\n"                     H* text2
493
                     ;# Execute erase command
494
                     sendRSPpacket $sock "O$text1"
495
                     EraseROM $CpuNr
496
                     sendRSPpacket $sock "O$text2"
497
                     set rsp_answer "OK"
498 2 olivier.gi
                    }
499 158 olivier.gi
        default     {set rsp_answer "OK"}
500 2 olivier.gi
    }
501
 
502
    return $rsp_answer
503
 
504
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.