Skip to content

Commit acfd97b

Browse files
committed
PolarFire SoC M-Mode Support with SC QSPI Flash
1 parent 3be63df commit acfd97b

File tree

15 files changed

+1893
-251
lines changed

15 files changed

+1893
-251
lines changed

.github/workflows/test-configs.yml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,16 @@ jobs:
272272
with:
273273
arch: riscv64
274274
config-file: ./config/examples/polarfire_mpfs250.config
275-
# Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv64imafd_zicsr_zmmul_zaamo_zalrsc'/'-mabi=lp64d')
276-
# Consider building cached RISCV64 toolchain for this target
277-
make-args: wolfboot.bin
275+
microchip_mpfs250_qspi_test:
276+
uses: ./.github/workflows/test-build-riscv.yml
277+
with:
278+
arch: riscv64
279+
config-file: ./config/examples/polarfire_mpfs250_qspi.config
280+
microchip_mpfs250_m_qspi_test:
281+
uses: ./.github/workflows/test-build-riscv.yml
282+
with:
283+
arch: riscv64
284+
config-file: ./config/examples/polarfire_mpfs250_m_qspi.config
278285

279286
raspi3_test:
280287
uses: ./.github/workflows/test-build.yml

arch.mk

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,17 @@ endif
581581
## RISCV64 (64-bit)
582582
ifeq ($(ARCH),RISCV64)
583583
CROSS_COMPILE?=riscv64-unknown-elf-
584-
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
584+
585+
# M-mode vs S-mode configuration
586+
ifeq ($(RISCV_MMODE),1)
587+
# Machine Mode: Running directly from eNVM/L2 SRAM
588+
CFLAGS+=-DWOLFBOOT_RISCV_MMODE -DWOLFBOOT_DUALBOOT
589+
# Use M-mode specific linker script
590+
LSCRIPT_IN:=hal/$(TARGET)-m.ld
591+
else
592+
# Supervisor Mode (default): Running under HSS with DDR available
593+
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
594+
endif
585595

586596
# If SD card or eMMC is enabled use update_disk loader with GPT support
587597
ifneq ($(filter 1,$(DISK_SDCARD) $(DISK_EMMC)),)
@@ -595,7 +605,17 @@ ifeq ($(ARCH),RISCV64)
595605
UPDATE_OBJS?=src/update_ram.o
596606
endif
597607

598-
ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany
608+
ifeq ($(RISCV_MMODE),1)
609+
# E51 core: rv64imac (no FPU, no crypto extensions)
610+
ARCH_FLAGS=-march=rv64imac -mabi=lp64 -mcmodel=medany
611+
else
612+
# U54 cores: rv64gc (with FPU)
613+
ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany
614+
615+
# FDT support required
616+
CFLAGS+=-DWOLFBOOT_FDT
617+
OBJS+=src/fdt.o
618+
endif
599619
CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV -DARCH_RISCV64
600620
CFLAGS+=$(ARCH_FLAGS)
601621
LDFLAGS+=$(ARCH_FLAGS)
@@ -607,9 +627,6 @@ ifeq ($(ARCH),RISCV64)
607627
# Unified RISC-V boot code (32/64-bit via __riscv_xlen)
608628
OBJS+=src/boot_riscv_start.o src/boot_riscv.o src/vector_riscv.o
609629

610-
CFLAGS+=-DWOLFBOOT_FDT
611-
OBJS+=src/fdt.o
612-
613630
ifeq ($(SPMATH),1)
614631
MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c64.o
615632
endif

config/examples/polarfire_mpfs250.config

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ CFLAGS_EXTRA+=-DBOOT_PART_B=2
6767
# Speed up disk partition read (512KB chunks - max DMA size)
6868
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000
6969

70-
# DTS (Device Tree)
70+
# DTS (Device Tree) load address
7171
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000
7272

7373
# Optional Encryption
@@ -77,7 +77,7 @@ WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000
7777
#OBJS_EXTRA=src/my_custom_encrypt_key.o
7878

