Compare commits

...

47 Commits

Author SHA1 Message Date
Daniel Thompson 676e97cbe5 zephyr: Initial attempt at machine.Pin
The integration with Zephyr is fairly clean but requires us to use
two arguments to describe a pin:

  drv_name - Name to be sent to device_get_binding()
  pin      - Pin number within the port identified by drv_name

There is support for in/out pins and pull up/pull down but currently
there is no interrupt support.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-09 21:17:09 +01:00
Daniel Thompson 29eccb1007 zephyr: Implement utime module
This provides time and sleep together with the usual
ticks_us/_ms_diff and sleep_us/ms family.

We also provide access to Zephyr's high precision timer
as ticks_cycles (augmented by cycles_to_ns).

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-09 21:17:09 +01:00
Daniel Thompson bba5d67ced zephyr: Implement the help() function
The boot issue text mentions a help() function and encourages
the user to run it. It is very disconcerting to find that the
function does not exist...

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-09 21:17:09 +01:00
Daniel Thompson eddd31ff34 zephyr: Allow NETWORKING and MBEDTLS to be disabled
Allow micropython to automatically disable features that
Zephyr has been configured not to support.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-09 21:17:09 +01:00
Daniel Thompson 9ef2ec9110 zephyr: Exploit "make outputexports"
The outputexpors target, which exports Zephyr environment variables, was
recently added to Zephyr. By exploiting this feature we can hugely simplify
the build system, improving robustness at the same time.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-10-09 21:17:09 +01:00
Paul Sokolovsky 7b562a2be8 zephyr/modsocket: Check pending exception during (some) blocking ops. 2016-09-29 17:35:49 -07:00
Paul Sokolovsky f756c04a63 zephyr: Add Ctrl+C handling. 2016-09-29 17:35:49 -07:00
Paul Sokolovsky c1af9588d1 zephyr/zephyr_getchar: Add support for Ctrl+C handling.
Patch on top of upstream Zephyr console helpers.
2016-09-29 17:35:49 -07:00
Paul Sokolovsky 4de1683601 zephyr/Makefile: Automatically derive target-specific CFLAGS.
By tricking Zephyt arch Makefiles compute them for us (not just for
Zephyr). This make potentially break as Zephyr evolves.
2016-09-29 17:35:49 -07:00
Daniel Thompson 59a6b29748 zephyr: Switch sub-makes to use proper environment variables
Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-09-29 15:23:11 -07:00
Daniel Thompson adf833d8a1 zephyr: Support extra make targets
The two variables, GENERIC_TARGETS and CONFIG_TARGETS come, respectively,
from the the lists shown during "make help" and "make kconfig-help".

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-09-29 15:23:10 -07:00
Daniel Thompson a2be942dc2 zephyr: Automatically derive ARCH
Currently to compile for anything that except ARCH=x86 we have to
provide ARCH via the environment or make arguments. We can do better
than that!

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-09-29 15:23:10 -07:00
Daniel Thompson 9edf72ecae zephyr: Use ?= for BOARD
The main zephyr build system allows BOARD to come from the environment
but the micropython pre-build does not. Fix this.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
2016-09-29 15:23:10 -07:00
Paul Sokolovsky 66cac184af zephyr: Switch to build against Zephyr 1.6.0 by default. 2016-09-29 15:23:10 -07:00
Paul Sokolovsky 75eb7ec066 zephyr/prj.conf: Bump number of RX/TX buffers.
TLS generates a lot, plus there're leaks.
2016-09-29 15:23:10 -07:00
Paul Sokolovsky 79deb6cf49 zephyr/main: Execute main.py frozen module on boot, if available. 2016-09-29 15:23:10 -07:00
Paul Sokolovsky fa1b9593ed zephyr/modsocket: Be sure to define default gateway address (uip_draddr).
Talking to Internet won't work without this.
2016-09-29 15:23:10 -07:00
Paul Sokolovsky a39fe7d449 zephyr/mbedtls-config-upy.h: Disable asm support for now.
It has issues even on various ARM variants (e.g. armv7e-m errors out).
2016-09-29 15:23:10 -07:00
Paul Sokolovsky 718b896f48 zephyr/modsocket: Don't consult uip_connr flags when deciding conn state.
The fact that *now* connection closed doesn't mean there's no data in the
queue. We should process packet queue in order, and consider connection
closed only when hit corresponding state change packet (the latter requires
patches to Zephyr, because otherwise it doesn't deliver connection state
change packets to an app).
2016-09-29 15:22:59 -07:00
Paul Sokolovsky 5269f23b2c zephyr/prj.mdef: Bump "main" stack size to 8K.
More heavier use, like real-world TLS, can smash default 4K. And *this*
stack appears to be used by main(), not CONFIG_MAIN_STACK_SIZE.
2016-09-29 10:16:24 -07:00
Paul Sokolovsky 2743eb105a zephyr: Add mbedTLS config for the port.
Zephyr appear to include only constrained config, we need more features to
access real-world HTTPS, etc.
2016-09-29 10:16:24 -07:00
Paul Sokolovsky 858d859d79 zephyr: Bump heap size to 24K, as required for umqtt.simple. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky ce7480d282 zephyr: Enable ustruct module, required for umqtt.simple. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky c5b33851d7 zephyr/modsocket: socket_write: Send only data fitting in a netbuf. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky 9290942f3a zephyr/modsocket: Detect connection reset in connect().
TODO: Think about connection reset in other places too.
2016-09-29 10:16:24 -07:00
Paul Sokolovsky d3ef82ec16 zephyr: Enable frozen modules support. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky 307612600d zephyr: Enable building ussl_mbedtls module.
Using Zephyr's builtin mbedtls.
2016-09-29 10:16:24 -07:00
Paul Sokolovsky e4a167d42a zephyr/prj.conf: Add network debug logging options (commented). 2016-09-29 10:16:24 -07:00
Paul Sokolovsky 8661fc288b zephyr/prj.conf: Enable mbedTLS. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky 3893a04f48 zephyr/modsocket: Add DEBUG_printf() logging. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky 2d387aa794 zephyr/modsocket: socket_read: Handle zero-length packets.
Zephyr actually filters these out, and requires patching to let them thru.
And underlying uIP uses them to e.g. communicate changes in connection
state (like peer closed connection). Without this change (and associated
Zephyr patch), socket read requests may hang if peer close happened after
read request was issued.
2016-09-29 10:16:24 -07:00
Paul Sokolovsky 1e8605882a zephyr/modsocket: repr(): Dump even more internal socket info. 2016-09-29 10:16:24 -07:00
Paul Sokolovsky b7ac314861 zephyr/modsocket: Implement partial reads/writes. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 545b5a21c6 zephyr/modsocket: Initial implementation of stream protocol. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 0b552e7f06 zephyr/Makefile: Add qemu-net target to run QEMU virtual networking. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky ed312b0575 zephyr: Enable building of modsocket. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 6ea9c13fee zephyr/modsocket: Add initial implementation of usocket module. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 8527d4803d zephyr: Enable (IPv4) networking support. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 4f9ce589f8 zephyr: Implement smart way to access Zephyr config variables.
For this, we first build Z part with libmicropython.a not existing. This
produces autoconf.h with all setiings, but eventually fails on linking
stage due to missing libmicropython.a. We then build MicroPython, which
now can access values in autoconf.h. Then we execute Z build again, which
now succeeds.
2016-09-29 10:16:23 -07:00
Paul Sokolovsky 8f68768a34 zephyr/Makefile: Switch to qemu_x86 by default.
As it supports QEMU virtual networking.
2016-09-29 10:16:23 -07:00
Paul Sokolovsky 7ca39a89ef zephyr: Switch to microkernel, required for network to work in background. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky c0f192f13e zephyr: Enable stack checking and micropython.mem_info(). 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 0882e0e997 zephyr/prj.conf: Set main thread stack size to 4K.
An interpreted language needs good size of stack to do anything useful
(minimum can be set to a lower value of course).
2016-09-29 10:16:23 -07:00
Paul Sokolovsky 26ffe8587b zephyr: Add README. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 84b92e6f28 zephyr: Add zephyr_getchar module to handle console input.
From https://github.com/pfalcon/zephyr_getchar .
2016-09-29 10:16:23 -07:00
Paul Sokolovsky ec252ff8f3 zephyr: Initial Zephyr RTOS port, Zephyr part. 2016-09-29 10:16:23 -07:00
Paul Sokolovsky 3c4fa6a080 zephyr: Initial Zephyr RTOS port, MicroPython part. 2016-09-29 10:16:23 -07:00
23 changed files with 3955 additions and 0 deletions

2
zephyr/.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
outdir/
qemu.pid

3
zephyr/Kbuild 100644
View File

@ -0,0 +1,3 @@
#subdir-ccflags-y += -I$(SOURCE_DIR)/../mylib/include
obj-y += src/

117
zephyr/Makefile 100644
View File

@ -0,0 +1,117 @@
#
# 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.
#
BOARD ?= qemu_x86
# Zephyr 1.5.0
#OUTDIR_PREFIX =
# Zephyr 1.6.0
OUTDIR_PREFIX = $(BOARD)
# Zephyr (generated) config files - must be defined before include below
Z_SYSGEN_H = outdir/$(OUTDIR_PREFIX)/misc/generated/sysgen/sysgen.h
Z_EXPORTS = outdir/$(OUTDIR_PREFIX)/Makefile.export
include $(Z_EXPORTS)
ifdef CONFIG_MBEDTLS
MICROPY_PY_USSL = 1
MICROPY_SSL_MBEDTLS = 1
MICROPY_SSL_MBEDTLS_INCLUDE = $(ZEPHYR_BASE)/ext/lib/crypto/mbedtls/include
endif
FROZEN_DIR = scripts
include ../py/mkenv.mk
include ../py/py.mk
INC += -I.
INC += -I..
INC += -I$(BUILD)
INC += -I$(ZEPHYR_BASE)/net/ip
INC += -I$(ZEPHYR_BASE)/net/ip/contiki
INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os
ifdef CONFIG_NETWORKING
SRC_MOD += modsocket.c
endif
SRC_C = help.c \
main.c \
modutime.c \
modmachine.c \
modpybpin.c \
uart_core.c \
lib/utils/stdout_helpers.c \
lib/utils/printf.c \
lib/utils/pyexec.c \
lib/utils/interrupt_char.c \
lib/mp-readline/readline.c \
lib/netutils/netutils.c \
$(BUILD)/frozen.c \
$(SRC_MOD)
LIB_SRC_C = $(addprefix lib/,\
utils/pyhelp.c \
)
# List of sources for qstr extraction
SRC_QSTR += $(SRC_C)
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(LIB_SRC_C:.c=.o))
CFLAGS = $(KBUILD_CFLAGS) $(NOSTDINC_FLAGS) $(ZEPHYRINCLUDE) \
-std=gnu99 -DNDEBUG $(INC)
include ../py/mkrules.mk
$(Z_EXPORTS):
$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) initconfig outputexports
GENERIC_TARGETS = all zephyr qemu qemugdb flash debug
KCONFIG_TARGETS = \
initconfig config nconfig menuconfig xconfig gconfig \
oldconfig silentoldconfig defconfig savedefconfig \
allnoconfig allyesconfig alldefconfig randconfig \
listnewconfig olddefconfig
CLEAN_TARGETS = pristine mrproper
$(GENERIC_TARGETS) : $(LIBMICROPYTHON)
$(CLEAN_TARGETS) : clean
$(GENERIC_TARGETS) $(KCONFIG_TARGETS) $(CLEAN_TARGETS):
$(RM) -f outdir/$(OUTDIR_PREFIX)/zephyr.lnk
$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) $@
# Note: doesn't rebuild binary, just runs qemu against it
qemu-net:
$(ZEPHYR_SDK_INSTALL_DIR)/sysroots/i686-pokysdk-linux/usr/bin/qemu-system-i386 -m 32 -cpu qemu32 \
-no-reboot -nographic -vga none -display none -net none -clock dynticks -no-acpi -balloon none \
-L $(ZEPHYR_SDK_INSTALL_DIR)/sysroots/i686-pokysdk-linux/usr/share/qemu \
-bios bios.bin -machine type=pc-0.14 -pidfile qemu.pid \
-serial mon:stdio -serial none -serial unix:/tmp/slip.sock \
-kernel outdir/$(OUTDIR_PREFIX)/zephyr.elf
# For GDB debugging with QEMU
#-s -S
$(LIBMICROPYTHON): $(Z_SYSGEN_H)
build/genhdr/qstr.i.last: $(Z_SYSGEN_H)
$(Z_SYSGEN_H):
rm -f $(LIBMICROPYTHON)
-$(MAKE) -f Makefile.zephyr BOARD=$(BOARD)
CLEAN_EXTRA = z_config_proxy.mk
# Clean Zephyr things too
clean : z_clean
z_clean :
$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) clean

View File

@ -0,0 +1,33 @@
#
# Copyright (c) 2016 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
KERNEL_TYPE = micro
# BOARD must be passed on command line from main Makefile
#BOARD =
CONF_FILE = prj.conf
MDEF_FILE = prj.mdef
#export SOURCE_DIR = $(ZEPHYR_BASE)/samples/static_lib/hello_world
export LDFLAGS_zephyr += -L$(CURDIR)
export ALL_LIBS += micropython
# Need to reference dir with mbedTLS config. ZEPHYRINCLUDE doesn't work
# (gets completely overriden by Z). Using STDINCLUDE is definitely a
# hack, but it happens not to be overriden by Z.
#export ZEPHYRINCLUDE += -I$(CURDIR)/src
export STDINCLUDE += -I$(CURDIR)/src
include ${ZEPHYR_BASE}/Makefile.inc

40
zephyr/README 100644
View File

@ -0,0 +1,40 @@
This is initial proof of concept port of MicroPython to Zephyr RTOS
http://zephyrproject.org. It only integrates with Zephyr's console
subsystem so far.
Supported out of the box is Zephyr's armv7-m (Cortex-M3) architecture,
with qemu_cortex_m3 being a default target. Supporting others architectures
may require editing makefiles.
To build:
Intstall Zephyr SDK and Zephyr source from the link above. Configure
Zephyr environment as described in its instructions. Then:
make
To run in QEMU:
make qemu
To build for a real board (see link above for supported Cortex-M boards):
make BOARD=frdm_k64f
For boards with limited FLASH it may be necessary to disable unnecessary
features. For example to run with BOARD=qemu_cortex_m3 try:
make BOARD=qemu_cortex_m3 initconfig
$ZEPHYR_BASE/scripts/config --file outdir/qemu_cortex_m3/.config \
--disable NETWORKING \
--disable MBEDTLS
make BOARD=qemu_cortex_m3
As before we can run this in QEMU too:
make BOARD=qemu_cortex_m3 qemu
The clean targets (clean, pristine, mrproper) all act like their Zephyr
namesakes. In particular a "clean" will causes a full rebuild but will not
remove the .config file.

56
zephyr/help.c 100644
View File

@ -0,0 +1,56 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2013-2016 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 "lib/utils/pyhelp.h"
STATIC const char *help_text =
"Welcome to MicroPython!\n"
"\n"
"Control commands:\n"
" CTRL-A -- on a blank line, enter raw REPL mode\n"
" CTRL-B -- on a blank line, enter normal REPL mode\n"
" CTRL-C -- interrupt a running program\n"
" CTRL-D -- on a blank line, do a soft reset of the board\n"
" CTRL-E -- on a blank line, enter paste mode\n"
"\n"
"For further help on a specific object, type help(obj)\n"
;
STATIC mp_obj_t builtin_help(uint n_args, const mp_obj_t *args) {
if (n_args == 0) {
// print a general help message
printf("%s", help_text);
} else {
// try to print something sensible about the given object
pyhelp_print_obj(args[0]);
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, builtin_help);

102
zephyr/main.c 100644
View File

@ -0,0 +1,102 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "py/nlr.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/repl.h"
#include "py/gc.h"
#include "py/stackctrl.h"
#include "lib/utils/pyexec.h"
#include "lib/mp-readline/readline.h"
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
if (lex == NULL) {
printf("MemoryError: lexer could not allocate memory\n");
return;
}
nlr_buf_t nlr;
if (nlr_push(&nlr) == 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, MP_EMIT_OPT_NONE, 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);
}
}
static char *stack_top;
static char heap[24 * 1024];
int real_main(void) {
int stack_dummy;
stack_top = (char*)&stack_dummy;
mp_stack_set_top(stack_top);
// Should be set to CONFIG_MAIN_STACK_SIZE in prj.conf minus fuzz factor
mp_stack_set_limit(3584);
#if MICROPY_ENABLE_GC
gc_init(heap, heap + sizeof(heap));
#endif
mp_init();
MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
pyexec_frozen_module("main.py");
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
for (;;) {
int c = mp_hal_stdin_rx_chr();
if (pyexec_event_repl_process_char(c)) {
break;
}
}
#else
pyexec_friendly_repl();
#endif
//do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
//do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
mp_deinit();
return 0;
}
void gc_collect(void) {
// WARNING: This gc_collect implementation doesn't try to get root
// pointers from CPU registers, and thus may function incorrectly.
void *dummy;
gc_collect_start();
gc_collect_root(&dummy, ((mp_uint_t)stack_top - (mp_uint_t)&dummy) / sizeof(mp_uint_t));
gc_collect_end();
gc_dump_info();
}
mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
return NULL;
}
mp_import_stat_t mp_import_stat(const char *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);
void nlr_jump_fail(void *val) {
}
void NORETURN __fatal_error(const char *msg) {
while (1);
}
#ifndef NDEBUG
void MP_WEAK __assert_func(const char *file, int line, const char *func, const char *expr) {
printf("Assertion '%s' failed, at file %s:%d\n", expr, file, line);
__fatal_error("Assertion failed");
}
#endif

View File

@ -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 "modpyb.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(&pyb_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

16
zephyr/modpyb.h 100644
View File

@ -0,0 +1,16 @@
#ifndef __MICROPY_INCLUDED_ZEPHYR_MODPYB_H__
#define __MICROPY_INCLUDED_ZEPHYR_MODPYB_H__
#include "py/obj.h"
extern const mp_obj_type_t pyb_pin_type;
MP_DECLARE_CONST_FUN_OBJ(pyb_info_obj);
typedef struct _pyb_pin_obj_t {
mp_obj_base_t base;
struct device *port;
uint32_t pin;
} pyb_pin_obj_t;
#endif // __MICROPY_INCLUDED_ZEPHYR_MODPYB_H__

180
zephyr/modpybpin.c 100644
View File

@ -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 "modpyb.h"
const mp_obj_base_t pyb_pin_obj_template = {&pyb_pin_type};
STATIC void pyb_pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_pin_obj_t *self = self_in;
// pin name
mp_printf(print, "Pin(%p@%d)", self->port, self->pin);
}
// pin.init(mode, pull=None, *, value)
STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_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) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
}
// get initial value
int 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 pyb_pin_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 2, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted port
const char *drv_name = mp_obj_str_get_str(args[0]);
int wanted_pin = mp_obj_get_int(args[1]);
struct device *wanted_port = device_get_binding(drv_name);
if (!wanted_port) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "invalid pin"));
}
pyb_pin_obj_t *pin = m_new_obj(pyb_pin_obj_t);
pin->base = pyb_pin_obj_template;
pin->port = wanted_port;
pin->pin = wanted_pin;
if (n_args > 2 || 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);
pyb_pin_obj_init_helper(pin, n_args - 2, args + 2, &kw_args);
}
return (mp_obj_t)pin;
}
// fast method for getting/setting pin value
STATIC mp_obj_t pyb_pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
pyb_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 pyb_pin_obj_init(mp_uint_t n_args, const mp_obj_t *args, mp_map_t *kw_args) {
return pyb_pin_obj_init_helper(args[0], n_args - 1, args + 1, kw_args);
}
MP_DEFINE_CONST_FUN_OBJ_KW(pyb_pin_init_obj, 1, pyb_pin_obj_init);
// pin.value([value])
STATIC mp_obj_t pyb_pin_value(mp_uint_t n_args, const mp_obj_t *args) {
return pyb_pin_call(args[0], n_args - 1, 0, args + 1);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_pin_value_obj, 1, 2, pyb_pin_value);
// pin.low()
STATIC mp_obj_t pyb_pin_low(mp_obj_t self_in) {
pyb_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(pyb_pin_low_obj, pyb_pin_low);
// pin.high()
STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
pyb_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(pyb_pin_high_obj, pyb_pin_high);
STATIC const mp_map_elem_t pyb_pin_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_pin_init_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pyb_pin_value_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pyb_pin_low_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pyb_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(pyb_pin_locals_dict, pyb_pin_locals_dict_table);
const mp_obj_type_t pyb_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = pyb_pin_print,
.make_new = pyb_pin_make_new,
.call = pyb_pin_call,
.locals_dict = (mp_obj_t)&pyb_pin_locals_dict,
};

319
zephyr/modsocket.c 100644
View File

@ -0,0 +1,319 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
*
* 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 1 // MICROPY_PY_
#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
#include "py/stream.h"
#include "lib/netutils/netutils.h"
// Zephyr includes
#include <zephyr.h>
#include <net/net_core.h>
#include <net/net_socket.h>
#include <net/ip_buf.h>
#define PACK_ALIAS_STRUCT __attribute__((__packed__,__may_alias__))
#include <contiki/ip/uipaddr.h>
#if 1 // print debugging info
#define DEBUG_printf DEBUG_printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
#endif
#define IPADDR {{192, 0, 2, 2}}
#define MY_IPADDR {IPADDR}
#define WAIT_TICKS TICKS_UNLIMITED
// These are uIP public interface variables wich specify this host address/netmask.
uip_ipaddr_t uip_hostaddr = IPADDR;
uip_ipaddr_t uip_netmask = { { 255, 255, 255, 0 } };
uip_ipaddr_t uip_draddr = {{192, 0, 2, 1}};
static struct net_addr my_addr = {
.family = AF_INET,
{ .in_addr = MY_IPADDR },
};
typedef struct _socket_obj_t {
mp_obj_base_t base;
struct net_context *sock;
struct net_addr peer_addr;
struct net_buf *incoming;
mp_uint_t recv_offset;
#define STATE_NEW 0
#define STATE_CONNECTING 1
#define STATE_CONNECTED 2
#define STATE_PEER_CLOSED 3
#define STATE_CLOSED 4
byte state;
} socket_obj_t;
static inline void poll_sockets(void) {
if (MP_STATE_VM(mp_pending_exception) != NULL) {
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
nlr_raise(obj);
}
task_sleep(sys_clock_ticks_per_sec / 10);
}
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
socket_obj_t *self = self_in;
if (self->sock != NULL) {
struct uip_conn *uip_connr = net_context_get_internal_connection(self->sock);
mp_printf(print, "<socket %p: state=%d Zstatus=%d income=%p(@%d) uip_conn=%p",
self->sock,
self->state,
net_context_get_connection_status(self->sock),
self->incoming,
self->recv_offset,
uip_connr);
if (uip_connr != NULL) {
mp_printf(print, " uip_flags=%x uip_oustand=%d",
uip_connr->tcpstateflags,
uip_outstanding(uip_connr));
}
mp_printf(print, ">");
} else {
mp_printf(print, "<socket %p: state=%d>", self->sock, self->state);
}
}
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
assert(n_args == 0);
#if 0
// Net initialization on demand. Has been moved to main(), to let
// the app respond to pings imemdiately after startup.
if (net_init() < 0) {
printf("Error in net_init()\n");
return mp_const_none;
}
#endif
socket_obj_t *o = m_new_obj(socket_obj_t);
o->base.type = type;
// We don't know if this will be client or server socket, so it's
// instantiated lazily
o->sock = NULL;
o->incoming = NULL;
o->recv_offset = 0;
o->state = STATE_NEW;
return o;
}
STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
socket_obj_t *self = self_in;
// Get address
uint8_t ip[NETUTILS_IPV4ADDR_BUFSIZE];
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_BIG);
DEBUG_printf("resolved: %d.%d.%d.%d\n", ip[0], ip[1], ip[2], ip[3]);
struct in_addr in4addr_peer = {{{ip[0], ip[1], ip[2], ip[3]}}};
self->peer_addr.in_addr = in4addr_peer;
self->peer_addr.family = AF_INET;
int proto = IPPROTO_TCP;
self->sock = net_context_get(proto, &self->peer_addr, port, &my_addr, 0);
int ret = net_context_tcp_init(self->sock, /*NULL,*/ NET_TCP_TYPE_CLIENT);
DEBUG_printf("net_context_tcp_init()=%d\n", ret);
// Blocking wait until actually connected
while (net_context_get_connection_status(self->sock) == -EINPROGRESS) {
DEBUG_printf("waiting to connect: %d\n", net_context_get_connection_status(self->sock));
poll_sockets();
}
if (net_context_get_connection_status(self->sock) == -ECONNRESET) {
self->state = STATE_PEER_CLOSED;
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(MP_ECONNRESET)));
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
socket_obj_t *self = self_in;
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
struct net_buf *netbuf = ip_buf_get_tx(self->sock);
uint8_t *ptr = net_buf_add(netbuf, bufinfo.len);
memcpy(ptr, bufinfo.buf, bufinfo.len);
ip_buf_appdatalen(netbuf) = bufinfo.len;
int ret = net_send(netbuf);
return mp_obj_new_int(ret);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
STATIC mp_uint_t socket_write(mp_obj_t self_in, const void *buf, mp_uint_t len, int *errcode) {
DEBUG_printf("socket_write(%p, %p, %d)\n", self_in, buf, len);
socket_obj_t *self = self_in;
struct uip_conn *uip_connr = net_context_get_internal_connection(self->sock);
while (uip_outstanding(uip_connr)) {
DEBUG_printf("wait outstanding flush of %d bytes (connflags: %x)\n", uip_outstanding(uip_connr), uip_connr->tcpstateflags);
poll_sockets();
}
struct net_buf *netbuf = ip_buf_get_tx(self->sock);
if (len > net_buf_tailroom(netbuf)) {
len = net_buf_tailroom(netbuf);
}
uint8_t *ptr = net_buf_add(netbuf, len);
memcpy(ptr, buf, len);
ip_buf_appdatalen(netbuf) = len;
int ret = net_send(netbuf);
if (ret >= 0) {
return len;
}
*errcode = ret;
return MP_STREAM_ERROR;
}
STATIC mp_uint_t socket_read(mp_obj_t self_in, void *buf, mp_uint_t len, int *errcode) {
socket_obj_t *self = self_in;
struct uip_conn *uip_connr = net_context_get_internal_connection(self->sock);
DEBUG_printf("socket_read(%p, %p, %d) conn_flags: %x\n", self_in, buf, len, uip_connr->tcpstateflags);
while (self->incoming == NULL) {
if (self->state == STATE_PEER_CLOSED /*|| uip_connr->tcpstateflags == UIP_CLOSED*/) {
DEBUG_printf("socket_read: Returning EOF\n");
return 0;
}
DEBUG_printf("socket_read: calling net_receive\n");
self->incoming = net_receive(self->sock, WAIT_TICKS);
if (uip_closed(self->incoming)) {
DEBUG_printf("uip_closed() == true\n");
self->state = STATE_PEER_CLOSED;
}
if (ip_buf_appdatalen(self->incoming) == 0) {
// We may be passed 0-length packet to indicate peer closed
// condition (or by any other reason).
self->incoming = NULL;
}
}
mp_uint_t remaining = ip_buf_appdatalen(self->incoming) - self->recv_offset;
if (len > remaining) {
len = remaining;
}
memcpy(buf, ip_buf_appdata(self->incoming) + self->recv_offset, len);
remaining -= len;
if (remaining == 0) {
ip_buf_unref(self->incoming);
self->incoming = NULL;
self->recv_offset = 0;
} else {
self->recv_offset += len;
}
return len;
}
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
socket_obj_t *self = self_in;
if (self->state == STATE_PEER_CLOSED) {
return mp_const_empty_bytes;
}
struct net_buf *buf = net_receive(self->sock, WAIT_TICKS);
mp_obj_t ret = mp_obj_new_bytes(ip_buf_appdata(buf), ip_buf_appdatalen(buf));
if (uip_closed(buf)) {
//printf("uip_closed() == true\n");
self->state = STATE_PEER_CLOSED;
}
ip_buf_unref(buf);
return ret;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
socket_obj_t *self = self_in;
net_context_put(self->sock);
self->sock = NULL;
self->state = STATE_CLOSED;
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
STATIC const mp_stream_p_t socket_stream_p = {
.read = socket_read,
.write = socket_write,
};
STATIC const mp_obj_type_t socket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.print = socket_print,
.make_new = socket_make_new,
.protocol = &socket_stream_p,
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
STATIC const mp_map_elem_t machine_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
};
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
const mp_obj_module_t mp_module_socket = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&machine_module_globals,
};
#endif // MICROPY_PY_

