Skip to content

Commit 4377a13

Browse files
committed
PolarFire SoC M-Mode, QSPI and L2-LIM support
Adds support for running wolfBoot in **Machine Mode (M-mode)** on the PolarFire SoC MPFS250T, booting from eNVM and loading a signed application from **SC QSPI flash** into on-chip LIM (Loosely Integrated Memory). No HSS (Hart Software Services) or DDR is required. It also extends the existing PolarFire HAL with multi-hart support, L2 cache configuration, per-hart UART, and refactors shared code (SDHCI, SCB mailbox, linker/test-app) for both S-mode and M-mode builds.
1 parent 4a53bd1 commit 4377a13

27 files changed

+2016
-818
lines changed

.gdbinit

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,3 @@ add-symbol-file test-app/image.elf
44
set pagination off
55
foc c
66

7-

.github/workflows/test-build-riscv.yml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ jobs:
1919
build:
2020
runs-on: ubuntu-24.04
2121
timeout-minutes: 30
22-
2322
steps:
2423
- uses: actions/checkout@v4
2524
with:
@@ -80,26 +79,28 @@ jobs:
8079
- name: Update repository
8180
run: sudo apt-get update -o Acquire::Retries=3
8281

83-
- name: Download and install RISC-V toolchains
82+
# ============================================================
83+
# Prebuilt RISC-V toolchains from riscv-collab
84+
# https://github.com/riscv-collab/riscv-gnu-toolchain/releases
85+
# Extracts to: riscv/bin/riscv{32,64}-unknown-elf-*
86+
# ============================================================
87+
- name: Download and install RISC-V toolchain (riscv32)
8488
if: ${{ inputs.arch == 'riscv' }}
8589
run: |
86-
# Download SiFive prebuilt toolchain with newlib
87-
wget -q https://static.dev.sifive.com/dev-tools/freedom-tools/v2020.12/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz
88-
tar xzf riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14.tar.gz
89-
echo "$GITHUB_WORKSPACE/riscv64-unknown-elf-toolchain-10.2.0-2020.12.8-x86_64-linux-ubuntu14/bin" >> $GITHUB_PATH
90-
91-
# Download latest prebuilt RISC-V toolchains
92-
#wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz
93-
#tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz
94-
#echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH
90+
wget -q https://github.com/riscv-collab/riscv-gnu-toolchain/releases/latest/download/riscv32-elf-ubuntu-24.04-gcc.tar.xz
91+
tar -xf riscv32-elf-ubuntu-24.04-gcc.tar.xz
92+
echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH
93+
$GITHUB_WORKSPACE/riscv/bin/riscv32-unknown-elf-gcc --version
9594
96-
- name: Download and install RISC-V toolchains
95+
- name: Install RISC-V toolchain (riscv64)
9796
if: ${{ inputs.arch == 'riscv64' }}
9897
run: |
99-
wget -q https://github.com/RISCV-Tools/riscv-gnu-toolchain/releases/latest/download/riscv64-elf-ubuntu-24.04-gcc.tar.xz
100-
tar -xf riscv64-elf-ubuntu-24.04-gcc.tar.xz
101-
echo "$GITHUB_WORKSPACE/riscv/bin" >> $GITHUB_PATH
98+
sudo apt-get install -y gcc-riscv64-unknown-elf binutils-riscv64-unknown-elf
99+
riscv64-unknown-elf-gcc --version
102100
101+
# ============================================================
102+
# Build wolfboot
103+
# ============================================================
103104
- name: make clean
104105
run: |
105106
make distclean
@@ -115,10 +116,9 @@ jobs:
115116
- name: Build wolfboot (riscv32)
116117
if: ${{ inputs.arch == 'riscv' }}
117118
run: |
118-
# using riscv64 for now since riscv32-unknown-elf- is missing "zicsr" extension
119-
make CROSS_COMPILE=riscv64-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}}
119+
make CROSS_COMPILE=riscv32-unknown-elf- FREEDOM_E_SDK=$GITHUB_WORKSPACE/freedom-e-sdk ${{inputs.make-args}}
120120
121-
- name: Build wolfboot (riscv64))
121+
- name: Build wolfboot (riscv64)
122122
if: ${{ inputs.arch == 'riscv64' }}
123123
run: |
124124
make CROSS_COMPILE=riscv64-unknown-elf- ${{inputs.make-args}}

.github/workflows/test-configs.yml

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ jobs:
1919
with:
2020
arch: riscv
2121
config-file: ./config/examples/hifive1.config
22-
# Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv32imafdc_zicsr_zmmul_zaamo_zalrsc_zca_zcd_zcf'/'-mabi=ilp32d')
23-
# Consider building cached RISCV64 toolchain for this target
24-
make-args: wolfboot.bin
2522

