Skip to content

Commit 0426934

Browse files
committed
qemu-arm: Merge RISC-V 32-bit support into qemu-arm port.
Currently both the qemu-arm and qemu-riscv ports share a lot of code and functionality. This commit merges the qemu-riscv port into the qemu-arm port. The only real differences between the two are the toolchains used to build the code, and the initialisation/startup framework. Everything else is pretty much the same, so this brings the following benefits: - less code duplication - less burden on maintenance - generalised qemu port, could in the future support other architectures A new board `VIRT_RV32` has been added to the qemu-arm port which is the existing RISC-V board from the qemu-riscv port. To build it: $ make BOARD=VIRT_RV32 repl To cleanly separate the code for the different architectures, startup code has been moved to ports/qemu-arm/mcu/<arch>/. Signed-off-by: Damien George <damien@micropython.org>
1 parent f769b43 commit 0426934

33 files changed

+212
-602
lines changed

.github/workflows/ports_qemu-arm.yml

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,26 @@ concurrency:
1919
cancel-in-progress: true
2020

2121
jobs:
22-
build_and_test:
22+
build_and_test_arm:
2323
runs-on: ubuntu-latest
2424
steps:
2525
- uses: actions/checkout@v4
2626
- name: Install packages
27-
run: source tools/ci.sh && ci_qemu_arm_setup
27+
run: source tools/ci.sh && ci_qemu_setup_arm
2828
- name: Build and run test suite
29-
run: source tools/ci.sh && ci_qemu_arm_build
29+
run: source tools/ci.sh && ci_qemu_build_arm
30+
- name: Print failures
31+
if: failure()
32+
run: tests/run-tests.py --print-failures
33+
34+
build_and_test_rv32:
35+
runs-on: ubuntu-latest
36+
steps:
37+
- uses: actions/checkout@v4
38+
- name: Install packages
39+
run: source tools/ci.sh && ci_qemu_setup_rv32
40+
- name: Build and run test suite
41+
run: source tools/ci.sh && ci_qemu_build_rv32
3042
- name: Print failures
3143
if: failure()
3244
run: tests/run-tests.py --print-failures

.github/workflows/ports_qemu-riscv.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

ports/qemu-arm/Makefile

Lines changed: 92 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
################################################################################
2+
# Initial setup of Makefile environment
3+
14
BOARD ?= MPS2_AN385
25

36
# Make the build directory reflect the board.
@@ -14,16 +17,79 @@ QSTR_DEFS = qstrdefsport.h
1417

1518
# MicroPython feature configurations
1619
MICROPY_ROM_TEXT_COMPRESSION ?= 1
20+
21+
ifeq ($(QEMU_ARCH),arm)
1722
FROZEN_MANIFEST ?= "freeze('test-frzmpy')"
23+
endif
24+
ifeq ($(QEMU_ARCH),riscv32)
25+
FROZEN_MANIFEST ?= "freeze('test-frzmpy', ('frozen_const.py', 'frozen_viper.py', 'native_frozen_align.py'))"
26+
endif
1827

1928
# include py core make definitions
2029
include $(TOP)/py/py.mk
2130
include $(TOP)/extmod/extmod.mk
2231

32+
################################################################################
33+
# ARM specific settings
34+
35+
ifeq ($(QEMU_ARCH),arm)
36+
2337
CROSS_COMPILE ?= arm-none-eabi-
2438

