Skip to content

Commit c986b4d

Browse files
gamelasterborneoa
authored andcommitted
tcl/target: add Bouffalo Lab BL602 and BL702L chip series support
BL602, BL702 and BL702L series of chips are sharing same architecture, so they all need same software reset mechanism as well. Only difference (in terms of configuration needed for JTAG) are TAP ID, workarea address and size. This is addressed by creating bl602_common.cfg tcl file, which contains all those common stuff between the chips. The script is prefixed by bl602, as this was first *publicly* available chip from Bouffalo with this architecture. This patch also improves reset mechanism. Previous reset mechanism did not worked properly when slower JTAG adapter was used (it attached too late). New reset mechanism uses various methods to keep CPU in BootROM, until the JTAG adapter does not attach again after reset. Additionally, we trigger SW Reset by directly using DMI commands to write to register with system bus method, to avoid getting error about unsuccessful write. The new method works on both FT232H (8MHz JTAG clock) and unnamed CMSIS-DAP dongle (1.5MHz JTAG clock). Change-Id: I5be3694927793fd3f64c9ed4ee6ded2db0d25cae Signed-off-by: Marek Kraus <[email protected]> Reviewed-on: https://review.openocd.org/c/openocd/+/8593 Tested-by: jenkins Reviewed-by: Antonio Borneo <[email protected]>
1 parent e142584 commit c986b4d

File tree

4 files changed

+234
-49
lines changed

4 files changed

+234
-49
lines changed

tcl/target/bl602.cfg

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
#
4+
# Bouffalo Labs BL602 and BL604 target
5+
#
6+
# https://en.bouffalolab.com/product/?type=detail&id=1
7+
#
8+
# Default JTAG pins: (if not changed by eFuse configuration)
9+
# TDO - GPIO11
10+
# TMS - GPIO12
11+
# TCK - GPIO14
12+
# TDI - GPIO17
13+
#
14+
15+
if { [info exists CHIPNAME] } {
16+
set BL602_CHIPNAME $CHIPNAME
17+
} else {
18+
set BL602_CHIPNAME bl602
19+
}
20+
21+
set CPUTAPID 0x20000c05
22+
23+
# For work-area we use DTCM instead of ITCM, due ITCM is used as buffer for L1 cache and XIP
24+
set WORKAREAADDR 0x42014000
25+
set WORKAREASIZE 0xC000
26+
27+
source [find target/bl602_common.cfg]
28+
29+
# JTAG reset is broken. Read comment of bl602_sw_reset_hbn_wait function for more information
30+
$_TARGETNAME configure -event reset-assert {
31+
halt
32+
33+
bl602_sw_reset_hbn_wait
34+
}

