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

Subversion Repositories openmsp430

[/] [openmsp430/] [trunk/] [tools/] [lib/] [tcl-lib/] [dbg_functions.tcl] - Blame information for rev 133

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

Line No. Rev Author Line
1 2 olivier.gi
#------------------------------------------------------------------------------
2
# Copyright (C) 2001 Authors
3
#
4
# This source file may be used and distributed without restriction provided
5
# that this copyright statement is not removed from the file and that any
6
# derivative work contains the original copyright notice and the associated
7
# disclaimer.
8
#
9
# This source file is free software; you can redistribute it and/or modify
10
# it under the terms of the GNU Lesser General Public License as published
11
# by the Free Software Foundation; either version 2.1 of the License, or
12
# (at your option) any later version.
13
#
14
# This source is distributed in the hope that it will be useful, but WITHOUT
15
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17
# License for more details.
18
#
19
# You should have received a copy of the GNU Lesser General Public License
20
# along with this source; if not, write to the Free Software Foundation,
21
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22
#
23
#------------------------------------------------------------------------------
24
# 
25
# File Name:   dbg_functions.tcl
26
#
27 15 olivier.gi
# Author(s):
28
#             - Olivier Girard,    olgirard@gmail.com
29
#
30
#------------------------------------------------------------------------------
31
# $Rev: 133 $
32
# $LastChangedBy: olivier.girard $
33
# $LastChangedDate: 2012-03-22 21:28:26 +0100 (Thu, 22 Mar 2012) $
34
#------------------------------------------------------------------------------
35
#
36 2 olivier.gi
# Description: Main utility functions for the openMSP430 serial debug
37
#             interface.
38
#
39
#       The following functions are implemented according to the SLAA149
40
#     application report from TI (Programming a Flash-Based MSP430 Using the
41
#     JTAG Interface):
42
#
43
#               - ExecutePOR      ()
44
#               - SetPC           (Addr)
45
#               - HaltCPU         ()
46
#               - ReleaseCPU      ()
47
#               - GetDevice       ()
48
#               - ReleaseDevice   (Addr)
49
#               - WriteMem        (Format,    Addr,     Data)
50
#               - WriteMemQuick   (StartAddr, DataArray)
51
#               - ReadMem         (Format,    Addr)
52
#               - ReadMemQuick    (StartAddr, Length)
53
#               - VerifyMem       (StartAddr, DataArray)
54
#
55
#
56
#       The following have been added:
57
#
58
#               - ExecutePOR_Halt ()
59
#               - GetCPU_ID       ()
60
#               - GetCPU_ID_SIZE  ()
61 74 olivier.gi
#               - VerifyCPU_ID    ()
62 2 olivier.gi
#               - WriteReg        (Addr,      Data)
63
#               - WriteRegAll     (DataArray)
64
#               - ReadReg         (Addr)
65
#               - ReadRegAll      ()
66
#               - WriteMemQuick8  (StartAddr, DataArray)
67
#               - ReadMemQuick8   (StartAddr, Length)
68
#               - StepCPU         ()
69
#               - EraseRAM        ()
70
#               - EraseROM        ()
71
#               - InitBreakUnits  ()
72
#               - SetHWBreak      (Type, Addr,      Rd,       Wr)
73
#               - ClearHWBreak    (Type, Addr)
74
#               - IsHalted        ()
75
#               - ClrStatus       ()
76 110 olivier.gi
#               - GetChipAlias    ()
77 2 olivier.gi
# 
78
#------------------------------------------------------------------------------
79
 
80
# GLOBAL VARIABLES
81
global hw_break
82 110 olivier.gi
global omsp_info
83
set    omsp_info(connected) 0
84 2 olivier.gi
 
85
# SOURCE REQUIRED LIBRARIES
86 110 olivier.gi
set     scriptDir [file dirname [info script]]
87
source $scriptDir/dbg_uart.tcl
88
source $scriptDir/xml.tcl
89 2 olivier.gi
 
90 110 olivier.gi
 
91 2 olivier.gi
#=============================================================================#
92
# ExecutePOR ()                                                               #
93
#-----------------------------------------------------------------------------#
94
# Description: Executes a power-up clear (PUC) command.                       #
95
# Arguments  : None.                                                          #
96
# Result     : 0 if error, 1 otherwise.                                       #
97
#=============================================================================#
98
proc ExecutePOR {} {
99
 
100
    # Set PUC
101
    set cpu_ctl_org [dbg_uart_rd CPU_CTL]
102
    set cpu_ctl_new [expr 0x40 | $cpu_ctl_org]
103
    dbg_uart_wr CPU_CTL $cpu_ctl_new
104
 
105
    # Remove PUC, clear break after reset
106
    set cpu_ctl_org [expr 0x5f & $cpu_ctl_org]
107
    dbg_uart_wr CPU_CTL $cpu_ctl_org
108
 
109
    # Check CPU ID
110 74 olivier.gi
    if {![VerifyCPU_ID]} {
111 124 olivier.gi
    return 0
112 2 olivier.gi
    }
113
 
114
    # Check status: make sure a PUC occured
115
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
116
    set puc_pnd      [expr 0x04 & $cpu_stat_val]
117
    if {![string eq $puc_pnd 4]} {
118 124 olivier.gi
    return 0
119 2 olivier.gi
    }
120
 
121
    # Clear PUC pending flag
122
    dbg_uart_wr CPU_STAT 0x04
123
 
124 110 olivier.gi
    return 1
125 2 olivier.gi
}
126
 
127
#=============================================================================#
128
# SetPC (Addr)                                                                #
129
#-----------------------------------------------------------------------------#
130
# Description: Loads the target device CPU's program counter (PC) with the    #
131
#              desired 16-bit address.                                        #
132
# Arguments  : Addr - Desired 16-bit PC value (in hexadecimal).               #
133
# Result     : 0 if error, 1 otherwise.                                       #
134
#=============================================================================#
135
proc SetPC {Addr} {
136
 
137
    return [WriteReg 0 $Addr]
138
}
139
 
140
#=============================================================================#
141
# HaltCPU ()                                                                  #
142
#-----------------------------------------------------------------------------#
143
# Description: Sends the target CPU into a controlled, stopped state.         #
144
# Arguments  : None.                                                          #
145
# Result     : 0 if error, 1 otherwise.                                       #
146
#=============================================================================#
147
proc HaltCPU {} {
148
 
149
    set result 1
150
 
151
    # Stop CPU
152
    set cpu_ctl_org [dbg_uart_rd CPU_CTL]
153
    set cpu_ctl_new [expr 0x01 | $cpu_ctl_org]
154
    dbg_uart_wr CPU_CTL $cpu_ctl_new
155
 
156
    # Check status: make sure the CPU halted
157
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
158
    set halted       [expr 0x01 & $cpu_stat_val]
159
    if {![string eq $halted 1]} {
160 124 olivier.gi
    set result 0
161 2 olivier.gi
    }
162
 
163
    return $result
164
}
165
 
166
#=============================================================================#
167
# ReleaseCPU ()                                                               #
168
#-----------------------------------------------------------------------------#
169
# Description: Releases the target device's CPU from the controlled, stopped  #
170
#              state. (Does not release the target device from debug control.)#
171
# Arguments  : None.                                                          #
172
# Result     : 0 if error, 1 otherwise.                                       #
173
#=============================================================================#
174
proc ReleaseCPU {} {
175
 
176
    set result 1
177
 
178
    # Start CPU
179
    set cpu_ctl_org [dbg_uart_rd CPU_CTL]
180
    set cpu_ctl_new [expr 0x02 | $cpu_ctl_org]
181
    dbg_uart_wr CPU_CTL $cpu_ctl_new
182
 
183
    # Check status: make sure the CPU runs
184
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
185
    set halted       [expr 0x01 & $cpu_stat_val]
186
    if {![string eq $halted 0]} {
187 124 olivier.gi
    set result 0
188 2 olivier.gi
    }
189
 
190
    return $result
191
}
192
 
193
#=============================================================================#
194
# GetDevice ()                                                                #
195
#-----------------------------------------------------------------------------#
196
# Description: Takes the target MSP430 device under JTAG control.             #
197
#              Enable the auto-freeze feature of timers when in the CPU is    #
198
#              stopped. This prevents an automatic watchdog reset condition.  #
199
#              Enables software breakpoints.                                  #
200
# Arguments  : None.                                                          #
201
# Result     : 0 if error, 1 otherwise.                                       #
202
#=============================================================================#
203
proc GetDevice {} {
204
 
205
    global hw_break
206 110 olivier.gi
    global omsp_info
207 2 olivier.gi
 
208
    # Set UART global variables
209
    if {![info exists ::serial_baudrate]} {
210 124 olivier.gi
    set ::serial_baudrate 9600
211 2 olivier.gi
    }
212
    if {![info exists ::serial_device]} {
213 124 olivier.gi
    set ::serial_device   /dev/ttyUSB0
214 2 olivier.gi
    }
215
 
216
    # Open connection
217
    if {![dbg_uart_connect $::serial_device $::serial_baudrate]} {
218 124 olivier.gi
    return 0
219 2 olivier.gi
    }
220
 
221 110 olivier.gi
    if {[VerifyCPU_ID]} {
222 2 olivier.gi
 
223 124 olivier.gi
    # Enable auto-freeze & software breakpoints
224
    dbg_uart_wr CPU_CTL 0x0018
225 2 olivier.gi
 
226 124 olivier.gi
    # Initialize the omsp_info global variable
227
    GetCPU_ID
228
    set omsp_info(connected) 1
229 110 olivier.gi
 
230 124 olivier.gi
    # Get number of hardware breakpoints
231
    set hw_break(num)       [InitBreakUnits]
232
    set omsp_info(hw_break) $hw_break(num)
233
 
234 110 olivier.gi
 
235 124 olivier.gi
    return 1
236 110 olivier.gi
    } else {
237 124 olivier.gi
    return 0
238 110 olivier.gi
    }
239 2 olivier.gi
}
240
 
241
#=============================================================================#
242
# ReleaseDevice (Addr)                                                        #
243
#-----------------------------------------------------------------------------#
244
# Description: Releases the target device from JTAG control; CPU starts       #
245
#              execution at the specified PC address.                         #
246
# Arguments  : Addr - (0xfffe: perform reset; address at reset vector loaded  #
247
#                 into PC; otherwise address specified by Addr loaded into PC #
248
# Result     : 0 if error, 1 otherwise.                                       #
249
#=============================================================================#
250
proc ReleaseDevice {Addr} {
251
 
252
    if {[expr $Addr]==[expr 0xfffe]} {
253 124 olivier.gi
    set result 1
254
    set result [expr $result+[ExecutePOR]]
255
    set result [expr $result+[ReleaseCPU]]
256 2 olivier.gi
    } else {
257 124 olivier.gi
    set result 0
258
    set result [expr $result+[HaltCPU]]
259
    set result [expr $result+[SetPC $Addr]]
260
    set result [expr $result+[ReleaseCPU]]
261 2 olivier.gi
    }
262
 
263
    if {$result==3} {
264 124 olivier.gi
    return 1
265 2 olivier.gi
    } else {
266 124 olivier.gi
    return 0
267 2 olivier.gi
    }
268
}
269
 
