Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions .github/workflows/test-configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,16 @@ jobs:
with:
arch: riscv64
config-file: ./config/examples/polarfire_mpfs250.config
# Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv64imafd_zicsr_zmmul_zaamo_zalrsc'/'-mabi=lp64d')
# Consider building cached RISCV64 toolchain for this target
make-args: wolfboot.bin
microchip_mpfs250_qspi_test:
uses: ./.github/workflows/test-build-riscv.yml
with:
arch: riscv64
config-file: ./config/examples/polarfire_mpfs250_qspi.config
microchip_mpfs250_m_qspi_test:
uses: ./.github/workflows/test-build-riscv.yml
with:
arch: riscv64
config-file: ./config/examples/polarfire_mpfs250_m_qspi.config

raspi3_test:
uses: ./.github/workflows/test-build.yml
Expand Down
27 changes: 22 additions & 5 deletions arch.mk
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,17 @@ endif
## RISCV64 (64-bit)
ifeq ($(ARCH),RISCV64)
CROSS_COMPILE?=riscv64-unknown-elf-
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT

# M-mode vs S-mode configuration
ifeq ($(RISCV_MMODE),1)
# Machine Mode: Running directly from eNVM/L2 SRAM
CFLAGS+=-DWOLFBOOT_RISCV_MMODE -DWOLFBOOT_DUALBOOT
# Use M-mode specific linker script
LSCRIPT_IN:=hal/$(TARGET)-m.ld
else
# Supervisor Mode (default): Running under HSS with DDR available
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
endif

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

ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany
ifeq ($(RISCV_MMODE),1)
# E51 core: rv64imac (no FPU, no crypto extensions)
ARCH_FLAGS=-march=rv64imac -mabi=lp64 -mcmodel=medany
else
# U54 cores: rv64gc (with FPU)
ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany

# FDT support required
CFLAGS+=-DWOLFBOOT_FDT
OBJS+=src/fdt.o
endif
CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV -DARCH_RISCV64
CFLAGS+=$(ARCH_FLAGS)
LDFLAGS+=$(ARCH_FLAGS)
Expand All @@ -607,9 +627,6 @@ ifeq ($(ARCH),RISCV64)
# Unified RISC-V boot code (32/64-bit via __riscv_xlen)
OBJS+=src/boot_riscv_start.o src/boot_riscv.o src/vector_riscv.o

CFLAGS+=-DWOLFBOOT_FDT
OBJS+=src/fdt.o

ifeq ($(SPMATH),1)
MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c64.o
endif
Expand Down
4 changes: 2 additions & 2 deletions config/examples/polarfire_mpfs250.config
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ CFLAGS_EXTRA+=-DBOOT_PART_B=2
# Speed up disk partition read (512KB chunks - max DMA size)
CFLAGS_EXTRA+=-DDISK_BLOCK_SIZE=0x80000

# DTS (Device Tree)
# DTS (Device Tree) load address
WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000

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

# Optional EMMC_SD debugging logs
#CFLAGS_EXTRA+=-DDEBUG_MMC
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
# Optional disk debugging logs
#CFLAGS_EXTRA+=-DDEBUG_DISK
#CFLAGS_EXTRA+=-DDISK_TEST
Expand Down
102 changes: 102 additions & 0 deletions config/examples/polarfire_mpfs250_m_qspi.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# PolarFire SoC MPFS250T M-Mode (Machine Mode) with SC QSPI Flash
#
# This configuration runs wolfBoot directly from eNVM in M-mode (Machine Mode),
# and boots a test application from SC QSPI flash to on-chip LIM (no DDR).
#
# Boot flow:
# 1. eNVM (0x20220100) -> L2_SCRATCH (0x0A000000) - wolfBoot starts
# 2. Load signed app image from SC QSPI flash to LIM (0x08000000)
# 3. Verify signature and boot
#
# Flash using mpfsBootmodeProgrammer (bootmode 1):
# java -jar mpfsBootmodeProgrammer.jar --bootmode 1 --die MPFS250T \
# --package FCG1152 --workdir $PWD wolfboot.elf

ARCH?=RISCV64
TARGET?=mpfs250
SIGN?=ECC384
HASH?=SHA384
IMAGE_HEADER_SIZE=512
WOLFBOOT_VERSION?=1
ARMORED?=0
DEBUG?=0
DEBUG_SYMBOLS?=1
DEBUG_UART?=1
VTOR?=1
NO_XIP?=1
NVM_FLASH_WRITEONCE?=0
UART_FLASH?=0
V?=0
NO_MPU?=1
RAM_CODE?=0
SPMATH?=0
SPMATHALL?=1
DUALBANK_SWAP?=0
PKA?=0
ENCRYPT=0
WOLFTPM?=0
ELF?=1
#DEBUG_ELF?=1

OPTIMIZATION_LEVEL=1

# M-Mode Configuration
# Runs on E51 core in Machine Mode from L2 SRAM
RISCV_MMODE?=1

# Stack size per hart (reduced for L2 SRAM constraints)
CFLAGS_EXTRA+=-DSTACK_SIZE_PER_HART=8192

# E51 core lacks RISC-V crypto extensions (Zknh), use portable C implementations
NO_ASM?=1

# QSPI Flash Configuration
# Using Micron MT25QL01GBBB (128MB, 64KB sectors)
EXT_FLASH?=1
SPI_FLASH?=0

# SPI Flash Controller Selection:
# MPFS_SC_SPI: Use SC QSPI Controller (0x37020100) for fabric-connected flash.
# Direct register access to System Controller's QSPI instance.
# DEFAULT: Use MSS QSPI Controller (0x21000000) for external flash
# on MSS QSPI pins.
CFLAGS_EXTRA+=-DMPFS_SC_SPI

# No SD card or eMMC
DISK_SDCARD?=0
DISK_EMMC?=0

# L2 SRAM Address for wolfBoot (256KB available)
# Stack grows down from end of L2_SCRATCH
WOLFBOOT_ORIGIN?=0x0A000000

# Load application to LIM (Loosely Integrated Memory, 2MB)
# Note: update_ram places header at (LOAD_ADDRESS - IMAGE_HEADER_SIZE),
# so offset by header size to keep everything within LIM (starts at 0x08000000)
WOLFBOOT_LOAD_ADDRESS?=0x08000200

# Flash geometry (64 KB sector to match QSPI flash)
WOLFBOOT_SECTOR_SIZE?=0x10000

# Partition layout for 128MB QSPI flash
# Boot partition: 0x00020000 - 0x01FFFFFF (~32MB)
# Update partition: 0x02000000 - 0x03FFFFFF (~32MB)
# Swap partition: 0x04000000 - 0x0400FFFF (64KB)
WOLFBOOT_PARTITION_SIZE?=0x1FE0000
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x2000000
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x4000000

# Speed up reads from flash by using larger blocks
CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096

# Debug options (useful for initial M-mode bring-up)
#CFLAGS_EXTRA+=-DDEBUG_BOOT

# Optional QSPI debugging
# Uncomment for verbose QSPI debug output
#CFLAGS_EXTRA+=-DDEBUG_QSPI

# Optional QSPI flash test (erase/write/read on update partition)
# Uncomment to run test during hal_init()
#CFLAGS_EXTRA+=-DTEST_EXT_FLASH
107 changes: 101 additions & 6 deletions docs/Targets.md
Original file line number Diff line number Diff line change
Expand Up @@ -797,9 +797,10 @@ The PolarFire SoC is a 64-bit RISC-V SoC featuring a five-core CPU cluster (1×

### PolarFire SoC Files

`hal/mpfs250.c` - Hardware abstraction layer implementation (UART and uSD)
`hal/mpfs250.c` - Hardware abstraction layer (UART, QSPI, SD/eMMC, multi-hart)
`hal/mpfs250.h` - Register definitions and hardware interfaces
`hal/mpfs250.ld` - Linker script for the platform
`hal/mpfs250.ld` - Linker script for S-mode (HSS-based boot)
`hal/mpfs250-m.ld` - Linker script for M-mode (eNVM + L2 SRAM)
`hal/mpfs.dts` - Device tree source
`hal/mpfs.yaml` - HSS payload generator configuration
`hal/mpfs250.its` - Example FIT image creation template
Expand Down Expand Up @@ -1363,11 +1364,105 @@ ML-DSA 87 verify 200 ops took 1.077 sec, avg 5.385 ms, 185.704 ops/
Benchmark complete
```

### PolarFire TODO
### PolarFire Machine Mode (M-Mode) Support

* Add support for full HSS replacement using wolfboot
- Machine level assembly startup
- DDR driver
wolfBoot supports running directly in Machine Mode (M-mode) on PolarFire SoC,
replacing the Hart Software Services (HSS) as the first-stage bootloader. In
M-mode, wolfBoot runs on the E51 monitor core and loads a signed application
from SC QSPI flash to on-chip LIM (Loosely Integrated Memory).

#### M-Mode Features

* Runs on E51 monitor core (hart 0) directly from eNVM
* Executes from L2 Scratchpad SRAM (256KB at 0x0A000000)
* Loads signed application from SC QSPI flash to LIM (0x08000000)
* No HSS or DDR required — boots entirely from on-chip memory
* Wakes and manages secondary U54 harts via IPI
* Per-hart UART output (each hart uses its own MMUART)
* ECC384 + SHA384 signature verification

#### M-Mode Files

| File | Description |
|------|-------------|
| `config/examples/polarfire_mpfs250_m_qspi.config` | M-mode + SC QSPI configuration |
| `hal/mpfs250-m.ld` | M-mode linker script (eNVM + L2 SRAM) |
| `hal/mpfs250.c` | HAL with QSPI driver, UART, L2 cache init |
| `src/boot_riscv_start.S` | M-mode assembly startup |

#### Building for M-Mode

```sh
# Copy M-mode QSPI configuration
cp config/examples/polarfire_mpfs250_m_qspi.config .config

# Build wolfBoot and signed test-app
make clean
make
```

This produces:
- `wolfboot.elf` — bootloader for eNVM (~26KB)
- `test-app/image_v1_signed.bin` — signed application for QSPI flash

#### Flashing

M-mode requires programming two targets:

1. **eNVM** (wolfBoot): Programmed via JTAG using mpfsBootmodeProgrammer (bootmode 1)
2. **QSPI flash** (signed application): Programmed via Libero/FPExpress SPI programming

```sh
# Set SoftConsole installation directory
export SC_INSTALL_DIR=/opt/Microchip/SoftConsole-v2022.2-RISC-V-747

# Flash wolfboot.elf to eNVM
$SC_INSTALL_DIR/eclipse/jre/bin/java -jar \
$SC_INSTALL_DIR/extras/mpfs/mpfsBootmodeProgrammer.jar \
--bootmode 1 --die MPFS250T --package FCG1152 --workdir $PWD wolfboot.elf

# Flash test-app/image_v1_signed.bin to QSPI at offset 0x20000
# (use Libero SoC Design Suite SPI flash programming)
```

#### M-Mode Boot Flow

1. **eNVM Reset Vector** (0x20220100): CPU starts, copies code to L2 SRAM
2. **L2 SRAM Execution** (0x0A000000): wolfBoot runs from scratchpad
3. **Hardware Init**: L2 cache configuration, UART setup
4. **QSPI Init**: SC QSPI controller (0x37020100), JEDEC ID read, 4-byte address mode
5. **Image Load**: Read signed image from QSPI flash (0x20000) to LIM (0x08000200)
6. **Verify & Boot**: SHA384 integrity check, ECC384 signature verification, jump to app

#### M-Mode QSPI Partition Layout

The SC QSPI flash (Micron MT25QL01G, 128MB) is partitioned as:

| Region | Address | Size |
|--------|---------|------|
| Boot partition | 0x00020000 | ~32MB |
| Update partition | 0x02000000 | ~32MB |
| Swap partition | 0x04000000 | 64KB |

#### M-Mode UART Mapping

| Hart | Core | MMUART | USB Device |
|------|------|--------|------------|
| 0 | E51 | MMUART0 | /dev/ttyUSB0 |
| 1 | U54_1 | MMUART1 | /dev/ttyUSB1 |
| 2 | U54_2 | MMUART2 | N/A |
| 3 | U54_3 | MMUART3 | N/A |
| 4 | U54_4 | MMUART4 | N/A |

#### M-Mode Notes

* The E51 core is rv64imac (no FPU or crypto extensions). wolfBoot is compiled
with `NO_ASM=1` to use portable C crypto implementations and
`-march=rv64imac -mabi=lp64` for correct code generation.
* CLINT MTIME counter is not running in bare-metal M-mode (no HSS), so
`udelay()` uses a calibrated busy loop instead of the timer CSR.
* DDR initialization support is available on the `polarfire_ddr` branch for
use cases that require loading larger applications to DDR memory.


## STM32F7
Expand Down
Loading
Loading