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 158

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

Line No. Rev Author Line
1 158 olivier.gi
#-----------------------------------------------------------------------------------------------------------
2 2 olivier.gi
# 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 158 olivier.gi
#-----------------------------------------------------------------------------------------------------------
24 2 olivier.gi
# 
25
# File Name:   dbg_functions.tcl
26
#
27 15 olivier.gi
# Author(s):
28
#             - Olivier Girard,    olgirard@gmail.com
29
#
30 158 olivier.gi
#-----------------------------------------------------------------------------------------------------------
31 15 olivier.gi
# $Rev: 158 $
32
# $LastChangedBy: olivier.girard $
33
# $LastChangedDate: 2012-10-15 23:49:09 +0200 (Mon, 15 Oct 2012) $
34 158 olivier.gi
#-----------------------------------------------------------------------------------------------------------
35 15 olivier.gi
#
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 158 olivier.gi
#               - GetDevice       (CpuNr)
44
#               - ReleaseDevice   (CpuNr, Addr)
45
#               - ExecutePOR      (CpuNr)
46
#               - SetPC           (CpuNr, Addr)
47
#               - HaltCPU         (CpuNr)
48
#               - ReleaseCPU      (CpuNr)
49
#               - WriteMem        (CpuNr, Format,    Addr,     Data)
50
#               - WriteMemQuick   (CpuNr, StartAddr, DataList)
51
#               - ReadMem         (CpuNr, Format,    Addr)
52
#               - ReadMemQuick    (CpuNr, StartAddr, Length)
53
#               - VerifyMem       (CpuNr, StartAddr, DataList)
54 2 olivier.gi
#
55
#
56
#       The following have been added:
57
#
58 158 olivier.gi
#               - ExecutePOR_Halt (CpuNr)
59
#               - GetCPU_ID       (CpuNr)
60
#               - GetCPU_ID_SIZE  (CpuNr)
61
#               - VerifyCPU_ID    (CpuNr)
62
#               - WriteReg        (CpuNr, Addr,      Data)
63
#               - WriteRegAll     (CpuNr, DataList)
64
#               - ReadReg         (CpuNr, Addr)
65
#               - ReadRegAll      (CpuNr)
66
#               - WriteMemQuick8  (CpuNr, StartAddr, DataList)
67
#               - ReadMemQuick8   (CpuNr, StartAddr, Length)
68
#               - StepCPU         (CpuNr)
69
#               - EraseRAM        (CpuNr)
70
#               - EraseROM        (CpuNr)
71
#               - InitBreakUnits  (CpuNr)
72
#               - SetHWBreak      (CpuNr, Type, Addr,      Rd,       Wr)
73
#               - ClearHWBreak    (CpuNr, Type, Addr)
74
#               - IsHalted        (CpuNr)
75
#               - ClrStatus       (CpuNr)
76
#               - GetChipAlias    (CpuNr)
77
#               - GetAllowedSpeeds()
78 2 olivier.gi
# 
79 158 olivier.gi
#-----------------------------------------------------------------------------------------------------------
80 2 olivier.gi
 
81 158 olivier.gi
#==========================================================================================================#
82
# GLOBAL VARIABLES: OMSP_CONF
83
#-----------------------------------------------------------------------------------------------------------
84
#
85
# The global conifugration array variable is meant to be initialized by the higher level
86
# programs prior the "GetDevice" call.
87
#
88
#  omsp_conf(interface)                     ->  Debug interface type: "uart" or "i2c_usb-iss"
89
#  omsp_conf(device)                        ->  Serial port device (i.e. /dev/ttyS0 or COM2:)
90
#  omsp_conf(baudrate)                      ->  UART communication speed
91
#  omsp_conf(<cpu_nr>,cpuaddr)              ->  Address of the core <cpu_nr> (i.e. I2C device address)
92
#
93
#==========================================================================================================#
94
global omsp_conf
95
 
96
# Initialize to default values
97
set omsp_conf(interface)       uart_generic
98
set omsp_conf(device)          /dev/ttyUSB0
99
set omsp_conf(baudrate)        9600
100
for {set i 0} {$i<128} {incr i} {
101
    set omsp_conf($i,cpuaddr) 0
102
}
103
 
104
 
105
#==========================================================================================================#
106
# GLOBAL VARIABLES: OMSP_INFO
107
#-----------------------------------------------------------------------------------------------------------
108
#
109
# This array variable is updated by the "GetDevice" procedure when the connection is built
110
# with the oMSP core.
111
# The array is structured as following:
112
#
113
#  omsp_info(connected)                     ->  Main Physical connection is active
114
#  omsp_info(<cpu_nr>,connected)            ->  Connection to CPU <cpu_nr> is active
115
#  omsp_info(<cpu_nr>,hw_break)             ->  Number of hardware breakpoints
116
#  omsp_info(<cpu_nr>,cpu_ver)              ->  From CPU_ID  : CPU Version
117
#  omsp_info(<cpu_nr>,user_ver)             ->  From CPU_ID  : User version
118
#  omsp_info(<cpu_nr>,per_size)             ->  From CPU_ID  : Peripheral address size 
119
#  omsp_info(<cpu_nr>,dmem_size)            ->  From CPU_ID  : Data memory size 
120
#  omsp_info(<cpu_nr>,pmem_size)            ->  From CPU_ID  : Program memory size
121
#  omsp_info(<cpu_nr>,mpy)                  ->  From CPU_ID  : Hardware multiplier
122
#  omsp_info(<cpu_nr>,asic)                 ->  From CPU_ID  : ASIC/FPGA version
123
#  omsp_info(<cpu_nr>,inst_nr)              ->  From CPU_NR  : current oMSP instance number
124
#  omsp_info(<cpu_nr>,total_nr)             ->  From CPU_NR  : totalnumber of oMSP instances-1
125
#  omsp_info(<cpu_nr>,alias)                ->  From XML File: Alias name
126
#  omsp_info(<cpu_nr>,extra,0,Description)  ->  From XML File: Optional Description
127
#  omsp_info(<cpu_nr>,extra,1,Contact)      ->  From XML File: Contact person
128
#  omsp_info(<cpu_nr>,extra,2,Email)        ->  From XML File: Email of contact person
129
#  omsp_info(<cpu_nr>,extra,3,URL)          ->  From XML File: URL of the project
130
#  omsp_info(<cpu_nr>,extra,4,per_size)     ->  From XML File: Custom Peripheral address size 
131
#  omsp_info(<cpu_nr>,extra,5,dmem_size)    ->  From XML File: Custom Data memory size 
132
#  omsp_info(<cpu_nr>,extra,6,pmem_size)    ->  From XML File: Custom Program memory size
133
#  omsp_info(<cpu_nr>,extra,?,????)         ->  From XML File: ... any extra stuff
134
#
135
#==========================================================================================================#
136 110 olivier.gi
global omsp_info
137 158 olivier.gi
 
138
# Initialize connection status 
139 110 olivier.gi
set    omsp_info(connected) 0
140 2 olivier.gi
 
141 158 olivier.gi
# Support up to 128 multicore implementations
142
for {set i 0} {$i<128} {incr i} {
143
    set  omsp_info($i,connected) 0
144
}
145
 
146
 
147
#==========================================================================================================#
148 2 olivier.gi
# SOURCE REQUIRED LIBRARIES
149 158 olivier.gi
#==========================================================================================================#
150
 
151 110 olivier.gi
set     scriptDir [file dirname [info script]]
152
source $scriptDir/xml.tcl
153 158 olivier.gi
source $scriptDir/dbg_uart_generic.tcl
154
source $scriptDir/dbg_uart_usb-iss.tcl
155
source $scriptDir/dbg_i2c_usb-iss.tcl
156 2 olivier.gi
 
157 110 olivier.gi
 
158 158 olivier.gi
#==========================================================================================================#
159
# DEBUG PROCEDURES
160
#==========================================================================================================#
161
 
162 2 olivier.gi
#=============================================================================#
163 158 olivier.gi
# GetDevice (CpuNr)                                                           #
164 2 olivier.gi
#-----------------------------------------------------------------------------#
165 158 olivier.gi
# Description: Takes the target MSP430 device under UART/I2C control.         #
166
#              Enable the auto-freeze feature of timers when in the CPU is    #
167
#              stopped. This prevents an automatic watchdog reset condition.  #
168
#              Enables software breakpoints.                                  #
169
# Arguments  : CpuNr - oMSP device number to connect to.                      #
170
# Result     : 0 if error, 1 otherwise.                                       #
171
#=============================================================================#
172
proc GetDevice {CpuNr} {
173
 
174
    global omsp_conf
175
    global omsp_info
176
 
177
    # Copy global variable to local for code readability
178
    set if       $omsp_conf(interface)
179
    set device   $omsp_conf(device)
180
    set baudrate $omsp_conf(baudrate)
181
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
182
 
183
 
184
    # Open Physical connection (if not already open)
185
    if {$omsp_info(connected)==0} {
186
 
187
        if {![${if}::dbg_open $device $baudrate]} {
188
            return 0
189
        }
190
 
191
        # Physical connection is active
192
        set omsp_info(connected) 1
193
    }
194
 
195
 
196
    # Open Connection with the CPU
197
    if {$omsp_info($CpuNr,connected)==0} {
198
 
199
        # Connect to the CPU
200
        if {![${if}::dbg_connect $cpuaddr]} {
201
            return 0
202
        }
203
 
204
        # Make sure the CPU_ID is correct
205
        if {![VerifyCPU_ID $CpuNr]} {
206
            return 0
207
        }
208
 
209
        # Enable auto-freeze & software breakpoints
210
        ${if}::dbg_wr $cpuaddr CPU_CTL 0x0018
211
 
212
        # Initialize the omsp_info global variable
213
        GetCPU_ID $CpuNr
214
 
215
        # Get number of hardware breakpoints
216
        set omsp_info($CpuNr,hw_break)  [InitBreakUnits $CpuNr]
217
 
218
        # Connection with the CPU is now active
219
        set omsp_info($CpuNr,connected) 1
220
    }
221
 
222
    return 1
223
}
224
 
225
#=============================================================================#
226
# ReleaseDevice (CpuNr, Addr)                                                 #
227
#-----------------------------------------------------------------------------#
228
# Description: Releases the target device from UART/I2C control; CPU starts   #
229
#              execution at the specified PC address.                         #
230
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
231
#              Addr  - 0xfffe: perform reset;                                 #
232
#                              address at reset vector loaded into PC;        #
233
#                      otherwise address specified by Addr loaded into PC.    #
234
# Result     : 0 if error, 1 otherwise.                                       #
235
#=============================================================================#
236
proc ReleaseDevice {CpuNr Addr} {
237
 
238
    if {[expr $Addr]==[expr 0xfffe]} {
239
        set result 1
240
        set result [expr $result+[ExecutePOR $CpuNr]]
241
        set result [expr $result+[ReleaseCPU $CpuNr]]
242
    } else {
243
        set result 0
244
        set result [expr $result+[HaltCPU    $CpuNr]]
245
        set result [expr $result+[SetPC      $CpuNr $Addr]]
246
        set result [expr $result+[ReleaseCPU $CpuNr]]
247
    }
248
 
249
    if {$result==3} {
250
        return 1
251
    } else {
252
        return 0
253
    }
254
}
255
 
256
#=============================================================================#
257
# ExecutePOR (CpuNr)                                                          #
258
#-----------------------------------------------------------------------------#
259 2 olivier.gi
# Description: Executes a power-up clear (PUC) command.                       #
260 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
261 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
262
#=============================================================================#
263 158 olivier.gi
proc ExecutePOR {CpuNr} {
264 2 olivier.gi
 
265 158 olivier.gi
    global omsp_conf
266
 
267
    # Copy global variable to local for code readability
268
    set if       $omsp_conf(interface)
269
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
270
 
271 2 olivier.gi
    # Set PUC
272 158 olivier.gi
    set cpu_ctl_org [${if}::dbg_rd $cpuaddr CPU_CTL]
273 2 olivier.gi
    set cpu_ctl_new [expr 0x40 | $cpu_ctl_org]
274 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_new
275 2 olivier.gi
 
276
    # Remove PUC, clear break after reset
277
    set cpu_ctl_org [expr 0x5f & $cpu_ctl_org]
278 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_org
279 2 olivier.gi
 
280
    # Check status: make sure a PUC occured
281 158 olivier.gi
    set cpu_stat_val [${if}::dbg_rd $cpuaddr CPU_STAT]
282 2 olivier.gi
    set puc_pnd      [expr 0x04 & $cpu_stat_val]
283
    if {![string eq $puc_pnd 4]} {
284 158 olivier.gi
        return 0
285 2 olivier.gi
    }
286
 
287
    # Clear PUC pending flag
288 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_STAT 0x04
289 2 olivier.gi
 
290 110 olivier.gi
    return 1
291 2 olivier.gi
}
292
 
293
#=============================================================================#
294 158 olivier.gi
# SetPC (CpuNr, Addr)                                                         #
295 2 olivier.gi
#-----------------------------------------------------------------------------#
296
# Description: Loads the target device CPU's program counter (PC) with the    #
297
#              desired 16-bit address.                                        #
298 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
299
#              Addr  - Desired 16-bit PC value (in hexadecimal).              #
300 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
301
#=============================================================================#
302 158 olivier.gi
proc SetPC {CpuNr Addr} {
303 2 olivier.gi
 
304 158 olivier.gi
    return [WriteReg $CpuNr 0 $Addr]
305 2 olivier.gi
}
306
 
307
#=============================================================================#
308 158 olivier.gi
# HaltCPU (CpuNr)                                                             #
309 2 olivier.gi
#-----------------------------------------------------------------------------#
310
# Description: Sends the target CPU into a controlled, stopped state.         #
311 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
312 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
313
#=============================================================================#
314 158 olivier.gi
proc HaltCPU {CpuNr} {
315 2 olivier.gi
 
316 158 olivier.gi
    global omsp_conf
317 2 olivier.gi
 
318 158 olivier.gi
    # Copy global variable to local for code readability
319
    set if       $omsp_conf(interface)
320
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
321
 
322 2 olivier.gi
    # Stop CPU
323 158 olivier.gi
    set cpu_ctl_org [${if}::dbg_rd $cpuaddr CPU_CTL]
324 2 olivier.gi
    set cpu_ctl_new [expr 0x01 | $cpu_ctl_org]
325 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_new
326 2 olivier.gi
 
327
    # Check status: make sure the CPU halted
328 158 olivier.gi
    set cpu_stat_val [${if}::dbg_rd $cpuaddr CPU_STAT]
329 2 olivier.gi
    set halted       [expr 0x01 & $cpu_stat_val]
330
    if {![string eq $halted 1]} {
331 158 olivier.gi
        return 0
332 2 olivier.gi
    }
333
 
334 158 olivier.gi
    return 1
335 2 olivier.gi
}
336
 
337
#=============================================================================#
338 158 olivier.gi
# ReleaseCPU (CpuNr)                                                          #
339 2 olivier.gi
#-----------------------------------------------------------------------------#
340
# Description: Releases the target device's CPU from the controlled, stopped  #
341
#              state. (Does not release the target device from debug control.)#
342 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
343 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
344
#=============================================================================#
345 158 olivier.gi
proc ReleaseCPU {CpuNr} {
346 2 olivier.gi
 
347 158 olivier.gi
    global omsp_conf
348 2 olivier.gi
 
349 158 olivier.gi
    # Copy global variable to local for code readability
350
    set if       $omsp_conf(interface)
351
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
352
 
353 2 olivier.gi
    # Start CPU
354 158 olivier.gi
    set cpu_ctl_org [${if}::dbg_rd $cpuaddr CPU_CTL]
355 2 olivier.gi
    set cpu_ctl_new [expr 0x02 | $cpu_ctl_org]
356 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_new
357 2 olivier.gi
 
358
    # Check status: make sure the CPU runs
359 158 olivier.gi
    set cpu_stat_val [${if}::dbg_rd $cpuaddr CPU_STAT]
360 2 olivier.gi
    set halted       [expr 0x01 & $cpu_stat_val]
361
    if {![string eq $halted 0]} {
362 158 olivier.gi
        return 0
363 2 olivier.gi
    }
364
 
365 124 olivier.gi
    return 1
366 2 olivier.gi
}
367
 
368
#=============================================================================#
369 158 olivier.gi
# WriteMem (CpuNr, Format, Addr, Data)                                        #
370 2 olivier.gi
#-----------------------------------------------------------------------------#
371
# Description: Write a single byte or word to a given address (RAM, ROM &     #
372
#              Peripherals.                                                   #
373 158 olivier.gi
# Arguments  : CpuNr  - oMSP device number to be addressed.                   #
374
#              Format - 0 to write a word, 1 to write a byte.                 #
375 2 olivier.gi
#              Addr   - Destination address for data to be written.           #
376
#              Data   - Data value to be written.                             #
377
# Result     : 0 if error, 1 otherwise.                                       #
378
#=============================================================================#
379 158 olivier.gi
proc WriteMem {CpuNr Format Addr Data} {
380 2 olivier.gi
 
381 158 olivier.gi
    global omsp_conf
382 2 olivier.gi
 
383 158 olivier.gi
    # Copy global variable to local for code readability
384
    set if       $omsp_conf(interface)
385
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
386
 
387
    # Configure memory transfer
388
    #${if}::dbg_wr $cpuaddr MEM_CNT  0x0000
389
    ${if}::dbg_wr $cpuaddr MEM_ADDR $Addr
390
    ${if}::dbg_wr $cpuaddr MEM_DATA $Data
391
 
392
    # Trigger transfer
393 2 olivier.gi
    if {$Format==0} {
394 158 olivier.gi
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0003
395 2 olivier.gi
    } else {
396 158 olivier.gi
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x000b
397 2 olivier.gi
    }
398
 
399
    return 1
400
}
401
 
402
#=============================================================================#
403 158 olivier.gi
# WriteMemQuick (CpuNr, StartAddr, DataList)                                  #
404 2 olivier.gi
#-----------------------------------------------------------------------------#
405 158 olivier.gi
# Description: Writes a list of words into the target device memory (RAM,     #
406 2 olivier.gi
#              ROM & Peripherals.                                             #
407 158 olivier.gi
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
408
#              StartAddr - Start address of destination memory.               #
409
#              DataList  - List of data to be written (in hexadecimal).       #
410 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
411
#=============================================================================#
412 158 olivier.gi
proc WriteMemQuick {CpuNr StartAddr DataList} {
413 2 olivier.gi
 
414 158 olivier.gi
    global omsp_conf
415
 
416
    # Copy global variable to local for code readability
417
    set if       $omsp_conf(interface)
418
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
419
 
420
    # Single data transfer
421
    if {[llength $DataList]==1} {
422
        WriteMem $CpuNr 0 $StartAddr $DataList
423
 
424
    # Burst data transfer
425 2 olivier.gi
    } else {
426
 
427 158 olivier.gi
        # Configure & trigger memory transfer
428
        ${if}::dbg_wr $cpuaddr MEM_CNT  [expr [llength $DataList]-1]
429
        ${if}::dbg_wr $cpuaddr MEM_ADDR $StartAddr
430
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0003
431 2 olivier.gi
 
432 158 olivier.gi
        # Send data list
433
        ${if}::dbg_burst_tx $cpuaddr 0 $DataList
434 2 olivier.gi
 
435
    }
436
    return 1
437
}
438
 
439
#=============================================================================#
440 158 olivier.gi
# ReadMem (CpuNr, Format, Addr)                                               #
441 2 olivier.gi
#-----------------------------------------------------------------------------#
442
# Description: Read one byte or word from a specified target memory address.  #
443 158 olivier.gi
# Arguments  : CpuNr  - oMSP device number to be addressed.                   #
444
#              Format - 0 to read a word, 1 to read a byte.                   #
445 2 olivier.gi
#              Addr   - Target address for data to be read.                   #
446
# Result     : Data value stored in the target address memory location.       #
447
#=============================================================================#
448 158 olivier.gi
proc ReadMem {CpuNr Format Addr} {
449 2 olivier.gi
 
450 158 olivier.gi
    global omsp_conf
451 2 olivier.gi
 
452 158 olivier.gi
    # Copy global variable to local for code readability
453
    set if       $omsp_conf(interface)
454
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
455
 
456
    # Single data transfer
457
    #${if}::dbg_wr $cpuaddr MEM_CNT  0x0000
458
    ${if}::dbg_wr $cpuaddr MEM_ADDR $Addr
459
 
460
    # Trigger transfer
461 2 olivier.gi
    if {$Format==0} {
462 158 olivier.gi
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0001
463
        set mem_val [${if}::dbg_rd $cpuaddr MEM_DATA]
464 2 olivier.gi
    } else {
465 158 olivier.gi
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0009
466
        set mem_val [${if}::dbg_rd $cpuaddr MEM_DATA]
467
        set mem_val [format "0x%02x" $mem_val]
468 2 olivier.gi
    }
469
 
470
    return $mem_val
471
}
472
 
473
#=============================================================================#
474 158 olivier.gi
# ReadMemQuick (CpuNr, StartAddr, Length)                                     #
475 2 olivier.gi
#-----------------------------------------------------------------------------#
476 158 olivier.gi
# Description: Reads a list of words from target memory.                      #
477
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
478
#              StartAddr - Start address of target memory to be read.         #
479
#              Length    - Number of words to be read.                        #
480 2 olivier.gi
# Result     : List of data values stored in the target memory.               #
481
#=============================================================================#
482 158 olivier.gi
proc ReadMemQuick {CpuNr StartAddr Length} {
483 2 olivier.gi
 
484 158 olivier.gi
    global omsp_conf
485
 
486
    # Copy global variable to local for code readability
487
    set if       $omsp_conf(interface)
488
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
489
 
490
    # Single data transfer
491 2 olivier.gi
    if {$Length==1} {
492 158 olivier.gi
        set mem_val [ReadMem $CpuNr 0 $StartAddr]
493
 
494
    # Burst data transfer
495 2 olivier.gi
    } else {
496
 
497 158 olivier.gi
        # Configure & trigger memory transfer
498
        ${if}::dbg_wr $cpuaddr MEM_CNT  [expr $Length-1]
499
        ${if}::dbg_wr $cpuaddr MEM_ADDR $StartAddr
500
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0001
501 2 olivier.gi
 
502 158 olivier.gi
        # Receive Data list
503
        set mem_val [${if}::dbg_burst_rx $cpuaddr 0 [expr $Length*2]]
504 2 olivier.gi
    }
505
    return $mem_val
506
}
507
 
508
#=============================================================================#
509 158 olivier.gi
# VerifyMem (CpuNr, StartAddr, DataList)                                      #
510 2 olivier.gi
#-----------------------------------------------------------------------------#
511
# Description: Performs a program verification over the given memory range.   #
512 158 olivier.gi
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
513
#              StartAddr - Start address of the memory to be verified.        #
514
#              DataList  - List of reference data (in hexadecimal).           #
515 2 olivier.gi
# Result     : 0 if error, 1 if verification was successful.                  #
516
#=============================================================================#
517 158 olivier.gi
proc VerifyMem {CpuNr StartAddr DataList {DumpOnError 0}} {
518 2 olivier.gi
 
519 158 olivier.gi
    # Read memory content
520
    set mem_val [ReadMemQuick $CpuNr $StartAddr [llength $DataList]]
521 2 olivier.gi
 
522 158 olivier.gi
    # Compare memory contents
523
    set    return_val [string equal $DataList $mem_val]
524 2 olivier.gi
 
525 158 olivier.gi
    # Dump memory content in files for comparison
526
    if {($return_val==0) && ($DumpOnError==1)} {
527 74 olivier.gi
 
528 158 olivier.gi
        # Delete old files
529
        file delete -force openmsp430-verifymem-debug-expected.mem
530
        file delete -force openmsp430-verifymem-debug-dumped.mem
531
 
532
        # Write expected memory content
533
        set fileId [open openmsp430-verifymem-debug-expected.mem "w"]
534
        foreach hexCode $DataList {
535
            puts $fileId $hexCode
536
        }
537
        close $fileId
538
 
539
        # Dump read memory content
540
        set fileId [open openmsp430-verifymem-debug-dumped.mem "w"]
541
        foreach hexCode $mem_val {
542
            puts $fileId $hexCode
543
        }
544
        close $fileId
545 77 olivier.gi
    }
546 74 olivier.gi
 
547
    return $return_val
548 2 olivier.gi
}
549
 
550
#=============================================================================#
551 158 olivier.gi
# ExecutePOR_Halt (CpuNr)                                                     #
552 2 olivier.gi
#-----------------------------------------------------------------------------#
553
# Description: Same as ExecutePOR with the difference that the CPU            #
554
#              automatically goes in Halt mode after reset.                   #
555 158 olivier.gi
# Arguments  : CpuNr  - oMSP device number to be addressed.                   #
556 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
557
#=============================================================================#
558 158 olivier.gi
proc ExecutePOR_Halt {CpuNr} {
559 2 olivier.gi
 
560 158 olivier.gi
    global omsp_conf
561 2 olivier.gi
 
562 158 olivier.gi
    # Copy global variable to local for code readability
563
    set if       $omsp_conf(interface)
564
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
565
 
566 2 olivier.gi
    # Perform PUC
567 158 olivier.gi
    set cpu_ctl_org [${if}::dbg_rd $cpuaddr CPU_CTL]
568 2 olivier.gi
    set cpu_ctl_new [expr 0x60 | $cpu_ctl_org]
569 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_new
570
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_org
571 2 olivier.gi
 
572
    # Check status: make sure a PUC occured and that the CPU is halted
573 158 olivier.gi
    set cpu_stat_val [${if}::dbg_rd $cpuaddr CPU_STAT]
574 2 olivier.gi
    set puc_pnd      [expr 0x05 & $cpu_stat_val]
575
    if {![string eq $puc_pnd 5]} {
576 158 olivier.gi
        return 0
577 2 olivier.gi
    }
578
 
579
    # Clear PUC pending flag
580 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_STAT 0x04
581 2 olivier.gi
 
582 158 olivier.gi
    return 1
583 2 olivier.gi
}
584
 
585
#=============================================================================#
586 158 olivier.gi
# GetCPU_ID (CpuNr)                                                           #
587 2 olivier.gi
#-----------------------------------------------------------------------------#
588 110 olivier.gi
# Description: This function reads the CPU_ID from the target device, update  #
589
#              the omsp_info global variable and return the raw CPU_ID value. #
590 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
591 2 olivier.gi
# Result     : Return CPU_ID.                                                 #
592
#=============================================================================#
593 158 olivier.gi
proc GetCPU_ID {CpuNr} {
594 2 olivier.gi
 
595 158 olivier.gi
    global omsp_conf
596 110 olivier.gi
    global omsp_info
597 158 olivier.gi
 
598
     # Copy global variable to local for code readability
599
    set if       $omsp_conf(interface)
600
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
601
 
602
    # Retreive CPU_ID/CPU_NR values
603
    set cpu_id_lo [${if}::dbg_rd $cpuaddr CPU_ID_LO]
604
    set cpu_id_hi [${if}::dbg_rd $cpuaddr CPU_ID_HI]
605
    set cpu_nr    [${if}::dbg_rd $cpuaddr CPU_NR]
606 124 olivier.gi
 
607
    # Check if value is valid
608
    if {[string eq "0x" $cpu_id_lo]} {
609
        set cpu_id_lo "0x0000"
610
    }
611
    if {[string eq "0x" $cpu_id_hi]} {
612
        set cpu_id_hi "0x0000"
613
    }
614 158 olivier.gi
    if {[string eq "0x" $cpu_nr]} {
615
        set cpu_nr    "0x0000"
616
    }
617 124 olivier.gi
 
618
    # Remove the "0x" prefix
619
    regsub {0x} $cpu_id_lo {} cpu_id_lo
620
    regsub {0x} $cpu_id_hi {} cpu_id_hi
621 2 olivier.gi
 
622 110 olivier.gi
    set cpu_id    "0x$cpu_id_hi$cpu_id_lo"
623
    set cpu_id_lo "0x$cpu_id_lo"
624
    set cpu_id_hi "0x$cpu_id_hi"
625
 
626
 
627
    # Extract the omsp info depending on the CPU version
628 158 olivier.gi
    set omsp_info($CpuNr,cpu_ver) [expr ($cpu_id_lo & 0x0007)+1]
629
    if {$omsp_info($CpuNr,cpu_ver)==1} {
630
        set omsp_info($CpuNr,user_ver)    --
631
        set omsp_info($CpuNr,per_size)   512
632
        set omsp_info($CpuNr,dmem_size)  [expr $cpu_id_lo]
633
        set omsp_info($CpuNr,pmem_size)  [expr $cpu_id_hi]
634
        set omsp_info($CpuNr,mpy)         --
635
        set omsp_info($CpuNr,asic)         0
636 110 olivier.gi
    } else {
637 158 olivier.gi
        set omsp_info($CpuNr,user_ver)   [expr  ($cpu_id_lo & 0x01f0)/16]
638
        set omsp_info($CpuNr,per_size)   [expr (($cpu_id_lo & 0xfe00)/512)  * 512]
639
        set omsp_info($CpuNr,dmem_size)  [expr (($cpu_id_hi & 0x03fe)/2)    * 128]
640
        set omsp_info($CpuNr,pmem_size)  [expr (($cpu_id_hi & 0xfc00)/1024) * 1024]
641
        set omsp_info($CpuNr,mpy)        [expr  ($cpu_id_hi & 0x0001)/1]
642
        set omsp_info($CpuNr,asic)       [expr  ($cpu_id_lo & 0x0008)/8]
643 110 olivier.gi
    }
644
 
645 158 olivier.gi
    # Get the instance number
646
    set omsp_info($CpuNr,inst_nr)  [expr  ($cpu_nr & 0x00ff)/1]
647
    set omsp_info($CpuNr,total_nr) [expr  ($cpu_nr & 0xff00)/256]
648 110 olivier.gi
 
649 158 olivier.gi
    # Get alias from the XML file
650
    set omsp_info($CpuNr,alias) [GetChipAlias $CpuNr]
651
 
652 110 olivier.gi
    return $cpu_id
653 2 olivier.gi
}
654
 
655
#=============================================================================#
656 158 olivier.gi
# GetCPU_ID_SIZE (CpuNr)                                                      #
657 2 olivier.gi
#-----------------------------------------------------------------------------#
658 110 olivier.gi
# Description: Returns the Data and Program memory sizes of the connected     #
659
#              device.                                                        #
660 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
661
# Result     : Return "PMEM_SIZE DMEM_SIZE PER_SIZE" in byte.                 #
662 2 olivier.gi
#=============================================================================#
663 158 olivier.gi
proc GetCPU_ID_SIZE {CpuNr} {
664 2 olivier.gi
 
665 110 olivier.gi
    global omsp_info
666 2 olivier.gi
 
667 158 olivier.gi
    # Check if custom sizes are available from the XML file
668
    set custom_pmem [array names omsp_info -glob "$CpuNr,extra,*,pmem_size"]
669
    set custom_dmem [array names omsp_info -glob "$CpuNr,extra,*,dmem_size"]
670
    set custom_per  [array names omsp_info -glob "$CpuNr,extra,*,per_size"]
671
 
672
    # Program memory size
673
    if {$custom_pmem != ""} {
674
        set pmem_size $omsp_info($custom_pmem)
675
    } elseif {[info exists omsp_info($CpuNr,pmem_size)]} {
676
        set pmem_size $omsp_info($CpuNr,pmem_size)
677 87 olivier.gi
    } else {
678 110 olivier.gi
        set pmem_size -1
679 87 olivier.gi
    }
680 158 olivier.gi
 
681
    # Data memory size
682
    if {$custom_dmem != ""} {
683
        set dmem_size $omsp_info($custom_dmem)
684
    } elseif {[info exists omsp_info($CpuNr,dmem_size)]} {
685
        set dmem_size $omsp_info($CpuNr,dmem_size)
686 87 olivier.gi
    } else {
687 110 olivier.gi
        set dmem_size -1
688 87 olivier.gi
    }
689 2 olivier.gi
 
690 158 olivier.gi
    # Peripheral address space size
691
    if {$custom_per != ""} {
692
        set per_size $omsp_info($custom_per)
693
    } elseif {[info exists omsp_info($CpuNr,per_size)]} {
694
        set per_size $omsp_info($CpuNr,per_size)
695
    } else {
696
        set per_size -1
697
    }
698
 
699
    return "$pmem_size $dmem_size $per_size"
700 2 olivier.gi
}
701
 
702
#=============================================================================#
703 158 olivier.gi
# VerifyCPU_ID (CpuNr)                                                        #
704 2 olivier.gi
#-----------------------------------------------------------------------------#
705
# Description: Read and check the CPU_ID from the target device.              #
706 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
707 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
708
#=============================================================================#
709 158 olivier.gi
proc VerifyCPU_ID {CpuNr} {
710 2 olivier.gi
 
711 158 olivier.gi
    global omsp_conf
712 114 olivier.gi
    global omsp_info
713
 
714 158 olivier.gi
    set cpu_id_full [GetCPU_ID $CpuNr]
715 2 olivier.gi
 
716 110 olivier.gi
    if {[string eq "0x00000000" $cpu_id_full] |
717 158 olivier.gi
        ([string length $cpu_id_full]!=10)    |
718
        ($omsp_info($CpuNr,cpu_ver) >3)       } {
719
 
720
        puts "\n"
721
        puts "ERROR: cpu_id not valid: $cpu_id_full"
722
        puts ""
723
        puts "         --------------------------------------------------------------"
724
        puts "       !!!! What next:                                               !!!!"
725
        if {[regexp {i2c_} $omsp_conf(interface)]} {
726
            puts "       !!!!    - double check the I2C address of the target core.    !!!!"
727
        }
728
        puts "       !!!!    - check that you are properly connected to the board. !!!!"
729
        puts "       !!!!    - try reseting the serial debug interface (or CPU).   !!!!"
730
        puts "         --------------------------------------------------------------"
731
        puts ""
732
 
733
        return 0
734 2 olivier.gi
    }
735 158 olivier.gi
    return 1
736 2 olivier.gi
}
737
 
738
#=============================================================================#
739 158 olivier.gi
# WriteReg (CpuNr, Addr,  Data)                                               #
740 2 olivier.gi
#-----------------------------------------------------------------------------#
741
# Description: Write a word to the the selected CPU register.                 #
742 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
743
#              Addr  - Target CPU Register number.                            #
744
#              Data  - Data value to be written.                              #
745 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
746
#=============================================================================#
747 158 olivier.gi
proc WriteReg {CpuNr Addr Data} {
748 2 olivier.gi
 
749 158 olivier.gi
    global omsp_conf
750 2 olivier.gi
 
751 158 olivier.gi
    # Copy global variable to local for code readability
752
    set if       $omsp_conf(interface)
753
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
754 2 olivier.gi
 
755 158 olivier.gi
    # Configure memory transfer
756
    #${if}::dbg_wr $cpuaddr MEM_CNT  0x0000
757
    ${if}::dbg_wr $cpuaddr MEM_ADDR $Addr
758
    ${if}::dbg_wr $cpuaddr MEM_DATA $Data
759
 
760
    # Trigger transfer
761
    ${if}::dbg_wr $cpuaddr MEM_CTL  0x0007
762
 
763 2 olivier.gi
    return 1
764
}
765
 
766
#=============================================================================#
767 158 olivier.gi
# WriteRegAll (CpuNr, DataList)                                               #
768 2 olivier.gi
#-----------------------------------------------------------------------------#
769
# Description: Write all CPU registers.                                       #
770 158 olivier.gi
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
771
#              DataList  - Data values to be written.                         #
772 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
773
#=============================================================================#
774 158 olivier.gi
proc WriteRegAll {CpuNr DataList} {
775 2 olivier.gi
 
776 158 olivier.gi
    global omsp_conf
777 2 olivier.gi
 
778 158 olivier.gi
    # Copy global variable to local for code readability
779
    set if       $omsp_conf(interface)
780
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
781 2 olivier.gi
 
782 158 olivier.gi
    # Configure & trigger memory transfer
783
    ${if}::dbg_wr $cpuaddr MEM_CNT  [expr [llength $DataList]-1]
784
    ${if}::dbg_wr $cpuaddr MEM_ADDR 0x0000
785
    ${if}::dbg_wr $cpuaddr MEM_CTL  0x0007
786 2 olivier.gi
 
787 158 olivier.gi
    # Send data list
788
    ${if}::dbg_burst_tx $cpuaddr 0 $DataList
789 2 olivier.gi
 
790
    return 1
791
}
792
 
793
#=============================================================================#
794 158 olivier.gi
# ReadReg (CpuNr, Addr)                                                       #
795 2 olivier.gi
#-----------------------------------------------------------------------------#
796
# Description: Read the value from the selected CPU register.                 #
797 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
798
#              Addr  - Target CPU Register number.                            #
799 2 olivier.gi
# Result     : Data value stored in the selected CPU register.                #
800
#=============================================================================#
801 158 olivier.gi
proc ReadReg {CpuNr Addr} {
802 2 olivier.gi
 
803 158 olivier.gi
    global omsp_conf
804 2 olivier.gi
 
805 158 olivier.gi
    # Copy global variable to local for code readability
806
    set if       $omsp_conf(interface)
807
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
808 2 olivier.gi
 
809 158 olivier.gi
    # Single data transfer
810
    ${if}::dbg_wr $cpuaddr MEM_CNT  0x0000
811
    ${if}::dbg_wr $cpuaddr MEM_ADDR $Addr
812
 
813
    # Trigger transfer
814
    ${if}::dbg_wr $cpuaddr MEM_CTL  0x0005
815
    set reg_val [${if}::dbg_rd $cpuaddr MEM_DATA]
816
 
817 2 olivier.gi
    return $reg_val
818
}
819
 
820
#=============================================================================#
821 158 olivier.gi
# ReadRegAll (CpuNr)                                                          #
822 2 olivier.gi
#-----------------------------------------------------------------------------#
823
# Description: Read all CPU registers.                                        #
824 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
825 2 olivier.gi
# Result     : Current values of all CPU registers.                           #
826
#=============================================================================#
827 158 olivier.gi
proc ReadRegAll {CpuNr} {
828 2 olivier.gi
 
829 158 olivier.gi
    global omsp_conf
830 2 olivier.gi
 
831 158 olivier.gi
    # Copy global variable to local for code readability
832
    set if       $omsp_conf(interface)
833
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
834 2 olivier.gi
 
835 158 olivier.gi
    # Configure & trigger memory transfer
836
    ${if}::dbg_wr $cpuaddr MEM_CNT  0x000f
837
    ${if}::dbg_wr $cpuaddr MEM_ADDR 0x0000
838
    ${if}::dbg_wr $cpuaddr MEM_CTL  0x0005
839
 
840
    # Receive Data list
841
    set reg_val [${if}::dbg_burst_rx $cpuaddr 0 32]
842
 
843 2 olivier.gi
    return $reg_val
844
}
845
 
846
#=============================================================================#
847 158 olivier.gi
# WriteMemQuick8 (CpuNr, StartAddr, DataList)                                 #
848 2 olivier.gi
#-----------------------------------------------------------------------------#
849 158 olivier.gi
# Description: Writes a list of bytes into the target device memory (RAM,     #
850 2 olivier.gi
#              ROM & Peripherals.                                             #
851 158 olivier.gi
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
852
#              StartAddr - Start address of destination memory.               #
853
#              DataList  - List of data to be written (in hexadecimal).       #
854 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
855
#=============================================================================#
856 158 olivier.gi
proc WriteMemQuick8 {CpuNr StartAddr DataList} {
857 2 olivier.gi
 
858 158 olivier.gi
    global omsp_conf
859
 
860
    # Copy global variable to local for code readability
861
    set if       $omsp_conf(interface)
862
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
863
 
864
    # Single data transfer
865
    if {[llength $DataList]==1} {
866
        WriteMem $CpuNr 1 $StartAddr $DataList
867
 
868
    # Burst data transfer
869 2 olivier.gi
    } else {
870
 
871 158 olivier.gi
        # Configure & trigger memory transfer
872
        ${if}::dbg_wr $cpuaddr MEM_CNT  [expr [llength $DataList]-1]
873
        ${if}::dbg_wr $cpuaddr MEM_ADDR $StartAddr
874
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x000b
875 2 olivier.gi
 
876 158 olivier.gi
        # Send data list
877
        ${if}::dbg_burst_tx $cpuaddr 1 $DataList
878 2 olivier.gi
 
879
    }
880
    return 1
881
}
882
 
883
#=============================================================================#
884 158 olivier.gi
# ReadMemQuick8 (CpuNr, StartAddr, Length)                                    #
885 2 olivier.gi
#-----------------------------------------------------------------------------#
886 158 olivier.gi
# Description: Reads a list of bytes from target memory.                      #
887
# Arguments  : CpuNr     - oMSP device number to be addressed.                #
888
#              StartAddr - Start address of target memory to be read.         #
889 2 olivier.gi
#              Length    - Number of bytes to be read.                        #
890
# Result     : List of data values stored in the target memory.               #
891
#=============================================================================#
892 158 olivier.gi
proc ReadMemQuick8 {CpuNr StartAddr Length} {
893 2 olivier.gi
 
894 158 olivier.gi
    global omsp_conf
895
 
896
    # Copy global variable to local for code readability
897
    set if       $omsp_conf(interface)
898
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
899
 
900
    # Single data transfer
901 2 olivier.gi
    if {$Length==1} {
902 158 olivier.gi
        set mem_val [ReadMem $CpuNr 1 $StartAddr]
903
 
904
    # Burst data transfer
905 2 olivier.gi
    } else {
906
 
907 158 olivier.gi
        # Configure & trigger memory transfer
908
        ${if}::dbg_wr $cpuaddr MEM_CNT  [expr $Length-1]
909
        ${if}::dbg_wr $cpuaddr MEM_ADDR $StartAddr
910
        ${if}::dbg_wr $cpuaddr MEM_CTL  0x0009
911
 
912
        # Receive Data list
913
        set mem_val [${if}::dbg_burst_rx $cpuaddr 1 $Length]
914 2 olivier.gi
    }
915
 
916
    return $mem_val
917
}
918
 
919
#=============================================================================#
920 158 olivier.gi
# StepCPU (CpuNr)                                                             #
921 2 olivier.gi
#-----------------------------------------------------------------------------#
922
# Description: Performs a CPU incremental step.                               #
923 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
924 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
925
#=============================================================================#
926 158 olivier.gi
proc StepCPU {CpuNr} {
927 2 olivier.gi
 
928 158 olivier.gi
    global omsp_conf
929
 
930
    # Copy global variable to local for code readability
931
    set if       $omsp_conf(interface)
932
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
933
 
934 2 olivier.gi
    # Check if the device is halted. If not, stop it.
935 158 olivier.gi
    set cpu_ctl_val [${if}::dbg_rd $cpuaddr CPU_CTL]
936 2 olivier.gi
    set cpu_ctl_new [expr 0x04 | $cpu_ctl_val]
937 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_CTL $cpu_ctl_new
938 2 olivier.gi
 
939
    return 1
940
}
941
 
942
#=============================================================================#
943 158 olivier.gi
# EraseRAM (CpuNr)                                                            #
944 2 olivier.gi
#-----------------------------------------------------------------------------#
945
# Description: Erase RAM.                                                     #
946 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
947 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
948
#=============================================================================#
949 158 olivier.gi
proc EraseRAM {CpuNr} {
950 2 olivier.gi
 
951 158 olivier.gi
    global omsp_info
952 2 olivier.gi
 
953 158 olivier.gi
    set ram_size [lindex [GetCPU_ID_SIZE $CpuNr] 1]
954
    set per_size [lindex [GetCPU_ID_SIZE $CpuNr] 2]
955
 
956 87 olivier.gi
    if {$ram_size!=-1} {
957 2 olivier.gi
 
958 158 olivier.gi
        set DataList ""
959
        for {set i 0} {$i<$ram_size} {incr i} {
960
            lappend DataList 0x00
961
        }
962 2 olivier.gi
 
963 158 olivier.gi
        WriteMemQuick8 $CpuNr $per_size $DataList
964
 
965
        return 1
966 87 olivier.gi
    }
967
    return 0
968 2 olivier.gi
}
969
 
970
#=============================================================================#
971 158 olivier.gi
# EraseROM (CpuNr)                                                            #
972 2 olivier.gi
#-----------------------------------------------------------------------------#
973
# Description: Erase ROM.                                                     #
974 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
975 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
976
#=============================================================================#
977 158 olivier.gi
proc EraseROM {CpuNr} {
978 2 olivier.gi
 
979 158 olivier.gi
    set rom_size  [lindex [GetCPU_ID_SIZE $CpuNr] 0]
980 2 olivier.gi
    set rom_start [expr 0x10000-$rom_size]
981
 
982 96 olivier.gi
    if {$rom_size!=-1} {
983 158 olivier.gi
        set DataList ""
984
        for {set i 0} {$i<$rom_size} {incr i} {
985
            lappend DataList 0x00
986
        }
987 2 olivier.gi
 
988 158 olivier.gi
        WriteMemQuick8 $CpuNr $rom_start $DataList
989 2 olivier.gi
 
990 158 olivier.gi
        return 1
991 87 olivier.gi
    }
992
    return 0
993 2 olivier.gi
}
994
 
995
#=============================================================================#
996 158 olivier.gi
# InitBreakUnits(CpuNr)                                                       #
997 2 olivier.gi
#-----------------------------------------------------------------------------#
998
# Description: Initialize the hardware breakpoint units.                      #
999 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1000 2 olivier.gi
# Result     : Number of hardware breakpoint units.                           #
1001
#=============================================================================#
1002 158 olivier.gi
proc InitBreakUnits {CpuNr} {
1003 2 olivier.gi
 
1004 158 olivier.gi
    global omsp_conf
1005
 
1006
    # Copy global variable to local for code readability
1007
    set if       $omsp_conf(interface)
1008
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
1009
 
1010
    # Initialize each hardware breakpoint unit and count how many of them
1011
    # are present in the current core
1012 2 olivier.gi
    set num_brk_units 0
1013
    for {set i 0} {$i<4} {incr i} {
1014
 
1015 158 olivier.gi
        ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR0" 0x1234
1016
        set new_val [${if}::dbg_rd $cpuaddr "BRK$i\_ADDR0"]
1017
        if {$new_val=="0x1234"} {
1018
            incr num_brk_units
1019
            ${if}::dbg_wr $cpuaddr "BRK$i\_CTL"   0x00
1020
            ${if}::dbg_wr $cpuaddr "BRK$i\_STAT"  0xff
1021
            ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR0" 0x0000
1022
            ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR1" 0x0000
1023
        }
1024 2 olivier.gi
    }
1025
    return $num_brk_units
1026
}
1027
 
1028
#=============================================================================#
1029 158 olivier.gi
# SetHWBreak(CpuNr, Type, Addr, Rd, Wr)                                       #
1030 2 olivier.gi
#-----------------------------------------------------------------------------#
1031
# Description: Set data/instruction breakpoint on a given memory address.     #
1032 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1033
#              Type  - 1 for instruction break, 0 for data break.             #
1034
#              Addr  - Memory address of the data breakpoint.                 #
1035
#              Rd    - Breakpoint on read access.                             #
1036
#              Wr    - Breakpoint on write access.                            #
1037 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
1038
#=============================================================================#
1039 158 olivier.gi
proc SetHWBreak {CpuNr Type Addr Rd Wr} {
1040 2 olivier.gi
 
1041 158 olivier.gi
    global omsp_info
1042
    global omsp_conf
1043
 
1044
    # Copy global variable to local for code readability
1045
    set if       $omsp_conf(interface)
1046
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
1047
 
1048 2 olivier.gi
    # Compute the BRKx_CTL corresponding value
1049
    set brk_ctl_ref [format "0x02%x" [expr 8*$Type+4+2*$Wr+$Rd]]
1050
 
1051
    # First look for utilized units with correct BRKx_CTL attributes
1052 158 olivier.gi
    for {set i 0} {$i<$omsp_info($CpuNr,hw_break)} {incr i} {
1053
        if {[string eq [${if}::dbg_rd $cpuaddr "BRK$i\_CTL"] $brk_ctl_ref]} {
1054
 
1055
            # Look if there is an address free
1056
            set brk_addr0 [${if}::dbg_rd $cpuaddr "BRK$i\_ADDR0"]
1057
            set brk_addr1 [${if}::dbg_rd $cpuaddr "BRK$i\_ADDR1"]
1058
            if {[string eq $brk_addr0 $brk_addr1]} {
1059
                ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR1" $Addr
1060
                return 1
1061
            }
1062 124 olivier.gi
        }
1063 2 olivier.gi
    }
1064
 
1065
    # Then look for a free unit
1066 158 olivier.gi
    for {set i 0} {$i<$omsp_info($CpuNr,hw_break)} {incr i} {
1067
        if {[string eq [${if}::dbg_rd $cpuaddr "BRK$i\_CTL"] 0x00]} {
1068
            ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR0" $Addr
1069
            ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR1" $Addr
1070
            ${if}::dbg_wr $cpuaddr "BRK$i\_CTL"   $brk_ctl_ref
1071
            return 1
1072
        }
1073 2 olivier.gi
    }
1074
 
1075
    return 0
1076
}
1077
 
1078
#=============================================================================#
1079 158 olivier.gi
# ClearHWBreak(CpuNr, Type, Addr)                                             #
1080 2 olivier.gi
#-----------------------------------------------------------------------------#
1081
# Description: Clear the data/instruction breakpoint set on the provided      #
1082
#              memory address.                                                #
1083 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1084
#              Type  - 1 for instruction break, 0 for data break.             #
1085
#              Addr  - Data address of the breakpoint to be cleared.          #
1086 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
1087
#=============================================================================#
1088 158 olivier.gi
proc ClearHWBreak {CpuNr Type Addr} {
1089 2 olivier.gi
 
1090 158 olivier.gi
    global omsp_info
1091
    global omsp_conf
1092 2 olivier.gi
 
1093 158 olivier.gi
    # Copy global variable to local for code readability
1094
    set if       $omsp_conf(interface)
1095
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
1096 2 olivier.gi
 
1097 158 olivier.gi
    for {set i 0} {$i<$omsp_info($CpuNr,hw_break)} {incr i} {
1098
 
1099
        # Check if the unit works on Data or Instructions)
1100
        set brk_ctl [${if}::dbg_rd $cpuaddr "BRK$i\_CTL"]
1101
        if {[expr $brk_ctl & 0x08]==[expr 8*$Type]} {
1102
 
1103
            # Look for the matching address
1104
            set brk_addr0 [${if}::dbg_rd $cpuaddr "BRK$i\_ADDR0"]
1105
            set brk_addr1 [${if}::dbg_rd $cpuaddr "BRK$i\_ADDR1"]
1106
 
1107
            if {[string eq $brk_addr0 $brk_addr1] && [string eq $brk_addr0 $Addr]} {
1108
                ${if}::dbg_wr $cpuaddr "BRK$i\_CTL"   0x00
1109
                ${if}::dbg_wr $cpuaddr "BRK$i\_STAT"  0xff
1110
                ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR0" 0x0000
1111
                ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR1" 0x0000
1112
                return 1
1113
            }
1114
            if {[string eq $brk_addr0 $Addr]} {
1115
                ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR0" $brk_addr1
1116
                return 1
1117
            }
1118
            if {[string eq $brk_addr1 $Addr]} {
1119
                ${if}::dbg_wr $cpuaddr "BRK$i\_ADDR1" $brk_addr0
1120
                return 1
1121
            }
1122 124 olivier.gi
        }
1123 2 olivier.gi
    }
1124
    return 1
1125
}
1126
 
1127
#=============================================================================#
1128 158 olivier.gi
# IsHalted (CpuNr)                                                            #
1129 2 olivier.gi
#-----------------------------------------------------------------------------#
1130
# Description: Check if the CPU is currently stopped or not.                  #
1131 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1132 2 olivier.gi
# Result     : 0 if CPU is running, 1 if stopped.                             #
1133
#=============================================================================#
1134 158 olivier.gi
proc IsHalted {CpuNr} {
1135 2 olivier.gi
 
1136 158 olivier.gi
    global omsp_conf
1137
 
1138
    # Copy global variable to local for code readability
1139
    set if       $omsp_conf(interface)
1140
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
1141
 
1142 2 olivier.gi
    # Check current target status
1143 158 olivier.gi
    set cpu_stat_val [${if}::dbg_rd $cpuaddr CPU_STAT]
1144 2 olivier.gi
    set halted       [expr 0x01 & $cpu_stat_val]
1145
 
1146
    return $halted
1147
}
1148
 
