This file contains a compilation of various pieces of information about the BL602's hardware (e.g. core, peripherals, debug, memory map), gathered from the SDK repository and around the internet. This is the best we can do in lieu of a proper Technical Reference Manual, which has not yet been released as of this writing.
Contributions welcome!
According to soc602_reg.svd, the BL602 contains a RISC-V RV32IMAFC core. Interestingly, the datasheet and online spec sheets from Bouffalo Lab never mention RISC-V, simply calling the core a "32-bit RISC CPU."
CNX Software claims that the core is a SiFive E24. Although this claim is unsourced, information in the datasheet seems to corroborate it. The datasheet claims that the CPU achieves a Dhrystone score of 1.46 DMIPS/MHz and a CoreMark score of 3.1 CoreMark/MHz. These numbers exactly match what SiFive advertises for the E24. Similarly, the set of RISC-V extensions matches, as does the pipeline length (3-stage) and number of breakpoints/watchpoints (4).
The BL602 appears to diverge from the reference E24 implementation in its
memory map, however: its peripherals are mapped starting at 0x4000_0000
,
whereas SiFive's E24 Manual has a memory map placing peripherals at
0x2000_0000
(although these two regions alias one another on the BL602; see
below). Likewise, the BL602 maps its memories at 0x2000_0000
but the E24
reference design maps them at 0x6000_0000
. Finally, the BL602's TCMs are
differently-mapped, differently-named (TCM vs TIM), and differently-sized
(48KiB vs 32KiB) from the reference E24 ones. SiFive does claim that the memory
map and TIM sizes are customizable, though, so none of these differences are
strong evidence against the core being an E24.
clic.h, which is part of the BL602's register definition headers, appears to be a SiFive-authored file (see the include guard), and its addresses match the E24 reference. I think this is one of the clearest pieces of evidence for the core being SiFive IP.
The datasheet contains a memory map, as does soc602_reg.svd and bl602.h. As mentioned above, clic.h also contains part of the map. These sources have been synthesized into this unified table. (Accuracy is not guaranteed; please contribute a correction if you notice an error.)
The address ranges 0x2xxx_xxxx
, 0x3xxx_xxxx
, 0x4xxx_xxxx
, and
0x5xxx_xxxx
all appear to alias one another. 0x6xxx_xxxx
and
0x7xxx_xxxx
alias the same region for writes but cannot be written to (at
least not via JTAG), whereas all addresses 0x8000_0000
and above produce a
bus error for both writes and reads, indicating that the internal physical
memory bus is only 31 bits wide. The datasheet says that, for the TCMs and main
RAM, the 0x2xxx_xxxx
mappings are "used as program memory" and the
0x4xxx_xxxx
mappings are "used as data memory", but it is unclear why this is
or if the hardware makes any distinction between accesses via the various
mappings.
Base address | Top address | Name | Register description |
---|---|---|---|
0x0200_0000 |
0x027F_FFFF |
RISC-V CLINT | |
0x0280_0000 |
0x02FF_FFFF |
Hart 0 CLIC | |
0x2100_0000 |
0x2101_FFFF |
Mask ROM (holds boot and RomDriver code) | |
0x2200_8000 |
0x2201_3FFF |
ITCM (Instruction Tightly Coupled Memory) | |
0x2201_4000 |
0x2201_FFFF |
DTCM (Data Tightly Coupled Memory) | |
0x2202_0000 |
0x2202_FFFF |
Main RAM | |
0x2300_0000 |
0x23FF_FFFF |
XIP (eXecute In Place) flash mapping | |
0x4000_0000 |
0x4000_0FFF |
glb (global control registers) |
GLB |
0x4000_1000 |
0x4000_1FFF |
rf ("mixed signal"/radio) |
RF |
0x4000_2000 |
0x4000_2FFF |
gpip (ADC+DAC+analog comparator config) |
GPIP |
0x4000_3000 |
0x4000_3FFF |
sec_dbg (secure debug?) |
SEC_DBG |
0x4000_4000 |
0x4000_4FFF |
sec_eng (security engine, e.g. SHA+AES) |
SEC_ENG |
0x4000_5000 |
0x4000_5FFF |
tzc_sec ("trust isolation" #1) |
TZC_SEC |
0x4000_6000 |
0x4000_6FFF |
tzc_nsec ("trust isolation" #2) |
TZC_NSEC |
0x4000_7000 |
0x4000_707F |
ef_data_0 (eFuse data #1) |
EF_DATA_0 |
0x4000_7080 |
0x4000_70FF |
ef_data_1 (eFuse data #2) |
EF_DATA_1 |
0x4000_7800 |
0x4000_7FFF |
ef_ctrl (eFuse control) |
EF_CTRL |
0x4000_8000 |
0x4000_8FFF |
cci (???) |
CCI |
0x4000_9000 |
0x4000_9FFF |
l1c (cache control) |
L1C |
0x4000_A000 |
0x4000_A0FF |
uart0 (UART #1) |
UART |
0x4000_A100 |
0x4000_A1FF |
uart1 (UART #2) |
UART |
0x4000_A200 |
0x4000_A2FF |
spi (Serial Peripheral Interface) |
SPI |
0x4000_A300 |
0x4000_A3FF |
i2c (I2C) |
I2C |
0x4000_A400 |
0x4000_A4FF |
pwm (Pulse Width Modulation #1-#6) |
PWM |
0x4000_A500 |
0x4000_A5FF |
timer (Timer #1 and #2) |
TIMER |
0x4000_A600 |
0x4000_A6FF |
ir (infrared remote accelerator) |
IR |
0x4000_A700 |
0x4000_A7FF |
cks (checksum engine) |
CKS |
0x4000_B000 |
0x4000_B6FF |
sf_ctrl (serial flash control) |
SF_CTRL |
0x4000_B700 |
0x4000_BFFF |
sf_ctrl_buf (serial flash data buffer) |
|
0x4000_C000 |
0x4000_CFFF |
dma (Direct Memory Access engine) |
DMA |
0x4000_D000 |
0x4000_DFFF |
sdu (SDIO slave controller) |
|
0x4000_E000 |
0x4000_EFFF |
pds (Power Down Sleep/sleep control) |
PDS |
0x4000_F000 |
0x4000_F7FF |
hbn (Hibernate/deep sleep control) |
HBN |
0x4000_F800 |
0x4000_FFFF |
aon (Always-ON peripheral control) |
AON |
0x4001_0000 |
0x4001_0FFF |
Deep sleep retention RAM | |
0x4203_0000 |
0x4204_BFFF |
Wireless RAM | |
0x44b0_0000 |
0x44b0_???? |
mm (MAC management), txl , rxl and ps (undocumented WiFi/BLE, see mm_init ) |
|
0x44c0_0000 |
0x44c?_???? |
wifi phy (identified from phy_init ) (has many wifi related modules including agc ) |
PHY |
0x54c0_a000 |
0x54c0_???? |
agc ucode (identified from phy_init ) |
(Peripherals in italics
are present in the SVD but not the datasheet.)
bl602.h defines three extra mappings, labeled REMAP0, REMAP1, and REMAP2, in
addition to the ranges in the datasheet for each of flash XIP, main+wireless
RAM, and the TCMs. This appears to reflect the above-stated fact that
0x2xxx_xxxx
, 0x3xxx_xxxx
, and 0x4xxx_xxxx
alias one another, but
unfortunately the names give no hint to if or how the mappings differ. The
remap base addresses are as follows:
Memory | "Normal" base | REMAP0 base | REMAP1 base | REMAP2 base |
---|---|---|---|---|
XIP | 0x2300_0000 |
0x3300_0000 |
0x4300_0000 |
0x5300_0000 |
WRAM | 0x4202_0000 |
0x2202_0000 |
0x3202_0000 |
0x5202_0000 |
TCM | 0x2200_8000 |
0x3200_8000 |
0x4200_8000 |
0x5200_8000 |
Note that the "WRAM" mapping in bl602.h, which starts at 0x4202_0000
and goes
to 0x4204_C000
, is badly named. It encompasses all of main RAM and all of
wireless RAM (but not the TCMs), instead of just wireless RAM like its name
implies.
The datasheet claims that the system has 276KiB of RAM, and indeed that is the number we get by adding up 64KiB of main RAM, 112KiB of wireless RAM, 48KiB of instruction TCM, 48KiB of data TCM, and 4KiB of deep sleep retention RAM.
The BL602 has 128KiB of "ROM," mapped at 0x2100_0000
. As far as I can tell,
this is an actual Mask ROM that's hardwired at the factory, not a flash or an
EEPROM. What immutable data could take up 128KiB? Code, it appears! In the
OpenOCD configuration for the BL602, pc
is forced to the start of the
ROM after reset. Therefore, it seems likely that the beginning of the ROM holds
a BootROM which implements the various boot modes ("UART, SDIO, and Flash")
listed in the datasheet.
But that's not all that's in the ROM. There's an interesting peripheral driver
called RomDriver, which exposes a number of functions for global register
configuration, power+clock+sleep management, serial flash setup, and general
operations like delay and memcpy. However, none of the functions are actually
implemented by the driver! Instead, it forwards each call to a corresponding
function pointer in a table at 0x2101_0800
, which is within the ROM. I assume
the function pointers in that table are also ROM addresses, meaning the bulk
of the ROM is likely taken up by library code. The SDK has a macro called
BL602_USE_ROM_DRIVER
which selects whether to use the ROM implementation of
functions when available.
Registers in the TZ ("trust isolation") peripherals reference a ROM (for
example, tzc_rom0_r0_lock
). This could indicate that areas of the ROM need
protection from unauthorized reads. Perhaps the ROM holds factory-provisioned,
per-device keys that are used as part of the secure boot flow? This, however,
is purely speculation.
Here are the known areas of the ROM's memory map:
Base address | Top address | Name |
---|---|---|
0x2100_0000 |
0x2101_07FF |
BootROM (+ other stuff?) |
0x2101_0800 |
0x2101_0FFF |
RomDriver function table |
0x2101_1000 |
0x2101_FFFF |
RomDriver functions (+ other stuff?) |
The BL602's RF stack is mostly based on CEVA RivieraWaves reference platform. The PHY is custom by Bouffalolab, but implements the standard RivieraWaves PHY. Luckily almost all the source code is publicy available in different SDKs. The RivieraWaves code has been published here and the custom Bouffalolab PHY here. Some auxiliary code is also in either one of these repos. Together they cover most source in the demo binary.