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 114

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: 114 $
32
# $LastChangedBy: olivier.girard $
33
# $LastChangedDate: 2011-05-26 22:18:29 +0200 (Thu, 26 May 2011) $
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 110 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 110 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
        set result 0
161
    }
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
        set result 0
188
    }
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
        set ::serial_baudrate 9600
211
    }
212
    if {![info exists ::serial_device]} {
213
        set ::serial_device   /dev/ttyUSB0
214
    }
215
 
216
    # Open connection
217
    if {![dbg_uart_connect $::serial_device $::serial_baudrate]} {
218
        return 0
219
    }
220
 
221 110 olivier.gi
    if {[VerifyCPU_ID]} {
222 2 olivier.gi
 
223 110 olivier.gi
        # Enable auto-freeze & software breakpoints
224
        dbg_uart_wr CPU_CTL 0x0018
225 2 olivier.gi
 
226 110 olivier.gi
        # Initialize the omsp_info global variable
227
        GetCPU_ID
228
        set omsp_info(connected) 1
229
 
230
        # Get number of hardware breakpoints
231
        set hw_break(num)       [InitBreakUnits]
232
        set omsp_info(hw_break) $hw_break(num)
233
 
234
 
235
        return 1
236
    } else {
237
        return 0
238
    }
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
        set result 1
254
        set result [expr $result+[ExecutePOR]]
255
        set result [expr $result+[ReleaseCPU]]
256
    } else {
257
        set result 0
258
        set result [expr $result+[HaltCPU]]
259
        set result [expr $result+[SetPC $Addr]]
260
        set result [expr $result+[ReleaseCPU]]
261
    }
262
 
263
    if {$result==3} {
264
        return 1
265
    } else {
266
        return 0
267
    }
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
        dbg_uart_wr MEM_CTL  0x0003
288
    } else {
289
        dbg_uart_wr MEM_CTL  0x000b
290
    }
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
        WriteMem 0 $StartAddr $DataArray
308
    } else {
309
 
310
        dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
311
        dbg_uart_wr MEM_ADDR $StartAddr
312
        dbg_uart_wr MEM_CTL  0x0003
313
 
314
        foreach data [split $DataArray] {
315
 
316
            # Format data
317
            set data [format %04x $data]
318
            regexp {(..)(..)} $data match data_msb data_lsb
319
 
320
            # Send data
321
            dbg_uart_tx "0x$data_lsb 0x$data_msb"
322
        }
323
    }
324
    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
        dbg_uart_wr MEM_CTL  0x0001
342
        set mem_val [dbg_uart_rd MEM_DATA]
343
    } else {
344
        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
    }
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
        set mem_val [ReadMem 0 $StartAddr]
364
    } else {
365
 
366
        dbg_uart_wr MEM_CNT  [expr $Length-1]
367
        dbg_uart_wr MEM_ADDR $StartAddr
368
        dbg_uart_wr MEM_CTL  0x0001
369
 
370
        set mem_val [dbg_uart_rx 0 [expr $Length*2]]
371
    }
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
        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
        }
400
        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 2 olivier.gi
        set result 0
432
    }
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
        set result 0
439
    }
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
 
459
    # Retreive CPU_ID values
460 2 olivier.gi
    regsub {0x} [dbg_uart_rd CPU_ID_LO] {} cpu_id_lo
461
    regsub {0x} [dbg_uart_rd CPU_ID_HI] {} cpu_id_hi
462
 
463 110 olivier.gi
    set cpu_id    "0x$cpu_id_hi$cpu_id_lo"
464
    set cpu_id_lo "0x$cpu_id_lo"
465
    set cpu_id_hi "0x$cpu_id_hi"
466
 
467
 
468
    # Extract the omsp info depending on the CPU version
469
    set omsp_info(cpu_ver) [expr ($cpu_id_lo & 0x0007)+1]
470
    if {$omsp_info(cpu_ver)==1} {
471
        set omsp_info(asic)         0
472
        set omsp_info(user_ver)    --
473
        set omsp_info(per_size)   512
474
        set omsp_info(mpy)         --
475
        set omsp_info(dmem_size)  [expr $cpu_id_lo]
476
        set omsp_info(pmem_size)  [expr $cpu_id_hi]
477
    } else {
478
        set omsp_info(asic)       [expr  ($cpu_id_lo & 0x0008)/8]
479
        set omsp_info(user_ver)   [expr  ($cpu_id_lo & 0x01f0)/9]
480
        set omsp_info(per_size)   [expr (($cpu_id_lo & 0xfe00)/512)  * 512]
481
        set omsp_info(mpy)        [expr  ($cpu_id_hi & 0x0001)/1]
482
        set omsp_info(dmem_size)  [expr (($cpu_id_hi & 0x03fe)/2)    * 128]
483
        set omsp_info(pmem_size)  [expr (($cpu_id_hi & 0xfc00)/1024) * 1024]
484
    }
485
 
486
    set omsp_info(alias) [GetChipAlias]
487
 
488
    return $cpu_id
489 2 olivier.gi
}
490
 
491
#=============================================================================#
492
# GetCPU_ID_SIZE ()                                                           #
493
#-----------------------------------------------------------------------------#
494 110 olivier.gi
# Description: Returns the Data and Program memory sizes of the connected     #
495
#              device.                                                        #
496 2 olivier.gi
# Arguments  : None.                                                          #
497 110 olivier.gi
# Result     : Return "PMEM_SIZE DMEM_SIZE" in byte.                          #
498 2 olivier.gi
#=============================================================================#
499 74 olivier.gi
proc GetCPU_ID_SIZE {} {
500 2 olivier.gi
 
501 110 olivier.gi
    global omsp_info
502 2 olivier.gi
 
503 110 olivier.gi
    if {[info exists omsp_info(pmem_size)]} {
504
        set pmem_size $omsp_info(pmem_size)
505 87 olivier.gi
    } else {
506 110 olivier.gi
        set pmem_size -1
507 87 olivier.gi
    }
508 110 olivier.gi
    if {[info exists omsp_info(dmem_size)]} {
509
        set dmem_size $omsp_info(dmem_size)
510 87 olivier.gi
    } else {
511 110 olivier.gi
        set dmem_size -1
512 87 olivier.gi
    }
513 2 olivier.gi
 
514 110 olivier.gi
    return "$pmem_size $dmem_size"
515 2 olivier.gi
}
516
 
517
#=============================================================================#
518 74 olivier.gi
# VerifyCPU_ID ()                                                             #
519 2 olivier.gi
#-----------------------------------------------------------------------------#
520
# Description: Read and check the CPU_ID from the target device.              #
521
# Arguments  : None.                                                          #
522
# Result     : 0 if error, 1 otherwise.                                       #
523
#=============================================================================#
524 74 olivier.gi
proc VerifyCPU_ID {} {
525 2 olivier.gi
 
526 114 olivier.gi
    global omsp_info
527
 
528 2 olivier.gi
    set cpu_id_full [GetCPU_ID]
529
 
530 110 olivier.gi
    if {[string eq "0x00000000" $cpu_id_full] |
531 114 olivier.gi
        ([string length $cpu_id_full]!=10)    |
532
        ($omsp_info(cpu_ver) >2)              } {
533
        puts "\n"
534
        puts "ERROR: cpu_id not valid: $cpu_id_full"
535
        puts ""
536
        puts "         -------------------------------------------------------------"
537
        puts "       !!!! Make sure that you are properly connectec to the board  !!!!"
538
        puts "       !!!! or try reseting the serial debug interface (or CPU).    !!!!"
539
        puts "         -------------------------------------------------------------"
540
        puts ""
541 74 olivier.gi
        set result 0
542
    } else {
543 2 olivier.gi
        set result 1
544
    }
545
    return $result
546
}
547
 
548
#=============================================================================#
549
# WriteReg (Addr,  Data)                                                      #
550
#-----------------------------------------------------------------------------#
551
# Description: Write a word to the the selected CPU register.                 #
552
# Arguments  : Addr - Target CPU Register number.                             #
553
#              Data - Data value to be written.                               #
554
# Result     : 0 if error, 1 otherwise.                                       #
555
#=============================================================================#
556
proc WriteReg {Addr Data} {
557
 
558
    dbg_uart_wr MEM_CNT  0x0000
559
 
560
    dbg_uart_wr MEM_ADDR $Addr
561
    dbg_uart_wr MEM_DATA $Data
562
    dbg_uart_wr MEM_CTL  0x0007
563
 
564
    return 1
565
}
566
 
567
#=============================================================================#
568
# WriteRegAll (DataArray)                                                     #
569
#-----------------------------------------------------------------------------#
570
# Description: Write all CPU registers.                                       #
571
# Arguments  : DataArray - Data values to be written.                         #
572
# Result     : 0 if error, 1 otherwise.                                       #
573
#=============================================================================#
574
proc WriteRegAll {DataArray} {
575
 
576
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
577
    dbg_uart_wr MEM_ADDR 0x0000
578
    dbg_uart_wr MEM_CTL  0x0007
579
 
580
    foreach data [split $DataArray] {
581
 
582
        # Format data
583
        set data [format %04x $data]
584
        regexp {(..)(..)} $data match data_msb data_lsb
585
 
586
        # Send data
587
        dbg_uart_tx "0x$data_lsb 0x$data_msb"
588
    }
589
 
590
    return 1
591
}
592
 
593
#=============================================================================#
594
# ReadReg (Addr)                                                              #
595
#-----------------------------------------------------------------------------#
596
# Description: Read the value from the selected CPU register.                 #
597
# Arguments  : Addr - Target CPU Register number.                             #
598
# Result     : Data value stored in the selected CPU register.                #
599
#=============================================================================#
600
proc ReadReg {Addr} {
601
 
602
    dbg_uart_wr MEM_CNT  0x0000
603
 
604
    dbg_uart_wr MEM_ADDR $Addr
605
    dbg_uart_wr MEM_CTL  0x0005
606
    set reg_val [dbg_uart_rd MEM_DATA]
607
 
608
    return $reg_val
609
}
610
 
611
#=============================================================================#
612
# ReadRegAll ()                                                               #
613
#-----------------------------------------------------------------------------#
614
# Description: Read all CPU registers.                                        #
615
# Arguments  : None.                                                          #
616
# Result     : Current values of all CPU registers.                           #
617
#=============================================================================#
618
proc ReadRegAll {} {
619
 
620
    dbg_uart_wr MEM_CNT  0x000f
621
    dbg_uart_wr MEM_ADDR 0x0000
622
    dbg_uart_wr MEM_CTL  0x0005
623
 
624
    set reg_val [dbg_uart_rx 0 32]
625
 
626
    return $reg_val
627
}
628
 
629
#=============================================================================#
630
# WriteMemQuick8 (StartAddr, DataArray)                                       #
631
#-----------------------------------------------------------------------------#
632
# Description: Writes an array of bytes into the target device memory (RAM,   #
633
#              ROM & Peripherals.                                             #
634
# Arguments  : StartAddr - Start address of destination memory.               #
635
#              DataArray - List of data to be written (in hexadecimal).       #
636
# Result     : 0 if error, 1 otherwise.                                       #
637
#=============================================================================#
638
proc WriteMemQuick8 {StartAddr DataArray} {
639
 
640
    if {[llength $DataArray]==1} {
641
        WriteMem 1 $StartAddr $DataArray
642
    } else {
643
 
644
        dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
645
        dbg_uart_wr MEM_ADDR $StartAddr
646
        dbg_uart_wr MEM_CTL  0x000b
647
 
648
        foreach data [split $DataArray] {
649
 
650
            # Format data
651
            set data [format %02x $data]
652
 
653
            # Send data
654
            dbg_uart_tx "0x$data"
655
        }
656
    }
657
    return 1
658
}
659
 
660
#=============================================================================#
661
# ReadMemQuick8 (StartAddr, Length)                                           #
662
#-----------------------------------------------------------------------------#
663
# Description: Reads an array of bytes from target memory.                    #
664
# Arguments  : StartAddr - Start address of target memory to be read.         #
665
#              Length    - Number of bytes to be read.                        #
666
# Result     : List of data values stored in the target memory.               #
667
#=============================================================================#
668
proc ReadMemQuick8 {StartAddr Length} {
669
 
670
    if {$Length==1} {
671
        set mem_val [ReadMem 1 $StartAddr]
672
    } else {
673
        dbg_uart_wr MEM_CNT  [expr $Length-1]
674
        dbg_uart_wr MEM_ADDR $StartAddr
675
        dbg_uart_wr MEM_CTL  0x0009
676
 
677
        set mem_val [dbg_uart_rx 1 [expr $Length]]
678
    }
679
 
680
    return $mem_val
681
}
682
 
683
#=============================================================================#
684
# StepCPU ()                                                                  #
685
#-----------------------------------------------------------------------------#
686
# Description: Performs a CPU incremental step.                               #
687
# Arguments  : None.                                                          #
688
# Result     : 0 if error, 1 otherwise.                                       #
689
#=============================================================================#
690
proc StepCPU {} {
691
 
692
    # Check if the device is halted. If not, stop it.
693
    set cpu_ctl_val [dbg_uart_rd CPU_CTL]
694
    set cpu_ctl_new [expr 0x04 | $cpu_ctl_val]
695
    dbg_uart_wr CPU_CTL $cpu_ctl_new
696
 
697
    return 1
698
}
699
 
700
#=============================================================================#
701
# EraseRAM ()                                                                 #
702
#-----------------------------------------------------------------------------#
703
# Description: Erase RAM.                                                     #
704
# Arguments  : None.                                                          #
705
# Result     : 0 if error, 1 otherwise.                                       #
706
#=============================================================================#
707
proc EraseRAM {} {
708
 
709
    set ram_size [lindex [GetCPU_ID_SIZE] 1]
710
 
711 87 olivier.gi
    if {$ram_size!=-1} {
712
        set DataArray ""
713
        for {set i 0} {$i<$ram_size} {incr i} {
714
            lappend DataArray 0x00
715
        }
716 2 olivier.gi
 
717 87 olivier.gi
        WriteMemQuick8 $0x0200 $DataArray
718 2 olivier.gi
 
719 87 olivier.gi
        return 1
720
    }
721
    return 0
722 2 olivier.gi
}
723
 
724
#=============================================================================#
725
# EraseROM ()                                                                 #
726
#-----------------------------------------------------------------------------#
727
# Description: Erase ROM.                                                     #
728
# Arguments  : None.                                                          #
729
# Result     : 0 if error, 1 otherwise.                                       #
730
#=============================================================================#
731
proc EraseROM {} {
732
 
733
    set rom_size  [lindex [GetCPU_ID_SIZE] 0]
734
    set rom_start [expr 0x10000-$rom_size]
735
 
736 96 olivier.gi
    if {$rom_size!=-1} {
737 87 olivier.gi
        set DataArray ""
738
        for {set i 0} {$i<$rom_size} {incr i} {
739
            lappend DataArray 0x00
740
        }
741 2 olivier.gi
 
742 87 olivier.gi
        WriteMemQuick8 $rom_start $DataArray
743 2 olivier.gi
 
744 87 olivier.gi
        return 1
745
    }
746
    return 0
747 2 olivier.gi
}
748
 
749
#=============================================================================#
750
# InitBreakUnits()                                                            #
751
#-----------------------------------------------------------------------------#
752
# Description: Initialize the hardware breakpoint units.                      #
753
# Arguments  : None.                                                          #
754
# Result     : Number of hardware breakpoint units.                           #
755
#=============================================================================#
756
proc InitBreakUnits {} {
757
 
758
    set num_brk_units 0
759
    for {set i 0} {$i<4} {incr i} {
760
 
761
        dbg_uart_wr "BRK$i\_ADDR0" 0x1234
762
        set new_val [dbg_uart_rd "BRK$i\_ADDR0"]
763
        if {$new_val=="0x1234"} {
764
            incr num_brk_units
765
            dbg_uart_wr "BRK$i\_CTL"   0x00
766
            dbg_uart_wr "BRK$i\_STAT"  0xff
767
            dbg_uart_wr "BRK$i\_ADDR0" 0x0000
768
            dbg_uart_wr "BRK$i\_ADDR1" 0x0000
769
        }
770
    }
771
    return $num_brk_units
772
}
773
 
774
#=============================================================================#
775
# SetHWBreak(Type, Addr, Rd, Wr)                                              #
776
#-----------------------------------------------------------------------------#
777
# Description: Set data/instruction breakpoint on a given memory address.     #
778
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
779
#              Addr - Memory address of the data breakpoint.                  #
780
#              Rd   - Breakpoint on read access.                              #
781
#              Wr   - Breakpoint on write access.                             #
782
# Result     : 0 if error, 1 otherwise.                                       #
783
#=============================================================================#
784
proc SetHWBreak {Type Addr Rd Wr} {
785
    global hw_break
786
 
787
    # Compute the BRKx_CTL corresponding value
788
    set brk_ctl_ref [format "0x02%x" [expr 8*$Type+4+2*$Wr+$Rd]]
789
 
790
    # First look for utilized units with correct BRKx_CTL attributes
791
    for {set i 0} {$i<$hw_break(num)} {incr i} {
792
        if {[string eq [dbg_uart_rd "BRK$i\_CTL"] $brk_ctl_ref]} {
793
            # Look if there is an address free
794
            set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
795
            set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
796
            if {[string eq $brk_addr0 $brk_addr1]} {
797
                dbg_uart_wr "BRK$i\_ADDR1" $Addr
798
                return 1
799
            }
800
        }
801
    }
802
 
803
    # Then look for a free unit
804
    for {set i 0} {$i<$hw_break(num)} {incr i} {
805
        if {[string eq [dbg_uart_rd "BRK$i\_CTL"] 0x00]} {
806
            dbg_uart_wr "BRK$i\_ADDR0" $Addr
807
            dbg_uart_wr "BRK$i\_ADDR1" $Addr
808
            dbg_uart_wr "BRK$i\_CTL"   $brk_ctl_ref
809
            return 1
810
        }
811
    }
812
 
813
    return 0
814
}
815
 
816
#=============================================================================#
817
# ClearHWBreak(Type, Addr)                                                    #
818
#-----------------------------------------------------------------------------#
819
# Description: Clear the data/instruction breakpoint set on the provided      #
820
#              memory address.                                                #
821
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
822
#              Addr - Data address of the breakpoint to be cleared.           #
823
# Result     : 0 if error, 1 otherwise.                                       #
824
#=============================================================================#
825
proc ClearHWBreak {Type Addr} {
826
    global hw_break
827
 
828
    for {set i 0} {$i<$hw_break(num)} {incr i} {
829
        # Check if the unit works on Data or Instructions)
830
        set brk_ctl [dbg_uart_rd "BRK$i\_CTL"]
831
        if {[expr $brk_ctl & 0x08]==[expr 8*$Type]} {
832
 
833
            # Look for the matching address
834
            set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
835
            set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
836
 
837
            if {[string eq $brk_addr0 $brk_addr1] && [string eq $brk_addr0 $Addr]} {
838
                dbg_uart_wr "BRK$i\_CTL"   0x00
839
                dbg_uart_wr "BRK$i\_STAT"  0xff
840
                dbg_uart_wr "BRK$i\_ADDR0" 0x0000
841
                dbg_uart_wr "BRK$i\_ADDR1" 0x0000
842
                return 1
843
            }
844
            if {[string eq $brk_addr0 $Addr]} {
845
                dbg_uart_wr "BRK$i\_ADDR0" $brk_addr1
846
                return 1
847
            }
848
            if {[string eq $brk_addr1 $Addr]} {
849
                dbg_uart_wr "BRK$i\_ADDR1" $brk_addr0
850
                return 1
851
            }
852
        }
853
    }
854
    return 1
855
}
856
 
857
#=============================================================================#
858
# IsHalted ()                                                                 #
859
#-----------------------------------------------------------------------------#
860
# Description: Check if the CPU is currently stopped or not.                  #
861
# Arguments  : None.                                                          #
862
# Result     : 0 if CPU is running, 1 if stopped.                             #
863
#=============================================================================#
864
proc IsHalted {} {
865
 
866
    # Check current target status
867
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
868
    set halted       [expr 0x01 & $cpu_stat_val]
869
 
870
    return $halted
871
}
872
 
873
#=============================================================================#
874
# ClrStatus ()                                                                #
875
#-----------------------------------------------------------------------------#
876
# Description: Clear the status bit of the CPU_STAT register.                 #
877
# Arguments  : None.                                                          #
878
# Result     : 0 if error, 1 otherwise.                                       #
879
#=============================================================================#
880
proc ClrStatus {} {
881
 
882
    # Clear status
883
    dbg_uart_wr CPU_STAT  0xff
884
    dbg_uart_wr BRK0_STAT 0xff
885
    dbg_uart_wr BRK1_STAT 0xff
886
    dbg_uart_wr BRK2_STAT 0xff
887
    dbg_uart_wr BRK3_STAT 0xff
888
 
889
    return 1
890
}
891 110 olivier.gi
 
892
#=============================================================================#
893
# GetChipAlias ()                                                             #
894
#-----------------------------------------------------------------------------#
895
# Description: Parse the chip alias XML file an return the alias name.        #
896
# Arguments  : None.                                                          #
897
# Result     : Chip Alias.                                                    #
898
#=============================================================================#
899
proc GetChipAlias {} {
900
 
901
    global omsp_info
902
 
903
    # Set XML file name
904
    if {[info exists  ::env(OMSP_XML_FILE)]} {
905
        set xmlFile $::env(OMSP_XML_FILE)
906
    } else {
907
        set xmlFile [file normalize "$::scriptDir/../../omsp_alias.xml"]
908
    }
909
 
910
    # Read XML file
911
    if {[file exists $xmlFile]} {
912
        set fp [open $xmlFile r]
913
        set xmlData [read $fp]
914
        close $fp
915
    } else {
916
        puts "WARNING: the XML alias file was not found - $xmlFile"
917
        return ""
918
    }
919
 
920
    # Analyze XML file
921
    ::XML::Init $xmlData
922
    set wellFormed [::XML::IsWellFormed]
923
    if {$wellFormed ne ""} {
924
        puts "WARNING: the XML alias file is not well-formed - $xmlFile \n $wellFormed"
925
        return ""
926
    }
927
 
928
    #========================================================================#
929
    # Create list from XML file                                              #
930
    #========================================================================#
931
    set aliasList    ""
932
    set currentALIAS ""
933
    set currentTYPE  ""
934
    set currentTAG   ""
935
    while {1} {
936
        foreach {type val attr etype} [::XML::NextToken] break
937
        if {$type == "EOF"} break
938
 
939
        # Detect the start of a new alias description
940
        if {($type == "XML") & ($val == "omsp:alias") & ($etype == "START")} {
941
            set aliasName ""
942
            regexp {val=\"(.*)\"} $attr whole_match aliasName
943
            lappend aliasList $aliasName
944
            set currentALIAS $aliasName
945
        }
946
 
947
        # Detect start and end of the configuration field
948
        if {($type == "XML") & ($val == "omsp:configuration")} {
949
 
950
            if {($etype == "START")} {
951
                set currentTYPE  "config"
952
 
953
            } elseif {($etype == "END")} {
954
                set currentTYPE  ""
955
            }
956
        }
957
 
958
        # Detect start and end of the extra_info field
959
        if {($type == "XML") & ($val == "omsp:extra_info")} {
960
 
961
            if {($etype == "START")} {
962
                set currentTYPE  "extra_info"
963
                set idx 0
964
 
965
            } elseif {($etype == "END")} {
966
                set currentTYPE  ""
967
            }
968
        }
969
 
970
        # Detect the current TAG
971
        if {($type == "XML") & ($etype == "START")} {
972
            regsub {omsp:} $val {} val
973
            set currentTAG $val
974
        }
975
 
976
        if {($type == "TXT")} {
977
            if {$currentTYPE=="extra_info"} {
978
                set alias($currentALIAS,$currentTYPE,$idx,$currentTAG) $val
979
                incr idx
980
            } else {
981
                set alias($currentALIAS,$currentTYPE,$currentTAG) $val
982
            }
983
        }
984
    }
985
 
986
    #========================================================================#
987
    # Check if the current OMSP_INFO has an alias match                      #
988
    #========================================================================#
989
    foreach currentALIAS $aliasList {
990
        set aliasCONFIG [array names alias -glob "$currentALIAS,config,*"]
991
        set aliasEXTRA  [lsort -increasing [array names alias -glob "$currentALIAS,extra_info,*"]]
992
 
993
        #----------------------------------#
994
        # Is current alias matching ?      #
995
        #----------------------------------#
996
        set match       1
997
        set description ""
998
        foreach currentCONFIG $aliasCONFIG {
999
 
1000
            regsub "$currentALIAS,config," $currentCONFIG {} configName
1001
 
1002
            if {![string eq $omsp_info($configName) $alias($currentCONFIG)]} {
1003
                set match 0
1004
            }
1005
        }
1006
 
1007
        #----------------------------------#
1008
        # If matching, get the extra infos #
1009
        #----------------------------------#
1010
        if {$match} {
1011
 
1012
            set idx 0
1013
            foreach currentEXTRA $aliasEXTRA {
1014
                regsub "$currentALIAS,extra_info," $currentEXTRA {} extraName
1015
                set omsp_info(extra,$idx,$extraName) $alias($currentEXTRA)
1016
                incr idx
1017
            }
1018
            return $currentALIAS
1019
        }
1020
    }
1021
 
1022
    return ""
1023
}

powered by: WebSVN 2.1.0

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