1149
#=============================================================================#
1150 158 olivier.gi
# ClrStatus (CpuNr)                                                           #
1151 2 olivier.gi
#-----------------------------------------------------------------------------#
1152
# Description: Clear the status bit of the CPU_STAT register.                 #
1153 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1154 2 olivier.gi
# Result     : 0 if error, 1 otherwise.                                       #
1155
#=============================================================================#
1156 158 olivier.gi
proc ClrStatus {CpuNr} {
1157 2 olivier.gi
 
1158 158 olivier.gi
    global omsp_conf
1159
 
1160
    # Copy global variable to local for code readability
1161
    set if       $omsp_conf(interface)
1162
    set cpuaddr  $omsp_conf($CpuNr,cpuaddr)
1163
 
1164 2 olivier.gi
    # Clear status
1165 158 olivier.gi
    ${if}::dbg_wr $cpuaddr CPU_STAT  0xff
1166
    ${if}::dbg_wr $cpuaddr BRK0_STAT 0xff
1167
    ${if}::dbg_wr $cpuaddr BRK1_STAT 0xff
1168
    ${if}::dbg_wr $cpuaddr BRK2_STAT 0xff
1169
    ${if}::dbg_wr $cpuaddr BRK3_STAT 0xff
1170 2 olivier.gi
 
1171
    return 1
1172
}
1173 110 olivier.gi
 
1174
#=============================================================================#
1175 158 olivier.gi
# GetAllowedSpeeds()                                                          #
1176 110 olivier.gi
#-----------------------------------------------------------------------------#
1177 158 olivier.gi
# Description: Return the list of allowed speed configurations for the        #
1178
#              selected adapter.                                              #
1179
# Arguments  : None.                                                          #
1180
# Result     : list of modes.                                                 #
1181
#=============================================================================#
1182
proc GetAllowedSpeeds {} {
1183
 
1184
    global omsp_conf
1185
 
1186
    # Copy global variable to local for code readability
1187
    set if       $omsp_conf(interface)
1188
 
1189
    # Return list of allowed speed configuration
1190
    return [${if}::get_allowed_speeds]
1191
}
1192
 
1193
#=============================================================================#
1194
# GetChipAlias (CpuNr)                                                        #
1195
#-----------------------------------------------------------------------------#
1196 110 olivier.gi
# Description: Parse the chip alias XML file an return the alias name.        #
1197 158 olivier.gi
# Arguments  : CpuNr - oMSP device number to be addressed.                    #
1198 110 olivier.gi
# Result     : Chip Alias.                                                    #
1199
#=============================================================================#
1200 158 olivier.gi
proc GetChipAlias {CpuNr} {
1201 110 olivier.gi
 
1202
    global omsp_info
1203
 
1204
    # Set XML file name
1205
    if {[info exists  ::env(OMSP_XML_FILE)]} {
1206 158 olivier.gi
        set xmlFile $::env(OMSP_XML_FILE)
1207 110 olivier.gi
    } else {
1208 158 olivier.gi
        set xmlFile [file normalize "$::scriptDir/../../omsp_alias.xml"]
1209 110 olivier.gi
    }
1210
 
1211
    # Read XML file
1212
    if {[file exists $xmlFile]} {
1213 158 olivier.gi
        set fp [open $xmlFile r]
1214
        set xmlData [read $fp]
1215
        close $fp
1216 110 olivier.gi
    } else {
1217 158 olivier.gi
        puts "WARNING: the XML alias file was not found - $xmlFile"
1218
        return ""
1219 110 olivier.gi
    }
1220
 
1221
    # Analyze XML file
1222
    ::XML::Init $xmlData
1223
    set wellFormed [::XML::IsWellFormed]
1224
    if {$wellFormed ne ""} {
1225 158 olivier.gi
        puts "WARNING: the XML alias file is not well-formed - $xmlFile \n $wellFormed"
1226
        return ""
1227 110 olivier.gi
    }
1228
 
1229
    #========================================================================#
1230
    # Create list from XML file                                              #
1231
    #========================================================================#
1232
    set aliasList    ""
1233
    set currentALIAS ""
1234
    set currentTYPE  ""
1235
    set currentTAG   ""
1236
    while {1} {
1237 158 olivier.gi
        foreach {type val attr etype} [::XML::NextToken] break
1238
        if {$type == "EOF"} break
1239 110 olivier.gi
 
1240 158 olivier.gi
        # Detect the start of a new alias description
1241
        if {($type == "XML") & ($val == "omsp:alias") & ($etype == "START")} {
1242
            set aliasName ""
1243
            regexp {val=\"(.*)\"} $attr whole_match aliasName
1244
            lappend aliasList $aliasName
1245
            set currentALIAS $aliasName
1246
        }
1247 110 olivier.gi
 
1248 158 olivier.gi
        # Detect start and end of the configuration field
1249
        if {($type == "XML") & ($val == "omsp:configuration")} {
1250 110 olivier.gi
 
1251 158 olivier.gi
            if {($etype == "START")} {
1252
                set currentTYPE  "config"
1253 110 olivier.gi
 
1254 158 olivier.gi
            } elseif {($etype == "END")} {
1255
                set currentTYPE  ""
1256
            }
1257 124 olivier.gi
        }
1258 110 olivier.gi
 
1259 158 olivier.gi
        # Detect start and end of the extra_info field
1260
        if {($type == "XML") & ($val == "omsp:extra_info")} {
1261 110 olivier.gi
 
1262 158 olivier.gi
            if {($etype == "START")} {
1263
                set currentTYPE  "extra_info"
1264
                set idx 0
1265 110 olivier.gi
 
1266 158 olivier.gi
            } elseif {($etype == "END")} {
1267
                set currentTYPE  ""
1268
            }
1269 124 olivier.gi
        }
1270 158 olivier.gi
 
1271
        # Detect the current TAG
1272
        if {($type == "XML") & ($etype == "START")} {
1273
            regsub {omsp:} $val {} val
1274
            set currentTAG $val
1275
        }
1276 110 olivier.gi
 
1277 158 olivier.gi
        if {($type == "TXT")} {
1278
            if {$currentTYPE=="extra_info"} {
1279
                set alias($currentALIAS,$currentTYPE,$idx,$currentTAG) $val
1280
                incr idx
1281
            } else {
1282
                set alias($currentALIAS,$currentTYPE,$currentTAG) $val
1283
            }
1284 124 olivier.gi
        }
1285 110 olivier.gi
    }
1286
 
1287
    #========================================================================#
1288
    # Check if the current OMSP_INFO has an alias match                      #
1289
    #========================================================================#
1290
    foreach currentALIAS $aliasList {
1291
 
1292 158 olivier.gi
        set aliasCONFIG [array names alias -glob "$currentALIAS,config,*"]
1293
        set aliasEXTRA  [lsort -increasing [array names alias -glob "$currentALIAS,extra_info,*"]]
1294 110 olivier.gi
 
1295 158 olivier.gi
        #----------------------------------#
1296
        # Is current alias matching ?      #
1297
        #----------------------------------#
1298
        set match       1
1299
        set description ""
1300
        foreach currentCONFIG $aliasCONFIG {
1301 110 olivier.gi
 
1302 158 olivier.gi
            regsub "$currentALIAS,config," $currentCONFIG {} configName
1303
 
1304
            if {![string eq $omsp_info($CpuNr,$configName) $alias($currentCONFIG)]} {
1305
                set match 0
1306
            }
1307 124 olivier.gi
        }
1308 110 olivier.gi
 
1309 158 olivier.gi
        #----------------------------------#
1310
        # If matching, get the extra infos #
1311
        #----------------------------------#
1312
        if {$match} {
1313 110 olivier.gi
 
1314 158 olivier.gi
            set idx 0
1315
            foreach currentEXTRA $aliasEXTRA {
1316
                regsub "$currentALIAS,extra_info," $currentEXTRA {} extraName
1317
                set omsp_info($CpuNr,extra,$idx,$extraName) $alias($currentEXTRA)
1318
                incr idx
1319
            }
1320
            return $currentALIAS
1321 124 olivier.gi
        }
1322 110 olivier.gi
    }
1323
 
1324
    return ""
1325
}

powered by: WebSVN 2.1.0

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