Skip to content

Conversation

petejohanson-adi
Copy link
Contributor

This PR adds support for running Zephyr on the secondary RV32 (RISC-V) core on the MAX32 parts that include it (MAX32655, MAX32690, MAX78002). The PR adds the necessary interrupt controller (custom) and tickless system timer (using one of the timer peripherals, MTIMER is not support on RV32) in order to fully support threading, etc.

The RV32 core is launched by the primary ARM core, so some small enablement for specifying the location for the RV32 address/entrypoint is added in order to do so.

Twister tests on the three mentioned targets have all been performed internally, including slow timer tests to ensure that implementation is sound.

A few items to point out, for reviewers, that impact other areas, and I welcome feedback on:

  • The RV32 core does not support the FENCE instruction, so some minor changes to override that intrinsic where used in lib/os/spsc_pbuf.c are included.
  • Flashing the RV32 core code is actually performed using a programmer attached to the ARM core (using openocd or jlink), which required some OpenOCD runner tweaks to allow specifying different pre-init to be used specifically when performing a flash operation.

You can test locally with the following:

west build -p -b max32690evkit//m4 samples/sysbuild/hello_world -T sample.sysbuild.hello_world.max32690evkit_m4_rv32

And then flashing to an EVKit, and the corresponding code will be run on both cores. If you wish to run the Twister tests on the RV32 core, that same hello world sample is used as the "host program" on the ARM core to launch the RV32 code after a new test is flashed there, so before running twister, be sure to flash that sample to the evkit.

MaureenHelm and others added 23 commits October 13, 2025 09:37
Enables the sysbuild hello world sample application on the max32655evkit
board to demonstrate using the soc's arm cortex-m4 and risc-v cores
together. The build system produces two separate application images, one
for each core, therefore a few extra manual steps are currently required
to merge the images and program to flash.

1. Build the m4 and rv32 images:

  $ west build -p -b max32655evkit//m4 samples/sysbuild/hello_world/ \
    -T sample.sysbuild.hello_world.max32655evkit_m4_rv32

2. Merge the m4 and rv32 images into one combined image:

  $ python scripts/build/mergehex.py -o build/merged.hex \
    build/hello_world/zephyr/zephyr.hex build/remote/zephyr/zephyr.hex

3. Connect jlink to the m4 core:

  $ JLinkExe -device MAX32655 -if SWD -speed 4000 -autoconnect 1

4. Use jlink to program the combined image into flash:

  J-Link>loadfile build/merged.hex

5. Launch a jlink gdb server and attach a gdb client:

  $ west attach -r jlink --domain hello_world

6. Read memory at the address of the rv32 ram_console buffer:

  (gdb) x/s 0x2001c01c
  0x2001c01c:     "*** Booting Zephyr OS build v3.6.0-4398-g5fdc955c28e6
  ***\nHello world from max32655evkit/max32655/rv32\n"

Signed-off-by: Maureen Helm <[email protected]>
SRAM0-2 used for the CM4 and SRAM3 for the RISCV.
Use SRAM3 for WDT test. ROM will use lower SRAM setions
during boot, causing the test to fail.

Signed-off-by: Kevin Gillespie <[email protected]>
The olimex-arm-usb-ocd-h.cfg is under the fdti/ subdirectory.

Signed-off-by: Pete Johanson <[email protected]>
MAX32 shares peripherals, but with different interrupt numbers
used by the ARM and RISC-V cores, so refactor the shared DTS to
properly share peripherals and then do core specific additional
settings.

Signed-off-by: Pete Johanson <[email protected]>
The RV32 jtag pins are only connected when set to an alternate function,
so handle doing the pinctrl setup, if specified, on the primary ARM core.

Signed-off-by: Pete Johanson <[email protected]>
Add interrupt support for the RV32 core of the MAX32 series. A custom
vector table is used at the start of the flash range for the core, and
regular interrupts jump to an intermediary point that sets the mcause
interrupt bit so the standard RISC-V handling works as expected.

Signed-off-by: Pete Johanson <[email protected]>
The RV32 core does not implement RISC-V mtime, so add a new system
timer driver uses a peripheral timer for this functionality.

Signed-off-by: Pete Johanson <[email protected]>
Add support for the RV32 core on the MAX32690EVkit, and allow running the
sysbuild hello_world sample on both cores.

Signed-off-by: Pete Johanson <[email protected]>
Add the ability to specify different pre init commands for flashing, in the
case flashing needs to use a different transport/target than other
operations like debug for heterogeneous targets.

Signed-off-by: Pete Johanson <[email protected]>
Adjust for flashing RV32 targets using the same transport/target as the
main ARM core, allowing for debug to operate using the RV JTAG still.

Signed-off-by: Pete Johanson <[email protected]>
Use combination of base address and offset for the ARM host to boot
the RV32 core by specifying the flash base + partition offset with
`zephyr,rv32-flash` and `zephyr,code-rv32-partition` together.

Signed-off-by: Pete Johanson <[email protected]>
To aid in testing scenarios, add an optional delay for
the ARM core starting the RV32 boot. This will help avoid having the
RV32 core started on reset before a halt from the attached debugger.

Signed-off-by: Pete Johanson <[email protected]>
Split up MAX7800x DTS files to support RV32 core, and enable
the RV32 target for the max78002evkit board definition.

Signed-off-by: Pete Johanson <[email protected]>
Use a custom illegal instruction for the MAX32 RV32 family, since it
doesn't trap on `unimp` or any other write to a read-only/non-existent CSR.

Signed-off-by: Pete Johanson <[email protected]>
The flash info blocks needed to provide the device ID are not accessible to
the RV32 core on MAX32 devices, so disable this hwinfo driver there.

Signed-off-by: Pete Johanson <[email protected]>
Explicitly `k_panic` on RV32 to test coredump on that target.

Signed-off-by: Pete Johanson <[email protected]>
MAX32 RV32 core DMA support is still a WIP, so disable async API for now
there.

Signed-off-by: Pete Johanson <[email protected]>
Don't run the PSA ITS test on the max78002evkit//rv32 target, since the
automatic erase there now ends up erasing the flash region that contains
the "host" ARM application responsible for running the RV32 tests.

Signed-off-by: Pete Johanson <[email protected]>
The MAX32 RV32 core doesn't support the FENCE instruction, so redefine a
couple intrinsics that translate to FENCE instructions.

Signed-off-by: Pete Johanson <[email protected]>
The MAX32 RV32 core adjusts some intrinsics, so pull in <soc.h> to account
for that.

Signed-off-by: Pete Johanson <[email protected]>
In order to properly relocate some functions into RAM as needed by the
MAX32 flash driver, select the ARCH_HAS_RAMFUNC_SUPPORT config on RV32.

Signed-off-by: Pete Johanson <[email protected]>
Pull in latest ADI HAL for RV32 DMA build fixes.

Signed-off-by: Pete Johanson <[email protected]>
Remove the APARD32690 from flash1 testing, since it's board definition is
not yet set up wth separate storage partition.

Signed-off-by: Pete Johanson <[email protected]>
Copy link

@ycsin
Copy link
Member

ycsin commented Oct 13, 2025

Just wonder if, by any chance, that some of the refactoring / fixups can be split into a different PRs so that the scope is smaller and easier to review?

@petejohanson-adi
Copy link
Contributor Author

Just wonder if, by any chance, that some of the refactoring / fixups can be split into a different PRs so that the scope is smaller and easier to review?

Yeah, the couple minor things are not particularly RV32 specific are probably the best candidates for splitting out, can I can do so if folks want.

The rest of the MAX32 refactors are... kind of pointless to do in isolation, but can do so if folks really want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants