Skip to content

Commit b71229c

Browse files
committed
mpfs250 test-app: drive the Athena F5200 under WOLFCRYPT_TEST/WOLFCRYPT_BENCHMARK with per-size offload timing
1 parent f1d99c6 commit b71229c

11 files changed

Lines changed: 218 additions & 20 deletions

File tree

‎docs/PolarFire.md‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,6 +1225,31 @@ The AES offload is worth about 4.2x on the decrypt. **The hash offload is about
12251225

12261226
Athena also does not fit eNVM alongside the full feature set: with the manifest linked it needs both `GZIP` and `MPFS_SBI_SC_FLASH` dropped. Dropping `GZIP` costs nothing when the FIT's kernel is stored uncompressed.
12271227

1228+
The port also serves AES-256-ECB, which is how AES-256-XTS reaches the engine: wolfCrypt's XTS masks the whole buffer with the tweak chain and issues one bulk ECB call per XTS call (`HAVE_AES_ECB` required, distinct in/out buffers), while the tweak math stays in software. wolfBoot itself encrypts images with CTR and has no XTS use; the ECB path is for an application. Requests under `WC_MPFS_ATHENA_AES_MIN_SZ` (32 bytes) are declined to software, which keeps the XTS tweak and ciphertext-stealing blocks off the engine. See `wolfcrypt/src/port/microchip/README.md` in wolfSSL.
1229+
1230+
#### Measuring the offload bare-metal
1231+
1232+
The test application doubles as a bare-metal wolfCrypt test and benchmark harness for the engine, in the same M-mode environment wolfBoot uses, so its figures compare with the software build of the same app and not with a Linux userspace benchmark:
1233+
1234+
```sh
1235+
cp config/examples/polarfire_mpfs250_m_qspi.config .config
1236+
make clean
1237+
make MPFS_ATHENA=1 MPFS_ATHENA_CAL_DIR=/path/to/hart-software-services/services/crypto \
1238+
WOLFCRYPT_BENCHMARK=1 WOLFBOOT_L2SCRATCH_SIZE=512k
1239+
```
1240+
1241+
Load `test-app/image_v1_signed.bin` with `mpfs_qspi_prog.py` as for any M-mode test app. The benchmark app is about 240 KB and is loaded at `0x0A020200`, so the bootloader's stack has to sit at the top of all four scratchpad ways rather than the default 256 KB, which is what `WOLFBOOT_L2SCRATCH_SIZE=512k` does; `test-app/RISCV64-mpfs250.ld` reserves 64 KB for the app's own stack above that, sized for the benchmark's SP math frames. The `WOLFCRYPT_TEST=1` app is about 370 KB and does not fit the scratchpad beside the bootloader: build it on `polarfire_mpfs250_m_qspi_ddr.config` with its `-DWOLFBOOT_MMODE_SMODE_BOOT` line removed, which loads the signed app into DDR and enters it with the M-mode direct jump, and with `NO_ASM=1`, since the test-app's RISC-V SHA assembly does not assemble against the test configuration. `MPFS_ATHENA=1` makes the app bring the engine up itself, so the bootloader it runs under may be built with or without the offload. The app registers the port, runs its known-answer self-test and prints `Athena: self-test passed, engine served N call(s)`; the stock `wolfcrypt_test()` and `benchmark_test()` then drive the engine through `WC_USE_DEVID`, with the benchmark labelling offloaded results `HW`. The benchmark runs once per call size in `MPFS_BENCH_SIZES` (default 1 KiB, 512 B and 4 KiB; each needs twice that from `WOLFSSL_STATIC_MEMORY_TEST_SZ`), since one engine transfer per call amortises very differently at sector size and in bulk. The app ends with the total engine call count: a passing test or a plausible rate proves nothing about offload on its own, because every case the port declines runs in software. The same app built without `MPFS_ATHENA` is the software baseline. Object files are configuration-specific, so `make clean` between the two builds.
1242+
1243+
Measured on the Video Kit with the DDR configuration (E51 at 600 MHz), the software column being wolfCrypt's default C AES for RISC-V:
1244+
1245+
| Call size | AES-256-XTS software | AES-256-XTS Athena | AES-256-CTR Athena | SHA-384 software | SHA-384 Athena |
1246+
|---|---|---|---|---|---|
1247+
| 512 B | 48 KiB/s | 1.23 MiB/s | 12.9 MiB/s | 5.7 MiB/s | 11.4 MiB/s |
1248+
| 1 KiB | 49 KiB/s | 2.06 MiB/s | 14.6 MiB/s | 5.8 MiB/s | 13.2 MiB/s |
1249+
| 4 KiB | 49 KiB/s | 4.2 MiB/s | 16.1 MiB/s | 5.8 MiB/s | 14.8 MiB/s |
1250+
1251+
AES-128-XTS stays in software at about 68 KiB/s. The app keeps the five MSS watchdogs refreshed from a machine timer interrupt every 5 s, since a test or benchmark pass runs far longer than their window, and its M-mode trap handler prints the cause and halts instead of resuming at the faulting instruction. The RISC-V harts trap on misaligned accesses, so `user_settings.h` defines `WOLFSSL_USE_ALIGN` for `ARCH_RISCV64`; the AES-GCM tests and benchmark also need the wolfSSL change that takes the byte-wise GCM table multiply under that define on 64-bit builds.
1252+
12281253
## Source files
12291254