270
#=============================================================================#
271
# WriteMem (Format, Addr, Data)                                               #
272
#-----------------------------------------------------------------------------#
273
# Description: Write a single byte or word to a given address (RAM, ROM &     #
274
#              Peripherals.                                                   #
275
# Arguments  : Format - 0 to write a word, 1 to write a byte.                 #
276
#              Addr   - Destination address for data to be written.           #
277
#              Data   - Data value to be written.                             #
278
# Result     : 0 if error, 1 otherwise.                                       #
279
#=============================================================================#
280
proc WriteMem {Format Addr Data} {
281
 
282
    dbg_uart_wr MEM_CNT  0x0000
283
    dbg_uart_wr MEM_ADDR $Addr
284
    dbg_uart_wr MEM_DATA $Data
285
 
286
    if {$Format==0} {
287 124 olivier.gi
    dbg_uart_wr MEM_CTL  0x0003
288 2 olivier.gi
    } else {
289 124 olivier.gi
    dbg_uart_wr MEM_CTL  0x000b
290 2 olivier.gi
    }
291
 
292
    return 1
293
}
294
 
295
#=============================================================================#
296
# WriteMemQuick (StartAddr, DataArray)                                        #
297
#-----------------------------------------------------------------------------#
298
# Description: Writes an array of words into the target device memory (RAM,   #
299
#              ROM & Peripherals.                                             #
300
# Arguments  : StartAddr - Start address of destination memory.               #
301
#              DataArray - List of data to be written (in hexadecimal).       #
302
# Result     : 0 if error, 1 otherwise.                                       #
303
#=============================================================================#
304
proc WriteMemQuick {StartAddr DataArray} {
305
 
306
    if {[llength $DataArray]==1} {
307 124 olivier.gi
    WriteMem 0 $StartAddr $DataArray
308 2 olivier.gi
    } else {
309
 
310 124 olivier.gi
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
311
    dbg_uart_wr MEM_ADDR $StartAddr
312
    dbg_uart_wr MEM_CTL  0x0003
313 2 olivier.gi
 
314 124 olivier.gi
    foreach data [split $DataArray] {
315 2 olivier.gi
 
316 124 olivier.gi
        # Format data
317
        set data [format %04x $data]
318
        regexp {(..)(..)} $data match data_msb data_lsb
319 2 olivier.gi
 
320 124 olivier.gi
        # Send data
321
        dbg_uart_tx "0x$data_lsb 0x$data_msb"
322 2 olivier.gi
    }
323 124 olivier.gi
    }
324 2 olivier.gi
    return 1
325
}
326
 
327
#=============================================================================#
328
# ReadMem (Format, Addr)                                                      #
329
#-----------------------------------------------------------------------------#
330
# Description: Read one byte or word from a specified target memory address.  #
331
# Arguments  : Format - 0 to read a word, 1 to read a byte.                   #
332
#              Addr   - Target address for data to be read.                   #
333
# Result     : Data value stored in the target address memory location.       #
334
#=============================================================================#
335
proc ReadMem {Format Addr} {
336
 
337
    dbg_uart_wr MEM_CNT  0x0000
338
    dbg_uart_wr MEM_ADDR $Addr
339
 
340
    if {$Format==0} {
341 124 olivier.gi
    dbg_uart_wr MEM_CTL  0x0001
342
    set mem_val [dbg_uart_rd MEM_DATA]
343 2 olivier.gi
    } else {
344 124 olivier.gi
    dbg_uart_wr MEM_CTL  0x0009
345
    set mem_val [dbg_uart_rd MEM_DATA]
346
    set mem_val [format "0x%02x" $mem_val]
347 2 olivier.gi
    }
348
 
349
    return $mem_val
350
}
351
 
352
#=============================================================================#
353
# ReadMemQuick (StartAddr, Length)                                            #
354
#-----------------------------------------------------------------------------#
355
# Description: Reads an array of words from target memory.                    #
356
# Arguments  : StartAddr - Start address of target memory to be read.         #
357
#              Length    - Number of word to be read.                         #
358
# Result     : List of data values stored in the target memory.               #
359
#=============================================================================#
360
proc ReadMemQuick {StartAddr Length} {
361
 
362
    if {$Length==1} {
363 124 olivier.gi
    set mem_val [ReadMem 0 $StartAddr]
364 2 olivier.gi
    } else {
365
 
366 124 olivier.gi
    dbg_uart_wr MEM_CNT  [expr $Length-1]
367
    dbg_uart_wr MEM_ADDR $StartAddr
368
    dbg_uart_wr MEM_CTL  0x0001
369 2 olivier.gi
 
370 124 olivier.gi
    set mem_val [dbg_uart_rx 0 [expr $Length*2]]
371 2 olivier.gi
    }
372
    return $mem_val
373
}
374
 
375
#=============================================================================#
376
# VerifyMem (StartAddr, DataArray)                                            #
377
#-----------------------------------------------------------------------------#
378
# Description: Performs a program verification over the given memory range.   #
379
# Arguments  : StartAddr - Start address of the memory to be verified.        #
380
#              DataArray - List of reference data (in hexadecimal).           #
381
# Result     : 0 if error, 1 if verification was successful.                  #
382
#=============================================================================#
383 77 olivier.gi
proc VerifyMem {StartAddr DataArray {DumpOnError 0}} {
384 2 olivier.gi
 
385
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
386
    dbg_uart_wr MEM_ADDR $StartAddr
387
    dbg_uart_wr MEM_CTL  0x0001
388
 
389
    set mem_val [dbg_uart_rx 0 [expr [llength $DataArray]*2]]
390
 
391 74 olivier.gi
    set    return_val [string equal $DataArray $mem_val]
392
 
393 77 olivier.gi
    if {($return_val==0) && ($DumpOnError==1)} {
394 124 olivier.gi
    file delete -force openmsp430-verifymem-debug-original.mem
395
    file delete -force openmsp430-verifymem-debug-dumped.mem
396
    set fileId [open openmsp430-verifymem-debug-original.mem "w"]
397
    foreach hexCode $DataArray {
398
        puts $fileId $hexCode
399 77 olivier.gi
    }
400 124 olivier.gi
    close $fileId
401
    set fileId [open openmsp430-verifymem-debug-dumped.mem "w"]
402
    foreach hexCode $mem_val {
403
        puts $fileId $hexCode
404
    }
405
    close $fileId
406
    }
407 74 olivier.gi
 
408
    return $return_val
409 2 olivier.gi
}
410
 
411
#=============================================================================#
412
# ExecutePOR_Halt ()                                                          #
413
#-----------------------------------------------------------------------------#
414
# Description: Same as ExecutePOR with the difference that the CPU            #
415
#              automatically goes in Halt mode after reset.                   #
416
# Arguments  : None.                                                          #
417
# Result     : 0 if error, 1 otherwise.                                       #
418
#=============================================================================#
419
proc ExecutePOR_Halt {} {
420
 
421
    set result 1
422
 
423
    # Perform PUC
424
    set cpu_ctl_org [dbg_uart_rd CPU_CTL]
425
    set cpu_ctl_new [expr 0x60 | $cpu_ctl_org]
426
    dbg_uart_wr CPU_CTL $cpu_ctl_new
427
    dbg_uart_wr CPU_CTL $cpu_ctl_org
428
 
429
    # Check CPU ID
430 74 olivier.gi
    if {![VerifyCPU_ID]} {
431 124 olivier.gi
    set result 0
432 2 olivier.gi
    }
433
 
434
    # Check status: make sure a PUC occured and that the CPU is halted
435
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
436
    set puc_pnd      [expr 0x05 & $cpu_stat_val]
437
    if {![string eq $puc_pnd 5]} {
438 124 olivier.gi
    set result 0
439 2 olivier.gi
    }
440
 
441
    # Clear PUC pending flag
442
    dbg_uart_wr CPU_STAT 0x04
443
 
444
    return $result
445
}
446
 
447
#=============================================================================#
448
# GetCPU_ID ()                                                                #
449
#-----------------------------------------------------------------------------#
450 110 olivier.gi
# Description: This function reads the CPU_ID from the target device, update  #
451
#              the omsp_info global variable and return the raw CPU_ID value. #
452 2 olivier.gi
# Arguments  : None.                                                          #
453
# Result     : Return CPU_ID.                                                 #
454
#=============================================================================#
455
proc GetCPU_ID { } {
456
 
457 110 olivier.gi
    global omsp_info
458 124 olivier.gi
 
459 110 olivier.gi
    # Retreive CPU_ID values
460 124 olivier.gi
    set cpu_id_lo [dbg_uart_rd CPU_ID_LO]
461
    set cpu_id_hi [dbg_uart_rd CPU_ID_HI]
462
 
463
    # Check if value is valid
464
    if {[string eq "0x" $cpu_id_lo]} {
465
        set cpu_id_lo "0x0000"
466
    }
467
    if {[string eq "0x" $cpu_id_hi]} {
468
        set cpu_id_hi "0x0000"
469
    }
470
 
471
    # Remove the "0x" prefix
472
    regsub {0x} $cpu_id_lo {} cpu_id_lo
473
    regsub {0x} $cpu_id_hi {} cpu_id_hi
474 2 olivier.gi
 
475 110 olivier.gi
    set cpu_id    "0x$cpu_id_hi$cpu_id_lo"
476
    set cpu_id_lo "0x$cpu_id_lo"
477
    set cpu_id_hi "0x$cpu_id_hi"
478
 
479
 
480
    # Extract the omsp info depending on the CPU version
481
    set omsp_info(cpu_ver) [expr ($cpu_id_lo & 0x0007)+1]
482
    if {$omsp_info(cpu_ver)==1} {
483 124 olivier.gi
    set omsp_info(asic)         0
484
    set omsp_info(user_ver)    --
485
    set omsp_info(per_size)   512
486
    set omsp_info(mpy)         --
487
    set omsp_info(dmem_size)  [expr $cpu_id_lo]
488
    set omsp_info(pmem_size)  [expr $cpu_id_hi]
489 110 olivier.gi
    } else {
490 124 olivier.gi
    set omsp_info(asic)       [expr  ($cpu_id_lo & 0x0008)/8]
491
    set omsp_info(user_ver)   [expr  ($cpu_id_lo & 0x01f0)/9]
492
    set omsp_info(per_size)   [expr (($cpu_id_lo & 0xfe00)/512)  * 512]
493
    set omsp_info(mpy)        [expr  ($cpu_id_hi & 0x0001)/1]
494
    set omsp_info(dmem_size)  [expr (($cpu_id_hi & 0x03fe)/2)    * 128]
495
    set omsp_info(pmem_size)  [expr (($cpu_id_hi & 0xfc00)/1024) * 1024]
496 110 olivier.gi
    }
497
 
498
    set omsp_info(alias) [GetChipAlias]
499
 
500
    return $cpu_id
501 2 olivier.gi
}
502
 