140
zephyr/modutime.c 100644
View File

@ -0,0 +1,140 @@
/*
* 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 <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <zephyr.h>
#include "py/runtime.h"
#include "py/smallint.h"
#include "py/mphal.h"
#define MP_CLOCKS_PER_SEC CLOCKS_PER_SEC
#define CLOCK_DIV (MP_CLOCKS_PER_SEC / 1000.0F)
STATIC mp_obj_t mod_time_time(void) {
/* the absense of f.p. 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 mp_obj_t mod_time_ticks_us(void) {
mp_int_t us = sys_tick_get() * sys_clock_us_per_tick;
return MP_OBJ_NEW_SMALL_INT(us & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_ticks_us_obj, mod_time_ticks_us);
STATIC mp_obj_t mod_time_ticks_ms(void) {
int64_t us = sys_tick_get() * sys_clock_us_per_tick;
mp_int_t ms = us / 1000;
return MP_OBJ_NEW_SMALL_INT(ms & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_ticks_ms_obj, mod_time_ticks_ms);
STATIC mp_obj_t mod_time_ticks_cycles(void) {
return MP_OBJ_NEW_SMALL_INT(sys_cycle_get_32());
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_time_ticks_cycles_obj, mod_time_ticks_cycles);
STATIC mp_obj_t mod_time_cycles_to_ns(mp_obj_t arg) {
mp_int_t cycles = mp_obj_get_int(arg);
return mp_obj_new_int(SYS_CLOCK_HW_CYCLES_TO_NS(cycles));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_cycles_to_ns_obj, mod_time_cycles_to_ns);
STATIC mp_obj_t mod_time_ticks_diff(mp_obj_t oldval, mp_obj_t newval) {
mp_uint_t old = MP_OBJ_SMALL_INT_VALUE(oldval);
mp_uint_t new = MP_OBJ_SMALL_INT_VALUE(newval);
return MP_OBJ_NEW_SMALL_INT((new - old) & MP_SMALL_INT_POSITIVE_MASK);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_time_ticks_diff_obj, mod_time_ticks_diff);
STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) {
MP_THREAD_GIL_EXIT();
#if MICROPY_PY_BUILTINS_FLOAT
if (MP_OBJ_IS_INT(arg)) {
#endif
task_sleep(SECONDS(mp_obj_get_int(arg)));
#if MICROPY_PY_BUILTINS_FLOAT
} else {
task_sleep(MSEC(1000 * mp_obj_get_float(arg)));
}
#endif
MP_THREAD_GIL_ENTER();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_obj, mod_time_sleep);
STATIC mp_obj_t mod_time_sleep_ms(mp_obj_t arg) {
MP_THREAD_GIL_EXIT();
task_sleep(MSEC(mp_obj_get_int(arg)));
MP_THREAD_GIL_ENTER();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_ms_obj, mod_time_sleep_ms);
STATIC mp_obj_t mod_time_sleep_us(mp_obj_t arg) {
MP_THREAD_GIL_EXIT();
task_sleep(USEC(mp_obj_get_int(arg)));
MP_THREAD_GIL_ENTER();
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_time_sleep_us_obj, mod_time_sleep_us);
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(&mod_time_sleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep_ms), MP_ROM_PTR(&mod_time_sleep_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_sleep_us), MP_ROM_PTR(&mod_time_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(&mod_time_ticks_ms_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_us), MP_ROM_PTR(&mod_time_ticks_us_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_cycles), MP_ROM_PTR(&mod_time_ticks_cycles_obj) },
{ MP_ROM_QSTR(MP_QSTR_cycles_to_ns), MP_ROM_PTR(&mod_time_cycles_to_ns_obj) },
{ MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mod_time_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

View File

@ -0,0 +1,89 @@
#include <alloca.h>
// 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)
#define MICROPY_DEBUG_PRINTERS (1)
#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_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_UTIME (1)
/* TODO: Would really like IS_ENABLED(CONFIG_NETWORKING) here but Zephyr
* doesn't have this yet...
*/
#ifdef CONFIG_NETWORKING
#define MICROPY_PY_SOCKET (1)
#else
#define MICROPY_PY_SOCKET (0)
#endif
#define MICROPY_PY_STRUCT (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)
#define MICROPY_HW_BOARD_NAME "zephyr-generic"
#define MICROPY_HW_MCU_NAME "unknown-cpu"
#define MICROPY_MODULE_FROZEN_STR (1)
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];
// 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 }, \
extern const struct _mp_obj_module_t mp_module_machine;
extern const struct _mp_obj_module_t mp_module_socket;
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
#if MICROPY_PY_SOCKET
#define MICROPY_PY_SOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket) },
#else
#define MICROPY_PY_SOCKET_DEF
#endif
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
MICROPY_PY_SOCKET_DEF \
MICROPY_PY_UTIME_DEF \

View File

@ -0,0 +1 @@
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }

29
zephyr/prj.conf 100644
View File

@ -0,0 +1,29 @@
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y
CONFIG_NEWLIB_LIBC=y
CONFIG_FLOAT=y
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_NETWORKING=y
CONFIG_NETWORKING_WITH_IPV4=y
CONFIG_NETWORKING_WITH_TCP=y
CONFIG_NETWORKING_WITH_LOOPBACK=y
CONFIG_NETWORKING_UART=y
CONFIG_NETWORKING_DEBUG_UART=y
CONFIG_IP_BUF_RX_SIZE=17
CONFIG_IP_BUF_TX_SIZE=10
CONFIG_NANO_TIMEOUTS=y
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_CFG_FILE="mbedtls-config-upy.h"
CONFIG_RAM_SIZE=530
# Network debug logging
CONFIG_NETWORKING_WITH_LOGGING=y
#CONFIG_NETWORK_IP_STACK_DEBUG_CONTEXT=y
#CONFIG_NETWORK_IP_STACK_DEBUG_TCP_PSOCK=y
# Verbose net_buf-level logging
#CONFIG_NETWORK_IP_STACK_DEBUG_NET_BUF=y
#CONFIG_NET_BUF_DEBUG=y

5
zephyr/prj.mdef 100644
View File

@ -0,0 +1,5 @@
% Application : MicroPython
% TASK NAME PRIO ENTRY STACK GROUPS
% ==================================
TASK MAIN 7 main 8192 [EXE]

View File

@ -0,0 +1,17 @@
#
# Copyright (c) 2016 Intel Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
obj-y += zephyr_start.o zephyr_getchar.o

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2016 Linaro
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <zephyr.h>
#include <uart.h>
#include <drivers/console/uart_console.h>
#include <misc/printk.h>
#include "zephyr_getchar.h"
extern int mp_interrupt_char;
void mp_keyboard_interrupt(void);
static struct nano_sem uart_sem;
#define UART_BUFSIZE 256
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)
{
int i_next = (i_put + 1) & (UART_BUFSIZE - 1);
if (i_next == i_get) {
printk("UART buffer overflow - char dropped\n");
return 1;
}
if (ch == mp_interrupt_char) {
mp_keyboard_interrupt();
return 1;
} else {
uart_ringbuf[i_put] = ch;
i_put = i_next;
}
//printk("%x\n", ch);
nano_isr_sem_give(&uart_sem);
return 1;
}
uint8_t zephyr_getchar(void) {
nano_task_sem_take(&uart_sem, TICKS_UNLIMITED);
unsigned int key = irq_lock();
uint8_t c = uart_ringbuf[i_get++];
i_get &= UART_BUFSIZE - 1;
irq_unlock(key);
return c;
}
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);
// All NULLs because we're interested only in the callback above
uart_register_input(NULL, NULL, NULL);
}

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2016 Linaro
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
void zephyr_getchar_init(void);
uint8_t zephyr_getchar(void);

View File

@ -0,0 +1,23 @@
#include <zephyr.h>
#include "zephyr_getchar.h"
int real_main(void);
void main(void) {
#ifdef CONFIG_NETWORKING
if (net_init() < 0) {
printf("Error in net_init()\n");
}
#endif
zephyr_getchar_init();
real_main();
}
// This gets pulled in when mbedTLS is enabled in Zephyr config.
// It doesn't seem to be used by mbedTLS directly directly, but
// rather pulled in for some other libc dependency. All in all,
// this doesn't seem to be called, so included to avoid link
// error.
int gettimeofday(struct timeval *tv, struct timezone *tz) {
printf("! dummy gettimeofday called\n");
}

22
zephyr/uart_core.c 100644
View File

@ -0,0 +1,22 @@
#include <unistd.h>
#include "py/mpconfig.h"
#include "src/zephyr_getchar.h"
// Stopgap
extern void printk(const char*, ...);
/*
* Core UART functions to implement for a port
*/
// Receive single character
int mp_hal_stdin_rx_chr(void) {
return zephyr_getchar();
}
// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
while (len--) {
printk("%c", *str++);
}
}

17
zephyr/z_config.mk 100644
View File

@ -0,0 +1,17 @@
srctree = $(ZEPHYR_BASE)
include $(Z_DOTCONFIG)
override ARCH = $(subst $(DQUOTE),,$(CONFIG_ARCH))
SOC_NAME = $(subst $(DQUOTE),,$(CONFIG_SOC))
SOC_SERIES = $(subst $(DQUOTE),,$(CONFIG_SOC_SERIES))
SOC_FAMILY = $(subst $(DQUOTE),,$(CONFIG_SOC_FAMILY))
ifeq ($(SOC_SERIES),)
SOC_PATH = $(SOC_NAME)
else
SOC_PATH = $(SOC_FAMILY)/$(SOC_SERIES)
endif
KBUILD_CFLAGS := -c
include $(ZEPHYR_BASE)/scripts/Kbuild.include
include $(ZEPHYR_BASE)/arch/$(ARCH)/Makefile