7979
# Optional EMMC_SD debugging logs
80-
#CFLAGS_EXTRA+=-DDEBUG_MMC
80+
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
8181
# Optional disk debugging logs
8282
#CFLAGS_EXTRA+=-DDEBUG_DISK
8383
#CFLAGS_EXTRA+=-DDISK_TEST
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# PolarFire SoC MPFS250T M-Mode (Machine Mode) with SC QSPI Flash
2+
#
3+
# This configuration runs wolfBoot directly from eNVM in M-mode (Machine Mode),
4+
# and boots a test application from SC QSPI flash to on-chip LIM (no DDR).
5+
#
6+
# Boot flow:
7+
# 1. eNVM (0x20220100) -> L2_SCRATCH (0x0A000000) - wolfBoot starts
8+
# 2. Load signed app image from SC QSPI flash to LIM (0x08000000)
9+
# 3. Verify signature and boot
10+
#
11+
# Flash using mpfsBootmodeProgrammer (bootmode 1):
12+
# java -jar mpfsBootmodeProgrammer.jar --bootmode 1 --die MPFS250T \
13+
# --package FCG1152 --workdir $PWD wolfboot.elf
14+
15+
ARCH?=RISCV64
16+
TARGET?=mpfs250
17+
SIGN?=ECC384
18+
HASH?=SHA384
19+
IMAGE_HEADER_SIZE=512
20+
WOLFBOOT_VERSION?=1
21+
ARMORED?=0
22+
DEBUG?=0
23+
DEBUG_SYMBOLS?=1
24+
DEBUG_UART?=1
25+
VTOR?=1
26+
NO_XIP?=1
27+
NVM_FLASH_WRITEONCE?=0
28+
UART_FLASH?=0
29+
V?=0
30+
NO_MPU?=1
31+
RAM_CODE?=0
32+
SPMATH?=0
33+
SPMATHALL?=1
34+
DUALBANK_SWAP?=0
35+
PKA?=0
36+
ENCRYPT=0
37+
WOLFTPM?=0
38+
ELF?=1
39+
#DEBUG_ELF?=1
40+
41+
OPTIMIZATION_LEVEL=1
42+
43+
# M-Mode Configuration
44+
# Runs on E51 core in Machine Mode from L2 SRAM
45+
RISCV_MMODE?=1
46+
47+
# Stack size per hart (reduced for L2 SRAM constraints)
48+
CFLAGS_EXTRA+=-DSTACK_SIZE_PER_HART=8192
49+
50+
# E51 core lacks RISC-V crypto extensions (Zknh), use portable C implementations
51+
NO_ASM?=1
52+
53+
# QSPI Flash Configuration
54+
# Using Micron MT25QL01GBBB (128MB, 64KB sectors)
55+
EXT_FLASH?=1
56+
SPI_FLASH?=0
57+
58+
# SPI Flash Controller Selection:
59+
# MPFS_SC_SPI: Use SC QSPI Controller (0x37020100) for fabric-connected flash.
60+
# Direct register access to System Controller's QSPI instance.
61+
# DEFAULT: Use MSS QSPI Controller (0x21000000) for external flash
62+
# on MSS QSPI pins.
63+
CFLAGS_EXTRA+=-DMPFS_SC_SPI
64+
65+
# No SD card or eMMC
66+
DISK_SDCARD?=0
67+
DISK_EMMC?=0
68+
69+
# L2 SRAM Address for wolfBoot (256KB available)
70+
# Stack grows down from end of L2_SCRATCH
71+
WOLFBOOT_ORIGIN?=0x0A000000
72+
73+
# Load application to LIM (Loosely Integrated Memory, 2MB)
74+
# Note: update_ram places header at (LOAD_ADDRESS - IMAGE_HEADER_SIZE),
75+
# so offset by header size to keep everything within LIM (starts at 0x08000000)
76+
WOLFBOOT_LOAD_ADDRESS?=0x08000200
77+
78+
# Flash geometry (64 KB sector to match QSPI flash)
79+
WOLFBOOT_SECTOR_SIZE?=0x10000
80+
81+
# Partition layout for 128MB QSPI flash
82+
# Boot partition: 0x00020000 - 0x01FFFFFF (~32MB)
83+
# Update partition: 0x02000000 - 0x03FFFFFF (~32MB)
84+
# Swap partition: 0x04000000 - 0x0400FFFF (64KB)
85+
WOLFBOOT_PARTITION_SIZE?=0x1FE0000
86+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000
87+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x2000000
88+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x4000000
89+
90+
# Speed up reads from flash by using larger blocks
91+
CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096
92+
93+
# Debug options (useful for initial M-mode bring-up)
94+
#CFLAGS_EXTRA+=-DDEBUG_BOOT
95+
96+
# Optional QSPI debugging
97+
# Uncomment for verbose QSPI debug output
98+
#CFLAGS_EXTRA+=-DDEBUG_QSPI
99+
100+
# Optional QSPI flash test (erase/write/read on update partition)
101+
# Uncomment to run test during hal_init()
102+
#CFLAGS_EXTRA+=-DTEST_EXT_FLASH

docs/Targets.md

Lines changed: 101 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -797,9 +797,10 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1×
797797

798798
### PolarFire SoC Files
799799

800-
`hal/mpfs250.c` - Hardware abstraction layer implementation (UART and uSD)
800+
`hal/mpfs250.c` - Hardware abstraction layer (UART, QSPI, SD/eMMC, multi-hart)
801801
`hal/mpfs250.h` - Register definitions and hardware interfaces
802-
`hal/mpfs250.ld` - Linker script for the platform
802+
`hal/mpfs250.ld` - Linker script for S-mode (HSS-based boot)
803+
`hal/mpfs250-m.ld` - Linker script for M-mode (eNVM + L2 SRAM)
803804
`hal/mpfs.dts` - Device tree source
804805
`hal/mpfs.yaml` - HSS payload generator configuration
805806
`hal/mpfs250.its` - Example FIT image creation template
@@ -1363,11 +1364,105 @@ ML-DSA 87 verify 200 ops took 1.077 sec, avg 5.385 ms, 185.704 ops/
13631364
Benchmark complete
13641365
```
13651366
1366-
### PolarFire TODO
1367+
### PolarFire Machine Mode (M-Mode) Support
13671368
1368-
* Add support for full HSS replacement using wolfboot
1369-
- Machine level assembly startup
1370-
- DDR driver
1369+
wolfBoot supports running directly in Machine Mode (M-mode) on PolarFire SoC,
1370+
replacing the Hart Software Services (HSS) as the first-stage bootloader. In
1371+
M-mode, wolfBoot runs on the E51 monitor core and loads a signed application
1372+
from SC QSPI flash to on-chip LIM (Loosely Integrated Memory).
1373+
1374+
#### M-Mode Features
1375+
1376+
* Runs on E51 monitor core (hart 0) directly from eNVM
1377+
* Executes from L2 Scratchpad SRAM (256KB at 0x0A000000)
1378+
* Loads signed application from SC QSPI flash to LIM (0x08000000)
1379+
* No HSS or DDR required — boots entirely from on-chip memory
1380+
* Wakes and manages secondary U54 harts via IPI
1381+
* Per-hart UART output (each hart uses its own MMUART)
1382+
* ECC384 + SHA384 signature verification
1383+
1384+
#### M-Mode Files
1385+
1386+
| File | Description |
1387+
|------|-------------|
1388+
| `config/examples/polarfire_mpfs250_m_qspi.config` | M-mode + SC QSPI configuration |
1389+
| `hal/mpfs250-m.ld` | M-mode linker script (eNVM + L2 SRAM) |
1390+
| `hal/mpfs250.c` | HAL with QSPI driver, UART, L2 cache init |
1391+
| `src/boot_riscv_start.S` | M-mode assembly startup |
1392+
1393+
#### Building for M-Mode
1394+
1395+
```sh
1396+
# Copy M-mode QSPI configuration
1397+
cp config/examples/polarfire_mpfs250_m_qspi.config .config
1398+
1399+
# Build wolfBoot and signed test-app
1400+
make clean
1401+
make
1402+
```
1403+
1404+
This produces:
1405+
- `wolfboot.elf` — bootloader for eNVM (~26KB)
1406+
- `test-app/image_v1_signed.bin` — signed application for QSPI flash
1407+
1408+
#### Flashing
1409+
1410+
M-mode requires programming two targets:
1411+
1412+
1. **eNVM** (wolfBoot): Programmed via JTAG using mpfsBootmodeProgrammer (bootmode 1)
1413+
2. **QSPI flash** (signed application): Programmed via Libero/FPExpress SPI programming
1414+
1415+
```sh
1416+
# Set SoftConsole installation directory
1417+
export SC_INSTALL_DIR=/opt/Microchip/SoftConsole-v2022.2-RISC-V-747
1418+
1419+
# Flash wolfboot.elf to eNVM
1420+
$SC_INSTALL_DIR/eclipse/jre/bin/java -jar \
1421+
$SC_INSTALL_DIR/extras/mpfs/mpfsBootmodeProgrammer.jar \
1422+
--bootmode 1 --die MPFS250T --package FCG1152 --workdir $PWD wolfboot.elf
1423+
1424+
# Flash test-app/image_v1_signed.bin to QSPI at offset 0x20000
1425+
# (use Libero SoC Design Suite SPI flash programming)
1426+
```
1427+
1428+
#### M-Mode Boot Flow
1429+
1430+
1. **eNVM Reset Vector** (0x20220100): CPU starts, copies code to L2 SRAM
1431+
2. **L2 SRAM Execution** (0x0A000000): wolfBoot runs from scratchpad
1432+
3. **Hardware Init**: L2 cache configuration, UART setup
1433+
4. **QSPI Init**: SC QSPI controller (0x37020100), JEDEC ID read, 4-byte address mode
1434+
5. **Image Load**: Read signed image from QSPI flash (0x20000) to LIM (0x08000200)
1435+
6. **Verify & Boot**: SHA384 integrity check, ECC384 signature verification, jump to app
1436+
1437+
#### M-Mode QSPI Partition Layout
1438+
1439+
The SC QSPI flash (Micron MT25QL01G, 128MB) is partitioned as:
1440+
1441+
| Region | Address | Size |
1442+
|--------|---------|------|
1443+
| Boot partition | 0x00020000 | ~32MB |
1444+
| Update partition | 0x02000000 | ~32MB |
1445+
| Swap partition | 0x04000000 | 64KB |
1446+
1447+
#### M-Mode UART Mapping
1448+
1449+
| Hart | Core | MMUART | USB Device |
1450+
|------|------|--------|------------|
1451+
| 0 | E51 | MMUART0 | /dev/ttyUSB0 |
1452+
| 1 | U54_1 | MMUART1 | /dev/ttyUSB1 |
1453+
| 2 | U54_2 | MMUART2 | N/A |
1454+
| 3 | U54_3 | MMUART3 | N/A |
1455+
| 4 | U54_4 | MMUART4 | N/A |
1456+
1457+
#### M-Mode Notes
1458+
1459+
* The E51 core is rv64imac (no FPU or crypto extensions). wolfBoot is compiled
1460+
with `NO_ASM=1` to use portable C crypto implementations and
1461+
`-march=rv64imac -mabi=lp64` for correct code generation.
1462+
* CLINT MTIME counter is not running in bare-metal M-mode (no HSS), so
1463+
`udelay()` uses a calibrated busy loop instead of the timer CSR.
1464+
* DDR initialization support is available on the `polarfire_ddr` branch for
1465+
use cases that require loading larger applications to DDR memory.
13711466
13721467
13731468
## STM32F7

0 commit comments

Comments
 (0)