39+
LDFLAGS += -nostdlib
40+
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
41+
42+
SRC_C += \
43+
mcu/arm/startup.c \
44+
shared/runtime/semihosting_arm.c \
45+
46+
endif
47+
48+
################################################################################
49+
# RISC-V 32-bit specific settings
50+
51+
ifeq ($(QEMU_ARCH),riscv32)
52+
53+
CROSS_COMPILE ?= riscv64-unknown-elf-
54+
55+
GCC_VERSION = $(word 1, $(subst ., , $(shell $(CC) -dumpversion)))
56+
57+
RV32_ABI = ilp32
58+
59+
QEMU_ARGS += -bios none
60+
61+
# GCC 10 and lower do not recognise the Zicsr extension in the architecture name.
62+
ifeq ($(shell test $(GCC_VERSION) -le 10; echo $$?),0)
63+
RV32_ARCH ?= rv32imac
64+
else
65+
# Recent GCC versions explicitly require to declare extensions.
66+
RV32_ARCH ?= rv32imac_zicsr
67+
endif
68+
69+
AFLAGS += -mabi=$(RV32_ABI) -march=$(RV32_ARCH)
70+
CFLAGS += $(AFLAGS)
71+
LDFLAGS += -mabi=$(RV32_ABI) -march=$(RV32_ARCH) -Wl,-EL
72+
73+
SRC_C += \
74+
mcu/rv32/interrupts.c \
75+
mcu/rv32/startup.c \
76+
77+
SRC_BOARD_O += mcu/rv32/entrypoint.o
78+
79+
endif
80+
81+
################################################################################
82+
# Project specific settings and compiler/linker flags
83+
2584
QEMU_SYSTEM = qemu-system-$(QEMU_ARCH)
2685
QEMU_ARGS += -machine $(QEMU_MACHINE) -nographic -monitor null -semihosting
86+
QEMU_ARGS += $(QEMU_EXTRA)
87+
88+
# Specifying QEMU_DEBUG=1 will block qemu until a debugger is connected.
89+
ifeq ($(QEMU_DEBUG),1)
90+
QEMU_DEBUG_ARGS ?= -s
91+
QEMU_ARGS += -S $(QEMU_DEBUG_ARGS) $(QEMU_DEBUG_EXTRA)
92+
endif
2793

2894
INC += -I.
2995
INC += -I$(TOP)
@@ -34,6 +100,8 @@ CFLAGS += $(INC) -Wall -Wpointer-arith -Wdouble-promotion -Wfloat-conversion -We
34100
-ffunction-sections -fdata-sections
35101
CFLAGS += $(CFLAGS_EXTRA)
36102

103+
LDFLAGS += -T $(LDSCRIPT) -Wl,--gc-sections -Wl,-Map=$(@:.elf=.map)
104+
37105
# Debugging/Optimization
38106
ifeq ($(DEBUG), 1)
39107
CFLAGS += -g
@@ -42,25 +110,31 @@ else
42110
COPT += -Os -DNDEBUG
43111
endif
44112

45-
## With CoudeSourcery it's actually a little different, you just need `-T generic-m-hosted.ld`.
46-
## Although for some reason `$(LD)` will not find that linker script, it works with `$(CC)`.
47-
## It turns out that this is specific to CoudeSourcery, and ARM version of GCC ships something
48-
## else instead and according to the following files, this is what we need to pass to `$(CC).
49-
## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/makefile.conf
50-
## - gcc-arm-none-eabi-4_8-2014q1/share/gcc-arm-none-eabi/samples/src/qemu/Makefile
51-
LDFLAGS= -T $(LDSCRIPT) --gc-sections -Map=$(@:.elf=.map)
52-
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
113+
# If Picolibc is available then select it explicitly. Ubuntu 22.04 ships its
114+
# bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default
115+
# is "nosys" so a value must be provided. To avoid having per-distro
116+
# workarounds, always select Picolibc if available.
117+
PICOLIBC_SPECS = $(shell $(CC) --print-file-name=picolibc.specs)
118+
ifeq ($(PICOLIBC_SPECS),picolibc.specs)
119+
# Picolibc was not found.
120+
else
121+
$(info picolibc used $(PICOLIBC_SPECS))
122+
SPECS_FRAGMENT = --specs=$(PICOLIBC_SPECS)
123+
CFLAGS += $(SPECS_FRAGMENT)
124+
LDFLAGS += $(SPECS_FRAGMENT)
125+
endif
53126

54-
SRC_C = \
127+
################################################################################
128+
# Source files and libraries
129+
130+
SRC_C += \
55131
main.c \
56-
startup.c \
57132
uart.c \
58133
mphalport.c \
59134
shared/libc/string0.c \
60135
shared/readline/readline.c \
61136
shared/runtime/interrupt_char.c \
62137
shared/runtime/pyexec.c \
63-
shared/runtime/semihosting_arm.c \
64138
shared/runtime/stdout_helpers.c \
65139
shared/runtime/sys_stdio_mphal.c \
66140

@@ -75,6 +149,9 @@ OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
75149
# List of sources for qstr extraction
76150
SRC_QSTR += $(SRC_C) $(LIB_SRC_C)
77151

152+
################################################################################
153+
# Main targets
154+
78155
all: $(BUILD)/firmware.elf
79156

80157
.PHONY: repl
@@ -91,9 +168,11 @@ test: $(BUILD)/firmware.elf
91168
$(eval DIRNAME=ports/$(notdir $(CURDIR)))
92169
cd $(TOP)/tests && ./run-tests.py --target qemu-arm --device execpty:"$(QEMU_SYSTEM) $(QEMU_ARGS) -serial pty -kernel ../$(DIRNAME)/$<" $(RUN_TESTS_ARGS) $(RUN_TESTS_EXTRA)
93170

94-
## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here.
95171
$(BUILD)/firmware.elf: $(LDSCRIPT) $(OBJ)
96-
$(Q)$(LD) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
172+
$(Q)$(CC) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)
97173
$(Q)$(SIZE) $@
98174

175+
################################################################################
176+
# Remaining make rules
177+
99178
include $(TOP)/py/mkrules.mk

ports/qemu-arm/README.md

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
MicroPython port to qemu-arm
22
============================
33

4-
This is experimental, community-supported port for Cortex-M emulation as
5-
provided by QEMU (http://qemu.org).
4+
This is experimental, community-supported port for Cortex-M and RISC-V RV32IMC
5+
emulation as provided by QEMU (http://qemu.org).
66

77
The purposes of this port are to enable:
88

@@ -18,6 +18,25 @@ The purposes of this port are to enable:
1818
- no need to use OpenOCD or anything else that might slow down the
1919
process in terms of plugging things together, pressing buttons, etc.
2020

21+
Dependencies
22+
------------
23+
24+
### ARM
25+
26+
For ARM-based boards the build requires a bare-metal ARM toolchain, such as
27+
`arm-none-eabi-gcc`.
28+
29+
### RISC-V
30+
31+
For RISC-V-based boards the build requires a bare metal RISC-V toolchain with GCC 10
32+
or later, either with multilib support or 32 bits specific (M, C, and Zicsr
33+
extensions must be supported, along with ilp32 ABI). Both newlib and picolibc are
34+
supported, with the latter having precedence if found.
35+
36+
Most pre-built toolchains should work out of the box, either coming from your
37+
Linux distribution's package manager, or independently packaged ones like
38+
[xPack](https://xpack.github.io/dev-tools/riscv-none-elf-gcc/).
39+
2140
Build instructions
2241
------------------
2342

@@ -36,12 +55,13 @@ different board pass the `BOARD` argument to `make`, for example:
3655

3756
Available boards are:
3857

39-
| Name for `BOARD=` | Corresponding qemu board |
40-
| ----------------- | ------------------------ |
41-
| `MICROBIT` | `microbit` |
42-
| `MPS2_AN385` | `mps2-an385` |
43-
| `NETDUINO2` | `netduino2` |
44-
| `SABRELITE` | `sabrelite` |
58+
| Name for `BOARD=` | Architecture | Corresponding qemu board |
59+
| ----------------- | ------------ | ------------------------ |
60+
| `MICROBIT` | `arm` | `microbit` |
61+
| `MPS2_AN385` | `arm` | `mps2-an385` |
62+
| `NETDUINO2` | `arm` | `netduino2` |
63+
| `SABRELITE` | `arm` | `sabrelite` |
64+
| `VIRT_RV32` | `riscv32` | `virt` |
4565

4666
Running
4767
-------
@@ -84,3 +104,9 @@ The following options can be specified on the `make` command line:
84104
- `CFLAGS_EXTRA`: pass in extra flags for the compiler.
85105
- `RUN_TESTS_EXTRA`: pass in extra flags for `run-tests.py` when invoked via
86106
`make test`.
107+
- `QEMU_DEBUG=1`: when running qemu (via `repl`, `run` or `test` target), qemu
108+
will block until a debugger is connected. By default it waits for a gdb connection
109+
on TCP port 1234.
110+
- `QEMU_DEBUG_ARGS`: defaults to `-s` (gdb on TCP port 1234), but can be overridden
111+
with different qemu gdb arguments.
112+
- `QEMU_DEBUG_EXTRA`: extra options to pass to qemu when `QEMU_DEBUG=1` is used.

ports/qemu-arm/boards/MICROBIT.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft
66
CFLAGS += -DQEMU_SOC_NRF51
77
CFLAGS += -DMICROPY_HW_MCU_NAME='"nRF51"'
88

9-
LDSCRIPT = nrf51.ld
9+
LDSCRIPT = mcu/arm/nrf51.ld
1010

1111
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb1.o
1212

ports/qemu-arm/boards/MPS2_AN385.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
55
CFLAGS += -DQEMU_SOC_MPS2
66
CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-M3"'
77

8-
LDSCRIPT = mps2.ld
8+
LDSCRIPT = mcu/arm/mps2.ld
99

1010
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
1111

ports/qemu-arm/boards/NETDUINO2.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
55
CFLAGS += -DQEMU_SOC_STM32
66
CFLAGS += -DMICROPY_HW_MCU_NAME='"STM32"'
77

8-
LDSCRIPT = stm32.ld
8+
LDSCRIPT = mcu/arm/stm32.ld
99

1010
SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o
1111

ports/qemu-arm/boards/SABRELITE.mk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-A9"'
88
# Cortex-A9 should support unaligned-access, but qemu doesn't seem to.
99
CFLAGS += -mno-unaligned-access
1010

11-
LDSCRIPT = imx6.ld
11+
LDSCRIPT = mcu/arm/imx6.ld
1212

1313
SRC_BOARD_O = shared/runtime/gchelper_generic.o
1414

ports/qemu-arm/boards/VIRT_RV32.mk

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
QEMU_ARCH = riscv32
2+
QEMU_MACHINE = virt
3+
4+
CFLAGS += -DQEMU_SOC_VIRT
5+
CFLAGS += -DMICROPY_HW_MCU_NAME='"$(RV32_ARCH)"'
6+
7+
LDSCRIPT = mcu/rv32/virt.ld
8+
9+
SRC_BOARD_O += shared/runtime/gchelper_native.o shared/runtime/gchelper_rv32i.o
10+
11+
MPY_CROSS_FLAGS += -march=rv32imc
12+
13+
# These Thumb tests don't run on RV32, so exclude them.
14+
RUN_TESTS_ARGS = --exclude 'inlineasm|qemu-arm/asm_test'
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

ports/qemu-arm/mpconfigport.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@
3737
#define MICROPY_EMIT_THUMB (1)
3838
#define MICROPY_EMIT_INLINE_THUMB (1)
3939
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))
40+
#elif defined(__riscv)
41+
#define MICROPY_EMIT_RV32 (1)
4042
#endif
4143

4244
#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1)
@@ -47,7 +49,11 @@
4749
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
4850
#define MICROPY_WARNINGS (1)
4951
#define MICROPY_PY_IO_IOBASE (0)
52+
#if defined(__ARM_ARCH)
5053
#define MICROPY_PY_SYS_PLATFORM "qemu-arm"
54+
#elif defined(__riscv)
55+
#define MICROPY_PY_SYS_PLATFORM "qemu-riscv32"
56+
#endif
5157
#define MICROPY_PY_SYS_STDIO_BUFFER (0)
5258
#define MICROPY_PY_SELECT (0)
5359
#define MICROPY_PY_TIME (0)

ports/qemu-arm/mphalport.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include <stddef.h>
2728
#include "shared/runtime/interrupt_char.h"

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy