Skip to content

Commit a8d7fa0

Browse files
committed
qemu-arm: Merge RISC-V 32-bit support into qemu-arm port.
Signed-off-by: Damien George <damien@micropython.org>
1 parent 9647f9c commit a8d7fa0

31 files changed

+152
-586
lines changed

.github/workflows/ports_qemu-riscv.yml

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

ports/qemu-arm/Makefile

Lines changed: 51 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,18 @@ QSTR_DEFS = qstrdefsport.h
1414

1515
# MicroPython feature configurations
1616
MICROPY_ROM_TEXT_COMPRESSION ?= 1
17+
18+
ifeq ($(QEMU_ARCH),arm)
1719
FROZEN_MANIFEST ?= "freeze('test-frzmpy')"
20+
endif
21+
ifeq ($(QEMU_ARCH),riscv32)
22+
FROZEN_MANIFEST ?= "freeze('test-frzmpy', ('frozen_const.py', 'frozen_viper.py', 'native_frozen_align.py'))"
23+
endif
1824

1925
# include py core make definitions
2026
include $(TOP)/py/py.mk
2127
include $(TOP)/extmod/extmod.mk
2228

23-
CROSS_COMPILE ?= arm-none-eabi-
24-
2529
QEMU_SYSTEM = qemu-system-$(QEMU_ARCH)
2630
QEMU_ARGS += -machine $(QEMU_MACHINE) -nographic -monitor null -semihosting
2731

@@ -42,6 +46,10 @@ else
4246
COPT += -Os -DNDEBUG
4347
endif
4448

49+
ifeq ($(QEMU_ARCH),arm)
50+
51+
CROSS_COMPILE ?= arm-none-eabi-
52+
4553
## With CoudeSourcery it's actually a little different, you just need `-T generic-m-hosted.ld`.
4654
## Although for some reason `$(LD)` will not find that linker script, it works with `$(CC)`.
4755
## It turns out that this is specific to CoudeSourcery, and ARM version of GCC ships something
@@ -51,16 +59,49 @@ endif
5159
LDFLAGS= -T $(LDSCRIPT) --gc-sections -Map=$(@:.elf=.map)
5260
LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
5361

54-
SRC_C = \
62+
SRC_C += \
63+
mcu/arm/startup.c \
64+
shared/runtime/semihosting_arm.c \
65+
66+
endif
67+
68+
ifeq ($(QEMU_ARCH),riscv32)
69+
70+
CROSS_COMPILE ?= riscv64-unknown-elf-
71+
72+
# If Picolibc is available then select it explicitly. Ubuntu 22.04 ships its
73+
# bare metal RISC-V toolchain with Picolibc rather than Newlib, and the default
74+
# is "nosys" so a value must be provided. To avoid having per-distro
75+
# workarounds, always select Picolibc if available.
76+
PICOLIBC_SPECS = $(shell $(CC) --print-file-name=picolibc.specs)
77+
ifeq ($(PICOLIBC_SPECS),picolibc.specs)
78+
# Picolibc was not found.
79+
SPECS_FRAGMENT =
80+
else
81+
SPECS_FRAGMENT = --specs=$(PICOLIBC_SPECS)
82+
CFLAGS += $(SPECS_FRAGMENT)
83+
endif
84+
85+
LD = $(CC)
86+
87+
LDFLAGS += $(SPECS_FRAGMENT) -Wl,--gc-sections -Wl,-Map=$(@:.elf=.map)
88+
89+
SRC_C += \
90+
mcu/rv32/interrupts.c \
91+
mcu/rv32/startup.c \
92+
93+
QEMU_ARGS += -bios none
94+
95+
endif
96+
97+
SRC_C += \
5598
main.c \
56-
startup.c \
5799
uart.c \
58100
mphalport.c \
59101
shared/libc/string0.c \
60102
shared/readline/readline.c \
61103
shared/runtime/interrupt_char.c \
62104
shared/runtime/pyexec.c \
63-
shared/runtime/semihosting_arm.c \
64105
shared/runtime/stdout_helpers.c \
65106
shared/runtime/sys_stdio_mphal.c \
66107

