Compare commits
37 Commits
jebbatime
...
better-bui
Author | SHA1 | Date |
---|---|---|
Daniel Thompson | 32d4b1eb0f | |
Daniel Thompson | 08d596dd95 | |
Daniel Thompson | d6086be810 | |
Daniel Thompson | 9af5511d93 | |
Daniel Thompson | d5632b5292 | |
Paul Sokolovsky | 0ab6e8fbfd | |
Paul Sokolovsky | b6934ad68c | |
Paul Sokolovsky | 13d54f0914 | |
Paul Sokolovsky | 668e5bcf41 | |
Paul Sokolovsky | 37c7951926 | |
Paul Sokolovsky | 814d6e4169 | |
Paul Sokolovsky | 1819653ce9 | |
Paul Sokolovsky | 90ed575cdc | |
Paul Sokolovsky | 508ed4cc64 | |
Paul Sokolovsky | 2aa6cd9168 | |
Paul Sokolovsky | d545d6bb83 | |
Paul Sokolovsky | 632dfe9be3 | |
Paul Sokolovsky | c703fd0480 | |
Paul Sokolovsky | 7443422093 | |
Paul Sokolovsky | 23ca7e2657 | |
Paul Sokolovsky | e2032582d7 | |
Paul Sokolovsky | dd766368e2 | |
Paul Sokolovsky | 15845b708c | |
Paul Sokolovsky | 788f6ed2e3 | |
Paul Sokolovsky | f2a4d1ad4e | |
Paul Sokolovsky | efed2dd984 | |
Paul Sokolovsky | 316f42bdc1 | |
Paul Sokolovsky | 13257a9f11 | |
Paul Sokolovsky | b310abc440 | |
Paul Sokolovsky | d01061a198 | |
Paul Sokolovsky | bb7fd43b04 | |
Paul Sokolovsky | 24026ed17b | |
Paul Sokolovsky | de2203510e | |
Paul Sokolovsky | b0a95fc00c | |
Paul Sokolovsky | 8004ee68ff | |
Paul Sokolovsky | 217035f23a | |
Paul Sokolovsky | bec77172e7 |
|
@ -0,0 +1,293 @@
|
|||
/*
|
||||
* 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 MICROPY_PY_USSL && MICROPY_SSL_MBEDTLS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
|
||||
// mbedtls_time_t
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/net.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/x509_crt.h"
|
||||
#include "mbedtls/pk.h"
|
||||
#include "mbedtls/entropy.h"
|
||||
#include "mbedtls/ctr_drbg.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
typedef struct _mp_obj_ssl_socket_t {
|
||||
mp_obj_base_t base;
|
||||
mp_obj_t sock;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
mbedtls_x509_crt cacert;
|
||||
mbedtls_x509_crt cert;
|
||||
mbedtls_pk_context pkey;
|
||||
} mp_obj_ssl_socket_t;
|
||||
|
||||
struct ssl_args {
|
||||
mp_arg_val_t key;
|
||||
mp_arg_val_t cert;
|
||||
mp_arg_val_t server_side;
|
||||
mp_arg_val_t server_hostname;
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t ussl_socket_type;
|
||||
|
||||
static void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
|
||||
printf("DBG:%s:%04d: %s\n", file, line, str);
|
||||
}
|
||||
|
||||
// TODO: FIXME!
|
||||
int null_entropy_func(void *data, unsigned char *output, size_t len) {
|
||||
// enjoy random bytes
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
|
||||
mp_obj_t sock = *(mp_obj_t*)ctx;
|
||||
|
||||
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_WRITE);
|
||||
int err;
|
||||
|
||||
int out_sz = sock_stream->write(sock, buf, len, &err);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -err;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
|
||||
mp_obj_t sock = *(mp_obj_t*)ctx;
|
||||
|
||||
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_READ);
|
||||
int err;
|
||||
|
||||
int out_sz = sock_stream->read(sock, buf, len, &err);
|
||||
if (out_sz == MP_STREAM_ERROR) {
|
||||
return -err;
|
||||
} else {
|
||||
return out_sz;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
|
||||
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
|
||||
o->base.type = &ussl_socket_type;
|
||||
|
||||
int ret;
|
||||
mbedtls_ssl_init(&o->ssl);
|
||||
mbedtls_ssl_config_init(&o->conf);
|
||||
mbedtls_x509_crt_init(&o->cacert);
|
||||
mbedtls_x509_crt_init(&o->cert);
|
||||
mbedtls_pk_init(&o->pkey);
|
||||
mbedtls_ctr_drbg_init(&o->ctr_drbg);
|
||||
// Debug level (0-4)
|
||||
mbedtls_debug_set_threshold(0);
|
||||
|
||||
mbedtls_entropy_init(&o->entropy);
|
||||
const byte seed[] = "upy";
|
||||
ret = mbedtls_ctr_drbg_seed(&o->ctr_drbg, null_entropy_func/*mbedtls_entropy_func*/, &o->entropy, seed, sizeof(seed));
|
||||
if (ret != 0) {
|
||||
printf("ret=%d\n", ret);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
ret = mbedtls_ssl_config_defaults(&o->conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (ret != 0) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_authmode(&o->conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_ssl_conf_rng(&o->conf, mbedtls_ctr_drbg_random, &o->ctr_drbg);
|
||||
mbedtls_ssl_conf_dbg(&o->conf, mbedtls_debug, NULL);
|
||||
|
||||
ret = mbedtls_ssl_setup(&o->ssl, &o->conf);
|
||||
if (ret != 0) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (args->server_hostname.u_obj != mp_const_none) {
|
||||
const char *sni = mp_obj_str_get_str(args->server_hostname.u_obj);
|
||||
ret = mbedtls_ssl_set_hostname(&o->ssl, sni);
|
||||
if (ret != 0) {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
o->sock = sock;
|
||||
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
|
||||
|
||||
if (args->key.u_obj != MP_OBJ_NULL) {
|
||||
mp_uint_t key_len;
|
||||
const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len);
|
||||
// len should include terminating null
|
||||
ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
mp_uint_t cert_len;
|
||||
const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
|
||||
// len should include terminating null
|
||||
ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
|
||||
assert(ret == 0);
|
||||
|
||||
ret = mbedtls_ssl_conf_own_cert(&o->conf, &o->cert, &o->pkey);
|
||||
assert(ret == 0);
|
||||
}
|
||||
|
||||
if (args->server_side.u_bool) {
|
||||
assert(0);
|
||||
} else {
|
||||
while ((ret = mbedtls_ssl_handshake(&o->ssl)) != 0) {
|
||||
if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
//assert(0);
|
||||
printf("mbedtls_ssl_handshake error: -%x\n", -ret);
|
||||
nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(EIO)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<_SSLSocket %p>", self);
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
int ret = mbedtls_ssl_read(&o->ssl, buf, size);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
*errcode = ret;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
|
||||
mp_obj_ssl_socket_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
|
||||
int ret = mbedtls_ssl_write(&o->ssl, buf, size);
|
||||
if (ret >= 0) {
|
||||
return ret;
|
||||
}
|
||||
*errcode = ret;
|
||||
return MP_STREAM_ERROR;
|
||||
}
|
||||
|
||||
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
|
||||
mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
|
||||
mbedtls_x509_crt_free(&self->cacert);
|
||||
mbedtls_ssl_free(&self->ssl);
|
||||
mbedtls_ssl_config_free(&self->conf);
|
||||
mbedtls_ctr_drbg_free(&self->ctr_drbg);
|
||||
mbedtls_entropy_free(&self->entropy);
|
||||
|
||||
mp_obj_t dest[2];
|
||||
mp_load_method(self->sock, MP_QSTR_close, dest);
|
||||
return mp_call_method_n_kw(0, 0, dest);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_close_obj, socket_close);
|
||||
|
||||
STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readall), MP_ROM_PTR(&mp_stream_readall_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
|
||||
|
||||
STATIC const mp_stream_p_t ussl_socket_stream_p = {
|
||||
.read = socket_read,
|
||||
.write = socket_write,
|
||||
};
|
||||
|
||||
STATIC const mp_obj_type_t ussl_socket_type = {
|
||||
{ &mp_type_type },
|
||||
// Save on qstr's, reuse same as for module
|
||||
.name = MP_QSTR_ussl,
|
||||
.print = socket_print,
|
||||
.getiter = NULL,
|
||||
.iternext = NULL,
|
||||
.protocol = &ussl_socket_stream_p,
|
||||
.locals_dict = (void*)&ussl_socket_locals_dict,
|
||||
};
|
||||
|
||||
STATIC mp_obj_t mod_ssl_wrap_socket(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
// TODO: Implement more args
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_key, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_cert, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||
{ MP_QSTR_server_side, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} },
|
||||
{ MP_QSTR_server_hostname, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
};
|
||||
|
||||
// TODO: Check that sock implements stream protocol
|
||||
mp_obj_t sock = pos_args[0];
|
||||
|
||||
struct ssl_args args;
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args,
|
||||
MP_ARRAY_SIZE(allowed_args), allowed_args, (mp_arg_val_t*)&args);
|
||||
|
||||
return MP_OBJ_FROM_PTR(socket_new(sock, &args));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 1, mod_ssl_wrap_socket);
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_ssl_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ussl) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_wrap_socket), MP_ROM_PTR(&mod_ssl_wrap_socket_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_ssl_globals, mp_module_ssl_globals_table);
|
||||
|
||||
const mp_obj_module_t mp_module_ussl = {
|
||||
.base = { &mp_type_module },
|
||||
.name = MP_QSTR_ussl,
|
||||
.globals = (mp_obj_dict_t*)&mp_module_ssl_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_USSL
|
6
py/py.mk
6
py/py.mk
|
@ -24,6 +24,11 @@ CFLAGS_MOD += -DMICROPY_PY_USSL=1
|
|||
ifeq ($(MICROPY_SSL_AXTLS),1)
|
||||
CFLAGS_MOD += -DMICROPY_SSL_AXTLS=1 -I../lib/axtls/ssl -I../lib/axtls/crypto -I../lib/axtls/config
|
||||
LDFLAGS_MOD += -Lbuild -laxtls
|
||||
else ifeq ($(MICROPY_SSL_MBEDTLS),1)
|
||||
# Can be overriden by ports which have "builtin" mbedTLS
|
||||
MICROPY_SSL_MBEDTLS_INCLUDE ?= ../lib/mbedtls/include
|
||||
CFLAGS_MOD += -DMICROPY_SSL_MBEDTLS=1 -I$(MICROPY_SSL_MBEDTLS_INCLUDE)
|
||||
LDFLAGS_MOD += -L../lib/mbedtls/library -lmbedx509 -lmbedtls -lmbedcrypto
|
||||
endif
|
||||
endif
|
||||
|
||||
|
@ -210,6 +215,7 @@ PY_O_BASENAME = \
|
|||
../extmod/machine_i2c.o \
|
||||
../extmod/machine_spi.o \
|
||||
../extmod/modussl_axtls.o \
|
||||
../extmod/modussl_mbedtls.o \
|
||||
../extmod/modurandom.o \
|
||||
../extmod/modwebsocket.o \
|
||||
../extmod/modwebrepl.o \
|
||||
|
|
|
@ -29,6 +29,7 @@ MICROPY_PY_FFI = 1
|
|||
# ussl module requires axtls
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_SSL_AXTLS = 1
|
||||
MICROPY_SSL_MBEDTLS = 0
|
||||
|
||||
# jni module requires JVM/JNI
|
||||
MICROPY_PY_JNI = 0
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
#subdir-ccflags-y += -I$(SOURCE_DIR)/../mylib/include
|
||||
|
||||
obj-y += src/
|
|
@ -0,0 +1,112 @@
|
|||
#
|
||||
# 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)
|
||||
|
||||
DOTCONFIG = outdir/$(OUTDIR_PREFIX)/.config
|
||||
DQUOTE = "
|
||||
# "
|
||||
include $(DOTCONFIG)
|
||||
override ARCH = $(subst $(DQUOTE),,$(CONFIG_ARCH))
|
||||
|
||||
MICROPY_PY_USSL = 1
|
||||
MICROPY_SSL_MBEDTLS = 1
|
||||
MICROPY_SSL_MBEDTLS_INCLUDE = $(ZEPHYR_BASE)/ext/lib/crypto/mbedtls/include
|
||||
|
||||
FROZEN_DIR = scripts
|
||||
|
||||
# Zephyr toolchain config is 2-pass, so included twice
|
||||
include $(ZEPHYR_BASE)/scripts/Makefile.toolchain.$(ZEPHYR_GCC_VARIANT)
|
||||
include $(ZEPHYR_BASE)/scripts/Makefile.toolchain.$(ZEPHYR_GCC_VARIANT)
|
||||
|
||||
CFLAGS_arm = -mthumb -mcpu=cortex-m3 -mabi=aapcs
|
||||
ifeq ($(CONFIG_FLOAT), y)
|
||||
ifeq ($(CONFIG_FP_SOFTABI), y)
|
||||
CFLAGS_arm += -mfloat-abi=softfp -mfpu=fpv4-sp-d16
|
||||
endif
|
||||
ifeq ($(CONFIG_FP_HARDABI), y)
|
||||
CFLAGS_arm += -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS_x86 = -fno-asynchronous-unwind-tables -ffreestanding -fno-stack-protector \
|
||||
-fno-omit-frame-pointer -mpreferred-stack-boundary=2 -mno-sse -march=pentium
|
||||
|
||||
CFLAGS_TARGET = $(CFLAGS_$(ARCH))
|
||||
|
||||
include ../py/mkenv.mk
|
||||
include ../py/py.mk
|
||||
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I$(BUILD)
|
||||
INC += -I$(ZEPHYR_BASE)/include -I$(ZEPHYR_BASE) \
|
||||
-I$(ZEPHYR_BASE)/net/ip -I$(ZEPHYR_BASE)/net/ip/contiki -I$(ZEPHYR_BASE)/net/ip/contiki/os \
|
||||
-Ioutdir/$(OUTDIR_PREFIX)/misc/generated/sysgen \
|
||||
-I$(dir $(Z_AUTOCONF_H))
|
||||
|
||||
SRC_C = main.c \
|
||||
uart_core.c \
|
||||
modsocket.c \
|
||||
lib/utils/stdout_helpers.c \
|
||||
lib/utils/printf.c \
|
||||
lib/utils/pyexec.c \
|
||||
lib/mp-readline/readline.c \
|
||||
lib/netutils/netutils.c \
|
||||
$(BUILD)/frozen.c \
|
||||
$(SRC_MOD)
|
||||
|
||||
# List of sources for qstr extraction
|
||||
SRC_QSTR += $(SRC_C)
|
||||
|
||||
OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
|
||||
|
||||
COPT = -Os -DNDEBUG -fdata-sections -ffunction-sections
|
||||
CFLAGS = -std=gnu99 $(TOOLCHAIN_CFLAGS) $(INC) $(CFLAGS_MOD) $(COPT) $(CFLAGS_TARGET)
|
||||
|
||||
include ../py/mkrules.mk
|
||||
|
||||
$(DOTCONFIG) :
|
||||
$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) initconfig
|
||||
|
||||
GENERIC_TARGETS = all zephyr qemu qemugdb flash debug
|
||||
KCONFIG_TARGETS = config nconfig menuconfig xconfig gconfig
|
||||
|
||||
$(GENERIC_TARGETS) $(KCONFIG_TARGETS): $(LIBMICROPYTHON)
|
||||
$(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
|
||||
|
||||
|
||||
Z_AUTOCONF_H = outdir/$(OUTDIR_PREFIX)/include/generated/autoconf.h
|
||||
|
||||
$(LIBMICROPYTHON): $(Z_AUTOCONF_H)
|
||||
build/genhdr/qstr.i.last: $(Z_AUTOCONF_H)
|
||||
|
||||
$(Z_AUTOCONF_H):
|
||||
rm -f $(LIBMICROPYTHON)
|
||||
-$(MAKE) -f Makefile.zephyr BOARD=$(BOARD)
|
||||
|
||||
# Clean Zephyr things too
|
||||
CLEAN_EXTRA = outdir
|
|
@ -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
|
|
@ -0,0 +1,22 @@
|
|||
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
|
|
@ -0,0 +1,99 @@
|
|||
#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"
|
||||
|
||||
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();
|
||||
#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
|
|
@ -0,0 +1,309 @@
|
|||
/*
|
||||
* 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/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 <net/ip/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 } };
|
||||
|
||||
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 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));
|
||||
task_sleep(sys_clock_ticks_per_sec / 10);
|
||||
}
|
||||
|
||||
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\n", uip_outstanding(uip_connr));
|
||||
task_sleep(sys_clock_ticks_per_sec / 10);
|
||||
}
|
||||
|
||||
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 },
|
||||
.name = MP_QSTR_usocket,
|
||||
.globals = (mp_obj_dict_t*)&machine_module_globals,
|
||||
};
|
||||
|
||||
#endif // MICROPY_PY_
|
|
@ -0,0 +1,58 @@
|
|||
#include <alloca.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_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 \
|
||||
const char *readline_hist[8];
|
||||
|
||||
extern const struct _mp_obj_module_t mp_module_socket;
|
||||
|
||||
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||
{ MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_socket) }, \
|
||||
|
||||
// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles
|
||||
#include "autoconf.h"
|
|
@ -0,0 +1,2 @@
|
|||
static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; }
|
||||
static inline void mp_hal_set_interrupt_char(char c) {}
|
|
@ -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=8
|
||||
CONFIG_IP_BUF_TX_SIZE=5
|
||||
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
|
|
@ -0,0 +1,5 @@
|
|||
% Application : MicroPython
|
||||
|
||||
% TASK NAME PRIO ENTRY STACK GROUPS
|
||||
% ==================================
|
||||
TASK MAIN 7 main 4096 [EXE]
|
|
@ -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
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
|
@ -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);
|
|
@ -0,0 +1,21 @@
|
|||
#include <zephyr.h>
|
||||
#include "zephyr_getchar.h"
|
||||
|
||||
int real_main(void);
|
||||
|
||||
void main(void) {
|
||||
if (net_init() < 0) {
|
||||
printf("Error in net_init()\n");
|
||||
}
|
||||
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");
|
||||
}
|
|
@ -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++);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue