kopia lustrzana https://github.com/micropython/micropython
Merge ca93048ab9
into e60e8079a7
commit
8e27ad3264
|
@ -23,3 +23,12 @@ jobs:
|
||||||
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
|
run: make -C examples/embedding -f micropython_embed.mk && make -C examples/embedding
|
||||||
- name: Run
|
- name: Run
|
||||||
run: ./examples/embedding/embed | grep "hello world"
|
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
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# 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 += -I$(EMBED_DIR)/lib/littlefs
|
||||||
|
CFLAGS += -Wall -Og -fno-common
|
||||||
|
|
||||||
|
SRC += main.c mphal.c modules/c_hello/modc_hello.c
|
||||||
|
SRC += $(wildcard $(EMBED_DIR)/*/*.c)
|
||||||
|
# Filter out lib because the files in there cannot be compiled separately, they
|
||||||
|
# are #included by other .c files.
|
||||||
|
SRC += $(filter-out $(EMBED_DIR)/lib/%.c,$(wildcard $(EMBED_DIR)/*/*/*.c))
|
||||||
|
OBJ += $(SRC:.c=.o)
|
||||||
|
|
||||||
|
$(PROG): $(OBJ)
|
||||||
|
$(CC) -o $@ $^ -lm
|
||||||
|
|
||||||
|
clean:
|
||||||
|
/bin/rm -f $(OBJ) $(PROG)
|
|
@ -0,0 +1,43 @@
|
||||||
|
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 -C mpy-cross
|
||||||
|
$ cd examples/embedding-full
|
||||||
|
$ 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.
|
|
@ -0,0 +1,113 @@
|
||||||
|
/* 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.5 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"
|
||||||
|
// Skip testing stdin when using the POSIX implementation, i.e. it is
|
||||||
|
// connected to actual stdin, because that makes the program wait for input,
|
||||||
|
// which can be inconvenient or confusing (giving the appearance of being
|
||||||
|
// stuck). There is no harm enabling it if you remember to provide some
|
||||||
|
// input.
|
||||||
|
#if !MICROPY_VFS_POSIX
|
||||||
|
"print('sys.stdin.read(3):', repr(sys.stdin.read(3)))\n"
|
||||||
|
"print('sys.stdin.buffer.read(3):', repr(sys.stdin.buffer.read(3)))\n"
|
||||||
|
#endif
|
||||||
|
"sys.stdout.write('hello stdout text\\n')\n"
|
||||||
|
"sys.stdout.buffer.write(b'hello stdout binary\\n')\n"
|
||||||
|
"sys.stdout.write('hello stderr text\\n')\n"
|
||||||
|
"sys.stdout.buffer.write(b'hello stderr binary\\n')\n"
|
||||||
|
"import os\n"
|
||||||
|
"help(os)\n"
|
||||||
|
"print('os.uname():', os.uname())\n"
|
||||||
|
"import random\n"
|
||||||
|
"help(random)\n"
|
||||||
|
"import time\n"
|
||||||
|
"help(time)\n"
|
||||||
|
"print('time.gmtime(736622952) = 2023-05-05T17:29:12Z:', time.gmtime(736622952))\n"
|
||||||
|
"import math\n"
|
||||||
|
"help(math)\n"
|
||||||
|
"import uctypes\n"
|
||||||
|
"help(uctypes)\n"
|
||||||
|
"import frozenhello\n"
|
||||||
|
"help(frozenhello)\n"
|
||||||
|
"print('frozenhello.hello():', frozenhello.hello())\n"
|
||||||
|
"import c_hello\n"
|
||||||
|
"help(c_hello)\n"
|
||||||
|
"print('c_hello.hello():', c_hello.hello())\n"
|
||||||
|
"import fsimage, vfs\n"
|
||||||
|
"vfs.mount(fsimage.BlockDev(), '/lfs', readonly=True)\n"
|
||||||
|
"print('os.listdir(\\'/lfs\\'):', os.listdir('/lfs'))\n"
|
||||||
|
"with open('/lfs/lfshello.py', 'rb') as f:\n"
|
||||||
|
" print('lfshello.py:', f.read())\n"
|
||||||
|
"sys.path.append('/lfs')\n"
|
||||||
|
"import lfshello\n"
|
||||||
|
"help(lfshello)\n"
|
||||||
|
"print('lfshello.hello():', lfshello.hello())\n"
|
||||||
|
"vfs.mount(vfs.VfsPosix('.'), '/posix')\n"
|
||||||
|
"print('os.listdir(\\'/posix\\'):', os.listdir('/posix'))\n"
|
||||||
|
"with open('/posix/posixhello.py', 'wb') as f:\n"
|
||||||
|
" f.write(b'def hello():\\n return \"Hello from a POSIX file!\"\\n')\n"
|
||||||
|
"with open('/posix/posixhello.py', 'rb') as f:\n"
|
||||||
|
" print('posixhello.py:', f.read())\n"
|
||||||
|
"sys.path.append('/posix')\n"
|
||||||
|
"import posixhello\n"
|
||||||
|
"help(posixhello)\n"
|
||||||
|
"print('posixhello.hello():', posixhello.hello())\n"
|
||||||
|
"os.unlink('/posix/posixhello.py')"
|
||||||
|
"\n"
|
||||||
|
"print('finish')\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
// This array is the MicroPython GC heap.
|
||||||
|
static char heap[16 * 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;
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
module("frozenhello.py", base_path="modules")
|
||||||
|
module("fsimage.py", base_path="modules")
|
|
@ -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
|
||||||
|
|
||||||
|
# Set the location of the top of the MicroPython repository.
|
||||||
|
MICROPYTHON_TOP = ../..
|
||||||
|
|
||||||
|
# Include modules from extmod in the output.
|
||||||
|
EMBED_EXTRA = extmod
|
||||||
|
|
||||||
|
# Include helper sources for the time module in the output.
|
||||||
|
EMBED_EXTRA += \
|
||||||
|
shared/timeutils/timeutils.c \
|
||||||
|
shared/timeutils/timeutils.h \
|
||||||
|
shared/timeutils/modtime_mphal.h
|
||||||
|
|
||||||
|
# Include source for mphal-backed stdio in the output.
|
||||||
|
# Disable when using POSIX-backed stdio (MICROPY_VFS_POSIX).
|
||||||
|
#EMBED_EXTRA += \
|
||||||
|
# shared/runtime/sys_stdio_mphal.c
|
||||||
|
|
||||||
|
# Include library sources for littlefs 2 in the output.
|
||||||
|
EMBED_EXTRA += littlefs2
|
||||||
|
|
||||||
|
# Freeze Python modules.
|
||||||
|
FROZEN_MANIFEST ?= manifest.py
|
||||||
|
|
||||||
|
# Add C modules.
|
||||||
|
USER_C_MODULES = modules
|
||||||
|
|
||||||
|
# Include the main makefile fragment to build the MicroPython component.
|
||||||
|
include $(MICROPYTHON_TOP)/ports/embed/embed.mk
|
|
@ -0,0 +1,2 @@
|
||||||
|
C_HELLO_MOD_DIR := $(USERMOD_DIR)
|
||||||
|
SRC_USERMOD_C += $(C_HELLO_MOD_DIR)/modc_hello.c
|
|
@ -0,0 +1,23 @@
|
||||||
|
// Check examples/usercmodule for more info about how this works.
|
||||||
|
|
||||||
|
#include "py/runtime.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
|
|
||||||
|
static mp_obj_t c_hello_hello() {
|
||||||
|
static const MP_DEFINE_STR_OBJ(hello_str, "Hello from C!");
|
||||||
|
return MP_OBJ_FROM_PTR(&hello_str);
|
||||||
|
}
|
||||||
|
static MP_DEFINE_CONST_FUN_OBJ_0(c_hello_hello_obj, c_hello_hello);
|
||||||
|
|
||||||
|
static const mp_rom_map_elem_t c_hello_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_c_hello) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_hello), MP_ROM_PTR(&c_hello_hello_obj) },
|
||||||
|
};
|
||||||
|
static MP_DEFINE_CONST_DICT(c_hello_module_globals, c_hello_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t c_hello_module = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t *)&c_hello_module_globals,
|
||||||
|
};
|
||||||
|
|
||||||
|
MP_REGISTER_MODULE(MP_QSTR_c_hello, c_hello_module);
|
|
@ -0,0 +1,2 @@
|
||||||
|
def hello():
|
||||||
|
return "Hello from the cold!"
|
|
@ -0,0 +1,27 @@
|
||||||
|
# a minimal read-only block device containing a tiny littlefs image
|
||||||
|
|
||||||
|
|
||||||
|
class BlockDev:
|
||||||
|
def readblocks(self, block_num, buf, offset=0):
|
||||||
|
addr = block_num * 128 + offset
|
||||||
|
for i in range(len(buf)):
|
||||||
|
buf[i] = (
|
||||||
|
b"\x03\x00\x00\x00\xf0\x0f\xff\xf7littlefs/\xe0\x00\x10\x01\x00\x02\x00\x80\x00\x00\x00\x03\x00\x00\x00"
|
||||||
|
b"\xff\x00\x00\x00\xff\xff\xff\x7f\xfe\x03\x00\x00 \x00\x04\x13lfshello.py 0\x00\x03\x02"
|
||||||
|
b"\x00\x00\x006\x00\x00\x00\x100\x00\x00\x00\xda#\xed=!\xb7\x17`\x1f\xf8!\x99\xf8T\x19\xff\xff\xff\xff\xff"
|
||||||
|
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
b"\x02\x00\x00\x00\xf0\x0f\xff\xf7littlefs/\xe0\x00\x10\x01\x00\x02\x00\x80\x00\x00\x00\x03\x00\x00\x00"
|
||||||
|
b"\xff\x00\x00\x00\xff\xff\xff\x7f\xfe\x03\x00\x00\x7f\xef\xfc\x10 \x00\x00\x00R\xaa\xf5\xe6\x0f\xe0\x00\x0cq)\x81\xa1"
|
||||||
|
b"\x90\x0f\xf8\x04@\x00\x00\x0blfshello.py \x00\x00\x0bp\x1f\xf8%\x12\xbc\x179\xff"
|
||||||
|
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
b'def hello():\n return "Hello f'
|
||||||
|
b'rom a littlefs file!"\n\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff'
|
||||||
|
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||||
|
)[addr + i]
|
||||||
|
|
||||||
|
def ioctl(self, op, arg):
|
||||||
|
if op == 4: # block count
|
||||||
|
return 3
|
||||||
|
if op == 5: # block size
|
||||||
|
return 128
|
|
@ -0,0 +1,69 @@
|
||||||
|
/* 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 <port/mpconfigport_common.h>
|
||||||
|
|
||||||
|
// 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"
|
||||||
|
#define MICROPY_PY_OS_UNAME (1)
|
||||||
|
#define MICROPY_HW_BOARD_NAME "embedded"
|
||||||
|
#define MICROPY_HW_MCU_NAME "C"
|
||||||
|
|
||||||
|
// Enable the VFS subsystem, littlefs and POSIX VFS, importing from VFS, and
|
||||||
|
// the vfs module.
|
||||||
|
#define MICROPY_VFS (1)
|
||||||
|
#define MICROPY_VFS_LFS2 (1)
|
||||||
|
#define MICROPY_VFS_POSIX (1)
|
||||||
|
#define MICROPY_READER_VFS (1)
|
||||||
|
#define MICROPY_PY_VFS (1)
|
||||||
|
|
||||||
|
// Enable floating point numbers and the math module.
|
||||||
|
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
|
||||||
|
|
||||||
|
// Enable more functions in the time module. Requires additions to EMBED_EXTRA,
|
||||||
|
// see micropython_embed.mk.
|
||||||
|
#define MICROPY_PY_TIME_GMTIME_LOCALTIME_MKTIME (1)
|
||||||
|
#define MICROPY_PY_TIME_TIME_TIME_NS (1)
|
||||||
|
#define MICROPY_PY_TIME_INCLUDEFILE "shared/timeutils/modtime_mphal.h"
|
||||||
|
|
||||||
|
// Requires shared/readline/readline.h, don't bother as we have no input.
|
||||||
|
#define MICROPY_PY_BUILTINS_INPUT (0)
|
||||||
|
|
||||||
|
// Requires MICROPY_EVENT_POLL_HOOK, don't bother as we have no pollable objects.
|
||||||
|
#define MICROPY_PY_SELECT (0)
|
||||||
|
|
||||||
|
// On by default and works in this configuration, but disable it to avoid a
|
||||||
|
// linker error if you don't include extmod/moductypes.c 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)
|
||||||
|
|
||||||
|
// We have our own implementation of mp_hal_stdout_tx_strn_cooked().
|
||||||
|
#undef MP_PLAT_PRINT_STRN
|
||||||
|
|
||||||
|
// Enable freezing of Python modules. These would be set automatically for the
|
||||||
|
// port build based on the presence of FROZEN_MANIFEST by py/mkrules.mk, but
|
||||||
|
// must be set explicitly for the application build.
|
||||||
|
#define MICROPY_MODULE_FROZEN_MPY 1
|
||||||
|
#define MICROPY_MODULE_FROZEN_STR 1
|
||||||
|
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
|
||||||
|
// must match MPY_TOOL_FLAGS or defaults for mpy-tool.py arguments
|
||||||
|
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_MPZ)
|
||||||
|
#define MPZ_DIG_SIZE (16)
|
|
@ -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
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "py/builtin.h"
|
||||||
|
#include "py/compile.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
|
#if MICROPY_PY_SYS_STDFILES
|
||||||
|
#include "py/stream.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
#if MICROPY_PY_ASYNCIO
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_ms(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_PY_TIME
|
||||||
|
|
||||||
|
void mp_hal_delay_ms(mp_uint_t ms) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void mp_hal_delay_us(mp_uint_t us) {
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_us(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_cpu(void) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_PY_TIME_TIME_TIME_NS
|
||||||
|
|
||||||
|
uint64_t mp_hal_time_ns(void) {
|
||||||
|
// Nanoseconds since the Epoch.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Text-mode standard output
|
||||||
|
// (When MICROPY_PY_SYS_STDFILES && MICROPY_VFS_POSIX, this is only used for
|
||||||
|
// mp_plat_print (mostly debug output), but not for print() and sys.stdout.)
|
||||||
|
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
|
||||||
|
// This is a simplistic implementation for demonstration purposes. A real
|
||||||
|
// one would probably want to prefix every line, not just at the start of a
|
||||||
|
// write operation.
|
||||||
|
static int start_of_line = 1;
|
||||||
|
if (start_of_line) printf("py: ");
|
||||||
|
printf("%.*s", (int)len, str);
|
||||||
|
start_of_line = (len > 0 && (str[len-1] == '\n' || str[len-1] == '\r'));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MICROPY_PY_SYS_STDFILES && !MICROPY_VFS_POSIX
|
||||||
|
|
||||||
|
// Binary-mode standard input
|
||||||
|
// Receive single character, blocking until one is available.
|
||||||
|
int mp_hal_stdin_rx_chr(void) {
|
||||||
|
return 'X';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binary-mode standard output
|
||||||
|
// Send the string of given length.
|
||||||
|
mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
|
||||||
|
printf("tx: %.*s", (int)len, str);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
|
||||||
|
uintptr_t ret = 0;
|
||||||
|
if ((poll_flags & MP_STREAM_POLL_RD) /* && can_read */) {
|
||||||
|
ret |= MP_STREAM_POLL_RD;
|
||||||
|
}
|
||||||
|
if ((poll_flags & MP_STREAM_POLL_WR) /* && can_write */) {
|
||||||
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -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
|
This directory contains a simple example of how to embed a minimal version of
|
||||||
existing C application.
|
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
|
A C application is represented here by the file `main.c`. It executes two
|
||||||
simple Python scripts which print things to the standard output.
|
simple Python scripts which print things to the standard output.
|
||||||
|
|
|
@ -29,9 +29,15 @@
|
||||||
#if MICROPY_PY_VFS
|
#if MICROPY_PY_VFS
|
||||||
|
|
||||||
#include "extmod/vfs.h"
|
#include "extmod/vfs.h"
|
||||||
|
#if MICROPY_VFS_FAT
|
||||||
#include "extmod/vfs_fat.h"
|
#include "extmod/vfs_fat.h"
|
||||||
|
#endif
|
||||||
|
#if MICROPY_VFS_LFS1 || MICROPY_VFS_LFS2
|
||||||
#include "extmod/vfs_lfs.h"
|
#include "extmod/vfs_lfs.h"
|
||||||
|
#endif
|
||||||
|
#if MICROPY_VFS_POSIX
|
||||||
#include "extmod/vfs_posix.h"
|
#include "extmod/vfs_posix.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !MICROPY_VFS
|
#if !MICROPY_VFS
|
||||||
#error "MICROPY_PY_VFS requires MICROPY_VFS"
|
#error "MICROPY_PY_VFS requires MICROPY_VFS"
|
||||||
|
|
|
@ -12,6 +12,15 @@ include $(MICROPYTHON_TOP)/py/mkenv.mk
|
||||||
|
|
||||||
# Include py core make definitions.
|
# Include py core make definitions.
|
||||||
include $(TOP)/py/py.mk
|
include $(TOP)/py/py.mk
|
||||||
|
ifeq ($(filter extmod,$(EMBED_EXTRA)),extmod)
|
||||||
|
include $(TOP)/extmod/extmod.mk
|
||||||
|
endif
|
||||||
|
|
||||||
|
# The parts of EMBED_EXTRA that name literal files and don't need special handling.
|
||||||
|
EMBED_EXTRA_FILES = $(filter-out extmod littlefs1 littlefs2,$(EMBED_EXTRA))
|
||||||
|
|
||||||
|
# Extra files need to be searched for QSTRs.
|
||||||
|
SRC_QSTR += $(addprefix $(TOP)/,$(EMBED_EXTRA_FILES))
|
||||||
|
|
||||||
# Set the location of the MicroPython embed port.
|
# Set the location of the MicroPython embed port.
|
||||||
MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed
|
MICROPYTHON_EMBED_PORT = $(MICROPYTHON_TOP)/ports/embed
|
||||||
|
@ -31,6 +40,11 @@ GENHDR_OUTPUT = $(addprefix $(BUILD)/genhdr/, \
|
||||||
root_pointers.h \
|
root_pointers.h \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Define the module freezing output.
|
||||||
|
ifneq ($(FROZEN_MANIFEST),)
|
||||||
|
FROZEN_OUTPUT = $(BUILD)/frozen_content.c
|
||||||
|
endif
|
||||||
|
|
||||||
# Define the top-level target, the generated output files.
|
# Define the top-level target, the generated output files.
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
all: micropython-embed-package
|
all: micropython-embed-package
|
||||||
|
@ -43,23 +57,62 @@ clean-micropython-embed-package:
|
||||||
|
|
||||||
PACKAGE_DIR ?= micropython_embed
|
PACKAGE_DIR ?= micropython_embed
|
||||||
PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port)
|
PACKAGE_DIR_LIST = $(addprefix $(PACKAGE_DIR)/,py extmod shared/runtime genhdr port)
|
||||||
|
ifeq ($(filter extmod,$(EMBED_EXTRA)),extmod)
|
||||||
|
PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,lib/uzlib lib/crypto-algorithms lib/re1.5)
|
||||||
|
endif
|
||||||
|
ifneq ($(filter littlefs1 littlefs2,$(EMBED_EXTRA)),)
|
||||||
|
PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,lib/littlefs libsrc/littlefs)
|
||||||
|
endif
|
||||||
|
ifneq ($(FROZEN_MANIFEST),)
|
||||||
|
PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,frozen)
|
||||||
|
endif
|
||||||
|
ifneq ($(EMBED_EXTRA_FILES),)
|
||||||
|
PACKAGE_DIR_LIST += $(addprefix $(PACKAGE_DIR)/,$(filter-out ./,$(sort $(dir $(EMBED_EXTRA_FILES)))))
|
||||||
|
endif
|
||||||
|
|
||||||
.PHONY: micropython-embed-package
|
.PHONY: micropython-embed-package
|
||||||
micropython-embed-package: $(GENHDR_OUTPUT)
|
micropython-embed-package: $(GENHDR_OUTPUT) $(FROZEN_OUTPUT)
|
||||||
$(ECHO) "Generate micropython_embed output:"
|
$(ECHO) "Generate micropython_embed output:"
|
||||||
$(Q)$(RM) -rf $(PACKAGE_DIR_LIST)
|
$(Q)$(RM) -rf $(PACKAGE_DIR_LIST)
|
||||||
$(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST)
|
$(Q)$(MKDIR) -p $(PACKAGE_DIR_LIST)
|
||||||
$(ECHO) "- py"
|
$(ECHO) "- py"
|
||||||
$(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py
|
$(Q)$(CP) $(TOP)/py/*.[ch] $(PACKAGE_DIR)/py
|
||||||
$(ECHO) "- extmod"
|
$(ECHO) "- extmod"
|
||||||
|
ifeq ($(filter extmod,$(EMBED_EXTRA)),extmod)
|
||||||
|
$(Q)$(CP) $(TOP)/extmod/*.[ch] $(PACKAGE_DIR)/extmod
|
||||||
|
$(ECHO) "- lib"
|
||||||
|
$(Q)$(CP) $(TOP)/lib/uzlib/*.[ch] $(PACKAGE_DIR)/lib/uzlib
|
||||||
|
$(Q)$(CP) $(TOP)/lib/crypto-algorithms/*.[ch] $(PACKAGE_DIR)/lib/crypto-algorithms
|
||||||
|
$(Q)$(CP) $(TOP)/lib/re1.5/*.[ch] $(PACKAGE_DIR)/lib/re1.5
|
||||||
|
else
|
||||||
$(Q)$(CP) $(TOP)/extmod/modplatform.h $(PACKAGE_DIR)/extmod
|
$(Q)$(CP) $(TOP)/extmod/modplatform.h $(PACKAGE_DIR)/extmod
|
||||||
|
endif
|
||||||
|
ifneq ($(filter littlefs1 littlefs2,$(EMBED_EXTRA)),)
|
||||||
|
$(ECHO) "- libsrc"
|
||||||
|
ifeq ($(filter littlefs1,$(EMBED_EXTRA)),littlefs1)
|
||||||
|
$(Q)$(CP) $(TOP)/lib/littlefs/lfs1*.h $(PACKAGE_DIR)/lib/littlefs
|
||||||
|
$(Q)$(CP) $(TOP)/lib/littlefs/lfs1*.c $(PACKAGE_DIR)/libsrc/littlefs
|
||||||
|
endif
|
||||||
|
ifeq ($(filter littlefs2,$(EMBED_EXTRA)),littlefs2)
|
||||||
|
$(Q)$(CP) $(TOP)/lib/littlefs/lfs2*.h $(PACKAGE_DIR)/lib/littlefs
|
||||||
|
$(Q)$(CP) $(TOP)/lib/littlefs/lfs2*.c $(PACKAGE_DIR)/libsrc/littlefs
|
||||||
|
endif
|
||||||
|
endif
|
||||||
$(ECHO) "- shared"
|
$(ECHO) "- shared"
|
||||||
$(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime
|
$(Q)$(CP) $(TOP)/shared/runtime/gchelper.h $(PACKAGE_DIR)/shared/runtime
|
||||||
$(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime
|
$(Q)$(CP) $(TOP)/shared/runtime/gchelper_generic.c $(PACKAGE_DIR)/shared/runtime
|
||||||
$(ECHO) "- genhdr"
|
$(ECHO) "- genhdr"
|
||||||
$(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr
|
$(Q)$(CP) $(GENHDR_OUTPUT) $(PACKAGE_DIR)/genhdr
|
||||||
|
ifneq ($(FROZEN_MANIFEST),)
|
||||||
|
$(ECHO) "- frozen"
|
||||||
|
$(Q)$(CP) $(FROZEN_OUTPUT) $(PACKAGE_DIR)/frozen
|
||||||
|
endif
|
||||||
$(ECHO) "- port"
|
$(ECHO) "- port"
|
||||||
$(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port
|
$(Q)$(CP) $(MICROPYTHON_EMBED_PORT)/port/*.[ch] $(PACKAGE_DIR)/port
|
||||||
|
ifneq ($(EMBED_EXTRA_FILES),)
|
||||||
|
$(ECHO) "- extra"
|
||||||
|
$(Q)$(foreach FILE,$(EMBED_EXTRA_FILES),$(CP) $(TOP)/$(FILE) $(dir $(PACKAGE_DIR)/$(FILE)) &&) true
|
||||||
|
endif
|
||||||
|
|
||||||
# Include remaining core make rules.
|
# Include remaining core make rules.
|
||||||
include $(TOP)/py/mkrules.mk
|
include $(TOP)/py/mkrules.mk
|
||||||
|
|
|
@ -40,3 +40,13 @@ typedef long mp_off_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MICROPY_MPHALPORT_H "port/mphalport.h"
|
#define MICROPY_MPHALPORT_H "port/mphalport.h"
|
||||||
|
|
||||||
|
// Default implementation for applications that want output to go to the system
|
||||||
|
// printf(). If you don't, or don't have printf() available, or use
|
||||||
|
// shared/libc/printf.c (MICROPY_USE_INTERNAL_PRINTF) which would be a circular
|
||||||
|
// definition, #undef this and implement mp_hal_stdout_tx_strn_cooked().
|
||||||
|
#define MP_PLAT_PRINT_STRN(str, len) \
|
||||||
|
do { \
|
||||||
|
extern int printf(const char *fmt, ...); \
|
||||||
|
printf("%.*s", (int)len, str); \
|
||||||
|
} while (0)
|
||||||
|
|
|
@ -1,2 +1,26 @@
|
||||||
// Define so there's no dependency on extmod/virtpin.h
|
// Define so there's no dependency on extmod/virtpin.h
|
||||||
#define mp_hal_pin_obj_t
|
#define mp_hal_pin_obj_t mp_obj_t
|
||||||
|
|
||||||
|
#if MICROPY_KBD_EXCEPTION
|
||||||
|
void mp_hal_set_interrupt_char(int c);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_VFS_POSIX
|
||||||
|
// This macro is used to implement PEP 475 to retry specified syscalls on EINTR
|
||||||
|
#define MP_HAL_RETRY_SYSCALL(ret, syscall, raise) { \
|
||||||
|
for (;;) { \
|
||||||
|
MP_THREAD_GIL_EXIT(); \
|
||||||
|
ret = syscall; \
|
||||||
|
MP_THREAD_GIL_ENTER(); \
|
||||||
|
if (ret == -1) { \
|
||||||
|
int err = errno; \
|
||||||
|
if (err == EINTR) { \
|
||||||
|
mp_handle_pending(true); \
|
||||||
|
continue; \
|
||||||
|
} \
|
||||||
|
raise; \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -251,8 +251,8 @@ endif
|
||||||
submodules:
|
submodules:
|
||||||
$(ECHO) "Updating submodules: $(GIT_SUBMODULES)"
|
$(ECHO) "Updating submodules: $(GIT_SUBMODULES)"
|
||||||
ifneq ($(GIT_SUBMODULES),)
|
ifneq ($(GIT_SUBMODULES),)
|
||||||
$(Q)git submodule sync $(addprefix $(TOP)/,$(GIT_SUBMODULES))
|
$(Q)cd $(TOP) && git submodule sync $(GIT_SUBMODULES)
|
||||||
$(Q)git submodule update --init $(addprefix $(TOP)/,$(GIT_SUBMODULES))
|
$(Q)cd $(TOP) && git submodule update --init $(GIT_SUBMODULES)
|
||||||
endif
|
endif
|
||||||
.PHONY: submodules
|
.PHONY: submodules
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*
|
*
|
||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2022-2023 Damien P. George
|
* Copyright (c) 2013-2023 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -24,10 +24,29 @@
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "py/obj.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
|
#include "shared/timeutils/timeutils.h"
|
||||||
|
|
||||||
// Send string of given length to stdout, converting \n to \r\n.
|
// Return the localtime as an 8-tuple.
|
||||||
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
|
static mp_obj_t mp_time_localtime_get(void) {
|
||||||
printf("%.*s", (int)len, str);
|
mp_int_t seconds = mp_hal_time_ns() / 1000000000;
|
||||||
|
timeutils_struct_time_t tm;
|
||||||
|
timeutils_seconds_since_epoch_to_struct_time(seconds, &tm);
|
||||||
|
mp_obj_t tuple[8] = {
|
||||||
|
tuple[0] = mp_obj_new_int(tm.tm_year),
|
||||||
|
tuple[1] = mp_obj_new_int(tm.tm_mon),
|
||||||
|
tuple[2] = mp_obj_new_int(tm.tm_mday),
|
||||||
|
tuple[3] = mp_obj_new_int(tm.tm_hour),
|
||||||
|
tuple[4] = mp_obj_new_int(tm.tm_min),
|
||||||
|
tuple[5] = mp_obj_new_int(tm.tm_sec),
|
||||||
|
tuple[6] = mp_obj_new_int(tm.tm_wday),
|
||||||
|
tuple[7] = mp_obj_new_int(tm.tm_yday),
|
||||||
|
};
|
||||||
|
return mp_obj_new_tuple(8, tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the number of seconds, as an integer, since the Epoch.
|
||||||
|
static mp_obj_t mp_time_time_get(void) {
|
||||||
|
return mp_obj_new_int(mp_hal_time_ns() / 1000000000);
|
||||||
}
|
}
|
Ładowanie…
Reference in New Issue