503
#=============================================================================#
504
# GetCPU_ID_SIZE ()                                                           #
505
#-----------------------------------------------------------------------------#
506 110 olivier.gi
# Description: Returns the Data and Program memory sizes of the connected     #
507
#              device.                                                        #
508 2 olivier.gi
# Arguments  : None.                                                          #
509 110 olivier.gi
# Result     : Return "PMEM_SIZE DMEM_SIZE" in byte.                          #
510 2 olivier.gi
#=============================================================================#
511 74 olivier.gi
proc GetCPU_ID_SIZE {} {
512 2 olivier.gi
 
513 110 olivier.gi
    global omsp_info
514 2 olivier.gi
 
515 110 olivier.gi
    if {[info exists omsp_info(pmem_size)]} {
516 124 olivier.gi
    set pmem_size $omsp_info(pmem_size)
517 87 olivier.gi
    } else {
518 110 olivier.gi
        set pmem_size -1
519 87 olivier.gi
    }
520 110 olivier.gi
    if {[info exists omsp_info(dmem_size)]} {
521 124 olivier.gi
    set dmem_size $omsp_info(dmem_size)
522 87 olivier.gi
    } else {
523 110 olivier.gi
        set dmem_size -1
524 87 olivier.gi
    }
525 2 olivier.gi
 
526 110 olivier.gi
    return "$pmem_size $dmem_size"
527 2 olivier.gi
}
528
 
529
#=============================================================================#
530 74 olivier.gi
# VerifyCPU_ID ()                                                             #
531 2 olivier.gi
#-----------------------------------------------------------------------------#
532
# Description: Read and check the CPU_ID from the target device.              #
533
# Arguments  : None.                                                          #
534
# Result     : 0 if error, 1 otherwise.                                       #
535
#=============================================================================#
536 74 olivier.gi
proc VerifyCPU_ID {} {
537 2 olivier.gi
 
538 114 olivier.gi
    global omsp_info
539
 
540 2 olivier.gi
    set cpu_id_full [GetCPU_ID]
541
 
542 110 olivier.gi
    if {[string eq "0x00000000" $cpu_id_full] |
543 124 olivier.gi
    ([string length $cpu_id_full]!=10)    |
544 133 olivier.gi
        ($omsp_info(cpu_ver) >3)              } {
545 124 olivier.gi
    puts "\n"
546
    puts "ERROR: cpu_id not valid: $cpu_id_full"
547
    puts ""
548
    puts "         -------------------------------------------------------------"
549
    puts "       !!!! Make sure that you are properly connected to the board  !!!!"
550
    puts "       !!!! or try reseting the serial debug interface (or CPU).    !!!!"
551
    puts "         -------------------------------------------------------------"
552
    puts ""
553
    set result 0
554 74 olivier.gi
    } else {
555 124 olivier.gi
    set result 1
556 2 olivier.gi
    }
557
    return $result
558
}
559
 
560
#=============================================================================#
561
# WriteReg (Addr,  Data)                                                      #
562
#-----------------------------------------------------------------------------#
563
# Description: Write a word to the the selected CPU register.                 #
564
# Arguments  : Addr - Target CPU Register number.                             #
565
#              Data - Data value to be written.                               #
566
# Result     : 0 if error, 1 otherwise.                                       #
567
#=============================================================================#
568
proc WriteReg {Addr Data} {
569
 
570
    dbg_uart_wr MEM_CNT  0x0000
571
 
572
    dbg_uart_wr MEM_ADDR $Addr
573
    dbg_uart_wr MEM_DATA $Data
574
    dbg_uart_wr MEM_CTL  0x0007
575
 
576
    return 1
577
}
578
 
579
#=============================================================================#
580
# WriteRegAll (DataArray)                                                     #
581
#-----------------------------------------------------------------------------#
582
# Description: Write all CPU registers.                                       #
583
# Arguments  : DataArray - Data values to be written.                         #
584
# Result     : 0 if error, 1 otherwise.                                       #
585
#=============================================================================#
586
proc WriteRegAll {DataArray} {
587
 
588
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
589
    dbg_uart_wr MEM_ADDR 0x0000
590
    dbg_uart_wr MEM_CTL  0x0007
591
 
592
    foreach data [split $DataArray] {
593
 
594 124 olivier.gi
    # Format data
595
    set data [format %04x $data]
596
    regexp {(..)(..)} $data match data_msb data_lsb
597 2 olivier.gi
 
598 124 olivier.gi
    # Send data
599
    dbg_uart_tx "0x$data_lsb 0x$data_msb"
600 2 olivier.gi
    }
601
 
602
    return 1
603
}
604
 
605
#=============================================================================#
606
# ReadReg (Addr)                                                              #
607
#-----------------------------------------------------------------------------#
608
# Description: Read the value from the selected CPU register.                 #
609
# Arguments  : Addr - Target CPU Register number.                             #
610
# Result     : Data value stored in the selected CPU register.                #
611
#=============================================================================#
612
proc ReadReg {Addr} {
613
 
614
    dbg_uart_wr MEM_CNT  0x0000
615
 
616
    dbg_uart_wr MEM_ADDR $Addr
617
    dbg_uart_wr MEM_CTL  0x0005
618
    set reg_val [dbg_uart_rd MEM_DATA]
619
 
620
    return $reg_val
621
}
622
 
623
#=============================================================================#
624
# ReadRegAll ()                                                               #
625
#-----------------------------------------------------------------------------#
626
# Description: Read all CPU registers.                                        #
627
# Arguments  : None.                                                          #
628
# Result     : Current values of all CPU registers.                           #
629
#=============================================================================#
630
proc ReadRegAll {} {
631
 
632
    dbg_uart_wr MEM_CNT  0x000f
633
    dbg_uart_wr MEM_ADDR 0x0000
634
    dbg_uart_wr MEM_CTL  0x0005
635
 
636
    set reg_val [dbg_uart_rx 0 32]
637
 
638
    return $reg_val
639
}
640
 
641
#=============================================================================#
642
# WriteMemQuick8 (StartAddr, DataArray)                                       #
643
#-----------------------------------------------------------------------------#
644
# Description: Writes an array of bytes into the target device memory (RAM,   #
645
#              ROM & Peripherals.                                             #
646
# Arguments  : StartAddr - Start address of destination memory.               #
647
#              DataArray - List of data to be written (in hexadecimal).       #
648
# Result     : 0 if error, 1 otherwise.                                       #
649
#=============================================================================#
650
proc WriteMemQuick8 {StartAddr DataArray} {
651
 
652
    if {[llength $DataArray]==1} {
653 124 olivier.gi
    WriteMem 1 $StartAddr $DataArray
654 2 olivier.gi
    } else {
655
 
656 124 olivier.gi
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
657
    dbg_uart_wr MEM_ADDR $StartAddr
658
    dbg_uart_wr MEM_CTL  0x000b
659 2 olivier.gi
 
660 124 olivier.gi
    foreach data [split $DataArray] {
661 2 olivier.gi
 
662 124 olivier.gi
        # Format data
663
        set data [format %02x $data]
664 2 olivier.gi
 
665 124 olivier.gi
        # Send data
666
        dbg_uart_tx "0x$data"
667 2 olivier.gi
    }
668 124 olivier.gi
    }
669 2 olivier.gi
    return 1
670
}
671
 
672
#=============================================================================#
673
# ReadMemQuick8 (StartAddr, Length)                                           #
674
#-----------------------------------------------------------------------------#
675
# Description: Reads an array of bytes from target memory.                    #
676
# Arguments  : StartAddr - Start address of target memory to be read.         #
677
#              Length    - Number of bytes to be read.                        #
678
# Result     : List of data values stored in the target memory.               #
679
#=============================================================================#
680
proc ReadMemQuick8 {StartAddr Length} {
681
 
682
    if {$Length==1} {
683 124 olivier.gi
    set mem_val [ReadMem 1 $StartAddr]
684 2 olivier.gi
    } else {
685 124 olivier.gi
    dbg_uart_wr MEM_CNT  [expr $Length-1]
686
    dbg_uart_wr MEM_ADDR $StartAddr
687
    dbg_uart_wr MEM_CTL  0x0009
688 2 olivier.gi
 
689 124 olivier.gi
    set mem_val [dbg_uart_rx 1 [expr $Length]]
690 2 olivier.gi
    }
691
 
692
    return $mem_val
693
}
694
 
695
#=============================================================================#
696
# StepCPU ()                                                                  #
697
#-----------------------------------------------------------------------------#
698
# Description: Performs a CPU incremental step.                               #
699
# Arguments  : None.                                                          #
700
# Result     : 0 if error, 1 otherwise.                                       #
701
#=============================================================================#
702
proc StepCPU {} {
703
 
704
    # Check if the device is halted. If not, stop it.
705
    set cpu_ctl_val [dbg_uart_rd CPU_CTL]
706
    set cpu_ctl_new [expr 0x04 | $cpu_ctl_val]
707
    dbg_uart_wr CPU_CTL $cpu_ctl_new
708
 
709
    return 1
710
}
711
 
712
#=============================================================================#
713
# EraseRAM ()                                                                 #
714
#-----------------------------------------------------------------------------#
715
# Description: Erase RAM.                                                     #
716
# Arguments  : None.                                                          #
717
# Result     : 0 if error, 1 otherwise.                                       #
718
#=============================================================================#
719
proc EraseRAM {} {
720
 
721
    set ram_size [lindex [GetCPU_ID_SIZE] 1]
722
 
723 87 olivier.gi
    if {$ram_size!=-1} {
724 124 olivier.gi
    set DataArray ""
725
    for {set i 0} {$i<$ram_size} {incr i} {
726
        lappend DataArray 0x00
727
    }
728 2 olivier.gi
 
729 124 olivier.gi
    WriteMemQuick8 $0x0200 $DataArray
730 2 olivier.gi
 
731 124 olivier.gi
    return 1
732 87 olivier.gi
    }
733
    return 0
734 2 olivier.gi
}
735
 
736
#=============================================================================#
737
# EraseROM ()                                                                 #
738
#-----------------------------------------------------------------------------#
739
# Description: Erase ROM.                                                     #
740
# Arguments  : None.                                                          #
741
# Result     : 0 if error, 1 otherwise.                                       #
742
#=============================================================================#
743
proc EraseROM {} {
744
 
745
    set rom_size  [lindex [GetCPU_ID_SIZE] 0]
746
    set rom_start [expr 0x10000-$rom_size]
747
 
748 96 olivier.gi
    if {$rom_size!=-1} {
749 124 olivier.gi
    set DataArray ""
750
    for {set i 0} {$i<$rom_size} {incr i} {
751
        lappend DataArray 0x00
752
    }
753 2 olivier.gi
 
754 124 olivier.gi
    WriteMemQuick8 $rom_start $DataArray
755 2 olivier.gi
 
756 124 olivier.gi
    return 1
757 87 olivier.gi
    }
758
    return 0
759 2 olivier.gi
}
760
 
761
#=============================================================================#
762
# InitBreakUnits()                                                            #
763
#-----------------------------------------------------------------------------#
764
# Description: Initialize the hardware breakpoint units.                      #
765
# Arguments  : None.                                                          #
766
# Result     : Number of hardware breakpoint units.                           #
767
#=============================================================================#
768
proc InitBreakUnits {} {
769
 
770
    set num_brk_units 0
771
    for {set i 0} {$i<4} {incr i} {
772
 
773 124 olivier.gi
    dbg_uart_wr "BRK$i\_ADDR0" 0x1234
774
    set new_val [dbg_uart_rd "BRK$i\_ADDR0"]
775
    if {$new_val=="0x1234"} {
776
        incr num_brk_units
777
        dbg_uart_wr "BRK$i\_CTL"   0x00
778
        dbg_uart_wr "BRK$i\_STAT"  0xff
779
        dbg_uart_wr "BRK$i\_ADDR0" 0x0000
780
        dbg_uart_wr "BRK$i\_ADDR1" 0x0000
781 2 olivier.gi
    }
782 124 olivier.gi
    }
783 2 olivier.gi
    return $num_brk_units
784
}
785
 
