From 16db37e7c6b5bab9636ea671c5461bcc4418d3d8 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Mon, 1 May 2023 15:11:19 +0200 Subject: [PATCH] examples/embedding-full: Add a more full-featured embedding example. It compiles and runs in this state, but a lot of functionality is still missing, to be extended over the following commits. Signed-off-by: Christian Walther --- .github/workflows/examples.yml | 9 +++ examples/embedding-full/Makefile | 25 ++++++++ examples/embedding-full/README.md | 41 +++++++++++++ examples/embedding-full/main.c | 62 ++++++++++++++++++++ examples/embedding-full/micropython_embed.mk | 9 +++ examples/embedding-full/mpconfigport.h | 32 ++++++++++ examples/embedding-full/mphal.c | 26 ++++++++ examples/embedding/README.md | 9 +-- ports/embed/port/mphalport.h | 4 ++ 9 files changed, 213 insertions(+), 4 deletions(-) create mode 100644 examples/embedding-full/Makefile create mode 100644 examples/embedding-full/README.md create mode 100644 examples/embedding-full/main.c create mode 100644 examples/embedding-full/micropython_embed.mk create mode 100644 examples/embedding-full/mpconfigport.h create mode 100644 examples/embedding-full/mphal.c diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 6613f10662..fe7c6640a5 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -23,3 +23,12 @@ jobs: run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding - name: Run run: ./examples/embedding/embed | grep "hello world" + + embedding-full: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Build + run: make -C examples/embedding-full -f micropython_embed.mk submodules && make -C examples/embedding-full -f micropython_embed.mk && make -C examples/embedding-full + - name: Run + run: ./examples/embedding-full/embed diff --git a/examples/embedding-full/Makefile b/examples/embedding-full/Makefile new file mode 100644 index 0000000000..c51fe5ed4d --- /dev/null +++ b/examples/embedding-full/Makefile @@ -0,0 +1,25 @@ +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2022-2023 Damien P. George +# +# This is a very simple makefile that demonstrates how to build the embed port. +# All it needs to do is build all *.c files in the micropython_embed directory. +# This makefile would be replaced with your custom build system. + +EMBED_DIR = micropython_embed +PROG = embed + +CFLAGS += -I. +CFLAGS += -I$(EMBED_DIR) +CFLAGS += -I$(EMBED_DIR)/port +CFLAGS += -Wall -Og -fno-common + +SRC += main.c mphal.c +SRC += $(wildcard $(EMBED_DIR)/*/*.c) $(wildcard $(EMBED_DIR)/*/*/*.c) +OBJ += $(SRC:.c=.o) + +$(PROG): $(OBJ) + $(CC) -o $@ $^ + +clean: + /bin/rm -f $(OBJ) $(PROG) diff --git a/examples/embedding-full/README.md b/examples/embedding-full/README.md new file mode 100644 index 0000000000..a185e16b2b --- /dev/null +++ b/examples/embedding-full/README.md @@ -0,0 +1,41 @@ +Example of embedding MicroPython in a standalone C application (full) +===================================================================== + +This directory contains a simple example of how to embed a full-featured +version of MicroPython in an existing C application. +See also _embedding_ for a more minimal version. + +A C application is represented here by the file `main.c`. It executes two +simple Python scripts which print things to the standard output. +Functions used by the MicroPython core that need to be provided by the +application are implemented in `mphal.c`. + +Building the example +-------------------- + +First build the embed port using: + + $ make -f micropython_embed.mk submodules + $ make -f micropython_embed.mk + +This will generate the `micropython_embed` directory which is a self-contained +copy of MicroPython suitable for embedding. The .c files in this directory need +to be compiled into your project, in whatever way your project can do that. The +example here uses make and a provided `Makefile`. + +To build the example project, based on `main.c`, use: + + $ make + +That will create an executable called `embed` which you can run: + + $ ./embed + +Out of tree build +----------------- + +This example is set up to work out of the box, being part of the MicroPython +tree. Your application will be outside of this tree, but the only thing you +need to do for that is to change `MICROPYTHON_TOP` (found in `micropython_embed.mk`) +to point to the location of the MicroPython repository. The MicroPython +repository may, for example, be a git submodule in your project. diff --git a/examples/embedding-full/main.c b/examples/embedding-full/main.c new file mode 100644 index 0000000000..f0cdb0c1c3 --- /dev/null +++ b/examples/embedding-full/main.c @@ -0,0 +1,62 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022-2023 Damien P. George + */ + +#include "port/micropython_embed.h" +#include "py/stackctrl.h" + +// This is example 1 script, which will be compiled and executed. +static const char *example_1 = + "print('hello world!', list(x + 1 for x in range(10)), end='eol\\n')"; + +// This is example 2 script, which will be compiled and executed. +static const char *example_2 = + "for i in range(10):\n" + " print('iter {:08}'.format(i))\n" + "\n" + "try:\n" + " 1//0\n" + "except Exception as er:\n" + " print('caught exception', repr(er))\n" + "\n" + "import gc\n" + "print('run GC collect')\n" + "gc.collect()\n" + "\n" + "print('help(\\'modules\\'):')\n" + "help('modules')\n" + "import sys\n" + "help(sys)\n" + "\n" + "print('finish')\n" + ; + +// This array is the MicroPython GC heap. +static char heap[8 * 1024]; + +int main() { +#if MICROPY_STACK_CHECK + // Set the stack limit, otherwise the default is zero and we will end up in + // nlr_jump_fail() immediately. + mp_stack_set_limit(10240); +#endif + // Initialise MicroPython. + // + // Note: &stack_top below should be good enough for many cases. + // However, depending on environment, there might be more appropriate + // ways to get the stack top value. + // eg. pthread_get_stackaddr_np, pthread_getattr_np, + // __builtin_frame_address/__builtin_stack_address, etc. + int stack_top; + mp_embed_init(&heap[0], sizeof(heap), &stack_top); + + // Run the example scripts (they will be compiled first). + mp_embed_exec_str(example_1); + mp_embed_exec_str(example_2); + + // Deinitialise MicroPython. + mp_embed_deinit(); + + return 0; +} diff --git a/examples/embedding-full/micropython_embed.mk b/examples/embedding-full/micropython_embed.mk new file mode 100644 index 0000000000..5db5415927 --- /dev/null +++ b/examples/embedding-full/micropython_embed.mk @@ -0,0 +1,9 @@ +# This file is part of the MicroPython project, http://micropython.org/ +# The MIT License (MIT) +# Copyright (c) 2022-2023 Damien P. George + +# Set the location of the top of the MicroPython repository. +MICROPYTHON_TOP = ../.. + +# Include the main makefile fragment to build the MicroPython component. +include $(MICROPYTHON_TOP)/ports/embed/embed.mk diff --git a/examples/embedding-full/mpconfigport.h b/examples/embedding-full/mpconfigport.h new file mode 100644 index 0000000000..ec96e5ad1f --- /dev/null +++ b/examples/embedding-full/mpconfigport.h @@ -0,0 +1,32 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022-2023 Damien P. George + */ + +// Include common MicroPython embed configuration. +#include + +// Use the same starting configuration as on most bare-metal targets. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +// MicroPython configuration. +#define MICROPY_ENABLE_COMPILER (1) +#define MICROPY_ENABLE_GC (1) +#define MICROPY_PY_GC (1) + +#define MICROPY_PY_SYS_PLATFORM "embedded" + +// Requires shared/readline/readline.h, don't bother as we have no input. +#define MICROPY_PY_BUILTINS_INPUT (0) + +// Can be enabled once extmod/moductypes.c is included in the build. +#define MICROPY_PY_UCTYPES (0) + +// Can be enabled once either shared/runtime/sys_stdio_mphal.c or +// extmod/vfs_posix_file.c is included in the build. +#define MICROPY_PY_SYS_STDFILES (0) + +// Can be enabled if you provide an implementation of +// mp_hal_set_interrupt_char() in mphal.c or include +// shared/runtime/interrupt_char.c in the build. +#define MICROPY_KBD_EXCEPTION (0) diff --git a/examples/embedding-full/mphal.c b/examples/embedding-full/mphal.c new file mode 100644 index 0000000000..32e508b1e9 --- /dev/null +++ b/examples/embedding-full/mphal.c @@ -0,0 +1,26 @@ +/* This file is part of the MicroPython project, http://micropython.org/ + * The MIT License (MIT) + * Copyright (c) 2022-2023 Damien P. George + */ + +#include "py/builtin.h" +#include "py/compile.h" +#include "py/mperrno.h" + +#if !MICROPY_VFS + +mp_lexer_t *mp_lexer_new_from_file(qstr filename) { + mp_raise_OSError(MP_ENOENT); +} + +mp_import_stat_t mp_import_stat(const char *path) { + (void)path; + return MP_IMPORT_STAT_NO_EXIST; +} + +mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open); + +#endif diff --git a/examples/embedding/README.md b/examples/embedding/README.md index 3f19aff41f..4beeb93623 100644 --- a/examples/embedding/README.md +++ b/examples/embedding/README.md @@ -1,8 +1,9 @@ -Example of embedding MicroPython in a standalone C application -============================================================== +Example of embedding MicroPython in a standalone C application (minimal) +======================================================================== -This directory contains a simple example of how to embed MicroPython in an -existing C application. +This directory contains a simple example of how to embed a minimal version of +MicroPython in an existing C application. +See also _embedding-full_ for a more full-featured version. A C application is represented here by the file `main.c`. It executes two simple Python scripts which print things to the standard output. diff --git a/ports/embed/port/mphalport.h b/ports/embed/port/mphalport.h index 49928e154d..fd4a58aa8f 100644 --- a/ports/embed/port/mphalport.h +++ b/ports/embed/port/mphalport.h @@ -1,2 +1,6 @@ // Define so there's no dependency on extmod/virtpin.h #define mp_hal_pin_obj_t + +#if MICROPY_KBD_EXCEPTION +void mp_hal_set_interrupt_char(int c); +#endif