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 110

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: 110 $
32
# $LastChangedBy: olivier.girard $
33
# $LastChangedDate: 2011-05-19 22:33:51 +0200 (Thu, 19 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
    set cpu_id_full [GetCPU_ID]
527
 
528 110 olivier.gi
    if {[string eq "0x00000000" $cpu_id_full] |
529
        ([string length $cpu_id_full]!=10)} {
530 74 olivier.gi
        set result 0
531
    } else {
532 2 olivier.gi
        set result 1
533
    }
534
    return $result
535
}
536
 
537
#=============================================================================#
538
# WriteReg (Addr,  Data)                                                      #
539
#-----------------------------------------------------------------------------#
540
# Description: Write a word to the the selected CPU register.                 #
541
# Arguments  : Addr - Target CPU Register number.                             #
542
#              Data - Data value to be written.                               #
543
# Result     : 0 if error, 1 otherwise.                                       #
544
#=============================================================================#
545
proc WriteReg {Addr Data} {
546
 
547
    dbg_uart_wr MEM_CNT  0x0000
548
 
549
    dbg_uart_wr MEM_ADDR $Addr
550
    dbg_uart_wr MEM_DATA $Data
551
    dbg_uart_wr MEM_CTL  0x0007
552
 
553
    return 1
554
}
555
 
556
#=============================================================================#
557
# WriteRegAll (DataArray)                                                     #
558
#-----------------------------------------------------------------------------#
559
# Description: Write all CPU registers.                                       #
560
# Arguments  : DataArray - Data values to be written.                         #
561
# Result     : 0 if error, 1 otherwise.                                       #
562
#=============================================================================#
563
proc WriteRegAll {DataArray} {
564
 
565
    dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
566
    dbg_uart_wr MEM_ADDR 0x0000
567
    dbg_uart_wr MEM_CTL  0x0007
568
 
569
    foreach data [split $DataArray] {
570
 
571
        # Format data
572
        set data [format %04x $data]
573
        regexp {(..)(..)} $data match data_msb data_lsb
574
 
575
        # Send data
576
        dbg_uart_tx "0x$data_lsb 0x$data_msb"
577
    }
578
 
579
    return 1
580
}
581
 
582
#=============================================================================#
583
# ReadReg (Addr)                                                              #
584
#-----------------------------------------------------------------------------#
585
# Description: Read the value from the selected CPU register.                 #
586
# Arguments  : Addr - Target CPU Register number.                             #
587
# Result     : Data value stored in the selected CPU register.                #
588
#=============================================================================#
589
proc ReadReg {Addr} {
590
 
591
    dbg_uart_wr MEM_CNT  0x0000
592
 
593
    dbg_uart_wr MEM_ADDR $Addr
594
    dbg_uart_wr MEM_CTL  0x0005
595
    set reg_val [dbg_uart_rd MEM_DATA]
596
 
597
    return $reg_val
598
}
599
 
600
#=============================================================================#
601
# ReadRegAll ()                                                               #
602
#-----------------------------------------------------------------------------#
603
# Description: Read all CPU registers.                                        #
604
# Arguments  : None.                                                          #
605
# Result     : Current values of all CPU registers.                           #
606
#=============================================================================#
607
proc ReadRegAll {} {
608
 
609
    dbg_uart_wr MEM_CNT  0x000f
610
    dbg_uart_wr MEM_ADDR 0x0000
611
    dbg_uart_wr MEM_CTL  0x0005
612
 
613
    set reg_val [dbg_uart_rx 0 32]
614
 
615
    return $reg_val
616
}
617
 
618
#=============================================================================#
619
# WriteMemQuick8 (StartAddr, DataArray)                                       #
620
#-----------------------------------------------------------------------------#
621
# Description: Writes an array of bytes into the target device memory (RAM,   #
622
#              ROM & Peripherals.                                             #
623
# Arguments  : StartAddr - Start address of destination memory.               #
624
#              DataArray - List of data to be written (in hexadecimal).       #
625
# Result     : 0 if error, 1 otherwise.                                       #
626
#=============================================================================#
627
proc WriteMemQuick8 {StartAddr DataArray} {
628
 
629
    if {[llength $DataArray]==1} {
630
        WriteMem 1 $StartAddr $DataArray
631
    } else {
632
 
633
        dbg_uart_wr MEM_CNT  [expr [llength $DataArray]-1]
634
        dbg_uart_wr MEM_ADDR $StartAddr
635
        dbg_uart_wr MEM_CTL  0x000b
636
 
637
        foreach data [split $DataArray] {
638
 
639
            # Format data
640
            set data [format %02x $data]
641
 
642
            # Send data
643
            dbg_uart_tx "0x$data"
644
        }
645
    }
646
    return 1
647
}
648
 
649
#=============================================================================#
650
# ReadMemQuick8 (StartAddr, Length)                                           #
651
#-----------------------------------------------------------------------------#
652
# Description: Reads an array of bytes from target memory.                    #
653
# Arguments  : StartAddr - Start address of target memory to be read.         #
654
#              Length    - Number of bytes to be read.                        #
655
# Result     : List of data values stored in the target memory.               #
656
#=============================================================================#
657
proc ReadMemQuick8 {StartAddr Length} {
658
 
659
    if {$Length==1} {
660
        set mem_val [ReadMem 1 $StartAddr]
661
    } else {
662
        dbg_uart_wr MEM_CNT  [expr $Length-1]
663
        dbg_uart_wr MEM_ADDR $StartAddr
664
        dbg_uart_wr MEM_CTL  0x0009
665
 
666
        set mem_val [dbg_uart_rx 1 [expr $Length]]
667
    }
668
 
669
    return $mem_val
670
}
671
 
672
#=============================================================================#
673
# StepCPU ()                                                                  #
674
#-----------------------------------------------------------------------------#
675
# Description: Performs a CPU incremental step.                               #
676
# Arguments  : None.                                                          #
677
# Result     : 0 if error, 1 otherwise.                                       #
678
#=============================================================================#
679
proc StepCPU {} {
680
 
681
    # Check if the device is halted. If not, stop it.
682
    set cpu_ctl_val [dbg_uart_rd CPU_CTL]
683
    set cpu_ctl_new [expr 0x04 | $cpu_ctl_val]
684
    dbg_uart_wr CPU_CTL $cpu_ctl_new
685
 
686
    return 1
687
}
688
 
689
#=============================================================================#
690
# EraseRAM ()                                                                 #
691
#-----------------------------------------------------------------------------#
692
# Description: Erase RAM.                                                     #
693
# Arguments  : None.                                                          #
694
# Result     : 0 if error, 1 otherwise.                                       #
695
#=============================================================================#
696
proc EraseRAM {} {
697
 
698
    set ram_size [lindex [GetCPU_ID_SIZE] 1]
699
 
700 87 olivier.gi
    if {$ram_size!=-1} {
701
        set DataArray ""
702
        for {set i 0} {$i<$ram_size} {incr i} {
703
            lappend DataArray 0x00
704
        }
705 2 olivier.gi
 
706 87 olivier.gi
        WriteMemQuick8 $0x0200 $DataArray
707 2 olivier.gi
 
708 87 olivier.gi
        return 1
709
    }
710
    return 0
711 2 olivier.gi
}
712
 
713
#=============================================================================#
714
# EraseROM ()                                                                 #
715
#-----------------------------------------------------------------------------#
716
# Description: Erase ROM.                                                     #
717
# Arguments  : None.                                                          #
718
# Result     : 0 if error, 1 otherwise.                                       #
719
#=============================================================================#
720
proc EraseROM {} {
721
 
722
    set rom_size  [lindex [GetCPU_ID_SIZE] 0]
723
    set rom_start [expr 0x10000-$rom_size]
724
 
725 96 olivier.gi
    if {$rom_size!=-1} {
726 87 olivier.gi
        set DataArray ""
727
        for {set i 0} {$i<$rom_size} {incr i} {
728
            lappend DataArray 0x00
729
        }
730 2 olivier.gi
 
731 87 olivier.gi
        WriteMemQuick8 $rom_start $DataArray
732 2 olivier.gi
 
733 87 olivier.gi
        return 1
734
    }
735
    return 0
736 2 olivier.gi
}
737
 
738
#=============================================================================#
739
# InitBreakUnits()                                                            #
740
#-----------------------------------------------------------------------------#
741
# Description: Initialize the hardware breakpoint units.                      #
742
# Arguments  : None.                                                          #
743
# Result     : Number of hardware breakpoint units.                           #
744
#=============================================================================#
745
proc InitBreakUnits {} {
746
 
747
    set num_brk_units 0
748
    for {set i 0} {$i<4} {incr i} {
749
 
750
        dbg_uart_wr "BRK$i\_ADDR0" 0x1234
751
        set new_val [dbg_uart_rd "BRK$i\_ADDR0"]
752
        if {$new_val=="0x1234"} {
753
            incr num_brk_units
754
            dbg_uart_wr "BRK$i\_CTL"   0x00
755
            dbg_uart_wr "BRK$i\_STAT"  0xff
756
            dbg_uart_wr "BRK$i\_ADDR0" 0x0000
757
            dbg_uart_wr "BRK$i\_ADDR1" 0x0000
758
        }
759
    }
760
    return $num_brk_units
761
}
762
 
763
#=============================================================================#
764
# SetHWBreak(Type, Addr, Rd, Wr)                                              #
765
#-----------------------------------------------------------------------------#
766
# Description: Set data/instruction breakpoint on a given memory address.     #
767
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
768
#              Addr - Memory address of the data breakpoint.                  #
769
#              Rd   - Breakpoint on read access.                              #
770
#              Wr   - Breakpoint on write access.                             #
771
# Result     : 0 if error, 1 otherwise.                                       #
772
#=============================================================================#
773
proc SetHWBreak {Type Addr Rd Wr} {
774
    global hw_break
775
 
776
    # Compute the BRKx_CTL corresponding value
777
    set brk_ctl_ref [format "0x02%x" [expr 8*$Type+4+2*$Wr+$Rd]]
778
 
779
    # First look for utilized units with correct BRKx_CTL attributes
780
    for {set i 0} {$i<$hw_break(num)} {incr i} {
781
        if {[string eq [dbg_uart_rd "BRK$i\_CTL"] $brk_ctl_ref]} {
782
            # Look if there is an address free
783
            set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
784
            set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
785
            if {[string eq $brk_addr0 $brk_addr1]} {
786
                dbg_uart_wr "BRK$i\_ADDR1" $Addr
787
                return 1
788
            }
789
        }
790
    }
791
 
792
    # Then look for a free unit
793
    for {set i 0} {$i<$hw_break(num)} {incr i} {
794
        if {[string eq [dbg_uart_rd "BRK$i\_CTL"] 0x00]} {
795
            dbg_uart_wr "BRK$i\_ADDR0" $Addr
796
            dbg_uart_wr "BRK$i\_ADDR1" $Addr
797
            dbg_uart_wr "BRK$i\_CTL"   $brk_ctl_ref
798
            return 1
799
        }
800
    }
801
 
802
    return 0
803
}
804
 
805
#=============================================================================#
806
# ClearHWBreak(Type, Addr)                                                    #
807
#-----------------------------------------------------------------------------#
808
# Description: Clear the data/instruction breakpoint set on the provided      #
809
#              memory address.                                                #
810
# Arguments  : Type - 1 for instruction break, 0 for data break.              #
811
#              Addr - Data address of the breakpoint to be cleared.           #
812
# Result     : 0 if error, 1 otherwise.                                       #
813
#=============================================================================#
814
proc ClearHWBreak {Type Addr} {
815
    global hw_break
816
 
817
    for {set i 0} {$i<$hw_break(num)} {incr i} {
818
        # Check if the unit works on Data or Instructions)
819
        set brk_ctl [dbg_uart_rd "BRK$i\_CTL"]
820
        if {[expr $brk_ctl & 0x08]==[expr 8*$Type]} {
821
 
822
            # Look for the matching address
823
            set brk_addr0 [dbg_uart_rd "BRK$i\_ADDR0"]
824
            set brk_addr1 [dbg_uart_rd "BRK$i\_ADDR1"]
825
 
826
            if {[string eq $brk_addr0 $brk_addr1] && [string eq $brk_addr0 $Addr]} {
827
                dbg_uart_wr "BRK$i\_CTL"   0x00
828
                dbg_uart_wr "BRK$i\_STAT"  0xff
829
                dbg_uart_wr "BRK$i\_ADDR0" 0x0000
830
                dbg_uart_wr "BRK$i\_ADDR1" 0x0000
831
                return 1
832
            }
833
            if {[string eq $brk_addr0 $Addr]} {
834
                dbg_uart_wr "BRK$i\_ADDR0" $brk_addr1
835
                return 1
836
            }
837
            if {[string eq $brk_addr1 $Addr]} {
838
                dbg_uart_wr "BRK$i\_ADDR1" $brk_addr0
839
                return 1
840
            }
841
        }
842
    }
843
    return 1
844
}
845
 
846
#=============================================================================#
847
# IsHalted ()                                                                 #
848
#-----------------------------------------------------------------------------#
849
# Description: Check if the CPU is currently stopped or not.                  #
850
# Arguments  : None.                                                          #
851
# Result     : 0 if CPU is running, 1 if stopped.                             #
852
#=============================================================================#
853
proc IsHalted {} {
854
 
855
    # Check current target status
856
    set cpu_stat_val [dbg_uart_rd CPU_STAT]
857
    set halted       [expr 0x01 & $cpu_stat_val]
858
 
859
    return $halted
860
}
861
 
862
#=============================================================================#
863
# ClrStatus ()                                                                #
864
#-----------------------------------------------------------------------------#
865
# Description: Clear the status bit of the CPU_STAT register.                 #
866
# Arguments  : None.                                                          #
867
# Result     : 0 if error, 1 otherwise.                                       #
868
#=============================================================================#
869
proc ClrStatus {} {
870
 
871
    # Clear status
872
    dbg_uart_wr CPU_STAT  0xff
873
    dbg_uart_wr BRK0_STAT 0xff
874
    dbg_uart_wr BRK1_STAT 0xff
875
    dbg_uart_wr BRK2_STAT 0xff
876
    dbg_uart_wr BRK3_STAT 0xff
877
 
878
    return 1
879
}
880 110 olivier.gi
 
881
#=============================================================================#
882
# GetChipAlias ()                                                             #
883
#-----------------------------------------------------------------------------#
884
# Description: Parse the chip alias XML file an return the alias name.        #
885
# Arguments  : None.                                                          #
886
# Result     : Chip Alias.                                                    #
887
#=============================================================================#
888
proc GetChipAlias {} {
889
 
890
    global omsp_info
891
 
892
    # Set XML file name
893
    if {[info exists  ::env(OMSP_XML_FILE)]} {
894
        set xmlFile $::env(OMSP_XML_FILE)
895
    } else {
896
        set xmlFile [file normalize "$::scriptDir/../../omsp_alias.xml"]
897
    }
898
 
899
    # Read XML file
900
    if {[file exists $xmlFile]} {
901
        set fp [open $xmlFile r]
902
        set xmlData [read $fp]
903
        close $fp
904
    } else {
905
        puts "WARNING: the XML alias file was not found - $xmlFile"
906
        return ""
907
    }
908
 
909
    # Analyze XML file
910
    ::XML::Init $xmlData
911
    set wellFormed [::XML::IsWellFormed]
912
    if {$wellFormed ne ""} {
913
        puts "WARNING: the XML alias file is not well-formed - $xmlFile \n $wellFormed"
914
        return ""
915
    }
916
 
917
    #========================================================================#
918
    # Create list from XML file                                              #
919
    #========================================================================#
920
    set aliasList    ""
921
    set currentALIAS ""
922
    set currentTYPE  ""
923
    set currentTAG   ""
924
    while {1} {
925
        foreach {type val attr etype} [::XML::NextToken] break
926
        if {$type == "EOF"} break
927
 
928
        # Detect the start of a new alias description
929
        if {($type == "XML") & ($val == "omsp:alias") & ($etype == "START")} {
930
            set aliasName ""
931
            regexp {val=\"(.*)\"} $attr whole_match aliasName
932
            lappend aliasList $aliasName
933
            set currentALIAS $aliasName
934
        }
935
 
936
        # Detect start and end of the configuration field
937
        if {($type == "XML") & ($val == "omsp:configuration")} {
938
 
939
            if {($etype == "START")} {
940
                set currentTYPE  "config"
941
 
942
            } elseif {($etype == "END")} {
943
                set currentTYPE  ""
944
            }
945
        }
946
 
947
        # Detect start and end of the extra_info field
948
        if {($type == "XML") & ($val == "omsp:extra_info")} {
949
 
950
            if {($etype == "START")} {
951
                set currentTYPE  "extra_info"
952
                set idx 0
953
 
954
            } elseif {($etype == "END")} {
955
                set currentTYPE  ""
956
            }
957
        }
958
 
959
        # Detect the current TAG
960
        if {($type == "XML") & ($etype == "START")} {
961
            regsub {omsp:} $val {} val
962
            set currentTAG $val
963
        }
964
 
965
        if {($type == "TXT")} {
966
            if {$currentTYPE=="extra_info"} {
967
                set alias($currentALIAS,$currentTYPE,$idx,$currentTAG) $val
968
                incr idx
969
            } else {
970
                set alias($currentALIAS,$currentTYPE,$currentTAG) $val
971
            }
972
        }
973
    }
974
 
975
    #========================================================================#
976
    # Check if the current OMSP_INFO has an alias match                      #
977
    #========================================================================#
978
    foreach currentALIAS $aliasList {
979
        set aliasCONFIG [array names alias -glob "$currentALIAS,config,*"]
980
        set aliasEXTRA  [lsort -increasing [array names alias -glob "$currentALIAS,extra_info,*"]]
981
 
982
        #----------------------------------#
983
        # Is current alias matching ?      #
984
        #----------------------------------#
985
        set match       1
986
        set description ""
987
        foreach currentCONFIG $aliasCONFIG {
988
 
989
            regsub "$currentALIAS,config," $currentCONFIG {} configName
990
 
991
            if {![string eq $omsp_info($configName) $alias($currentCONFIG)]} {
992
                set match 0
993
            }
994
        }
995
 
996
        #----------------------------------#
997
        # If matching, get the extra infos #
998
        #----------------------------------#
999
        if {$match} {
1000
 
1001
            set idx 0
1002
            foreach currentEXTRA $aliasEXTRA {
1003
                regsub "$currentALIAS,extra_info," $currentEXTRA {} extraName
1004
                set omsp_info(extra,$idx,$extraName) $alias($currentEXTRA)
1005
                incr idx
1006
            }
1007
            return $currentALIAS
1008
        }
1009
    }
1010
 
1011
    return ""
1012
}

powered by: WebSVN 2.1.0

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