diff options
author | Damien George <damien@micropython.org> | 2024-08-12 11:32:28 +1000 |
---|---|---|
committer | Damien George <damien@micropython.org> | 2024-08-28 11:52:08 +1000 |
commit | d9a0fdda9a7b0db55c1115b55bb1b83cd5ce739c (patch) | |
tree | 5a87d4ffe4dd8219e5e8303a1d14ba87ab7fb442 | |
parent | 8a3842eba7db90af2b29035c5c1ecfd5b140f493 (diff) |
qemu-arm: Rework to provide a REPL and run tests via a pty serial port.
Currently, the qemu-arm (and qemu-riscv) port has two build modes:
- a simple test that executes a Python string; and
- a full test that uses tinytest to embed all tests within the firmware,
then executes that and captures the output.
This is very different to all the other ports. A difficulty with using
tinytest is that with the large number of tests the firmware overflows its
virtual flash size. It's also hard to run tests via .mpy files and with
the native emitter. Being different to the other ports also means an extra
burden on maintenance.
This commit reworks the qemu-arm port so that it has a single build target
that creates a standard firmware which has a REPL. When run under
qemu-system-arm, the REPL acts like any other bare-metal port, complete
with soft reset (use machine.reset() to turn it off and exit
qemu-system-arm).
This approach gives many benefits:
- allows playing with a REPL without hardware;
- allows running the test suite as it would on a bare-metal board, by
making qemu-system-arm redirect the UART serial of the virtual device to
a /dev/pts/xx file, and then running run-tests.py against that serial
device;
- skipping tests is now done via the logic in `run-tests.py` and no longer
needs multiple places to define which tests to skip
(`tools/tinytest-codegen.py`, `ports/qemu-arm/tests_profile.txt` and also
`tests/run-tests.py`);
- allows testing/using mpremote with the qemu-arm port.
Eventually the qemu-riscv port would have a similar change.
Prior to this commit the test results were:
743 tests ok. (121 skipped)
With this commit the test results are:
753 tests performed (22673 individual testcases)
753 tests passed
138 tests skipped
More tests are skipped because more are included in the run. But overall
more tests pass.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r-- | .github/workflows/ports_qemu-arm.yml | 2 | ||||
-rw-r--r-- | ports/qemu-arm/Makefile | 41 | ||||
-rw-r--r-- | ports/qemu-arm/Makefile.test | 33 | ||||
-rw-r--r-- | ports/qemu-arm/README.md | 59 | ||||
-rw-r--r-- | ports/qemu-arm/main.c | 53 | ||||
-rw-r--r-- | ports/qemu-arm/modmachine.c | 16 | ||||
-rw-r--r-- | ports/qemu-arm/mpconfigport.h | 13 | ||||
-rw-r--r-- | ports/qemu-arm/mphalport.c | 66 | ||||
-rw-r--r-- | ports/qemu-arm/mphalport.h | 5 | ||||
-rw-r--r-- | ports/qemu-arm/startup.c | 29 | ||||
-rw-r--r-- | ports/qemu-arm/tests_profile.txt | 16 | ||||
-rw-r--r-- | ports/qemu-riscv/Makefile | 2 | ||||
-rw-r--r-- | ports/qemu-riscv/main.c (renamed from ports/qemu-arm/test_main.c) | 38 | ||||
-rwxr-xr-x | tests/run-tests.py | 12 | ||||
-rwxr-xr-x | tools/ci.sh | 6 |
15 files changed, 237 insertions, 154 deletions
diff --git a/.github/workflows/ports_qemu-arm.yml b/.github/workflows/ports_qemu-arm.yml index db3cd7871..99750b753 100644 --- a/.github/workflows/ports_qemu-arm.yml +++ b/.github/workflows/ports_qemu-arm.yml @@ -29,4 +29,4 @@ jobs: run: source tools/ci.sh && ci_qemu_arm_build - name: Print failures if: failure() - run: grep --before-context=100 --text "FAIL" ports/qemu-arm/build/console.out + run: tests/run-tests.py --print-failures diff --git a/ports/qemu-arm/Makefile b/ports/qemu-arm/Makefile index 5ff63bf7d..cdfc39580 100644 --- a/ports/qemu-arm/Makefile +++ b/ports/qemu-arm/Makefile @@ -11,14 +11,19 @@ QSTR_DEFS = qstrdefsport.h # MicroPython feature configurations MICROPY_ROM_TEXT_COMPRESSION ?= 1 +FROZEN_MANIFEST ?= "freeze('test-frzmpy')" # include py core make definitions include $(TOP)/py/py.mk include $(TOP)/extmod/extmod.mk +CFLAGS += -DMICROPY_HW_BOARD_NAME='"$(BOARD)"' +QEMU_ARGS += -machine $(BOARD) -nographic -monitor null -semihosting + ifeq ($(BOARD),netduino2) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_STM32 +CFLAGS += -DMICROPY_HW_MCU_NAME='"STM32"' LDSCRIPT = stm32.ld SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o MPY_CROSS_FLAGS += -march=armv7m @@ -27,8 +32,9 @@ endif ifeq ($(BOARD),microbit) CFLAGS += -mthumb -mcpu=cortex-m0 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_NRF51 +CFLAGS += -DMICROPY_HW_MCU_NAME='"nRF51"' LDSCRIPT = nrf51.ld -QEMU_EXTRA = -global nrf51-soc.flash-size=1048576 -global nrf51-soc.sram-size=262144 +QEMU_ARGS += -global nrf51-soc.flash-size=1048576 -global nrf51-soc.sram-size=262144 SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb1.o MPY_CROSS_FLAGS += -march=armv7m endif @@ -36,6 +42,7 @@ endif ifeq ($(BOARD),mps2-an385) CFLAGS += -mthumb -mcpu=cortex-m3 -mfloat-abi=soft CFLAGS += -DQEMU_SOC_MPS2 +CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-M3"' LDSCRIPT = mps2.ld SRC_BOARD_O = shared/runtime/gchelper_native.o shared/runtime/gchelper_thumb2.o MPY_CROSS_FLAGS += -march=armv7m @@ -44,11 +51,16 @@ endif ifeq ($(BOARD),sabrelite) CFLAGS += -mcpu=cortex-a9 CFLAGS += -DQEMU_SOC_IMX6 +CFLAGS += -DMICROPY_HW_MCU_NAME='"Cortex-A9"' LDSCRIPT = imx6.ld -QEMU_EXTRA = -m 128M +QEMU_ARGS += -m 128M SRC_BOARD_O = shared/runtime/gchelper_generic.o # It's really armv7a but closest supported value is armv6. MPY_CROSS_FLAGS += -march=armv6 +# Cortex-A9 should support unaligned-access, but qemu doesn't seem to. +CFLAGS += -mno-unaligned-access +# These don't work on Cortex-A9. +TESTS_EXCLUDE = --exclude '(asmdiv|asmspecialregs).py' endif CROSS_COMPILE ?= arm-none-eabi- @@ -81,16 +93,18 @@ LIBS = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name) SRC_COMMON_C = \ startup.c \ uart.c \ + mphalport.c \ shared/libc/string0.c \ + shared/readline/readline.c \ + shared/runtime/interrupt_char.c \ + shared/runtime/pyexec.c \ + shared/runtime/semihosting_arm.c \ + shared/runtime/stdout_helpers.c \ shared/runtime/sys_stdio_mphal.c \ SRC_RUN_C = \ main.c \ -SRC_TEST_C = \ - test_main.c \ - lib/tinytest/tinytest.c \ - LIB_SRC_C += $(SRC_LIB_LIBM_C) LIB_SRC_C += $(SRC_LIB_LIBM_SQRT_SW_C) @@ -116,10 +130,21 @@ OBJ = $(OBJ_COMMON) $(OBJ_RUN) $(OBJ_TEST) # List of sources for qstr extraction SRC_QSTR += $(SRC_COMMON_C) $(SRC_RUN_C) $(LIB_SRC_C) -all: run +all: $(BUILD)/firmware.elf +.PHONY: repl +repl: $(BUILD)/firmware.elf + $(ECHO) "Use machine.reset() to exit" + qemu-system-arm $(QEMU_ARGS) -serial mon:stdio -kernel $< + +.PHONY: run run: $(BUILD)/firmware.elf - qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< + qemu-system-arm $(QEMU_ARGS) -serial pty -kernel $< + +.PHONY: test +test: $(BUILD)/firmware.elf + $(eval DIRNAME=ports/$(notdir $(CURDIR))) + cd $(TOP)/tests && ./run-tests.py --target qemu-arm --device execpty:"qemu-system-arm $(QEMU_ARGS) -serial pty -kernel ../$(DIRNAME)/$<" $(TESTS_EXCLUDE) ## `$(LD)` doesn't seem to like `--specs` for some reason, but we can just use `$(CC)` here. $(BUILD)/firmware.elf: $(LDSCRIPT) $(ALL_OBJ_RUN) diff --git a/ports/qemu-arm/Makefile.test b/ports/qemu-arm/Makefile.test deleted file mode 100644 index cb5b0927c..000000000 --- a/ports/qemu-arm/Makefile.test +++ /dev/null @@ -1,33 +0,0 @@ -LIB_SRC_C = shared/upytesthelper/upytesthelper.c - -FROZEN_MANIFEST ?= "freeze('test-frzmpy')" - -include Makefile - -ifeq ($(BOARD),sabrelite) -# These don't work on Cortex-A9. -TESTS_EXCLUDE = inlineasm/asmdiv.py inlineasm/asmspecialregs.py -endif - -CFLAGS += -DTEST - -.PHONY: $(BUILD)/genhdr/tests.h - -TESTS_PROFILE = $(dir $(abspath $(firstword $(MAKEFILE_LIST))))/tests_profile.txt - -$(BUILD)/test_main.o: $(BUILD)/genhdr/tests.h -$(BUILD)/genhdr/tests.h: - (cd $(TOP)/tests; ./run-tests.py --target=qemu-arm --write-exp) - $(Q)echo "Generating $@";(cd $(TOP)/tests; ../tools/tinytest-codegen.py --profile $(TESTS_PROFILE) $(addprefix --exclude ,$(TESTS_EXCLUDE))) > $@ - -$(BUILD)/lib/tinytest/tinytest.o: CFLAGS += -DNO_FORKING - -$(BUILD)/firmware-test.elf: $(LDSCRIPT) $(ALL_OBJ_TEST) - $(Q)$(LD) $(LDFLAGS) -o $@ $(ALL_OBJ_TEST) $(LIBS) - $(Q)$(SIZE) $@ - -# Note: Using timeout(1) to handle cases where qemu hangs (e.g. this can happen with alignment errors). -test: $(BUILD)/firmware-test.elf - timeout --foreground -k 5s 30s qemu-system-arm -machine $(BOARD) $(QEMU_EXTRA) -nographic -monitor null -semihosting -kernel $< > $(BUILD)/console.out - $(Q)tail -n2 $(BUILD)/console.out - $(Q)tail -n1 $(BUILD)/console.out | grep -q "status: 0" diff --git a/ports/qemu-arm/README.md b/ports/qemu-arm/README.md index f821c4d1e..34d73fd16 100644 --- a/ports/qemu-arm/README.md +++ b/ports/qemu-arm/README.md @@ -1,3 +1,6 @@ +MicroPython port to qemu-arm +============================ + This is experimental, community-supported port for Cortex-M emulation as provided by QEMU (http://qemu.org). @@ -15,14 +18,52 @@ The purposes of this port are to enable: - no need to use OpenOCD or anything else that might slow down the process in terms of plugging things together, pressing buttons, etc. -This port will only work with the [GNU ARM Embedded Toolchain]( -https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads - and not with CodeSourcery toolchain. You will need to modify -`LDFLAGS` if you want to use CodeSourcery's version of `arm-none-eabi`. -The difference is that CodeSourcery needs `-T generic-m-hosted.ld` while -ARM's version requires `--specs=nano.specs --specs=rdimon.specs` to be -passed to the linker. +Build instructions +------------------ + +First make sure the MicroPython cross-compiler is built (run from this directory): + + $ make -C ../../mpy-cross + +Then build using: + + $ make + +The default qemu-supported board is `mps2-an385`, a Cortex-M3 board. To select a +different board pass the `BOARD` argument to `make`, for example: + + $ make BOARD=sabrelite + +Running +------- + +When the firmware is run it will provide a REPL on the emulated hardware UART. +To access the REPL directly use: + + $ make repl + +This will start `qemu-system-arm` with the UART redirected to stdio. It's also +possible to redirect the UART to a pty device using: + + $ make run + +This will start the emulation and the name of the pty device will be printed to +stdout. This serial device then be accessed via a serial terminal program, +for example `mpremote`: + + $ mpremote connect /dev/pts/1 + +You can disconnect and reconnect to the serial device multiple times. Once you +are finished, stop the `make run` command by pressing Ctrl-C where that command +was started (or execute `machine.reset()` at the REPL). + +The test suite can be run against the firmware by using the UART redirection. +You can either do this automatically using the single command: + + $ make test -To build and run image with builtin testsuite: +Or manually by first starting the emulation with `make run` and then running the +tests against the serial device, for example: - make -f Makefile.test test + $ cd ../../tests + $ ./run-tests.py --target qemu-arm --device /dev/pts/1 diff --git a/ports/qemu-arm/main.c b/ports/qemu-arm/main.c index 025c1f17d..042106580 100644 --- a/ports/qemu-arm/main.c +++ b/ports/qemu-arm/main.c @@ -25,41 +25,50 @@ */ #include <stdlib.h> -#include <stdio.h> #include "py/compile.h" #include "py/runtime.h" #include "py/stackctrl.h" #include "py/gc.h" #include "py/mperrno.h" +#include "shared/runtime/gchelper.h" +#include "shared/runtime/pyexec.h" -void do_str(const char *src, mp_parse_input_kind_t input_kind) { - nlr_buf_t nlr; - if (nlr_push(&nlr) == 0) { - mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); - qstr source_name = lex->source_name; - mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); - mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); - mp_call_function_0(module_fun); - nlr_pop(); - } else { - // uncaught exception - mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); - } -} +#define HEAP_SIZE (100 * 1024) + +static uint32_t gc_heap[HEAP_SIZE / sizeof(uint32_t)]; int main(int argc, char **argv) { mp_stack_ctrl_init(); mp_stack_set_limit(10240); - uint32_t heap[16 * 1024 / 4]; - gc_init(heap, (char *)heap + 16 * 1024); - mp_init(); - do_str("print('hello world!')", MP_PARSE_SINGLE_INPUT); - mp_deinit(); - return 0; + gc_init(gc_heap, (char *)gc_heap + HEAP_SIZE); + + for (;;) { + mp_init(); + + for (;;) { + if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { + if (pyexec_raw_repl() != 0) { + break; + } + } else { + if (pyexec_friendly_repl() != 0) { + break; + } + } + } + + mp_printf(&mp_plat_print, "MPY: soft reboot\n"); + + gc_sweep_all(); + mp_deinit(); + } } void gc_collect(void) { + gc_collect_start(); + gc_helper_collect_regs_and_stack(); + gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(qstr filename) { @@ -67,6 +76,6 @@ mp_lexer_t *mp_lexer_new_from_file(qstr filename) { } void nlr_jump_fail(void *val) { - printf("uncaught NLR\n"); + mp_printf(&mp_plat_print, "uncaught NLR\n"); exit(1); } diff --git a/ports/qemu-arm/modmachine.c b/ports/qemu-arm/modmachine.c index a897c5670..75872a22c 100644 --- a/ports/qemu-arm/modmachine.c +++ b/ports/qemu-arm/modmachine.c @@ -27,6 +27,22 @@ // This file is never compiled standalone, it's included directly from // extmod/modmachine.c via MICROPY_PY_MACHINE_INCLUDEFILE. +#include <stdlib.h> + static void mp_machine_idle(void) { // Do nothing. } + +#if MICROPY_PY_MACHINE_RESET + +static void mp_machine_reset(void) { + // Exit qemu (via semihosting call). + exit(0); +} + +static mp_int_t mp_machine_reset_cause(void) { + // Not implemented. + return 0; +} + +#endif diff --git a/ports/qemu-arm/mpconfigport.h b/ports/qemu-arm/mpconfigport.h index fce379e47..4059a5926 100644 --- a/ports/qemu-arm/mpconfigport.h +++ b/ports/qemu-arm/mpconfigport.h @@ -42,22 +42,19 @@ #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) #define MICROPY_MEM_STATS (1) #define MICROPY_ENABLE_GC (1) -#define MICROPY_KBD_EXCEPTION (0) -#define MICROPY_HELPER_REPL (0) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT) #define MICROPY_WARNINGS (1) -#define MICROPY_PY_BUILTINS_INPUT (0) -#define MICROPY_PY_BUILTINS_HELP (0) #define MICROPY_PY_IO_IOBASE (0) #define MICROPY_PY_SYS_PLATFORM "qemu-arm" -#define MICROPY_PY_SYS_STDFILES (0) #define MICROPY_PY_SYS_STDIO_BUFFER (0) #define MICROPY_PY_SELECT (0) #define MICROPY_PY_TIME (0) #define MICROPY_PY_ASYNCIO (0) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_INCLUDEFILE "ports/qemu-arm/modmachine.c" +#define MICROPY_PY_MACHINE_RESET (1) #define MICROPY_PY_MACHINE_PIN_BASE (1) #define MICROPY_VFS (1) @@ -78,8 +75,4 @@ typedef long mp_off_t; // We need an implementation of the log2 function which is not a macro. #define MP_NEED_LOG2 (1) -#ifdef TEST -#include "shared/upytesthelper/upytesthelper.h" -#undef MP_PLAT_PRINT_STRN -#define MP_PLAT_PRINT_STRN(str, len) upytest_output(str, len) -#endif +#define MP_STATE_PORT MP_STATE_VM diff --git a/ports/qemu-arm/mphalport.c b/ports/qemu-arm/mphalport.c new file mode 100644 index 000000000..dbb87b48b --- /dev/null +++ b/ports/qemu-arm/mphalport.c @@ -0,0 +1,66 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2024 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "py/mphal.h" +#include "shared/runtime/semihosting_arm.h" +#include "uart.h" + +// UART is better behaved with redirection under qemu-system-arm, so prefer that for stdio. +#define USE_UART (1) +#define USE_SEMIHOSTING (0) + +uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) { + // Not implemented. + return 0; +} + +int mp_hal_stdin_rx_chr(void) { + for (;;) { + #if USE_UART + int c = uart_rx_chr(); + if (c >= 0) { + return c; + } + #endif + #if USE_SEMIHOSTING + char str[1]; + int ret = mp_semihosting_rx_chars(str, 1); + if (ret == 0) { + return str[0]; + } + #endif + } +} + +mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) { + #if USE_UART + uart_tx_strn(str, len); + #endif + #if USE_SEMIHOSTING + mp_semihosting_tx_strn(str, len); + #endif + return len; +} diff --git a/ports/qemu-arm/mphalport.h b/ports/qemu-arm/mphalport.h index 8a40505ba..348b45701 100644 --- a/ports/qemu-arm/mphalport.h +++ b/ports/qemu-arm/mphalport.h @@ -24,7 +24,4 @@ * THE SOFTWARE. */ -#include "uart.h" - -#define mp_hal_stdin_rx_chr() (0) -#define mp_hal_stdout_tx_strn_cooked(s, l) uart_tx_strn((s), (l)) +#include "shared/runtime/interrupt_char.h" diff --git a/ports/qemu-arm/startup.c b/ports/qemu-arm/startup.c index a1e89d111..118a5b800 100644 --- a/ports/qemu-arm/startup.c +++ b/ports/qemu-arm/startup.c @@ -28,6 +28,7 @@ #include <stdio.h> #include <stdlib.h> +#include "shared/runtime/semihosting_arm.h" #include "uart.h" extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss; @@ -97,6 +98,8 @@ const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = { #endif void _start(void) { + mp_semihosting_init(); + // Enable the UART uart_init(); @@ -108,21 +111,9 @@ void _start(void) { exit(0); } -__attribute__((naked)) void exit(int status) { +void exit(int status) { // Force qemu to exit using ARM Semihosting - __asm volatile ( - "mov r1, r0\n" - "cmp r1, #0\n" - "bne .notclean\n" - "ldr r1, =0x20026\n" // ADP_Stopped_ApplicationExit, a clean exit - ".notclean:\n" - "movs r0, #0x18\n" // SYS_EXIT - #if defined(__ARM_ARCH_ISA_ARM) - "svc 0x00123456\n" - #elif defined(__ARM_ARCH_ISA_THUMB) - "bkpt 0xab\n" - #endif - ); + mp_semihosting_exit(status); for (;;) { } } @@ -134,13 +125,3 @@ void __assert_func(const char *file, int line, const char *func, const char *exp exit(1); } #endif - -// The following are needed for tinytest - -#include <stdio.h> - -int setvbuf(FILE *stream, char *buf, int mode, size_t size) { - return 0; -} - -struct _reent *_impure_ptr; diff --git a/ports/qemu-arm/tests_profile.txt b/ports/qemu-arm/tests_profile.txt deleted file mode 100644 index 101943b7c..000000000 --- a/ports/qemu-arm/tests_profile.txt +++ /dev/null @@ -1,16 +0,0 @@ -# Port-specific test directories. - -test_dirs.update(("inlineasm", "ports/qemu-arm")) - -# Port-specific tests exclusion list. - -exclude_tests.update( - ( - # inline asm FP tests (require Cortex-M4) - "inlineasm/asmfpaddsub.py", - "inlineasm/asmfpcmp.py", - "inlineasm/asmfpldrstr.py", - "inlineasm/asmfpmuldiv.py", - "inlineasm/asmfpsqrt.py", - ) -) diff --git a/ports/qemu-riscv/Makefile b/ports/qemu-riscv/Makefile index 6f15ce52e..473aec882 100644 --- a/ports/qemu-riscv/Makefile +++ b/ports/qemu-riscv/Makefile @@ -81,7 +81,7 @@ SRC_COMMON_C = \ shared/runtime/sys_stdio_mphal.c \ SRC_RUN_C = \ - ports/qemu-arm/main.c \ + main.c \ SRC_TEST_C = \ test_main.c \ diff --git a/ports/qemu-arm/test_main.c b/ports/qemu-riscv/main.c index 96984f7cd..025c1f17d 100644 --- a/ports/qemu-arm/test_main.c +++ b/ports/qemu-riscv/main.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2014 Ilya Dmitrichenko + * Copyright (c) 2014-2023 Damien P. George * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -32,28 +32,34 @@ #include "py/stackctrl.h" #include "py/gc.h" #include "py/mperrno.h" -#include "shared/runtime/gchelper.h" -#include "lib/tinytest/tinytest.h" -#include "lib/tinytest/tinytest_macros.h" -#define HEAP_SIZE (100 * 1024) - -#include "genhdr/tests.h" +void do_str(const char *src, mp_parse_input_kind_t input_kind) { + nlr_buf_t nlr; + if (nlr_push(&nlr) == 0) { + mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0); + qstr source_name = lex->source_name; + mp_parse_tree_t parse_tree = mp_parse(lex, input_kind); + mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true); + mp_call_function_0(module_fun); + nlr_pop(); + } else { + // uncaught exception + mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); + } +} -int main() { +int main(int argc, char **argv) { mp_stack_ctrl_init(); mp_stack_set_limit(10240); - static uint32_t heap[HEAP_SIZE / sizeof(uint32_t)]; - upytest_set_heap(heap, (char *)heap + HEAP_SIZE); - int r = tinytest_main(0, NULL, groups); - printf("status: %d\n", r); - return r; + uint32_t heap[16 * 1024 / 4]; + gc_init(heap, (char *)heap + 16 * 1024); + mp_init(); + do_str("print('hello world!')", MP_PARSE_SINGLE_INPUT); + mp_deinit(); + return 0; } void gc_collect(void) { - gc_collect_start(); - gc_helper_collect_regs_and_stack(); - gc_collect_end(); } mp_lexer_t *mp_lexer_new_from_file(qstr filename) { diff --git a/tests/run-tests.py b/tests/run-tests.py index d0c93f74b..60bfc2599 100755 --- a/tests/run-tests.py +++ b/tests/run-tests.py @@ -676,7 +676,11 @@ def run_tests(pyb, tests, args, result_dir, num_threads=1): "extmod/time_time_ns.py" ) # RA fsp rtc function doesn't support nano sec info elif args.target == "qemu-arm": - skip_tests.add("misc/print_exception.py") # requires sys stdfiles + skip_tests.add("inlineasm/asmfpaddsub.py") # requires Cortex-M4 + skip_tests.add("inlineasm/asmfpcmp.py") + skip_tests.add("inlineasm/asmfpldrstr.py") + skip_tests.add("inlineasm/asmfpmuldiv.py") + skip_tests.add("inlineasm/asmfpsqrt.py") elif args.target == "qemu-riscv": skip_tests.add("misc/print_exception.py") # requires sys stdfiles elif args.target == "webassembly": @@ -1043,7 +1047,6 @@ the last matching regex is used: LOCAL_TARGETS = ( "unix", - "qemu-arm", "qemu-riscv", "webassembly", ) @@ -1054,6 +1057,7 @@ the last matching regex is used: "esp32", "minimal", "nrf", + "qemu-arm", "renesas-ra", "rp2", ) @@ -1141,10 +1145,6 @@ the last matching regex is used: "ports/unix", ) elif args.target == "qemu-arm": - if not args.write_exp: - raise ValueError("--target=qemu-arm must be used with --write-exp") - # Generate expected output files for qemu run. - # This list should match the test_dirs tuple in tinytest-codegen.py. test_dirs += ( "float", "inlineasm", diff --git a/tools/ci.sh b/tools/ci.sh index 7353a3ecd..175d7f576 100755 --- a/tools/ci.sh +++ b/tools/ci.sh @@ -258,10 +258,8 @@ function ci_qemu_arm_build { make ${MAKEOPTS} -C ports/qemu-arm submodules make ${MAKEOPTS} -C ports/qemu-arm CFLAGS_EXTRA=-DMP_ENDIANNESS_BIG=1 make ${MAKEOPTS} -C ports/qemu-arm clean - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test submodules - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test test - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test clean - make ${MAKEOPTS} -C ports/qemu-arm -f Makefile.test BOARD=sabrelite test + make ${MAKEOPTS} -C ports/qemu-arm test + make ${MAKEOPTS} -C ports/qemu-arm BOARD=sabrelite test } ######################################################################################## |