786
#=============================================================================#
787
# SetHWBreak(Type, Addr, Rd, Wr)                                              #
788
#-----------------------------------------------------------------------------#
789
# Description: Set data/instruction breakpoint on a given memory address.     #
790
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
791
#              Addr - Memory address of the data breakpoint.                  #
792
#              Rd   - Breakpoint on read access.                              #
793
#              Wr   - Breakpoint on write access.                             #
794
# Result     : 0 if error, 1 otherwise.                                       #
795
#=============================================================================#
796
proc SetHWBreak {Type Addr Rd Wr} {
797
    global hw_break
798
 
799
    # Compute the BRKx_CTL corresponding value
800
    set brk_ctl_ref [format "0x02%x" [expr 8*$Type+4+2*$Wr+$Rd]]
801
 
802
    # First look for utilized units with correct BRKx_CTL attributes
803
    for {set i 0} {$i<$hw_break(num)} {incr i} {
804 124 olivier.gi
    if {[string eq [dbg_uart_rd "BRK$i\_CTL"] $brk_ctl_ref]} {
805
        # Look if there is an address free
806
        set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
807
        set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
808
        if {[string eq $brk_addr0 $brk_addr1]} {
809
        dbg_uart_wr "BRK$i\_ADDR1" $Addr
810
        return 1
811
        }
812 2 olivier.gi
    }
813 124 olivier.gi
    }
814 2 olivier.gi
 
815
    # Then look for a free unit
816
    for {set i 0} {$i<$hw_break(num)} {incr i} {
817 124 olivier.gi
    if {[string eq [dbg_uart_rd "BRK$i\_CTL"] 0x00]} {
818
        dbg_uart_wr "BRK$i\_ADDR0" $Addr
819
        dbg_uart_wr "BRK$i\_ADDR1" $Addr
820
        dbg_uart_wr "BRK$i\_CTL"   $brk_ctl_ref
821
        return 1
822 2 olivier.gi
    }
823 124 olivier.gi
    }
824 2 olivier.gi
 
825
    return 0
826
}
827
 
828
#=============================================================================#
829
# ClearHWBreak(Type, Addr)                                                    #
830
#-----------------------------------------------------------------------------#
831
# Description: Clear the data/instruction breakpoint set on the provided      #
832
#              memory address.                                                #
833
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
834
#              Addr - Data address of the breakpoint to be cleared.           #
835
# Result     : 0 if error, 1 otherwise.                                       #
836
#=============================================================================#
837
proc ClearHWBreak {Type Addr} {
838
    global hw_break
839
 
840
    for {set i 0} {$i<$hw_break(num)} {incr i} {
841 124 olivier.gi
    # Check if the unit works on Data or Instructions)
842
    set brk_ctl [dbg_uart_rd "BRK$i\_CTL"]
843
    if {[expr $brk_ctl & 0x08]==[expr 8*$Type]} {
844 2 olivier.gi
 
845 124 olivier.gi
        # Look for the matching address
846
        set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
847
        set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
848 2 olivier.gi
 
849 124 olivier.gi
        if {[string eq $brk_addr0 $brk_addr1] && [string eq $brk_addr0 $Addr]} {
850
        dbg_uart_wr "BRK$i\_CTL"   0x00
851
        dbg_uart_wr "BRK$i\_STAT"  0xff
852
        dbg_uart_wr "BRK$i\_ADDR0" 0x0000
853
        dbg_uart_wr "BRK$i\_ADDR1" 0x0000
854
        return 1
855
        }
856
        if {[string eq $brk_addr0 $Addr]} {
857
        dbg_uart_wr "BRK$i\_ADDR0" $brk_addr1
858
        return 1
859
        }
860
        if {[string eq $brk_addr1 $Addr]} {
861
        dbg_uart_wr "BRK$i\_ADDR1" $brk_addr0
862
        return 1
863
        }
864 2 olivier.gi
    }
865 124 olivier.gi
    }
866 2 olivier.gi
    return 1
867
}
868
 
869
#=============================================================================#
870
# IsHalted ()                                                                 #
871
#-----------------------------------------------------------------------------#
872
# Description: Check if the CPU is currently stopped or not.                  #
873
# Arguments  : None.                                                          #
874
# Result     : 0 if CPU is running, 1 if stopped.                             #
875
#=============================================================================#
876
proc IsHalted {} {
877
 
878
    # Check current target status
879
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
880
    set halted       [expr 0x01 & $cpu_stat_val]
881
 
882
    return $halted
883
}
884
 
885
#=============================================================================#
886
# ClrStatus ()                                                                #
887
#-----------------------------------------------------------------------------#
888
# Description: Clear the status bit of the CPU_STAT register.                 #
889
# Arguments  : None.                                                          #
890
# Result     : 0 if error, 1 otherwise.                                       #
891
#=============================================================================#
892
proc ClrStatus {} {
893
 
894
    # Clear status
895
    dbg_uart_wr CPU_STAT  0xff
896
    dbg_uart_wr BRK0_STAT 0xff
897
    dbg_uart_wr BRK1_STAT 0xff
898
    dbg_uart_wr BRK2_STAT 0xff
899
    dbg_uart_wr BRK3_STAT 0xff
900
 
901
    return 1
902
}
903 110 olivier.gi
 
