summaryrefslogtreecommitdiffstatshomepage
path: root/zephyr
diff options
context:
space:
mode:
Diffstat (limited to 'zephyr')
-rw-r--r--zephyr/Makefile33
-rw-r--r--zephyr/README.md64
-rw-r--r--zephyr/machine_pin.c180
-rw-r--r--zephyr/main.c4
-rw-r--r--zephyr/modmachine.c71
-rw-r--r--zephyr/modmachine.h16
-rw-r--r--zephyr/modutime.c67
-rw-r--r--zephyr/mpconfigport.h44
-rw-r--r--zephyr/mpconfigport_minimal.h91
-rw-r--r--zephyr/mphalport.h28
-rw-r--r--zephyr/prj.conf1
-rw-r--r--zephyr/src/zephyr_getchar.c5
12 files changed, 575 insertions, 29 deletions
diff --git a/zephyr/Makefile b/zephyr/Makefile
index 1db84cb320..9ddf121250 100644
--- a/zephyr/Makefile
+++ b/zephyr/Makefile
@@ -1,20 +1,22 @@
#
-# This is main Makefile, which uses MicroPython build system, but
-# Zephyr arch-specific toolchain (setup by Zephyr's Makefile.toolchain.*).
-# Unfortunately, it's currently not possible to get target (as in: specific
-# board to run on) specific compile-time options from Zephyr, so these must
-# be set (duplicated) in this Makefile. Currently, these configured for
-# ARM Cortex-M3. This Makefile builds MicroPython as a library, and then
-# calls recursively Makefile.zephyr to build complete application using
-# Zephyr build system.
+# This is the main Makefile, which uses MicroPython build system,
+# but Zephyr arch-specific toolchain and target-specific flags.
+# This Makefile builds MicroPython as a library, and then calls
+# recursively Makefile.zephyr to build complete application binary
+# using Zephyr build system.
#
BOARD ?= qemu_x86
+CONF_FILE = prj.conf
# Zephyr 1.5.0
#OUTDIR_PREFIX =
# Zephyr 1.6.0
OUTDIR_PREFIX = $(BOARD)
+# Default heap size is 16KB, which is on conservative side, to let
+# it build for smaller boards, but it won't be enough for larger
+# applications, and will need to be increased.
+MICROPY_HEAP_SIZE = 16384
FROZEN_DIR = scripts
# Zephyr (generated) config files - must be defined before include below
@@ -34,6 +36,9 @@ INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os
SRC_C = main.c \
help.c \
+ modutime.c \
+ modmachine.c \
+ machine_pin.c \
uart_core.c \
lib/utils/stdout_helpers.c \
lib/utils/printf.c \
@@ -41,7 +46,6 @@ SRC_C = main.c \
lib/utils/interrupt_char.c \
lib/utils/pyhelp.c \
lib/mp-readline/readline.c \
- $(BUILD)/frozen.c \
$(SRC_MOD)
# List of sources for qstr extraction
@@ -50,12 +54,12 @@ SRC_QSTR += $(SRC_C)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
CFLAGS = $(KBUILD_CFLAGS) $(NOSTDINC_FLAGS) $(ZEPHYRINCLUDE) \
- -std=gnu99 -DNDEBUG $(INC)
+ -std=gnu99 -fomit-frame-pointer -DNDEBUG -DMICROPY_HEAP_SIZE=$(MICROPY_HEAP_SIZE) $(CFLAGS_EXTRA) $(INC)
include ../py/mkrules.mk
$(Z_EXPORTS):
- $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) initconfig outputexports
+ $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE) initconfig outputexports
GENERIC_TARGETS = all zephyr qemu qemugdb flash debug
KCONFIG_TARGETS = \
@@ -70,14 +74,17 @@ $(CLEAN_TARGETS): clean
$(GENERIC_TARGETS) $(KCONFIG_TARGETS) $(CLEAN_TARGETS):
$(RM) -f outdir/$(OUTDIR_PREFIX)/zephyr.lnk
- $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) $@
+ $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE) $@
$(LIBMICROPYTHON): $(Z_SYSGEN_H)
build/genhdr/qstr.i.last: $(Z_SYSGEN_H)
$(Z_SYSGEN_H):
rm -f $(LIBMICROPYTHON)
- -$(MAKE) -f Makefile.zephyr BOARD=$(BOARD)
+ -$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE)
+
+minimal:
+ $(MAKE) BOARD=$(BOARD) CFLAGS_EXTRA='-DMP_CONFIGFILE="<mpconfigport_minimal.h>"' FROZEN_DIR=
# Clean Zephyr things too
clean: z_clean
diff --git a/zephyr/README.md b/zephyr/README.md
index 63fb0e39f4..30f668bb4a 100644
--- a/zephyr/README.md
+++ b/zephyr/README.md
@@ -6,12 +6,20 @@ This is an initial port of MicroPython to Zephyr RTOS
The port integrates well with Zephyr build system, using the latest
features which will be available in 1.6.0, and thus requires Zephyr
-master to build against. All boards supported by Zephyr should be
-supported (but not all were tested).
+master to build against. All boards supported by Zephyr (with standard
+level of feature support, like UART console) should work with
+MicroPython (but not all were tested).
-At this time, only basic interactive prompt (REPL) over UART connection
-is supported. Over time, bindings for various Zephyr subsystems may
-be added.
+Features supported at this time:
+
+* REPL (interactive prompt) over Zephyr UART console.
+* `utime` module for time measurements and delays.
+* `machine.Pin` class for GPIO control.
+* "Frozen modules" support to allow to bundle Python modules together
+ with firmware. Including complete applications, including with
+ run-on-boot capability.
+
+Over time, bindings for various Zephyr subsystems may be added.
Building
@@ -36,10 +44,52 @@ supported boards.
Running
-------
-To run the resulting application in QEMU (for BOARDs like qemu_x86,
+To run the resulting firmware in QEMU (for BOARDs like qemu_x86,
qemu_cortex_m3):
make qemu
-For deploying/flashing the application on a real board, follow Zephyr
+For deploying/flashing a firmware on a real board, follow Zephyr
documentation for a given board.
+
+
+Quick example
+-------------
+
+To blink an LED:
+
+ import time
+ from machine import Pin
+
+ LED = Pin(("GPIO_1", 21), Pin.OUT)
+ while True:
+ LED.value(1)
+ time.sleep(0.5)
+ LED.value(0)
+ time.sleep(0.5)
+
+The above code uses an LED location for a FRDM-K64F board (port B, pin 21;
+following Zephyr conventions port are identified by "GPIO_x", where *x*
+starts from 0). You will need to adjust it for another board (using board's
+reference materials). To execute the above sample, copy it to clipboard, in
+MicroPython REPL enter "paste mode" using Ctrl+E, paste clipboard, press
+Ctrl+D to finish paste mode and start execution.
+
+
+Minimal build
+-------------
+
+MicroPython is committed to maintain minimal binary size for Zephyr port
+below 128KB, as long as Zephyr project is committed to maintain stable
+minimal size of their kernel (which they appear to be). Note that at such
+size, there is no support for any Zephyr features beyond REPL over UART,
+and only very minimal set of builtin Python modules. Thus, this build
+is more suitable for code size control and quick demonstrations even on
+smaller systems. It's also suitable for careful enabling of features one
+by one to achieve needed functionality and code size. This is in contrast
+to the "default" build, which may get more and more features enabled by
+default over time.
+
+To make a minimal build:
+
+ make BOARD=<board> minimal
diff --git a/zephyr/machine_pin.c b/zephyr/machine_pin.c
new file mode 100644
index 0000000000..049255e9f6
--- /dev/null
+++ b/zephyr/machine_pin.c
@@ -0,0 +1,180 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014, 2015 Damien P. George
+ * Copyright (c) 2016 Linaro Limited
+ *
+ * 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 <stdint.h>
+#include <string.h>
+
+#include <zephyr.h>
+#include <gpio.h>
+
+#include "py/nlr.h"
+#include "py/runtime.h"
+#include "py/gc.h"
+#include "py/mphal.h"
+#include "modmachine.h"
+
+const mp_obj_base_t machine_pin_obj_template = {&machine_pin_type};
+
+STATIC void machine_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ machine_pin_obj_t *self = self_in;
+ mp_printf(print, "<Pin %p %d>", self->port, self->pin);
+}
+
+// pin.init(mode, pull=None, *, value)
+STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_mode, ARG_pull, ARG_value };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_mode, MP_ARG_REQUIRED | MP_ARG_INT },
+ { MP_QSTR_pull, MP_ARG_OBJ, {.u_obj = mp_const_none}},
+ { MP_QSTR_value, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL}},
+ };
+
+ // parse args
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
+
+ // get io mode
+ uint mode = args[ARG_mode].u_int;
+
+ // get pull mode
+ uint pull = GPIO_PUD_NORMAL;
+ if (args[ARG_pull].u_obj != mp_const_none) {
+ pull = mp_obj_get_int(args[ARG_pull].u_obj);
+ }
+
+ int ret = gpio_pin_configure(self->port, self->pin, mode | pull);
+ if (ret) {
+ mp_raise_ValueError("invalid pin");
+ }
+
+ // get initial value
+ if (args[ARG_value].u_obj != MP_OBJ_NULL) {
+ (void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[ARG_value].u_obj));
+ }
+
+ return mp_const_none;
+}
+
+// constructor(drv_name, pin, ...)
+STATIC mp_obj_t machine_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
+
+ // get the wanted port
+ if (!MP_OBJ_IS_TYPE(args[0], &mp_type_tuple)) {
+ mp_raise_ValueError("Pin id must be tuple of (\"GPIO_x\", pin#)");
+ }
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(args[0], 2, &items);
+ const char *drv_name = mp_obj_str_get_str(items[0]);
+ int wanted_pin = mp_obj_get_int(items[1]);
+ struct device *wanted_port = device_get_binding(drv_name);
+ if (!wanted_port) {
+ mp_raise_ValueError("invalid port");
+ }
+
+ machine_pin_obj_t *pin = m_new_obj(machine_pin_obj_t);
+ pin->base = machine_pin_obj_template;
+ pin->port = wanted_port;
+ pin->pin = wanted_pin;
+
+ if (n_args > 1 || n_kw > 0) {
+ // pin mode given, so configure this GPIO
+ mp_map_t kw_args;
+ mp_map_init_fixed_table(&kw_args, n_kw, args + n_args);
+ machine_pin_obj_init_helper(pin, n_args - 1, args + 1, &kw_args);
+ }
+
+ return (mp_obj_t)pin;
+}
+
+// fast method for getting/setting pin value
+STATIC mp_obj_t machine_pin_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+ mp_arg_check_num(n_args, n_kw, 0, 1, false);
+ machine_pin_obj_t *self = self_in;
+ if (n_args == 0) {
+ uint32_t pin_val;
+ (void)gpio_pin_read(self->port, self->pin, &pin_val);
+ return MP_OBJ_NEW_SMALL_INT(pin_val);
+ } else {
+ (void)gpio_pin_write(self->port, self->pin, mp_obj_is_true(args[0]));
+ return mp_const_none;
+ }
+}
+
+// pin.init(mode, pull)
+STATIC mp_obj_t machine_pin_obj_init(size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
+ return machine_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
+}
+MP_DEFINE_CONST_FUN_OBJ_KW(machine_pin_init_obj, 1, machine_pin_obj_init);
+
+// pin.value([value])
+STATIC mp_obj_t machine_pin_value(size_t n_args, const mp_obj_t *args) {
+ return machine_pin_call(args[0], n_args - 1, 0, args + 1);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_pin_value_obj, 1, 2, machine_pin_value);
+
+// pin.low()
+STATIC mp_obj_t machine_pin_low(mp_obj_t self_in) {
+ machine_pin_obj_t *self = self_in;
+ (void)gpio_pin_write(self->port, self->pin, 0);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_low_obj, machine_pin_low);
+
+// pin.high()
+STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
+ machine_pin_obj_t *self = self_in;
+ (void)gpio_pin_write(self->port, self->pin, 1);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
+
+STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
+ // instance methods
+ { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&machine_pin_init_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&machine_pin_value_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&machine_pin_low_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&machine_pin_high_obj },
+
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_IN) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_DIR_OUT) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PUD_PULL_UP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PUD_PULL_DOWN) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
+
+const mp_obj_type_t machine_pin_type = {
+ { &mp_type_type },
+ .name = MP_QSTR_Pin,
+ .print = machine_pin_print,
+ .make_new = machine_pin_make_new,
+ .call = machine_pin_call,
+ .locals_dict = (mp_obj_t)&machine_pin_locals_dict,
+};
diff --git a/zephyr/main.c b/zephyr/main.c
index 8d319098b2..9146cfadb6 100644
--- a/zephyr/main.c
+++ b/zephyr/main.c
@@ -58,7 +58,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
}
static char *stack_top;
-static char heap[16 * 1024];
+static char heap[MICROPY_HEAP_SIZE];
int real_main(void) {
int stack_dummy;
@@ -72,7 +72,9 @@ int real_main(void) {
#endif
mp_init();
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
+ #if MICROPY_MODULE_FROZEN
pyexec_frozen_module("main.py");
+ #endif
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
for (;;) {
diff --git a/zephyr/modmachine.c b/zephyr/modmachine.c
new file mode 100644
index 0000000000..6194a95dad
--- /dev/null
+++ b/zephyr/modmachine.c
@@ -0,0 +1,71 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2015 Damien P. George
+ * Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2016 Linaro Limited
+ *
+ * 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>
+#include <stdio.h>
+
+#include "py/obj.h"
+#include "py/runtime.h"
+#include "extmod/machine_mem.h"
+#include "extmod/machine_pulse.h"
+#include "extmod/machine_i2c.h"
+#include "modmachine.h"
+
+#if MICROPY_PY_MACHINE
+
+STATIC mp_obj_t machine_reset(void) {
+ printf("Warning: %s is not implemented\n", __func__);
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
+
+STATIC mp_obj_t machine_reset_cause(void) {
+ printf("Warning: %s is not implemented\n", __func__);
+ return MP_OBJ_NEW_SMALL_INT(42);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
+
+STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
+
+ { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
+
+ // reset causes
+ /*{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },*/
+};
+
+STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
+
+const mp_obj_module_t mp_module_machine = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&machine_module_globals,
+};
+
+#endif // MICROPY_PY_MACHINE
diff --git a/zephyr/modmachine.h b/zephyr/modmachine.h
new file mode 100644
index 0000000000..596c59b178
--- /dev/null
+++ b/zephyr/modmachine.h
@@ -0,0 +1,16 @@
+#ifndef __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__
+#define __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__
+
+#include "py/obj.h"
+
+extern const mp_obj_type_t machine_pin_type;
+
+MP_DECLARE_CONST_FUN_OBJ_0(machine_info_obj);
+
+typedef struct _machine_pin_obj_t {
+ mp_obj_base_t base;
+ struct device *port;
+ uint32_t pin;
+} machine_pin_obj_t;
+
+#endif // __MICROPY_INCLUDED_ZEPHYR_MODMACHINE_H__
diff --git a/zephyr/modutime.c b/zephyr/modutime.c
new file mode 100644
index 0000000000..8b96a5ab1e
--- /dev/null
+++ b/zephyr/modutime.c
@@ -0,0 +1,67 @@
+/*
+ * This file is part of the Micro Python project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2016 Linaro Limited
+ *
+ * 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/mpconfig.h"
+#if MICROPY_PY_UTIME
+
+#include <zephyr.h>
+
+#include "py/runtime.h"
+#include "py/smallint.h"
+#include "py/mphal.h"
+#include "extmod/utime_mphal.h"
+
+STATIC mp_obj_t mod_time_time(void) {
+ /* The absense of FP support is deliberate. The Zephyr port uses
+ * single precision floats so the fraction component will start to
+ * lose precision on devices with a long uptime.
+ */
+ return mp_obj_new_int(sys_tick_get() / sys_clock_ticks_per_sec);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_time_obj, mod_time_time);
+
+STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_utime) },
+ { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&mp_utime_sleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&mod_time_time_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_ms), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_time_globals, mp_module_time_globals_table);
+
+const mp_obj_module_t mp_module_time = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_time_globals,
+};
+
+#endif // MICROPY_PY_UTIME
diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h
index 1654e79b8c..e291faf1d6 100644
--- a/zephyr/mpconfigport.h
+++ b/zephyr/mpconfigport.h
@@ -28,10 +28,10 @@
// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles
#include "autoconf.h"
-// Saving extra crumbs to make sure binary fits in 128K
-#define MICROPY_COMP_CONST_FOLDING (0)
-#define MICROPY_COMP_CONST (0)
-#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)
+// Usually passed from Makefile
+#ifndef MICROPY_HEAP_SIZE
+#define MICROPY_HEAP_SIZE (16 * 1024)
+#endif
#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_GC (1)
@@ -53,13 +53,33 @@
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (0)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
+#define MICROPY_PY_MACHINE (1)
+#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_PY_STRUCT (0)
+#define MICROPY_PY_UTIME (1)
+#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_SYS_MODULES (0)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
+
+// Saving extra crumbs to make sure binary fits in 128K
+#define MICROPY_COMP_CONST_FOLDING (0)
+#define MICROPY_COMP_CONST (0)
+#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)
+
+#ifdef CONFIG_BOARD
+#define MICROPY_HW_BOARD_NAME "zephyr-" CONFIG_BOARD
+#else
#define MICROPY_HW_BOARD_NAME "zephyr-generic"
+#endif
+
+#ifdef CONFIG_SOC
+#define MICROPY_HW_MCU_NAME CONFIG_SOC
+#else
#define MICROPY_HW_MCU_NAME "unknown-cpu"
+#endif
+
#define MICROPY_MODULE_FROZEN_STR (1)
typedef int mp_int_t; // must be pointer size
@@ -77,6 +97,22 @@ typedef long mp_off_t;
mp_obj_t mp_kbd_exception; \
const char *readline_hist[8];
+extern const struct _mp_obj_module_t mp_module_machine;
+extern const struct _mp_obj_module_t mp_module_time;
+
+#if MICROPY_PY_UTIME
+#define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) },
+#else
+#define MICROPY_PY_UTIME_DEF
+#endif
+
+#define MICROPY_PORT_BUILTIN_MODULES \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
+ MICROPY_PY_UTIME_DEF \
+
+#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) }, \
+
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \
diff --git a/zephyr/mpconfigport_minimal.h b/zephyr/mpconfigport_minimal.h
new file mode 100644
index 0000000000..6629ffe9c3
--- /dev/null
+++ b/zephyr/mpconfigport_minimal.h
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Linaro Limited
+ *
+ * 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 <alloca.h>
+
+// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles
+#include "autoconf.h"
+
+// Usually passed from Makefile
+#ifndef MICROPY_HEAP_SIZE
+#define MICROPY_HEAP_SIZE (16 * 1024)
+#endif
+
+#define MICROPY_STACK_CHECK (1)
+#define MICROPY_ENABLE_GC (1)
+#define MICROPY_HELPER_REPL (1)
+#define MICROPY_REPL_AUTO_INDENT (1)
+#define MICROPY_CPYTHON_COMPAT (0)
+#define MICROPY_PY_ASYNC_AWAIT (0)
+#define MICROPY_PY_ATTRTUPLE (0)
+#define MICROPY_PY_BUILTINS_ENUMERATE (0)
+#define MICROPY_PY_BUILTINS_FILTER (0)
+#define MICROPY_PY_BUILTINS_MIN_MAX (0)
+#define MICROPY_PY_BUILTINS_PROPERTY (0)
+#define MICROPY_PY_BUILTINS_RANGE_ATTRS (0)
+#define MICROPY_PY_BUILTINS_REVERSED (0)
+#define MICROPY_PY_BUILTINS_SET (0)
+#define MICROPY_PY_BUILTINS_SLICE (0)
+#define MICROPY_PY_ARRAY (0)
+#define MICROPY_PY_COLLECTIONS (0)
+#define MICROPY_PY_CMATH (0)
+#define MICROPY_PY_IO (0)
+#define MICROPY_PY_STRUCT (0)
+#define MICROPY_PY_SYS_MODULES (0)
+#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG)
+#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_FLOAT)
+#define MICROPY_PY_BUILTINS_COMPLEX (0)
+
+// Saving extra crumbs to make sure binary fits in 128K
+#define MICROPY_COMP_CONST_FOLDING (0)
+#define MICROPY_COMP_CONST (0)
+#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0)
+
+#ifdef CONFIG_BOARD
+#define MICROPY_HW_BOARD_NAME "zephyr-" CONFIG_BOARD
+#else
+#define MICROPY_HW_BOARD_NAME "zephyr-generic"
+#endif
+
+#ifdef CONFIG_SOC
+#define MICROPY_HW_MCU_NAME CONFIG_SOC
+#else
+#define MICROPY_HW_MCU_NAME "unknown-cpu"
+#endif
+
+typedef int mp_int_t; // must be pointer size
+typedef unsigned mp_uint_t; // must be pointer size
+
+typedef void *machine_ptr_t; // must be of pointer size
+typedef const void *machine_const_ptr_t; // must be of pointer size
+typedef long mp_off_t;
+
+#define BYTES_PER_WORD (sizeof(mp_int_t))
+
+#define MP_STATE_PORT MP_STATE_VM
+
+#define MICROPY_PORT_ROOT_POINTERS \
+ mp_obj_t mp_kbd_exception; \
+ const char *readline_hist[8];
diff --git a/zephyr/mphalport.h b/zephyr/mphalport.h
index 1bb64e0002..fafbb9ebe5 100644
--- a/zephyr/mphalport.h
+++ b/zephyr/mphalport.h
@@ -1 +1,27 @@
-static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
+#include <zephyr.h>
+#include "lib/utils/interrupt_char.h"
+
+static inline mp_uint_t mp_hal_ticks_us(void) {
+ return sys_tick_get() * sys_clock_us_per_tick;
+}
+
+static inline mp_uint_t mp_hal_ticks_ms(void) {
+ int64_t us = sys_tick_get() * sys_clock_us_per_tick;
+ mp_int_t ms = us / 1000;
+ return ms;
+}
+
+static inline mp_uint_t mp_hal_ticks_cpu(void) {
+ // ticks_cpu() is defined as using the highest-resolution timing source
+ // in the system. This is usually a CPU clock, but doesn't have to be,
+ // here we just use Zephyr hi-res timer.
+ return sys_cycle_get_32();
+}
+
+static inline void mp_hal_delay_us(mp_uint_t delay) {
+ k_busy_wait(delay);
+}
+
+static inline void mp_hal_delay_ms(mp_uint_t delay) {
+ k_sleep(delay);
+}
diff --git a/zephyr/prj.conf b/zephyr/prj.conf
index 35cb036ded..0b0827d25f 100644
--- a/zephyr/prj.conf
+++ b/zephyr/prj.conf
@@ -1,4 +1,5 @@
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y
+CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS=y
CONFIG_NEWLIB_LIBC=y
CONFIG_FLOAT=y
diff --git a/zephyr/src/zephyr_getchar.c b/zephyr/src/zephyr_getchar.c
index 89e3e0efbc..0f673c9c80 100644
--- a/zephyr/src/zephyr_getchar.c
+++ b/zephyr/src/zephyr_getchar.c
@@ -28,7 +28,7 @@ static struct nano_sem uart_sem;
static uint8_t uart_ringbuf[UART_BUFSIZE];
static uint8_t i_get, i_put;
-static int console_irq_input_hook(struct device *dev, uint8_t ch)
+static int console_irq_input_hook(uint8_t ch)
{
int i_next = (i_put + 1) & (UART_BUFSIZE - 1);
if (i_next == i_get) {
@@ -58,8 +58,7 @@ uint8_t zephyr_getchar(void) {
void zephyr_getchar_init(void) {
nano_sem_init(&uart_sem);
- struct device *uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
- uart_irq_input_hook_set(uart_console_dev, console_irq_input_hook);
+ uart_console_in_debug_hook_install(console_irq_input_hook);
// All NULLs because we're interested only in the callback above
uart_register_input(NULL, NULL, NULL);
}