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 210

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

powered by: WebSVN 2.1.0

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