904
#=============================================================================#
905
# GetChipAlias ()                                                             #
906
#-----------------------------------------------------------------------------#
907
# Description: Parse the chip alias XML file an return the alias name.        #
908
# Arguments  : None.                                                          #
909
# Result     : Chip Alias.                                                    #
910
#=============================================================================#
911
proc GetChipAlias {} {
912
 
913
    global omsp_info
914
 
915
    # Set XML file name
916
    if {[info exists  ::env(OMSP_XML_FILE)]} {
917 124 olivier.gi
    set xmlFile $::env(OMSP_XML_FILE)
918 110 olivier.gi
    } else {
919 124 olivier.gi
    set xmlFile [file normalize "$::scriptDir/../../omsp_alias.xml"]
920 110 olivier.gi
    }
921
 
922
    # Read XML file
923
    if {[file exists $xmlFile]} {
924 124 olivier.gi
    set fp [open $xmlFile r]
925
    set xmlData [read $fp]
926
    close $fp
927 110 olivier.gi
    } else {
928 124 olivier.gi
    puts "WARNING: the XML alias file was not found - $xmlFile"
929
    return ""
930 110 olivier.gi
    }
931
 
932
    # Analyze XML file
933
    ::XML::Init $xmlData
934
    set wellFormed [::XML::IsWellFormed]
935
    if {$wellFormed ne ""} {
936 124 olivier.gi
    puts "WARNING: the XML alias file is not well-formed - $xmlFile \n $wellFormed"
937
    return ""
938 110 olivier.gi
    }
939
 
940
    #========================================================================#
941
    # Create list from XML file                                              #
942
    #========================================================================#
943
    set aliasList    ""
944
    set currentALIAS ""
945
    set currentTYPE  ""
946
    set currentTAG   ""
947
    while {1} {
948 124 olivier.gi
    foreach {type val attr etype} [::XML::NextToken] break
949
    if {$type == "EOF"} break
950 110 olivier.gi
 
951 124 olivier.gi
    # Detect the start of a new alias description
952
    if {($type == "XML") & ($val == "omsp:alias") & ($etype == "START")} {
953
        set aliasName ""
954
        regexp {val=\"(.*)\"} $attr whole_match aliasName
955
        lappend aliasList $aliasName
956
        set currentALIAS $aliasName
957
    }
958 110 olivier.gi
 
959 124 olivier.gi
    # Detect start and end of the configuration field
960
    if {($type == "XML") & ($val == "omsp:configuration")} {
961 110 olivier.gi
 
962 124 olivier.gi
        if {($etype == "START")} {
963
        set currentTYPE  "config"
964 110 olivier.gi
 
965 124 olivier.gi
        } elseif {($etype == "END")} {
966
        set currentTYPE  ""
967
        }
968
    }
969 110 olivier.gi
 
970 124 olivier.gi
    # Detect start and end of the extra_info field
971
    if {($type == "XML") & ($val == "omsp:extra_info")} {
972 110 olivier.gi
 
973 124 olivier.gi
        if {($etype == "START")} {
974
        set currentTYPE  "extra_info"
975
        set idx 0
976 110 olivier.gi
 
977 124 olivier.gi
        } elseif {($etype == "END")} {
978
        set currentTYPE  ""
979
        }
980
    }
981 110 olivier.gi
 
982 124 olivier.gi
    # Detect the current TAG
983
    if {($type == "XML") & ($etype == "START")} {
984
        regsub {omsp:} $val {} val
985
        set currentTAG $val
986
    }
987 110 olivier.gi
 
988 124 olivier.gi
    if {($type == "TXT")} {
989
        if {$currentTYPE=="extra_info"} {
990
        set alias($currentALIAS,$currentTYPE,$idx,$currentTAG) $val
991
        incr idx
992
        } else {
993
        set alias($currentALIAS,$currentTYPE,$currentTAG) $val
994
        }
995 110 olivier.gi
    }
996 124 olivier.gi
    }
997 110 olivier.gi
 
998
    #========================================================================#
999
    # Check if the current OMSP_INFO has an alias match                      #
1000
    #========================================================================#
1001
    foreach currentALIAS $aliasList {
1002 124 olivier.gi
    set aliasCONFIG [array names alias -glob "$currentALIAS,config,*"]
1003
    set aliasEXTRA  [lsort -increasing [array names alias -glob "$currentALIAS,extra_info,*"]]
1004 110 olivier.gi
 
1005 124 olivier.gi
    #----------------------------------#
1006
    # Is current alias matching ?      #
1007
    #----------------------------------#
1008
    set match       1
1009
    set description ""
1010
    foreach currentCONFIG $aliasCONFIG {
1011 110 olivier.gi
 
1012 124 olivier.gi
        regsub "$currentALIAS,config," $currentCONFIG {} configName
1013 110 olivier.gi
 
1014 124 olivier.gi
        if {![string eq $omsp_info($configName) $alias($currentCONFIG)]} {
1015
        set match 0
1016
        }
1017
    }
1018 110 olivier.gi
 
1019 124 olivier.gi
    #----------------------------------#
1020
    # If matching, get the extra infos #
1021
    #----------------------------------#
1022
    if {$match} {
1023 110 olivier.gi
 
1024 124 olivier.gi
        set idx 0
1025
        foreach currentEXTRA $aliasEXTRA {
1026
        regsub "$currentALIAS,extra_info," $currentEXTRA {} extraName
1027
        set omsp_info(extra,$idx,$extraName) $alias($currentEXTRA)
1028
        incr idx
1029
        }
1030
        return $currentALIAS
1031 110 olivier.gi
    }
1032 124 olivier.gi
    }
1033 110 olivier.gi
 
1034
    return ""
1035
}

powered by: WebSVN 2.1.0

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