@@ -86,6 +127,11 @@ repl: $(BUILD)/firmware.elf
86127
run: $(BUILD)/firmware.elf
87128
$(QEMU_SYSTEM) $(QEMU_ARGS) -serial pty -kernel $<
88129

130+
# `make debug` will block QEMU until a debugger is connected to port 1234.
131+
.PHONY: debug
132+
debug: $(BUILD)/firmware.elf
133+
$(QEMU_SYSTEM) $(QEMU_ARGS) -serial mon:stdio -S -s -kernel $<
134+
89135
.PHONY: test
90136
test: $(BUILD)/firmware.elf
91137
$(eval DIRNAME=ports/$(notdir $(CURDIR)))

ports/qemu-arm/README.md

Lines changed: 21 additions & 2 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

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: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
QEMU_ARCH = riscv32
2+
QEMU_MACHINE = virt
3+
4+
ABI = ilp32
5+
# GCC 10 and lower do not recognise the Zicsr extension in the
6+
# architecture name. "Make" unfortunately does not provide any simple way
7+
# to perform numeric comparisons, so to keep things simple we assume that
8+
# GCC is at least version 10 for the time being.
9+
GCC_VERSION = $(word 1, $(subst ., , $(shell $(CC) -dumpversion)))
10+
ifeq ($(GCC_VERSION),10)
11+
ARCH ?= rv32imac
12+
else
13+
# Recent GCC versions explicitly require to declare extensions.
14+
ARCH ?= rv32imac_zicsr
15+
ARCH_LD ?= rv32imac_zicsr
16+
endif
17+
18+
AFLAGS += -mabi=$(ABI) -march=$(ARCH)
19+
CFLAGS += $(AFLAGS)
20+
CFLAGS += -DQEMU_SOC_VIRT
21+
CFLAGS += -DMICROPY_HW_MCU_NAME='"$(ARCH)"'
22+
23+
ARCH_LD ?= $(ARCH)
24+
LDSCRIPT = mcu/rv32/virt.ld
25+
LDFLAGS += -mabi=$(ABI) -march=$(ARCH_LD) -T $(LDSCRIPT) -Wl,-EL
26+
27+
SRC_BOARD_O += shared/runtime/gchelper_native.o shared/runtime/gchelper_rv32i.o
28+
SRC_BOARD_O += rv/entrypoint.o
29+
30+
MPY_CROSS_FLAGS += -march=rv32imc
31+
32+
# These Thumb tests don't run on RV32.
33+
TESTS_EXCLUDE = --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/uart.c

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
*
44
* The MIT License (MIT)
55
*
6-
* Copyright (c) 2018-2021 Damien P. George
6+
* Copyright (c) 2018-2024 Damien P. George
7+
* Copyright (c) 2023 Alessandro Gatti
78
*
89
* Permission is hereby granted, free of charge, to any person obtaining a copy
910
* of this software and associated documentation files (the "Software"), to deal
@@ -175,4 +176,36 @@ void uart_tx_strn(const char *buf, size_t len) {
175176
}
176177
}
177178

179+
#elif defined(QEMU_SOC_VIRT)
180+
181+
// Line status register bits.
182+
#define UART_LSR_THRE (0x20)
183+
#define UART_LSR_DR (0x01)
184+
185+
typedef struct _UART_t {
186+
volatile uint8_t DR;
187+
volatile uint8_t r0[4];
188+
volatile uint8_t LSR;
189+
} UART_t;
190+
191+
#define UART0 ((UART_t *)(0x10000000))
192+
193+
void uart_init(void) {
194+
}
195+
196+
int uart_rx_chr(void) {
197+
if (UART0->LSR & UART_LSR_DR) {
198+
return UART0->DR;
199+
}
200+
return UART_RX_NO_CHAR;
201+
}
202+
203+
void uart_tx_strn(const char *buffer, size_t length) {
204+
for (size_t index = 0; index < length; index++) {
205+
while (!(UART0->LSR & UART_LSR_THRE)) {
206+
}
207+
UART0->DR = buffer[index];
208+
}
209+
}
210+
178211
#endif

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