12301255
`hal/mpfs250.c` - Hardware abstraction layer (UART, QSPI, SD/eMMC, multi-hart)

‎docs/Targets.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -910,7 +910,7 @@ Make variables, on the command line or in the `.config`. See [PolarFire.md](Pola
910910
| Option | Purpose |
911911
|--------|---------|
912912
| `LIBERO_FPGA_CONFIG_DIR` | Path to the board's Libero/HSS `fpga_design_config` headers. Enables LPDDR4 init (`MPFS_DDR_INIT`); required for the M-Mode + DDR build. |
913-
| `MPFS_ATHENA` (+ `MPFS_ATHENA_CAL_DIR`) | SHA-384 and AES-256-CTR offload to the Athena F5200 (TeraFire), with a mandatory self-check. |
913+
| `MPFS_ATHENA` (+ `MPFS_ATHENA_CAL_DIR`) | SHA-384, AES-256-CTR and AES-256-ECB (AES-XTS) offload to the Athena F5200 (TeraFire), with a mandatory self-check. With `WOLFCRYPT_TEST=1` or `WOLFCRYPT_BENCHMARK=1` the test-app also drives the engine. |
914914
| `SNVM_KEYSTORE`, `SNVM_KEYSTORE_PROVISION`, `SNVM_KEYSTORE_REQUIRE_ROM` | Serve the verification keystore from secure NVM; the one-time writer; refuse to boot unless every keystore page is ROM-flagged. |
915915
| `SNVM_KEK`, `SNVM_ENCKEY_PROVISION` | PUF-derived KEK with RFC 3394 key-wrap for the sNVM-stored image-encryption key, and its one-time writer. |
916916
| `MPFS_SCB_SMODE_DENY` | Fence S-mode off the System Controller mailbox (PMP plus dtb node removal), so nothing after wolfBoot can reach the sNVM write service. |

‎hal/mpfs250.c‎

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -145,10 +145,6 @@ extern uint8_t _main_hart_hls; /* linker-provided address symbol; typed as uint8
145145

146146
/* CLINT MSIP register for IPI delivery */
147147
#define CLINT_MSIP_REG(hart) (*(volatile uint32_t*)(CLINT_BASE + (hart) * 4))
148-
/* CLINT machine-timer comparator (per hart) and MTIME counter */
149-
#define CLINT_MTIMECMP_REG(hart) \
150-
(*(volatile uint64_t*)(CLINT_BASE + 0x4000UL + (hart) * 8UL))
151-
#define CLINT_MTIME_REG (*(volatile uint64_t*)(CLINT_BASE + 0xBFF8UL))
152148

153149
/* Signal secondary harts that E51 (main hart) is ready. */
154150
static void mpfs_signal_main_hart_started(void)
@@ -216,10 +212,10 @@ void secondary_hart_entry(unsigned long hartid, HLS_DATA* hls)
216212
}
217213
}
218214

219-
#if defined(MPFS_DDR_INIT) && defined(WOLFBOOT_MMODE_SMODE_BOOT)
215+
#ifdef WOLFBOOT_RISCV_MMODE
220216
/* Enable the CLINT MTIME counter via the SYSREG RTC clock divider. Without it
221217
* MTIME never advances and an S-mode OS has no scheduler tick. */
222-
static void mpfs_enable_mtime(void)
218+
void mpfs_enable_mtime(void)
223219
{
224220
volatile uint32_t *rtc_cr = (volatile uint32_t *)(SYSREG_BASE + 0x0CUL);
225221
uint32_t div;
@@ -232,7 +228,9 @@ static void mpfs_enable_mtime(void)
232228
*rtc_cr |= (1UL << 16); /* enable RTC/time-base clock */
233229
__asm__ volatile("fence iorw, iorw" ::: "memory");
234230
}
231+
#endif /* WOLFBOOT_RISCV_MMODE */
235232

233+
#if defined(MPFS_DDR_INIT) && defined(WOLFBOOT_MMODE_SMODE_BOOT)
236234
/* SBI HSM hart_start backend: stage the target hart's mailbox and ring its
237235
* MSIP; it enters S-mode at saddr with a0=hartid, a1=opaque. */
238236
int sbi_hal_hart_start(unsigned long hartid, unsigned long saddr,

‎hal/mpfs250.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,10 @@ int mpfs_nonce(uint8_t *nonce);
388388
#ifndef CLINT_BASE
389389
#define CLINT_BASE 0x02000000UL
390390
#endif
391+
/* Machine-timer comparator (per hart) and the MTIME counter. */
392+
#define CLINT_MTIMECMP_REG(hart) \
393+
(*(volatile uint64_t*)(CLINT_BASE + 0x4000UL + (hart) * 8UL))
394+
#define CLINT_MTIME_REG (*(volatile uint64_t*)(CLINT_BASE + 0xBFF8UL))
391395

392396
/* RTC Clock Frequency (1 MHz after divisor) */
393397
#define RTC_CLOCK_FREQ 1000000UL
@@ -472,6 +476,7 @@ void uart_write(const char* buf, unsigned int sz);
472476
#endif
473477
#ifdef WOLFBOOT_RISCV_MMODE
474478
void secondary_hart_entry(unsigned long hartid, HLS_DATA* hls);
479+
void mpfs_enable_mtime(void);
475480
#endif
476481
#endif /* __ASSEMBLER__ */
477482

‎include/user_settings.h‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,14 @@ extern int tolower(int c);
596596
# endif
597597
#endif
598598

599+
/* The RISC-V harts trap on a misaligned load or store with nothing to emulate
600+
* it bare-metal, so make wolfCrypt's ALIGN* attributes real: without this the
601+
* word-sized casts it makes on struct members (the AES-GCM table, for one)
602+
* fault. */
603+
#ifdef ARCH_RISCV64
604+
# define WOLFSSL_USE_ALIGN
605+
#endif
606+
599607
#if defined(EXT_ENCRYPTED)
600608
# define HAVE_PWDBASED
601609
#endif
@@ -764,7 +772,9 @@ extern int tolower(int c);
764772
#define WC_NO_HASHDRBG
765773
#define CUSTOM_RAND_GENERATE_SEED my_rng_seed_gen
766774
#define CUSTOM_RAND_GENERATE_BLOCK my_rng_seed_gen
775+
#ifndef __ASSEMBLER__
767776
extern int my_rng_seed_gen(unsigned char* output, unsigned int sz);
777+
#endif
768778

769779
/* Full test/benchmark algo set: AES ECB/CBC/CTR/GCM/XTS,
770780
* SHA-256/384/512, SHA-3. (AES-CBC/GCM added below; SHA-384/512
@@ -919,7 +929,17 @@ extern int tolower(int c);
919929
#define WOLFSSL_STATIC_MEMORY
920930
#endif
921931
#ifndef WOLFSSL_STATIC_MEMORY_TEST_SZ
922-
#define WOLFSSL_STATIC_MEMORY_TEST_SZ (10 * 1024)
932+
#if defined(TARGET_mpfs250) && defined(MPFS_DDR_INIT)
933+
/* Every default bucket, including the two above 4 KB that the
934+
* benchmark's 4 KB buffers and the test's larger contexts need;
935+
* a pool without them hands out something else. Only with DDR:
936+
* the L2 scratchpad app has no room for it. */
937+
#define WOLFSSL_STATIC_MEMORY_TEST_SZ (128 * 1024)
938+
#elif defined(TARGET_mpfs250)
939+
#define WOLFSSL_STATIC_MEMORY_TEST_SZ (64 * 1024)
940+
#else
941+
#define WOLFSSL_STATIC_MEMORY_TEST_SZ (10 * 1024)
942+
#endif
923943
#endif
924944
#define WOLFSSL_STATIC_MEMORY_LEAN
925945

@@ -929,7 +949,9 @@ extern int tolower(int c);
929949
/* User time functions provided */
930950
#define WOLFSSL_USER_CURRTIME
931951
#define XTIME my_time
952+
#ifndef __ASSEMBLER__
932953
extern unsigned long my_time(unsigned long* timer);
954+
#endif
933955
#endif
934956

935957
#if !defined(WOLFCRYPT_TEST) && !defined(WOLFCRYPT_BENCHMARK)

‎test-app/Makefile‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,18 @@ ifeq ($(SEC_QORIQ),1)
268268
APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/nxp/sec_qoriq_baremetal.o
269269
endif
270270

271+
# PolarFire SoC Athena F5200. options.mk already supplies the defines, the CAL
272+
# include path and the archive in LIBS; the port objects are added here because
273+
# the apps build their own wolfCrypt object list.
274+
ifeq ($(MPFS_ATHENA),1)
275+
ifeq ($(WOLFCRYPT_TEST)$(WOLFCRYPT_BENCHMARK),)
276+
$(warning MPFS_ATHENA=1 without WOLFCRYPT_TEST or WOLFCRYPT_BENCHMARK only runs the engine self-test in the test-app)
277+
endif
278+
WOLFCRYPT_SUPPORT=1
279+
APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/cryptocb.o
280+
APP_OBJS+=$(WOLFBOOT_LIB_WOLFSSL)/wolfcrypt/src/port/microchip/mpfs_athena.o
281+
endif
282+
271283
ifeq ($(WOLFCRYPT_TEST),1)
272284
CFLAGS+=-DWOLFCRYPT_TEST
273285
WOLFCRYPT_SUPPORT=1
@@ -1530,6 +1542,13 @@ endif
15301542
ifeq ($(TARGET),mpfs250)
15311543
LSCRIPT_TEMPLATE:=RISCV64-mpfs250.ld
15321544
CFLAGS+=-DRAMFUNCTION='__attribute__((used,section(".ramcode")))'
1545+
# The wolfCrypt test and benchmark need far more stack than the plain app,
1546+
# which the L2 scratchpad configurations have no room to reserve.
1547+
ifneq ($(filter 1,$(WOLFCRYPT_TEST) $(WOLFCRYPT_BENCHMARK)),)
1548+
TEST_APP_STACK_SIZE?=0x00010000
1549+
else
1550+
TEST_APP_STACK_SIZE?=0x00002000
1551+
endif
15331552
endif
15341553

15351554
# $(CYPRESS_PDL)/devices/templates/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.o
@@ -1983,7 +2002,8 @@ endif
19832002
sed -e "s/@WOLFBOOT_PARTITION_BOOT_ADDRESS@/$(WOLFBOOT_PARTITION_BOOT_ADDRESS)/g" | \
19842003
sed -e "s/@WOLFBOOT_PARTITION_SIZE@/$(WOLFBOOT_PARTITION_SIZE)/g" | \
19852004
sed -e "s/@WOLFBOOT_PARTITION_UPDATE_ADDRESS@/$(WOLFBOOT_PARTITION_UPDATE_ADDRESS)/g" | \
1986-
sed -e "s/@WOLFBOOT_PARTITION_SWAP_ADDRESS@/$(WOLFBOOT_PARTITION_SWAP_ADDRESS)/g" \
2005+
sed -e "s/@WOLFBOOT_PARTITION_SWAP_ADDRESS@/$(WOLFBOOT_PARTITION_SWAP_ADDRESS)/g" | \
2006+
sed -e "s/@TEST_APP_STACK_SIZE@/$(TEST_APP_STACK_SIZE)/g" \
19872007
> $(@)
19882008
$(Q)rm -f .app-size .entry-point .wolfboot-offset .partition-size .header-size
19892009

‎test-app/RISCV64-mpfs250.ld‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
/* TODO: Update with actual memory map for MPFS250 */
55

66
_Min_Heap_Size = 0x00002000; /* required amount of heap */
7-
_Min_Stack_Size = 0x00002000; /* required amount of stack */
7+
_Min_Stack_Size = @TEST_APP_STACK_SIZE@; /* required amount of stack */
88

99
OUTPUT_ARCH( "riscv" )
1010

‎test-app/app_mpfs250.c‎

Lines changed: 106 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,84 @@ int wolfcrypt_test(void *args);
4646
int benchmark_test(void *args);
4747
#endif
4848

49+
#ifdef WOLFCRYPT_BENCHMARK
50+
/* Buffer sizes the whole benchmark is run at, in turn: the Athena F5200 does
51+
* one engine transfer per call, so a sector-sized call and a bulk one amortise
52+
* the setup very differently, and the software build runs the same set as the
53+
* baseline. Each needs twice the size from the static pool
54+
* (WOLFSSL_STATIC_MEMORY_TEST_SZ). */
55+
#ifndef MPFS_BENCH_SIZES
56+
#define MPFS_BENCH_SIZES { 1024, 512, 4096 }
57+
#endif
58+
#endif /* WOLFCRYPT_BENCHMARK */
59+
60+
#ifdef MPFS_ATHENA
61+
#include <wolfssl/wolfcrypt/settings.h>
62+
#include <wolfssl/wolfcrypt/port/microchip/mpfs_athena.h>
63+
64+
static void mpfs_athena_app_init(void)
65+
{
66+
int ret;
67+
68+
/* The engine is brought up here, not by the bootloader: a wolfBoot built
69+
* without MPFS_ATHENA never touched it, and the port's own init handles
70+
* one that did. wolfcrypt_test and benchmark_test register the device
71+
* again, which the port accepts. */
72+
ret = wolfCrypt_Init();
73+
if (ret != 0) {
74+
wolfBoot_printf("Athena: wolfCrypt_Init failed (%d)\r\n", ret);
75+
return;
76+
}
77+
ret = wc_MpfsAthena_RegisterDevice(WC_MPFS_ATHENA_DEVID);
78+
if (ret != 0) {
79+
wolfBoot_printf("Athena: RegisterDevice failed (%d)\r\n", ret);
80+
return;
81+
}
82+
ret = wc_MpfsAthena_SelfTest();
83+
if (ret != 0) {
84+
wolfBoot_printf("Athena: self-test failed: %s (rc %d)\r\n",
85+
wc_MpfsAthena_SelfTestDesc(), ret);
86+
return;
87+
}
88+
wolfBoot_printf("Athena: self-test passed, engine served %u call(s)\r\n",
89+
(unsigned int)wc_MpfsAthena_GetCbCount());
90+
}
91+
92+
#endif /* MPFS_ATHENA */
93+
94+
95+
#ifdef WOLFBOOT_RISCV_MMODE
96+
#include "../hal/riscv.h"
97+
/* MTIME is not running in an M-mode boot: start it, then let the machine
98+
* timer interrupt refresh the watchdogs every 5 s for as long as the app
99+
* runs. */
100+
#define MPFS_WDT_PET_TICKS (5ULL * RTC_CLOCK_FREQ)
101+
102+
/* The vector saved the caller's registers, so plain C: refresh the five MSS
103+
* watchdogs, which the bitstream arms and which reset the chip well inside a
104+
* test run, then rearm. */
105+
void isr_mtimer(void)
106+
{
107+
mpfs_wdt_pet_all();
108+
CLINT_MTIMECMP_REG(0) = CLINT_MTIME_REG + MPFS_WDT_PET_TICKS;
109+
}
110+
111+
static void mpfs_wdt_timer_start(void)
112+
{
113+
mpfs_enable_mtime();
114+
CLINT_MTIMECMP_REG(0) = CLINT_MTIME_REG + MPFS_WDT_PET_TICKS;
115+
csr_set(mie, MIE_MTIE);
116+
csr_set(mstatus, MSTATUS_MIE);
117+
#ifdef MPFS_DDR_INIT
118+
/* The bootloader raised the E51 to the Libero PLL rate; this copy of the
119+
* HAL's clock variable, which times the benchmark, still holds the reset
120+
* rate. Without DDR init the clock is never raised and that reset rate is
121+
* the right one. */
122+
mpfs_cpu_freq_mhz =
123+
(uint32_t)(LIBERO_SETTING_MSS_COREPLEX_CPU_CLK / 1000000UL);
124+
#endif
125+
}
126+
#endif
49127

50128
void main(void)
51129
{
@@ -61,6 +139,14 @@ void main(void)
61139
wolfBoot_printf("GPL v3\r\n");
62140
wolfBoot_printf("========================\r\n");
63141

142+
#ifdef WOLFBOOT_RISCV_MMODE
143+
mpfs_wdt_timer_start();
144+
#endif
145+
146+
#ifdef MPFS_ATHENA
147+
mpfs_athena_app_init();
148+
#endif
149+
64150
#ifdef WOLFCRYPT_TEST
65151
wolfBoot_printf("\r\nRunning wolfCrypt tests...\r\n");
66152
wolfCrypt_Init();
@@ -72,11 +158,30 @@ void main(void)
72158
#ifdef WOLFCRYPT_BENCHMARK
73159
wolfBoot_printf("Running wolfCrypt benchmarks...\r\n");
74160
wolfCrypt_Init();
75-
benchmark_test(NULL);
161+
{
162+
static const unsigned int sizes[] = MPFS_BENCH_SIZES;
163+
unsigned int i;
164+
/* benchmark_test() puts the block size back to its default on its
165+
* first run, so take that run's setup first and configure after. */
166+
benchmark_init();
167+
benchmark_free();
168+
for (i = 0; i < sizeof(sizes) / sizeof(sizes[0]); i++) {
169+
wolfBoot_printf("\r\n--- %u-byte calls ---\r\n", sizes[i]);
170+
benchmark_configure(sizes[i]);
171+
benchmark_test(NULL);
172+
}
173+
}
76174
wolfCrypt_Cleanup();
77175
wolfBoot_printf("Benchmarks complete.\r\n\r\n");
78176
#endif
79177

178+
#ifdef MPFS_ATHENA
179+
/* A passing test or a plausible figure proves nothing about offload on
180+
* its own: every case the port declines runs in software. */
181+
wolfBoot_printf("Athena: engine served %u call(s) in total\r\n",
182+
(unsigned int)wc_MpfsAthena_GetCbCount());
183+
#endif
184+
80185
while(1) {
81186
/* Main application loop */
82187
/* TODO: Add watchdog feed if needed */

‎test-app/startup_riscv.c‎

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
#include <stdint.h>
2323
#include "hal/riscv.h"
24+
#include "printf.h"
2425

2526
extern void trap_entry(void);
2627
extern void trap_exit(void);
@@ -77,15 +78,35 @@ void do_boot(const uint32_t *app_offset)
7778
}
7879

7980
static uint32_t synctrap_cause = 0;
80-
void __attribute__((naked)) isr_synctrap(void)
81-
{
8281
#ifdef WOLFBOOT_RISCV_MMODE
83-
asm volatile("csrr %0, mcause" : "=r"(synctrap_cause));
84-
asm volatile("mret");
82+
/* The vector saved the caller's registers, so this can be plain C. Report the
83+
* fault and stop rather than resume at the faulting instruction, which would
84+
* trap again for ever with nothing on the console. Hardware clears mstatus.MIE
85+
* on trap entry, so the timer interrupt that pets the MSS watchdogs cannot run
86+
* here and they reset the board a few seconds after the message. */
87+
void isr_synctrap(void)
88+
{
89+
unsigned long cause, epc, tval;
90+
asm volatile("csrr %0, mcause" : "=r"(cause));
91+
asm volatile("csrr %0, mepc" : "=r"(epc));
92+
asm volatile("csrr %0, mtval" : "=r"(tval));
93+
synctrap_cause = (uint32_t)cause;
94+
wolfBoot_printf("TRAP: cause=%lx epc=%lx tval=%lx\r\n", cause, epc, tval);
95+
while (1) {
96+
/* halt */
97+
}
98+
}
8599
#else
100+
void __attribute__((naked)) isr_synctrap(void)
101+
{
86102
asm volatile("csrr %0, scause" : "=r"(synctrap_cause));
87103
asm volatile("sret");
104+
}
88105
#endif
106+
107+
/* Machine timer interrupt; a target that uses it defines its own. */
108+
void __attribute__((weak)) isr_mtimer(void)
109+
{
89110
}
90111

91112
void isr_empty(void)

‎test-app/vector_riscv.S‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ IV:
131131
.align 2
132132
j trap_empty
133133
.align 2
134-
j trap_empty
134+
j _mtimer
135135
.align 2
136136
j trap_empty
137137
.align 2
@@ -187,5 +187,10 @@ _synctrap:
187187
jal isr_synctrap
188188
trap_exit
189189

190+
_mtimer:
191+
trap_entry
192+
jal isr_mtimer
193+
trap_exit
194+
190195
trap_empty:
191196
nop

0 commit comments

Comments
 (0)