This is an automated email from Gerrit. Luis de Arquer ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/6124
-- gerrit commit a7477408d6880f59abef5d8e5c307a5eb84eb7af Author: Luis de Arquer <[email protected]> Date: Wed Mar 24 17:14:40 2021 +0100 target/once: Initial support for On Chip Emulator (Power arch, e200 core) Basic support for debug control of the Power Architecture e200 core. All of the SPC56x/RPC56x devices from ST (and possibly MPC56x from NXP) should be compatible with this implementation, based on ST Application Note AN4035. The following functionality is provided: - Read/Write CPU registers - Read/Write arbitrary memory location (32-bit) - Execute single instruction - Load binary file to memory location - Execute code at specific memory location, until a breakpoint is reached Tested on ST SPC560D. binary.tcl is added as a dependency. It is taken from jimtcl. The full original license is added on the header, plus an SPDX meta tag, with GPL2 as extra choice Change-Id: Icaa8a5d38923f5768e64f00c62058fafe93ab6ed Signed-off-by: Luis de Arquer <[email protected]> diff --git a/tcl/binary.tcl b/tcl/binary.tcl new file mode 100644 index 0000000..fc1c7ca --- /dev/null +++ b/tcl/binary.tcl @@ -0,0 +1,319 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause +# +# Implements the 'binary scan' and 'binary format' commands. +# +# (c) 2010 Steve Bennett <[email protected]> +# +# Copyright 2005 Salvatore Sanfilippo <[email protected]> +# Copyright 2005 Clemens Hintze <[email protected]> +# Copyright 2005 patthoyts - Pat Thoyts <[email protected]> +# Copyright 2008 oharboe - Øyvind Harboe - [email protected] +# Copyright 2008 Andrew Lunn <[email protected]> +# Copyright 2008 Duane Ellis <[email protected]> +# Copyright 2008 Uwe Klein <[email protected]> +# Copyright 2008 Steve Bennett <[email protected]> +# Copyright 2009 Nico Coesel <[email protected]> +# Copyright 2009 Zachary T Welch [email protected] +# Copyright 2009 David Brownell +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials +# provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE JIM TCL PROJECT ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +# JIM TCL PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# The views and conclusions contained in the software and documentation +# are those of the authors and should not be interpreted as representing +# official policies, either expressed or implied, of the Jim Tcl Project. + + +package require pack +package require regexp + +proc binary {cmd args} { + tailcall "binary $cmd" {*}$args +} + +proc "binary format" {formatString args} { + set bitoffset 0 + set result {} + # This RE is too unreliable... + foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] { + switch -exact -- $t { + a - + A { + set value [binary::nextarg args] + set sn [string bytelength $value] + if {$n ne "*"} { + if {$n eq ""} { + set n 1 + } + if {$n > $sn} { + # Need to pad the string with spaces or nulls + append value [string repeat [dict get {A " " a \x00} $t] $($n - $sn)] + } + } else { + set n $sn + } + if {$n} { + set bitoffset [pack result $value -str $(8 * $n) $bitoffset] + } + } + x { + if {$n eq "*"} { + return -code error {cannot use "*" in format string with "x"} + } + if {$n eq ""} { + set n 1 + } + loop i 0 $n { + set bitoffset [pack result 0 -intbe 8 $bitoffset] + } + } + @ { + if {$n eq ""} { + return -code error {missing count for "@" field specifier} + } + if {$n eq "*"} { + set bitoffset $(8 * [string bytelength $result]) + } else { + # May need to pad it out + set max [string bytelength $result] + append result [string repeat \x00 $($n - $max)] + set bitoffset $(8 * $n) + } + } + X { + if {$n eq "*"} { + set bitoffset 0 + } elseif {$n eq ""} { + incr bitoffset -8 + } else { + incr bitoffset $($n * -8) + } + if {$bitoffset < 0} { + set bitoffset 0 + } + } + default { + if {![info exists ::binary::scalarinfo($t)]} { + return -code error "bad field specifier \"$t\"" + } + + # A scalar (integer or float) type + lassign $::binary::scalarinfo($t) type convtype size prefix + set value [binary::nextarg args] + + if {$type in {bin hex}} { + set value [split $value {}] + } + set vn [llength $value] + if {$n eq "*"} { + set n $vn + } elseif {$n eq ""} { + set n 1 + set value [list $value] + } elseif {$vn < $n} { + if {$type in {bin hex}} { + # Need to pad the list with zeros + lappend value {*}[lrepeat $($n - $vn) 0] + } else { + return -code error "number of elements in list does not match count" + } + } elseif {$vn > $n} { + # Need to truncate the list + set value [lrange $value 0 $n-1] + } + + set convtype -$::binary::convtype($convtype) + + foreach v $value { + set bitoffset [pack result $prefix$v $convtype $size $bitoffset] + } + # Now pad out with zeros to the end of the current byte + if {$bitoffset % 8} { + set bitoffset [pack result 0 $convtype $(8 - $bitoffset % 8) $bitoffset] + } + } + } + } + return $result +} + +proc "binary scan" {value formatString {args varName}} { + # Pops the next arg from the front of the list and returns it. + # Throws an error if no more args + set bitoffset 0 + set count 0 + # This RE is too unreliable... + foreach {conv t u n} [regexp -all -inline {([^[:space:]])(u)?([*0-9]*)} $formatString] { + set rembytes $([string bytelength $value] - $bitoffset / 8) + switch -exact -- $t { + a - + A { + if {$n eq "*"} { + set n $rembytes + } elseif {$n eq ""} { + set n 1 + } + if {$n > $rembytes} { + break + } + + set var [binary::nextarg varName] + + set result [unpack $value -str $bitoffset $($n * 8)] + incr bitoffset $([string bytelength $result] * 8) + if {$t eq "A"} { + set result [string trimright $result] + } + } + x { + # Skip bytes + if {$n eq "*"} { + set n $rembytes + } elseif {$n eq ""} { + set n 1 + } + if {$n > $rembytes} { + set n $rembytes + } + incr bitoffset $($n * 8) + continue + } + X { + # Back up bytes + if {$n eq "*"} { + set bitoffset 0 + continue + } + if {$n eq ""} { + set n 1 + } + if {$n * 8 > $bitoffset} { + set bitoffset 0 + continue + } + incr bitoffset -$($n * 8) + continue + } + @ { + if {$n eq ""} { + return -code error {missing count for "@" field specifier} + } + if {$n eq "*" || $n > $rembytes + $bitoffset / 8} { + incr bitoffset $($rembytes * 8) + } elseif {$n < 0} { + set bitoffset 0 + } else { + set bitoffset $($n * 8) + } + continue + } + default { + if {![info exists ::binary::scalarinfo($t)]} { + return -code error "bad field specifier \"$t\"" + } + # A scalar (integer or float) type + lassign $::binary::scalarinfo($t) type convtype size prefix + set var [binary::nextarg varName] + + if {$n eq "*"} { + set n $($rembytes * 8 / $size) + } else { + if {$n eq ""} { + set n 1 + } + } + if {$n * $size > $rembytes * 8} { + break + } + + if {$type in {hex bin}} { + set u u + } + set convtype -$u$::binary::convtype($convtype) + + set result {} + loop i 0 $n { + set v [unpack $value $convtype $bitoffset $size] + if {$type in {bin hex}} { + append result [lindex {0 1 2 3 4 5 6 7 8 9 a b c d e f} $v] + } else { + lappend result $v + } + incr bitoffset $size + } + # Now skip to the end of the current byte + if {$bitoffset % 8} { + incr bitoffset $(8 - ($bitoffset % 8)) + } + } + } + uplevel 1 [list set $var $result] + incr count + } + return $count +} + +# Pops the next arg from the front of the list and returns it. +# Throws an error if no more args +proc binary::nextarg {&arglist} { + if {[llength $arglist] == 0} { + return -level 2 -code error "not enough arguments for all format specifiers" + } + set arglist [lassign $arglist arg] + return $arg +} + +set binary::scalarinfo { + c {int be 8} + s {int le 16} + t {int host 16} + S {int be 16} + i {int le 32} + I {int be 32} + n {int host 32} + w {int le 64} + W {int be 64} + m {int host 64} + h {hex le 4 0x} + H {hex be 4 0x} + b {bin le 1} + B {bin be 1} + r {float fle 32} + R {float fbe 32} + f {float fhost 32} + q {float fle 64} + Q {float fbe 64} + d {float fhost 64} +} +set binary::convtype { + be intbe + le intle + fbe floatbe + fle floatle +} +if {$::tcl_platform(byteOrder) eq "bigEndian"} { + array set binary::convtype {host intbe fhost floatbe} +} else { + array set binary::convtype {host intle fhost floatle} +} diff --git a/tcl/target/once.cfg b/tcl/target/once.cfg new file mode 100644 index 0000000..e2eec5e --- /dev/null +++ b/tcl/target/once.cfg @@ -0,0 +1,273 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# e200z0 OnCE (On Chip Emulator) +# +# Copyright (c) 2021, Hsin Chong Machinery Works Co., Ltd +# Copyright (c) 2021, Inertim Research, SL +# [email protected] +# +# +# The On-Chip Emulation is part of Nexus/JTAG specification. +# Implemented following the ST Application Note AN4035 +# +# Nexus/JTAG Flash programming supports the following products: +# SPC563Mxx +# SPC564Axx +# SPC56APxx +# SPC560Dxx +# SPC560Bxx +# SPC564Bxx +# SPC560Cxx +# SPC560Pxx +# SPC56ECxx +# SPC56ELxx +# RPC56ELxx +# RPC560Bxx +# RPC564Bxx +# RPC56APxx +# RPC564Axx +# + + +source [find binary.tcl] + + +proc once_read_osr {once} { + + set osr 0x[irscan $once 0x011] + return $osr +} + + +proc once_read_jtag_id {once} { + + irscan $once 0x002 + set once_id 0x[drscan $once 32 0x00000000] + return $once_id +} + + +proc once_read_dbsr {once} { + + irscan $once 0x230 + set dbsr 0x[drscan $once 32 0x00000000] + return $dbsr +} + + +proc once_read_cpuscr {once} { + + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + return $cpuscr +} + + +proc once_enter_debug_mode {once} { + + # First we need to enter debug mode, then enable external debug mode. + + # 1- Enter debug mode while holding reset + jtag_reset 0 1 + + irscan $once 0x012 + set ocr 0x[drscan $once 32 0x00000005] + + jtag_reset 0 0 + + # TODO: We can use this read for checking (osr == 0x209) + #set osr [once_read_osr $once] + #echo "OSR = $osr" + + irscan $once 0x012 + set ocr 0x[drscan $once 32 0x00000006] + + # 2- Enable external debug mode + # Write DBCR0 for enabling external debug + irscan $once 0x031 + drscan $once 32 0x80000000 + + # Clear all DBSR flags + irscan $once 0x030 + drscan $once 32 0xFFFFFFFF +} + + +proc once_read_pc {once} { + + # Read CPUSCR register chain -> [ WBBRL WBBRH MSR PC IR CTL ] + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + # Save PC subregister + set pc 0x[lindex $cpuscr 3] + + return $pc +} + + +proc once_read_wbbr {once} { + + # Read CPUSCR register chain -> [ WBBRL WBBRH MSR PC IR CTL ] + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + # Save WBBRL subregister + set wbbr 0x[lindex $cpuscr 0] + + return $wbbr +} + + +# Single step with WBBR. +# WBBR is used to pass operand information to/from CPU +proc once_single_step_wbbr {once instruction wbbr} { + + # Read CPUSCR register chain -> [ WBBRL WBBRH MSR PC IR CTL ] + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + # Save CTL subregister + set ctl 0x[lindex $cpuscr 5] + + set ctl [expr $ctl & 0xFFFF0000] + set ctl [expr $ctl | 0x00000402] ;# FFRA=1 (Use wbbr), IRSTAT8=1 (VLE inst) + set ctl [format 0x%08x $ctl] + + # Write CPUSCR + irscan $once 0x010 + drscan $once 32 $wbbr 32 0x00000000 32 0x00000000 32 0x00000008 32 $instruction 32 $ctl + + # GO command + irscan $once 0x111 + drscan $once 32 0x00000000 +} + + +# Single step without WBBR +proc once_single_step {once instruction} { + + # Read CPUSCR register chain -> [ WBBRL WBBRH MSR PC IR CTL ] + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + # Save CTL subregister + set ctl 0x[lindex $cpuscr 5] + + set ctl [expr $ctl & 0xFFFF0000] + set ctl [expr $ctl | 0x00000002] ;# FFRA=0 (Don't use wbbr), IRSTAT8=1 (VLE inst) + set ctl [format 0x%08x $ctl] + + # Write CPUSCR + irscan $once 0x010 + drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000008 32 $instruction 32 $ctl + + # GO command + irscan $once 0x111 + drscan $once 32 0x00000000 +} + + +proc once_read32 {once address} { + + once_single_step_wbbr $once 0x501F0000 $address + + # Read CPUSCR + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + set value 0x[lindex $cpuscr 0] + return $value +} + +proc once_write32 {once address value} { + + # Write $value into R1 + once_single_step_wbbr $once 0x1BE1D000 $value + + # Write R1 into address + once_single_step_wbbr $once 0x543F0000 $address +} + + +proc once_read_gpr {once gpr} { + + # ori gpr ^ 0 -> gpr and wwbr + set shifted_gpr_s [expr $gpr << 21] + set shifted_gpr_a [expr $gpr << 16] + set inst 0x1800D000 + set inst [format 0x%08X [expr $inst | $shifted_gpr_s]] + set inst [format 0x%08X [expr $inst | $shifted_gpr_a]] + + once_single_step $once $inst + + set value [once_read_wbbr $once] + return $value +} + + +proc once_write_gpr {once gpr value} { + + # ori value ^ 0 -> gpr + set shifted_gpr [expr $gpr << 16] + set inst 0x1800D000 + set inst [format 0x%08X [expr $inst | $shifted_gpr]] + + once_single_step_wbbr $once $inst $value + +} + + +# Load binary file to SRAM +# If the binary is going to be executed, it should end with 32 bit zeroes +# (this creates a breakpoint) +proc once_load_bin {once address filename} { + + set infile [open $filename r] + + set bytes [read $infile 4] + while { $bytes ne ""} { + set ret [binary scan $bytes Iu s] + if { $ret == 0 } { + puts "File size is not multiple of 4" + exit + } + set s [format 0x%08X $s] + puts "Block: $s" + + once_write32 $once $address $s + + set address [expr 0x04 + $address] + set address [format 0x%08X $address] + set bytes [read $infile 4] + } +} + + +# Run a previously loaded binary on @address +proc once_run {once address} { + + # Read CPUSCR register chain -> [ WBBRL WBBRH MSR PC IR CTL ] + irscan $once 0x210 + set cpuscr [drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000 32 0x00000000] + + # Save CTL subregister + set ctl 0x[lindex $cpuscr 5] + + set ctl [expr $ctl & 0xFFFF0000] + set ctl [expr $ctl | 0x00000002] ;# FFRA=0 (Don't use wbbr), IRSTAT8=1 (VLE inst) + set ctl [format 0x%08X $ctl] + + set pc [expr $address - 0x02] + set pc [format 0x%08X $pc] + #puts "pc = $pc" + + # Write CPUSCR + set instruction 0x60000000 ;# nop + irscan $once 0x010 + drscan $once 32 0x00000000 32 0x00000000 32 0x00000000 32 $pc 32 $instruction 32 $ctl + + # GO command + Leave debug mode + irscan $once 0x191 + drscan $once 32 0x00000000 +} -- _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
