Import xPack OpenOCD 0.12.0-7 and GNU Make 4.4.1 from x86_64-w64-mingw32.
This commit is contained in:
@@ -0,0 +1,143 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Script for Bouffalo chips with similar architecture used in BL602
|
||||
# based on SiFive E21 core
|
||||
|
||||
source [find mem_helper.tcl]
|
||||
|
||||
transport select jtag
|
||||
|
||||
if { [info exists CPUTAPID ] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
error "you must specify a tap id"
|
||||
}
|
||||
|
||||
if { [info exists BL602_CHIPNAME] } {
|
||||
set _CHIPNAME $BL602_CHIPNAME
|
||||
} else {
|
||||
error "you must specify a chip name"
|
||||
}
|
||||
|
||||
if { [info exists WORKAREAADDR] } {
|
||||
set _WORKAREAADDR $WORKAREAADDR
|
||||
} else {
|
||||
error "you must specify a work area address"
|
||||
}
|
||||
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
error "you must specify a work area size"
|
||||
}
|
||||
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||
|
||||
riscv set_mem_access sysbus
|
||||
riscv set_enable_virt2phys off
|
||||
|
||||
$_TARGETNAME configure -work-area-phys $_WORKAREAADDR -work-area-size $_WORKAREASIZE -work-area-backup 1
|
||||
|
||||
# Internal RC ticks on 32 MHz, so this speed should be safe to use.
|
||||
adapter speed 8000
|
||||
|
||||
# Useful functions
|
||||
|
||||
set dmcontrol 0x10
|
||||
set dmcontrol_dmactive [expr {1 << 0}]
|
||||
set dmcontrol_ndmreset [expr {1 << 1}]
|
||||
set dmcontrol_resumereq [expr {1 << 30}]
|
||||
set dmcontrol_haltreq [expr {1 << 31}]
|
||||
|
||||
proc bl602_restore_clock_defaults { } {
|
||||
# Switch clock to internal RC32M
|
||||
# In HBN_GLB, set ROOT_CLK_SEL = 0
|
||||
mmw 0x4000f030 0x0 0x00000003
|
||||
# Wait for clock switch
|
||||
sleep 10
|
||||
|
||||
# GLB_REG_BCLK_DIS_FALSE
|
||||
mww 0x40000ffc 0x0
|
||||
|
||||
# HCLK is RC32M, so BCLK/HCLK doesn't need divider
|
||||
# In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0
|
||||
mmw 0x40000000 0x0 0x00FFFF00
|
||||
# Wait for clock to stabilize
|
||||
sleep 10
|
||||
}
|
||||
|
||||
# By spec, ndmreset should reset whole chip. This implementation resets only few parts of the chip.
|
||||
# CTRL_PWRON_RESET register in GLB core triggers full "power-on like" reset, so we use it instead
|
||||
# for full software reset.
|
||||
proc bl602_sw_reset { } {
|
||||
# In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET
|
||||
mmw 0x40000018 0x0 0x00000007
|
||||
|
||||
# This Software reset method resets everything, so CPU as well.
|
||||
# It does that in not much good way, resulting in Debug Module being reset as well.
|
||||
# This also means, that right after CPU and Debug Module are turned on, we need to
|
||||
# enable Debug Module and halt CPU if needed. Additionally, we trigger this SW reset
|
||||
# through system bus access directly with DMI commands, to avoid errors printed by
|
||||
# OpenOCD about unsuccessful register write.
|
||||
|
||||
# In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1
|
||||
riscv dmi_write 0x39 0x40000018
|
||||
riscv dmi_write 0x3c 0x7
|
||||
|
||||
# We need to wait for chip to finish reset and execute BootROM
|
||||
sleep 1
|
||||
|
||||
# JTAG Debug Transport Module is reset as well, so we need to get into RUN/IDLE state
|
||||
runtest 10
|
||||
|
||||
# We need to enable Debug Module and halt the CPU, so we can reset Program Counter
|
||||
# and to do additional clean-ups. If reset was called without halt, resume is handled
|
||||
# by reset-deassert-post event handler.
|
||||
|
||||
# In Debug Module Control (dmcontrol), set dmactive to 1 and then haltreq to 1
|
||||
riscv dmi_write $::dmcontrol $::dmcontrol_dmactive
|
||||
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_haltreq} ]
|
||||
|
||||
# Set Program Counter to start of BootROM
|
||||
set_reg {pc 0x21000000}
|
||||
}
|
||||
|
||||
# On BL602 and BL702, the only way to force chip stay in BootROM (until JTAG attaches)
|
||||
# is by putting infinity loop into HBN RAM (which is not reset by sw reset), and then
|
||||
# configure HBN registers, which will cause BootROM to jump into our code early in BootROM.
|
||||
proc bl602_sw_reset_hbn_wait {} {
|
||||
# Restore clocks to defaults
|
||||
bl602_restore_clock_defaults
|
||||
|
||||
# In HBN RAM, write infinity loop instruction
|
||||
# beq zero, zero, 0
|
||||
mww 0x40010000 0x00000063
|
||||
# In HNB, set HBN_RSV0 (Status Flag) to "EHBN" (as uint32_t)
|
||||
mww 0x4000f100 0x4e424845
|
||||
# In HBN, set HBN_RSV1 (WakeUp Address) to HBN RAM address
|
||||
mww 0x4000f104 0x40010000
|
||||
|
||||
# Perform software reset
|
||||
bl602_sw_reset
|
||||
|
||||
# Clear HBN RAM, HBN_RSV0 and HBN_RSV1
|
||||
mww 0x40010000 0x00000000
|
||||
mww 0x4000f100 0x00000000
|
||||
mww 0x4000f104 0x00000000
|
||||
|
||||
# This early jump method locks up BootROM through Trust Zone Controller.
|
||||
# That means any read of BootROM returns 0xDEADBEEF.
|
||||
# Only way to reset it, is through JTAG Reset, thus toggling ndmreset in dmcontrol.
|
||||
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_ndmreset} ]
|
||||
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive} ]
|
||||
}
|
||||
|
||||
$_TARGETNAME configure -event reset-deassert-post {
|
||||
# Resume the processor if reset was triggered without halt request
|
||||
if {$halt == 0} {
|
||||
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_resumereq} ]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user