tcl/target/bl602_common.cfg

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
# Script for Bouffalo chips with similar architecture used in BL602
4+
# based on SiFive E21 core
5+
6+
source [find mem_helper.tcl]
7+
8+
transport select jtag
9+
10+
if { [info exists CPUTAPID ] } {
11+
set _CPUTAPID $CPUTAPID
12+
} else {
13+
error "you must specify a tap id"
14+
}
15+
16+
if { [info exists BL602_CHIPNAME] } {
17+
set _CHIPNAME $BL602_CHIPNAME
18+
} else {
19+
error "you must specify a chip name"
20+
}
21+
22+
if { [info exists WORKAREAADDR] } {
23+
set _WORKAREAADDR $WORKAREAADDR
24+
} else {
25+
error "you must specify a work area address"
26+
}
27+
28+
if { [info exists WORKAREASIZE] } {
29+
set _WORKAREASIZE $WORKAREASIZE
30+
} else {
31+
error "you must specify a work area size"
32+
}
33+
34+
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID
35+
36+
set _TARGETNAME $_CHIPNAME.cpu
37+
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
38+
39+
riscv set_mem_access sysbus
40+
riscv set_enable_virt2phys off
41+
42+
$_TARGETNAME configure -work-area-phys $_WORKAREAADDR -work-area-size $_WORKAREASIZE -work-area-backup 1
43+
44+
# Internal RC ticks on 32 MHz, so this speed should be safe to use.
45+
adapter speed 8000
46+
47+
# Useful functions
48+
49+
set dmcontrol 0x10
50+
set dmcontrol_dmactive [expr {1 << 0}]
51+
set dmcontrol_ndmreset [expr {1 << 1}]
52+
set dmcontrol_resumereq [expr {1 << 30}]
53+
set dmcontrol_haltreq [expr {1 << 31}]
54+
55+
proc bl602_restore_clock_defaults { } {
56+
# Switch clock to internal RC32M
57+
# In HBN_GLB, set ROOT_CLK_SEL = 0
58+
mmw 0x4000f030 0x0 0x00000003
59+
# Wait for clock switch
60+
sleep 10
61+
62+
# GLB_REG_BCLK_DIS_FALSE
63+
mww 0x40000ffc 0x0
64+
65+
# HCLK is RC32M, so BCLK/HCLK doesn't need divider
66+
# In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0
67+
mmw 0x40000000 0x0 0x00FFFF00
68+
# Wait for clock to stabilize
69+
sleep 10
70+
}
71+
72+
# By spec, ndmreset should reset whole chip. This implementation resets only few parts of the chip.
73+
# CTRL_PWRON_RESET register in GLB core triggers full "power-on like" reset, so we use it instead
74+
# for full software reset.
75+
proc bl602_sw_reset { } {
76+
# In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET
77+
mmw 0x40000018 0x0 0x00000007
78+
79+
# This Software reset method resets everything, so CPU as well.
80+
# It does that in not much good way, resulting in Debug Module being reset as well.
81+
# This also means, that right after CPU and Debug Module are turned on, we need to
82+
# enable Debug Module and halt CPU if needed. Additionally, we trigger this SW reset
83+
# through system bus access directly with DMI commands, to avoid errors printed by
84+
# OpenOCD about unsuccessful register write.
85+
86+
# In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1
87+
riscv dmi_write 0x39 0x40000018
88+
riscv dmi_write 0x3c 0x7
89+
90+
# We need to wait for chip to finish reset and execute BootROM
91+
sleep 1
92+
93+
# JTAG Debug Transport Module is reset as well, so we need to get into RUN/IDLE state
94+
runtest 10
95+
96+
# We need to enable Debug Module and halt the CPU, so we can reset Program Counter
97+
# and to do additional clean-ups. If reset was called without halt, resume is handled
98+
# by reset-deassert-post event handler.
99+
100+
# In Debug Module Control (dmcontrol), set dmactive to 1 and then haltreq to 1
101+
riscv dmi_write $::dmcontrol $::dmcontrol_dmactive
102+
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_haltreq} ]
103+
104+
# Set Program Counter to start of BootROM
105+
set_reg {pc 0x21000000}
106+
}
107+
108+
# On BL602 and BL702, the only way to force chip stay in BootROM (until JTAG attaches)
109+
# is by putting infinity loop into HBN RAM (which is not reset by sw reset), and then
110+
# configure HBN registers, which will cause BootROM to jump into our code early in BootROM.
111+
proc bl602_sw_reset_hbn_wait {} {
112+
# Restore clocks to defaults
113+
bl602_restore_clock_defaults
114+
115+
# In HBN RAM, write infinity loop instruction
116+
# beq zero, zero, 0
117+
mww 0x40010000 0x00000063
118+
# In HNB, set HBN_RSV0 (Status Flag) to "EHBN" (as uint32_t)
119+
mww 0x4000f100 0x4e424845
120+
# In HBN, set HBN_RSV1 (WakeUp Address) to HBN RAM address
121+
mww 0x4000f104 0x40010000
122+
123+
# Perform software reset
124+
bl602_sw_reset
125+
126+
# Clear HBN RAM, HBN_RSV0 and HBN_RSV1
127+
mww 0x40010000 0x00000000
128+
mww 0x4000f100 0x00000000
129+
mww 0x4000f104 0x00000000
130+
131+
# This early jump method locks up BootROM through Trust Zone Controller.
132+
# That means any read of BootROM returns 0xDEADBEEF.
133+
# Only way to reset it, is through JTAG Reset, thus toggling ndmreset in dmcontrol.
134+
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_ndmreset} ]
135+
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive} ]
136+
}
137+
138+
$_TARGETNAME configure -event reset-deassert-post {
139+
# Resume the processor if reset was triggered without halt request
140+
if {$halt == 0} {
141+
riscv dmi_write $::dmcontrol [ expr {$::dmcontrol_dmactive | $::dmcontrol_resumereq} ]
142+
}
143+
}

tcl/target/bl702.cfg

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -12,62 +12,23 @@
1212
# TDO - GPIO9
1313
#
1414

15-
source [find mem_helper.tcl]
16-
17-
transport select jtag
18-
1915
if { [info exists CHIPNAME] } {
20-
set _CHIPNAME $CHIPNAME
16+
set BL602_CHIPNAME $CHIPNAME
2117
} else {
22-
set _CHIPNAME bl702
18+
set BL602_CHIPNAME bl702
2319
}
2420

25-
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x20000e05
26-
27-
set _TARGETNAME $_CHIPNAME.cpu
28-
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
29-
30-
riscv set_mem_access sysbus
21+
set CPUTAPID 0x20000e05
3122

32-
$_TARGETNAME configure -work-area-phys 0x22020000 -work-area-size 0x10000 -work-area-backup 1
23+
# For work-area we use DTCM instead of ITCM, due ITCM is used as buffer for L1 cache and XIP
24+
set WORKAREAADDR 0x22014000
25+
set WORKAREASIZE 0xC000
3326

34-
# Internal RC ticks on 32 MHz, so this speed should be safe to use.
35-
adapter speed 4000
27+
source [find target/bl602_common.cfg]
3628

37-
# Debug Module's ndmreset resets only Trust Zone Controller, so we need to do SW reset instead.
38-
# CTRL_PWRON_RESET triggers full "power-on like" reset.
39-
# This means that pinmux configuration to access JTAG is reset as well, and configured back early
40-
# in BootROM.
41-
$_TARGETNAME configure -event reset-assert-pre {
29+
# JTAG reset is broken. Read comment of bl602_sw_reset_hbn_wait function for more information
30+
$_TARGETNAME configure -event reset-assert {
4231
halt
4332

44-
# Switch clock to internal RC32M
45-
# In HBN_GLB, set ROOT_CLK_SEL = 0
46-
mmw 0x4000f030 0x0 0x00000003
47-
# Wait for clock switch
48-
sleep 10
49-
50-
# GLB_REG_BCLK_DIS_FALSE
51-
mww 0x40000ffc 0x0
52-
53-
# HCLK is RC32M, so BCLK/HCLK doesn't need divider
54-
# In GLB_CLK_CFG0, set BCLK_DIV = 0 and HCLK_DIV = 0
55-
mmw 0x40000000 0x0 0x00FFFF00
56-
# Wait for clock to stabilize
57-
sleep 10
58-
59-
# Do reset
60-
# In GLB_SWRST_CFG2, clear CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET
61-
mmw 0x40000018 0x0 0x00000007
62-
63-
# Since this full software reset resets GPIO pinmux as well, we will lose access
64-
# to JTAG right away after writing to register. This chip doesn't support abstract
65-
# memory access, so when this is done by progbuf or sysbus, OpenOCD will fail to read
66-
# if write was successful or not, and will print error about that. Since receiving of
67-
# this error is expected, we will turn off log printing for a moment,
68-
set lvl [lindex [debug_level] 1]
69-
debug_level -1
70-
# In GLB_SWRST_CFG2, set CTRL_SYS_RESET, CTRL_CPU_RESET and CTRL_PWRON_RESET to 1
71-
catch {mmw 0x40000018 0x7 0x0}
72-
debug_level $lvl
33+
bl602_sw_reset_hbn_wait
7334
}

tcl/target/bl702l.cfg

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# SPDX-License-Identifier: GPL-2.0-or-later
2+
3+
#
4+
# Bouffalo Labs BL702L and BL704L target
5+
#
6+
# https://en.bouffalolab.com/product/?type=detail&id=26
7+
#
8+
# Default JTAG pins: (if not changed by eFuse configuration)
9+
# TMS - GPIO0
10+
# TDI - GPIO1
11+
# TCK - GPIO2
12+
# TDO - GPIO7
13+
#
14+
15+
if { [info exists CHIPNAME] } {
16+
set BL602_CHIPNAME $CHIPNAME
17+
} else {
18+
set BL602_CHIPNAME bl702l
19+
}
20+
21+
set CPUTAPID 0x20000e05
22+
23+
# For work-area we use beginning of OCRAM, since BL702L have only ITCM, which can be taken
24+
# by L1 cache and XIP during runtime.
25+
set WORKAREAADDR 0x42020000
26+
set WORKAREASIZE 0x10000
27+
28+
source [find target/bl602_common.cfg]
29+
30+
# JTAG reset is broken. Read comment of bl602_sw_reset function for more information
31+
# On BL702L, we are forcing boot into ISP mode, so chip stays in BootROM until JTAG re-attach
32+
$_TARGETNAME configure -event reset-assert {
33+
halt
34+
35+
# Restore clocks to defaults
36+
bl602_restore_clock_defaults
37+
38+
# In HBN_RSV2, set HBN_RELEASE_CORE to HBN_RELEASE_CORE_FLAG (4)
39+
# and HBN_USER_BOOT_SEL to 1 (ISP)
40+
mww 0x4000f108 0x44000000
41+
42+
# Perform software reset
43+
bl602_sw_reset
44+
45+
# Reset HBN_RSV2 so BootROM will not force ISP mode again
46+
mww 0x4000f108 0x00000000
47+
}

0 commit comments

Comments
 (0)