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 208

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

powered by: WebSVN 2.1.0

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