2623
sama5d3_test:
2724
uses: ./.github/workflows/test-build.yml
@@ -266,9 +263,16 @@ jobs:
266263
with:
267264
arch: riscv64
268265
config-file: ./config/examples/polarfire_mpfs250.config
269-
# Only building wolfBoot - not test app for now (cross compiler cannot find suitable multilib set for '-march=rv64imafd_zicsr_zmmul_zaamo_zalrsc'/'-mabi=lp64d')
270-
# Consider building cached RISCV64 toolchain for this target
271-
make-args: wolfboot.bin
266+
microchip_mpfs250_qspi_test:
267+
uses: ./.github/workflows/test-build-riscv.yml
268+
with:
269+
arch: riscv64
270+
config-file: ./config/examples/polarfire_mpfs250_qspi.config
271+
microchip_mpfs250_m_qspi_test:
272+
uses: ./.github/workflows/test-build-riscv.yml
273+
with:
274+
arch: riscv64
275+
config-file: ./config/examples/polarfire_mpfs250_m_qspi.config
272276

273277
raspi3_test:
274278
uses: ./.github/workflows/test-build.yml

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ language.settings.xml
327327

328328
# PolarFire SoC Device Tree Binary
329329
hal/mpfs.dtb
330+
bootmode1/
330331

331332
# Emulator test: generated linker scripts
332333
test-app/emu-test-apps/*/target.ld

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,8 @@ $(LSCRIPT): $(LSCRIPT_IN) FORCE
521521
sed -e "s/@WOLFBOOT_LOAD_BASE@/$(WOLFBOOT_LOAD_BASE)/g" | \
522522
sed -e "s/@BOOTLOADER_START@/$(BOOTLOADER_START)/g" | \
523523
sed -e "s/@IMAGE_HEADER_SIZE@/$(IMAGE_HEADER_SIZE)/g" | \
524-
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" \
524+
sed -e "s/@FSP_S_LOAD_BASE@/$(FSP_S_LOAD_BASE)/g" | \
525+
sed -e "s/@WOLFBOOT_L2LIM_SIZE@/$(WOLFBOOT_L2LIM_SIZE)/g" \
525526
> $@
526527

527528
hex: wolfboot.hex

arch.mk

Lines changed: 65 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,24 @@ endif
564564
## RISCV (32-bit)
565565
ifeq ($(ARCH),RISCV)
566566
CROSS_COMPILE?=riscv32-unknown-elf-
567-
ARCH_FLAGS=-march=rv32imac -mabi=ilp32 -mcmodel=medany
567+
# GCC 12+ separated _zicsr (CSR instructions) and _zifencei (fence.i)
568+
# from the base "I" extension, requiring them to be listed explicitly in
569+
# the -march string. Detect with compile-only tests (-c).
570+
#
571+
# IMPORTANT: these extensions are added to CFLAGS only (compilation).
572+
# They must NOT appear in LDFLAGS because GCC 15 decomposes the ISA
573+
# string (m→zmmul, a→zaamo+zalrsc, c→zca) producing an expanded
574+
# -march that has no matching multilib, causing a fatal error at
575+
# link time. The base march is multilib-safe for all GCC versions.
576+
RISCV32_ZICSR := $(shell echo "void _start(void){}" | \
577+
$(CROSS_COMPILE)gcc -march=rv32imac_zicsr -mabi=ilp32 -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
578+
RISCV32_ZIFENCEI := $(shell echo "void _start(void){}" | \
579+
$(CROSS_COMPILE)gcc -march=rv32imac_zifencei -mabi=ilp32 -c -x c - -o /dev/null 2>/dev/null && echo _zifencei)
568580
CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV
569-
CFLAGS+=$(ARCH_FLAGS)
570-
LDFLAGS+=$(ARCH_FLAGS)
581+
# Compilation: extended march so assembler accepts CSR/fence.i
582+
CFLAGS+=-march=rv32imac$(RISCV32_ZICSR)$(RISCV32_ZIFENCEI) -mabi=ilp32 -mcmodel=medany
583+
# Linking: base march (no extension suffixes) for multilib lookup
584+
LDFLAGS+=-march=rv32imac -mabi=ilp32 -mcmodel=medany
571585
MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c32.o
572586

573587
# Prune unused functions and data
@@ -582,7 +596,24 @@ endif
582596
## RISCV64 (64-bit)
583597
ifeq ($(ARCH),RISCV64)
584598
CROSS_COMPILE?=riscv64-unknown-elf-
585-
CFLAGS+=-DMMU -DWOLFBOOT_DUALBOOT
599+
600+
# M-mode vs S-mode configuration
601+
ifeq ($(RISCV_MMODE),1)
602+
# Machine Mode: Running directly from eNVM/L2 SRAM
603+
CFLAGS+=-DWOLFBOOT_RISCV_MMODE -DWOLFBOOT_DUALBOOT
604+
# Use M-mode specific linker script
605+
LSCRIPT_IN:=hal/$(TARGET)-m.ld
606+
else
607+
# Supervisor Mode: Running under HSS
608+
CFLAGS+=-DWOLFBOOT_DUALBOOT
609+
ifeq ($(MPFS_L2LIM),1)
610+
# L2-LIM mode: wolfBoot in on-chip SRAM, loaded by HSS (no DDR)
611+
LSCRIPT_IN:=hal/$(TARGET)-hss.ld
612+
else
613+
# DDR mode (default): full MMU and FDT support
614+
CFLAGS+=-DMMU
615+
endif
616+
endif
586617

587618
# If SD card or eMMC is enabled use update_disk loader with GPT support
588619
ifneq ($(filter 1,$(DISK_SDCARD) $(DISK_EMMC)),)
@@ -596,10 +627,30 @@ ifeq ($(ARCH),RISCV64)
596627
UPDATE_OBJS?=src/update_ram.o
597628
endif
598629

599-
ARCH_FLAGS=-march=rv64imafd -mabi=lp64d -mcmodel=medany
630+
# GCC 12+ extension detection (see RISCV 32-bit section above).
631+
# Extensions go in CFLAGS only; LDFLAGS uses the base march to avoid
632+
# GCC 15 multilib lookup failures from ISA string decomposition.
633+
RISCV64_ZICSR := $(shell echo "void _start(void){}" | \
634+
$(CROSS_COMPILE)gcc -march=rv64imafd_zicsr -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
635+
RISCV64_ZIFENCEI := $(shell echo "void _start(void){}" | \
636+
$(CROSS_COMPILE)gcc -march=rv64imafd_zifencei -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zifencei)
637+
638+
ifeq ($(RISCV_MMODE),1)
639+
# E51 core: rv64imac (no FPU, no crypto extensions)
640+
CFLAGS+=-march=rv64imac$(RISCV64_ZICSR)$(RISCV64_ZIFENCEI) -mabi=lp64 -mcmodel=medany
641+
LDFLAGS+=-march=rv64imac -mabi=lp64 -mcmodel=medany
642+
else
643+
# U54 cores: rv64gc (with FPU)
644+
CFLAGS+=-march=rv64imafd$(RISCV64_ZICSR)$(RISCV64_ZIFENCEI) -mabi=lp64d -mcmodel=medany
645+
LDFLAGS+=-march=rv64imafd -mabi=lp64d -mcmodel=medany
646+
647+
# FDT support for DDR S-mode (not needed for L2-LIM bare-metal boot)
648+
ifneq ($(MPFS_L2LIM),1)
649+
CFLAGS+=-DWOLFBOOT_FDT
650+
OBJS+=src/fdt.o
651+
endif
652+
endif
600653
CFLAGS+=-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV -DARCH_RISCV64
601-
CFLAGS+=$(ARCH_FLAGS)
602-
LDFLAGS+=$(ARCH_FLAGS)
603654

604655
# Prune unused functions and data
605656
CFLAGS +=-ffunction-sections -fdata-sections
@@ -608,9 +659,6 @@ ifeq ($(ARCH),RISCV64)
608659
# Unified RISC-V boot code (32/64-bit via __riscv_xlen)
609660
OBJS+=src/boot_riscv_start.o src/boot_riscv.o src/vector_riscv.o
610661

611-
CFLAGS+=-DWOLFBOOT_FDT
612-
OBJS+=src/fdt.o
613-
614662
ifeq ($(SPMATH),1)
615663
MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/sp_c64.o
616664
endif
@@ -1632,6 +1680,13 @@ ifeq ($(DEBUG_UART),1)
16321680
endif
16331681
endif
16341682

1683+
# UART QSPI programmer (PolarFire SoC MPFS): receive binary over UART and
1684+
# write it directly to QSPI flash. Requires EXT_FLASH=1 and DEBUG_UART=1.
1685+
# Use tools/scripts/mpfs_qspi_prog.py on the host side.
1686+
ifeq ($(UART_QSPI_PROGRAM),1)
1687+
CFLAGS+=-DUART_QSPI_PROGRAM
1688+
endif
1689+
16351690
ifeq ($(NXP_CUSTOM_DCD),1)
16361691
CFLAGS+=-DNXP_CUSTOM_DCD
16371692
OBJS+=$(NXP_CUSTOM_DCD_OBJS)

config/examples/polarfire_mpfs250.config

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

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

7474
# Optional Encryption
@@ -78,7 +78,7 @@ WOLFBOOT_LOAD_DTS_ADDRESS?=0x8A000000
7878
#OBJS_EXTRA=src/my_custom_encrypt_key.o
7979

8080
# Optional EMMC_SD debugging logs
81-
#CFLAGS_EXTRA+=-DDEBUG_MMC
81+
#CFLAGS_EXTRA+=-DDEBUG_SDHCI
8282
# Optional disk debugging logs
8383
#CFLAGS_EXTRA+=-DDEBUG_DISK
8484
#CFLAGS_EXTRA+=-DDISK_TEST
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
ARCH?=RISCV64
2+
TARGET?=mpfs250
3+
4+
# ECC P384 + SHA384
5+
SIGN?=ECC384
6+
HASH?=SHA384
7+
IMAGE_HEADER_SIZE=512
8+
9+
WOLFBOOT_VERSION?=1
10+
ARMORED?=0
11+
DEBUG?=0
12+
DEBUG_SYMBOLS?=1
13+
DEBUG_UART?=1
14+
VTOR?=1
15+
16+
NO_XIP?=1
17+
18+
NVM_FLASH_WRITEONCE?=0
19+
UART_FLASH?=0
20+
V?=0
21+
NO_MPU?=1
22+
RAM_CODE?=0
23+
SPMATH?=1
24+
DUALBANK_SWAP?=0
25+
PKA?=0
26+
ENCRYPT=0
27+
WOLFTPM?=0
28+
ELF?=0
29+
30+
# U54 cores lack RISC-V crypto extensions (Zknh); use portable C implementations
31+
NO_ASM?=1
32+
33+
# QSPI Flash Configuration
34+
# Using Micron MT25QL01GBBB (128MB, 64KB sectors)
35+
EXT_FLASH?=1
36+
SPI_FLASH?=0
37+
38+
# SPI Flash Controller Selection:
39+
# MPFS_SC_SPI: Use SC QSPI Controller (0x37020100) for fabric-connected flash.
40+
# Direct register access to System Controller's QSPI instance.
41+
# DEFAULT: Use MSS QSPI Controller (0x21000000) for external flash
42+
# on MSS QSPI pins.
43+
CFLAGS_EXTRA+=-DMPFS_SC_SPI
44+
45+
# L2-LIM mode: wolfBoot loaded by HSS to L2-LIM (no DDR)
46+
# HSS runs on E51 from eNVM, loads wolfBoot to L2-LIM on U54 (S-mode)
47+
# wolfBoot loads application from SC ext SPI flash to L2-LIM
48+
MPFS_L2LIM?=1
49+
50+
# wolfBoot origin in L2-LIM (above HSS resident region)
51+
# NOTE: Adjust based on HSS L2-LIM footprint. HSS typically uses ~200-400KB
52+
# from 0x08000000. Check HSS linker map for actual end address.
53+
WOLFBOOT_ORIGIN?=0x08040000
54+
55+
# Application loaded from QSPI to L2-LIM (above wolfBoot, 128KB offset)
56+
WOLFBOOT_LOAD_ADDRESS?=0x08060000
57+
58+
# Stack at top of 1.5MB L2-LIM (grows downward)
59+
WOLFBOOT_STACK_TOP?=0x08180000
60+
61+
# L2-LIM size available for wolfBoot (STACK_TOP - ORIGIN)
62+
WOLFBOOT_L2LIM_SIZE?=0x140000
63+
64+
# Flash geometry (64 KB sector)
65+
WOLFBOOT_SECTOR_SIZE?=0x10000
66+
67+
# Partition layout for 128MB QSPI flash
68+
# Boot partition: 0x00020000 - 0x01FFFFFF (~32MB)
69+
# Update partition: 0x02000000 - 0x03FFFFFF (~32MB)
70+
# Swap partition: 0x04000000 - 0x0400FFFF (64KB)
71+
# Remaining: 0x04010000 - 0x07FFFFFF (~64MB available)
72+
WOLFBOOT_PARTITION_SIZE?=0x1FE0000
73+
WOLFBOOT_PARTITION_BOOT_ADDRESS?=0x20000
74+
WOLFBOOT_PARTITION_UPDATE_ADDRESS?=0x2000000
75+
WOLFBOOT_PARTITION_SWAP_ADDRESS?=0x4000000
76+
77+
# Speed up reads from flash by using larger blocks
78+
CFLAGS_EXTRA+=-DWOLFBOOT_SHA_BLOCK_SIZE=4096
79+
80+
# Optional Encryption
81+
#CUSTOM_ENCRYPT_KEY=1
82+
#ENCRYPT=1
83+
#ENCRYPT_WITH_AES256=1
84+
#OBJS_EXTRA=src/my_custom_encrypt_key.o
85+
86+
# Optional QSPI debugging
87+
# Uncomment for verbose QSPI debug output
88+
#CFLAGS_EXTRA+=-DDEBUG_QSPI
89+
90+
# Optional QSPI flash test (erase/write/read on update partition)
91+
# Uncomment to run test during hal_init()
92+
#CFLAGS_EXTRA+=-DTEST_EXT_FLASH

0 commit comments

Comments
 (0)