summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien George <damien@micropython.org>2022-10-06 11:14:13 +1100
committerDamien George <damien@micropython.org>2023-01-20 22:28:50 +1100
commita8a1ad13916aa74fca30ad23061a5552935bf097 (patch)
treeb80f7fab1df0f5c6e142a1f631c44eb51715e77a
parentabaa4abd2d5d43eb812301ab7f0fcaa9c93c18c2 (diff)
embed: Add new "embed" port which builds a simple C package.
Signed-off-by: Damien George <damien@micropython.org>
-rw-r--r--ports/embed/README.md18
-rw-r--r--ports/embed/embed.mk65
-rw-r--r--ports/embed/port/embed_util.c106
-rw-r--r--ports/embed/port/micropython_embed.h41
-rw-r--r--ports/embed/port/mpconfigport_common.h38
-rw-r--r--ports/embed/port/mphalport.c33
-rw-r--r--ports/embed/port/mphalport.h2
7 files changed, 303 insertions, 0 deletions
diff --git a/ports/embed/README.md b/ports/embed/README.md
new file mode 100644
index 000000000..556cfc749
--- /dev/null
+++ b/ports/embed/README.md
@@ -0,0 +1,18 @@
+MicroPython embed port
+======================
+
+This is a port of MicroPython that outputs a set of .c and .h files for embedding
+into a wider project. This port essentially targets the C language, instead of a
+particular hardware architecture or platform.
+
+To use this port in a project there are three main steps:
+
+1. Provide configuration for the project via an `mpconfigport.h` file.
+
+2. Build this embed port against that configuration, using the provided `embed.mk`.
+ The output is a set of self-contained source files for building MicroPython.
+ These files can be placed outside this repository.
+
+3. Build the project. This requires compiling all .c files from the above step.
+
+See `examples/embedding` for an example.
diff --git a/ports/embed/embed.mk b/ports/embed/embed.mk
new file mode 100644
index 000000000..7fb344d70
--- /dev/null
+++ b/ports/embed/embed.mk
@@ -0,0 +1,65 @@
+# This file is part of the MicroPython project, http://micropython.org/
+# The MIT License (MIT)
+# Copyright (c) 2022-2023 Damien P. George
+#
+# This file is intended to be included by a Makefile in a custom project.
+
+# Set the build output directory for the generated files.
+BUILD = build-embed
+
+# Include the core environment definitions; this will set $(TOP).
+include $(MICROPYTHON_TOP)/py/mkenv.mk
+
+# Include py core make definitions.
+include $(TOP)/py/py.mk
+
+# Set the location of the MicroPython embed port.
+MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed
+
+# Set default makefile-level MicroPython feature configurations.
+MICROPY_ROM_TEXT_COMPRESSION ?= 0
+
+# Set CFLAGS for the MicroPython build.
+CFLAGS += -I. -I$(TOP) -I$(BUILD) -I$(MICROPYTHON_EMBED_PORT)
+CFLAGS += -Wall -Werror -std=c99
+
+# Define the required generated header files.
+GENHDR_OUTPUT = $(addprefix $(BUILD)/genhdr/, \
+ moduledefs.h \
+ mpversion.h \
+ qstrdefs.generated.h \
+ root_pointers.h \
+ )
+
+# Define the top-level target, the generated output files.
+.PHONY: all
+all: micropython-embed-package
+
+clean: clean-micropython-embed-package
+
+.PHONY: clean-micropython-embed-package
+clean-micropython-embed-package:
+ $(RM) -rf $(PACKAGE_DIR)
+
+PACKAGE_DIR ?= micropython_embed
+PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port)
+
+.PHONY: micropython-embed-package
+micropython-embed-package: $(GENHDR_OUTPUT)
+ $(ECHO) "Generate micropython_embed output:"
+ $(Q)$(RM) -rf $(PACKAGE_DIR_LIST)
+ $(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST)
+ $(ECHO) "- py"
+ $(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py
+ $(ECHO) "- extmod"
+ $(Q)$(CP) $(TOP)/extmod/moduplatform.h $(PACKAGE_DIR)/extmod
+ $(ECHO) "- shared"
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime
+ $(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime
+ $(ECHO) "- genhdr"
+ $(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr
+ $(ECHO) "- port"
+ $(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port
+
+# Include remaining core make rules.
+include $(TOP)/py/mkrules.mk
diff --git a/ports/embed/port/embed_util.c b/ports/embed/port/embed_util.c
new file mode 100644
index 000000000..a3850f3c0
--- /dev/null
+++ b/ports/embed/port/embed_util.c
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-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
+ * 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 <string.h>
+#include "py/compile.h"
+#include "py/gc.h"
+#include "py/persistentcode.h"
+#include "py/runtime.h"
+#include "py/stackctrl.h"
+#include "shared/runtime/gchelper.h"
+#include "port/micropython_embed.h"
+
+// Initialise the runtime.
+void mp_embed_init(void *gc_heap, size_t gc_heap_size) {
+ mp_stack_ctrl_init();
+ gc_init(gc_heap, (uint8_t *)gc_heap + gc_heap_size);
+ mp_init();
+}
+
+#if MICROPY_ENABLE_COMPILER
+// Compile and execute the given source script (Python text).
+void mp_embed_exec_str(const char *src) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Compile, parse and execute the given string.
+ 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, MP_PARSE_FILE_INPUT);
+ mp_obj_t module_fun = mp_compile(&parse_tree, source_name, true);
+ mp_call_function_0(module_fun);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+#if MICROPY_PERSISTENT_CODE_LOAD
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len) {
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ // Execute the given .mpy data.
+ mp_module_context_t *ctx = m_new_obj(mp_module_context_t);
+ ctx->module.globals = mp_globals_get();
+ mp_compiled_module_t cm = mp_raw_code_load_mem(mpy, len, ctx);
+ mp_obj_t f = mp_make_function_from_raw_code(cm.rc, ctx, MP_OBJ_NULL);
+ mp_call_function_0(f);
+ nlr_pop();
+ } else {
+ // Uncaught exception: print it out.
+ mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
+ }
+}
+#endif
+
+// Deinitialise the runtime.
+void mp_embed_deinit(void) {
+ mp_deinit();
+}
+
+#if MICROPY_ENABLE_GC
+// Run a garbage collection cycle.
+void gc_collect(void) {
+ gc_collect_start();
+ gc_helper_collect_regs_and_stack();
+ gc_collect_end();
+}
+#endif
+
+// Called if an exception is raised outside all C exception-catching handlers.
+void nlr_jump_fail(void *val) {
+ for (;;) {
+ }
+}
+
+#ifndef NDEBUG
+// Used when debugging is enabled.
+void __assert_func(const char *file, int line, const char *func, const char *expr) {
+ for (;;) {
+ }
+}
+#endif
diff --git a/ports/embed/port/micropython_embed.h b/ports/embed/port/micropython_embed.h
new file mode 100644
index 000000000..bf55d9b2b
--- /dev/null
+++ b/ports/embed/port/micropython_embed.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-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
+ * 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.
+ */
+#ifndef MICROPY_INCLUDED_MICROPYTHON_EMBED_H
+#define MICROPY_INCLUDED_MICROPYTHON_EMBED_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+void mp_embed_init(void *gc_heap, size_t gc_heap_size);
+void mp_embed_deinit(void);
+
+// Only available if MICROPY_ENABLE_COMPILER is enabled.
+void mp_embed_exec_str(const char *src);
+
+// Only available if MICROPY_PERSISTENT_CODE_LOAD is enabled.
+void mp_embed_exec_mpy(const uint8_t *mpy, size_t len);
+
+#endif // MICROPY_INCLUDED_MICROPYTHON_EMBED_H
diff --git a/ports/embed/port/mpconfigport_common.h b/ports/embed/port/mpconfigport_common.h
new file mode 100644
index 000000000..69216a758
--- /dev/null
+++ b/ports/embed/port/mpconfigport_common.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-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
+ * 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 <stdint.h>
+
+// Type definitions for the specific machine
+
+typedef intptr_t mp_int_t; // must be pointer size
+typedef uintptr_t mp_uint_t; // must be pointer size
+typedef long mp_off_t;
+
+// Need to provide a declaration/definition of alloca()
+#include <alloca.h>
+
+#define MICROPY_MPHALPORT_H "port/mphalport.h"
diff --git a/ports/embed/port/mphalport.c b/ports/embed/port/mphalport.c
new file mode 100644
index 000000000..8e76a8e22
--- /dev/null
+++ b/ports/embed/port/mphalport.c
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2022-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
+ * 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 <stdio.h>
+#include "py/mphal.h"
+
+// Send string of given length to stdout, converting \n to \r\n.
+void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
+ printf("%.*s", (int)len, str);
+}
diff --git a/ports/embed/port/mphalport.h b/ports/embed/port/mphalport.h
new file mode 100644
index 000000000..49928e154
--- /dev/null
+++ b/ports/embed/port/mphalport.h
@@ -0,0 +1,2 @@
+// Define so there's no dependency on extmod/virtpin.h
+#define mp_hal_pin_obj_t