summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Ruben Bakke <glennbakke@gmail.com>2017-04-09 17:45:32 +0200
committerGlenn Ruben Bakke <glennbakke@gmail.com>2017-04-09 17:45:32 +0200
commit360243af92bd096522153521bce323f60bdb1b80 (patch)
treee3b0e94099da7ce5e9d895e22e02435c61f205e0
parent5d06aa32609959115b496ac0e596438bfdbda038 (diff)
parentb87432b8fb8332548be11b63c9139065ce565f91 (diff)
Merge branch 'master' into nrf5_no_sdk
-rw-r--r--README.md11
-rw-r--r--bare-arm/Makefile2
-rw-r--r--bare-arm/mpconfigport.h2
-rw-r--r--cc3200/Makefile2
-rw-r--r--cc3200/application.mk3
-rw-r--r--cc3200/ftp/ftp.c2
-rw-r--r--cc3200/mods/modmachine.c5
-rw-r--r--cc3200/mods/moduos.c2
-rw-r--r--cc3200/mods/modusocket.c4
-rw-r--r--cc3200/mods/modutime.c26
-rw-r--r--cc3200/mods/modwlan.c12
-rw-r--r--cc3200/mods/pybi2c.c2
-rw-r--r--cc3200/mods/pybrtc.c4
-rw-r--r--cc3200/mods/pybuart.c13
-rw-r--r--cc3200/mpconfigport.h1
-rw-r--r--cc3200/mptask.c2
-rw-r--r--docs/esp8266/general.rst10
-rw-r--r--docs/library/btree.rst144
-rw-r--r--docs/library/builtins.rst10
-rw-r--r--docs/library/framebuf.rst25
-rw-r--r--docs/library/index.rst1
-rw-r--r--docs/library/machine.I2C.rst2
-rw-r--r--docs/library/machine.Pin.rst62
-rw-r--r--docs/library/machine.SPI.rst12
-rw-r--r--docs/library/machine.UART.rst35
-rw-r--r--docs/library/machine.rst11
-rw-r--r--docs/library/uhashlib.rst30
-rw-r--r--docs/library/uos.rst42
-rw-r--r--docs/library/usocket.rst12
-rw-r--r--docs/library/utime.rst141
-rw-r--r--docs/wipy/general.rst94
-rw-r--r--drivers/nrf24l01/nrf24l01.py76
-rw-r--r--esp8266/Makefile7
-rw-r--r--esp8266/esp8266_common.ld1
-rw-r--r--esp8266/esp_mphal.c7
-rw-r--r--esp8266/fatfs_port.c2
-rw-r--r--esp8266/machine_pin.c28
-rw-r--r--esp8266/machine_rtc.c2
-rw-r--r--esp8266/modesp.c477
-rw-r--r--esp8266/modmachine.c2
-rw-r--r--esp8266/modnetwork.c8
-rw-r--r--esp8266/modutime.c4
-rw-r--r--esp8266/mpconfigport.h4
-rw-r--r--examples/embedding/Makefile.upylib3
-rw-r--r--examples/embedding/mpconfigport_minimal.h2
-rw-r--r--extmod/modbtree.c44
-rw-r--r--extmod/modframebuf.c49
-rw-r--r--extmod/modlwip.c5
-rw-r--r--extmod/modujson.c2
-rw-r--r--extmod/modure.c4
-rw-r--r--extmod/moduselect.c2
-rw-r--r--extmod/modussl_mbedtls.c4
-rw-r--r--extmod/modutimeq.c12
-rw-r--r--extmod/modwebrepl.c2
-rw-r--r--extmod/utime_mphal.c6
-rw-r--r--extmod/vfs.c4
-rw-r--r--extmod/vfs_fat.c2
-rw-r--r--lib/libm/nearbyintf.c21
-rw-r--r--lib/mp-readline/readline.c2
-rw-r--r--lib/netutils/netutils.c4
-rw-r--r--lib/timeutils/timeutils.c2
-rw-r--r--lib/utils/interrupt_char.c5
-rw-r--r--minimal/Makefile5
-rw-r--r--minimal/main.c2
-rw-r--r--minimal/mpconfigport.h2
-rw-r--r--mpy-cross/Makefile2
-rw-r--r--mpy-cross/mpconfigport.h2
-rw-r--r--pic16bit/Makefile3
-rw-r--r--pic16bit/main.c2
-rw-r--r--pic16bit/mpconfigport.h1
-rw-r--r--py/argcheck.c8
-rw-r--r--py/bc.c47
-rw-r--r--py/bc.h13
-rw-r--r--py/builtinevex.c6
-rw-r--r--py/builtinimport.c10
-rw-r--r--py/compile.c38
-rw-r--r--py/emitbc.c6
-rw-r--r--py/emitnative.c43
-rw-r--r--py/lexer.c83
-rw-r--r--py/mkrules.mk7
-rw-r--r--py/modbuiltins.c28
-rw-r--r--py/modmath.c2
-rw-r--r--py/modmicropython.c14
-rw-r--r--py/modthread.c4
-rw-r--r--py/mpconfig.h24
-rw-r--r--py/mpstate.h17
-rw-r--r--py/nlrx86.c3
-rw-r--r--py/obj.c32
-rw-r--r--py/obj.h34
-rw-r--r--py/objarray.c7
-rw-r--r--py/objcomplex.c3
-rw-r--r--py/objdict.c2
-rw-r--r--py/objfloat.c3
-rw-r--r--py/objfun.c16
-rw-r--r--py/objgenerator.c16
-rw-r--r--py/objint.c67
-rw-r--r--py/objint.h11
-rw-r--r--py/objint_longlong.c20
-rw-r--r--py/objint_mpz.c24
-rw-r--r--py/objlist.c10
-rw-r--r--py/objmap.c6
-rw-r--r--py/objnamedtuple.c26
-rw-r--r--py/objobject.c2
-rw-r--r--py/objrange.c6
-rw-r--r--py/objstr.c27
-rw-r--r--py/objstringio.c2
-rw-r--r--py/objstrunicode.c2
-rw-r--r--py/objtuple.c7
-rw-r--r--py/objtype.c52
-rw-r--r--py/objzip.c6
-rw-r--r--py/parsenum.c2
-rw-r--r--py/py.mk4
-rw-r--r--py/repl.c6
-rw-r--r--py/runtime.c57
-rw-r--r--py/runtime.h18
-rw-r--r--py/scheduler.c117
-rw-r--r--py/sequence.c38
-rw-r--r--py/vm.c91
-rw-r--r--qemu-arm/Makefile4
-rw-r--r--qemu-arm/mpconfigport.h2
-rw-r--r--stmhal/Makefile7
-rw-r--r--stmhal/boards/LIMIFROG/mpconfigboard.h7
-rw-r--r--stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h5
-rw-r--r--stmhal/boards/NUCLEO_F767ZI/pins.csv50
-rw-r--r--stmhal/boards/NUCLEO_L476RG/mpconfigboard.h4
-rw-r--r--stmhal/boards/STM32F769DISC/mpconfigboard.h16
-rw-r--r--stmhal/boards/STM32F769DISC/mpconfigboard.mk2
-rw-r--r--stmhal/boards/STM32F769DISC/pins.csv12
-rw-r--r--stmhal/boards/STM32F7DISC/mpconfigboard.h10
-rw-r--r--stmhal/boards/STM32L476DISC/mpconfigboard.h7
-rwxr-xr-xstmhal/boards/make-pins.py4
-rw-r--r--stmhal/boards/stm32f767_af.csv33
-rw-r--r--stmhal/boards/stm32f769_af.csv171
-rw-r--r--stmhal/can.c6
-rw-r--r--stmhal/dma.c8
-rw-r--r--stmhal/dma.h2
-rw-r--r--stmhal/extint.c3
-rw-r--r--stmhal/hal/f7/src/stm32f7xx_hal_dma.c4
-rw-r--r--stmhal/i2c.c53
-rw-r--r--stmhal/input.c2
-rw-r--r--stmhal/irq.h4
-rw-r--r--stmhal/lcd.c4
-rw-r--r--stmhal/main.c2
-rw-r--r--stmhal/modnwcc3k.c6
-rw-r--r--stmhal/modnwwiznet5k.c2
-rw-r--r--stmhal/moduos.c2
-rw-r--r--stmhal/modusocket.c4
-rw-r--r--stmhal/modutime.c4
-rw-r--r--stmhal/mpconfigport.h13
-rw-r--r--stmhal/mphalport.h4
-rw-r--r--stmhal/pendsv.c3
-rw-r--r--stmhal/pin_defs_stmhal.h12
-rw-r--r--stmhal/pybthread.c17
-rw-r--r--stmhal/sdcard.c69
-rw-r--r--stmhal/spi.c14
-rw-r--r--stmhal/startup_stm32.S24
-rw-r--r--stmhal/systick.c17
-rw-r--r--stmhal/timer.c2
-rw-r--r--stmhal/usbd_cdc_interface.c91
-rw-r--r--teensy/Makefile3
-rw-r--r--teensy/main.c2
-rw-r--r--teensy/mpconfigport.h2
-rw-r--r--tests/basics/builtin_range.py6
-rw-r--r--tests/basics/bytearray_slice_assign.py5
-rw-r--r--tests/basics/class_super_closure.py18
-rw-r--r--tests/basics/for_range.py7
-rw-r--r--tests/basics/list_slice_assign_grow.py5
-rw-r--r--tests/basics/tuple1.py4
-rw-r--r--tests/extmod/framebuf1.py172
-rw-r--r--tests/extmod/framebuf1.py.exp47
-rw-r--r--tests/extmod/vfs_fat_fileio.py.exp24
-rw-r--r--tests/extmod/vfs_fat_fileio1.py118
-rw-r--r--tests/extmod/vfs_fat_fileio1.py.exp13
-rw-r--r--tests/extmod/vfs_fat_fileio2.py (renamed from tests/extmod/vfs_fat_fileio.py)75
-rw-r--r--tests/extmod/vfs_fat_fileio2.py.exp11
-rw-r--r--tests/feature_check/const.py1
-rw-r--r--tests/feature_check/const.py.exp0
-rw-r--r--tests/float/builtin_float_hash.py22
-rw-r--r--tests/float/builtin_float_round.py7
-rw-r--r--tests/float/builtin_float_round_intbig.py4
-rw-r--r--tests/float/bytearray_construct.py7
-rw-r--r--tests/float/bytes_construct.py7
-rw-r--r--tests/float/complex1.py4
-rw-r--r--tests/float/math_fun_int.py15
-rw-r--r--tests/float/math_fun_intbig.py12
-rw-r--r--tests/micropython/heapalloc_iter.py9
-rw-r--r--tests/micropython/heapalloc_str.py4
-rw-r--r--tests/micropython/schedule.py61
-rw-r--r--tests/micropython/schedule.py.exp4
-rwxr-xr-xtests/run-tests24
-rw-r--r--tests/unix/extra_coverage.py.exp11
-rwxr-xr-xtools/pyboard.py91
-rw-r--r--unix/Makefile3
-rw-r--r--unix/alloc.c6
-rw-r--r--unix/coverage.c29
-rw-r--r--unix/main.c2
-rw-r--r--unix/modffi.c3
-rw-r--r--unix/modos.c9
-rw-r--r--unix/modtermios.c3
-rw-r--r--unix/modtime.c4
-rw-r--r--unix/mpconfigport.h10
-rw-r--r--unix/mpconfigport_coverage.h1
-rw-r--r--unix/mpconfigport_minimal.h2
-rw-r--r--windows/.gitignore1
-rw-r--r--windows/Makefile2
-rw-r--r--windows/micropython.vcxproj8
-rw-r--r--windows/mpconfigport.h2
-rw-r--r--windows/msvc/genhdr.targets4
-rw-r--r--zephyr/Makefile22
-rw-r--r--zephyr/machine_pin.c27
-rw-r--r--zephyr/modmachine.c2
-rw-r--r--zephyr/modusocket.c456
-rw-r--r--zephyr/mpconfigport.h21
-rw-r--r--zephyr/mpconfigport_minimal.h4
-rw-r--r--zephyr/prj_base.conf10
-rw-r--r--zephyr/src/zephyr_getchar.c3
216 files changed, 2753 insertions, 1985 deletions
diff --git a/README.md b/README.md
index 9e747e82c..26c6f6a01 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,4 @@
-[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo]
-[travis-img]: https://travis-ci.org/micropython/micropython.png?branch=master
-[travis-repo]: https://travis-ci.org/micropython/micropython
-[coveralls-img]: https://coveralls.io/repos/micropython/micropython/badge.png?branch=master
-[coveralls-repo]: https://coveralls.io/r/micropython/micropython?branch=master
+[![Build Status](https://travis-ci.org/micropython/micropython.png?branch=master)](https://travis-ci.org/micropython/micropython) [![Coverage Status](https://coveralls.io/repos/micropython/micropython/badge.png?branch=master)](https://coveralls.io/r/micropython/micropython?branch=master)
The MicroPython project
=======================
@@ -38,7 +34,9 @@ Major components in this repository:
- minimal/ -- a minimal MicroPython port. Start with this if you want
to port MicroPython to another microcontroller.
- tests/ -- test framework and test scripts.
-- docs/ -- user documentation in Sphinx reStructuredText format.
+- docs/ -- user documentation in Sphinx reStructuredText format. Rendered
+ HTML documentation is available at http://docs.micropython.org (be sure
+ to select needed board/port at the bottom left corner).
Additional components:
- bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used
@@ -48,6 +46,7 @@ Additional components:
- pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
- cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
+- extmod/ -- additional (non-core) modules implemented in C.
- tools/ -- various tools, including the pyboard.py module.
- examples/ -- a few example Python scripts.
diff --git a/bare-arm/Makefile b/bare-arm/Makefile
index a57ccfd19..cfd427c60 100644
--- a/bare-arm/Makefile
+++ b/bare-arm/Makefile
@@ -13,7 +13,7 @@ INC += -I..
INC += -I$(BUILD)
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
+CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h
index 912fae66f..97e866bdb 100644
--- a/bare-arm/mpconfigport.h
+++ b/bare-arm/mpconfigport.h
@@ -46,8 +46,6 @@
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
#define UINT_FMT "%lu"
diff --git a/cc3200/Makefile b/cc3200/Makefile
index 4db3b9e8d..663496435 100644
--- a/cc3200/Makefile
+++ b/cc3200/Makefile
@@ -20,7 +20,7 @@ include ../py/mkenv.mk
CROSS_COMPILE ?= arm-none-eabi-
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
+CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
CFLAGS += -Iboards/$(BOARD)
CFLAGS += $(CFLAGS_MOD)
diff --git a/cc3200/application.mk b/cc3200/application.mk
index b15dbde7f..5d25424e1 100644
--- a/cc3200/application.mk
+++ b/cc3200/application.mk
@@ -18,9 +18,6 @@ APP_INC += -Iutil
APP_INC += -Ibootmgr
APP_INC += -I$(BUILD)
APP_INC += -I$(BUILD)/genhdr
-APP_INC += -I../lib/mp-readline
-APP_INC += -I../lib/netutils
-APP_INC += -I../lib/timeutils
APP_INC += -I../stmhal
APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS
diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c
index 22035d6b3..1febe291f 100644
--- a/cc3200/ftp/ftp.c
+++ b/cc3200/ftp/ftp.c
@@ -29,6 +29,7 @@
#include "py/mpstate.h"
#include "py/obj.h"
+#include "lib/timeutils/timeutils.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
@@ -48,7 +49,6 @@
#include "fifo.h"
#include "socketfifo.h"
#include "updater.h"
-#include "timeutils.h"
#include "moduos.h"
/******************************************************************************
diff --git a/cc3200/mods/modmachine.c b/cc3200/mods/modmachine.c
index 3c4e5a116..fd1485607 100644
--- a/cc3200/mods/modmachine.c
+++ b/cc3200/mods/modmachine.c
@@ -111,10 +111,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info)
#endif
STATIC mp_obj_t machine_freq(void) {
- mp_obj_t tuple[1] = {
- mp_obj_new_int(HAL_FCPU_HZ),
- };
- return mp_obj_new_tuple(1, tuple);
+ return mp_obj_new_int(HAL_FCPU_HZ);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c
index 5523c887f..add10ec6c 100644
--- a/cc3200/mods/moduos.c
+++ b/cc3200/mods/moduos.c
@@ -33,6 +33,7 @@
#include "py/objtuple.h"
#include "py/objstr.h"
#include "py/runtime.h"
+#include "lib/timeutils/timeutils.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "genhdr/mpversion.h"
@@ -43,7 +44,6 @@
#include "random.h"
#include "mpexception.h"
#include "version.h"
-#include "timeutils.h"
#include "pybsd.h"
#include "pybuart.h"
diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c
index 02ce3e279..ca28bf7ba 100644
--- a/cc3200/mods/modusocket.c
+++ b/cc3200/mods/modusocket.c
@@ -34,7 +34,7 @@
#include "py/objstr.h"
#include "py/runtime.h"
#include "py/stream.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#include "modusocket.h"
#include "mpexception.h"
@@ -737,7 +737,7 @@ STATIC const mp_obj_type_t socket_type = {
// function usocket.getaddrinfo(host, port)
/// \function getaddrinfo(host, port)
STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
- mp_uint_t hlen;
+ size_t hlen;
const char *host = mp_obj_str_get_data(host_in, &hlen);
mp_int_t port = mp_obj_get_int(port_in);
diff --git a/cc3200/mods/modutime.c b/cc3200/mods/modutime.c
index de1f75012..48fde67e7 100644
--- a/cc3200/mods/modutime.c
+++ b/cc3200/mods/modutime.c
@@ -33,8 +33,8 @@
#include "py/obj.h"
#include "py/smallint.h"
#include "py/mphal.h"
+#include "lib/timeutils/timeutils.h"
#include "extmod/utime_mphal.h"
-#include "timeutils.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -102,7 +102,7 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- mp_uint_t len;
+ size_t len;
mp_obj_t *elem;
mp_obj_get_array(tuple, &len, &elem);
@@ -131,24 +131,6 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
}
MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
-STATIC mp_obj_t time_sleep_ms (mp_obj_t ms_in) {
- mp_int_t ms = mp_obj_get_int(ms_in);
- if (ms > 0) {
- mp_hal_delay_ms(ms);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms);
-
-STATIC mp_obj_t time_sleep_us (mp_obj_t usec_in) {
- mp_int_t usec = mp_obj_get_int(usec_in);
- if (usec > 0) {
- mp_hal_delay_us(usec);
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us);
-
STATIC const mp_map_elem_t time_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
@@ -158,8 +140,8 @@ STATIC const mp_map_elem_t time_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
// MicroPython additions
- { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj },
diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c
index 2a0d3bf63..68d892364 100644
--- a/cc3200/mods/modwlan.c
+++ b/cc3200/mods/modwlan.c
@@ -773,7 +773,7 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
wlan_validate_mode(mode);
// get the ssid
- mp_uint_t ssid_len = 0;
+ size_t ssid_len = 0;
const char *ssid = NULL;
if (args[1].u_obj != NULL) {
ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len);
@@ -782,7 +782,7 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
// get the auth config
uint8_t auth = SL_SEC_TYPE_OPEN;
- mp_uint_t key_len = 0;
+ size_t key_len = 0;
const char *key = NULL;
if (args[2].u_obj != mp_const_none) {
mp_obj_t *sec;
@@ -922,13 +922,13 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get the ssid
- mp_uint_t ssid_len;
+ size_t ssid_len;
const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
wlan_validate_ssid_len(ssid_len);
// get the auth config
uint8_t auth = SL_SEC_TYPE_OPEN;
- mp_uint_t key_len = 0;
+ size_t key_len = 0;
const char *key = NULL;
if (args[1].u_obj != mp_const_none) {
mp_obj_t *sec;
@@ -1077,7 +1077,7 @@ STATIC mp_obj_t wlan_ssid (mp_uint_t n_args, const mp_obj_t *args) {
if (n_args == 1) {
return mp_obj_new_str((const char *)self->ssid, strlen((const char *)self->ssid), false);
} else {
- mp_uint_t len;
+ size_t len;
const char *ssid = mp_obj_str_get_data(args[1], &len);
wlan_validate_ssid_len(len);
wlan_set_ssid(ssid, len, false);
@@ -1101,7 +1101,7 @@ STATIC mp_obj_t wlan_auth (mp_uint_t n_args, const mp_obj_t *args) {
} else {
// get the auth config
uint8_t auth = SL_SEC_TYPE_OPEN;
- mp_uint_t key_len = 0;
+ size_t key_len = 0;
const char *key = NULL;
if (args[1] != mp_const_none) {
mp_obj_t *sec;
diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c
index 658b2bfcd..a6009cb77 100644
--- a/cc3200/mods/pybi2c.c
+++ b/cc3200/mods/pybi2c.c
@@ -278,6 +278,8 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
mp_raise_OSError(MP_EIO);
}
+ } else {
+ mp_raise_OSError(MP_EIO);
}
}
diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c
index ddc26faf9..134bd440e 100644
--- a/cc3200/mods/pybrtc.c
+++ b/cc3200/mods/pybrtc.c
@@ -29,6 +29,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "py/mperrno.h"
+#include "lib/timeutils/timeutils.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -37,7 +38,6 @@
#include "pybrtc.h"
#include "mpirq.h"
#include "pybsleep.h"
-#include "timeutils.h"
#include "simplelink.h"
#include "modnetwork.h"
#include "modwlan.h"
@@ -196,7 +196,7 @@ STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
// set date and time
mp_obj_t *items;
- uint len;
+ size_t len;
mp_obj_get_array(datetime, &len, &items);
// verify the tuple
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
index bab2b3d22..92bb3e46e 100644
--- a/cc3200/mods/pybuart.c
+++ b/cc3200/mods/pybuart.c
@@ -375,10 +375,13 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
config |= UART_CONFIG_PAR_NONE;
} else {
uint parity = mp_obj_get_int(args[2].u_obj);
- if (parity != UART_CONFIG_PAR_ODD && parity != UART_CONFIG_PAR_EVEN) {
+ if (parity == 0) {
+ config |= UART_CONFIG_PAR_EVEN;
+ } else if (parity == 1) {
+ config |= UART_CONFIG_PAR_ODD;
+ } else {
goto error;
}
- config |= parity;
}
// stop bits
config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
@@ -388,7 +391,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
uint flowcontrol = UART_FLOWCONTROL_NONE;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
- mp_uint_t n_pins = 2;
+ size_t n_pins = 2;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_uart_def_pin[self->uart_id];
@@ -454,7 +457,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
if (args[0].u_obj == MP_OBJ_NULL) {
if (args[5].u_obj != MP_OBJ_NULL) {
mp_obj_t *pins;
- mp_uint_t n_pins = 2;
+ size_t n_pins = 2;
mp_obj_get_array(args[5].u_obj, &n_pins, &pins);
// check the Tx pin (or the Rx if Tx is None)
if (pins[0] == mp_const_none) {
@@ -577,8 +580,6 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_EVEN), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_EVEN) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ODD), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_ODD) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(UART_TRIGGER_RX_ANY) },
};
diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h
index a8dc0cfeb..4d19900ae 100644
--- a/cc3200/mpconfigport.h
+++ b/cc3200/mpconfigport.h
@@ -200,7 +200,6 @@ extern const struct _mp_obj_module_t mp_module_ussl;
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
#define MP_SSIZE_MAX (0x7FFFFFFF)
diff --git a/cc3200/mptask.c b/cc3200/mptask.c
index 3c49a5603..d446711a2 100644
--- a/cc3200/mptask.c
+++ b/cc3200/mptask.c
@@ -33,6 +33,7 @@
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
+#include "lib/mp-readline/readline.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs.h"
@@ -51,7 +52,6 @@
#include "lib/utils/pyexec.h"
#include "gccollect.h"
#include "gchelper.h"
-#include "readline.h"
#include "mperror.h"
#include "simplelink.h"
#include "modnetwork.h"
diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst
index cd659f80a..47df80d7b 100644
--- a/docs/esp8266/general.rst
+++ b/docs/esp8266/general.rst
@@ -107,8 +107,16 @@ This will allow to keep the structure of your application clear, as well as
allow to install multiple applications on a board, and switch among them.
+Known Issues
+------------
+
Real-time clock
----------------
+~~~~~~~~~~~~~~~
+
+RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As
+a workaround, to measure short enough intervals you can use
+``utime.time()``, etc. functions, and for wall clock time, synchronize from
+the net using included ``ntpdate.py`` module.
Due to limitations of the ESP8266 chip the internal real-time clock (RTC)
will overflow every 7:45h. If a long-term working RTC time is required then
diff --git a/docs/library/btree.rst b/docs/library/btree.rst
new file mode 100644
index 000000000..aebcbc160
--- /dev/null
+++ b/docs/library/btree.rst
@@ -0,0 +1,144 @@
+:mod:`btree` -- simple BTree database
+=====================================
+
+.. module:: btree
+ :synopsis: simple BTree database
+
+The ``btree`` module implements a simple key-value database using external
+storage (disk files, or in general case, a random-access stream). Keys are
+stored sorted in the database, and besides efficient retrieval by a key
+value, a database also supports efficient ordered range scans (retrieval
+of values with the keys in a given range). On the application interface
+side, BTree database work as close a possible to a way standard `dict`
+type works, one notable difference is that both keys and values must
+be `bytes` objects (so, if you want to store objects of other types, you
+need to serialize them to `bytes` first).
+
+The module is based on the well-known BerkelyDB library, version 1.xx.
+
+Example::
+
+ import btree
+
+ # First, we need to open a stream which holds a database
+ # This is usually a file, but can be in-memory database
+ # using uio.BytesIO, a raw flash section, etc.
+ f = open("mydb", "w+b")
+
+ # Now open a database itself
+ db = btree.open(f)
+
+ # The keys you add will be sorted internally in the database
+ db[b"3"] = b"three"
+ db[b"1"] = b"one"
+ db[b"2"] = b"two"
+
+ # Prints b'two'
+ print(db[b"2"])
+
+ # Iterate over sorted keys in the database, starting from b"2"
+ # until the end of the database, returning only values.
+ # Mind that arguments passed to values() method are *key* values.
+ # Prints:
+ # b'two'
+ # b'three'
+ for word in db.values(b"2"):
+ print(word)
+
+ del db[b"2"]
+
+ # No longer true, prints False
+ print(b"2" in db)
+
+ # Prints:
+ # b"1"
+ # b"3"
+ for key in db:
+ print(key)
+
+ db.close()
+
+ # Don't forget to close the underlying stream!
+ f.close()
+
+
+Functions
+---------
+
+.. function:: open(stream, \*, flags=0, cachesize=0, pagesize=0, minkeypage=0)
+
+ Open a database from a random-access `stream` (like an open file). All
+ other parameters are optional and keyword-only, and allow to tweak advanced
+ paramters of the database operation (most users will not need them):
+
+ * `flags` - Currently unused.
+ * `cachesize` - Suggested maximum memory cache size in bytes. For a
+ board with enough memory using larger values may improve performance.
+ The value is only a recommendation, the module may use more memory if
+ values set too low.
+ * `pagesize` - Page size used for the nodes in BTree. Acceptable range
+ is 512-65536. If 0, underlying I/O block size will be used (the best
+ compromise between memory usage and performance).
+ * `minkeypage` - Minimum number of keys to store per page. Default value
+ of 0 equivalent to 2.
+
+ Returns a `BTree` object, which implements a dictionary protocol (set
+ of methods), and some additional methods described below.
+
+Methods
+-------
+
+.. method:: btree.close()
+
+ Close the database. It's mandatory to close the database at the end of
+ processing, as some unwritten data may be still in the cache. Note that
+ this does not close underlying streamw with which the database was opened,
+ it should be closed separately (which is also mandatory to make sure that
+ data flushed from buffer to the underlying storage).
+
+.. method:: btree.flush()
+
+ Flush any data in cache to the underlying stream.
+
+.. method:: btree.__getitem__(key)
+.. method:: btree.get(key, default=None)
+.. method:: btree.__setitem__(key, val)
+.. method:: btree.__detitem__(key)
+.. method:: btree.__contains__(key)
+
+ Standard dictionary methods.
+
+.. method:: btree.__iter__()
+
+ A BTree object can be iterated over directly (similar to a dictionary)
+ to get access to all keys in order.
+
+.. method:: btree.keys([start_key, [end_key, [flags]]])
+.. method:: btree.values([start_key, [end_key, [flags]]])
+.. method:: btree.items([start_key, [end_key, [flags]]])
+
+ These methods are similar to standard dictionary methods, but also can
+ take optional parameters to iterate over a key sub-range, instead of
+ the entire database. Note that for all 3 methods, `start_key` and
+ `end_key` arguments represent key values. For example, ``values()``
+ method will iterate over values corresponding to they key range
+ given. None values for `start_key` means "from the first key", no
+ `end_key` or its value of None means "until the end of database".
+ By default, range is inclusive of `start_key` and exclusive of
+ `end_key`, you can include `end_key` in iteration by passing `flags`
+ of `btree.INCL`. You can iterate in descending key direction
+ by passing `flags` of `btree.DESC`. The flags values can be ORed
+ together.
+
+Constants
+---------
+
+.. data:: INCL
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be inclusive of the end key.
+
+.. data:: DESC
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be in descending direction of keys.
diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst
index d53c4d377..46f762660 100644
--- a/docs/library/builtins.rst
+++ b/docs/library/builtins.rst
@@ -67,6 +67,16 @@ All builtin functions are described here. They are also available via
.. class:: int()
+ .. classmethod:: from_bytes(bytes, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
+ .. method:: to_bytes(size, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
.. function:: isinstance()
.. function:: issubclass()
diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst
index 91fc362fd..61f0635f3 100644
--- a/docs/library/framebuf.rst
+++ b/docs/library/framebuf.rst
@@ -116,9 +116,32 @@ Other methods
Constants
---------
-.. data:: framebuf.MVLSB
+.. data:: framebuf.MONO_VLSB
Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are vertically mapped with
+ bit 0 being nearest the top of the screen. Consequently each byte occupies
+ 8 vertical pixels. Subsequent bytes appear at successive horizontal
+ locations until the rightmost edge is reached. Further bytes are rendered
+ at locations starting at the leftmost edge, 8 pixels lower.
+
+.. data:: framebuf.MONO_HLSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 0 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
+
+.. data:: framebuf.MONO_HMSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 7 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
.. data:: framebuf.RGB565
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 5d64d01f7..1a61f6882 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -153,6 +153,7 @@ the following libraries.
.. toctree::
:maxdepth: 1
+ btree.rst
framebuf.rst
machine.rst
micropython.rst
diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst
index cdeb246eb..45944709e 100644
--- a/docs/library/machine.I2C.rst
+++ b/docs/library/machine.I2C.rst
@@ -100,7 +100,7 @@ General Methods
Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of
those that respond. A device responds if it pulls the SDA line low after
- its address (including a read bit) is sent on the bus.
+ its address (including a write bit) is sent on the bus.
Note: on WiPy the I2C object must be in master mode for this method to be valid.
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index 952131f09..216ebcb2a 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -38,58 +38,6 @@ Usage Model::
# configure an irq callback
p0.irq(lambda p:print(p))
-.. only:: port_wipy
-
- On the WiPy board the pins are identified by their string id::
-
- from machine import Pin
- g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
-
- You can also configure the Pin to generate interrupts. For instance::
-
- from machine import Pin
-
- def pincb(pin):
- print(pin.id())
-
- pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
- pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
- # the callback can be triggered manually
- pin_int.irq()()
- # to disable the callback
- pin_int.irq().disable()
-
- Now every time a falling edge is seen on the gpio pin, the callback will be
- executed. Caution: mechanical push buttons have "bounce" and pushing or
- releasing a switch will often generate multiple edges.
- See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
- explanation, along with various techniques for debouncing.
-
- All pin objects go through the pin mapper to come up with one of the
- gpio pins.
-
- For the ``drive`` parameter the strengths are:
-
- - ``Pin.LOW_POWER`` - 2mA drive capability.
- - ``Pin.MED_POWER`` - 4mA drive capability.
- - ``Pin.HIGH_POWER`` - 6mA drive capability.
-
- For the ``alt`` parameter please refer to the pinout and alternate functions
- table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
- for the specific alternate functions that each pin supports.
-
- For interrupts, the ``priority`` can take values in the range 1-7. And the
- ``wake`` parameter has the following properties:
-
- - If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
- - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
- ``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
- of this pins can be enabled as a wake source at the same time, so, only
- the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
- - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
- ``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
- 6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
-
Constructors
------------
@@ -277,16 +225,6 @@ Methods
This method returns a callback object.
-.. only:: port_wipy
-
- .. method:: Pin.alt_list()
-
- Returns a list of the alternate functions supported by the pin. List items are
- a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
-
- Availability: WiPy.
-
-
Attributes
----------
diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst
index e8a8a2d8c..82858629f 100644
--- a/docs/library/machine.SPI.rst
+++ b/docs/library/machine.SPI.rst
@@ -10,18 +10,6 @@ SS (Slave Select), to select a particular device on a bus with which
communication takes place. Management of an SS signal should happen in
user code (via machine.Pin class).
-.. only:: port_wipy
-
- See usage model of I2C; SPI is very similar. Main difference is
- parameters to init the SPI bus::
-
- from machine import SPI
- spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
-
- Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
- 1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
- sample data on the first or second clock edge respectively.
-
Constructors
------------
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index 0b6b24e89..fe7597eb5 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -15,17 +15,13 @@ UART objects can be created and initialised using::
uart = UART(1, 9600) # init with given baudrate
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
-.. only:: port_machineoard
+Supported paramters differ on a board:
- Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
-
- *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
- only 7 and 8 bits are supported.
-
-.. only:: port_wipy
-
- Bits can be 5, 6, 7, 8. Parity can be ``None``, ``UART.EVEN`` or ``UART.ODD``. Stop can be 1 or 2.
+Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With `parity=None`,
+only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits
+are supported.
+WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2.
A UART object acts like a stream object and reading and writing is done
using the standard stream methods::
@@ -47,22 +43,12 @@ using the standard stream methods::
uart.any() # returns True if any characters waiting
-.. only:: port_wipy
-
- To check if there is anything to be read, use::
-
- uart.any() # returns the number of characters available for reading
-
Constructors
------------
-.. only:: port_wipy
+.. class:: UART(id, ...)
- .. class:: UART(bus, ...)
-
- Construct a UART object on the given bus. ``bus`` can be 0 or 1.
- If the bus is not given, the default one will be selected (0) or the selection
- will be made based on the given pins.
+ Construct a UART object of the given id.
Methods
-------
@@ -75,7 +61,7 @@ Methods
- ``baudrate`` is the clock rate.
- ``bits`` is the number of bits per character, 7, 8 or 9.
- - ``parity`` is the parity, ``None``, ``UART.EVEN`` or ``UART.ODD``.
+ - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
- ``stop`` is the number of stop bits, 1 or 2.
- ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order).
Any of the pins can be None if one wants the UART to operate with limited functionality.
@@ -159,11 +145,6 @@ Methods
Constants
---------
- .. data:: UART.EVEN
- .. data:: UART.ODD
-
- parity types (along with ``None``)
-
.. data:: UART.RX_ANY
IRQ trigger sources
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index c677bcbf0..1007f142f 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -52,16 +52,7 @@ Power related functions
.. function:: freq()
- .. only:: not port_wipy
-
- Returns CPU frequency in hertz.
-
- .. only:: port_wipy
-
- Returns a tuple of clock frequencies: ``(sysclk,)``
- These correspond to:
-
- - sysclk: frequency of the CPU
+ Returns CPU frequency in hertz.
.. function:: idle()
diff --git a/docs/library/uhashlib.rst b/docs/library/uhashlib.rst
index 2c340e40b..cd0216dae 100644
--- a/docs/library/uhashlib.rst
+++ b/docs/library/uhashlib.rst
@@ -37,36 +37,6 @@ Constructors
Create an MD5 hasher object and optionally feed ``data`` into it.
-.. only:: port_wipy
-
- .. class:: uhashlib.sha1([data[, block_size]])
-
- Create a sha1 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
-
- .. class:: uhashlib.sha256([data[, block_size]])
-
- Create a sha256 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
-
- .. admonition:: CPython extension
- :class: attention
-
- Due to hardware implementation details of the WiPy, data must be buffered before being
- digested, which would make it impossible to calculate the hash of big blocks of data that
- do not fit in RAM. In this case, since most likely the total size of the data is known
- in advance, the size can be passed to the constructor and hence the HASH hardware engine
- of the WiPy can be properly initialized without needing buffering. If ``block_size`` is
- to be given, an initial chunk of ``data`` must be passed as well. **When using this extension,
- care must be taken to make sure that the length of all intermediate chunks (including the
- initial one) is a multiple of 4 bytes.** The last chunk may be of any length.
-
- Example::
-
- hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
- hash.update('1234') # also multiple of 4 bytes
- ...
- hash.update('12345') # last chunk may be of any length
- hash.digest()
-
Methods
-------
diff --git a/docs/library/uos.rst b/docs/library/uos.rst
index cd0c5cae8..bb3c20017 100644
--- a/docs/library/uos.rst
+++ b/docs/library/uos.rst
@@ -61,28 +61,26 @@ Functions
Get the status of a file or directory.
-.. only:: port_unix or port_pyboard or port_esp8266
-
- .. function:: statvfs(path)
-
- Get the status of a fileystem.
-
- Returns a tuple with the filesystem information in the following order:
-
- * ``f_bsize`` -- file system block size
- * ``f_frsize`` -- fragment size
- * ``f_blocks`` -- size of fs in f_frsize units
- * ``f_bfree`` -- number of free blocks
- * ``f_bavail`` -- number of free blocks for unpriviliged users
- * ``f_files`` -- number of inodes
- * ``f_ffree`` -- number of free inodes
- * ``f_favail`` -- number of free inodes for unpriviliged users
- * ``f_flag`` -- mount flags
- * ``f_namemax`` -- maximum filename length
-
- Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
- and the ``f_flags`` parameter may return ``0`` as they can be unavailable
- in a port-specific implementation.
+.. function:: statvfs(path)
+
+ Get the status of a fileystem.
+
+ Returns a tuple with the filesystem information in the following order:
+
+ * ``f_bsize`` -- file system block size
+ * ``f_frsize`` -- fragment size
+ * ``f_blocks`` -- size of fs in f_frsize units
+ * ``f_bfree`` -- number of free blocks
+ * ``f_bavail`` -- number of free blocks for unpriviliged users
+ * ``f_files`` -- number of inodes
+ * ``f_ffree`` -- number of free inodes
+ * ``f_favail`` -- number of free inodes for unpriviliged users
+ * ``f_flag`` -- mount flags
+ * ``f_namemax`` -- maximum filename length
+
+ Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
+ and the ``f_flags`` parameter may return ``0`` as they can be unavailable
+ in a port-specific implementation.
.. function:: sync()
diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst
index dd0f5708b..71deaebc4 100644
--- a/docs/library/usocket.rst
+++ b/docs/library/usocket.rst
@@ -41,18 +41,6 @@ Functions
Create a new socket using the given address family, socket type and protocol number.
- .. only:: port_wipy
-
- .. note::
-
- SSL sockets need to be created the following way before wrapping them with
- ``ssl.wrap_socket``::
-
- import socket
- import ssl
- s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
- ss = ssl.wrap_socket(s)
-
.. function:: socket.getaddrinfo(host, port)
Translate the host/port argument into a sequence of 5-tuples that contain all the
diff --git a/docs/library/utime.rst b/docs/library/utime.rst
index 109c3560c..871f6c678 100644
--- a/docs/library/utime.rst
+++ b/docs/library/utime.rst
@@ -55,60 +55,50 @@ Functions
which expresses a time as per localtime. It returns an integer which is
the number of seconds since Jan 1, 2000.
-.. only:: port_unix or port_pyboard or port_esp8266
+.. function:: sleep(seconds)
- .. function:: sleep(seconds)
-
- Sleep for the given number of seconds. Seconds can be a floating-point number to
- sleep for a fractional number of seconds. Note that other MicroPython ports may
- not accept floating-point argument, for compatibility with them use ``sleep_ms()``
- and ``sleep_us()`` functions.
+ Sleep for the given number of seconds. Some boards may accept `seconds` as a
+ floating-point number to sleep for a fractional number of seconds. Note that
+ other boards may not accept a floating-point argument, for compatibility with
+ them use ``sleep_ms()`` and ``sleep_us()`` functions.
-.. only:: port_wipy
+.. function:: sleep_ms(ms)
- .. function:: sleep(seconds)
-
- Sleep for the given number of seconds.
+ Delay for given number of milliseconds, should be positive or 0.
-.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
+.. function:: sleep_us(us)
- .. function:: sleep_ms(ms)
+ Delay for given number of microseconds, should be positive or 0.
- Delay for given number of milliseconds, should be positive or 0.
+.. function:: ticks_ms()
- .. function:: sleep_us(us)
+ Returns an increasing millisecond counter with an arbitrary reference point, that
+ wraps around after some value. This value is not explicitly exposed, but we will
+ refer to it as ``TICKS_MAX`` to simplify discussion. Period of the values is
+ ``TICKS_PERIOD = TICKS_MAX + 1``. ``TICKS_PERIOD`` is guaranteed to be a power of
+ two, but otherwise may differ from port to port. The same period value is used
+ for all of ``ticks_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (for
+ simplicity). Thus, these functions will return a value in range [``0`` ..
+ ``TICKS_MAX``], inclusive, total ``TICKS_PERIOD`` values. Note that only
+ non-negative values are used. For the most part, you should treat values returned
+ by these functions as opaque. The only operations available for them are
+ ``ticks_diff()`` and ``ticks_add()`` functions described below.
- Delay for given number of microseconds, should be positive or 0
+ Note: Performing standard mathematical operations (+, -) or relational
+ operators (<, <=, >, >=) directly on these value will lead to invalid
+ result. Performing mathematical operations and then passing their results
+ as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
+ invalid results from the latter functions.
- .. function:: ticks_ms()
+.. function:: ticks_us()
- Returns an increasing millisecond counter with an arbitrary reference point,
- that wraps around after some value. This value is not explicitly exposed,
- but we will refer to it as `TICKS_MAX` to simplify discussion. Period of
- the values is `TICKS_PERIOD = TICKS_MAX + 1`. `TICKS_PERIOD` is guaranteed
- to be a power of two, but otherwise may differ from port to port. The same
- period value is used for all of ticks_ms(), ticks_us(), ticks_cpu() functions
- (for simplicity). Thus, these functions will return a value in range
- [0 .. `TICKS_MAX`], inclusive, total `TICKS_PERIOD` values. Note that only
- non-negative values are used. For the most part, you should treat values
- returned by these functions as opaque. The only operations available for them
- are ``ticks_diff()`` and ``ticks_add()`` functions described below.
+ Just like ``ticks_ms()`` above, but in microseconds.
- Note: Performing standard mathematical operations (+, -) or relational
- operators (<, <=, >, >=) directly on these value will lead to invalid
- result. Performing mathematical operations and then passing their results
- as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
- invalid results from the latter functions.
+.. function:: ticks_cpu()
- .. function:: ticks_us()
-
- Just like ``ticks_ms`` above, but in microseconds.
-
-.. function:: ticks_cpu()
-
- Similar to ``ticks_ms`` and ``ticks_us``, but with the highest possible resolution
+ Similar to ``ticks_ms()`` and ``ticks_us()``, but with the highest possible resolution
in the system. This is usually CPU clocks, and that's why the function is named that
- way. But it doesn't have to a CPU clock, some other timing source available in a
+ way. But it doesn't have to be a CPU clock, some other timing source available in a
system (e.g. high-resolution timer) can be used instead. The exact timing unit
(resolution) of this function is not specified on ``utime`` module level, but
documentation for a specific port may provide more specific information. This
@@ -118,13 +108,13 @@ Functions
Availability: Not every port implements this function.
-.. function:: ticks_add(ticks, delta)
+.. function:: ticks_add(ticks, delta)
Offset ticks value by a given number, which can be either positive or negative.
Given a ``ticks`` value, this function allows to calculate ticks value ``delta``
ticks before or after it, following modular-arithmetic definition of tick values
(see ``ticks_ms()`` above). ``ticks`` parameter must be a direct result of call
- to ``tick_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (or from previous
+ to ``ticks_ms()``, ``ticks_us()``, or ``ticks_cpu()`` functions (or from previous
call to ``ticks_add()``). However, ``delta`` can be an arbitrary integer number
or numeric expression. ``ticks_add()`` is useful for calculating deadlines for
events/tasks. (Note: you must use ``ticks_diff()`` function to work with
@@ -133,35 +123,37 @@ Functions
Examples::
# Find out what ticks value there was 100ms ago
- print(tick_add(time.ticks_ms(), -100))
+ print(ticks_add(time.ticks_ms(), -100))
# Calculate deadline for operation and test for it
- deadline = tick_add(time.ticks_ms(), 200)
+ deadline = ticks_add(time.ticks_ms(), 200)
while ticks_diff(deadline, time.ticks_ms()) > 0:
do_a_little_of_something()
# Find out TICKS_MAX used by this port
- print(tick_add(0, -1))
-
-
-.. function:: ticks_diff(ticks1, ticks2)
-
- Measure ticks difference between values returned from ticks_ms(), ticks_us(), or ticks_cpu()
- functions. The argument order is the same as for subtraction operator,
- ``tick_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by
- ticks_ms(), etc. functions may wrap around, so directly using subtraction on them will
- produce incorrect result. That is why ticks_diff() is needed, it implements modular
- (or more specifically, ring) arithmetics to produce correct result even for wrap-around
- values (as long as they not too distant inbetween, see below). The function returns
- **signed** value in the range [`-TICKS_PERIOD/2` .. `TICKS_PERIOD/2-1`] (that's a typical
- range definition for two's-complement signed binary integers). If the result is negative,
- it means that `ticks1` occured earlier in time than `ticks2`. Otherwise, it means that
- `ticks1` occured after `ticks2`. This holds `only` if `ticks1` and `ticks2` are apart from
- each other for no more than `TICKS_PERIOD/2-1` ticks. If that does not hold, incorrect
- result will be returned. Specifically, if 2 tick values are apart for `TICKS_PERIOD/2-1`
- ticks, that value will be returned by the function. However, if `TICKS_PERIOD/2` of
- real-time ticks has passed between them, the function will return `-TICKS_PERIOD/2`
- instead, i.e. result value will wrap around to the negative range of possible values.
+ print(ticks_add(0, -1))
+
+
+.. function:: ticks_diff(ticks1, ticks2)
+
+ Measure ticks difference between values returned from ``ticks_ms()``, ``ticks_us()``,
+ or ``ticks_cpu()`` functions. The argument order is the same as for subtraction
+ operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``.
+ However, values returned by ``ticks_ms()``, etc. functions may wrap around, so
+ directly using subtraction on them will produce incorrect result. That is why
+ ``ticks_diff()`` is needed, it implements modular (or more specifically, ring)
+ arithmetics to produce correct result even for wrap-around values (as long as they not
+ too distant inbetween, see below). The function returns **signed** value in the range
+ [``-TICKS_PERIOD/2`` .. ``TICKS_PERIOD/2-1``] (that's a typical range definition for
+ two's-complement signed binary integers). If the result is negative, it means that
+ ``ticks1`` occured earlier in time than ``ticks2``. Otherwise, it means that
+ ``ticks1`` occured after ``ticks2``. This holds ``only`` if ``ticks1`` and ``ticks2``
+ are apart from each other for no more than ``TICKS_PERIOD/2-1`` ticks. If that does
+ not hold, incorrect result will be returned. Specifically, if two tick values are
+ apart for ``TICKS_PERIOD/2-1`` ticks, that value will be returned by the function.
+ However, if ``TICKS_PERIOD/2`` of real-time ticks has passed between them, the
+ function will return ``-TICKS_PERIOD/2`` instead, i.e. result value will wrap around
+ to the negative range of possible values.
Informal rationale of the constraints above: Suppose you are locked in a room with no
means to monitor passing of time except a standard 12-notch clock. Then if you look at
@@ -200,20 +192,21 @@ Functions
print("Oops, running late, tell task to run faster!")
task.run(run_faster=true)
- Note: Do not pass ``time()`` values to ``ticks_diff()``, and should use
+ Note: Do not pass ``time()`` values to ``ticks_diff()``, you should use
normal mathematical operations on them. But note that ``time()`` may (and will)
also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
.. function:: time()
- Returns the number of seconds, as an integer, since the Epoch, assuming that underlying
- RTC is set and maintained as described above. If an RTC is not set, this function returns
- number of seconds since a port-specific reference point in time (for embedded boards without
- a battery-backed RTC, usually since power up or reset). If you want to develop portable
- MicroPython application, you should not rely on this function to provide higher than second
- precision. If you need higher precision, use ``ticks_ms()`` and ``ticks_us()`` functions,
- if you need calendar time, ``localtime()`` without an argument is a better choice.
+ Returns the number of seconds, as an integer, since the Epoch, assuming that
+ underlying RTC is set and maintained as described above. If an RTC is not set, this
+ function returns number of seconds since a port-specific reference point in time (for
+ embedded boards without a battery-backed RTC, usually since power up or reset). If you
+ want to develop portable MicroPython application, you should not rely on this function
+ to provide higher than second precision. If you need higher precision, use
+ ``ticks_ms()`` and ``ticks_us()`` functions, if you need calendar time,
+ ``localtime()`` without an argument is a better choice.
.. admonition:: Difference to CPython
:class: attention
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index 0991dbaea..eca9bbe45 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -179,3 +179,97 @@ Details on sleep modes
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
and ``WLAN``
* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``.
+
+Additional details for machine.Pin
+----------------------------------
+
+On the WiPy board the pins are identified by their string id::
+
+ from machine import Pin
+ g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
+
+You can also configure the Pin to generate interrupts. For instance::
+
+ from machine import Pin
+
+ def pincb(pin):
+ print(pin.id())
+
+ pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
+ pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
+ # the callback can be triggered manually
+ pin_int.irq()()
+ # to disable the callback
+ pin_int.irq().disable()
+
+Now every time a falling edge is seen on the gpio pin, the callback will be
+executed. Caution: mechanical push buttons have "bounce" and pushing or
+releasing a switch will often generate multiple edges.
+See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
+explanation, along with various techniques for debouncing.
+
+All pin objects go through the pin mapper to come up with one of the
+gpio pins.
+
+For the ``drive`` parameter the strengths are:
+
+ - ``Pin.LOW_POWER`` - 2mA drive capability.
+ - ``Pin.MED_POWER`` - 4mA drive capability.
+ - ``Pin.HIGH_POWER`` - 6mA drive capability.
+
+For the ``alt`` parameter please refer to the pinout and alternate functions
+table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
+for the specific alternate functions that each pin supports.
+
+For interrupts, the ``priority`` can take values in the range 1-7. And the
+``wake`` parameter has the following properties:
+
+ - If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
+ - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
+ ``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
+ of this pins can be enabled as a wake source at the same time, so, only
+ the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
+ - If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
+ ``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
+ 6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
+
+Additional Pin methods:
+
+.. method:: machine.Pin.alt_list()
+
+ Returns a list of the alternate functions supported by the pin. List items are
+ a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
+
+Known issues
+------------
+
+Incompatible way to create SSL sockets
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+SSL sockets need to be created the following way before wrapping them with.
+``ssl.wrap_socket``::
+
+ import socket
+ import ssl
+ s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
+ ss = ssl.wrap_socket(s)
+
+Incompatibilities in uhashlib module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Due to hardware implementation details of the WiPy, data must be buffered before being
+digested, which would make it impossible to calculate the hash of big blocks of data that
+do not fit in RAM. In this case, since most likely the total size of the data is known
+in advance, the size can be passed to the constructor and hence the HASH hardware engine
+of the WiPy can be properly initialized without needing buffering. If ``block_size`` is
+to be given, an initial chunk of ``data`` must be passed as well. **When using this extension,
+care must be taken to make sure that the length of all intermediate chunks (including the
+initial one) is a multiple of 4 bytes.** The last chunk may be of any length.
+
+Example::
+
+ hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
+ hash.update('1234') # also multiple of 4 bytes
+ ...
+ hash.update('12345') # last chunk may be of any length
+ hash.digest()
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
index 3c79650bf..788906dc0 100644
--- a/drivers/nrf24l01/nrf24l01.py
+++ b/drivers/nrf24l01/nrf24l01.py
@@ -2,7 +2,7 @@
"""
from micropython import const
-import pyb
+import utime
# nRF24L01+ registers
CONFIG = const(0x00)
@@ -53,22 +53,24 @@ class NRF24L01:
def __init__(self, spi, cs, ce, channel=46, payload_size=16):
assert payload_size <= 32
- # init the SPI bus and pins
- spi.init(spi.MASTER, baudrate=4000000, polarity=0, phase=0, firstbit=spi.MSB)
- cs.init(cs.OUT_PP, cs.PULL_NONE)
- ce.init(ce.OUT_PP, ce.PULL_NONE)
+ self.buf = bytearray(1)
# store the pins
self.spi = spi
self.cs = cs
self.ce = ce
+ # init the SPI bus and pins
+ self.init_spi(4000000)
+ cs.init(cs.OUT, value=1)
+ ce.init(ce.OUT, value=0)
+
# reset everything
self.ce.low()
self.cs.high()
self.payload_size = payload_size
self.pipe0_read_addr = None
- pyb.delay(5)
+ utime.sleep_ms(5)
# set address width to 5 bytes and check for device present
self.reg_write(SETUP_AW, 0b11)
@@ -98,28 +100,44 @@ class NRF24L01:
self.flush_rx()
self.flush_tx()
+ def init_spi(self, baudrate):
+ try:
+ master = self.spi.MASTER
+ except AttributeError:
+ self.spi.init(baudrate=baudrate, polarity=0, phase=0)
+ else:
+ self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
+
def reg_read(self, reg):
self.cs.low()
- self.spi.send_recv(reg)
- buf = self.spi.recv(1)
+ self.spi.readinto(self.buf, reg)
+ self.spi.readinto(self.buf)
+ self.cs.high()
+ return self.buf[0]
+
+ def reg_write_bytes(self, reg, buf):
+ self.cs.low()
+ self.spi.readinto(self.buf, 0x20 | reg)
+ self.spi.write(buf)
self.cs.high()
- return buf[0]
+ return self.buf[0]
- def reg_write(self, reg, buf):
+ def reg_write(self, reg, value):
self.cs.low()
- status = self.spi.send_recv(0x20 | reg)[0]
- self.spi.send(buf)
+ self.spi.readinto(self.buf, 0x20 | reg)
+ ret = self.buf[0]
+ self.spi.readinto(self.buf, value)
self.cs.high()
- return status
+ return ret
def flush_rx(self):
self.cs.low()
- self.spi.send(FLUSH_RX)
+ self.spi.readinto(self.buf, FLUSH_RX)
self.cs.high()
def flush_tx(self):
self.cs.low()
- self.spi.send(FLUSH_TX)
+ self.spi.readinto(self.buf, FLUSH_TX)
self.cs.high()
# power is one of POWER_x defines; speed is one of SPEED_x defines
@@ -144,8 +162,8 @@ class NRF24L01:
# address should be a bytes object 5 bytes long
def open_tx_pipe(self, address):
assert len(address) == 5
- self.reg_write(RX_ADDR_P0, address)
- self.reg_write(TX_ADDR, address)
+ self.reg_write_bytes(RX_ADDR_P0, address)
+ self.reg_write_bytes(TX_ADDR, address)
self.reg_write(RX_PW_P0, self.payload_size)
# address should be a bytes object 5 bytes long
@@ -157,7 +175,7 @@ class NRF24L01:
if pipe_id == 0:
self.pipe0_read_addr = address
if pipe_id < 2:
- self.reg_write(RX_ADDR_P0 + pipe_id, address)
+ self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
else:
self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
@@ -168,12 +186,12 @@ class NRF24L01:
self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
if self.pipe0_read_addr is not None:
- self.reg_write(RX_ADDR_P0, self.pipe0_read_addr)
+ self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
self.flush_rx()
self.flush_tx()
self.ce.high()
- pyb.udelay(130)
+ utime.sleep_us(130)
def stop_listening(self):
self.ce.low()
@@ -187,8 +205,8 @@ class NRF24L01:
def recv(self):
# get the data
self.cs.low()
- self.spi.send(R_RX_PAYLOAD)
- buf = self.spi.recv(self.payload_size)
+ self.spi.readinto(self.buf, R_RX_PAYLOAD)
+ buf = self.spi.read(self.payload_size)
self.cs.high()
# clear RX ready flag
self.reg_write(STATUS, RX_DR)
@@ -198,9 +216,9 @@ class NRF24L01:
# blocking wait for tx complete
def send(self, buf, timeout=500):
send_nonblock = self.send_start(buf)
- start = pyb.millis()
+ start = utime.ticks_ms()
result = None
- while result is None and pyb.elapsed_millis(start) < timeout:
+ while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
result = self.send_done() # 1 == success, 2 == fail
if result == 2:
raise OSError("send failed")
@@ -209,18 +227,18 @@ class NRF24L01:
def send_start(self, buf):
# power up
self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
- pyb.udelay(150)
+ utime.sleep_us(150)
# send the data
self.cs.low()
- self.spi.send(W_TX_PAYLOAD)
- self.spi.send(buf)
+ self.spi.readinto(self.buf, W_TX_PAYLOAD)
+ self.spi.write(buf)
if len(buf) < self.payload_size:
- self.spi.send(b'\x00' * (self.payload_size - len(buf))) # pad out data
+ self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data
self.cs.high()
# enable the chip so it can send the data
self.ce.high()
- pyb.udelay(15) # needs to be >10us
+ utime.sleep_us(15) # needs to be >10us
self.ce.low()
# returns None if send still in progress, 1 for success, 2 for fail
diff --git a/esp8266/Makefile b/esp8266/Makefile
index 5e61fc16d..a3da9d398 100644
--- a/esp8266/Makefile
+++ b/esp8266/Makefile
@@ -25,9 +25,6 @@ ESP_SDK = $(shell $(CC) -print-sysroot)/usr
INC += -I.
INC += -I..
INC += -I../stmhal
-INC += -I../lib/mp-readline
-INC += -I../lib/netutils
-INC += -I../lib/timeutils
INC += -I$(BUILD)
INC += -I$(ESP_SDK)/include
@@ -41,7 +38,7 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
-DLWIP_OPEN_SRC
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
+CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
$(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
LDSCRIPT = esp8266.ld
@@ -108,7 +105,7 @@ LIB_SRC_C = $(addprefix lib/,\
libc/string0.c \
libm/math.c \
libm/fmodf.c \
- libm/roundf.c \
+ libm/nearbyintf.c \
libm/ef_sqrt.c \
libm/kf_rem_pio2.c \
libm/kf_sin.c \
diff --git a/esp8266/esp8266_common.ld b/esp8266/esp8266_common.ld
index f721c28b0..1da835681 100644
--- a/esp8266/esp8266_common.ld
+++ b/esp8266/esp8266_common.ld
@@ -100,6 +100,7 @@ SECTIONS
*py/qstr.o*(.literal* .text*)
*py/repl.o*(.literal* .text*)
*py/runtime.o*(.literal* .text*)
+ *py/scheduler.o*(.literal* .text*)
*py/scope.o*(.literal* .text*)
*py/sequence.o*(.literal* .text*)
*py/showbc.o*(.literal* .text*)
diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c
index f5e284fde..7ecc7776a 100644
--- a/esp8266/esp_mphal.c
+++ b/esp8266/esp_mphal.c
@@ -33,6 +33,7 @@
#include "ets_alt_task.h"
#include "py/obj.h"
#include "py/mpstate.h"
+#include "py/runtime.h"
#include "extmod/misc.h"
#include "lib/utils/pyexec.h"
@@ -130,11 +131,7 @@ void mp_hal_delay_ms(uint32_t delay) {
void ets_event_poll(void) {
ets_loop_iter();
- 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);
- }
+ mp_handle_pending();
}
void __assert_func(const char *file, int line, const char *func, const char *expr) {
diff --git a/esp8266/fatfs_port.c b/esp8266/fatfs_port.c
index 20c3235d4..02384f605 100644
--- a/esp8266/fatfs_port.c
+++ b/esp8266/fatfs_port.c
@@ -25,8 +25,8 @@
*/
#include "py/obj.h"
+#include "lib/timeutils/timeutils.h"
#include "lib/oofatfs/ff.h"
-#include "timeutils.h"
#include "modmachine.h"
DWORD get_fattime(void) {
diff --git a/esp8266/machine_pin.c b/esp8266/machine_pin.c
index a1e94e898..d4c6d3dea 100644
--- a/esp8266/machine_pin.c
+++ b/esp8266/machine_pin.c
@@ -87,11 +87,15 @@ STATIC uint8_t pin_mode[16 + 1];
// forward declaration
STATIC const pin_irq_obj_t pin_irq_obj[16];
+// whether the irq is hard or soft
+STATIC bool pin_irq_is_hard[16];
+
void pin_init0(void) {
ETS_GPIO_INTR_DISABLE();
ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL);
// disable all interrupts
memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t));
+ memset(pin_irq_is_hard, 0, sizeof(pin_irq_is_hard));
for (int p = 0; p < 16; ++p) {
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p);
SET_TRIGGER(p, 0);
@@ -100,17 +104,23 @@ void pin_init0(void) {
}
void pin_intr_handler(uint32_t status) {
+ mp_sched_lock();
gc_lock();
status &= 0xffff;
for (int p = 0; status; ++p, status >>= 1) {
if (status & 1) {
mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p];
if (handler != MP_OBJ_NULL) {
- mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
+ if (pin_irq_is_hard[p]) {
+ mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
+ } else {
+ mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
+ }
}
}
}
gc_unlock();
+ mp_sched_unlock();
}
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
@@ -342,12 +352,13 @@ STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high);
-// pin.irq(*, trigger, handler=None)
+// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- enum { ARG_trigger, ARG_handler };
+ enum { ARG_handler, ARG_trigger, ARG_hard };
static const mp_arg_t allowed_args[] = {
- { MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} },
+ { MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
};
pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
@@ -357,15 +368,18 @@ STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities"));
}
- if (args[ARG_trigger].u_int != 0) {
+ if (n_args > 1 || kw_args->used != 0) {
// configure irq
mp_obj_t handler = args[ARG_handler].u_obj;
+ uint32_t trigger = args[ARG_trigger].u_int;
if (handler == mp_const_none) {
handler = MP_OBJ_NULL;
+ trigger = 0;
}
ETS_GPIO_INTR_DISABLE();
MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler;
- SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int);
+ pin_irq_is_hard[self->phys_port] = args[ARG_hard].u_bool;
+ SET_TRIGGER(self->phys_port, trigger);
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port);
ETS_GPIO_INTR_ENABLE();
}
diff --git a/esp8266/machine_rtc.c b/esp8266/machine_rtc.c
index 8c1fe0779..019b705ba 100644
--- a/esp8266/machine_rtc.c
+++ b/esp8266/machine_rtc.c
@@ -30,7 +30,7 @@
#include "py/nlr.h"
#include "py/obj.h"
#include "py/runtime.h"
-#include "timeutils.h"
+#include "lib/timeutils/timeutils.h"
#include "user_interface.h"
#include "modmachine.h"
diff --git a/esp8266/modesp.c b/esp8266/modesp.c
index b7ce122b1..432fd5ac3 100644
--- a/esp8266/modesp.c
+++ b/esp8266/modesp.c
@@ -25,492 +25,19 @@
*/
#include <stdio.h>
-#include <string.h>
-#include <stdbool.h>
-#include "py/nlr.h"
-#include "py/obj.h"
#include "py/gc.h"
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "drivers/dht/dht.h"
-#include "netutils.h"
-#include "queue.h"
-#include "ets_sys.h"
#include "uart.h"
#include "user_interface.h"
-#include "espconn.h"
-#include "spi_flash.h"
#include "mem.h"
#include "espneopixel.h"
#include "espapa102.h"
#include "modmachine.h"
-#define MODESP_ESPCONN (0)
-
-#if MODESP_ESPCONN
-STATIC const mp_obj_type_t esp_socket_type;
-
-typedef struct _esp_socket_obj_t {
- mp_obj_base_t base;
- struct espconn *espconn;
-
- mp_obj_t cb_connect;
- mp_obj_t cb_recv;
- mp_obj_t cb_sent;
- mp_obj_t cb_disconnect;
-
- uint8_t *recvbuf;
- mp_uint_t recvbuf_len;
-
- bool fromserver;
-
- mp_obj_list_t *connlist;
-} esp_socket_obj_t;
-
-// Due to the onconnect callback not being able to recognize the parent esp_socket,
-// we can have only one esp_socket listening at a time
-// This should be solvable by some PIC hacking
-STATIC esp_socket_obj_t *esp_socket_listening;
-
-STATIC mp_obj_t esp_socket_make_new_base() {
- esp_socket_obj_t *s = m_new_obj_with_finaliser(esp_socket_obj_t);
- s->recvbuf = NULL;
- s->base.type = (mp_obj_t)&esp_socket_type;
- s->cb_connect = mp_const_none;
- s->cb_recv = mp_const_none;
- s->cb_disconnect = mp_const_none;
- s->cb_sent = mp_const_none;
- s->fromserver = false;
- s->connlist = NULL;
- return s;
-}
-
-// constructor esp_socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
-// Arguments ignored as we do not support UDP (yet)
-STATIC mp_obj_t esp_socket_make_new(const mp_obj_type_t *type_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, 4, false);
-
- esp_socket_obj_t *s = esp_socket_make_new_base();
- s->espconn = m_new_obj(struct espconn);
-
- s->espconn->reverse = s;
- // TODO: UDP Support
- s->espconn->type = ESPCONN_TCP;
- s->espconn->state = ESPCONN_NONE;
-
- s->espconn->proto.tcp = m_new_obj(esp_tcp);
-
- return s;
-}
-
-// method socket.close()
-STATIC mp_obj_t esp_socket_close(mp_obj_t self_in) {
- esp_socket_obj_t *s = self_in;
-
- if (esp_socket_listening == s) {
- esp_socket_listening = NULL;
- }
-
- if (s->espconn->state != ESPCONN_NONE && s->espconn->state != ESPCONN_CLOSE) {
- espconn_disconnect(s->espconn);
- }
-
- if (s->connlist != NULL) {
- mp_obj_list_set_len(s->connlist, 0);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_close_obj, esp_socket_close);
-
-// method socket.__del__()
-STATIC mp_obj_t esp_socket___del__(mp_obj_t self_in) {
- esp_socket_obj_t *s = self_in;
-
- esp_socket_close(self_in);
-
- if (s->fromserver) {
- espconn_delete(s->espconn);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket___del___obj, esp_socket___del__);
-
-// method socket.bind(address)
-STATIC mp_obj_t esp_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
- esp_socket_obj_t *s = self_in;
-
- mp_uint_t port = netutils_parse_inet_addr(addr_in,
- s->espconn->proto.tcp->remote_ip, NETUTILS_BIG);
- s->espconn->proto.tcp->local_port = port;
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_bind_obj, esp_socket_bind);
-
-STATIC void esp_socket_recv_callback(void *arg, char *pdata, unsigned short len) {
- struct espconn *conn = arg;
- esp_socket_obj_t *s = conn->reverse;
-
- if (s->cb_recv != mp_const_none) {
- call_function_2_protected(s->cb_recv, s, mp_obj_new_bytes((byte *)pdata, len));
- } else {
- if (s->recvbuf == NULL) {
- s->recvbuf = m_new(uint8_t, len);
- s->recvbuf_len = len;
- if (s->recvbuf != NULL) {
- memcpy(s->recvbuf, pdata, len);
- }
- } else {
- s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len + len);
- if (s->recvbuf != NULL) {
- memcpy(&s->recvbuf[s->recvbuf_len], pdata, len);
- s->recvbuf_len += len;
- }
- }
- if (s->recvbuf == NULL) {
- esp_socket_close(s);
- return;
- }
- }
-}
-
-STATIC void esp_socket_sent_callback(void *arg) {
- struct espconn *conn = arg;
- esp_socket_obj_t *s = conn->reverse;
-
- if (s->cb_sent != mp_const_none) {
- call_function_1_protected(s->cb_sent, s);
- }
-}
-
-STATIC void esp_socket_disconnect_callback(void *arg) {
- struct espconn *conn = arg;
- esp_socket_obj_t *s = conn->reverse;
-
- if (s->cb_disconnect != mp_const_none) {
- call_function_1_protected(s->cb_disconnect, s);
- }
-
- esp_socket_close(s);
-}
-
-STATIC void esp_socket_connect_callback_server(void *arg) {
- struct espconn *conn = arg;
-
- esp_socket_obj_t *s = esp_socket_make_new_base();
- s->espconn = conn;
- s->fromserver = true;
- conn->reverse = s;
-
- espconn_regist_recvcb(conn, esp_socket_recv_callback);
- espconn_regist_sentcb(conn, esp_socket_sent_callback);
- espconn_regist_disconcb(conn, esp_socket_disconnect_callback);
- espconn_regist_time(conn, 15, 0);
-
- if (esp_socket_listening->cb_connect != mp_const_none) {
- call_function_1_protected(esp_socket_listening->cb_connect, s);
- } else {
- mp_obj_list_append(esp_socket_listening->connlist, s);
- }
-}
-
-STATIC void esp_socket_connect_callback_client(void *arg) {
- struct espconn *conn = arg;
- esp_socket_obj_t *s = conn->reverse;
-
- if (s->cb_connect != mp_const_none) {
- call_function_1_protected(s->cb_connect, s);
- }
-}
-
-// method socket.listen(backlog)
-STATIC mp_obj_t esp_socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
- esp_socket_obj_t *s = self_in;
-
- if (esp_socket_listening != NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "only one espconn can listen at a time"));
- }
-
- esp_socket_listening = s;
-
- s->connlist = mp_obj_new_list(0, NULL);
-
- espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_server);
- espconn_accept(s->espconn);
- espconn_regist_time(s->espconn, 1500, 0);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_listen_obj, esp_socket_listen);
-
-// method socket.accept()
-STATIC mp_obj_t esp_socket_accept(mp_obj_t self_in) {
- esp_socket_obj_t *s = self_in;
-
- if (s->connlist == NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "not listening"));
- }
-
- do {
- mp_uint_t len;
- mp_obj_t *items;
-
- mp_obj_list_get(s->connlist, &len, &items);
- if (len == 0) {
- break;
- }
-
- esp_socket_obj_t *rs = items[0];
- mp_obj_list_remove(s->connlist, rs);
- if (rs->espconn->state != ESPCONN_CLOSE) {
- return rs;
- }
- } while (true);
-
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "no connection in queue"));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_accept_obj, esp_socket_accept);
-
-// method socket.connect(address)
-STATIC mp_obj_t esp_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
- esp_socket_obj_t *s = self_in;
-
- if (s->espconn == NULL || s->espconn->state != ESPCONN_NONE) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "transport endpoint is already connected or closed"));
- }
-
- espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_client);
- espconn_regist_recvcb(s->espconn, esp_socket_recv_callback);
- espconn_regist_sentcb(s->espconn, esp_socket_sent_callback);
- espconn_regist_disconcb(s->espconn, esp_socket_disconnect_callback);
-
- s->espconn->proto.tcp->remote_port =
- netutils_parse_inet_addr(addr_in, s->espconn->proto.tcp->remote_ip,
- NETUTILS_BIG);
- espconn_connect(s->espconn);
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_connect_obj, esp_socket_connect);
-
-// method socket.send(bytes)
-STATIC mp_obj_t esp_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
- esp_socket_obj_t *s = self_in;
-
- if (s->espconn->state == ESPCONN_NONE || s->espconn->state == ESPCONN_CLOSE) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "not connected"));
- }
-
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
-
- espconn_sent(s->espconn, bufinfo.buf, bufinfo.len);
-
- return mp_obj_new_int(bufinfo.len);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_send_obj, esp_socket_send);
-
-// method socket.recv(bufsize)
-STATIC mp_obj_t esp_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
- esp_socket_obj_t *s = self_in;
-
- if (s->recvbuf == NULL) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "no data available"));
- }
-
- mp_uint_t mxl = mp_obj_get_int(len_in);
- if (mxl >= s->recvbuf_len) {
- mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, s->recvbuf_len);
- m_del(uint8_t, s->recvbuf, s->recvbuf_len);
- s->recvbuf = NULL;
- return trt;
- } else {
- mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, mxl);
- memmove(s->recvbuf, &s->recvbuf[mxl], s->recvbuf_len - mxl);
- s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len - mxl);
- s->recvbuf_len -= mxl;
- return trt;
- }
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recv_obj, esp_socket_recv);
-
-// method socket.sendto(bytes, address)
-STATIC mp_obj_t esp_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_socket_sendto_obj, esp_socket_sendto);
-
-// method socket.recvfrom(bufsize)
-STATIC mp_obj_t esp_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recvfrom_obj, esp_socket_recvfrom);
-
-// method socket.getpeername()
-STATIC mp_obj_t esp_socket_getpeername(mp_obj_t self_in) {
- esp_socket_obj_t *s = self_in;
-
- if (s->espconn->state == ESPCONN_NONE) {
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
- "not connected"));
- }
-
- mp_obj_t tuple[2] = {
- netutils_format_ipv4_addr(s->espconn->proto.tcp->remote_ip, NETUTILS_BIG),
- mp_obj_new_int(s->espconn->proto.tcp->remote_port),
- };
-
- return mp_obj_new_tuple(2, tuple);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_getpeername_obj, esp_socket_getpeername);
-
-STATIC mp_obj_t esp_socket_onconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
- esp_socket_obj_t *s = self_in;
- s->cb_connect = lambda_in;
-
- if (s->connlist != NULL) {
- do {
- mp_uint_t len;
- mp_obj_t *items;
-
- mp_obj_list_get(s->connlist, &len, &items);
- if (len == 0) {
- break;
- }
-
- esp_socket_obj_t *rs = items[0];
- mp_obj_list_remove(s->connlist, rs);
- if (s->espconn->state != ESPCONN_CLOSE) {
- call_function_1_protected(s->cb_connect, rs);
- }
- } while (true);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onconnect_obj, esp_socket_onconnect);
-
-STATIC mp_obj_t esp_socket_onrecv(mp_obj_t self_in, mp_obj_t lambda_in) {
- esp_socket_obj_t *s = self_in;
- s->cb_recv = lambda_in;
- if (s->recvbuf != NULL) {
- call_function_2_protected(s->cb_recv, s,
- mp_obj_new_bytes((byte *)s->recvbuf, s->recvbuf_len));
- s->recvbuf = NULL;
- }
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onrecv_obj, esp_socket_onrecv);
-
-STATIC mp_obj_t esp_socket_onsent(mp_obj_t self_in, mp_obj_t lambda_in) {
- esp_socket_obj_t *s = self_in;
- s->cb_sent = lambda_in;
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onsent_obj, esp_socket_onsent);
-
-STATIC mp_obj_t esp_socket_ondisconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
- esp_socket_obj_t *s = self_in;
- s->cb_disconnect = lambda_in;
-
- if (s->espconn->state == ESPCONN_CLOSE) {
- call_function_1_protected(s->cb_disconnect, s);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_ondisconnect_obj, esp_socket_ondisconnect);
-
-typedef struct _esp_getaddrinfo_cb_struct_t {
- mp_obj_t lambda;
- mp_uint_t port;
-} esp_getaddrinfo_cb_struct_t;
-
-STATIC esp_getaddrinfo_cb_struct_t esp_getaddrinfo_cb_struct;
-
-STATIC void esp_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
- mp_obj_t namestr = mp_obj_new_str(name, strlen(name), true);
- if (ipaddr != NULL) {
- uint8_t ip[4];
- ip[0] = (ipaddr->addr >> 24) & 0xff;
- ip[1] = (ipaddr->addr >> 16) & 0xff;
- ip[2] = (ipaddr->addr >> 8) & 0xff;
- ip[3] = (ipaddr->addr >> 0) & 0xff;
-
- mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
-
- tuple->items[0] = MP_OBJ_NEW_SMALL_INT(0);
- tuple->items[1] = MP_OBJ_NEW_SMALL_INT(0);
- tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
- tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
- tuple->items[4] = netutils_format_inet_addr(ip,
- esp_getaddrinfo_cb_struct.port, NETUTILS_LITTLE);
- call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, tuple);
- } else {
- call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, mp_const_none);
- }
-}
-
-STATIC mp_obj_t esp_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in,
- mp_obj_t lambda_in) {
- mp_uint_t hlen;
- const char *host = mp_obj_str_get_data(host_in, &hlen);
- ip_addr_t ipaddr;
-
- esp_getaddrinfo_cb_struct.lambda = lambda_in;
- esp_getaddrinfo_cb_struct.port = mp_obj_get_int(port_in);
-
- err_t ret = espconn_gethostbyname(NULL, host, &ipaddr,
- esp_getaddrinfo_cb);
-
- if (ret == ESPCONN_OK) {
- esp_getaddrinfo_cb(host, &ipaddr, NULL);
- }
-
- return mp_const_none;
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_getaddrinfo_obj, esp_getaddrinfo);
-
-STATIC const mp_map_elem_t esp_socket_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&esp_socket___del___obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&esp_socket_close_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&esp_socket_bind_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&esp_socket_listen_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&esp_socket_accept_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_socket_connect_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&esp_socket_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&esp_socket_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&esp_socket_sendto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&esp_socket_recvfrom_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_getpeername), (mp_obj_t)&esp_socket_getpeername_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_onconnect), (mp_obj_t)&esp_socket_onconnect_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_onrecv), (mp_obj_t)&esp_socket_onrecv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_onsent), (mp_obj_t)&esp_socket_onsent_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ondisconnect), (mp_obj_t)&esp_socket_ondisconnect_obj },
-};
-STATIC MP_DEFINE_CONST_DICT(esp_socket_locals_dict, esp_socket_locals_dict_table);
-
-STATIC const mp_obj_type_t esp_socket_type = {
- { &mp_type_type },
- .name = MP_QSTR_socket,
- .make_new = esp_socket_make_new,
- .locals_dict = (mp_obj_t)&esp_socket_locals_dict,
-};
-#endif
-
#define MODESP_INCLUDE_CONSTANTS (1)
void error_check(bool status, const char *msg) {
@@ -834,10 +361,6 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_size), (mp_obj_t)&esp_flash_size_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_user_start), (mp_obj_t)&esp_flash_user_start_obj },
- #if MODESP_ESPCONN
- { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
- #endif
#if MICROPY_ESP8266_NEOPIXEL
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
#endif
diff --git a/esp8266/modmachine.c b/esp8266/modmachine.c
index 222ed004d..c26c63396 100644
--- a/esp8266/modmachine.c
+++ b/esp8266/modmachine.c
@@ -157,7 +157,7 @@ STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
STATIC void esp_timer_cb(void *arg) {
esp_timer_obj_t *self = arg;
- mp_call_function_1_protected(self->callback, self);
+ mp_sched_schedule(self->callback, self);
}
STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
diff --git a/esp8266/modnetwork.c b/esp8266/modnetwork.c
index 1d8a02bc9..627655b36 100644
--- a/esp8266/modnetwork.c
+++ b/esp8266/modnetwork.c
@@ -32,7 +32,7 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mphal.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "queue.h"
#include "user_interface.h"
#include "espconn.h"
@@ -97,7 +97,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
require_if(args[0], STATION_IF);
struct station_config config = {{0}};
- mp_uint_t len;
+ size_t len;
const char *p;
if (n_args > 1) {
@@ -311,7 +311,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
}
case QS(MP_QSTR_essid): {
req_if = SOFTAP_IF;
- mp_uint_t len;
+ size_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.ssid));
memcpy(cfg.ap.ssid, s, len);
@@ -330,7 +330,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
}
case QS(MP_QSTR_password): {
req_if = SOFTAP_IF;
- mp_uint_t len;
+ size_t len;
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
len = MIN(len, sizeof(cfg.ap.password) - 1);
memcpy(cfg.ap.password, s, len);
diff --git a/esp8266/modutime.c b/esp8266/modutime.c
index 2adb6c563..bdeb3bb45 100644
--- a/esp8266/modutime.c
+++ b/esp8266/modutime.c
@@ -34,8 +34,8 @@
#include "py/runtime.h"
#include "py/mphal.h"
#include "py/smallint.h"
+#include "lib/timeutils/timeutils.h"
#include "modmachine.h"
-#include "timeutils.h"
#include "user_interface.h"
#include "extmod/utime_mphal.h"
@@ -84,7 +84,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
/// which expresses a time as per localtime. It returns an integer which is
/// the number of seconds since Jan 1, 2000.
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- mp_uint_t len;
+ size_t len;
mp_obj_t *elem;
mp_obj_get_array(tuple, &len, &elem);
diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h
index cf4cbecd4..b25bb8bb4 100644
--- a/esp8266/mpconfigport.h
+++ b/esp8266/mpconfigport.h
@@ -28,6 +28,7 @@
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
+#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_COMPLEX (0)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
@@ -117,8 +118,6 @@
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p)))
#define MP_SSIZE_MAX (0x7fffffff)
@@ -181,7 +180,6 @@ extern const struct _mp_obj_module_t onewire_module;
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[8]; \
- vstr_t *repl_line; \
mp_obj_t pin_irq_handler[16]; \
// We need to provide a declaration/definition of alloca()
diff --git a/examples/embedding/Makefile.upylib b/examples/embedding/Makefile.upylib
index d8dbade3f..873c0fd34 100644
--- a/examples/embedding/Makefile.upylib
+++ b/examples/embedding/Makefile.upylib
@@ -14,13 +14,12 @@ INC += -I.
INC += -I..
INC += -I$(MPTOP)
INC += -I$(MPTOP)/unix
-#INC += -I../lib/timeutils
INC += -I$(BUILD)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wpointer-arith -Wuninitialized
-CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
+CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
# Debugging/Optimization
ifdef DEBUG
diff --git a/examples/embedding/mpconfigport_minimal.h b/examples/embedding/mpconfigport_minimal.h
index 48d200858..d16827fa3 100644
--- a/examples/embedding/mpconfigport_minimal.h
+++ b/examples/embedding/mpconfigport_minimal.h
@@ -119,8 +119,6 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
diff --git a/extmod/modbtree.c b/extmod/modbtree.c
index 27f700eea..127dd71a3 100644
--- a/extmod/modbtree.c
+++ b/extmod/modbtree.c
@@ -97,12 +97,8 @@ STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
- // Different ports may have different type sizes
- mp_uint_t v;
- key.data = (void*)mp_obj_str_get_data(args[1], &v);
- key.size = v;
- val.data = (void*)mp_obj_str_get_data(args[2], &v);
- val.size = v;
+ key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
+ val.data = (void*)mp_obj_str_get_data(args[2], &val.size);
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
@@ -110,10 +106,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
DBT key, val;
- // Different ports may have different type sizes
- mp_uint_t v;
- key.data = (void*)mp_obj_str_get_data(args[1], &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
if (n_args > 2) {
@@ -132,10 +125,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
DBT key, val;
if (n_args > 2) {
- // Different ports may have different type sizes
- mp_uint_t v;
- key.data = (void*)mp_obj_str_get_data(args[2], &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(args[2], &key.size);
}
int res = __bt_seq(self->db, &key, &val, flags);
@@ -206,14 +196,11 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
DBT key, val;
int res;
- // Different ports may have different type sizes
- mp_uint_t v;
bool desc = self->flags & FLAG_DESC;
if (self->start_key != MP_OBJ_NULL) {
int flags = R_FIRST;
if (self->start_key != mp_const_none) {
- key.data = (void*)mp_obj_str_get_data(self->start_key, &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(self->start_key, &key.size);
flags = R_CURSOR;
} else if (desc) {
flags = R_LAST;
@@ -231,8 +218,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
if (self->end_key != mp_const_none) {
DBT end_key;
- end_key.data = (void*)mp_obj_str_get_data(self->end_key, &v);
- end_key.size = v;
+ end_key.data = (void*)mp_obj_str_get_data(self->end_key, &end_key.size);
BTREE *t = self->db->internal;
int cmp = t->bt_cmp(&key, &end_key);
if (desc) {
@@ -264,13 +250,10 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
- // Different ports may have different type sizes
- mp_uint_t v;
if (value == MP_OBJ_NULL) {
// delete
DBT key;
- key.data = (void*)mp_obj_str_get_data(index, &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(index, &key.size);
int res = __bt_delete(self->db, &key, 0);
if (res == RET_SPECIAL) {
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
@@ -280,8 +263,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
} else if (value == MP_OBJ_SENTINEL) {
// load
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(index, &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(index, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
if (res == RET_SPECIAL) {
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
@@ -291,10 +273,8 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
} else {
// store
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(index, &v);
- key.size = v;
- val.data = (void*)mp_obj_str_get_data(value, &v);
- val.size = v;
+ key.data = (void*)mp_obj_str_get_data(index, &key.size);
+ val.data = (void*)mp_obj_str_get_data(value, &val.size);
int res = __bt_put(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_const_none;
@@ -305,10 +285,8 @@ STATIC mp_obj_t btree_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
switch (op) {
case MP_BINARY_OP_IN: {
- mp_uint_t v;
DBT key, val;
- key.data = (void*)mp_obj_str_get_data(rhs_in, &v);
- key.size = v;
+ key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size);
int res = __bt_get(self->db, &key, &val, 0);
CHECK_ERROR(res);
return mp_obj_new_bool(res != RET_SPECIAL);
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index 792a3a7fa..b8e84fe1c 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -53,6 +53,41 @@ typedef struct _mp_framebuf_p_t {
fill_rect_t fill_rect;
} mp_framebuf_p_t;
+// constants for formats
+#define FRAMEBUF_MVLSB (0)
+#define FRAMEBUF_RGB565 (1)
+#define FRAMEBUF_GS4_HMSB (2)
+#define FRAMEBUF_MHLSB (3)
+#define FRAMEBUF_MHMSB (4)
+
+// Functions for MHLSB and MHMSB
+
+STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
+ size_t index = (x + y * fb->stride) >> 3;
+ int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
+ ((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((color != 0) << offset);
+}
+
+STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
+ size_t index = (x + y * fb->stride) >> 3;
+ int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
+ return (((uint8_t*)fb->buf)[index] >> (offset)) & 0x01;
+}
+
+STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
+ int reverse = fb->format == FRAMEBUF_MHMSB;
+ int advance = fb->stride >> 3;
+ while (w--) {
+ uint8_t *b = &((uint8_t*)fb->buf)[(x >> 3) + y * advance];
+ int offset = reverse ? x & 7 : 7 - (x & 7);
+ for (int hh = h; hh; --hh) {
+ *b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
+ b += advance;
+ }
+ ++x;
+ }
+}
+
// Functions for MVLSB format
STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
@@ -148,15 +183,12 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w,
}
}
-// constants for formats
-#define FRAMEBUF_MVLSB (0)
-#define FRAMEBUF_RGB565 (1)
-#define FRAMEBUF_GS4_HMSB (2)
-
STATIC mp_framebuf_p_t formats[] = {
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
+ [FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
+ [FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
};
static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
@@ -207,6 +239,10 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
case FRAMEBUF_RGB565:
case FRAMEBUF_GS4_HMSB:
break;
+ case FRAMEBUF_MHLSB:
+ case FRAMEBUF_MHMSB:
+ o->stride = (o->stride + 7) & ~7;
+ break;
default:
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"invalid format"));
@@ -543,8 +579,11 @@ STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) },
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB) },
+ { MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB) },
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565) },
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB) },
+ { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB) },
+ { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 5b03d7c29..fffabb98a 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -36,7 +36,7 @@
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "lwip/init.h"
#include "lwip/timers.h"
@@ -1264,8 +1264,7 @@ STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg)
// lwip.getaddrinfo
STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
- mp_uint_t hlen;
- const char *host = mp_obj_str_get_data(host_in, &hlen);
+ const char *host = mp_obj_str_get_str(host_in);
mp_int_t port = mp_obj_get_int(port_in);
getaddrinfo_state_t state;
diff --git a/extmod/modujson.c b/extmod/modujson.c
index ca4e6df10..bb2d45274 100644
--- a/extmod/modujson.c
+++ b/extmod/modujson.c
@@ -274,7 +274,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
- mp_uint_t len;
+ size_t len;
const char *buf = mp_obj_str_get_data(obj, &len);
vstr_t vstr = {len, len, (char*)buf, true};
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0};
diff --git a/extmod/modure.c b/extmod/modure.c
index b8c242429..7be091cc0 100644
--- a/extmod/modure.c
+++ b/extmod/modure.c
@@ -96,7 +96,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
(void)n_args;
mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
Subject subj;
- mp_uint_t len;
+ size_t len;
subj.begin = mp_obj_str_get_data(args[1], &len);
subj.end = subj.begin + len;
int caps_num = (self->re.sub + 1) * 2;
@@ -128,7 +128,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
Subject subj;
- mp_uint_t len;
+ size_t len;
subj.begin = mp_obj_str_get_data(args[1], &len);
subj.end = subj.begin + len;
int caps_num = (self->re.sub + 1) * 2;
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 5b00f6bad..46dbe42e1 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -113,7 +113,7 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) {
/// \function select(rlist, wlist, xlist[, timeout])
STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) {
// get array data from tuple/list arguments
- mp_uint_t rwx_len[3];
+ size_t rwx_len[3];
mp_obj_t *r_array, *w_array, *x_array;
mp_obj_get_array(args[0], &rwx_len[0], &r_array);
mp_obj_get_array(args[1], &rwx_len[1], &w_array);
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
index a7b8a1440..40dd8c049 100644
--- a/extmod/modussl_mbedtls.c
+++ b/extmod/modussl_mbedtls.c
@@ -156,13 +156,13 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
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;
+ size_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;
+ size_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);
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
index 1d7425bd7..a19b3fda9 100644
--- a/extmod/modutimeq.c
+++ b/extmod/modutimeq.c
@@ -166,6 +166,17 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop);
+STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) {
+ mp_obj_utimeq_t *heap = get_heap(heap_in);
+ if (heap->len == 0) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
+ }
+
+ struct qentry *item = &heap->items[0];
+ return MP_OBJ_NEW_SMALL_INT(item->time);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime);
+
#if DEBUG
STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) {
mp_obj_utimeq_t *heap = get_heap(heap_in);
@@ -190,6 +201,7 @@ STATIC mp_obj_t utimeq_unary_op(mp_uint_t op, mp_obj_t self_in) {
STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) },
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) },
+ { MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_utimeq_peektime_obj) },
#if DEBUG
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) },
#endif
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index 8e0580966..ce3c7dcbd 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -308,7 +308,7 @@ STATIC mp_obj_t webrepl_close(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
- mp_uint_t len;
+ size_t len;
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
if (len > sizeof(webrepl_passwd) - 1) {
mp_raise_ValueError("");
diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c
index f447b3a68..e99ba46ce 100644
--- a/extmod/utime_mphal.c
+++ b/extmod/utime_mphal.c
@@ -37,13 +37,11 @@
#include "extmod/utime_mphal.h"
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
- MP_THREAD_GIL_EXIT();
#if MICROPY_PY_BUILTINS_FLOAT
mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o));
#else
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
#endif
- MP_THREAD_GIL_ENTER();
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
@@ -51,9 +49,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
mp_int_t ms = mp_obj_get_int(arg);
if (ms > 0) {
- MP_THREAD_GIL_EXIT();
mp_hal_delay_ms(ms);
- MP_THREAD_GIL_ENTER();
}
return mp_const_none;
}
@@ -62,9 +58,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
mp_int_t us = mp_obj_get_int(arg);
if (us > 0) {
- MP_THREAD_GIL_EXIT();
mp_hal_delay_us(us);
- MP_THREAD_GIL_ENTER();
}
return mp_const_none;
}
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 3ab8261dd..e389ab324 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -134,7 +134,7 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get the mount point
- mp_uint_t mnt_len;
+ size_t mnt_len;
const char *mnt_str = mp_obj_str_get_data(pos_args[1], &mnt_len);
// see if we need to auto-detect and create the filesystem
@@ -180,7 +180,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj, 2, mp_vfs_mount);
mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) {
// remove vfs from the mount table
mp_vfs_mount_t *vfs = NULL;
- mp_uint_t mnt_len;
+ size_t mnt_len;
const char *mnt_str = NULL;
if (MP_OBJ_IS_STR(mnt_in)) {
mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len);
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 8cd5a4674..dee4f9298 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -268,7 +268,7 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * SECSIZE(fatfs)); // f_bsize
t->items[1] = t->items[0]; // f_frsize
- t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks
+ t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2)); // f_blocks
t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree
t->items[4] = t->items[3]; // f_bavail
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files
diff --git a/lib/libm/nearbyintf.c b/lib/libm/nearbyintf.c
new file mode 100644
index 000000000..1c3545945
--- /dev/null
+++ b/lib/libm/nearbyintf.c
@@ -0,0 +1,21 @@
+// adapted from the rintf() function from musl-1.1.16
+
+#include "libm.h"
+
+float nearbyintf(float x)
+{
+ union {float f; uint32_t i;} u = {x};
+ int e = u.i>>23 & 0xff;
+ int s = u.i>>31;
+ float_t y;
+
+ if (e >= 0x7f+23)
+ return x;
+ if (s)
+ y = x - 0x1p23f + 0x1p23f;
+ else
+ y = x + 0x1p23f - 0x1p23f;
+ if (y == 0)
+ return s ? -0.0f : 0.0f;
+ return y;
+}
diff --git a/lib/mp-readline/readline.c b/lib/mp-readline/readline.c
index cbb99cc94..4b9875136 100644
--- a/lib/mp-readline/readline.c
+++ b/lib/mp-readline/readline.c
@@ -31,7 +31,7 @@
#include "py/mpstate.h"
#include "py/repl.h"
#include "py/mphal.h"
-#include "readline.h"
+#include "lib/mp-readline/readline.h"
#if 0 // print debugging info
#define DEBUG_PRINT (1)
diff --git a/lib/netutils/netutils.c b/lib/netutils/netutils.c
index b896cf0c8..f6718bf3e 100644
--- a/lib/netutils/netutils.c
+++ b/lib/netutils/netutils.c
@@ -33,7 +33,7 @@
#include "py/obj.h"
#include "py/nlr.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
// Takes an array with a raw IPv4 address and returns something like '192.168.0.1'.
mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) {
@@ -58,7 +58,7 @@ mp_obj_t netutils_format_inet_addr(uint8_t *ip, mp_uint_t port, netutils_endian_
}
void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
- mp_uint_t addr_len;
+ size_t addr_len;
const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
if (addr_len == 0) {
// special case of no address given
diff --git a/lib/timeutils/timeutils.c b/lib/timeutils/timeutils.c
index 19d3ddbdd..0af39a295 100644
--- a/lib/timeutils/timeutils.c
+++ b/lib/timeutils/timeutils.c
@@ -27,7 +27,7 @@
#include "py/obj.h"
-#include "timeutils.h"
+#include "lib/timeutils/timeutils.h"
// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately
// after Feb 29. We calculate seconds as a signed integer relative to that.
diff --git a/lib/utils/interrupt_char.c b/lib/utils/interrupt_char.c
index ab4efd911..344db88c7 100644
--- a/lib/utils/interrupt_char.c
+++ b/lib/utils/interrupt_char.c
@@ -46,4 +46,9 @@ void mp_keyboard_interrupt(void) {
#else
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
#endif
+ #if MICROPY_ENABLE_SCHEDULER
+ if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
+ MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
+ }
+ #endif
}
diff --git a/minimal/Makefile b/minimal/Makefile
index 411751735..d61515797 100644
--- a/minimal/Makefile
+++ b/minimal/Makefile
@@ -14,7 +14,6 @@ endif
INC += -I.
INC += -I..
-INC += -I../lib/mp-readline
INC += -I../stmhal
INC += -I$(BUILD)
@@ -22,9 +21,9 @@ ifeq ($(CROSS), 1)
DFU = ../tools/dfu.py
PYDFU = ../tools/pydfu.py
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
+CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
else
-CFLAGS = -m32 $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT)
+CFLAGS = -m32 $(INC) -Wall -Werror -std=c99 $(COPT)
endif
#Debugging/Optimization
diff --git a/minimal/main.c b/minimal/main.c
index 496d925e7..5cc88ff66 100644
--- a/minimal/main.c
+++ b/minimal/main.c
@@ -106,7 +106,7 @@ extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
void Reset_Handler(void) __attribute__((naked));
void Reset_Handler(void) {
// set stack pointer
- asm volatile ("ldr sp, =_estack");
+ __asm volatile ("ldr sp, =_estack");
// copy .data section from flash to RAM
for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) {
*dest++ = *src++;
diff --git a/minimal/mpconfigport.h b/minimal/mpconfigport.h
index e08943860..47fc98429 100644
--- a/minimal/mpconfigport.h
+++ b/minimal/mpconfigport.h
@@ -57,8 +57,6 @@
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
// This port is intended to be 32-bit, but unfortunately, int32_t for
diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile
index 3f9956620..3d5e5da2f 100644
--- a/mpy-cross/Makefile
+++ b/mpy-cross/Makefile
@@ -19,7 +19,7 @@ INC += -I$(BUILD)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wpointer-arith -Wuninitialized
-CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
+CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables
# Debugging/Optimization
diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h
index 0f7651098..383de1439 100644
--- a/mpy-cross/mpconfigport.h
+++ b/mpy-cross/mpconfigport.h
@@ -100,8 +100,6 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
diff --git a/pic16bit/Makefile b/pic16bit/Makefile
index cfe8af86e..8c0c1c999 100644
--- a/pic16bit/Makefile
+++ b/pic16bit/Makefile
@@ -14,14 +14,13 @@ PART = 33FJ256GP506
INC += -I.
INC += -I..
-INC += -I../lib/mp-readline
INC += -I../stmhal
INC += -I$(BUILD)
INC += -I$(XC16)/include
INC += -I$(XC16)/support/$(PARTFAMILY)/h
CFLAGS_PIC16BIT = -mcpu=$(PART) -mlarge-code
-CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
+CFLAGS = $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
#Debugging/Optimization
ifeq ($(DEBUG), 1)
diff --git a/pic16bit/main.c b/pic16bit/main.c
index f2a9debab..7de790069 100644
--- a/pic16bit/main.c
+++ b/pic16bit/main.c
@@ -35,7 +35,7 @@
#include "py/mphal.h"
#include "py/mperrno.h"
#include "lib/utils/pyexec.h"
-#include "readline.h"
+#include "lib/mp-readline/readline.h"
#include "board.h"
#include "modpyb.h"
diff --git a/pic16bit/mpconfigport.h b/pic16bit/mpconfigport.h
index a0371a8ae..e4113956b 100644
--- a/pic16bit/mpconfigport.h
+++ b/pic16bit/mpconfigport.h
@@ -68,7 +68,6 @@
// type definitions for the specific machine
#define MP_ENDIANNESS_LITTLE (1)
-#define BYTES_PER_WORD (2)
#define MPZ_DIG_SIZE (8)
// The xc16 compiler doesn't seem to respect alignment (!!) so we
diff --git a/py/argcheck.c b/py/argcheck.c
index 8cef10b16..9f225345d 100644
--- a/py/argcheck.c
+++ b/py/argcheck.c
@@ -37,7 +37,7 @@ void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_ar
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_arg_error_terse_mismatch();
} else {
- mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments");
+ mp_raise_TypeError("function does not take keyword arguments");
}
}
@@ -115,7 +115,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n
mp_arg_error_terse_mismatch();
} else {
// TODO better error message
- mp_raise_msg(&mp_type_TypeError, "extra positional arguments given");
+ mp_raise_TypeError("extra positional arguments given");
}
}
if (kws_found < kws->used) {
@@ -123,7 +123,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n
mp_arg_error_terse_mismatch();
} else {
// TODO better error message
- mp_raise_msg(&mp_type_TypeError, "extra keyword arguments given");
+ mp_raise_TypeError("extra keyword arguments given");
}
}
}
@@ -136,7 +136,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER
NORETURN void mp_arg_error_terse_mismatch(void) {
- mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch");
+ mp_raise_TypeError("argument num/types mismatch");
}
#endif
diff --git a/py/bc.c b/py/bc.c
index 07de08fc3..4c0eb5391 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -54,6 +54,16 @@ mp_uint_t mp_decode_uint(const byte **ptr) {
return unum;
}
+// This function is used to help reduce stack usage at the caller, for the case when
+// the caller doesn't need to increase the ptr argument. If ptr is a local variable
+// and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler
+// must allocate a slot on the stack for ptr, and this slot cannot be reused for
+// anything else in the function because the pointer may have been stored in a global
+// and reused later in the function.
+mp_uint_t mp_decode_uint_value(const byte *ptr) {
+ return mp_decode_uint(&ptr);
+}
+
STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
// generic message, used also for other argument issues
@@ -86,25 +96,26 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) {
// On entry code_state should be allocated somewhere (stack/heap) and
// contain the following valid entries:
-// - code_state->ip should contain the offset in bytes from the start of
-// the bytecode chunk to just after n_state and n_exc_stack
-// - code_state->n_state should be set to the state size (locals plus stack)
-void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+// - code_state->fun_bc should contain a pointer to the function object
+// - code_state->ip should contain the offset in bytes from the pointer
+// code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native)
+void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
// usage for the common case of positional only args.
- size_t n_state = code_state->n_state;
+
+ // get the function object that we want to set up (could be bytecode or native code)
+ mp_obj_fun_bc_t *self = code_state->fun_bc;
// ip comes in as an offset into bytecode, so turn it into a true pointer
code_state->ip = self->bytecode + (size_t)code_state->ip;
- // store pointer to constant table
- code_state->const_table = self->const_table;
-
#if MICROPY_STACKLESS
code_state->prev = NULL;
#endif
// get params
+ size_t n_state = mp_decode_uint(&code_state->ip);
+ mp_decode_uint(&code_state->ip); // skip n_exc_stack
size_t scope_flags = *code_state->ip++;
size_t n_pos_args = *code_state->ip++;
size_t n_kwonly_args = *code_state->ip++;
@@ -168,7 +179,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz
}
// get pointer to arg_names array
- const mp_obj_t *arg_names = (const mp_obj_t*)code_state->const_table;
+ const mp_obj_t *arg_names = (const mp_obj_t*)self->const_table;
for (size_t i = 0; i < n_kw; i++) {
// the keys in kwargs are expected to be qstr objects
@@ -185,7 +196,12 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz
}
// Didn't find name match with positional args
if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {
- mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments");
+ if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+ mp_raise_TypeError("unexpected keyword argument");
+ } else {
+ nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
+ "unexpected keyword argument '%q'", MP_OBJ_QSTR_VALUE(wanted_arg_name)));
+ }
}
mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
continue2:;
@@ -234,7 +250,7 @@ continue2:;
} else {
// no keyword arguments given
if (n_kwonly_args != 0) {
- mp_raise_msg(&mp_type_TypeError, "function missing keyword-only argument");
+ mp_raise_TypeError("function missing keyword-only argument");
}
if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
*var_pos_kw_args = mp_obj_new_dict(0);
@@ -244,13 +260,8 @@ continue2:;
// get the ip and skip argument names
const byte *ip = code_state->ip;
- // store pointer to code_info and jump over it
- {
- code_state->code_info = ip;
- const byte *ip2 = ip;
- size_t code_info_size = mp_decode_uint(&ip2);
- ip += code_info_size;
- }
+ // jump over code info (source file and line-number mapping)
+ ip += mp_decode_uint_value(ip);
// bytecode prelude: initialise closed over variables
size_t local_num;
diff --git a/py/bc.h b/py/bc.h
index c7dffbac5..e8d428612 100644
--- a/py/bc.h
+++ b/py/bc.h
@@ -28,6 +28,7 @@
#include "py/runtime.h"
#include "py/obj.h"
+#include "py/objfun.h"
// bytecode layout:
//
@@ -70,9 +71,12 @@ typedef struct _mp_exc_stack_t {
} mp_exc_stack_t;
typedef struct _mp_code_state_t {
- const byte *code_info;
+ // The fun_bc entry points to the underlying function object that is being executed.
+ // It is needed to access the start of bytecode and the const_table.
+ // It is also needed to prevent the GC from reclaiming the bytecode during execution,
+ // because the ip pointer below will always point to the interior of the bytecode.
+ mp_obj_fun_bc_t *fun_bc;
const byte *ip;
- const mp_uint_t *const_table;
mp_obj_t *sp;
// bit 0 is saved currently_in_except_block value
mp_exc_stack_t *exc_sp;
@@ -80,7 +84,6 @@ typedef struct _mp_code_state_t {
#if MICROPY_STACKLESS
struct _mp_code_state_t *prev;
#endif
- size_t n_state;
// Variable-length
mp_obj_t state[0];
// Variable-length, never accessed by name, only as (void*)(state + n_state)
@@ -88,11 +91,11 @@ typedef struct _mp_code_state_t {
} mp_code_state_t;
mp_uint_t mp_decode_uint(const byte **ptr);
+mp_uint_t mp_decode_uint_value(const byte *ptr);
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
-struct _mp_obj_fun_bc_t;
-void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
+void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args);
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);
void mp_bytecode_print2(const byte *code, size_t len, const mp_uint_t *const_table);
const byte *mp_bytecode_print_str(const byte *ip);
diff --git a/py/builtinevex.c b/py/builtinevex.c
index b0514ee99..d9a3833cc 100644
--- a/py/builtinevex.c
+++ b/py/builtinevex.c
@@ -78,7 +78,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {
(void)n_args;
// get the source
- mp_uint_t str_len;
+ size_t str_len;
const char *str = mp_obj_str_get_data(args[0], &str_len);
// get the filename
@@ -95,7 +95,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {
case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break;
case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break;
default:
- mp_raise_msg(&mp_type_ValueError, "bad compile mode");
+ mp_raise_ValueError("bad compile mode");
}
mp_obj_code_t *code = m_new_obj(mp_obj_code_t);
@@ -128,7 +128,7 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i
}
#endif
- mp_uint_t str_len;
+ size_t str_len;
const char *str = mp_obj_str_get_data(args[0], &str_len);
// create the lexer
diff --git a/py/builtinimport.c b/py/builtinimport.c
index 96846b963..cf17d5305 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -97,7 +97,7 @@ STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {
#if MICROPY_PY_SYS
// extract the list of paths
- mp_uint_t path_num;
+ size_t path_num;
mp_obj_t *path_items;
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
@@ -111,7 +111,7 @@ STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *d
// go through each path looking for a directory or file
for (mp_uint_t i = 0; i < path_num; i++) {
vstr_reset(dest);
- mp_uint_t p_len;
+ size_t p_len;
const char *p = mp_obj_str_get_data(path_items[i], &p_len);
if (p_len > 0) {
vstr_add_strn(dest, p, p_len);
@@ -265,7 +265,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
}
}
- mp_uint_t mod_len;
+ size_t mod_len;
const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);
if (level != 0) {
@@ -296,7 +296,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
DEBUG_printf("\n");
#endif
- mp_uint_t this_name_l;
+ size_t this_name_l;
const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);
const char *p = this_name + this_name_l;
@@ -341,7 +341,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
if (new_mod_q == MP_QSTR_) {
- mp_raise_msg(&mp_type_ValueError, "cannot perform relative import");
+ mp_raise_ValueError("cannot perform relative import");
}
module_name = MP_OBJ_NEW_QSTR(new_mod_q);
mod_str = new_mod;
diff --git a/py/compile.c b/py/compile.c
index ca21d8294..cf9e5079b 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -456,8 +456,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
break;
}
} else {
- compile_syntax_error(comp, pn, "can't assign to literal");
- return;
+ goto cannot_assign;
}
} else {
// pn must be a struct
@@ -472,7 +471,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
case PN_exprlist:
// lhs is a tuple
if (assign_kind != ASSIGN_STORE) {
- goto bad_aug;
+ goto cannot_assign;
}
c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
break;
@@ -485,7 +484,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
} else {
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
if (assign_kind != ASSIGN_STORE) {
- goto bad_aug;
+ goto cannot_assign;
}
pns = (mp_parse_node_struct_t*)pns->nodes[0];
goto testlist_comp;
@@ -495,7 +494,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
case PN_atom_bracket:
// lhs is something in brackets
if (assign_kind != ASSIGN_STORE) {
- goto bad_aug;
+ goto cannot_assign;
}
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// empty list, assignment allowed
@@ -543,10 +542,6 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
cannot_assign:
compile_syntax_error(comp, pn, "can't assign to expression");
- return;
-
- bad_aug:
- compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
}
// stuff for lambda and comprehensions and generators:
@@ -1449,8 +1444,9 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
pn_range_start = args[0];
pn_range_end = args[1];
pn_range_step = args[2];
- // We need to know sign of step. This is possible only if it's constant
- if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
+ // the step must be a non-zero constant integer to do the optimisation
+ if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)
+ || MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) {
optimize = false;
}
}
@@ -1529,7 +1525,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
// this is a catch all exception handler
if (i + 1 != n_except) {
- compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
+ compile_syntax_error(comp, pn_excepts[i], "default 'except' must be last");
compile_decrease_except_level(comp);
return;
}
@@ -2190,9 +2186,10 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
compile_load_id(comp, MP_QSTR___class__);
// look for first argument to function (assumes it's "self")
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
- if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) {
+ id_info_t *id = &comp->scope_cur->id_info[i];
+ if (id->flags & ID_FLAG_IS_PARAM) {
// first argument found; load it and call super
- EMIT_LOAD_FAST(MP_QSTR_, comp->scope_cur->id_info[i].local_num);
+ compile_load_id(comp, id->qst);
EMIT_ARG(call_function, 2, 0, 0);
return;
}
@@ -2437,13 +2434,21 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
compile_node(comp, pn_i);
if (is_dict) {
if (!is_key_value) {
- compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
+ if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
+ } else {
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dict");
+ }
return;
}
EMIT(store_map);
} else {
if (is_key_value) {
- compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
+ if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
+ } else {
+ compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
+ }
return;
}
}
@@ -3005,6 +3010,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
// There are 4 slots on the stack for the iterator, and the first one is
// NULL to indicate that the second one points to the iterator object.
if (scope->kind == SCOPE_GEN_EXPR) {
+ // TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4
EMIT(load_null);
compile_load_id(comp, qstr_arg);
EMIT(load_null);
diff --git a/py/emitbc.c b/py/emitbc.c
index 0076c147e..673cd405f 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -735,7 +735,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
// need to pop the iterator if we are breaking out of a for loop
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
// also pop the iter_buf
- for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; ++i) {
+ for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) {
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
}
}
@@ -778,7 +778,7 @@ void mp_emit_bc_end_finally(emit_t *emit) {
}
void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
- emit_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1 : 0);
+ emit_bc_pre(emit, use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0);
emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);
}
@@ -788,7 +788,7 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
}
void mp_emit_bc_for_iter_end(emit_t *emit) {
- emit_bc_pre(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
+ emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);
}
void mp_emit_bc_pop_block(emit_t *emit) {
diff --git a/py/emitnative.c b/py/emitnative.c
index 55eb6cadf..3ab001f8d 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -407,43 +407,29 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
#endif
// prepare incoming arguments for call to mp_setup_code_state
+
#if N_X86
- asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_2);
- asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_3);
- asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_4);
- asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_5);
- #else
- #if N_THUMB
- ASM_MOV_REG_REG(emit->as, ASM_THUMB_REG_R4, REG_ARG_4);
- #elif N_ARM
- ASM_MOV_REG_REG(emit->as, ASM_ARM_REG_R4, REG_ARG_4);
- #else
- ASM_MOV_REG_REG(emit->as, REG_ARG_5, REG_ARG_4);
- #endif
- ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_ARG_3);
- ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_ARG_2);
- ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_1);
+ asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1);
+ asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2);
+ asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3);
+ asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4);
#endif
+ // set code_state.fun_bc
+ ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t));
+
// set code_state.ip (offset from start of this function to prelude info)
// XXX this encoding may change size
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1);
-
- // set code_state.n_state
- ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1);
+ ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1);
// put address of code_state into first arg
ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);
// call mp_setup_code_state to prepare code_state structure
#if N_THUMB
- asm_thumb_op16(emit->as, 0xb400 | (1 << ASM_THUMB_REG_R4)); // push 5th arg
asm_thumb_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);
- asm_thumb_op16(emit->as, 0xbc00 | (1 << REG_RET)); // pop dummy (was 5th arg)
#elif N_ARM
- asm_arm_push(emit->as, 1 << ASM_ARM_REG_R4); // push 5th arg
asm_arm_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4);
- asm_arm_pop(emit->as, 1 << REG_RET); // pop dummy (was 5th arg)
#else
ASM_CALL_IND(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE);
#endif
@@ -477,6 +463,9 @@ STATIC void emit_native_end_pass(emit_t *emit) {
if (!emit->do_viper_types) {
emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
+ mp_asm_base_data(&emit->as->base, 1, 0x80 | ((emit->n_state >> 7) & 0x7f));
+ mp_asm_base_data(&emit->as->base, 1, emit->n_state & 0x7f);
+ mp_asm_base_data(&emit->as->base, 1, 0); // n_exc_stack
mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags);
mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args);
mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args);
@@ -1772,7 +1761,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
assert(vtype == VTYPE_PYOBJ);
if (use_stack) {
- emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, MP_OBJ_ITER_BUF_NSLOTS);
emit_call(emit, MP_F_NATIVE_GETITER);
} else {
// mp_getiter will allocate the iter_buf on the heap
@@ -1784,8 +1773,8 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
emit_native_pre(emit);
- emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
- adjust_stack(emit, 4);
+ emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS);
+ adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS);
emit_call(emit, MP_F_NATIVE_ITERNEXT);
ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
@@ -1795,7 +1784,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
STATIC void emit_native_for_iter_end(emit_t *emit) {
// adjust stack counter (we get here from for_iter ending, which popped the value for us)
emit_native_pre(emit);
- adjust_stack(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
+ adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS);
emit_post(emit);
}
diff --git a/py/lexer.c b/py/lexer.c
index fadaee6f3..05651abec 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -159,7 +159,6 @@ STATIC void next_char(mp_lexer_t *lex) {
STATIC void indent_push(mp_lexer_t *lex, size_t indent) {
if (lex->num_indent_level >= lex->alloc_indent_level) {
- // TODO use m_renew_maybe and somehow indicate an error if it fails... probably by using MP_TOKEN_MEMORY_ERROR
lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);
lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC;
}
@@ -177,7 +176,6 @@ STATIC void indent_pop(mp_lexer_t *lex) {
// some tricky operator encoding:
// <op> = begin with <op>, if this opchar matches then begin here
// e<op> = end with <op>, if this opchar matches then end
-// E<op> = mandatory end with <op>, this opchar must match, then end
// c<op> = continue with <op>, if this opchar matches then continue matching
// this means if the start of two ops are the same then they are equal til the last char
@@ -194,7 +192,7 @@ STATIC const char *const tok_enc =
"%e=" // % %=
"^e=" // ^ ^=
"=e=" // = ==
- "!E="; // !=
+ "!."; // start of special cases: != . ...
// TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries
STATIC const uint8_t tok_enc_kind[] = {
@@ -214,7 +212,6 @@ STATIC const uint8_t tok_enc_kind[] = {
MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,
MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
- MP_TOKEN_OP_NOT_EQUAL,
};
// must have the same order as enum in lexer.h
@@ -604,20 +601,6 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
}
}
- } else if (is_char(lex, '.')) {
- // special handling for . and ... operators, because .. is not a valid operator
-
- // get first char
- next_char(lex);
-
- if (is_char_and(lex, '.', '.')) {
- next_char(lex);
- next_char(lex);
- lex->tok_kind = MP_TOKEN_ELLIPSIS;
- } else {
- lex->tok_kind = MP_TOKEN_DEL_PERIOD;
- }
-
} else {
// search for encoded delimiter or operator
@@ -626,9 +609,6 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
for (; *t != 0 && !is_char(lex, *t); t += 1) {
if (*t == 'e' || *t == 'c') {
t += 1;
- } else if (*t == 'E') {
- tok_enc_index -= 1;
- t += 1;
}
tok_enc_index += 1;
}
@@ -639,55 +619,48 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
// didn't match any delimiter or operator characters
lex->tok_kind = MP_TOKEN_INVALID;
+ } else if (*t == '!') {
+ // "!=" is a special case because "!" is not a valid operator
+ if (is_char(lex, '=')) {
+ next_char(lex);
+ lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;
+ } else {
+ lex->tok_kind = MP_TOKEN_INVALID;
+ }
+
+ } else if (*t == '.') {
+ // "." and "..." are special cases because ".." is not a valid operator
+ if (is_char_and(lex, '.', '.')) {
+ next_char(lex);
+ next_char(lex);
+ lex->tok_kind = MP_TOKEN_ELLIPSIS;
+ } else {
+ lex->tok_kind = MP_TOKEN_DEL_PERIOD;
+ }
+
} else {
// matched a delimiter or operator character
// get the maximum characters for a valid token
t += 1;
size_t t_index = tok_enc_index;
- for (;;) {
- for (; *t == 'e'; t += 1) {
- t += 1;
- t_index += 1;
- if (is_char(lex, *t)) {
- next_char(lex);
- tok_enc_index = t_index;
- break;
- }
- }
-
- if (*t == 'E') {
- t += 1;
- if (is_char(lex, *t)) {
- next_char(lex);
- tok_enc_index = t_index;
- } else {
- lex->tok_kind = MP_TOKEN_INVALID;
- goto tok_enc_no_match;
- }
- break;
- }
-
- if (*t == 'c') {
- t += 1;
- t_index += 1;
- if (is_char(lex, *t)) {
- next_char(lex);
- tok_enc_index = t_index;
- t += 1;
- } else {
+ while (*t == 'c' || *t == 'e') {
+ t_index += 1;
+ if (is_char(lex, t[1])) {
+ next_char(lex);
+ tok_enc_index = t_index;
+ if (*t == 'e') {
break;
}
- } else {
+ } else if (*t == 'c') {
break;
}
+ t += 2;
}
// set token kind
lex->tok_kind = tok_enc_kind[tok_enc_index];
- tok_enc_no_match:
-
// compute bracket level for implicit line joining
if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) {
lex->nested_bracket_level += 1;
diff --git a/py/mkrules.mk b/py/mkrules.mk
index bc6389144..2ba57e0ee 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -142,8 +142,15 @@ clean-prog:
endif
LIBMICROPYTHON = libmicropython.a
+
+# We can execute extra commands after library creation using
+# LIBMICROPYTHON_EXTRA_CMD. This may be needed e.g. to integrate
+# with 3rd-party projects which don't have proper dependency
+# tracking. Then LIBMICROPYTHON_EXTRA_CMD can e.g. touch some
+# other file to cause needed effect, e.g. relinking with new lib.
lib $(LIBMICROPYTHON): $(OBJ)
$(AR) rcs $(LIBMICROPYTHON) $^
+ $(LIBMICROPYTHON_EXTRA_CMD)
clean:
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 13312d229..e8119456d 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -180,7 +180,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
str[3] = (c & 0x3F) | 0x80;
len = 4;
} else {
- mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)");
+ mp_raise_ValueError("chr() arg not in range(0x110000)");
}
return mp_obj_new_str(str, len, true);
#else
@@ -189,7 +189,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
char str[1] = {ord};
return mp_obj_new_str(str, 1, true);
} else {
- mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(256)");
+ mp_raise_ValueError("chr() arg not in range(256)");
}
#endif
}
@@ -289,7 +289,7 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t
if (default_elem != NULL) {
best_obj = default_elem->value;
} else {
- mp_raise_msg(&mp_type_ValueError, "arg is an empty sequence");
+ mp_raise_ValueError("arg is an empty sequence");
}
}
return best_obj;
@@ -336,7 +336,7 @@ STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) {
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
- mp_uint_t len;
+ size_t len;
const char *str = mp_obj_str_get_data(o_in, &len);
#if MICROPY_PY_BUILTINS_STR_UNICODE
if (MP_OBJ_IS_STR(o_in)) {
@@ -397,9 +397,9 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *
mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP);
mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP);
const char *sep_data = " ";
- mp_uint_t sep_len = 1;
+ size_t sep_len = 1;
const char *end_data = "\n";
- mp_uint_t end_len = 1;
+ size_t end_len = 1;
if (sep_elem != NULL && sep_elem->value != mp_const_none) {
sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);
}
@@ -473,22 +473,16 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
mp_float_t val = mp_obj_get_float(o_in);
mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig);
// TODO may lead to overflow
- mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val * mult) / mult;
+ mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult;
return mp_obj_new_float(rounded);
}
mp_float_t val = mp_obj_get_float(o_in);
- mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
- mp_int_t r = rounded;
- // make rounded value even if it was halfway between ints
- if (val - rounded == 0.5) {
- r = (r + 1) & (~1);
- } else if (val - rounded == -0.5) {
- r &= ~1;
- }
+ mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val);
+ return mp_obj_new_int_from_float(rounded);
#else
mp_int_t r = mp_obj_get_int(o_in);
-#endif
return mp_obj_new_int(r);
+#endif
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round);
@@ -510,7 +504,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
if (n_args > 1) {
- mp_raise_msg(&mp_type_TypeError, "must use keyword argument for key function");
+ mp_raise_TypeError("must use keyword argument for key function");
}
mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args);
mp_obj_list_sort(1, &self, kwargs);
diff --git a/py/modmath.c b/py/modmath.c
index 7c51eab03..ddab337d0 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -57,7 +57,7 @@ STATIC NORETURN void math_error(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
#define MATH_FUN_1_TO_INT(py_name, c_name) \
- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { mp_int_t x = MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj)); return mp_obj_new_int(x); } \
+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
#define MATH_FUN_1_ERRCOND(py_name, c_name, error_condition) \
diff --git a/py/modmicropython.c b/py/modmicropython.c
index 675d169cc..a74e6aa3c 100644
--- a/py/modmicropython.c
+++ b/py/modmicropython.c
@@ -29,6 +29,7 @@
#include "py/mpstate.h"
#include "py/builtin.h"
#include "py/stackctrl.h"
+#include "py/runtime.h"
#include "py/gc.h"
// Various builtins specific to MicroPython runtime,
@@ -128,6 +129,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf);
#endif
+#if MICROPY_ENABLE_SCHEDULER
+STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) {
+ if (!mp_sched_schedule(function, arg)) {
+ mp_raise_msg(&mp_type_RuntimeError, "schedule stack full");
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule);
+#endif
+
STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) },
{ MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) },
@@ -151,6 +162,9 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },
{ MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },
#endif
+ #if MICROPY_ENABLE_SCHEDULER
+ { MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) },
+ #endif
};
STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table);
diff --git a/py/modthread.c b/py/modthread.c
index dda9e9348..d0e71dad3 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -215,7 +215,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
thread_entry_args_t *th_args;
// get positional arguments
- mp_uint_t pos_args_len;
+ size_t pos_args_len;
mp_obj_t *pos_args_items;
mp_obj_get_array(args[1], &pos_args_len, &pos_args_items);
@@ -227,7 +227,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
} else {
// positional and keyword arguments
if (mp_obj_get_type(args[2]) != &mp_type_dict) {
- mp_raise_msg(&mp_type_TypeError, "expecting a dict for keyword args");
+ mp_raise_TypeError("expecting a dict for keyword args");
}
mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map;
th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used);
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 7e3bd8bdb..06c19f72b 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -556,6 +556,15 @@ typedef double mp_float_t;
#define MICROPY_CPYTHON_COMPAT (1)
#endif
+// Perform full checks as done by CPython. Disabling this
+// may produce incorrect results, if incorrect data is fed,
+// but should not lead to MicroPython crashes or similar
+// grave issues (in other words, only user app should be,
+// affected, not system).
+#ifndef MICROPY_FULL_CHECKS
+#define MICROPY_FULL_CHECKS (1)
+#endif
+
// Whether POSIX-semantics non-blocking streams are supported
#ifndef MICROPY_STREAMS_NON_BLOCK
#define MICROPY_STREAMS_NON_BLOCK (0)
@@ -616,6 +625,16 @@ typedef double mp_float_t;
#define MICROPY_USE_INTERNAL_PRINTF (1)
#endif
+// Support for internal scheduler
+#ifndef MICROPY_ENABLE_SCHEDULER
+#define MICROPY_ENABLE_SCHEDULER (0)
+#endif
+
+// Maximum number of entries in the scheduler
+#ifndef MICROPY_SCHEDULER_DEPTH
+#define MICROPY_SCHEDULER_DEPTH (4)
+#endif
+
// Support for generic VFS sub-system
#ifndef MICROPY_VFS
#define MICROPY_VFS (0)
@@ -1095,6 +1114,11 @@ typedef double mp_float_t;
#define STATIC static
#endif
+// Number of bytes in a word
+#ifndef BYTES_PER_WORD
+#define BYTES_PER_WORD (sizeof(mp_uint_t))
+#endif
+
#define BITS_PER_BYTE (8)
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
// mp_int_t value with most significant bit set
diff --git a/py/mpstate.h b/py/mpstate.h
index 9e4f54ae5..0134dd8e8 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -50,6 +50,16 @@ typedef struct mp_dynamic_compiler_t {
extern mp_dynamic_compiler_t mp_dynamic_compiler;
#endif
+// These are the values for sched_state
+#define MP_SCHED_IDLE (1)
+#define MP_SCHED_LOCKED (-1)
+#define MP_SCHED_PENDING (0) // 0 so it's a quick check in the VM
+
+typedef struct _mp_sched_item_t {
+ mp_obj_t func;
+ mp_obj_t arg;
+} mp_sched_item_t;
+
// This structure hold information about the memory allocation system.
typedef struct _mp_state_mem_t {
#if MICROPY_MEM_STATS
@@ -129,6 +139,12 @@ typedef struct _mp_state_vm_t {
// pending exception object (MP_OBJ_NULL if not pending)
volatile mp_obj_t mp_pending_exception;
+ #if MICROPY_ENABLE_SCHEDULER
+ volatile int16_t sched_state;
+ uint16_t sched_sp;
+ mp_sched_item_t sched_stack[MICROPY_SCHEDULER_DEPTH];
+ #endif
+
// current exception being handled, for sys.exc_info()
#if MICROPY_PY_SYS_EXC_INFO
mp_obj_base_t *cur_exception;
@@ -222,7 +238,6 @@ typedef struct _mp_state_ctx_t {
extern mp_state_ctx_t mp_state_ctx;
-#define MP_STATE_CTX(x) MP_STATE_THREAD(x)
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
diff --git a/py/nlrx86.c b/py/nlrx86.c
index 07ba72628..58aaa1a57 100644
--- a/py/nlrx86.c
+++ b/py/nlrx86.c
@@ -49,10 +49,9 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
__asm volatile (
// Check for Zephyr, which uses a different calling convention
// by default.
- // TODO: Better check for Zephyr.
// TODE: Better support for various x86 calling conventions
// (unfortunately, __attribute__((naked)) is not supported on x86).
- #ifndef CONFIG_SOC_IA32
+ #ifndef __ZEPHYR__
"pop %ebp \n" // undo function's prelude
#endif
"mov 4(%esp), %edx \n" // load nlr_buf
diff --git a/py/obj.c b/py/obj.c
index 4534ef1b2..98ffa930b 100644
--- a/py/obj.c
+++ b/py/obj.c
@@ -229,7 +229,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
return mp_obj_int_get_checked(arg);
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "can't convert to int");
+ mp_raise_TypeError("can't convert to int");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"can't convert %s to int", mp_obj_get_type_str(arg)));
@@ -279,7 +279,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
return mp_obj_float_get(arg);
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "can't convert to float");
+ mp_raise_TypeError("can't convert to float");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"can't convert %s to float", mp_obj_get_type_str(arg)));
@@ -310,7 +310,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
mp_obj_complex_get(arg, real, imag);
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "can't convert to complex");
+ mp_raise_TypeError("can't convert to complex");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"can't convert %s to complex", mp_obj_get_type_str(arg)));
@@ -321,14 +321,14 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
#endif
// note: returned value in *items may point to the interior of a GC block
-void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
+void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) {
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
mp_obj_tuple_get(o, len, items);
} else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) {
mp_obj_list_get(o, len, items);
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "expected tuple/list");
+ mp_raise_TypeError("expected tuple/list");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
@@ -337,12 +337,12 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
}
// note: returned value in *items may point to the interior of a GC block
-void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
- mp_uint_t seq_len;
+void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) {
+ size_t seq_len;
mp_obj_get_array(o, &seq_len, items);
if (seq_len != len) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_ValueError, "tuple/list has wrong length");
+ mp_raise_ValueError("tuple/list has wrong length");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"requested length %d but object has length %d", (int)len, (int)seq_len));
@@ -351,13 +351,13 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
}
// is_slice determines whether the index is a slice index
-mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice) {
+size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) {
mp_int_t i;
if (MP_OBJ_IS_SMALL_INT(index)) {
i = MP_OBJ_SMALL_INT_VALUE(index);
} else if (!mp_obj_get_int_maybe(index, &i)) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "indices must be integers");
+ mp_raise_TypeError("indices must be integers");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"%q indices must be integers, not %s",
@@ -384,7 +384,9 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index,
}
}
}
- return i;
+
+ // By this point 0 <= i <= len and so fits in a size_t
+ return (size_t)i;
}
mp_obj_t mp_obj_id(mp_obj_t o_in) {
@@ -410,7 +412,7 @@ mp_obj_t mp_obj_len(mp_obj_t o_in) {
mp_obj_t len = mp_obj_len_maybe(o_in);
if (len == MP_OBJ_NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object has no len");
+ mp_raise_TypeError("object has no len");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
@@ -451,7 +453,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
}
if (value == MP_OBJ_NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object does not support item deletion");
+ mp_raise_TypeError("object does not support item deletion");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object does not support item deletion", mp_obj_get_type_str(base)));
@@ -466,7 +468,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
}
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object does not support item assignment");
+ mp_raise_TypeError("object does not support item assignment");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object does not support item assignment", mp_obj_get_type_str(base)));
@@ -500,7 +502,7 @@ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
if (!mp_get_buffer(obj, bufinfo, flags)) {
- mp_raise_msg(&mp_type_TypeError, "object with buffer protocol required");
+ mp_raise_TypeError("object with buffer protocol required");
}
}
diff --git a/py/obj.h b/py/obj.h
index 79a6d56fa..49ba645f7 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -422,6 +422,10 @@ typedef struct _mp_obj_iter_buf_t {
mp_obj_t buf[3];
} mp_obj_iter_buf_t;
+// The number of slots that an mp_obj_iter_buf_t needs on the Python value stack.
+// It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D).
+#define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t))
+
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
@@ -672,9 +676,9 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in);
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
#endif
//qstr mp_obj_get_qstr(mp_obj_t arg);
-void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items); // *items may point inside a GC block
-void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items); // *items may point inside a GC block
-mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
+void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block
+void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block
+size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice);
mp_obj_t mp_obj_id(mp_obj_t o_in);
mp_obj_t mp_obj_len(mp_obj_t o_in);
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL
@@ -708,12 +712,13 @@ void mp_init_emergency_exception_buf(void);
bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2);
qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
-const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len);
+const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len);
mp_obj_t mp_obj_str_intern(mp_obj_t str);
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes);
#if MICROPY_PY_BUILTINS_FLOAT
// float
+static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }
mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
// complex
@@ -724,7 +729,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t
#endif
// tuple
-void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items);
+void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);
void mp_obj_tuple_del(mp_obj_t self_in);
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in);
@@ -733,7 +738,7 @@ struct _mp_obj_list_t;
void mp_obj_list_init(struct _mp_obj_list_t *o, size_t n);
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value);
-void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items);
+void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);
void mp_obj_list_set_len(mp_obj_t self_in, size_t len);
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
@@ -819,17 +824,17 @@ typedef struct {
mp_int_t step;
} mp_bound_slice_t;
-void mp_seq_multiply(const void *items, mp_uint_t item_sz, mp_uint_t len, mp_uint_t times, void *dest);
+void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest);
#if MICROPY_PY_BUILTINS_SLICE
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
#endif
#define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
#define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }
-bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, mp_uint_t len1, const byte *data2, mp_uint_t len2);
-bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const mp_obj_t *items2, mp_uint_t len2);
-mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args, const mp_obj_t *args);
-mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value);
-mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
+bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2);
+bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2);
+mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args);
+mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value);
+mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems
#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz))
#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz) \
@@ -838,9 +843,10 @@ mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice
/*printf("memmove(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * (item_sz));*/ \
memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), (dest_len - end) * (item_sz));
+// Note: dest and slice regions may overlap
#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz) \
/*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * (item_sz));*/ \
- memmove(((char*)dest) + (beg + len_adj) * (item_sz), ((char*)dest) + (beg) * (item_sz), (dest_len - beg) * (item_sz)); \
- memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));
+ memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \
+ memmove(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));
#endif // __MICROPY_INCLUDED_PY_OBJ_H__
diff --git a/py/objarray.c b/py/objarray.c
index a84a63151..21479a800 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -162,8 +162,7 @@ STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size
mp_arg_check_num(n_args, n_kw, 1, 2, false);
// get typecode
- mp_uint_t l;
- const char *typecode = mp_obj_str_get_data(args[0], &l);
+ const char *typecode = mp_obj_str_get_str(args[0]);
if (n_args == 1) {
// 1 arg: make an empty array
@@ -392,7 +391,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);
if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
compat_error:
- mp_raise_msg(&mp_type_ValueError, "lhs and rhs should be compatible");
+ mp_raise_ValueError("lhs and rhs should be compatible");
}
src_len = src_slice->len;
src_items = src_slice->items;
@@ -471,7 +470,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
return MP_OBJ_FROM_PTR(res);
#endif
} else {
- mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
+ size_t index = mp_get_index(o->base.type, o->len, index_in, false);
#if MICROPY_PY_BUILTINS_MEMORYVIEW
if (o->base.type == &mp_type_memoryview) {
index += o->free;
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 426e76e5f..7ec47edb5 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -80,7 +80,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si
case 1:
if (MP_OBJ_IS_STR(args[0])) {
// a string, parse it
- mp_uint_t l;
+ size_t l;
const char *s = mp_obj_str_get_data(args[0], &l);
return mp_parse_num_decimal(s, l, true, true, NULL);
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
@@ -117,6 +117,7 @@ STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);
+ case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag));
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);
default: return MP_OBJ_NULL; // op not supported
diff --git a/py/objdict.c b/py/objdict.c
index 013cc0a04..f6929d23f 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -386,7 +386,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
if (key == MP_OBJ_STOP_ITERATION
|| value == MP_OBJ_STOP_ITERATION
|| stop != MP_OBJ_STOP_ITERATION) {
- mp_raise_msg(&mp_type_ValueError, "dictionary update sequence has the wrong length");
+ mp_raise_ValueError("dict update sequence has wrong length");
} else {
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
}
diff --git a/py/objfloat.c b/py/objfloat.c
index 9292490a9..2c355d355 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -89,7 +89,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size
default:
if (MP_OBJ_IS_STR(args[0])) {
// a string, parse it
- mp_uint_t l;
+ size_t l;
const char *s = mp_obj_str_get_data(args[0], &l);
return mp_parse_num_decimal(s, l, false, false, NULL);
} else if (mp_obj_is_float(args[0])) {
@@ -106,6 +106,7 @@ STATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) {
mp_float_t val = mp_obj_float_get(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0);
+ case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val));
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val);
default: return MP_OBJ_NULL; // op not supported
diff --git a/py/objfun.c b/py/objfun.c
index a823f49e5..08d031c8d 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -220,9 +220,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args
return NULL;
}
- code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack
- code_state->n_state = n_state;
- mp_setup_code_state(code_state, self, n_args, n_kw, args);
+ code_state->fun_bc = self;
+ code_state->ip = 0;
+ mp_setup_code_state(code_state, n_args, n_kw, args);
// execute the byte code with the correct globals context
code_state->old_globals = mp_globals_get();
@@ -265,9 +265,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
state_size = 0; // indicate that we allocated using alloca
}
- code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack
- code_state->n_state = n_state;
- mp_setup_code_state(code_state, self, n_args, n_kw, args);
+ code_state->fun_bc = self;
+ code_state->ip = 0;
+ mp_setup_code_state(code_state, n_args, n_kw, args);
// execute the byte code with the correct globals context
code_state->old_globals = mp_globals_get();
@@ -501,7 +501,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
return mp_obj_int_get_truncated(obj);
} else if (MP_OBJ_IS_STR(obj)) {
// pointer to the string (it's probably constant though!)
- mp_uint_t l;
+ size_t l;
return (mp_uint_t)mp_obj_str_get_data(obj, &l);
} else {
mp_obj_type_t *type = mp_obj_get_type(obj);
@@ -513,7 +513,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
#endif
} else if (type == &mp_type_tuple || type == &mp_type_list) {
// pointer to start of tuple (could pass length, but then could use len(x) for that)
- mp_uint_t len;
+ size_t len;
mp_obj_t *items;
mp_obj_get_array(obj, &len, &items);
return (mp_uint_t)items;
diff --git a/py/objgenerator.c b/py/objgenerator.c
index 654b18670..2e57fdf4b 100644
--- a/py/objgenerator.c
+++ b/py/objgenerator.c
@@ -67,9 +67,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
o->base.type = &mp_type_gen_instance;
o->globals = self_fun->globals;
- o->code_state.n_state = n_state;
- o->code_state.ip = (byte*)(ip - self_fun->bytecode); // offset to prelude
- mp_setup_code_state(&o->code_state, self_fun, n_args, n_kw, args);
+ o->code_state.fun_bc = self_fun;
+ o->code_state.ip = 0;
+ mp_setup_code_state(&o->code_state, n_args, n_kw, args);
return MP_OBJ_FROM_PTR(o);
}
@@ -92,7 +92,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
(void)kind;
mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
- mp_printf(print, "<generator object '%q' at %p>", mp_obj_code_get_name(self->code_state.code_info), self);
+ mp_printf(print, "<generator object '%q' at %p>", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self);
}
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
@@ -105,7 +105,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
}
if (self->code_state.sp == self->code_state.state - 1) {
if (send_value != mp_const_none) {
- mp_raise_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator");
+ mp_raise_TypeError("can't send non-None value to a just-started generator");
}
} else {
*self->code_state.sp = send_value;
@@ -134,10 +134,12 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
}
break;
- case MP_VM_RETURN_EXCEPTION:
+ case MP_VM_RETURN_EXCEPTION: {
+ size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode);
self->code_state.ip = 0;
- *ret_val = self->code_state.state[self->code_state.n_state - 1];
+ *ret_val = self->code_state.state[n_state - 1];
break;
+ }
}
return ret_kind;
diff --git a/py/objint.c b/py/objint.c
index 5aa6a95cc..46f9b1666 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -56,7 +56,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
return args[0];
} else if (MP_OBJ_IS_STR_OR_BYTES(args[0])) {
// a string, parse it
- mp_uint_t l;
+ size_t l;
const char *s = mp_obj_str_get_data(args[0], &l);
return mp_parse_num_integer(s, l, 0, NULL);
#if MICROPY_PY_BUILTINS_FLOAT
@@ -72,7 +72,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
default: {
// should be a string, parse it
// TODO proper error checking of argument types
- mp_uint_t l;
+ size_t l;
const char *s = mp_obj_str_get_data(args[0], &l);
return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
}
@@ -80,7 +80,14 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
}
#if MICROPY_PY_BUILTINS_FLOAT
-mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
+
+typedef enum {
+ MP_FP_CLASS_FIT_SMALLINT,
+ MP_FP_CLASS_FIT_LONGINT,
+ MP_FP_CLASS_OVERFLOW
+} mp_fp_as_int_class_t;
+
+STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
union {
mp_float_t f;
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
@@ -103,7 +110,12 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
e |= u.i[MP_ENDIANNESS_BIG] != 0;
#endif
- e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
+ if ((e & ~(1 << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {
+ // handle case of -0 (when sign is set but rest of bits are zero)
+ e = 0;
+ } else {
+ e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
+ }
} else {
e &= ~((1 << MP_FLOAT_EXP_SHIFT_I32) - 1);
}
@@ -125,6 +137,35 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
}
#undef MP_FLOAT_SIGN_SHIFT_I32
#undef MP_FLOAT_EXP_SHIFT_I32
+
+mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
+ int cl = fpclassify(val);
+ if (cl == FP_INFINITE) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "can't convert inf to int"));
+ } else if (cl == FP_NAN) {
+ mp_raise_ValueError("can't convert NaN to int");
+ } else {
+ mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
+ if (icl == MP_FP_CLASS_FIT_SMALLINT) {
+ return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
+ } else {
+ mp_obj_int_t *o = mp_obj_int_new_mpz();
+ mpz_set_from_float(&o->mpz, val);
+ return MP_OBJ_FROM_PTR(o);
+ }
+ #else
+ #if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
+ } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
+ return mp_obj_new_int_from_ll((long long)val);
+ #endif
+ } else {
+ mp_raise_ValueError("float too big");
+ }
+ #endif
+ }
+}
+
#endif
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
@@ -318,24 +359,6 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
return mp_const_none;
}
-#if MICROPY_PY_BUILTINS_FLOAT
-mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- int cl = fpclassify(val);
- if (cl == FP_INFINITE) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
- } else if (cl == FP_NAN) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else {
- mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
- if (icl == MP_FP_CLASS_FIT_SMALLINT) {
- return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
- } else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
- }
- }
-}
-#endif
-
mp_obj_t mp_obj_new_int(mp_int_t value) {
if (MP_SMALL_INT_FITS(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
diff --git a/py/objint.h b/py/objint.h
index 7205761ad..da56c1862 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -41,18 +41,13 @@ typedef struct _mp_obj_int_t {
extern const mp_obj_int_t mp_maxsize_obj;
#if MICROPY_PY_BUILTINS_FLOAT
-typedef enum {
- MP_FP_CLASS_FIT_SMALLINT,
- MP_FP_CLASS_FIT_LONGINT,
- MP_FP_CLASS_OVERFLOW
-} mp_fp_as_int_class_t;
-
-mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val);
mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in);
-#endif // MICROPY_PY_BUILTINS_FLOAT
+#endif
size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma);
+mp_obj_int_t *mp_obj_int_new_mpz(void);
+
void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
int base, const char *prefix, char base_char, char comma);
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 4ab49f337..540cfebd0 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -263,26 +263,6 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
return o;
}
-#if MICROPY_PY_BUILTINS_FLOAT
-mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- int cl = fpclassify(val);
- if (cl == FP_INFINITE) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
- } else if (cl == FP_NAN) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else {
- mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
- if (icl == MP_FP_CLASS_FIT_SMALLINT) {
- return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
- } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
- return mp_obj_new_int_from_ll((long long)val);
- } else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
- }
- }
-}
-#endif
-
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
// TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
// TODO check overflow
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 2cdf22505..2353bd8d6 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -74,7 +74,7 @@ const mp_obj_int_t mp_maxsize_obj = {
#undef NUM_DIG
#endif
-STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
+mp_obj_int_t *mp_obj_int_new_mpz(void) {
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
o->base.type = &mp_type_int;
mpz_init_zero(&o->mpz);
@@ -277,7 +277,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
case MP_BINARY_OP_INPLACE_RSHIFT: {
mp_int_t irhs = mp_obj_int_get_checked(rhs_in);
if (irhs < 0) {
- mp_raise_msg(&mp_type_ValueError, "negative shift count");
+ mp_raise_ValueError("negative shift count");
}
if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
mpz_shl_inpl(&res->mpz, zlhs, irhs);
@@ -387,26 +387,6 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
return mp_obj_new_int_from_ull(value);
}
-#if MICROPY_PY_BUILTINS_FLOAT
-mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- int cl = fpclassify(val);
- if (cl == FP_INFINITE) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
- } else if (cl == FP_NAN) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else {
- mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
- if (icl == MP_FP_CLASS_FIT_SMALLINT) {
- return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
- } else {
- mp_obj_int_t *o = mp_obj_int_new_mpz();
- mpz_set_from_float(&o->mpz, val);
- return MP_OBJ_FROM_PTR(o);
- }
- }
-}
-#endif
-
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
mp_obj_int_t *o = mp_obj_int_new_mpz();
size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
diff --git a/py/objlist.c b/py/objlist.c
index ba7898415..45e69c8bc 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -186,13 +186,13 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return MP_OBJ_FROM_PTR(res);
}
#endif
- mp_uint_t index_val = mp_get_index(self->base.type, self->len, index, false);
+ size_t index_val = mp_get_index(self->base.type, self->len, index, false);
return self->items[index_val];
} else {
#if MICROPY_PY_BUILTINS_SLICE
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
- mp_uint_t value_len; mp_obj_t *value_items;
+ size_t value_len; mp_obj_t *value_items;
mp_obj_get_array(value, &value_len, &value_items);
mp_bound_slice_t slice_out;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
@@ -268,7 +268,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
if (self->len == 0) {
mp_raise_msg(&mp_type_IndexError, "pop from empty list");
}
- mp_uint_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
+ size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
mp_obj_t ret = self->items[index];
self->len -= 1;
memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
@@ -475,7 +475,7 @@ mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) {
return MP_OBJ_FROM_PTR(o);
}
-void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
+void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
*len = self->len;
*items = self->items;
@@ -490,7 +490,7 @@ void mp_obj_list_set_len(mp_obj_t self_in, size_t len) {
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
- mp_uint_t i = mp_get_index(self->base.type, self->len, index, false);
+ size_t i = mp_get_index(self->base.type, self->len, index, false);
self->items[i] = value;
}
diff --git a/py/objmap.c b/py/objmap.c
index 0b2189016..111c964fd 100644
--- a/py/objmap.c
+++ b/py/objmap.c
@@ -31,7 +31,7 @@
typedef struct _mp_obj_map_t {
mp_obj_base_t base;
- mp_uint_t n_iters;
+ size_t n_iters;
mp_obj_t fun;
mp_obj_t iters[];
} mp_obj_map_t;
@@ -42,7 +42,7 @@ STATIC mp_obj_t map_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
o->base.type = type;
o->n_iters = n_args - 1;
o->fun = args[0];
- for (mp_uint_t i = 0; i < n_args - 1; i++) {
+ for (size_t i = 0; i < n_args - 1; i++) {
o->iters[i] = mp_getiter(args[i + 1], NULL);
}
return MP_OBJ_FROM_PTR(o);
@@ -53,7 +53,7 @@ STATIC mp_obj_t map_iternext(mp_obj_t self_in) {
mp_obj_map_t *self = MP_OBJ_TO_PTR(self_in);
mp_obj_t *nextses = m_new(mp_obj_t, self->n_iters);
- for (mp_uint_t i = 0; i < self->n_iters; i++) {
+ for (size_t i = 0; i < self->n_iters; i++) {
mp_obj_t next = mp_iternext(self->iters[i]);
if (next == MP_OBJ_STOP_ITERATION) {
m_del(mp_obj_t, nextses, self->n_iters);
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 18931a16c..52468747b 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -36,7 +36,7 @@
typedef struct _mp_obj_namedtuple_type_t {
mp_obj_type_t base;
- mp_uint_t n_fields;
+ size_t n_fields;
qstr fields[];
} mp_obj_namedtuple_type_t;
@@ -44,13 +44,13 @@ typedef struct _mp_obj_namedtuple_t {
mp_obj_tuple_t tuple;
} mp_obj_namedtuple_t;
-STATIC mp_uint_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) {
- for (mp_uint_t i = 0; i < type->n_fields; i++) {
+STATIC size_t namedtuple_find_field(const mp_obj_namedtuple_type_t *type, qstr name) {
+ for (size_t i = 0; i < type->n_fields; i++) {
if (type->fields[i] == name) {
return i;
}
}
- return -1;
+ return (size_t)-1;
}
STATIC void namedtuple_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
@@ -65,8 +65,8 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
if (dest[0] == MP_OBJ_NULL) {
// load attribute
mp_obj_namedtuple_t *self = MP_OBJ_TO_PTR(self_in);
- int id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);
- if (id == -1) {
+ size_t id = namedtuple_find_field((mp_obj_namedtuple_type_t*)self->tuple.base.type, attr);
+ if (id == (size_t)-1) {
return;
}
dest[0] = self->tuple.items[id];
@@ -102,14 +102,14 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
arg_objects = alloca(alloc_size);
memset(arg_objects, 0, alloc_size);
- for (mp_uint_t i = 0; i < n_args; i++) {
+ for (size_t i = 0; i < n_args; i++) {
arg_objects[i] = args[i];
}
- for (mp_uint_t i = n_args; i < n_args + 2 * n_kw; i += 2) {
+ for (size_t i = n_args; i < n_args + 2 * n_kw; i += 2) {
qstr kw = mp_obj_str_get_qstr(args[i]);
- int id = namedtuple_find_field(type, kw);
- if (id == -1) {
+ size_t id = namedtuple_find_field(type, kw);
+ if (id == (size_t)-1) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_arg_error_terse_mismatch();
} else {
@@ -136,7 +136,7 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
STATIC const mp_rom_obj_tuple_t namedtuple_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_tuple)}};
-STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, mp_uint_t n_fields, mp_obj_t *fields) {
+STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) {
mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields);
memset(&o->base, 0, sizeof(o->base));
o->base.base.type = &mp_type_type;
@@ -150,7 +150,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, mp_uint_t n_fields, mp_obj
o->base.getiter = mp_obj_tuple_getiter;
o->base.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&namedtuple_base_tuple;
o->n_fields = n_fields;
- for (mp_uint_t i = 0; i < n_fields; i++) {
+ for (size_t i = 0; i < n_fields; i++) {
o->fields[i] = mp_obj_str_get_qstr(fields[i]);
}
return MP_OBJ_FROM_PTR(o);
@@ -158,7 +158,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, mp_uint_t n_fields, mp_obj
STATIC mp_obj_t new_namedtuple_type(mp_obj_t name_in, mp_obj_t fields_in) {
qstr name = mp_obj_str_get_qstr(name_in);
- mp_uint_t n_fields;
+ size_t n_fields;
mp_obj_t *fields;
#if MICROPY_CPYTHON_COMPAT
if (MP_OBJ_IS_STR(fields_in)) {
diff --git a/py/objobject.c b/py/objobject.c
index b33dc491c..f9a7d17c3 100644
--- a/py/objobject.c
+++ b/py/objobject.c
@@ -50,7 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__);
STATIC mp_obj_t object___new__(mp_obj_t cls) {
if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) {
- mp_raise_msg(&mp_type_TypeError, "__new__ arg must be a user-type");
+ mp_raise_TypeError("__new__ arg must be a user-type");
}
mp_obj_t o = MP_OBJ_SENTINEL;
mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o);
diff --git a/py/objrange.c b/py/objrange.c
index dd074a98a..c78c53f11 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -105,8 +105,10 @@ STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t
o->start = mp_obj_get_int(args[0]);
o->stop = mp_obj_get_int(args[1]);
if (n_args == 3) {
- // TODO check step is non-zero
o->step = mp_obj_get_int(args[2]);
+ if (o->step == 0) {
+ mp_raise_ValueError("zero step");
+ }
}
}
@@ -155,7 +157,7 @@ STATIC mp_obj_t range_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return MP_OBJ_FROM_PTR(o);
}
#endif
- uint index_val = mp_get_index(self->base.type, len, index, false);
+ size_t index_val = mp_get_index(self->base.type, len, index, false);
return MP_OBJ_NEW_SMALL_INT(self->start + index_val * self->step);
} else {
return MP_OBJ_NULL; // op not supported
diff --git a/py/objstr.c b/py/objstr.c
index 2331004a5..70de0a693 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -236,7 +236,7 @@ STATIC mp_obj_t bytes_make_new(const mp_obj_type_t *type_in, size_t n_args, size
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
mp_int_t val = mp_obj_get_int(item);
- #if MICROPY_CPYTHON_COMPAT
+ #if MICROPY_FULL_CHECKS
if (val < 0 || val > 255) {
mp_raise_ValueError("bytes value out of range");
}
@@ -284,7 +284,7 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// check for modulo
if (op == MP_BINARY_OP_MODULO) {
mp_obj_t *args = &rhs_in;
- mp_uint_t n_args = 1;
+ size_t n_args = 1;
mp_obj_t dict = MP_OBJ_NULL;
if (MP_OBJ_IS_TYPE(rhs_in, &mp_type_tuple)) {
// TODO: Support tuple subclasses?
@@ -388,7 +388,7 @@ mp_obj_t mp_obj_str_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
// objstrunicode defines own version
const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, size_t self_len,
mp_obj_t index, bool is_slice) {
- mp_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
+ size_t index_val = mp_get_index(type, self_len, index, is_slice);
return self_data + index_val;
}
#endif
@@ -408,7 +408,7 @@ STATIC mp_obj_t bytes_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return mp_obj_new_str_of_type(type, self_data + slice.start, slice.stop - slice.start);
}
#endif
- mp_uint_t index_val = mp_get_index(type, self_len, index, false);
+ size_t index_val = mp_get_index(type, self_len, index, false);
// If we have unicode enabled the type will always be bytes, so take the short cut.
if (MICROPY_PY_BUILTINS_STR_UNICODE || type == &mp_type_bytes) {
return MP_OBJ_NEW_SMALL_INT(self_data[index_val]);
@@ -428,7 +428,7 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
GET_STR_DATA_LEN(self_in, sep_str, sep_len);
// process args
- mp_uint_t seq_len;
+ size_t seq_len;
mp_obj_t *seq_items;
if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {
@@ -513,7 +513,7 @@ mp_obj_t mp_obj_str_split(size_t n_args, const mp_obj_t *args) {
bad_implicit_conversion(sep);
}
- mp_uint_t sep_len;
+ size_t sep_len;
const char *sep_str = mp_obj_str_get_data(sep, &sep_len);
if (sep_len == 0) {
@@ -611,7 +611,7 @@ STATIC mp_obj_t str_rsplit(size_t n_args, const mp_obj_t *args) {
if (sep == mp_const_none) {
mp_not_implemented("rsplit(None,n)");
} else {
- mp_uint_t sep_len;
+ size_t sep_len;
const char *sep_str = mp_obj_str_get_data(sep, &sep_len);
if (sep_len == 0) {
@@ -1306,12 +1306,12 @@ STATIC vstr_t mp_obj_str_format_helper(const char *str, const char *top, int *ar
switch (type) {
case '\0': // no explicit format type implies 's'
case 's': {
- mp_uint_t slen;
+ size_t slen;
const char *s = mp_obj_str_get_data(arg, &slen);
if (precision < 0) {
precision = slen;
}
- if (slen > (mp_uint_t)precision) {
+ if (slen > (size_t)precision) {
slen = precision;
}
mp_print_strn(&print, s, slen, flags, fill, width);
@@ -1452,7 +1452,7 @@ not_enough_args:
switch (*str) {
case 'c':
if (MP_OBJ_IS_STR(arg)) {
- mp_uint_t slen;
+ size_t slen;
const char *s = mp_obj_str_get_data(arg, &slen);
if (slen != 1) {
mp_raise_TypeError("%%c requires int or char");
@@ -2065,9 +2065,10 @@ STATIC void bad_implicit_conversion(mp_obj_t self_in) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("can't convert to str implicitly");
} else {
+ const qstr src_name = mp_obj_get_type(self_in)->name;
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
- "can't convert '%s' object to str implicitly",
- mp_obj_get_type_str(self_in)));
+ "can't convert '%q' object to %q implicitly",
+ src_name, src_name == MP_QSTR_str ? MP_QSTR_bytes : MP_QSTR_str));
}
}
@@ -2096,7 +2097,7 @@ const char *mp_obj_str_get_str(mp_obj_t self_in) {
}
}
-const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len) {
+const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len) {
if (MP_OBJ_IS_STR_OR_BYTES(self_in)) {
GET_STR_DATA_LEN(self_in, s, l);
*len = l;
diff --git a/py/objstringio.c b/py/objstringio.c
index 61a30752e..88659deb8 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -39,7 +39,7 @@
#if MICROPY_CPYTHON_COMPAT
STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) {
if (o->vstr == NULL) {
- mp_raise_msg(&mp_type_ValueError, "I/O operation on closed file");
+ mp_raise_ValueError("I/O operation on closed file");
}
}
#else
diff --git a/py/objstrunicode.c b/py/objstrunicode.c
index 441ec293d..9a6ce9b9a 100644
--- a/py/objstrunicode.c
+++ b/py/objstrunicode.c
@@ -120,7 +120,7 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s
// so it must handle bytes.
if (type == &mp_type_bytes) {
// Taken from objstr.c:str_index_to_ptr()
- mp_uint_t index_val = mp_get_index(type, self_len, index, is_slice);
+ size_t index_val = mp_get_index(type, self_len, index, is_slice);
return self_data + index_val;
}
diff --git a/py/objtuple.c b/py/objtuple.c
index b28807c0d..eaf0e37f4 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -138,7 +138,8 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs);
switch (op) {
- case MP_BINARY_OP_ADD: {
+ case MP_BINARY_OP_ADD:
+ case MP_BINARY_OP_INPLACE_ADD: {
if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(rhs)), MP_OBJ_FROM_PTR(&mp_type_tuple))) {
return MP_OBJ_NULL; // op not supported
}
@@ -186,7 +187,7 @@ mp_obj_t mp_obj_tuple_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
return MP_OBJ_FROM_PTR(res);
}
#endif
- mp_uint_t index_value = mp_get_index(self->base.type, self->len, index, false);
+ size_t index_value = mp_get_index(self->base.type, self->len, index, false);
return self->items[index_value];
} else {
return MP_OBJ_NULL; // op not supported
@@ -244,7 +245,7 @@ mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items) {
return MP_OBJ_FROM_PTR(o);
}
-void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
+void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_tuple));
mp_obj_tuple_t *self = MP_OBJ_TO_PTR(self_in);
*len = self->len;
diff --git a/py/objtype.c b/py/objtype.c
index a4c424929..dd170b4c6 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -48,7 +48,7 @@ STATIC mp_obj_t static_class_method_make_new(const mp_obj_type_t *self_in, size_
/******************************************************************************/
// instance object
-STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, uint subobjs) {
+STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs) {
mp_obj_instance_t *o = m_new_obj_var(mp_obj_instance_t, mp_obj_t, subobjs);
o->base.type = class;
mp_map_init(&o->members, 0);
@@ -57,11 +57,11 @@ STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, uint subobjs) {
}
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
- mp_uint_t len = type->bases_tuple->len;
+ size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
int count = 0;
- for (uint i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(items[i]);
if (bt == &mp_type_object) {
@@ -96,7 +96,7 @@ STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_t
struct class_lookup_data {
mp_obj_instance_t *obj;
qstr attr;
- mp_uint_t meth_offset;
+ size_t meth_offset;
mp_obj_t *dest;
bool is_type;
};
@@ -165,12 +165,12 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
return;
}
- mp_uint_t len = type->bases_tuple->len;
+ size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
if (len == 0) {
return;
}
- for (uint i = 0; i < len - 1; i++) {
+ for (size_t i = 0; i < len - 1; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]);
if (bt == &mp_type_object) {
@@ -239,7 +239,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
assert(mp_obj_is_instance_type(self));
const mp_obj_type_t *native_base;
- uint num_native_bases = instance_count_native_bases(self, &native_base);
+ size_t num_native_bases = instance_count_native_bases(self, &native_base);
assert(num_native_bases < 2);
mp_obj_instance_t *o = MP_OBJ_TO_PTR(mp_obj_new_instance(self, num_native_bases));
@@ -311,7 +311,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
}
if (init_ret != mp_const_none) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "__init__() should return None");
+ mp_raise_TypeError("__init__() should return None");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret)));
@@ -477,7 +477,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des
// it will not result in modifications to the actual instance members.
mp_map_t *map = &self->members;
mp_obj_t attr_dict = mp_obj_new_dict(map->used);
- for (mp_uint_t i = 0; i < map->alloc; ++i) {
+ for (size_t i = 0; i < map->alloc; ++i) {
if (MP_MAP_SLOT_IS_FILLED(map, i)) {
mp_obj_dict_store(attr_dict, map->table[i].key, map->table[i].value);
}
@@ -688,7 +688,7 @@ STATIC mp_obj_t instance_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value
.dest = member,
.is_type = false,
};
- uint meth_args;
+ size_t meth_args;
if (value == MP_OBJ_NULL) {
// delete item
lookup.attr = MP_QSTR___delitem__;
@@ -744,7 +744,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
mp_obj_t call = mp_obj_instance_get_call(self_in, member);
if (call == MP_OBJ_NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not callable");
+ mp_raise_TypeError("object not callable");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not callable", mp_obj_get_type_str(self_in)));
@@ -826,7 +826,7 @@ STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_
return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]);
default:
- mp_raise_msg(&mp_type_TypeError, "type takes 1 or 3 arguments");
+ mp_raise_TypeError("type takes 1 or 3 arguments");
}
}
@@ -837,7 +837,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp
if (self->make_new == NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "cannot create instance");
+ mp_raise_TypeError("cannot create instance");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"cannot create '%q' instances", self->name));
@@ -916,16 +916,16 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
// TODO might need to make a copy of locals_dict; at least that's how CPython does it
// Basic validation of base classes
- mp_uint_t len;
+ size_t len;
mp_obj_t *items;
mp_obj_tuple_get(bases_tuple, &len, &items);
- for (uint i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_type_t *t = MP_OBJ_TO_PTR(items[i]);
// TODO: Verify with CPy, tested on function type
if (t->make_new == NULL) {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "type is not an acceptable base type");
+ mp_raise_TypeError("type is not an acceptable base type");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"type '%q' is not an acceptable base type", t->name));
@@ -957,9 +957,9 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
o->locals_dict = MP_OBJ_TO_PTR(locals_dict);
const mp_obj_type_t *native_base;
- uint num_native_bases = instance_count_native_bases(o, &native_base);
+ size_t num_native_bases = instance_count_native_bases(o, &native_base);
if (num_native_bases > 1) {
- mp_raise_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict");
+ mp_raise_TypeError("multiple bases have instance lay-out conflict");
}
mp_map_t *locals_map = &o->locals_dict->map;
@@ -1020,7 +1020,7 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
return;
}
- mp_uint_t len = type->bases_tuple->len;
+ size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
struct class_lookup_data lookup = {
.obj = MP_OBJ_TO_PTR(self->obj),
@@ -1029,7 +1029,7 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
.dest = dest,
.is_type = false,
};
- for (uint i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
if (dest[0] != MP_OBJ_NULL) {
@@ -1079,14 +1079,14 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
}
// get the base objects (they should be type objects)
- mp_uint_t len = self->bases_tuple->len;
+ size_t len = self->bases_tuple->len;
mp_obj_t *items = self->bases_tuple->items;
if (len == 0) {
return false;
}
// iterate through the base objects
- for (uint i = 0; i < len - 1; i++) {
+ for (size_t i = 0; i < len - 1; i++) {
if (mp_obj_is_subclass_fast(items[i], classinfo)) {
return true;
}
@@ -1098,7 +1098,7 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
}
STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
- mp_uint_t len;
+ size_t len;
mp_obj_t *items;
if (MP_OBJ_IS_TYPE(classinfo, &mp_type_type)) {
len = 1;
@@ -1106,10 +1106,10 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
} else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) {
mp_obj_tuple_get(classinfo, &len, &items);
} else {
- mp_raise_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes");
+ mp_raise_TypeError("issubclass() arg 2 must be a class or a tuple of classes");
}
- for (uint i = 0; i < len; i++) {
+ for (size_t i = 0; i < len; i++) {
// We explicitly check for 'object' here since no-one explicitly derives from it
if (items[i] == MP_OBJ_FROM_PTR(&mp_type_object) || mp_obj_is_subclass_fast(object, items[i])) {
return mp_const_true;
@@ -1120,7 +1120,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) {
STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) {
if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) {
- mp_raise_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class");
+ mp_raise_TypeError("issubclass() arg 1 must be a class");
}
return mp_obj_is_subclass(object, classinfo);
}
diff --git a/py/objzip.c b/py/objzip.c
index 5d9ba48e7..6f72d1595 100644
--- a/py/objzip.c
+++ b/py/objzip.c
@@ -32,7 +32,7 @@
typedef struct _mp_obj_zip_t {
mp_obj_base_t base;
- mp_uint_t n_iters;
+ size_t n_iters;
mp_obj_t iters[];
} mp_obj_zip_t;
@@ -42,7 +42,7 @@ STATIC mp_obj_t zip_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
mp_obj_zip_t *o = m_new_obj_var(mp_obj_zip_t, mp_obj_t, n_args);
o->base.type = type;
o->n_iters = n_args;
- for (mp_uint_t i = 0; i < n_args; i++) {
+ for (size_t i = 0; i < n_args; i++) {
o->iters[i] = mp_getiter(args[i], NULL);
}
return MP_OBJ_FROM_PTR(o);
@@ -56,7 +56,7 @@ STATIC mp_obj_t zip_iternext(mp_obj_t self_in) {
}
mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(self->n_iters, NULL));
- for (mp_uint_t i = 0; i < self->n_iters; i++) {
+ for (size_t i = 0; i < self->n_iters; i++) {
mp_obj_t next = mp_iternext(self->iters[i]);
if (next == MP_OBJ_STOP_ITERATION) {
mp_obj_tuple_del(MP_OBJ_FROM_PTR(tuple));
diff --git a/py/parsenum.c b/py/parsenum.c
index 2e41801ee..177118843 100644
--- a/py/parsenum.c
+++ b/py/parsenum.c
@@ -55,7 +55,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m
// check radix base
if ((base != 0 && base < 2) || base > 36) {
// this won't be reached if lex!=NULL
- mp_raise_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36");
+ mp_raise_ValueError("int() arg 2 must be >= 2 and <= 36");
}
// skip leading space
diff --git a/py/py.mk b/py/py.mk
index c4e2a79e6..5ff1fd6a6 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -16,9 +16,6 @@ endif
# some code is performance bottleneck and compiled with other optimization options
CSUPEROPT = -O3
-INC += -I../lib
-INC += -I../lib/netutils
-
# this sets the config file for FatFs
CFLAGS_MOD += -DFFCONF_H=\"lib/oofatfs/ffconf.h\"
@@ -143,6 +140,7 @@ PY_O_BASENAME = \
persistentcode.o \
runtime.o \
runtime_utils.o \
+ scheduler.o \
nativeglue.o \
stackctrl.o \
argcheck.o \
diff --git a/py/repl.c b/py/repl.c
index 997d80005..6d8f7cca4 100644
--- a/py/repl.c
+++ b/py/repl.c
@@ -153,7 +153,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t
mp_obj_t obj = MP_OBJ_NULL;
for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- mp_uint_t d_len;
+ size_t d_len;
const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
if (s_len == d_len && strncmp(s_start, d_str, d_len) == 0) {
obj = dict->map.table[i].value;
@@ -197,7 +197,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t
mp_uint_t match_len = 0;
for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- mp_uint_t d_len;
+ size_t d_len;
const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
if (match_str == NULL) {
@@ -247,7 +247,7 @@ mp_uint_t mp_repl_autocomplete(const char *str, mp_uint_t len, const mp_print_t
int line_len = MAX_LINE_LEN; // force a newline for first word
for (mp_uint_t i = 0; i < dict->map.alloc; i++) {
if (MP_MAP_SLOT_IS_FILLED(&dict->map, i)) {
- mp_uint_t d_len;
+ size_t d_len;
const char *d_str = mp_obj_str_get_data(dict->map.table[i].key, &d_len);
if (s_len <= d_len && strncmp(s_start, d_str, s_len) == 0) {
int gap = (line_len + WORD_SLOT_LEN - 1) / WORD_SLOT_LEN * WORD_SLOT_LEN - line_len;
diff --git a/py/runtime.c b/py/runtime.c
index 1f69290ba..1df6740b2 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -63,6 +63,10 @@ void mp_init(void) {
// no pending exceptions to start with
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ #if MICROPY_ENABLE_SCHEDULER
+ MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
+ MP_STATE_VM(sched_sp) = 0;
+ #endif
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
mp_init_emergency_exception_buf();
@@ -93,7 +97,8 @@ void mp_init(void) {
mp_obj_dict_store(MP_OBJ_FROM_PTR(&MP_STATE_VM(dict_main)), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
// locals = globals for outer module (see Objects/frameobject.c/PyFrame_New())
- MP_STATE_CTX(dict_locals) = MP_STATE_CTX(dict_globals) = &MP_STATE_VM(dict_main);
+ mp_locals_set(&MP_STATE_VM(dict_main));
+ mp_globals_set(&MP_STATE_VM(dict_main));
#if MICROPY_CAN_OVERRIDE_BUILTINS
// start with no extensions to builtins
@@ -132,8 +137,8 @@ mp_obj_t mp_load_name(qstr qst) {
// logic: search locals, globals, builtins
DEBUG_OP_printf("load name %s\n", qstr_str(qst));
// If we're at the outer scope (locals == globals), dispatch to load_global right away
- if (MP_STATE_CTX(dict_locals) != MP_STATE_CTX(dict_globals)) {
- mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
+ if (mp_locals_get() != mp_globals_get()) {
+ mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
if (elem != NULL) {
return elem->value;
}
@@ -144,7 +149,7 @@ mp_obj_t mp_load_name(qstr qst) {
mp_obj_t mp_load_global(qstr qst) {
// logic: search globals, builtins
DEBUG_OP_printf("load global %s\n", qstr_str(qst));
- mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
+ mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
if (elem == NULL) {
#if MICROPY_CAN_OVERRIDE_BUILTINS
if (MP_STATE_VM(mp_module_builtins_override_dict) != NULL) {
@@ -184,24 +189,24 @@ mp_obj_t mp_load_build_class(void) {
void mp_store_name(qstr qst, mp_obj_t obj) {
DEBUG_OP_printf("store name %s <- %p\n", qstr_str(qst), obj);
- mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst), obj);
+ mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst), obj);
}
void mp_delete_name(qstr qst) {
DEBUG_OP_printf("delete name %s\n", qstr_str(qst));
// TODO convert KeyError to NameError if qst not found
- mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_locals)), MP_OBJ_NEW_QSTR(qst));
+ mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_locals_get()), MP_OBJ_NEW_QSTR(qst));
}
void mp_store_global(qstr qst, mp_obj_t obj) {
DEBUG_OP_printf("store global %s <- %p\n", qstr_str(qst), obj);
- mp_obj_dict_store(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst), obj);
+ mp_obj_dict_store(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst), obj);
}
void mp_delete_global(qstr qst) {
DEBUG_OP_printf("delete global %s\n", qstr_str(qst));
// TODO convert KeyError to NameError if qst not found
- mp_obj_dict_delete(MP_OBJ_FROM_PTR(MP_STATE_CTX(dict_globals)), MP_OBJ_NEW_QSTR(qst));
+ mp_obj_dict_delete(MP_OBJ_FROM_PTR(mp_globals_get()), MP_OBJ_NEW_QSTR(qst));
}
mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
@@ -247,7 +252,7 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) {
}
}
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "unsupported type for operator");
+ mp_raise_TypeError("unsupported type for operator");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"unsupported type for %q: '%s'",
@@ -339,7 +344,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_INPLACE_LSHIFT: {
if (rhs_val < 0) {
// negative shift not allowed
- mp_raise_msg(&mp_type_ValueError, "negative shift count");
+ mp_raise_ValueError("negative shift count");
} else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) {
// left-shift will overflow, so use higher precision integer
lhs = mp_obj_new_int_from_ll(lhs_val);
@@ -354,7 +359,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
case MP_BINARY_OP_INPLACE_RSHIFT:
if (rhs_val < 0) {
// negative shift not allowed
- mp_raise_msg(&mp_type_ValueError, "negative shift count");
+ mp_raise_ValueError("negative shift count");
} else {
// standard precision is enough for right-shift
if (rhs_val >= (mp_int_t)BITS_PER_WORD) {
@@ -430,7 +435,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
lhs = mp_obj_new_float(lhs_val);
goto generic_binary_op;
#else
- mp_raise_msg(&mp_type_ValueError, "negative power with no float support");
+ mp_raise_ValueError("negative power with no float support");
#endif
} else {
mp_int_t ans = 1;
@@ -532,7 +537,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
}
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not iterable");
+ mp_raise_TypeError("object not iterable");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not iterable", mp_obj_get_type_str(rhs)));
@@ -554,7 +559,7 @@ generic_binary_op:
unsupported_op:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "unsupported type for operator");
+ mp_raise_TypeError("unsupported type for operator");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"unsupported types for %q: '%s', '%s'",
@@ -596,7 +601,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, size_t n_args, size_t n_kw, cons
}
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not callable");
+ mp_raise_TypeError("object not callable");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not callable", mp_obj_get_type_str(fun_in)));
@@ -665,7 +670,7 @@ void mp_call_prepare_args_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_
// optimise the case of a tuple and list
// get the items
- mp_uint_t len;
+ size_t len;
mp_obj_t *items;
mp_obj_get_array(pos_seq, &len, &items);
@@ -794,7 +799,7 @@ mp_obj_t mp_call_method_n_kw_var(bool have_self, size_t n_args_n_kw, const mp_ob
// unpacked items are stored in reverse order into the array pointed to by items
void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
- mp_uint_t seq_len;
+ size_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
mp_obj_t *seq_items;
mp_obj_get_array(seq_in, &seq_len, &seq_items);
@@ -825,14 +830,14 @@ void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
too_short:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack");
+ mp_raise_ValueError("wrong number of values to unpack");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"need more than %d values to unpack", (int)seq_len));
}
too_long:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack");
+ mp_raise_ValueError("wrong number of values to unpack");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"too many values to unpack (expected %d)", (int)num));
@@ -844,7 +849,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
size_t num_left = num_in & 0xff;
size_t num_right = (num_in >> 8) & 0xff;
DEBUG_OP_printf("unpack ex " UINT_FMT " " UINT_FMT "\n", num_left, num_right);
- mp_uint_t seq_len;
+ size_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
mp_obj_t *seq_items;
mp_obj_get_array(seq_in, &seq_len, &seq_items);
@@ -889,7 +894,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
too_short:
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack");
+ mp_raise_ValueError("wrong number of values to unpack");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
"need more than %d values to unpack", (int)seq_len));
@@ -928,7 +933,7 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c
const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]);
if (arg0_type != self->type) {
if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) {
- mp_raise_msg(&mp_type_TypeError, "argument has wrong type");
+ mp_raise_TypeError("argument has wrong type");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"argument should be a '%q' not a '%q'", self->type->name, arg0_type->name));
@@ -1119,7 +1124,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in, mp_obj_iter_buf_t *iter_buf) {
// object not iterable
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not iterable");
+ mp_raise_TypeError("object not iterable");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not iterable", mp_obj_get_type_str(o_in)));
@@ -1141,7 +1146,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) {
return mp_call_method_n_kw(0, 0, dest);
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not an iterator");
+ mp_raise_TypeError("object not an iterator");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
@@ -1177,7 +1182,7 @@ mp_obj_t mp_iternext(mp_obj_t o_in) {
}
} else {
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
- mp_raise_msg(&mp_type_TypeError, "object not an iterator");
+ mp_raise_TypeError("object not an iterator");
} else {
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
"'%s' object is not an iterator", mp_obj_get_type_str(o_in)));
@@ -1325,7 +1330,7 @@ import_error:
}
mp_load_method_maybe(module, MP_QSTR___name__, dest);
- mp_uint_t pkg_name_len;
+ size_t pkg_name_len;
const char *pkg_name = mp_obj_str_get_data(dest[0], &pkg_name_len);
const uint dot_name_len = pkg_name_len + 1 + qstr_len(name);
diff --git a/py/runtime.h b/py/runtime.h
index 954833b67..177869145 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -64,6 +64,16 @@ extern const qstr mp_binary_op_method_name[];
void mp_init(void);
void mp_deinit(void);
+void mp_handle_pending(void);
+void mp_handle_pending_tail(mp_uint_t atomic_state);
+
+#if MICROPY_ENABLE_SCHEDULER
+void mp_sched_lock(void);
+void mp_sched_unlock(void);
+static inline unsigned int mp_sched_num_pending(void) { return MP_STATE_VM(sched_sp); }
+bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg);
+#endif
+
// extra printing method specifically for mp_obj_t's which are integral type
int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char, int flags, char fill, int width, int prec);
@@ -73,10 +83,10 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
NORETURN void mp_arg_error_terse_mismatch(void);
NORETURN void mp_arg_error_unimpl_kw(void);
-static inline mp_obj_dict_t *mp_locals_get(void) { return MP_STATE_CTX(dict_locals); }
-static inline void mp_locals_set(mp_obj_dict_t *d) { MP_STATE_CTX(dict_locals) = d; }
-static inline mp_obj_dict_t *mp_globals_get(void) { return MP_STATE_CTX(dict_globals); }
-static inline void mp_globals_set(mp_obj_dict_t *d) { MP_STATE_CTX(dict_globals) = d; }
+static inline mp_obj_dict_t *mp_locals_get(void) { return MP_STATE_THREAD(dict_locals); }
+static inline void mp_locals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_locals) = d; }
+static inline mp_obj_dict_t *mp_globals_get(void) { return MP_STATE_THREAD(dict_globals); }
+static inline void mp_globals_set(mp_obj_dict_t *d) { MP_STATE_THREAD(dict_globals) = d; }
mp_obj_t mp_load_name(qstr qst);
mp_obj_t mp_load_global(qstr qst);
diff --git a/py/scheduler.c b/py/scheduler.c
new file mode 100644
index 000000000..30851a4d2
--- /dev/null
+++ b/py/scheduler.c
@@ -0,0 +1,117 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdio.h>
+
+#include "py/runtime.h"
+
+#if MICROPY_ENABLE_SCHEDULER
+
+// A variant of this is inlined in the VM at the pending exception check
+void mp_handle_pending(void) {
+ if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
+ if (obj != MP_OBJ_NULL) {
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ if (!mp_sched_num_pending()) {
+ MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+ nlr_raise(obj);
+ }
+ mp_handle_pending_tail(atomic_state);
+ }
+}
+
+// This function should only be called be mp_sched_handle_pending,
+// or by the VM's inlined version of that function.
+void mp_handle_pending_tail(mp_uint_t atomic_state) {
+ MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;
+ if (MP_STATE_VM(sched_sp) > 0) {
+ mp_sched_item_t item = MP_STATE_VM(sched_stack)[--MP_STATE_VM(sched_sp)];
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+ mp_call_function_1_protected(item.func, item.arg);
+ } else {
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+ }
+ mp_sched_unlock();
+}
+
+void mp_sched_lock(void) {
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ if (MP_STATE_VM(sched_state) < 0) {
+ --MP_STATE_VM(sched_state);
+ } else {
+ MP_STATE_VM(sched_state) = MP_SCHED_LOCKED;
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+}
+
+void mp_sched_unlock(void) {
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ if (++MP_STATE_VM(sched_state) == 0) {
+ // vm became unlocked
+ if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL || mp_sched_num_pending()) {
+ MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
+ } else {
+ MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
+ }
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+}
+
+bool mp_sched_schedule(mp_obj_t function, mp_obj_t arg) {
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ bool ret;
+ if (MP_STATE_VM(sched_sp) < MICROPY_SCHEDULER_DEPTH) {
+ if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
+ MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
+ }
+ MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].func = function;
+ MP_STATE_VM(sched_stack)[MP_STATE_VM(sched_sp)].arg = arg;
+ ++MP_STATE_VM(sched_sp);
+ ret = true;
+ } else {
+ // schedule stack is full
+ ret = false;
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+ return ret;
+}
+
+#else // MICROPY_ENABLE_SCHEDULER
+
+// A variant of this is inlined in the VM at the pending exception check
+void mp_handle_pending(void) {
+ if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
+ mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ nlr_raise(obj);
+ }
+}
+
+#endif // MICROPY_ENABLE_SCHEDULER
diff --git a/py/sequence.c b/py/sequence.c
index bc2cfc077..cd1a96617 100644
--- a/py/sequence.c
+++ b/py/sequence.c
@@ -38,9 +38,9 @@
// Implements backend of sequence * integer operation. Assumes elements are
// memory-adjacent in sequence.
-void mp_seq_multiply(const void *items, mp_uint_t item_sz, mp_uint_t len, mp_uint_t times, void *dest) {
- for (mp_uint_t i = 0; i < times; i++) {
- uint copy_sz = item_sz * len;
+void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest) {
+ for (size_t i = 0; i < times; i++) {
+ size_t copy_sz = item_sz * len;
memcpy(dest, items, copy_sz);
dest = (char*)dest + copy_sz;
}
@@ -119,7 +119,7 @@ bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice
#endif
-mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
+mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes) {
(void)len; // TODO can we remove len from the arg list?
mp_int_t start = indexes->start, stop = indexes->stop;
@@ -143,7 +143,7 @@ mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice
// Special-case comparison function for sequences of bytes
// Don't pass MP_BINARY_OP_NOT_EQUAL here
-bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, mp_uint_t len1, const byte *data2, mp_uint_t len2) {
+bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2) {
if (op == MP_BINARY_OP_EQUAL && len1 != len2) {
return false;
}
@@ -151,14 +151,14 @@ bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, mp_uint_t len1, const byt
// Let's deal only with > & >=
if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) {
SWAP(const byte*, data1, data2);
- SWAP(uint, len1, len2);
+ SWAP(size_t, len1, len2);
if (op == MP_BINARY_OP_LESS) {
op = MP_BINARY_OP_MORE;
} else {
op = MP_BINARY_OP_MORE_EQUAL;
}
}
- uint min_len = len1 < len2 ? len1 : len2;
+ size_t min_len = len1 < len2 ? len1 : len2;
int res = memcmp(data1, data2, min_len);
if (op == MP_BINARY_OP_EQUAL) {
// If we are checking for equality, here're the answer
@@ -187,7 +187,7 @@ bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, mp_uint_t len1, const byt
// Special-case comparison function for sequences of mp_obj_t
// Don't pass MP_BINARY_OP_NOT_EQUAL here
-bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const mp_obj_t *items2, mp_uint_t len2) {
+bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2) {
if (op == MP_BINARY_OP_EQUAL && len1 != len2) {
return false;
}
@@ -195,7 +195,7 @@ bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const
// Let's deal only with > & >=
if (op == MP_BINARY_OP_LESS || op == MP_BINARY_OP_LESS_EQUAL) {
SWAP(const mp_obj_t *, items1, items2);
- SWAP(uint, len1, len2);
+ SWAP(size_t, len1, len2);
if (op == MP_BINARY_OP_LESS) {
op = MP_BINARY_OP_MORE;
} else {
@@ -203,8 +203,8 @@ bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const
}
}
- mp_uint_t len = len1 < len2 ? len1 : len2;
- for (mp_uint_t i = 0; i < len; i++) {
+ size_t len = len1 < len2 ? len1 : len2;
+ for (size_t i = 0; i < len; i++) {
// If current elements equal, can't decide anything - go on
if (mp_obj_equal(items1[i], items2[i])) {
continue;
@@ -236,11 +236,11 @@ bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const
}
// Special-case of index() which searches for mp_obj_t
-mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args, const mp_obj_t *args) {
+mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args) {
mp_obj_type_t *type = mp_obj_get_type(args[0]);
mp_obj_t value = args[1];
- uint start = 0;
- uint stop = len;
+ size_t start = 0;
+ size_t stop = len;
if (n_args >= 3) {
start = mp_get_index(type, len, args[2], true);
@@ -249,19 +249,19 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args
}
}
- for (mp_uint_t i = start; i < stop; i++) {
+ for (size_t i = start; i < stop; i++) {
if (mp_obj_equal(items[i], value)) {
// Common sense says this cannot overflow small int
return MP_OBJ_NEW_SMALL_INT(i);
}
}
- mp_raise_msg(&mp_type_ValueError, "object not in sequence");
+ mp_raise_ValueError("object not in sequence");
}
-mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value) {
- mp_uint_t count = 0;
- for (uint i = 0; i < len; i++) {
+mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value) {
+ size_t count = 0;
+ for (size_t i = 0; i < len; i++) {
if (mp_obj_equal(items[i], value)) {
count++;
}
diff --git a/py/vm.c b/py/vm.c
index 7a906cd80..8ce635ca8 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -38,7 +38,7 @@
#include "py/bc.h"
#if 0
-#define TRACE(ip) printf("sp=%d ", (int)(sp - code_state->sp)); mp_bytecode_print2(ip, 1, code_state->const_table);
+#define TRACE(ip) printf("sp=%d ", (int)(sp - &code_state->state[0] + 1)); mp_bytecode_print2(ip, 1, code_state->fun_bc->const_table);
#else
#define TRACE(ip)
#endif
@@ -73,10 +73,10 @@ typedef enum {
ip += 2;
#define DECODE_PTR \
DECODE_UINT; \
- void *ptr = (void*)(uintptr_t)code_state->const_table[unum]
+ void *ptr = (void*)(uintptr_t)code_state->fun_bc->const_table[unum]
#define DECODE_OBJ \
DECODE_UINT; \
- mp_obj_t obj = (mp_obj_t)code_state->const_table[unum]
+ mp_obj_t obj = (mp_obj_t)code_state->fun_bc->const_table[unum]
#else
@@ -162,8 +162,9 @@ mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp
run_code_state: ;
#endif
// Pointers which are constant for particular invocation of mp_execute_bytecode()
- mp_obj_t * /*const*/ fastn = &code_state->state[code_state->n_state - 1];
- mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
+ size_t n_state = mp_decode_uint_value(code_state->fun_bc->bytecode);
+ mp_obj_t * /*const*/ fastn = &code_state->state[n_state - 1];
+ mp_exc_stack_t * /*const*/ exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
// variables that are visible to the exception handler (declared volatile)
volatile bool currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
@@ -284,12 +285,12 @@ dispatch_loop:
DECODE_QSTR;
mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
mp_uint_t x = *ip;
- if (x < MP_STATE_CTX(dict_locals)->map.alloc && MP_STATE_CTX(dict_locals)->map.table[x].key == key) {
- PUSH(MP_STATE_CTX(dict_locals)->map.table[x].value);
+ if (x < mp_locals_get()->map.alloc && mp_locals_get()->map.table[x].key == key) {
+ PUSH(mp_locals_get()->map.table[x].value);
} else {
- mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_locals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
+ mp_map_elem_t *elem = mp_map_lookup(&mp_locals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
if (elem != NULL) {
- *(byte*)ip = (elem - &MP_STATE_CTX(dict_locals)->map.table[0]) & 0xff;
+ *(byte*)ip = (elem - &mp_locals_get()->map.table[0]) & 0xff;
PUSH(elem->value);
} else {
PUSH(mp_load_name(MP_OBJ_QSTR_VALUE(key)));
@@ -313,12 +314,12 @@ dispatch_loop:
DECODE_QSTR;
mp_obj_t key = MP_OBJ_NEW_QSTR(qst);
mp_uint_t x = *ip;
- if (x < MP_STATE_CTX(dict_globals)->map.alloc && MP_STATE_CTX(dict_globals)->map.table[x].key == key) {
- PUSH(MP_STATE_CTX(dict_globals)->map.table[x].value);
+ if (x < mp_globals_get()->map.alloc && mp_globals_get()->map.table[x].key == key) {
+ PUSH(mp_globals_get()->map.table[x].value);
} else {
- mp_map_elem_t *elem = mp_map_lookup(&MP_STATE_CTX(dict_globals)->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
+ mp_map_elem_t *elem = mp_map_lookup(&mp_globals_get()->map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP);
if (elem != NULL) {
- *(byte*)ip = (elem - &MP_STATE_CTX(dict_globals)->map.table[0]) & 0xff;
+ *(byte*)ip = (elem - &mp_globals_get()->map.table[0]) & 0xff;
PUSH(elem->value);
} else {
PUSH(mp_load_global(MP_OBJ_QSTR_VALUE(key)));
@@ -683,7 +684,7 @@ unwind_jump:;
if (unum != 0) {
// pop iter and iter_buf
sp--;
- sp -= sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t);
+ sp -= MP_OBJ_ITER_BUF_NSLOTS;
}
DISPATCH_WITH_PEND_EXC_CHECK();
}
@@ -728,19 +729,20 @@ unwind_jump:;
SET_TOP(mp_getiter(TOP(), NULL));
DISPATCH();
- // An iterator for a for-loop takes 4 slots on the stack. They are either
- // used to store the iterator object itself, or the first slot is NULL and
+ // An iterator for a for-loop takes MP_OBJ_ITER_BUF_NSLOTS slots on
+ // the Python value stack. These slots are either used to store the
+ // iterator object itself, or the first slot is MP_OBJ_NULL and
// the second slot holds a reference to the iterator object.
ENTRY(MP_BC_GET_ITER_STACK): {
MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = TOP();
mp_obj_iter_buf_t *iter_buf = (mp_obj_iter_buf_t*)sp;
- sp += sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1;
+ sp += MP_OBJ_ITER_BUF_NSLOTS - 1;
obj = mp_getiter(obj, iter_buf);
if (obj != MP_OBJ_FROM_PTR(iter_buf)) {
// Iterator didn't use the stack so indicate that with MP_OBJ_NULL.
- sp[-3] = MP_OBJ_NULL;
- sp[-2] = obj;
+ sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] = MP_OBJ_NULL;
+ sp[-MP_OBJ_ITER_BUF_NSLOTS + 2] = obj;
}
DISPATCH();
}
@@ -750,14 +752,14 @@ unwind_jump:;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->sp = sp;
mp_obj_t obj;
- if (sp[-3] == MP_OBJ_NULL) {
- obj = sp[-2];
+ if (sp[-MP_OBJ_ITER_BUF_NSLOTS + 1] == MP_OBJ_NULL) {
+ obj = sp[-MP_OBJ_ITER_BUF_NSLOTS + 2];
} else {
- obj = MP_OBJ_FROM_PTR(&sp[-3]);
+ obj = MP_OBJ_FROM_PTR(&sp[-MP_OBJ_ITER_BUF_NSLOTS + 1]);
}
mp_obj_t value = mp_iternext_allow_raise(obj);
if (value == MP_OBJ_STOP_ITERATION) {
- sp -= 4; // pop the exhausted iterator
+ sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
ip += ulab; // jump to after for-block
} else {
PUSH(value); // push the next iteration value
@@ -1266,12 +1268,32 @@ yield:
pending_exception_check:
MICROPY_VM_HOOK_LOOP
+
+ #if MICROPY_ENABLE_SCHEDULER
+ // This is an inlined variant of mp_handle_pending
+ if (MP_STATE_VM(sched_state) == MP_SCHED_PENDING) {
+ MARK_EXC_IP_SELECTIVE();
+ mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
+ mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
+ if (obj != MP_OBJ_NULL) {
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
+ if (!mp_sched_num_pending()) {
+ MP_STATE_VM(sched_state) = MP_SCHED_IDLE;
+ }
+ MICROPY_END_ATOMIC_SECTION(atomic_state);
+ RAISE(obj);
+ }
+ mp_handle_pending_tail(atomic_state);
+ }
+ #else
+ // This is an inlined variant of mp_handle_pending
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
MARK_EXC_IP_SELECTIVE();
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
RAISE(obj);
}
+ #endif
#if MICROPY_PY_THREAD_GIL
#if MICROPY_PY_THREAD_GIL_VM_DIVISOR
@@ -1280,8 +1302,14 @@ pending_exception_check:
#else
{
#endif
+ #if MICROPY_ENABLE_SCHEDULER
+ // can only switch threads if the scheduler is unlocked
+ if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE)
+ #endif
+ {
MP_THREAD_GIL_EXIT();
MP_THREAD_GIL_ENTER();
+ }
}
#endif
@@ -1307,7 +1335,7 @@ exception_handler:
const byte *ip = code_state->ip + 1;
DECODE_ULABEL; // the jump offset if iteration finishes; for labels are always forward
code_state->ip = ip + ulab; // jump to after for-block
- code_state->sp -= 4; // pop the exhausted iterator
+ code_state->sp -= MP_OBJ_ITER_BUF_NSLOTS; // pop the exhausted iterator
goto outer_dispatch_loop; // continue with dispatch loop
} else if (*code_state->ip == MP_BC_YIELD_FROM) {
// StopIteration inside yield from call means return a value of
@@ -1327,8 +1355,16 @@ unwind_loop:
// But consider how to handle nested exceptions.
// TODO need a better way of not adding traceback to constant objects (right now, just GeneratorExit_obj and MemoryError_obj)
if (nlr.ret_val != &mp_const_GeneratorExit_obj && nlr.ret_val != &mp_const_MemoryError_obj) {
- const byte *ip = code_state->code_info;
+ const byte *ip = code_state->fun_bc->bytecode;
+ mp_decode_uint(&ip); // skip n_state
+ mp_decode_uint(&ip); // skip n_exc_stack
+ ip++; // skip scope_params
+ ip++; // skip n_pos_args
+ ip++; // skip n_kwonly_args
+ ip++; // skip n_def_pos_args
+ size_t bc = code_state->ip - ip;
size_t code_info_size = mp_decode_uint(&ip);
+ bc -= code_info_size;
#if MICROPY_PERSISTENT_CODE
qstr block_name = ip[0] | (ip[1] << 8);
qstr source_file = ip[2] | (ip[3] << 8);
@@ -1337,7 +1373,6 @@ unwind_loop:
qstr block_name = mp_decode_uint(&ip);
qstr source_file = mp_decode_uint(&ip);
#endif
- size_t bc = code_state->ip - code_state->code_info - code_info_size;
size_t source_line = 1;
size_t c;
while ((c = *ip)) {
@@ -1393,8 +1428,8 @@ unwind_loop:
} else if (code_state->prev != NULL) {
mp_globals_set(code_state->old_globals);
code_state = code_state->prev;
- fastn = &code_state->state[code_state->n_state - 1];
- exc_stack = (mp_exc_stack_t*)(code_state->state + code_state->n_state);
+ fastn = &code_state->state[n_state - 1];
+ exc_stack = (mp_exc_stack_t*)(code_state->state + n_state);
// variables that are visible to the exception handler (declared volatile)
currently_in_except_block = MP_TAGPTR_TAG0(code_state->exc_sp); // 0 or 1, to detect nested exceptions
exc_sp = MP_TAGPTR_PTR(code_state->exc_sp); // stack grows up, exc_sp points to top of stack
diff --git a/qemu-arm/Makefile b/qemu-arm/Makefile
index 61fc24364..d4bbe8d58 100644
--- a/qemu-arm/Makefile
+++ b/qemu-arm/Makefile
@@ -15,7 +15,7 @@ INC += -I$(BUILD)
INC += -I../tools/tinytest/
CFLAGS_CORTEX_M3 = -mthumb -mcpu=cortex-m3 -mfloat-abi=soft
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT) \
+CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 $(CFLAGS_CORTEX_M3) $(COPT) \
-ffunction-sections -fdata-sections
#Debugging/Optimization
@@ -47,7 +47,7 @@ SRC_TEST_C = \
LIB_SRC_C = $(addprefix lib/,\
libm/math.c \
libm/fmodf.c \
- libm/roundf.c \
+ libm/nearbyintf.c \
libm/ef_sqrt.c \
libm/kf_rem_pio2.c \
libm/kf_sin.c \
diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h
index f642c6428..974d3520b 100644
--- a/qemu-arm/mpconfigport.h
+++ b/qemu-arm/mpconfigport.h
@@ -39,8 +39,6 @@
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
#define MP_SSIZE_MAX (0x7fffffff)
diff --git a/stmhal/Makefile b/stmhal/Makefile
index 76579d130..09643be94 100644
--- a/stmhal/Makefile
+++ b/stmhal/Makefile
@@ -47,16 +47,13 @@ INC += -I$(CMSIS_DIR)/
INC += -I$(HAL_DIR)/inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc
#INC += -I$(USBHOST_DIR)
-INC += -I../lib/mp-readline
-INC += -I../lib/netutils
-INC += -I../lib/timeutils
CFLAGS_CORTEX_M = -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
CFLAGS_MCU_f4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_F4
CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 -DMCU_SERIES_F7
CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 -DMCU_SERIES_L4
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_MOD)
+CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD)
CFLAGS += -D$(CMSIS_MCU)
CFLAGS += $(CFLAGS_MCU_$(MCU_SERIES))
CFLAGS += $(COPT)
@@ -86,7 +83,7 @@ SRC_LIB = $(addprefix lib/,\
libm/atanf.c \
libm/atan2f.c \
libm/fmodf.c \
- libm/roundf.c \
+ libm/nearbyintf.c \
libm/log1pf.c \
libm/acoshf.c \
libm/asinhf.c \
diff --git a/stmhal/boards/LIMIFROG/mpconfigboard.h b/stmhal/boards/LIMIFROG/mpconfigboard.h
index 95fd6bf50..d04634ac3 100644
--- a/stmhal/boards/LIMIFROG/mpconfigboard.h
+++ b/stmhal/boards/LIMIFROG/mpconfigboard.h
@@ -37,13 +37,6 @@ void LIMIFROG_board_early_init(void);
#define MICROPY_HW_I2C1_SDA (pin_B9)
#define MICROPY_HW_I2C2_SCL (pin_B10)
#define MICROPY_HW_I2C2_SDA (pin_B11)
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
-// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
// SPI busses
#define MICROPY_HW_SPI1_NSS (pin_A4)
diff --git a/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h b/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
index 647525384..cafea136f 100644
--- a/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
+++ b/stmhal/boards/NUCLEO_F767ZI/mpconfigboard.h
@@ -52,11 +52,6 @@
#define MICROPY_HW_I2C3_SCL (pin_H7)
#define MICROPY_HW_I2C3_SDA (pin_H8)
-// TODO These should go in i2c.c
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
-
// SPI
#define MICROPY_HW_SPI3_NSS (pin_A4)
#define MICROPY_HW_SPI3_SCK (pin_B3)
diff --git a/stmhal/boards/NUCLEO_F767ZI/pins.csv b/stmhal/boards/NUCLEO_F767ZI/pins.csv
index f9f743489..897b1473e 100644
--- a/stmhal/boards/NUCLEO_F767ZI/pins.csv
+++ b/stmhal/boards/NUCLEO_F767ZI/pins.csv
@@ -1,25 +1,35 @@
-A0,PA0
-A1,PF10
-A2,PF9
-A3,PF8
-A4,PF7
-A5,PF6
-D0,PC7
-D1,PC6
-D2,PG6
-D3,PB4
-D4,PG7
-D5,PA8
-D6,PH6
-D7,PI3
-D8,PI2
-D9,PA15
-D10,PI0
-D11,PB15
-D12,PB14
-D13,PI1
+A0,PA3
+A1,PC0
+A2,PC3
+A3,PF3
+A4,PF5
+A5,PF10
+D0,PG9
+D1,PG14
+D2,PF15
+D3,PE13
+D4,PF14
+D5,PE11
+D6,PE9
+D7,PF13
+D8,PF12
+D9,PD15
+D10,PD14
+D11,PA7
+D12,PA6
+D13,PA5
D14,PB9
D15,PB8
+D16,PC6
+D17,PB15
+D18,PB13
+D19,PB12
+D20,PA15
+D21,PC7
+D22,PB5
+D23,PB3
+D24,PA4
+D25,PB4
LED1,PB0
LED2,PB7
LED3,PB14
diff --git a/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h b/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
index 181580b14..f2474619f 100644
--- a/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
+++ b/stmhal/boards/NUCLEO_L476RG/mpconfigboard.h
@@ -21,10 +21,6 @@
#define MICROPY_HW_UART_REPL PYB_UART_2
#define MICROPY_HW_UART_REPL_BAUD 115200
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
-
#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_4
// I2C busses
diff --git a/stmhal/boards/STM32F769DISC/mpconfigboard.h b/stmhal/boards/STM32F769DISC/mpconfigboard.h
index a4cbcc520..50b9c1618 100644
--- a/stmhal/boards/STM32F769DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F769DISC/mpconfigboard.h
@@ -1,4 +1,5 @@
-//This board is only confirmed to operate using openocd.
+// This board is confirmed to operate using stlink and openocd.
+// REPL is on UART(1) and is available through the stlink USB-UART device.
// To use openocd run "OPENOCD_CONFIG=boards/openocd_stm32f7.cfg" in
// the make command.
#define MICROPY_HW_BOARD_NAME "F769DISC"
@@ -42,11 +43,6 @@
#define MICROPY_HW_I2C3_SCL (pin_H7)
#define MICROPY_HW_I2C3_SDA (pin_H8)
-// TODO These should go in i2c.c
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
-
// SPI
#define MICROPY_HW_SPI2_NSS (pin_A11)
#define MICROPY_HW_SPI2_SCK (pin_A12)
@@ -54,7 +50,7 @@
#define MICROPY_HW_SPI2_MOSI (pin_B15)
// USRSW is pulled low. Pressing the button makes the input go high.
-#define MICROPY_HW_USRSW_PIN (pin_I11)
+#define MICROPY_HW_USRSW_PIN (pin_A0)
#define MICROPY_HW_USRSW_PULL (GPIO_NOPULL)
#define MICROPY_HW_USRSW_EXTI_MODE (GPIO_MODE_IT_RISING)
#define MICROPY_HW_USRSW_PRESSED (1)
@@ -67,6 +63,12 @@
#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin))
// SD card detect switch
+#define MICROPY_HW_SDMMC2_CK (pin_D6)
+#define MICROPY_HW_SDMMC2_CMD (pin_D7)
+#define MICROPY_HW_SDMMC2_D0 (pin_G9)
+#define MICROPY_HW_SDMMC2_D1 (pin_G10)
+#define MICROPY_HW_SDMMC2_D2 (pin_B3)
+#define MICROPY_HW_SDMMC2_D3 (pin_B4)
#define MICROPY_HW_SDCARD_DETECT_PIN (pin_I15)
#define MICROPY_HW_SDCARD_DETECT_PULL (GPIO_PULLUP)
#define MICROPY_HW_SDCARD_DETECT_PRESENT (GPIO_PIN_RESET)
diff --git a/stmhal/boards/STM32F769DISC/mpconfigboard.mk b/stmhal/boards/STM32F769DISC/mpconfigboard.mk
index 2e1e9952b..b65a18afb 100644
--- a/stmhal/boards/STM32F769DISC/mpconfigboard.mk
+++ b/stmhal/boards/STM32F769DISC/mpconfigboard.mk
@@ -1,4 +1,4 @@
MCU_SERIES = f7
CMSIS_MCU = STM32F769xx
-AF_FILE = boards/stm32f769_af.csv
+AF_FILE = boards/stm32f767_af.csv
LD_FILE = boards/stm32f769.ld
diff --git a/stmhal/boards/STM32F769DISC/pins.csv b/stmhal/boards/STM32F769DISC/pins.csv
index e59a51387..dcc2df208 100644
--- a/stmhal/boards/STM32F769DISC/pins.csv
+++ b/stmhal/boards/STM32F769DISC/pins.csv
@@ -33,12 +33,12 @@ AUDIO_SCL,PH7
EXT_SDA,PB9
EXT_SCL,PB8
EXT_RST,PG3
-SD_D0,PC8
-SD_D1,PC9
-SD_D2,PC10
-SD_D3,PC11
-SD_CK,PC12
-SD_CMD,PD2
+SD_D0,PG9
+SD_D1,PG10
+SD_D2,PB3
+SD_D3,PB4
+SD_CK,PD6
+SD_CMD,PD7
SD_SW,PI15
LCD_BL_CTRL,PK3
LCD_INT,PI13
diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h
index 38665055f..44a39c0a1 100644
--- a/stmhal/boards/STM32F7DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h
@@ -51,16 +51,6 @@ void STM32F7DISC_board_early_init(void);
#define MICROPY_HW_I2C3_SCL (pin_H7)
#define MICROPY_HW_I2C3_SDA (pin_H8)
-// The STM32F7 uses a TIMINGR register which is configured using an Excel
-// Spreadsheet from AN4235: http://www.st.com/web/en/catalog/tools/PF258335
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
-// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
-
// SPI
#define MICROPY_HW_SPI2_NSS (pin_I0)
#define MICROPY_HW_SPI2_SCK (pin_I1)
diff --git a/stmhal/boards/STM32L476DISC/mpconfigboard.h b/stmhal/boards/STM32L476DISC/mpconfigboard.h
index a93b486c6..258a86b60 100644
--- a/stmhal/boards/STM32L476DISC/mpconfigboard.h
+++ b/stmhal/boards/STM32L476DISC/mpconfigboard.h
@@ -47,13 +47,6 @@ void STM32L476DISC_board_early_init(void);
#define MICROPY_HW_I2C1_SDA (pin_B7)
#define MICROPY_HW_I2C2_SCL (pin_B10)
#define MICROPY_HW_I2C2_SDA (pin_B11)
-// We use an array of baudrates and corresponding TIMINGR values.
-//
-// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
-// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
-#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 100000
-#define MICROPY_HW_I2C_BAUDRATE_MAX 100000
// SPI busses
#define MICROPY_HW_SPI2_NSS (pin_D0)
diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py
index b33c92edc..371ac77dd 100755
--- a/stmhal/boards/make-pins.py
+++ b/stmhal/boards/make-pins.py
@@ -14,7 +14,8 @@ SUPPORTED_FN = {
'I2S' : ['CK', 'MCK', 'SD', 'WS', 'EXTSD'],
'USART' : ['RX', 'TX', 'CTS', 'RTS', 'CK'],
'UART' : ['RX', 'TX', 'CTS', 'RTS'],
- 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI']
+ 'SPI' : ['NSS', 'SCK', 'MISO', 'MOSI'],
+ 'SDMMC' : ['CK', 'CMD', 'D0', 'D1', 'D2', 'D3'],
}
CONDITIONAL_VAR = {
@@ -23,6 +24,7 @@ CONDITIONAL_VAR = {
'SPI' : 'MICROPY_HW_SPI{num}_SCK',
'UART' : 'MICROPY_HW_UART{num}_TX',
'USART' : 'MICROPY_HW_UART{num}_TX',
+ 'SDMMC' : 'MICROPY_HW_SDMMC{num}_CK',
}
def parse_port_pin(name_str):
diff --git a/stmhal/boards/stm32f767_af.csv b/stmhal/boards/stm32f767_af.csv
index eabc9ab3b..db27818c6 100644
--- a/stmhal/boards/stm32f767_af.csv
+++ b/stmhal/boards/stm32f767_af.csv
@@ -1,11 +1,11 @@
Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15
-,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/OTG2_HS/OTG1_FS,ETH/OTG1_FS,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS
+,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/SDMMC2/OTG2_HS/OTG1_FS,SDMMC2/ETH,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS
PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT
PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT
PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,LCD_R1,EVENTOUT
PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT
PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT
-PortA,PA5,,TIM2_CH1/TIM2_ETR,TIM8_CH1N,SPI1_SCK/I2S1_CK,,,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT
+PortA,PA5,,TIM2_CH1/TIM2_ETR,,TIM8_CH1N,,SPI1_SCK/I2S1_CK,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT
PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT
PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT
PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT
@@ -19,27 +19,27 @@ PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMICE,CSPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,U
PortB,PB0,,TIM1_CH2N,TIM3_CH3T,IM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT
PortB,PB1,,TIM1_CH3N,TIM3_CH4T,IM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT
PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT
-PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT
-PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT
+PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,SDMMC2_D2,,,,,EVENTOUT
+PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,SDMMC2_D3,,,,,EVENTOUT
PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT
PortB,PB6,,,TIM4_CH1,HDMICEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT
PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT
-PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT
-PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT
+PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,SDMMC2_D4,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT
+PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,SDMMC2_D5,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT
PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT
PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT
PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT
PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT
-PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT
-PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT
+PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,SDMMC2_D0,,OTG_HS_DM,,,EVENTOUT
+PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,SDMMC2_D1,,OTG_HS_DP,,,EVENTOUT
PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT
PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,ETH_MDC,,,,EVENTOUT
PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT
PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT
PortC,PC4,,,,,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT
PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT
-PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT
-PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT
+PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,SDMMC2_D6,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT
+PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,SDMMC2_D7,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT
PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,DCMI_D2,,EVENTOUT
PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,DCMI_D3,,EVENTOUT
PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT
@@ -54,8 +54,8 @@ PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT
PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT
PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT
PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT
-PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT
-PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,,FMC_NE1,,,EVENTOUT
+PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,SDMMC2_CK,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT
+PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,SDMMC2_CMD,FMC_NE1,,,EVENTOUT
PortD,PD8,,,,,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT
PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT
PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT
@@ -105,10 +105,10 @@ PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT
PortG,PG6,,,,,,,,,,,,,,DCMI_D12,LCD_R7,EVENTOUT
PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT
PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT
-PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT
-PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT
-PortG,PG11,,,,,,,,SPDIFRX_IN0,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT
-PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT
+PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,SDMMC2_D0,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT
+PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,SDMMC2_D1,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT
+PortG,PG11,,,,,,,,SPDIFRX_IN0,,,SDMMC2_D2,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT
+PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,SDMMC2_D3,FMC_NE4,,LCD_B1,EVENTOUT
PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT
PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT
PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT
@@ -168,4 +168,3 @@ PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT
PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT
PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT
PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT
-
diff --git a/stmhal/boards/stm32f769_af.csv b/stmhal/boards/stm32f769_af.csv
deleted file mode 100644
index eabc9ab3b..000000000
--- a/stmhal/boards/stm32f769_af.csv
+++ /dev/null
@@ -1,171 +0,0 @@
-Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15
-,,SYS,TIM1/2,TIM3/4/5,TIM8/9/10/11/LPTIM1/CEC,I2C1/2/3/4/CEC,SPI1/2/3/4/5/6,SPI3/SAI1,SPI2/3/USART1/2/3/UART5/SPDIFRX,SAI2/USART6/UART4/5/7/8/SPDIFRX,CAN1/2/TIM12/13/14/QUADSPI/LCD,SAI2/QUADSPI/OTG2_HS/OTG1_FS,ETH/OTG1_FS,FMC/SDMMC1/OTG2_FS,DCMI,LCD,SYS
-PortA,PA0,,TIM2_CH1/TIM2_ETR,TIM5_CH1,TIM8_ETR,,,,USART2_CTS,UART4_TX,,SAI2_SD_B,ETH_MII_CRS,,,,EVENTOUT
-PortA,PA1,,TIM2_CH2,TIM5_CH2,,,,,USART2_RTS,UART4_RX,QUADSPI_BK1_IO3,SAI2_MCK_B,ETH_MII_RX_CLK/ETH_RMII_REF_CLK,,,LCD_R2,EVENTOUT
-PortA,PA2,,TIM2_CH3,TIM5_CH3,TIM9_CH1,,,,USART2_TX,SAI2_SCK_B,,,ETH_MDIO,,,LCD_R1,EVENTOUT
-PortA,PA3,,TIM2_CH4,TIM5_CH4,TIM9_CH2,,,,USART2_RX,,,OTG_HS_ULPI_D0,ETH_MII_COL,,,LCD_B5,EVENTOUT
-PortA,PA4,,,,,,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,USART2_CK,,,,,OTG_HS_SOF,DCMI_HSYNC,LCD_VSYNC,EVENTOUT
-PortA,PA5,,TIM2_CH1/TIM2_ETR,TIM8_CH1N,SPI1_SCK/I2S1_CK,,,,,,,OTG_HS_ULPI_CK,,,,LCD_R4,EVENTOUT
-PortA,PA6,,TIM1_BKIN,TIM3_CH1,TIM8_BKIN,,SPI1_MISO,,,,TIM13_CH1,,,,DCMI_PIXCLK,LCD_G2,EVENTOUT
-PortA,PA7,,TIM1_CH1N,TIM3_CH2,TIM8_CH1N,,SPI1_MOSI/I2S1_SD,,,,TIM14_CH1,,ETH_MII_RX_DV/ETH_RMII_CRS_DV,FMC_SDNWE,,,EVENTOUT
-PortA,PA8,MCO1,TIM1_CH1,,TIM8_BKIN2,I2C3_SCL,,,USART1_CK,,,OTG_FS_SOF,,,,LCD_R6,EVENTOUT
-PortA,PA9,,TIM1_CH2,,,I2C3_SMBA,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,DCMI_D0,,EVENTOUT
-PortA,PA10,,TIM1_CH3,,,,,,USART1_RX,,,OTG_FS_ID,,,DCMI_D1,,EVENTOUT
-PortA,PA11,,TIM1_CH4,,,,,,USART1_CTS,,CAN1_RX,OTG_FS_DM,,,,LCD_R4,EVENTOUT
-PortA,PA12,,TIM1_ETR,,,,,,USART1_RTS,SAI2_FS_B,CAN1_TX,OTG_FS_DP,,,,LCD_R5,EVENTOUT
-PortA,PA13,JTMS,SWDIO,,,,,,,,,,,,,,EVENTOUT
-PortA,PA14,JTCK,SWCLK,,,,,,,,,,,,,,EVENTOUT
-PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMICE,CSPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT
-PortB,PB0,,TIM1_CH2N,TIM3_CH3T,IM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT
-PortB,PB1,,TIM1_CH3N,TIM3_CH4T,IM8_CH3N,,,,,,LCD_R6,OTG_HS_ULPI_D2,ETH_MII_RXD3,,,,EVENTOUT
-PortB,PB2,,,,,,,SAI1_SD_A,SPI3_MOSI/I2S3_SD,,QUADSPI_CLK,,,,,,EVENTOUT
-PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK/I2S1_CK,SPI3_SCK/I2S3_CK,,,,,,,,,EVENTOUT
-PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,,,,,,EVENTOUT
-PortB,PB5,,,TIM3_CH2,,I2C1_SMBA,SPI1_MOSI/I2S1_SD,SPI3_MOSI/I2S3_SD,,,CAN2_RX,OTG_HS_ULPI_D7,ETH_PPS_OUT,FMC_SDCKE1,DCMI_D10,,EVENTOUT
-PortB,PB6,,,TIM4_CH1,HDMICEC,I2C1_SCL,,,USART1_TX,,CAN2_TX,QUADSPI_BK1_NCS,,FMC_SDNE1,DCMI_D5,,EVENTOUT
-PortB,PB7,,,TIM4_CH2,,I2C1_SDA,,,USART1_RX,,,,,FMC_NL,DCMI_VSYNC,,EVENTOUT
-PortB,PB8,,,TIM4_CH3,TIM10_CH1,I2C1_SCL,,,,,CAN1_RX,,ETH_MII_TXD3,SDMMC1_D4,DCMI_D6,LCD_B6,EVENTOUT
-PortB,PB9,,,TIM4_CH4,TIM11_CH1,I2C1_SDA,SPI2_NSS/I2S2_WS,,,,CAN1_TX,,,SDMMC1_D5,DCMI_D7,LCD_B7,EVENTOUT
-PortB,PB10,,TIM2_CH3,,,I2C2_SCL,SPI2_SCK/I2S2_CK,,USART3_TX,,,OTG_HS_ULPI_D3,ETH_MII_RX_ER,,,LCD_G4,EVENTOUT
-PortB,PB11,,TIM2_CH4,,,I2C2_SDA,,,USART3_RX,,,OTG_HS_ULPI_D4,ETH_MII_TX_EN/ETH_RMII_TX_EN,,,LCD_G5,EVENTOUT
-PortB,PB12,,TIM1_BKIN,,,I2C2_SMBA,SPI2_NSS/I2S2_WS,,USART3_CK,,CAN2_RX,OTG_HS_ULPI_D5,ETH_MII_TXD0/ETH_RMII_TXD0,OTG_HS_ID,,,EVENTOUT
-PortB,PB13,,TIM1_CH1N,,,,SPI2_SCK/I2S2_CK,,USART3_CTS,,CAN2_TX,OTG_HS_ULPI_D6,ETH_MII_TXD1/ETH_RMII_TXD1,,,,EVENTOUT
-PortB,PB14,,TIM1_CH2N,,TIM8_CH2N,,SPI2_MISO,,USART3_RTS,,TIM12_CH1,,,OTG_HS_DM,,,EVENTOUT
-PortB,PB15,RTC_REFIN,TIM1_CH3N,,TIM8_CH3N,,SPI2_MOSI/I2S2_SD,,,,TIM12_CH2,,,OTG_HS_DP,,,EVENTOUT
-PortC,PC0,,,,,,,,,SAI2_FS_B,,OTG_HS_ULPI_STP,,FMC_SDNWE,,LCD_R5,EVENTOUT
-PortC,PC1,TRACED0,,,,,SPI2_MOSI/I2S2_SD,SAI1_SD_A,,,,,ETH_MDC,,,,EVENTOUT
-PortC,PC2,,,,,,SPI2_MISO,,,,,OTG_HS_ULPI_DIR,ETH_MII_TXD2,FMC_SDNE0,,,EVENTOUT
-PortC,PC3,,,,,,SPI2_MOSI/I2S2_SD,,,,,OTG_HS_ULPI_NXT,ETH_MII_TX_CLK,FMC_SDCKE0,,,EVENTOUT
-PortC,PC4,,,,,,I2S1_MCK,,,SPDIFRX_IN2,,,ETH_MII_RXD0/ETH_RMII_RXD0,FMC_SDNE0,,,EVENTOUT
-PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,EVENTOUT
-PortC,PC6,,,TIM3_CH1,TIM8_CH1,,I2S2_MCK,,,USART6_TX,,,,SDMMC1_D6,DCMI_D0,LCD_HSYNC,EVENTOUT
-PortC,PC7,,,TIM3_CH2,TIM8_CH2,,,I2S3_MCK,,USART6_RX,,,,SDMMC1_D7,DCMI_D1,LCD_G6,EVENTOUT
-PortC,PC8,TRACED1,,TIM3_CH3,TIM8_CH3,,,,UART5_RTS,USART6_CK,,,,SDMMC1_D0,DCMI_D2,,EVENTOUT
-PortC,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S_CKIN,,UART5_CTS,,QUADSPI_BK1_IO0,,,SDMMC1_D1,DCMI_D3,,EVENTOUT
-PortC,PC10,,,,,,,SPI3_SCK/I2S3_CK,USART3_TX,UART4_TX,QUADSPI_BK1_IO1,,,SDMMC1_D2,DCMI_D8,LCD_R2,EVENTOUT
-PortC,PC11,,,,,,,SPI3_MISO,USART3_RX,UART4_RX,QUADSPI_BK2_NCS,,,SDMMC1_D3,DCMI_D4,,EVENTOUT
-PortC,PC12,TRACED3,,,,,,SPI3_MOSI/I2S3_SD,USART3_CK,UART5_TX,,,,SDMMC1_CK,DCMI_D9,,EVENTOUT
-PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT
-PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT
-PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT
-PortD,PD0,,,,,,,,,,CAN1_RX,,,FMC_D2,,,EVENTOUT
-PortD,PD1,,,,,,,,,,CAN1_TX,,,FMC_D3,,,EVENTOUT
-PortD,PD2,TRACED2,,TIM3_ETR,,,,,,UART5_RX,,,,SDMMC1_CMD,DCMI_D11,,EVENTOUT
-PortD,PD3,,,,,,SPI2_SCK/I2S2_CK,,USART2_CTS,,,,,FMC_CLK,DCMI_D5,LCD_G7,EVENTOUT
-PortD,PD4,,,,,,,,USART2_RTS,,,,,FMC_NOE,,,EVENTOUT
-PortD,PD5,,,,,,,,USART2_TX,,,,,FMC_NWE,,,EVENTOUT
-PortD,PD6,,,,,,SPI3_MOSI/I2S3_SD,SAI1_SD_A,USART2_RX,,,,,FMC_NWAIT,DCMI_D10,LCD_B2,EVENTOUT
-PortD,PD7,,,,,,,,USART2_CK,SPDIFRX_IN0,,,,FMC_NE1,,,EVENTOUT
-PortD,PD8,,,,,,,,USART3_TX,SPDIFRX_IN1,,,,FMC_D13,,,EVENTOUT
-PortD,PD9,,,,,,,,USART3_RX,,,,,FMC_D14,,,EVENTOUT
-PortD,PD10,,,,,,,,USART3_CK,,,,,FMC_D15,,LCD_B3,EVENTOUT
-PortD,PD11,,,,,I2C4_SMBA,,,USART3_CTS,,QUADSPI_BK1_IO0,SAI2_SD_A,,FMC_A16/FMC_CLE,,,EVENTOUT
-PortD,PD12,,,TIM4_CH1,LPTIM1_IN1,I2C4_SCL,,,USART3_RTS,,QUADSPI_BK1_IO1,SAI2_FS_A,,FMC_A17/FMC_ALE,,,EVENTOUT
-PortD,PD13,,,TIM4_CH2,LPTIM1_OUT,I2C4_SDA,,,,,QUADSPI_BK1_IO3,SAI2_SCK_A,,FMC_A18,,,EVENTOUT
-PortD,PD14,,,TIM4_CH3,,,,,,UART8_CTS,,,,FMC_D0,,,EVENTOUT
-PortD,PD15,,,TIM4_CH4,,,,,,UART8_RTS,,,,FMC_D1,,,EVENTOUT
-PortE,PE0,,,TIM4_ETR,LPTIM1_ETR,,,,,UART8_RX,,SAI2_MCK_A,,FMC_NBL0,DCMI_D2,,EVENTOUT
-PortE,PE1,,,,LPTIM1_IN2,,,,,UART8_TX,,,,FMC_NBL1,DCMI_D3,,EVENTOUT
-PortE,PE2,TRACECLK,,,,,SPI4_SCK,SAI1_MCLK_A,,,QUADSPI_BK1_IO2,,ETH_MII_TXD3,FMC_A23,,,EVENTOUT
-PortE,PE3,TRACED0,,,,,,SAI1_SD_B,,,,,,FMC_A19,,,EVENTOUT
-PortE,PE4,TRACED1,,,,,SPI4_NSS,SAI1_FS_A,,,,,,FMC_A20,DCMI_D4,LCD_B0,EVENTOUT
-PortE,PE5,TRACED2,,,TIM9_CH1,,SPI4_MISO,SAI1_SCK_A,,,,,,FMC_A21,DCMI_D6,LCD_G0,EVENTOUT
-PortE,PE6,TRACED3,TIM1_BKIN2,,TIM9_CH2,,SPI4_MOSI,SAI1_SD_A,,,,SAI2_MCK_B,,FMC_A22,DCMI_D7,LCD_G1,EVENTOUT
-PortE,PE7,,TIM1_ETR,,,,,,,UART7_RX,,QUADSPI_BK2_IO0,,FMC_D4,,,EVENTOUT
-PortE,PE8,,TIM1_CH1N,,,,,,,UART7_TX,,QUADSPI_BK2_IO1,,FMC_D5,,,EVENTOUT
-PortE,PE9,,TIM1_CH1,,,,,,,UART7_RTS,,QUADSPI_BK2_IO2,,FMC_D6,,,EVENTOUT
-PortE,PE10,,TIM1_CH2N,,,,,,,UART7_CTS,,QUADSPI_BK2_IO3,,FMC_D7,,,EVENTOUT
-PortE,PE11,,TIM1_CH2,,,,SPI4_NSS,,,,,SAI2_SD_B,,FMC_D8,,LCD_G3,EVENTOUT
-PortE,PE12,,TIM1_CH3N,,,,SPI4_SCK,,,,,SAI2_SCK_B,,FMC_D9,,LCD_B4,EVENTOUT
-PortE,PE13,,TIM1_CH3,,,,SPI4_MISO,,,,,SAI2_FS_B,,FMC_D10,,LCD_DE,EVENTOUT
-PortE,PE14,,TIM1_CH4,,,,SPI4_MOSI,,,,,SAI2_MCK_B,,FMC_D11,,LCD_CLK,EVENTOUT
-PortE,PE15,,TIM1_BKIN,,,,,,,,,,,FMC_D12,,LCD_R7,EVENTOUT
-PortF,PF0,,,,,I2C2_SDA,,,,,,,,FMC_A0,,,EVENTOUT
-PortF,PF1,,,,,I2C2_SCL,,,,,,,,FMC_A1,,,EVENTOUT
-PortF,PF2,,,,,I2C2_SMBA,,,,,,,,FMC_A2,,,EVENTOUT
-PortF,PF3,,,,,,,,,,,,,FMC_A3,,,EVENTOUT
-PortF,PF4,,,,,,,,,,,,,FMC_A4,,,EVENTOUT
-PortF,PF5,,,,,,,,,,,,,FMC_A5,,,EVENTOUT
-PortF,PF6,,,,TIM10_CH1,,SPI5_NSS,SAI1_SD_B,,UART7_RX,QUADSPI_BK1_IO3,,,,,,EVENTOUT
-PortF,PF7,,,,TIM11_CH1,,SPI5_SCK,SAI1_MCLK_B,,UART7_TX,QUADSPI_BK1_IO2,,,,,,EVENTOUT
-PortF,PF8,,,,,,SPI5_MISO,SAI1_SCK_B,,UART7_RTS,TIM13_CH1,QUADSPI_BK1_IO0,,,,,EVENTOUT
-PortF,PF9,,,,,,SPI5_MOSI,SAI1_FS_B,,UART7_CTS,TIM14_CH1,QUADSPI_BK1_IO1,,,,,EVENTOUT
-PortF,PF10,,,,,,,,,,,,,,DCMI_D11,LCD_DE,EVENTOUT
-PortF,PF11,,,,,,SPI5_MOSI,,,,,SAI2_SD_B,,FMC_SDNRAS,DCMI_D12,,EVENTOUT
-PortF,PF12,,,,,,,,,,,,,FMC_A6,,,EVENTOUT
-PortF,PF13,,,,,I2C4_SMBA,,,,,,,,FMC_A7,,,EVENTOUT
-PortF,PF14,,,,,I2C4_SCL,,,,,,,,FMC_A8,,,EVENTOUT
-PortF,PF15,,,,,I2C4_SDA,,,,,,,,FMC_A9,,,EVENTOUT
-PortG,PG0,,,,,,,,,,,,,FMC_A10,,,EVENTOUT
-PortG,PG1,,,,,,,,,,,,,FMC_A11,,,EVENTOUT
-PortG,PG2,,,,,,,,,,,,,FMC_A12,,,EVENTOUT
-PortG,PG3,,,,,,,,,,,,,FMC_A13,,,EVENTOUT
-PortG,PG4,,,,,,,,,,,,,FMC_A14/FMC_BA0,,,EVENTOUT
-PortG,PG5,,,,,,,,,,,,,FMC_A15/FMC_BA1,,,EVENTOUT
-PortG,PG6,,,,,,,,,,,,,,DCMI_D12,LCD_R7,EVENTOUT
-PortG,PG7,,,,,,,,,USART6_CK,,,,FMC_INT,DCMI_D13,LCD_CLK,EVENTOUT
-PortG,PG8,,,,,,SPI6_NSS,,SPDIFRX_IN2,USART6_RTS,,,ETH_PPS_OUT,FMC_SDCLK,,,EVENTOUT
-PortG,PG9,,,,,,,,SPDIFRX_IN3,USART6_RX,QUADSPI_BK2_IO2,SAI2_FS_B,,FMC_NE2/FMC_NCE,DCMI_VSYNC,,EVENTOUT
-PortG,PG10,,,,,,,,,,LCD_G3,SAI2_SD_B,,FMC_NE3,DCMI_D2,LCD_B2,EVENTOUT
-PortG,PG11,,,,,,,,SPDIFRX_IN0,,,,ETH_MII_TX_EN/ETH_RMII_TX_EN,,DCMI_D3,LCD_B3,EVENTOUT
-PortG,PG12,,,,LPTIM1_IN1,,SPI6_MISO,,SPDIFRX_IN1,USART6_RTS,LCD_B4,,,FMC_NE4,,LCD_B1,EVENTOUT
-PortG,PG13,TRACED0,,,LPTIM1_OUT,,SPI6_SCK,,,USART6_CTS,,,ETH_MII_TXD0/ETH_RMII_TXD0,FMC_A24,,LCD_R0,EVENTOUT
-PortG,PG14,TRACED1,,,LPTIM1_ETR,,SPI6_MOSI,,,USART6_TX,QUADSPI_BK2_IO3,,ETH_MII_TXD1/ETH_RMII_TXD1,FMC_A25,,LCD_B0,EVENTOUT
-PortG,PG15,,,,,,,,,USART6_CTS,,,,FMC_SDNCAS,DCMI_D13,,EVENTOUT
-PortH,PH0,,,,,,,,,,,,,,,,EVENTOUT
-PortH,PH1,,,,,,,,,,,,,,,,EVENTOUT
-PortH,PH2,,,,LPTIM1_IN2,,,,,,QUADSPI_BK2_IO0,SAI2_SCK_B,ETH_MII_CRS,FMC_SDCKE0,,LCD_R0,EVENTOUT
-PortH,PH3,,,,,,,,,,QUADSPI_BK2_IO1,SAI2_MCK_B,ETH_MII_COL,FMC_SDNE0,,LCD_R1,EVENTOUT
-PortH,PH4,,,,,I2C2_SCL,,,,,,OTG_HS_ULPI_NXT,,,,,EVENTOUT
-PortH,PH5,,,,,I2C2_SDA,SPI5_NSS,,,,,,,FMC_SDNWE,,,EVENTOUT
-PortH,PH6,,,,,I2C2_SMBA,SPI5_SCK,,,,TIM12_CH1,,ETH_MII_RXD2,FMC_SDNE1,DCMI_D8,,EVENTOUT
-PortH,PH7,,,,,I2C3_SCL,SPI5_MISO,,,,,,ETH_MII_RXD3,FMC_SDCKE1,DCMI_D9,,EVENTOUT
-PortH,PH8,,,,,I2C3_SDA,,,,,,,,FMC_D16,DCMI_HSYNC,LCD_R2,EVENTOUT
-PortH,PH9,,,,,I2C3_SMBA,,,,,TIM12_CH2,,,FMC_D17,DCMI_D0,LCD_R3,EVENTOUT
-PortH,PH10,,,TIM5_CH1,,I2C4_SMBA,,,,,,,,FMC_D18,DCMI_D1,LCD_R4,EVENTOUT
-PortH,PH11,,,TIM5_CH2,,I2C4_SCL,,,,,,,,FMC_D19,DCMI_D2,LCD_R5,EVENTOUT
-PortH,PH12,,,TIM5_CH3,,I2C4_SDA,,,,,,,,FMC_D20,DCMI_D3,LCD_R6,EVENTOUT
-PortH,PH13,,,,TIM8_CH1N,,,,,,CAN1_TX,,,FMC_D21,,LCD_G2,EVENTOUT
-PortH,PH14,,,,TIM8_CH2N,,,,,,,,,FMC_D22,DCMI_D4,LCD_G3,EVENTOUT
-PortH,PH15,,,,TIM8_CH3N,,,,,,,,,FMC_D23,DCMI_D11,LCD_G4,EVENTOUT
-PortI,PI0,,,TIM5_CH4,,,SPI2_NSS/I2S2_WS,,,,,,,FMC_D24,DCMI_D13,LCD_G5,EVENTOUT
-PortI,PI1,,,,TIM8_BKIN2,,SPI2_SCK/I2S2_CK,,,,,,,FMC_D25,DCMI_D8,LCD_G6,EVENTOUT
-PortI,PI2,,,,TIM8_CH4,,SPI2_MISO,,,,,,,FMC_D26,DCMI_D9,LCD_G7,EVENTOUT
-PortI,PI3,,,,TIM8_ETR,,SPI2_MOSI/I2S2_SD,,,,,,,FMC_D27,DCMI_D10,,EVENTOUT
-PortI,PI4,,,,TIM8_BKIN,,,,,,,SAI2_MCK_A,,FMC_NBL2,DCMI_D5,LCD_B4,EVENTOUT
-PortI,PI5,,,,TIM8_CH1,,,,,,,SAI2_SCK_A,,FMC_NBL3,DCMI_VSYNC,LCD_B5,EVENTOUT
-PortI,PI6,,,,TIM8_CH2,,,,,,,SAI2_SD_A,,FMC_D28,DCMI_D6,LCD_B6,EVENTOUT
-PortI,PI7,,,,TIM8_CH3,,,,,,,SAI2_FS_A,,FMC_D29,DCMI_D7,LCD_B7,EVENTOUT
-PortI,PI8,,,,,,,,,,,,,,,,EVENTOUT
-PortI,PI9,,,,,,,,,,CAN1_RX,,,FMC_D30,,LCD_VSYNC,EVENTOUT
-PortI,PI10,,,,,,,,,,,,ETH_MII_RX_ER,FMC_D31,,LCD_HSYNC,EVENTOUT
-PortI,PI11,,,,,,,,,,,OTG_HS_ULPI_DIR,,,,,EVENTOUT
-PortI,PI12,,,,,,,,,,,,,,,LCD_HSYNC,EVENTOUT
-PortI,PI13,,,,,,,,,,,,,,,LCD_VSYNC,EVENTOUT
-PortI,PI14,,,,,,,,,,,,,,,LCD_CLK,EVENTOUT
-PortI,PI15,,,,,,,,,,,,,,,LCD_R0,EVENTOUT
-PortJ,PJ0,,,,,,,,,,,,,,,LCD_R1,EVENTOUT
-PortJ,PJ1,,,,,,,,,,,,,,,LCD_R2,EVENTOUT
-PortJ,PJ2,,,,,,,,,,,,,,,LCD_R3,EVENTOUT
-PortJ,PJ3,,,,,,,,,,,,,,,LCD_R4,EVENTOUT
-PortJ,PJ4,,,,,,,,,,,,,,,LCD_R5,EVENTOUT
-PortJ,PJ5,,,,,,,,,,,,,,,LCD_R6,EVENTOUT
-PortJ,PJ6,,,,,,,,,,,,,,,LCD_R7,EVENTOUT
-PortJ,PJ7,,,,,,,,,,,,,,,LCD_G0,EVENTOUT
-PortJ,PJ8,,,,,,,,,,,,,,,LCD_G1,EVENTOUT
-PortJ,PJ9,,,,,,,,,,,,,,,LCD_G2,EVENTOUT
-PortJ,PJ10,,,,,,,,,,,,,,,LCD_G3,EVENTOUT
-PortJ,PJ11,,,,,,,,,,,,,,,LCD_G4,EVENTOUT
-PortJ,PJ12,,,,,,,,,,,,,,,LCD_B0,EVENTOUT
-PortJ,PJ13,,,,,,,,,,,,,,,LCD_B1,EVENTOUT
-PortJ,PJ14,,,,,,,,,,,,,,,LCD_B2,EVENTOUT
-PortJ,PJ15,,,,,,,,,,,,,,,LCD_B3,EVENTOUT
-PortK,PK0,,,,,,,,,,,,,,,LCD_G5,EVENTOUT
-PortK,PK1,,,,,,,,,,,,,,,LCD_G6,EVENTOUT
-PortK,PK2,,,,,,,,,,,,,,,LCD_G7,EVENTOUT
-PortK,PK3,,,,,,,,,,,,,,,LCD_B4,EVENTOUT
-PortK,PK4,,,,,,,,,,,,,,,LCD_B5,EVENTOUT
-PortK,PK5,,,,,,,,,,,,,,,LCD_B6,EVENTOUT
-PortK,PK6,,,,,,,,,,,,,,,LCD_B7,EVENTOUT
-PortK,PK7,,,,,,,,,,,,,,,LCD_DE,EVENTOUT
-
diff --git a/stmhal/can.c b/stmhal/can.c
index e293b8742..09861ec73 100644
--- a/stmhal/can.c
+++ b/stmhal/can.c
@@ -631,8 +631,8 @@ STATIC mp_obj_t pyb_can_setfilter(mp_uint_t n_args, const mp_obj_t *pos_args, mp
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
- mp_uint_t len;
- mp_uint_t rtr_len;
+ size_t len;
+ size_t rtr_len;
mp_uint_t rtr_masks[4] = {0, 0, 0, 0};
mp_obj_t *rtr_flags;
mp_obj_t *params;
@@ -865,6 +865,7 @@ void can_rx_irq_handler(uint can_id, uint fifo_id) {
}
if (callback != mp_const_none) {
+ mp_sched_lock();
gc_lock();
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
@@ -877,6 +878,7 @@ void can_rx_irq_handler(uint can_id, uint fifo_id) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
gc_unlock();
+ mp_sched_unlock();
}
}
diff --git a/stmhal/dma.c b/stmhal/dma.c
index cf861fe12..04c874dc2 100644
--- a/stmhal/dma.c
+++ b/stmhal/dma.c
@@ -186,6 +186,9 @@ const dma_descr_t dma_I2C_1_TX = { DMA1_Stream6, DMA_CHANNEL_1, DMA_MEMORY_TO_PE
*/
// DMA2 streams
+#if defined(MCU_SERIES_F7) && defined(SDMMC2) && MICROPY_HW_HAS_SDCARD
+const dma_descr_t dma_SDMMC_2_RX= { DMA2_Stream0, DMA_CHANNEL_11, DMA_PERIPH_TO_MEMORY, dma_id_8, &dma_init_struct_sdio };
+#endif
const dma_descr_t dma_SPI_1_RX = { DMA2_Stream2, DMA_CHANNEL_3, DMA_PERIPH_TO_MEMORY, dma_id_10, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_5_RX = { DMA2_Stream3, DMA_CHANNEL_2, DMA_PERIPH_TO_MEMORY, dma_id_11, &dma_init_struct_spi_i2c };
#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
@@ -196,6 +199,9 @@ const dma_descr_t dma_SPI_5_TX = { DMA2_Stream4, DMA_CHANNEL_2, DMA_MEMORY_TO_PE
const dma_descr_t dma_SPI_4_TX = { DMA2_Stream4, DMA_CHANNEL_5, DMA_MEMORY_TO_PERIPH, dma_id_12, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_6_TX = { DMA2_Stream5, DMA_CHANNEL_1, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
const dma_descr_t dma_SPI_1_TX = { DMA2_Stream5, DMA_CHANNEL_3, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_spi_i2c };
+#if defined(MCU_SERIES_F7) && defined(SDMMC2) && MICROPY_HW_HAS_SDCARD
+const dma_descr_t dma_SDMMC_2_TX= { DMA2_Stream5, DMA_CHANNEL_11, DMA_MEMORY_TO_PERIPH, dma_id_13, &dma_init_struct_sdio };
+#endif
const dma_descr_t dma_SPI_6_RX = { DMA2_Stream6, DMA_CHANNEL_1, DMA_PERIPH_TO_MEMORY, dma_id_14, &dma_init_struct_spi_i2c };
#if defined(MICROPY_HW_HAS_SDCARD) && MICROPY_HW_HAS_SDCARD
const dma_descr_t dma_SDIO_0_TX= { DMA2_Stream6, DMA_CHANNEL_4, DMA_MEMORY_TO_PERIPH, dma_id_14, &dma_init_struct_sdio };
@@ -443,7 +449,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data){
} else {
// only necessary initialization
dma->State = HAL_DMA_STATE_READY;
-#if defined(MCU_SERIES_F4)
+#if defined(MCU_SERIES_F4) || defined(MCU_SERIES_F7)
// calculate DMA base address and bitshift to be used in IRQ handler
extern uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
DMA_CalcBaseAndBitshift(dma);
diff --git a/stmhal/dma.h b/stmhal/dma.h
index d9d771270..57b8f866d 100644
--- a/stmhal/dma.h
+++ b/stmhal/dma.h
@@ -45,6 +45,7 @@ extern const dma_descr_t dma_DAC_2_TX;
extern const dma_descr_t dma_SPI_3_TX;
extern const dma_descr_t dma_I2C_1_TX;
extern const dma_descr_t dma_I2C_2_TX;
+extern const dma_descr_t dma_SDMMC_2_RX;
extern const dma_descr_t dma_SPI_1_RX;
extern const dma_descr_t dma_SPI_5_RX;
extern const dma_descr_t dma_SDIO_0_RX;
@@ -53,6 +54,7 @@ extern const dma_descr_t dma_SPI_5_TX;
extern const dma_descr_t dma_SPI_4_TX;
extern const dma_descr_t dma_SPI_6_TX;
extern const dma_descr_t dma_SPI_1_TX;
+extern const dma_descr_t dma_SDMMC_2_TX;
extern const dma_descr_t dma_SPI_6_RX;
extern const dma_descr_t dma_SDIO_0_TX;
diff --git a/stmhal/extint.c b/stmhal/extint.c
index dacf8dd56..59b00cb73 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -28,7 +28,6 @@
#include <stddef.h>
#include <string.h>
-#include "py/nlr.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
@@ -412,6 +411,7 @@ void Handle_EXTI_Irq(uint32_t line) {
if (line < EXTI_NUM_VECTORS) {
mp_obj_t *cb = &MP_STATE_PORT(pyb_extint_callback)[line];
if (*cb != mp_const_none) {
+ mp_sched_lock();
// When executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
gc_lock();
@@ -427,6 +427,7 @@ void Handle_EXTI_Irq(uint32_t line) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
gc_unlock();
+ mp_sched_unlock();
}
}
}
diff --git a/stmhal/hal/f7/src/stm32f7xx_hal_dma.c b/stmhal/hal/f7/src/stm32f7xx_hal_dma.c
index 92f0d975c..df915ce52 100644
--- a/stmhal/hal/f7/src/stm32f7xx_hal_dma.c
+++ b/stmhal/hal/f7/src/stm32f7xx_hal_dma.c
@@ -149,7 +149,7 @@ typedef struct
* @{
*/
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
-static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
+uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma);
static HAL_StatusTypeDef DMA_CheckFifoParam(DMA_HandleTypeDef *hdma);
/**
@@ -1187,7 +1187,7 @@ static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t
* the configuration information for the specified DMA Stream.
* @retval Stream base address
*/
-static uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
+uint32_t DMA_CalcBaseAndBitshift(DMA_HandleTypeDef *hdma)
{
uint32_t stream_number = (((uint32_t)hdma->Instance & 0xFFU) - 16U) / 24U;
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 412a8e363..a3ded36ec 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -37,14 +37,6 @@
#include "dma.h"
#include "i2c.h"
-#if !defined(MICROPY_HW_I2C_BAUDRATE_DEFAULT)
-#define MICROPY_HW_I2C_BAUDRATE_DEFAULT 400000
-#endif
-
-#if !defined(MICROPY_HW_I2C_BAUDRATE_MAX)
-#define MICROPY_HW_I2C_BAUDRATE_MAX 400000
-#endif
-
/// \moduleref pyb
/// \class I2C - a two-wire serial protocol
///
@@ -134,10 +126,42 @@ const pyb_i2c_obj_t pyb_i2c_obj[] = {
#endif
};
-#if defined(MICROPY_HW_I2C_BAUDRATE_TIMING)
+#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
+
// The STM32F0, F3, F7 and L4 use a TIMINGR register rather than ClockSpeed and
// DutyCycle.
+#if defined(STM32F746xx)
+
+// The value 0x40912732 was obtained from the DISCOVERY_I2Cx_TIMING constant
+// defined in the STM32F7Cube file Drivers/BSP/STM32F746G-Discovery/stm32f7456g_discovery.h
+#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x40912732}}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (100000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (100000)
+
+#elif defined(STM32F767xx) || defined(STM32F769xx)
+
+// These timing values are for f_I2CCLK=54MHz and are only approximate
+#define MICROPY_HW_I2C_BAUDRATE_TIMING { \
+ {100000, 0xb0420f13}, \
+ {400000, 0x70330309}, \
+ {1000000, 0x50100103}, \
+ }
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (400000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (1000000)
+
+#elif defined(MCU_SERIES_L4)
+
+// The value 0x90112626 was obtained from the DISCOVERY_I2C1_TIMING constant
+// defined in the STM32L4Cube file Drivers/BSP/STM32L476G-Discovery/stm32l476g_discovery.h
+#define MICROPY_HW_I2C_BAUDRATE_TIMING {{100000, 0x90112626}}
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (100000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (100000)
+
+#else
+#error "no I2C timings for this MCU"
+#endif
+
STATIC const struct {
uint32_t baudrate;
uint32_t timing;
@@ -167,6 +191,9 @@ uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
#else
+#define MICROPY_HW_I2C_BAUDRATE_DEFAULT (400000)
+#define MICROPY_HW_I2C_BAUDRATE_MAX (400000)
+
STATIC void i2c_set_baudrate(I2C_InitTypeDef *init, uint32_t baudrate) {
init->ClockSpeed = baudrate;
init->DutyCycle = I2C_DUTYCYCLE_16_9;
@@ -176,7 +203,7 @@ uint32_t i2c_get_baudrate(I2C_InitTypeDef *init) {
return init->ClockSpeed;
}
-#endif // MICROPY_HW_I2C_BAUDRATE_TIMING
+#endif
void i2c_init0(void) {
// reset the I2C1 handles
@@ -733,12 +760,14 @@ STATIC mp_obj_t pyb_i2c_send(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (!use_dma) {
status = HAL_I2C_Master_Transmit(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len, args[2].u_int);
} else {
+ MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len);
status = HAL_I2C_Master_Transmit_DMA(self->i2c, i2c_addr, bufinfo.buf, bufinfo.len);
}
} else {
if (!use_dma) {
status = HAL_I2C_Slave_Transmit(self->i2c, bufinfo.buf, bufinfo.len, args[2].u_int);
} else {
+ MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len);
status = HAL_I2C_Slave_Transmit_DMA(self->i2c, bufinfo.buf, bufinfo.len);
}
}
@@ -807,12 +836,14 @@ STATIC mp_obj_t pyb_i2c_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
if (!use_dma) {
status = HAL_I2C_Master_Receive(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len, args[2].u_int);
} else {
+ MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len);
status = HAL_I2C_Master_Receive_DMA(self->i2c, i2c_addr, (uint8_t*)vstr.buf, vstr.len);
}
} else {
if (!use_dma) {
status = HAL_I2C_Slave_Receive(self->i2c, (uint8_t*)vstr.buf, vstr.len, args[2].u_int);
} else {
+ MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len);
status = HAL_I2C_Slave_Receive_DMA(self->i2c, (uint8_t*)vstr.buf, vstr.len);
}
}
@@ -893,6 +924,7 @@ STATIC mp_obj_t pyb_i2c_mem_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_
dma_init(&rx_dma, self->rx_dma_descr, self->i2c);
self->i2c->hdmatx = NULL;
self->i2c->hdmarx = &rx_dma;
+ MP_HAL_CLEANINVALIDATE_DCACHE(vstr.buf, vstr.len);
status = HAL_I2C_Mem_Read_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, (uint8_t*)vstr.buf, vstr.len);
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[3].u_int);
@@ -961,6 +993,7 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp
dma_init(&tx_dma, self->tx_dma_descr, self->i2c);
self->i2c->hdmatx = &tx_dma;
self->i2c->hdmarx = NULL;
+ MP_HAL_CLEAN_DCACHE(bufinfo.buf, bufinfo.len);
status = HAL_I2C_Mem_Write_DMA(self->i2c, i2c_addr, mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len);
if (status == HAL_OK) {
status = i2c_wait_dma_finished(self->i2c, args[3].u_int);
diff --git a/stmhal/input.c b/stmhal/input.c
index 07e7ba35c..c78525cc9 100644
--- a/stmhal/input.c
+++ b/stmhal/input.c
@@ -26,7 +26,7 @@
#include "py/nlr.h"
#include "py/obj.h"
-#include "readline.h"
+#include "lib/mp-readline/readline.h"
STATIC mp_obj_t mp_builtin_input(uint n_args, const mp_obj_t *args) {
if (n_args == 1) {
diff --git a/stmhal/irq.h b/stmhal/irq.h
index bb1749e03..a56f23652 100644
--- a/stmhal/irq.h
+++ b/stmhal/irq.h
@@ -133,10 +133,10 @@ MP_DECLARE_CONST_FUN_OBJ_0(pyb_irq_stats_obj);
#define IRQ_SUBPRI_CAN 0
// Interrupt priority for non-special timers.
-#define IRQ_PRI_TIMX 14
+#define IRQ_PRI_TIMX 13
#define IRQ_SUBPRI_TIMX 0
-#define IRQ_PRI_EXTINT 15
+#define IRQ_PRI_EXTINT 14
#define IRQ_SUBPRI_EXTINT 0
// PENDSV should be at the lowst priority so that other interrupts complete
diff --git a/stmhal/lcd.c b/stmhal/lcd.c
index cde6c36f6..ae453f0fc 100644
--- a/stmhal/lcd.c
+++ b/stmhal/lcd.c
@@ -373,7 +373,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_light_obj, pyb_lcd_light);
/// Write the string `str` to the screen. It will appear immediately.
STATIC mp_obj_t pyb_lcd_write(mp_obj_t self_in, mp_obj_t str) {
pyb_lcd_obj_t *self = self_in;
- mp_uint_t len;
+ size_t len;
const char *data = mp_obj_str_get_data(str, &len);
lcd_write_strn(self, data, len);
return mp_const_none;
@@ -445,7 +445,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_lcd_pixel_obj, 4, 4, pyb_lcd_pixe
STATIC mp_obj_t pyb_lcd_text(mp_uint_t n_args, const mp_obj_t *args) {
// extract arguments
pyb_lcd_obj_t *self = args[0];
- mp_uint_t len;
+ size_t len;
const char *data = mp_obj_str_get_data(args[1], &len);
int x0 = mp_obj_get_int(args[2]);
int y0 = mp_obj_get_int(args[3]);
diff --git a/stmhal/main.c b/stmhal/main.c
index 8d076a08b..566c2db07 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -31,6 +31,7 @@
#include "py/stackctrl.h"
#include "py/gc.h"
#include "py/mphal.h"
+#include "lib/mp-readline/readline.h"
#include "lib/utils/pyexec.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs.h"
@@ -40,7 +41,6 @@
#include "pendsv.h"
#include "pybthread.h"
#include "gccollect.h"
-#include "readline.h"
#include "modmachine.h"
#include "i2c.h"
#include "spi.h"
diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c
index e1426c055..26c6cd48c 100644
--- a/stmhal/modnwcc3k.c
+++ b/stmhal/modnwcc3k.c
@@ -37,7 +37,7 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#include "pin.h"
#include "genhdr/pins.h"
@@ -477,11 +477,11 @@ STATIC mp_obj_t cc3k_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// get ssid
- mp_uint_t ssid_len;
+ size_t ssid_len;
const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
// get key and sec
- mp_uint_t key_len = 0;
+ size_t key_len = 0;
const char *key = NULL;
mp_uint_t sec = WLAN_SEC_UNSEC;
if (args[1].u_obj != mp_const_none) {
diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c
index e3d5c6370..b32f16913 100644
--- a/stmhal/modnwwiznet5k.c
+++ b/stmhal/modnwwiznet5k.c
@@ -33,7 +33,7 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#include "pin.h"
#include "genhdr/pins.h"
diff --git a/stmhal/moduos.c b/stmhal/moduos.c
index 0af682612..745c0d5d7 100644
--- a/stmhal/moduos.c
+++ b/stmhal/moduos.c
@@ -31,12 +31,12 @@
#include "py/runtime.h"
#include "py/objtuple.h"
#include "py/objstr.h"
+#include "lib/timeutils/timeutils.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "genhdr/mpversion.h"
-#include "timeutils.h"
#include "rng.h"
#include "uart.h"
#include "portmodules.h"
diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c
index 7ff890264..fd60c5ad4 100644
--- a/stmhal/modusocket.c
+++ b/stmhal/modusocket.c
@@ -32,7 +32,7 @@
#include "py/objlist.h"
#include "py/runtime.h"
#include "py/mperrno.h"
-#include "netutils.h"
+#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#if MICROPY_PY_USOCKET
@@ -388,7 +388,7 @@ STATIC const mp_obj_type_t socket_type = {
// function usocket.getaddrinfo(host, port)
STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
- mp_uint_t hlen;
+ size_t hlen;
const char *host = mp_obj_str_get_data(host_in, &hlen);
mp_int_t port = mp_obj_get_int(port_in);
diff --git a/stmhal/modutime.c b/stmhal/modutime.c
index 7f2c549bd..97af35c49 100644
--- a/stmhal/modutime.c
+++ b/stmhal/modutime.c
@@ -31,9 +31,9 @@
#include "py/nlr.h"
#include "py/smallint.h"
#include "py/obj.h"
+#include "lib/timeutils/timeutils.h"
#include "extmod/utime_mphal.h"
#include "systick.h"
-#include "timeutils.h"
#include "portmodules.h"
#include "rtc.h"
@@ -100,7 +100,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
/// the number of seconds since Jan 1, 2000.
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
- mp_uint_t len;
+ size_t len;
mp_obj_t *elem;
mp_obj_get_array(tuple, &len, &elem);
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 38a5ac5da..3f3683199 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -69,6 +69,8 @@
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
#define MICROPY_USE_INTERNAL_ERRNO (1)
+#define MICROPY_ENABLE_SCHEDULER (1)
+#define MICROPY_SCHEDULER_DEPTH (8)
#define MICROPY_VFS (1)
#define MICROPY_VFS_FAT (1)
@@ -262,8 +264,6 @@ extern const struct _mp_obj_module_t mp_module_network;
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
#define MP_SSIZE_MAX (0x7fffffff)
@@ -303,6 +303,8 @@ static inline mp_uint_t disable_irq(void) {
#if MICROPY_PY_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
+ extern void mp_handle_pending(void); \
+ mp_handle_pending(); \
if (pyb_thread_enabled) { \
MP_THREAD_GIL_EXIT(); \
pyb_thread_yield(); \
@@ -312,7 +314,12 @@ static inline mp_uint_t disable_irq(void) {
} \
} while (0);
#else
-#define MICROPY_EVENT_POLL_HOOK __WFI();
+#define MICROPY_EVENT_POLL_HOOK \
+ do { \
+ extern void mp_handle_pending(void); \
+ mp_handle_pending(); \
+ __WFI(); \
+ } while (0);
#endif
// There is no classical C heap in bare-metal ports, only Python
diff --git a/stmhal/mphalport.h b/stmhal/mphalport.h
index 752102402..77cb0204d 100644
--- a/stmhal/mphalport.h
+++ b/stmhal/mphalport.h
@@ -10,8 +10,8 @@
#define MP_HAL_CLEAN_DCACHE(addr, size)
#elif defined(MCU_SERIES_F7)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1ff0f420)
-#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size) (SCB_CleanInvalidateDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)(addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
-#define MP_HAL_CLEAN_DCACHE(addr, size) (SCB_CleanDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)(addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
+#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size) (SCB_CleanInvalidateDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)((uint8_t*)addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
+#define MP_HAL_CLEAN_DCACHE(addr, size) (SCB_CleanDCache_by_Addr((uint32_t*)((uint32_t)addr & ~0x1f), ((uint32_t)((uint8_t*)addr + size + 0x1f) & ~0x1f) - ((uint32_t)addr & ~0x1f)))
#elif defined(MCU_SERIES_L4)
#define MP_HAL_UNIQUE_ID_ADDRESS (0x1fff7590)
#define MP_HAL_CLEANINVALIDATE_DCACHE(addr, size)
diff --git a/stmhal/pendsv.c b/stmhal/pendsv.c
index 4c2a14de1..200d13a5a 100644
--- a/stmhal/pendsv.c
+++ b/stmhal/pendsv.c
@@ -106,11 +106,14 @@ void pendsv_isr_handler(void) {
".no_obj:\n" // pendsv_object==NULL
"push {r4-r11, lr}\n"
"vpush {s16-s31}\n"
+ "mrs r5, primask\n" // save PRIMASK in r5
+ "cpsid i\n" // disable interrupts while we change stacks
"mov r0, sp\n" // pass sp to save
"mov r4, lr\n" // save lr because we are making a call
"bl pyb_thread_next\n" // get next thread to execute
"mov lr, r4\n" // restore lr
"mov sp, r0\n" // switch stacks
+ "msr primask, r5\n" // reenable interrupts
"vpop {s16-s31}\n"
"pop {r4-r11, lr}\n"
"bx lr\n" // return from interrupt; will return to new thread
diff --git a/stmhal/pin_defs_stmhal.h b/stmhal/pin_defs_stmhal.h
index 80c967016..d6a2ef424 100644
--- a/stmhal/pin_defs_stmhal.h
+++ b/stmhal/pin_defs_stmhal.h
@@ -48,6 +48,7 @@ enum {
AF_FN_UART = AF_FN_USART,
AF_FN_SPI,
AF_FN_I2S,
+ AF_FN_SDMMC,
};
enum {
@@ -85,6 +86,13 @@ enum {
AF_PIN_TYPE_I2S_SD,
AF_PIN_TYPE_I2S_WS,
AF_PIN_TYPE_I2S_EXTSD,
+
+ AF_PIN_TYPE_SDMMC_CK = 0,
+ AF_PIN_TYPE_SDMMC_CMD,
+ AF_PIN_TYPE_SDMMC_D0,
+ AF_PIN_TYPE_SDMMC_D1,
+ AF_PIN_TYPE_SDMMC_D2,
+ AF_PIN_TYPE_SDMMC_D3,
};
// The HAL uses a slightly different naming than we chose, so we provide
@@ -109,13 +117,15 @@ enum {
// Note that SPI and I2S are really the same peripheral as far as the HAL
// is concerned, so there is no I2S_TypeDef.
+// We use void* for SDMMC because not all MCUs have the SDMMC_TypeDef type.
#define PIN_DEFS_PORT_AF_UNION \
TIM_TypeDef *TIM; \
I2C_TypeDef *I2C; \
USART_TypeDef *USART; \
USART_TypeDef *UART; \
SPI_TypeDef *SPI;\
- SPI_TypeDef *I2S;
+ SPI_TypeDef *I2S; \
+ void *SDMMC; \
typedef GPIO_TypeDef pin_gpio_t;
diff --git a/stmhal/pybthread.c b/stmhal/pybthread.c
index 51e9a738d..6baf88f66 100644
--- a/stmhal/pybthread.c
+++ b/stmhal/pybthread.c
@@ -37,6 +37,11 @@
#define PYB_MUTEX_UNLOCKED ((void*)0)
#define PYB_MUTEX_LOCKED ((void*)1)
+// These macros are used when we only need to protect against a thread
+// switch; other interrupts are still allowed to proceed.
+#define RAISE_IRQ_PRI() raise_irq_pri(IRQ_PRI_PENDSV)
+#define RESTORE_IRQ_PRI(state) restore_irq_pri(state)
+
extern void __fatal_error(const char*);
volatile int pyb_thread_enabled;
@@ -176,15 +181,15 @@ void pyb_mutex_init(pyb_mutex_t *m) {
}
int pyb_mutex_lock(pyb_mutex_t *m, int wait) {
- uint32_t irq_state = disable_irq();
+ uint32_t irq_state = RAISE_IRQ_PRI();
if (*m == PYB_MUTEX_UNLOCKED) {
// mutex is available
*m = PYB_MUTEX_LOCKED;
- enable_irq(irq_state);
+ RESTORE_IRQ_PRI(irq_state);
} else {
// mutex is locked
if (!wait) {
- enable_irq(irq_state);
+ RESTORE_IRQ_PRI(irq_state);
return 0; // failed to lock mutex
}
if (*m == PYB_MUTEX_LOCKED) {
@@ -202,14 +207,14 @@ int pyb_mutex_lock(pyb_mutex_t *m, int wait) {
pyb_thread_remove_from_runable(pyb_thread_cur);
// thread switch will occur after we enable irqs
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
- enable_irq(irq_state);
+ RESTORE_IRQ_PRI(irq_state);
// when we come back we have the mutex
}
return 1; // have mutex
}
void pyb_mutex_unlock(pyb_mutex_t *m) {
- uint32_t irq_state = disable_irq();
+ uint32_t irq_state = RAISE_IRQ_PRI();
if (*m == PYB_MUTEX_LOCKED) {
// no threads are blocked on the mutex
*m = PYB_MUTEX_UNLOCKED;
@@ -226,7 +231,7 @@ void pyb_mutex_unlock(pyb_mutex_t *m) {
// put unblocked thread on runable list
pyb_thread_add_to_runable(th);
}
- enable_irq(irq_state);
+ RESTORE_IRQ_PRI(irq_state);
}
#endif // MICROPY_PY_THREAD
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index 73206f431..5abffa730 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -43,11 +43,29 @@
#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4)
+// The F7 has 2 SDMMC units but at the moment we only support using one of them in
+// a given build. If a boards config file defines MICROPY_HW_SDMMC2_CK then SDMMC2
+// is used, otherwise SDMMC1 is used.
+
+#if defined(MICROPY_HW_SDMMC2_CK)
+#define SDIO SDMMC2
+#define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC2_CLK_ENABLE()
+#define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC2_CLK_DISABLE()
+#define SDMMC_IRQn SDMMC2_IRQn
+#define SDMMC_TX_DMA dma_SDMMC_2_TX
+#define SDMMC_RX_DMA dma_SDMMC_2_RX
+#else
+#define SDIO SDMMC1
+#define SDMMC_CLK_ENABLE() __HAL_RCC_SDMMC1_CLK_ENABLE()
+#define SDMMC_CLK_DISABLE() __HAL_RCC_SDMMC1_CLK_DISABLE()
+#define SDMMC_IRQn SDMMC1_IRQn
+#define SDMMC_TX_DMA dma_SDIO_0_TX
+#define SDMMC_RX_DMA dma_SDIO_0_RX
+#endif
+
// The F7 & L4 series calls the peripheral SDMMC rather than SDIO, so provide some
// #defines for backwards compatability.
-#define SDIO SDMMC1
-
#define SDIO_CLOCK_EDGE_RISING SDMMC_CLOCK_EDGE_RISING
#define SDIO_CLOCK_EDGE_FALLING SDMMC_CLOCK_EDGE_FALLING
@@ -66,6 +84,16 @@
#define SDIO_TRANSFER_CLK_DIV SDMMC_TRANSFER_CLK_DIV
+#else
+
+// These are definitions for F4 MCUs so there is a common macro across all MCUs.
+
+#define SDMMC_CLK_ENABLE() __SDIO_CLK_ENABLE()
+#define SDMMC_CLK_DISABLE() __SDIO_CLK_DISABLE()
+#define SDMMC_IRQn SDIO_IRQn
+#define SDMMC_TX_DMA dma_SDIO_0_TX
+#define SDMMC_RX_DMA dma_SDIO_0_RX
+
#endif
// TODO: Since SDIO is fundamentally half-duplex, we really only need to
@@ -90,12 +118,23 @@ void sdcard_init(void) {
// Note: the mp_hal_pin_config function will configure the GPIO in
// fast mode which can do up to 50MHz. This should be plenty for SDIO
// which clocks up to 25MHz maximum.
+ #if defined(MICROPY_HW_SDMMC2_CK)
+ // Use SDMMC2 peripheral with pins provided by the board's config
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_CK, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_CMD, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D0, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D1, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ mp_hal_pin_config_alt(&MICROPY_HW_SDMMC2_D3, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, AF_FN_SDMMC, 2);
+ #else
+ // Default SDIO/SDMMC1 config
mp_hal_pin_config(&pin_C8, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C9, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C10, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C11, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_C12, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
mp_hal_pin_config(&pin_D2, MP_HAL_PIN_MODE_ALT, MP_HAL_PIN_PULL_UP, GPIO_AF12_SDIO);
+ #endif
// configure the SD card detect pin
// we do this here so we can detect if the SD card is inserted before powering it on
@@ -104,18 +143,18 @@ void sdcard_init(void) {
void HAL_SD_MspInit(SD_HandleTypeDef *hsd) {
// enable SDIO clock
- __SDIO_CLK_ENABLE();
+ SDMMC_CLK_ENABLE();
// NVIC configuration for SDIO interrupts
- HAL_NVIC_SetPriority(SDIO_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO);
- HAL_NVIC_EnableIRQ(SDIO_IRQn);
+ HAL_NVIC_SetPriority(SDMMC_IRQn, IRQ_PRI_SDIO, IRQ_SUBPRI_SDIO);
+ HAL_NVIC_EnableIRQ(SDMMC_IRQn);
// GPIO have already been initialised by sdcard_init
}
void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) {
- HAL_NVIC_DisableIRQ(SDIO_IRQn);
- __SDIO_CLK_DISABLE();
+ HAL_NVIC_DisableIRQ(SDMMC_IRQn);
+ SDMMC_CLK_DISABLE();
}
bool sdcard_is_present(void) {
@@ -184,6 +223,14 @@ void SDIO_IRQHandler(void) {
IRQ_EXIT(SDIO_IRQn);
}
+#if defined(MCU_SERIES_F7)
+void SDMMC2_IRQHandler(void) {
+ IRQ_ENTER(SDMMC2_IRQn);
+ HAL_SD_IRQHandler(&sd_handle);
+ IRQ_EXIT(SDMMC2_IRQn);
+}
+#endif
+
mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blocks) {
// check that SD card is initialised
if (sd_handle.Instance == NULL) {
@@ -214,7 +261,7 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
// we must disable USB irqs to prevent MSC contention with SD card
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
- dma_init(&sd_rx_dma, &dma_SDIO_0_RX, &sd_handle);
+ dma_init(&sd_rx_dma, &SDMMC_RX_DMA, &sd_handle);
sd_handle.hdmarx = &sd_rx_dma;
// make sure cache is flushed and invalidated so when DMA updates the RAM
@@ -227,7 +274,7 @@ mp_uint_t sdcard_read_blocks(uint8_t *dest, uint32_t block_num, uint32_t num_blo
err = HAL_SD_CheckReadOperation(&sd_handle, 100000000);
}
- dma_deinit(&dma_SDIO_0_RX);
+ dma_deinit(&SDMMC_RX_DMA);
sd_handle.hdmarx = NULL;
restore_irq_pri(basepri);
@@ -274,7 +321,7 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
// we must disable USB irqs to prevent MSC contention with SD card
uint32_t basepri = raise_irq_pri(IRQ_PRI_OTG_FS);
- dma_init(&sd_tx_dma, &dma_SDIO_0_TX, &sd_handle);
+ dma_init(&sd_tx_dma, &SDMMC_TX_DMA, &sd_handle);
sd_handle.hdmatx = &sd_tx_dma;
// make sure cache is flushed to RAM so the DMA can read the correct data
@@ -285,7 +332,7 @@ mp_uint_t sdcard_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t n
// wait for DMA transfer to finish, with a large timeout
err = HAL_SD_CheckWriteOperation(&sd_handle, 100000000);
}
- dma_deinit(&dma_SDIO_0_TX);
+ dma_deinit(&SDMMC_TX_DMA);
sd_handle.hdmatx = NULL;
restore_irq_pri(basepri);
diff --git a/stmhal/spi.c b/stmhal/spi.c
index 234d4bab7..d7c9b04cc 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -403,6 +403,11 @@ STATIC HAL_StatusTypeDef spi_wait_dma_finished(SPI_HandleTypeDef *spi, uint32_t
return HAL_OK;
}
+// A transfer of "len" bytes should take len*8*1000/baudrate milliseconds.
+// To simplify the calculation we assume the baudrate is never less than 8kHz
+// and use that value for the baudrate in the formula, plus a small constant.
+#define SPI_TRANSFER_TIMEOUT(len) ((len) + 100)
+
STATIC void spi_transfer(const pyb_spi_obj_t *self, size_t len, const uint8_t *src, uint8_t *dest, uint32_t timeout) {
// Note: there seems to be a problem sending 1 byte using DMA the first
// time directly after the SPI/DMA is initialised. The cause of this is
@@ -419,6 +424,7 @@ STATIC void spi_transfer(const pyb_spi_obj_t *self, size_t len, const uint8_t *s
dma_init(&tx_dma, self->tx_dma_descr, self->spi);
self->spi->hdmatx = &tx_dma;
self->spi->hdmarx = NULL;
+ MP_HAL_CLEAN_DCACHE(src, len);
status = HAL_SPI_Transmit_DMA(self->spi, (uint8_t*)src, len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
@@ -440,7 +446,7 @@ STATIC void spi_transfer(const pyb_spi_obj_t *self, size_t len, const uint8_t *s
}
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
-
+ MP_HAL_CLEANINVALIDATE_DCACHE(dest, len);
status = HAL_SPI_Receive_DMA(self->spi, dest, len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
@@ -460,6 +466,8 @@ STATIC void spi_transfer(const pyb_spi_obj_t *self, size_t len, const uint8_t *s
self->spi->hdmatx = &tx_dma;
dma_init(&rx_dma, self->rx_dma_descr, self->spi);
self->spi->hdmarx = &rx_dma;
+ MP_HAL_CLEAN_DCACHE(src, len);
+ MP_HAL_CLEANINVALIDATE_DCACHE(dest, len);
status = HAL_SPI_TransmitReceive_DMA(self->spi, (uint8_t*)src, dest, len);
if (status == HAL_OK) {
status = spi_wait_dma_finished(self->spi, timeout);
@@ -812,7 +820,7 @@ STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(pyb_spi_locals_dict, pyb_spi_locals_dict_table);
STATIC void spi_transfer_machine(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
- spi_transfer((pyb_spi_obj_t*)self_in, len, src, dest, 100);
+ spi_transfer((pyb_spi_obj_t*)self_in, len, src, dest, SPI_TRANSFER_TIMEOUT(len));
}
STATIC const mp_machine_spi_p_t pyb_spi_p = {
@@ -929,7 +937,7 @@ STATIC void machine_hard_spi_deinit(mp_obj_base_t *self_in) {
STATIC void machine_hard_spi_transfer(mp_obj_base_t *self_in, size_t len, const uint8_t *src, uint8_t *dest) {
machine_hard_spi_obj_t *self = (machine_hard_spi_obj_t*)self_in;
- spi_transfer(self->pyb, len, src, dest, 100);
+ spi_transfer(self->pyb, len, src, dest, SPI_TRANSFER_TIMEOUT(len));
}
STATIC const mp_machine_spi_p_t machine_hard_spi_p = {
diff --git a/stmhal/startup_stm32.S b/stmhal/startup_stm32.S
index 25b0fdd39..a688cd067 100644
--- a/stmhal/startup_stm32.S
+++ b/stmhal/startup_stm32.S
@@ -335,6 +335,12 @@ g_pfnVectors:
.word I2C4_EV_IRQHandler /* I2C4 Event */
.word I2C4_ER_IRQHandler /* I2C4 Error */
.word SPDIF_RX_IRQHandler /* SPDIF_RX */
+ .word DSIHOST_IRQHandler /* DSI host */
+ .word DFSDM1_FLT0_IRQHandler /* DFSDM1 filter 0 */
+ .word DFSDM1_FLT1_IRQHandler /* DFSDM1 filter 1 */
+ .word DFSDM1_FLT2_IRQHandler /* DFSDM1 filter 2 */
+ .word DFSDM1_FLT3_IRQHandler /* DFSDM1 filter 3 */
+ .word SDMMC2_IRQHandler /* SDMMC2 */
#endif
/*******************************************************************************
@@ -793,6 +799,24 @@ g_pfnVectors:
.weak SPDIF_RX_IRQHandler
.thumb_set SPDIF_RX_IRQHandler,Default_Handler
+
+ .weak DSIHOST_IRQHandler
+ .thumb_set DSIHOST_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT0_IRQHandler
+ .thumb_set DFSDM1_FLT0_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT1_IRQHandler
+ .thumb_set DFSDM1_FLT1_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT2_IRQHandler
+ .thumb_set DFSDM1_FLT2_IRQHandler,Default_Handler
+
+ .weak DFSDM1_FLT3_IRQHandler
+ .thumb_set DFSDM1_FLT3_IRQHandler,Default_Handler
+
+ .weak SDMMC2_IRQHandler
+ .thumb_set SDMMC2_IRQHandler,Default_Handler
#endif
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/stmhal/systick.c b/stmhal/systick.c
index eb11de9b7..4eac583e2 100644
--- a/stmhal/systick.c
+++ b/stmhal/systick.c
@@ -24,6 +24,7 @@
* THE SOFTWARE.
*/
+#include "py/runtime.h"
#include "py/mphal.h"
#include "irq.h"
#include "systick.h"
@@ -50,23 +51,17 @@ void HAL_Delay(uint32_t Delay) {
}
// Core delay function that does an efficient sleep and may switch thread context.
-// Note: Upon entering this function we may or may not have the GIL.
+// If IRQs are enabled then we must have the GIL.
void mp_hal_delay_ms(mp_uint_t Delay) {
if (query_irq() == IRQ_STATE_ENABLED) {
// IRQs enabled, so can use systick counter to do the delay
uint32_t start = uwTick;
// Wraparound of tick is taken care of by 2's complement arithmetic.
while (uwTick - start < Delay) {
- // Enter sleep mode, waiting for (at least) the SysTick interrupt.
- #if MICROPY_PY_THREAD
- if (pyb_thread_enabled) {
- pyb_thread_yield();
- } else {
- __WFI();
- }
- #else
- __WFI();
- #endif
+ // This macro will execute the necessary idle behaviour. It may
+ // raise an exception, switch threads or enter sleep mode (waiting for
+ // (at least) the SysTick interrupt).
+ MICROPY_EVENT_POLL_HOOK
}
} else {
// IRQs disabled, so need to use a busy loop for the delay.
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 494045c28..7f0a70c5e 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -1363,6 +1363,7 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o
// execute callback if it's set
if (callback != mp_const_none) {
+ mp_sched_lock();
// When executing code within a handler we must lock the GC to prevent
// any memory allocations. We must also catch any exceptions.
gc_lock();
@@ -1382,6 +1383,7 @@ STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_o
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
gc_unlock();
+ mp_sched_unlock();
}
}
}
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index 1c12cdc1c..941025515 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -61,7 +61,7 @@
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
-#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE=64 (APP_RX_DATA_SIZE was 2048)
+#define APP_RX_DATA_SIZE 1024 // this must be 2 or greater, and a power of 2
#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048)
/* Private macro -------------------------------------------------------------*/
@@ -69,9 +69,10 @@
static __IO uint8_t dev_is_connected = 0; // indicates if we are connected
-static uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; // received data from USB OUT endpoint is stored in this buffer
-static uint16_t UserRxBufCur = 0; // points to next available character in UserRxBuffer
-static uint16_t UserRxBufLen = 0; // counts number of valid characters in UserRxBuffer
+static uint8_t cdc_rx_packet_buf[CDC_DATA_FS_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer
+static uint8_t cdc_rx_user_buf[APP_RX_DATA_SIZE]; // received data is buffered here until the user reads it
+static volatile uint16_t cdc_rx_buf_put = 0; // circular buffer index
+static uint16_t cdc_rx_buf_get = 0; // circular buffer index
static uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer
static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available
@@ -141,10 +142,10 @@ static int8_t CDC_Itf_Init(void)
/*##-5- Set Application Buffers ############################################*/
USBD_CDC_SetTxBuffer(&hUSBDDevice, UserTxBuffer, 0);
- USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer);
+ USBD_CDC_SetRxBuffer(&hUSBDDevice, cdc_rx_packet_buf);
- UserRxBufCur = 0;
- UserRxBufLen = 0;
+ cdc_rx_buf_put = 0;
+ cdc_rx_buf_get = 0;
return (USBD_OK);
}
@@ -261,8 +262,10 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
if (UserTxBufPtrOut != UserTxBufPtrOutShadow) {
// We have sent data and are waiting for the low-level USB driver to
// finish sending it over the USB in-endpoint.
- // SOF occurs every 1ms, so we have a 150 * 1ms = 150ms timeout
- if (UserTxBufPtrWaitCount < 150) {
+ // SOF occurs every 1ms, so we have a 500 * 1ms = 500ms timeout
+ // We have a relatively large timeout because the USB host may be busy
+ // doing other things and we must give it a chance to read our data.
+ if (UserTxBufPtrWaitCount < 500) {
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
// USB in-endpoint is still reading the data
@@ -311,7 +314,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
* @param Buf: Buffer of data received
* @param Len: Number of data received (in bytes)
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
- * @note The buffer we are passed here is just UserRxBuffer, so we are
+ * @note The buffer we are passed here is just cdc_rx_packet_buf, so we are
* free to modify it.
*/
static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
@@ -320,54 +323,23 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len);
#endif
- // TODO improve this function to implement a circular buffer
-
- // if we have processed all the characters, reset the buffer counters
- if (UserRxBufCur > 0 && UserRxBufCur >= UserRxBufLen) {
- memmove(UserRxBuffer, UserRxBuffer + UserRxBufLen, *Len);
- UserRxBufCur = 0;
- UserRxBufLen = 0;
- }
-
- uint32_t delta_len;
-
- if (mp_interrupt_char == -1) {
- // no special interrupt character
- delta_len = *Len;
-
- } else {
- // filter out special interrupt character from the buffer
- bool char_found = false;
- uint8_t *dest = Buf;
- uint8_t *src = Buf;
- uint8_t *buf_top = Buf + *Len;
- for (; src < buf_top; src++) {
- if (*src == mp_interrupt_char) {
- char_found = true;
- // raise KeyboardInterrupt when interrupts are finished
- pendsv_kbd_intr();
- } else {
- if (char_found) {
- *dest = *src;
- }
- dest++;
+ // copy the incoming data into the circular buffer
+ for (uint8_t *src = Buf, *top = Buf + *Len; src < top; ++src) {
+ if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
+ pendsv_kbd_intr();
+ } else {
+ uint16_t next_put = (cdc_rx_buf_put + 1) & (APP_RX_DATA_SIZE - 1);
+ if (next_put == cdc_rx_buf_get) {
+ // overflow, we just discard the rest of the chars
+ break;
}
+ cdc_rx_user_buf[cdc_rx_buf_put] = *src;
+ cdc_rx_buf_put = next_put;
}
-
- // length of remaining characters
- delta_len = dest - Buf;
- }
-
- if (UserRxBufLen + delta_len + CDC_DATA_FS_MAX_PACKET_SIZE > APP_RX_DATA_SIZE) {
- // if we keep this data then the buffer can overflow on the next USB rx
- // so we don't increment the length, and throw this data away
- } else {
- // data fits, leaving room for another CDC_DATA_FS_OUT_PACKET_SIZE
- UserRxBufLen += delta_len;
}
- // initiate next USB packet transfer, to append to existing data in buffer
- USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer + UserRxBufLen);
+ // initiate next USB packet transfer
+ USBD_CDC_SetRxBuffer(&hUSBDDevice, cdc_rx_packet_buf);
USBD_CDC_ReceivePacket(&hUSBDDevice);
return USBD_OK;
@@ -461,7 +433,11 @@ void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) {
// Returns number of bytes in the rx buffer.
int USBD_CDC_RxNum(void) {
- return UserRxBufLen - UserRxBufCur;
+ int32_t rx_waiting = (int32_t)cdc_rx_buf_put - (int32_t)cdc_rx_buf_get;
+ if (rx_waiting < 0) {
+ rx_waiting += APP_RX_DATA_SIZE;
+ }
+ return rx_waiting;
}
// timout in milliseconds.
@@ -471,7 +447,7 @@ int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) {
for (uint32_t i = 0; i < len; i++) {
// Wait until we have at least 1 byte to read
uint32_t start = HAL_GetTick();
- while (UserRxBufLen == UserRxBufCur) {
+ while (cdc_rx_buf_put == cdc_rx_buf_get) {
// Wraparound of tick is taken care of by 2's complement arithmetic.
if (HAL_GetTick() - start >= timeout) {
// timeout
@@ -485,7 +461,8 @@ int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) {
}
// Copy byte from device to user buffer
- buf[i] = UserRxBuffer[UserRxBufCur++];
+ buf[i] = cdc_rx_user_buf[cdc_rx_buf_get];
+ cdc_rx_buf_get = (cdc_rx_buf_get + 1) & (APP_RX_DATA_SIZE - 1);
}
// Success, return number of bytes read
diff --git a/teensy/Makefile b/teensy/Makefile
index 82e04a1ae..9f52cc3c7 100644
--- a/teensy/Makefile
+++ b/teensy/Makefile
@@ -32,11 +32,10 @@ CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mcpu=cortex-m4 -msoft-float -mfloat
INC += -I.
INC += -I..
INC += -I../stmhal
-INC += -I../lib/mp-readline
INC += -I$(BUILD)
INC += -Icore
-CFLAGS = $(INC) -Wall -Wpointer-arith -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
+CFLAGS = $(INC) -Wall -Wpointer-arith -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4)
LDFLAGS = -nostdlib -T mk20dx256.ld -msoft-float -mfloat-abi=soft
ifeq ($(USE_ARDUINO_TOOLCHAIN),1)
diff --git a/teensy/main.c b/teensy/main.c
index d62ae3bdb..41bbeb5d9 100644
--- a/teensy/main.c
+++ b/teensy/main.c
@@ -10,7 +10,7 @@
#include "py/mphal.h"
#include "gccollect.h"
#include "lib/utils/pyexec.h"
-#include "readline.h"
+#include "lib/mp-readline/readline.h"
#include "lexermemzip.h"
#include "Arduino.h"
diff --git a/teensy/mpconfigport.h b/teensy/mpconfigport.h
index 07f60c43f..8c4022046 100644
--- a/teensy/mpconfigport.h
+++ b/teensy/mpconfigport.h
@@ -54,8 +54,6 @@ extern const struct _mp_obj_module_t time_module;
// type definitions for the specific machine
-#define BYTES_PER_WORD (4)
-
#define UINT_FMT "%u"
#define INT_FMT "%d"
diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py
index 7c3e5beef..6371ab56c 100644
--- a/tests/basics/builtin_range.py
+++ b/tests/basics/builtin_range.py
@@ -34,6 +34,12 @@ print(range(1, 4)[1:])
print(range(1, 4)[:-1])
print(range(7, -2, -4)[:])
+# zero step
+try:
+ range(1, 2, 0)
+except ValueError:
+ print("ValueError")
+
# bad unary op
try:
-range(1)
diff --git a/tests/basics/bytearray_slice_assign.py b/tests/basics/bytearray_slice_assign.py
index 510e784da..c4b5c43e3 100644
--- a/tests/basics/bytearray_slice_assign.py
+++ b/tests/basics/bytearray_slice_assign.py
@@ -51,6 +51,11 @@ b = bytearray(10)
b[:-1] = bytearray(500)
print(len(b), b[0], b[-1])
+# extension with self on RHS
+b = bytearray(x)
+b[4:] = b
+print(b)
+
# Assignment of bytes to array slice
b = bytearray(2)
b[1:1] = b"12345"
diff --git a/tests/basics/class_super_closure.py b/tests/basics/class_super_closure.py
new file mode 100644
index 000000000..41acae90d
--- /dev/null
+++ b/tests/basics/class_super_closure.py
@@ -0,0 +1,18 @@
+# test that no-arg super() works when self is closed over
+
+class A:
+ def __init__(self):
+ self.val = 4
+ def foo(self):
+ # we access a member of self to check that self is correct
+ return list(range(self.val))
+class B(A):
+ def foo(self):
+ # self is closed over because it's referenced in the list comprehension
+ # and then super() must detect this and load from the closure cell
+ return [self.bar(i) for i in super().foo()]
+ def bar(self, x):
+ return 2 * x
+
+print(A().foo())
+print(B().foo())
diff --git a/tests/basics/for_range.py b/tests/basics/for_range.py
index 58a8f7caa..fc736277d 100644
--- a/tests/basics/for_range.py
+++ b/tests/basics/for_range.py
@@ -6,6 +6,13 @@ for x in range(*(1, 3)):
for x in range(1, *(6, 2)):
print(x)
+# zero step
+try:
+ for x in range(1, 2, 0):
+ pass
+except ValueError:
+ print('ValueError')
+
# apply args using **
try:
for x in range(**{'end':1}):
diff --git a/tests/basics/list_slice_assign_grow.py b/tests/basics/list_slice_assign_grow.py
index 12b1541e3..fa256235f 100644
--- a/tests/basics/list_slice_assign_grow.py
+++ b/tests/basics/list_slice_assign_grow.py
@@ -26,3 +26,8 @@ print(l)
l = list(x)
l[100:100] = [10, 20, 30, 40]
print(l)
+
+# growing by using itself on RHS
+l = list(range(10))
+l[4:] = l
+print(l)
diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py
index 2993391d5..a7956c107 100644
--- a/tests/basics/tuple1.py
+++ b/tests/basics/tuple1.py
@@ -17,6 +17,10 @@ print(x[2:3])
print(x + (10, 100, 10000))
+# inplace add operator
+x += (10, 11, 12)
+print(x)
+
# construction of tuple from large iterator (tests implementation detail of uPy)
print(tuple(range(20)))
diff --git a/tests/extmod/framebuf1.py b/tests/extmod/framebuf1.py
index c204e63aa..990b0b120 100644
--- a/tests/extmod/framebuf1.py
+++ b/tests/extmod/framebuf1.py
@@ -7,87 +7,96 @@ except ImportError:
w = 5
h = 16
-buf = bytearray(w * h // 8)
-fbuf = framebuf.FrameBuffer(buf, w, h, framebuf.MVLSB)
-
-# access as buffer
-print(memoryview(fbuf)[0])
-
-# fill
-fbuf.fill(1)
-print(buf)
-fbuf.fill(0)
-print(buf)
-
-# put pixel
-fbuf.pixel(0, 0, 1)
-fbuf.pixel(4, 0, 1)
-fbuf.pixel(0, 15, 1)
-fbuf.pixel(4, 15, 1)
-print(buf)
-
-# clear pixel
-fbuf.pixel(4, 15, 0)
-print(buf)
-
-# get pixel
-print(fbuf.pixel(0, 0), fbuf.pixel(1, 1))
-
-# hline
-fbuf.fill(0)
-fbuf.hline(0, 1, w, 1)
-print('hline', buf)
-
-# vline
-fbuf.fill(0)
-fbuf.vline(1, 0, h, 1)
-print('vline', buf)
-
-# rect
-fbuf.fill(0)
-fbuf.rect(1, 1, 3, 3, 1)
-print('rect', buf)
-
-#fill rect
-fbuf.fill(0)
-fbuf.fill_rect(0, 0, 0, 3, 1) # zero width, no-operation
-fbuf.fill_rect(1, 1, 3, 3, 1)
-print('fill_rect', buf)
-
-# line
-fbuf.fill(0)
-fbuf.line(1, 1, 3, 3, 1)
-print('line', buf)
-
-# line steep negative gradient
-fbuf.fill(0)
-fbuf.line(3, 3, 2, 1, 1)
-print('line', buf)
-
-# scroll
-fbuf.fill(0)
-fbuf.pixel(2, 7, 1)
-fbuf.scroll(0, 1)
-print(buf)
-fbuf.scroll(0, -2)
-print(buf)
-fbuf.scroll(1, 0)
-print(buf)
-fbuf.scroll(-1, 0)
-print(buf)
-fbuf.scroll(2, 2)
-print(buf)
-
-# print text
-fbuf.fill(0)
-fbuf.text("hello", 0, 0, 1)
-print(buf)
-fbuf.text("hello", 0, 0, 0) # clear
-print(buf)
-
-# char out of font range set to chr(127)
-fbuf.text(str(chr(31)), 0, 0)
-print(buf)
+size = w * h // 8
+buf = bytearray(size)
+maps = {framebuf.MONO_VLSB : 'MONO_VLSB',
+ framebuf.MONO_HLSB : 'MONO_HLSB',
+ framebuf.MONO_HMSB : 'MONO_HMSB'}
+
+for mapping in maps.keys():
+ for x in range(size):
+ buf[x] = 0
+ fbuf = framebuf.FrameBuffer(buf, w, h, mapping)
+ print(maps[mapping])
+ # access as buffer
+ print(memoryview(fbuf)[0])
+
+ # fill
+ fbuf.fill(1)
+ print(buf)
+ fbuf.fill(0)
+ print(buf)
+
+ # put pixel
+ fbuf.pixel(0, 0, 1)
+ fbuf.pixel(4, 0, 1)
+ fbuf.pixel(0, 15, 1)
+ fbuf.pixel(4, 15, 1)
+ print(buf)
+
+ # clear pixel
+ fbuf.pixel(4, 15, 0)
+ print(buf)
+
+ # get pixel
+ print(fbuf.pixel(0, 0), fbuf.pixel(1, 1))
+
+ # hline
+ fbuf.fill(0)
+ fbuf.hline(0, 1, w, 1)
+ print('hline', buf)
+
+ # vline
+ fbuf.fill(0)
+ fbuf.vline(1, 0, h, 1)
+ print('vline', buf)
+
+ # rect
+ fbuf.fill(0)
+ fbuf.rect(1, 1, 3, 3, 1)
+ print('rect', buf)
+
+ #fill rect
+ fbuf.fill(0)
+ fbuf.fill_rect(0, 0, 0, 3, 1) # zero width, no-operation
+ fbuf.fill_rect(1, 1, 3, 3, 1)
+ print('fill_rect', buf)
+
+ # line
+ fbuf.fill(0)
+ fbuf.line(1, 1, 3, 3, 1)
+ print('line', buf)
+
+ # line steep negative gradient
+ fbuf.fill(0)
+ fbuf.line(3, 3, 2, 1, 1)
+ print('line', buf)
+
+ # scroll
+ fbuf.fill(0)
+ fbuf.pixel(2, 7, 1)
+ fbuf.scroll(0, 1)
+ print(buf)
+ fbuf.scroll(0, -2)
+ print(buf)
+ fbuf.scroll(1, 0)
+ print(buf)
+ fbuf.scroll(-1, 0)
+ print(buf)
+ fbuf.scroll(2, 2)
+ print(buf)
+
+ # print text
+ fbuf.fill(0)
+ fbuf.text("hello", 0, 0, 1)
+ print(buf)
+ fbuf.text("hello", 0, 0, 0) # clear
+ print(buf)
+
+ # char out of font range set to chr(127)
+ fbuf.text(str(chr(31)), 0, 0)
+ print(buf)
+ print()
# test invalid constructor, and stride argument
try:
@@ -98,3 +107,4 @@ except ValueError:
# test legacy constructor
fbuf = framebuf.FrameBuffer1(buf, w, h)
fbuf = framebuf.FrameBuffer1(buf, w, h, w)
+print(framebuf.MVLSB == framebuf.MONO_VLSB)
diff --git a/tests/extmod/framebuf1.py.exp b/tests/extmod/framebuf1.py.exp
index 83d775d3c..d954623de 100644
--- a/tests/extmod/framebuf1.py.exp
+++ b/tests/extmod/framebuf1.py.exp
@@ -1,3 +1,4 @@
+MONO_VLSB
0
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
@@ -18,4 +19,50 @@ bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01')
bytearray(b'\x00\x7f\x7f\x04\x04\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\xaaU\xaaU\xaa\x00\x00\x00\x00\x00')
+
+MONO_HLSB
+0
+bytearray(b'\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+1 0
+hline bytearray(b'\x00\xf8\x00\x00\x00\x00\x00\x00\x00\x00')
+vline bytearray(b'@@@@@@@@@@')
+rect bytearray(b'\x00pPp\x00\x00\x00\x00\x00\x00')
+fill_rect bytearray(b'\x00ppp\x00\x00\x00\x00\x00\x00')
+line bytearray(b'\x00@ \x10\x00\x00\x00\x00\x00\x00')
+line bytearray(b'\x00 \x10\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00 \x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00 \x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00')
+bytearray(b'``x````\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'P\xa8P\xa8P\xa8P\xa8\x00\x00')
+
+MONO_HMSB
+0
+bytearray(b'\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+1 0
+hline bytearray(b'\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00')
+vline bytearray(b'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02')
+rect bytearray(b'\x00\x0e\n\x0e\x00\x00\x00\x00\x00\x00')
+fill_rect bytearray(b'\x00\x0e\x0e\x0e\x00\x00\x00\x00\x00\x00')
+line bytearray(b'\x00\x02\x04\x08\x00\x00\x00\x00\x00\x00')
+line bytearray(b'\x00\x04\x04\x08\x00\x00\x00\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00')
+bytearray(b'\x06\x06\x1e\x06\x06\x06\x06\x00\x00\x00')
+bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+bytearray(b'\n\x15\n\x15\n\x15\n\x15\x00\x00')
+
ValueError
+True
diff --git a/tests/extmod/vfs_fat_fileio.py.exp b/tests/extmod/vfs_fat_fileio.py.exp
deleted file mode 100644
index 4e34e83a8..000000000
--- a/tests/extmod/vfs_fat_fileio.py.exp
+++ /dev/null
@@ -1,24 +0,0 @@
-<io.TextIOWrapper >
-True
-True
-True
-True
-hello!world!
-12
-h
-e
-True
-d
-True
-True
-True
-True
-True
-b'data in file'
-True
-['sub_file.txt', 'file.txt']
-['foo_file.txt', 'foo_dir', 'moved-to-root.txt']
-['foo_file.txt', 'foo_dir', 'moved-to-root.txt']
-new text
-['moved-to-root.txt']
-ENOSPC: True
diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py
new file mode 100644
index 000000000..526b3f5c1
--- /dev/null
+++ b/tests/extmod/vfs_fat_fileio1.py
@@ -0,0 +1,118 @@
+import sys
+try:
+ import uerrno
+ try:
+ import uos_vfs as uos
+ open = uos.vfs_open
+ except ImportError:
+ import uos
+except ImportError:
+ print("SKIP")
+ sys.exit()
+
+try:
+ uos.VfsFat
+except AttributeError:
+ print("SKIP")
+ sys.exit()
+
+
+class RAMFS:
+
+ SEC_SIZE = 512
+
+ def __init__(self, blocks):
+ self.data = bytearray(blocks * self.SEC_SIZE)
+
+ def readblocks(self, n, buf):
+ #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
+ for i in range(len(buf)):
+ buf[i] = self.data[n * self.SEC_SIZE + i]
+
+ def writeblocks(self, n, buf):
+ #print("writeblocks(%s, %x)" % (n, id(buf)))
+ for i in range(len(buf)):
+ self.data[n * self.SEC_SIZE + i] = buf[i]
+
+ def ioctl(self, op, arg):
+ #print("ioctl(%d, %r)" % (op, arg))
+ if op == 4: # BP_IOCTL_SEC_COUNT
+ return len(self.data) // self.SEC_SIZE
+ if op == 5: # BP_IOCTL_SEC_SIZE
+ return self.SEC_SIZE
+
+
+try:
+ bdev = RAMFS(50)
+except MemoryError:
+ print("SKIP")
+ sys.exit()
+
+uos.VfsFat.mkfs(bdev)
+vfs = uos.VfsFat(bdev)
+uos.mount(vfs, '/ramdisk')
+uos.chdir('/ramdisk')
+
+# file IO
+f = open("foo_file.txt", "w")
+print(str(f)[:17], str(f)[-1:])
+f.write("hello!")
+f.flush()
+f.close()
+f.close() # allowed
+try:
+ f.write("world!")
+except OSError as e:
+ print(e.args[0] == uerrno.EINVAL)
+
+try:
+ f.read()
+except OSError as e:
+ print(e.args[0] == uerrno.EINVAL)
+
+try:
+ f.flush()
+except OSError as e:
+ print(e.args[0] == uerrno.EINVAL)
+
+try:
+ open("foo_file.txt", "x")
+except OSError as e:
+ print(e.args[0] == uerrno.EEXIST)
+
+with open("foo_file.txt", "a") as f:
+ f.write("world!")
+
+with open("foo_file.txt") as f2:
+ print(f2.read())
+ print(f2.tell())
+
+ f2.seek(0, 0) # SEEK_SET
+ print(f2.read(1))
+
+ f2.seek(0, 1) # SEEK_CUR
+ print(f2.read(1))
+ try:
+ f2.seek(1, 1) # SEEK_END
+ except OSError as e:
+ print(e.args[0] == uerrno.EOPNOTSUPP)
+
+ f2.seek(-2, 2) # SEEK_END
+ print(f2.read(1))
+
+# using constructor of FileIO type to open a file
+# no longer working with new VFS sub-system
+#FileIO = type(f)
+#with FileIO("/ramdisk/foo_file.txt") as f:
+# print(f.read())
+
+# dirs
+vfs.mkdir("foo_dir")
+
+try:
+ vfs.rmdir("foo_file.txt")
+except OSError as e:
+ print(e.args[0] == 20) # uerrno.ENOTDIR
+
+vfs.remove("foo_file.txt")
+print(vfs.listdir())
diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp
new file mode 100644
index 000000000..7959a70ee
--- /dev/null
+++ b/tests/extmod/vfs_fat_fileio1.py.exp
@@ -0,0 +1,13 @@
+<io.TextIOWrapper >
+True
+True
+True
+True
+hello!world!
+12
+h
+e
+True
+d
+True
+['foo_dir']
diff --git a/tests/extmod/vfs_fat_fileio.py b/tests/extmod/vfs_fat_fileio2.py
index 6fdac0710..111abfa7e 100644
--- a/tests/extmod/vfs_fat_fileio.py
+++ b/tests/extmod/vfs_fat_fileio2.py
@@ -1,10 +1,15 @@
import sys
-import uerrno
try:
- import uos_vfs as uos
- open = uos.vfs_open
+ import uerrno
+ try:
+ import uos_vfs as uos
+ open = uos.vfs_open
+ except ImportError:
+ import uos
except ImportError:
- import uos
+ print("SKIP")
+ sys.exit()
+
try:
uos.VfsFat
except AttributeError:
@@ -48,67 +53,6 @@ vfs = uos.VfsFat(bdev)
uos.mount(vfs, '/ramdisk')
uos.chdir('/ramdisk')
-# file IO
-f = open("foo_file.txt", "w")
-print(str(f)[:17], str(f)[-1:])
-f.write("hello!")
-f.flush()
-f.close()
-f.close() # allowed
-try:
- f.write("world!")
-except OSError as e:
- print(e.args[0] == uerrno.EINVAL)
-
-try:
- f.read()
-except OSError as e:
- print(e.args[0] == uerrno.EINVAL)
-
-try:
- f.flush()
-except OSError as e:
- print(e.args[0] == uerrno.EINVAL)
-
-try:
- open("foo_file.txt", "x")
-except OSError as e:
- print(e.args[0] == uerrno.EEXIST)
-
-with open("foo_file.txt", "a") as f:
- f.write("world!")
-
-with open("foo_file.txt") as f2:
- print(f2.read())
- print(f2.tell())
-
- f2.seek(0, 0) # SEEK_SET
- print(f2.read(1))
-
- f2.seek(0, 1) # SEEK_CUR
- print(f2.read(1))
- try:
- f2.seek(1, 1) # SEEK_END
- except OSError as e:
- print(e.args[0] == uerrno.EOPNOTSUPP)
-
- f2.seek(-2, 2) # SEEK_END
- print(f2.read(1))
-
-# using constructor of FileIO type to open a file
-# no longer working with new VFS sub-system
-#FileIO = type(f)
-#with FileIO("/ramdisk/foo_file.txt") as f:
-# print(f.read())
-
-# dirs
-vfs.mkdir("foo_dir")
-
-try:
- vfs.rmdir("foo_file.txt")
-except OSError as e:
- print(e.args[0] == 20) # uerrno.ENOTDIR
-
try:
vfs.mkdir("foo_dir")
except OSError as e:
@@ -162,7 +106,6 @@ with open("moved-to-root.txt") as f:
# valid removes
vfs.remove("foo_dir/sub_file.txt")
-vfs.remove("foo_file.txt")
vfs.rmdir("foo_dir")
print(vfs.listdir())
diff --git a/tests/extmod/vfs_fat_fileio2.py.exp b/tests/extmod/vfs_fat_fileio2.py.exp
new file mode 100644
index 000000000..38ec5c9b9
--- /dev/null
+++ b/tests/extmod/vfs_fat_fileio2.py.exp
@@ -0,0 +1,11 @@
+True
+True
+True
+b'data in file'
+True
+['sub_file.txt', 'file.txt']
+['foo_dir', 'moved-to-root.txt']
+['foo_dir', 'moved-to-root.txt']
+new text
+['moved-to-root.txt']
+ENOSPC: True
diff --git a/tests/feature_check/const.py b/tests/feature_check/const.py
new file mode 100644
index 000000000..db32e8c69
--- /dev/null
+++ b/tests/feature_check/const.py
@@ -0,0 +1 @@
+x = const(1)
diff --git a/tests/feature_check/const.py.exp b/tests/feature_check/const.py.exp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/feature_check/const.py.exp
diff --git a/tests/float/builtin_float_hash.py b/tests/float/builtin_float_hash.py
new file mode 100644
index 000000000..ba6b63907
--- /dev/null
+++ b/tests/float/builtin_float_hash.py
@@ -0,0 +1,22 @@
+# test builtin hash function with float args
+
+# these should hash to an integer with a specific value
+for val in (
+ '0.0',
+ '1.0',
+ '2.0',
+ '-12.0',
+ '12345.0',
+ ):
+ print(val, hash(float(val)))
+
+# just check that these values are hashable
+for val in (
+ '0.1',
+ '-0.1',
+ '10.3',
+ 'inf',
+ '-inf',
+ 'nan',
+ ):
+ print(val, type(hash(float(val))))
diff --git a/tests/float/builtin_float_round.py b/tests/float/builtin_float_round.py
index de72514db..63cb39aa3 100644
--- a/tests/float/builtin_float_round.py
+++ b/tests/float/builtin_float_round.py
@@ -15,3 +15,10 @@ for i in range(11):
# test second arg
for i in range(-1, 3):
print(round(1.47, i))
+
+# test inf and nan
+for val in (float('inf'), float('nan')):
+ try:
+ round(val)
+ except (ValueError, OverflowError) as e:
+ print(type(e))
diff --git a/tests/float/builtin_float_round_intbig.py b/tests/float/builtin_float_round_intbig.py
new file mode 100644
index 000000000..2083e3ea3
--- /dev/null
+++ b/tests/float/builtin_float_round_intbig.py
@@ -0,0 +1,4 @@
+# test round() with floats that return large integers
+
+for x in (-1e25, 1e25):
+ print('%.3g' % round(x))
diff --git a/tests/float/bytearray_construct.py b/tests/float/bytearray_construct.py
index f72926635..db946a99d 100644
--- a/tests/float/bytearray_construct.py
+++ b/tests/float/bytearray_construct.py
@@ -1,5 +1,10 @@
# test construction of bytearray from array with float type
-from array import array
+try:
+ from array import array
+except ImportError:
+ import sys
+ print("SKIP")
+ sys.exit()
print(bytearray(array('f', [1, 2.3])))
diff --git a/tests/float/bytes_construct.py b/tests/float/bytes_construct.py
index 0a57e08a2..8664d7296 100644
--- a/tests/float/bytes_construct.py
+++ b/tests/float/bytes_construct.py
@@ -1,5 +1,10 @@
# test construction of bytearray from array with float type
-from array import array
+try:
+ from array import array
+except ImportError:
+ import sys
+ print("SKIP")
+ sys.exit()
print(bytes(array('f', [1, 2.3])))
diff --git a/tests/float/complex1.py b/tests/float/complex1.py
index 8c8d285e1..a6038de04 100644
--- a/tests/float/complex1.py
+++ b/tests/float/complex1.py
@@ -41,6 +41,10 @@ print(1j == 1j)
print(abs(1j))
print("%.5g" % abs(1j + 2))
+# builtin hash
+print(hash(1 + 0j))
+print(type(hash(1j)))
+
# float on lhs should delegate to complex
print(1.2 + 3j)
diff --git a/tests/float/math_fun_int.py b/tests/float/math_fun_int.py
new file mode 100644
index 000000000..ee54f0995
--- /dev/null
+++ b/tests/float/math_fun_int.py
@@ -0,0 +1,15 @@
+# test the math functions that return ints
+
+try:
+ import math
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
+
+for fun in (math.ceil, math.floor, math.trunc):
+ for x in (-1.6, -0.2, 0, 0.6, 1.4, float('inf'), float('nan')):
+ try:
+ print(fun(x))
+ except (ValueError, OverflowError) as e:
+ print(type(e))
diff --git a/tests/float/math_fun_intbig.py b/tests/float/math_fun_intbig.py
new file mode 100644
index 000000000..962c10daa
--- /dev/null
+++ b/tests/float/math_fun_intbig.py
@@ -0,0 +1,12 @@
+# test the math functions that return ints, with very large results
+
+try:
+ import math
+except ImportError:
+ print("SKIP")
+ import sys
+ sys.exit()
+
+for fun in (math.ceil, math.floor, math.trunc):
+ for x in (-1e25, 1e25):
+ print('%.3g' % fun(x))
diff --git a/tests/micropython/heapalloc_iter.py b/tests/micropython/heapalloc_iter.py
index e1ed3daa3..45d3519e4 100644
--- a/tests/micropython/heapalloc_iter.py
+++ b/tests/micropython/heapalloc_iter.py
@@ -1,10 +1,15 @@
# test that iterating doesn't use the heap
+try:
+ import array
+except ImportError:
+ import sys
+ print("SKIP")
+ sys.exit()
try:
from micropython import heap_lock, heap_unlock
except (ImportError, AttributeError):
heap_lock = heap_unlock = lambda:0
-import array
def do_iter(l):
for i in l:
@@ -20,7 +25,7 @@ ar = array.array('H', (123, 456))
t = (1, 2, 3)
l = [1, 2]
d = {1:2}
-s = {1}
+s = set((1,))
fs = frozenset((1,))
g1 = (100 + x for x in range(2))
g2 = gen_func()
diff --git a/tests/micropython/heapalloc_str.py b/tests/micropython/heapalloc_str.py
index 0df39d3c0..39aa56ccd 100644
--- a/tests/micropython/heapalloc_str.py
+++ b/tests/micropython/heapalloc_str.py
@@ -3,6 +3,7 @@ import micropython
micropython.heap_lock()
+# Concatenating empty string returns original string
b"" + b""
b"" + b"1"
b"2" + b""
@@ -11,4 +12,7 @@ b"2" + b""
"" + "1"
"2" + ""
+# If no replacements done, returns original string
+"foo".replace(",", "_")
+
micropython.heap_unlock()
diff --git a/tests/micropython/schedule.py b/tests/micropython/schedule.py
new file mode 100644
index 000000000..3d584eea4
--- /dev/null
+++ b/tests/micropython/schedule.py
@@ -0,0 +1,61 @@
+# test micropython.schedule() function
+
+import micropython
+
+try:
+ micropython.schedule
+except AttributeError:
+ print('SKIP')
+ import sys
+ sys.exit()
+
+# Basic test of scheduling a function.
+
+def callback(arg):
+ global done
+ print(arg)
+ done = True
+
+done = False
+micropython.schedule(callback, 1)
+while not done:
+ pass
+
+# Test that callbacks can be scheduled from within a callback, but
+# that they don't execute until the outer callback is finished.
+
+def callback_inner(arg):
+ global done
+ print('inner')
+ done += 1
+
+def callback_outer(arg):
+ global done
+ micropython.schedule(callback_inner, 0)
+ # need a loop so that the VM can check for pending events
+ for i in range(2):
+ pass
+ print('outer')
+ done += 1
+
+done = 0
+micropython.schedule(callback_outer, 0)
+while done != 2:
+ pass
+
+# Test that scheduling too many callbacks leads to an exception. To do this we
+# must schedule from within a callback to guarantee that the scheduler is locked.
+
+def callback(arg):
+ global done
+ try:
+ for i in range(100):
+ micropython.schedule(lambda x:x, None)
+ except RuntimeError:
+ print('RuntimeError')
+ done = True
+
+done = False
+micropython.schedule(callback, None)
+while not done:
+ pass
diff --git a/tests/micropython/schedule.py.exp b/tests/micropython/schedule.py.exp
new file mode 100644
index 000000000..c4a3e1227
--- /dev/null
+++ b/tests/micropython/schedule.py.exp
@@ -0,0 +1,4 @@
+1
+outer
+inner
+RuntimeError
diff --git a/tests/run-tests b/tests/run-tests
index b1bb7dd84..87d12ba36 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -201,6 +201,7 @@ def run_tests(pyb, tests, args):
skip_int_big = False
skip_set_type = False
skip_async = False
+ skip_const = False
# Check if micropython.native is supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/native_check.py')
@@ -222,6 +223,11 @@ def run_tests(pyb, tests, args):
if native == b'CRASH':
skip_async = True
+ # Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not
+ native = run_micropython(pyb, args, 'feature_check/const.py')
+ if native == b'CRASH':
+ skip_const = True
+
# Check if emacs repl is supported, and skip such tests if it's not
t = run_micropython(pyb, args, 'feature_check/repl_emacs_check.py')
if not 'True' in str(t, 'ascii'):
@@ -243,6 +249,7 @@ def run_tests(pyb, tests, args):
if not has_complex:
skip_tests.add('float/complex1.py')
+ skip_tests.add('float/complex1_intbig.py')
skip_tests.add('float/int_big_float.py')
skip_tests.add('float/true_value.py')
skip_tests.add('float/types.py')
@@ -279,11 +286,14 @@ def run_tests(pyb, tests, args):
skip_tests.add('extmod/urandom_basic.py') # requires urandom
skip_tests.add('extmod/urandom_extra.py') # requires urandom
elif args.target == 'esp8266':
- skip_tests.add('float/float2int.py') # requires at least fp32, there's float2int_fp30.py instead
+ skip_tests.add('float/float2int_intbig.py') # requires at least fp32, there's float2int_fp30_intbig.py instead
skip_tests.add('float/string_format.py') # requires at least fp32, there's string_format_fp30.py instead
skip_tests.add('float/bytes_construct.py') # requires fp32
skip_tests.add('float/bytearray_construct.py') # requires fp32
skip_tests.add('misc/rge_sm.py') # too large
+ elif args.target == 'minimal':
+ skip_tests.add('misc/rge_sm.py') # too large
+ skip_tests.add('micropython/opt_level.py') # don't assume line numbers are stored
# Some tests are known to fail on 64-bit machines
if pyb is None and platform.architecture()[0] == '64bit':
@@ -319,6 +329,7 @@ def run_tests(pyb, tests, args):
skip_tests.add('misc/sys_exc_info.py') # sys.exc_info() is not supported for native
skip_tests.add('micropython/heapalloc_traceback.py') # because native doesn't have proper traceback info
skip_tests.add('micropython/heapalloc_iter.py') # requires generators
+ skip_tests.add('micropython/schedule.py') # native code doesn't check pending events
for test_file in tests:
test_file = test_file.replace('\\', '/')
@@ -329,6 +340,7 @@ def run_tests(pyb, tests, args):
is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig")
is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset")
is_async = test_name.startswith("async_")
+ is_const = test_name.startswith("const")
skip_it = test_file in skip_tests
skip_it |= skip_native and is_native
@@ -336,6 +348,7 @@ def run_tests(pyb, tests, args):
skip_it |= skip_int_big and is_int_big
skip_it |= skip_set_type and is_set_type
skip_it |= skip_async and is_async
+ skip_it |= skip_const and is_const
if skip_it:
print("skip ", test_file)
@@ -420,7 +433,7 @@ def main():
cmd_parser.add_argument('files', nargs='*', help='input test files')
args = cmd_parser.parse_args()
- EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266')
+ EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'minimal')
if args.target in EXTERNAL_TARGETS:
import pyboard
pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password)
@@ -435,7 +448,7 @@ def main():
if args.target == 'pyboard':
# run pyboard tests
test_dirs = ('basics', 'micropython', 'float', 'misc', 'stress', 'extmod', 'pyb', 'pybnative', 'inlineasm')
- elif args.target == 'esp8266':
+ elif args.target in ('esp8266', 'minimal'):
test_dirs = ('basics', 'micropython', 'float', 'misc', 'extmod')
elif args.target == 'wipy':
# run WiPy tests
@@ -455,7 +468,10 @@ def main():
# clear search path to make sure tests use only builtin modules
os.environ['MICROPYPATH'] = ''
- if not run_tests(pyb, tests, args):
+ res = run_tests(pyb, tests, args)
+ if pyb:
+ pyb.close()
+ if not res:
sys.exit(1)
if __name__ == "__main__":
diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp
index 32117aba4..416993887 100644
--- a/tests/unix/extra_coverage.py.exp
+++ b/tests/unix/extra_coverage.py.exp
@@ -46,6 +46,17 @@ Warning: test
# binary
122
456
+# scheduler
+sched(0)=1
+sched(1)=1
+sched(2)=1
+sched(3)=1
+sched(4)=0
+unlocked
+3
+2
+1
+0
0123456789 b'0123456789'
7300
7300
diff --git a/tools/pyboard.py b/tools/pyboard.py
index d4ce8b788..5eac030bd 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -39,6 +39,7 @@ Or:
import sys
import time
+import os
try:
stdout = sys.stdout.buffer
@@ -116,9 +117,93 @@ class TelnetToSerial:
else:
return n_waiting
+
+class ProcessToSerial:
+ "Execute a process and emulate serial connection using its stdin/stdout."
+
+ def __init__(self, cmd):
+ import subprocess
+ self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=True, preexec_fn=os.setsid,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+ # Initially was implemented with selectors, but that adds Python3
+ # dependency. However, there can be race conditions communicating
+ # with a particular child process (like QEMU), and selectors may
+ # still work better in that case, so left inplace for now.
+ #
+ #import selectors
+ #self.sel = selectors.DefaultSelector()
+ #self.sel.register(self.subp.stdout, selectors.EVENT_READ)
+
+ import select
+ self.poll = select.poll()
+ self.poll.register(self.subp.stdout.fileno())
+
+ def close(self):
+ import signal
+ os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM)
+
+ def read(self, size=1):
+ data = b""
+ while len(data) < size:
+ data += self.subp.stdout.read(size - len(data))
+ return data
+
+ def write(self, data):
+ self.subp.stdin.write(data)
+ return len(data)
+
+ def inWaiting(self):
+ #res = self.sel.select(0)
+ res = self.poll.poll(0)
+ if res:
+ return 1
+ return 0
+
+
+class ProcessPtyToTerminal:
+ """Execute a process which creates a PTY and prints slave PTY as
+ first line of its output, and emulate serial connection using
+ this PTY."""
+
+ def __init__(self, cmd):
+ import subprocess
+ import re
+ import serial
+ self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=False, preexec_fn=os.setsid,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pty_line = self.subp.stderr.readline().decode("utf-8")
+ m = re.search(r"/dev/pts/[0-9]+", pty_line)
+ if not m:
+ print("Error: unable to find PTY device in startup line:", pty_line)
+ self.close()
+ sys.exit(1)
+ pty = m.group()
+ # rtscts, dsrdtr params are to workaround pyserial bug:
+ # http://stackoverflow.com/questions/34831131/pyserial-does-not-play-well-with-virtual-port
+ self.ser = serial.Serial(pty, interCharTimeout=1, rtscts=True, dsrdtr=True)
+
+ def close(self):
+ import signal
+ os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM)
+
+ def read(self, size=1):
+ return self.ser.read(size)
+
+ def write(self, data):
+ return self.ser.write(data)
+
+ def inWaiting(self):
+ return self.ser.inWaiting()
+
+
class Pyboard:
def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0):
- if device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3:
+ if device.startswith("exec:"):
+ self.serial = ProcessToSerial(device[len("exec:"):])
+ elif device.startswith("execpty:"):
+ self.serial = ProcessPtyToTerminal(device[len("qemupty:"):])
+ elif device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3:
# device looks like an IP address
self.serial = TelnetToSerial(device, user, password, read_timeout=10)
else:
@@ -234,7 +319,7 @@ class Pyboard:
# check if we could exec command
data = self.serial.read(2)
if data != b'OK':
- raise PyboardError('could not exec command')
+ raise PyboardError('could not exec command (response: %s)' % data)
def exec_raw(self, command, timeout=10, data_consumer=None):
self.exec_raw_no_follow(command);
@@ -300,6 +385,7 @@ def main():
pyb.enter_raw_repl()
except PyboardError as er:
print(er)
+ pyb.close()
sys.exit(1)
def execbuffer(buf):
@@ -307,6 +393,7 @@ def main():
ret, ret_err = pyb.exec_raw(buf, timeout=None, data_consumer=stdout_write_bytes)
except PyboardError as er:
print(er)
+ pyb.close()
sys.exit(1)
except KeyboardInterrupt:
sys.exit(1)
diff --git a/unix/Makefile b/unix/Makefile
index 83bd3f984..546985306 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -17,13 +17,12 @@ include ../py/py.mk
INC += -I.
INC += -I..
-INC += -I../lib/timeutils
INC += -I$(BUILD)
# compiler settings
CWARN = -Wall -Werror
CWARN += -Wpointer-arith -Wuninitialized
-CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
+CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
# Debugging/Optimization
ifdef DEBUG
diff --git a/unix/alloc.c b/unix/alloc.c
index 04c635ee9..54fc1d3c4 100644
--- a/unix/alloc.c
+++ b/unix/alloc.c
@@ -49,7 +49,7 @@ typedef struct _mmap_region_t {
struct _mmap_region_t *next;
} mmap_region_t;
-void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) {
+void mp_unix_alloc_exec(size_t min_size, void **ptr, size_t *size) {
// size needs to be a multiple of the page size
*size = (min_size + 0xfff) & (~0xfff);
*ptr = mmap(NULL, *size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
@@ -65,7 +65,7 @@ void mp_unix_alloc_exec(mp_uint_t min_size, void **ptr, mp_uint_t *size) {
MP_STATE_VM(mmap_region_head) = rg;
}
-void mp_unix_free_exec(void *ptr, mp_uint_t size) {
+void mp_unix_free_exec(void *ptr, size_t size) {
munmap(ptr, size);
// unlink the mmap'd region from the list
@@ -93,7 +93,7 @@ void *ffi_closure_alloc(size_t size, void **code);
void ffi_closure_free(void *ptr);
void *ffi_closure_alloc(size_t size, void **code) {
- mp_uint_t dummy;
+ size_t dummy;
mp_unix_alloc_exec(size, code, &dummy);
return *code;
}
diff --git a/unix/coverage.c b/unix/coverage.c
index ca236c430..09959525a 100644
--- a/unix/coverage.c
+++ b/unix/coverage.c
@@ -292,6 +292,35 @@ STATIC mp_obj_t extra_coverage(void) {
mp_printf(&mp_plat_print, "%.0lf\n", dar[0]);
}
+ // scheduler
+ {
+ mp_printf(&mp_plat_print, "# scheduler\n");
+
+ // lock scheduler
+ mp_sched_lock();
+
+ // schedule multiple callbacks; last one should fail
+ for (int i = 0; i < 5; ++i) {
+ mp_printf(&mp_plat_print, "sched(%d)=%d\n", i, mp_sched_schedule(MP_OBJ_FROM_PTR(&mp_builtin_print_obj), MP_OBJ_NEW_SMALL_INT(i)));
+ }
+
+ // test nested locking/unlocking
+ mp_sched_lock();
+ mp_sched_unlock();
+
+ // shouldn't do anything while scheduler is locked
+ mp_handle_pending();
+
+ // unlock scheduler
+ mp_sched_unlock();
+ mp_printf(&mp_plat_print, "unlocked\n");
+
+ // drain pending callbacks
+ while (mp_sched_num_pending()) {
+ mp_handle_pending();
+ }
+ }
+
mp_obj_streamtest_t *s = m_new_obj(mp_obj_streamtest_t);
s->base.type = &mp_type_stest_fileio;
s->buf = NULL;
diff --git a/unix/main.c b/unix/main.c
index 01ebdce17..a1c204cab 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -437,7 +437,7 @@ MP_NOINLINE int main_(int argc, char **argv) {
path = "~/.micropython/lib:/usr/lib/micropython";
#endif
}
- mp_uint_t path_num = 1; // [0] is for current dir (or base dir of the script)
+ size_t path_num = 1; // [0] is for current dir (or base dir of the script)
if (*path == ':') {
path_num++;
}
diff --git a/unix/modffi.c b/unix/modffi.c
index 74194e2cc..7a35d61ef 100644
--- a/unix/modffi.c
+++ b/unix/modffi.c
@@ -126,8 +126,7 @@ STATIC ffi_type *char2ffi_type(char c)
STATIC ffi_type *get_ffi_type(mp_obj_t o_in)
{
if (MP_OBJ_IS_STR(o_in)) {
- mp_uint_t len;
- const char *s = mp_obj_str_get_data(o_in, &len);
+ const char *s = mp_obj_str_get_str(o_in);
ffi_type *t = char2ffi_type(*s);
if (t != NULL) {
return t;
diff --git a/unix/modos.c b/unix/modos.c
index d6e6a8fb3..8e746c163 100644
--- a/unix/modos.c
+++ b/unix/modos.c
@@ -46,8 +46,7 @@
STATIC mp_obj_t mod_os_stat(mp_obj_t path_in) {
struct stat sb;
- mp_uint_t len;
- const char *path = mp_obj_str_get_data(path_in, &len);
+ const char *path = mp_obj_str_get_str(path_in);
int res = stat(path, &sb);
RAISE_ERRNO(res, errno);
@@ -87,8 +86,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_stat_obj, mod_os_stat);
STATIC mp_obj_t mod_os_statvfs(mp_obj_t path_in) {
STRUCT_STATVFS sb;
- mp_uint_t len;
- const char *path = mp_obj_str_get_data(path_in, &len);
+ const char *path = mp_obj_str_get_str(path_in);
int res = STATVFS(path, &sb);
RAISE_ERRNO(res, errno);
@@ -110,8 +108,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_os_statvfs_obj, mod_os_statvfs);
#endif
STATIC mp_obj_t mod_os_unlink(mp_obj_t path_in) {
- mp_uint_t len;
- const char *path = mp_obj_str_get_data(path_in, &len);
+ const char *path = mp_obj_str_get_str(path_in);
int r = unlink(path);
diff --git a/unix/modtermios.c b/unix/modtermios.c
index 2cb5f26df..5e82e772a 100644
--- a/unix/modtermios.c
+++ b/unix/modtermios.c
@@ -90,8 +90,7 @@ STATIC mp_obj_t mod_termios_tcsetattr(mp_obj_t fd_in, mp_obj_t when_in, mp_obj_t
if (i == VMIN || i == VTIME) {
term.c_cc[i] = mp_obj_get_int(cc->items[i]);
} else {
- mp_uint_t len;
- term.c_cc[i] = *mp_obj_str_get_data(cc->items[i], &len);
+ term.c_cc[i] = *mp_obj_str_get_str(cc->items[i]);
}
}
diff --git a/unix/modtime.c b/unix/modtime.c
index 85d1f5532..080d321ee 100644
--- a/unix/modtime.c
+++ b/unix/modtime.c
@@ -108,9 +108,7 @@ STATIC mp_obj_t mod_time_sleep(mp_obj_t arg) {
if (res != -1 || errno != EINTR) {
break;
}
- if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
- return mp_const_none;
- }
+ mp_handle_pending();
//printf("select: EINTR: %ld:%ld\n", tv.tv_sec, tv.tv_usec);
#else
break;
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 66de0fa96..7ecfc28c0 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -217,6 +217,9 @@ extern const struct _mp_obj_module_t mp_module_jni;
// type definitions for the specific machine
+// For size_t and ssize_t
+#include <unistd.h>
+
// assume that if we already defined the obj repr then we also defined types
#ifndef MICROPY_OBJ_REPR
#ifdef __LP64__
@@ -230,8 +233,6 @@ typedef unsigned int mp_uint_t; // must be pointer size
#endif
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
@@ -239,8 +240,8 @@ typedef long long mp_off_t;
typedef long mp_off_t;
#endif
-void mp_unix_alloc_exec(mp_uint_t min_size, void** ptr, mp_uint_t *size);
-void mp_unix_free_exec(void *ptr, mp_uint_t size);
+void mp_unix_alloc_exec(size_t min_size, void** ptr, size_t *size);
+void mp_unix_free_exec(void *ptr, size_t size);
void mp_unix_mark_exec(void);
#define MP_PLAT_ALLOC_EXEC(min_size, ptr, size) mp_unix_alloc_exec(min_size, ptr, size)
#define MP_PLAT_FREE_EXEC(ptr, size) mp_unix_free_exec(ptr, size)
@@ -253,7 +254,6 @@ void mp_unix_mark_exec(void);
#if MICROPY_PY_OS_DUPTERM
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#else
-#include <unistd.h>
#define MP_PLAT_PRINT_STRN(str, len) do { ssize_t ret = write(1, str, len); (void)ret; } while (0)
#endif
diff --git a/unix/mpconfigport_coverage.h b/unix/mpconfigport_coverage.h
index 9df8d0fca..387e182db 100644
--- a/unix/mpconfigport_coverage.h
+++ b/unix/mpconfigport_coverage.h
@@ -32,6 +32,7 @@
#include <mpconfigport.h>
+#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_PY_DELATTR_SETATTR (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
diff --git a/unix/mpconfigport_minimal.h b/unix/mpconfigport_minimal.h
index 65e35c8d9..788c8519d 100644
--- a/unix/mpconfigport_minimal.h
+++ b/unix/mpconfigport_minimal.h
@@ -127,8 +127,6 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
typedef long long mp_off_t;
diff --git a/windows/.gitignore b/windows/.gitignore
index ec2821211..12235e7c9 100644
--- a/windows/.gitignore
+++ b/windows/.gitignore
@@ -7,4 +7,5 @@
*.ilk
*.filters
/build/*
+.vs/*
*.VC.*db
diff --git a/windows/Makefile b/windows/Makefile
index 68de66a07..72c97381b 100644
--- a/windows/Makefile
+++ b/windows/Makefile
@@ -15,7 +15,7 @@ INC += -I..
INC += -I$(BUILD)
# compiler settings
-CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT)
+CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -DUNIX -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS_MOD) $(COPT)
LDFLAGS = $(LDFLAGS_MOD) -lm
# Debugging/Optimization
diff --git a/windows/micropython.vcxproj b/windows/micropython.vcxproj
index 6f6e11ab4..ee0b98abb 100644
--- a/windows/micropython.vcxproj
+++ b/windows/micropython.vcxproj
@@ -26,26 +26,26 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
- <PlatformToolset>v140</PlatformToolset>
+ <PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index 6156ad39e..844e2618f 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -128,8 +128,6 @@ typedef int mp_int_t; // must be pointer size
typedef unsigned int mp_uint_t; // must be pointer size
#endif
-#define BYTES_PER_WORD sizeof(mp_int_t)
-
// Just assume Windows is little-endian - mingw32 gcc doesn't
// define standard endianness macros.
#define MP_ENDIANNESS_LITTLE (1)
diff --git a/windows/msvc/genhdr.targets b/windows/msvc/genhdr.targets
index 8c2ba8eb2..afe5f5d76 100644
--- a/windows/msvc/genhdr.targets
+++ b/windows/msvc/genhdr.targets
@@ -87,6 +87,10 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
<MSBuild Projects="$(MSBuildThisFileFullPath)" Targets="CopyFileIfDifferent" Properties="SourceFile=$(TmpFile);DestFile=$(DestFile)"/>
</Target>
+ <Target Name="RemoveGeneratedFiles" AfterTargets="Clean">
+ <RemoveDir Directories="$(DestDir)"/>
+ </Target>
+
<!--Copies SourceFile to DestFile only if SourceFile's content differs from DestFile's.
We use this to 'touch' the generated files only when they are really newer
so a build is only triggered if the generated content actually changed,
diff --git a/zephyr/Makefile b/zephyr/Makefile
index 7a0d05298..057a88862 100644
--- a/zephyr/Makefile
+++ b/zephyr/Makefile
@@ -18,7 +18,6 @@ MICROPY_HEAP_SIZE = 16384
FROZEN_DIR = scripts
# 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)
@@ -34,6 +33,7 @@ INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os
SRC_C = main.c \
help.c \
+ modusocket.c \
modutime.c \
modzephyr.c \
modmachine.c \
@@ -57,7 +57,12 @@ CFLAGS = $(KBUILD_CFLAGS) $(NOSTDINC_FLAGS) $(ZEPHYRINCLUDE) \
include ../py/mkrules.mk
$(Z_EXPORTS): $(CONF_FILE)
- $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE) initconfig outputexports
+ # We use single target here ($(Z_EXPORTS)) for simplicity, but actually
+ # number of things get generated here: 'initconfig' generates C header for
+ # Kconfig configuration, 'outputexports' generates make environment with CC,
+ # etc., and 'lib' generates other headers which may be included by zephyr.h,
+ # e.g. DTS-related.
+ $(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE) initconfig outputexports lib
GENERIC_TARGETS = all zephyr run qemu qemugdb flash debug
KCONFIG_TARGETS = \
@@ -71,15 +76,13 @@ $(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) CONF_FILE=$(CONF_FILE) $@
-$(LIBMICROPYTHON): $(Z_SYSGEN_H)
-build/genhdr/qstr.i.last: $(Z_SYSGEN_H)
+$(LIBMICROPYTHON): | $(Z_EXPORTS)
+build/genhdr/qstr.i.last: | $(Z_EXPORTS)
-$(Z_SYSGEN_H):
- rm -f $(LIBMICROPYTHON)
- -$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE)
+# If we recreate libmicropython, also cause zephyr.bin relink
+LIBMICROPYTHON_EXTRA_CMD = -$(RM) -f outdir/$(OUTDIR_PREFIX)/zephyr.lnk
# Clean Zephyr things too
clean: z_clean
@@ -90,3 +93,6 @@ z_clean:
.PHONY: prj.conf
prj.conf: prj_base.conf
$(PYTHON) makeprj.py prj_base.conf prj_$(BOARD).conf $@
+
+test:
+ cd ../tests && ./run-tests --target minimal --device "execpty:make -C ../zephyr run BOARD=$(BOARD) QEMU_PTY=1"
diff --git a/zephyr/machine_pin.c b/zephyr/machine_pin.c
index 049255e9f..5bf273909 100644
--- a/zephyr/machine_pin.c
+++ b/zephyr/machine_pin.c
@@ -81,7 +81,7 @@ STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, mp_uint_t n
}
// constructor(drv_name, pin, ...)
-STATIC mp_obj_t machine_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted port
@@ -154,6 +154,24 @@ STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
+STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ (void)errcode;
+ machine_pin_obj_t *self = self_in;
+
+ switch (request) {
+ case MP_PIN_READ: {
+ uint32_t pin_val;
+ gpio_pin_read(self->port, self->pin, &pin_val);
+ return pin_val;
+ }
+ case MP_PIN_WRITE: {
+ gpio_pin_write(self->port, self->pin, arg);
+ return 0;
+ }
+ }
+ return -1;
+}
+
STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&machine_pin_init_obj },
@@ -170,11 +188,16 @@ STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
+STATIC const mp_pin_p_t machine_pin_pin_p = {
+ .ioctl = machine_pin_ioctl,
+};
+
const mp_obj_type_t machine_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = machine_pin_print,
- .make_new = machine_pin_make_new,
+ .make_new = mp_pin_make_new,
.call = machine_pin_call,
+ .protocol = &machine_pin_pin_p,
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
};
diff --git a/zephyr/modmachine.c b/zephyr/modmachine.c
index 6194a95da..4013815d1 100644
--- a/zephyr/modmachine.c
+++ b/zephyr/modmachine.c
@@ -32,6 +32,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/machine_mem.h"
+#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
#include "extmod/machine_i2c.h"
#include "modmachine.h"
@@ -56,6 +57,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
// reset causes
/*{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },*/
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
new file mode 100644
index 000000000..36ccdbc3b
--- /dev/null
+++ b/zephyr/modusocket.c
@@ -0,0 +1,456 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2017 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"
+#ifdef MICROPY_PY_USOCKET
+
+#include "py/runtime.h"
+
+#include <stdio.h>
+#include <zephyr.h>
+// Zephyr's generated version header
+#include <version.h>
+#include <net/net_context.h>
+#include <net/nbuf.h>
+
+#if 0 // print debugging info
+#define DEBUG_printf printf
+#else // don't print debugging info
+#define DEBUG_printf(...) (void)0
+#endif
+
+typedef struct _socket_obj_t {
+ mp_obj_base_t base;
+ struct net_context *ctx;
+ union {
+ struct k_fifo recv_q;
+ struct k_fifo accept_q;
+ };
+ struct net_buf *cur_buf;
+
+ #define STATE_NEW 0
+ #define STATE_CONNECTING 1
+ #define STATE_CONNECTED 2
+ #define STATE_PEER_CLOSED 3
+ int8_t state;
+} socket_obj_t;
+
+STATIC const mp_obj_type_t socket_type;
+
+// k_fifo extended API
+
+static inline void *_k_fifo_peek_head(struct k_fifo *fifo)
+{
+#if KERNEL_VERSION_NUMBER < 0x010763 /* 1.7.99 */
+ return sys_slist_peek_head(&fifo->data_q);
+#else
+ return sys_slist_peek_head(&fifo->_queue.data_q);
+#endif
+}
+
+static inline void *_k_fifo_peek_tail(struct k_fifo *fifo)
+{
+#if KERNEL_VERSION_NUMBER < 0x010763 /* 1.7.99 */
+ return sys_slist_peek_tail(&fifo->data_q);
+#else
+ return sys_slist_peek_tail(&fifo->_queue.data_q);
+#endif
+}
+
+static inline void _k_fifo_wait_non_empty(struct k_fifo *fifo, int32_t timeout)
+{
+ struct k_poll_event events[] = {
+ K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, fifo),
+ };
+
+ k_poll(events, MP_ARRAY_SIZE(events), timeout);
+ DEBUG_printf("poll res: %d\n", events[0].state);
+}
+
+// Helper functions
+
+#define RAISE_ERRNO(x) { int _err = x; if (_err < 0) mp_raise_OSError(-_err); }
+
+STATIC void socket_check_closed(socket_obj_t *socket) {
+ if (socket->ctx == NULL) {
+ // already closed
+ mp_raise_OSError(EBADF);
+ }
+}
+
+STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct sockaddr *sockaddr) {
+ // We employ the fact that port and address offsets are the same for IPv4 & IPv6
+ struct sockaddr_in *sockaddr_in = (struct sockaddr_in*)sockaddr;
+
+ mp_obj_t *addr_items;
+ mp_obj_get_array_fixed_n(addr_in, 2, &addr_items);
+ sockaddr_in->sin_family = net_context_get_family(socket->ctx);
+ RAISE_ERRNO(net_addr_pton(sockaddr_in->sin_family, mp_obj_str_get_str(addr_items[0]), &sockaddr_in->sin_addr));
+ sockaddr_in->sin_port = htons(mp_obj_get_int(addr_items[1]));
+}
+
+// Copy data from Zephyr net_buf chain into linear buffer.
+// We don't use net_nbuf_read(), because it's weird (e.g., we'd like to
+// free processed data fragment ASAP, while net_nbuf_read() holds onto
+// the whole fragment chain to do its deeds, and that's minor comparing
+// to the fact that it copies data byte by byte).
+static char *net_buf_gather(struct net_buf *buf, char *to, unsigned max_len) {
+ struct net_buf *tmp = buf->frags;
+ unsigned header_len = net_nbuf_appdata(buf) - tmp->data;
+ net_buf_pull(tmp, header_len);
+
+ while (tmp && max_len) {
+ unsigned len = tmp->len;
+ if (len > max_len) {
+ len = max_len;
+ }
+ memcpy(to, tmp->data, len);
+ to += len;
+ max_len -= len;
+ tmp = net_buf_frag_del(buf, tmp);
+ }
+
+ return to;
+}
+
+// Callback for incoming packets.
+static void sock_received_cb(struct net_context *context, struct net_buf *net_buf, int status, void *user_data) {
+ socket_obj_t *socket = (socket_obj_t*)user_data;
+ DEBUG_printf("recv cb: context: %p, status: %d, buf: %p", context, status, net_buf);
+ if (net_buf) {
+ DEBUG_printf(" (sz=%d, l=%d), token: %p", net_buf->size, net_buf->len, net_nbuf_token(net_buf));
+ }
+ DEBUG_printf("\n");
+
+ // if net_buf == NULL, EOF
+ if (net_buf == NULL) {
+ struct net_buf *last_buf = _k_fifo_peek_tail(&socket->recv_q);
+ if (last_buf == NULL) {
+ socket->state = STATE_PEER_CLOSED;
+ DEBUG_printf("Marked socket %p as peer-closed\n", socket);
+ } else {
+ // We abuse "buf_sent" flag to store EOF flag
+ net_nbuf_set_buf_sent(last_buf, true);
+ DEBUG_printf("Set EOF flag on %p\n", last_buf);
+ }
+ return;
+ }
+
+ // Make sure that "EOF flag" is not set
+ net_nbuf_set_buf_sent(net_buf, false);
+
+ // net_buf->frags will be overwritten by fifo, so save it
+ net_nbuf_set_token(net_buf, net_buf->frags);
+ k_fifo_put(&socket->recv_q, net_buf);
+}
+
+// Callback for incoming connections.
+static void sock_accepted_cb(struct net_context *new_ctx, struct sockaddr *addr, socklen_t addrlen, int status, void *user_data) {
+ socket_obj_t *socket = (socket_obj_t*)user_data;
+ DEBUG_printf("accept cb: context: %p, status: %d, new ctx: %p\n", socket->ctx, status, new_ctx);
+ DEBUG_printf("new_ctx ref_cnt: %d\n", new_ctx->refcount);
+
+ k_fifo_put(&socket->accept_q, new_ctx);
+}
+
+socket_obj_t *socket_new(void) {
+ socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
+ socket->base.type = (mp_obj_t)&socket_type;
+ k_fifo_init(&socket->recv_q);
+ socket->cur_buf = NULL;
+ socket->state = STATE_NEW;
+ return socket;
+}
+
+// Methods
+
+STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
+ socket_obj_t *self = self_in;
+ if (self->ctx == NULL) {
+ mp_printf(print, "<socket NULL>");
+ } else {
+ struct net_context *ctx = self->ctx;
+ mp_printf(print, "<socket %p type=%d>", ctx, net_context_get_type(ctx));
+ }
+}
+
+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) {
+ mp_arg_check_num(n_args, n_kw, 0, 4, false);
+
+ socket_obj_t *socket = socket_new();
+
+ int family = AF_INET;
+ int socktype = SOCK_STREAM;
+ int proto = -1;
+
+ if (n_args >= 1) {
+ family = mp_obj_get_int(args[0]);
+ if (n_args >= 2) {
+ socktype = mp_obj_get_int(args[1]);
+ if (n_args >= 3) {
+ proto = mp_obj_get_int(args[2]);
+ }
+ }
+ }
+
+ if (proto == -1) {
+ proto = IPPROTO_TCP;
+ if (socktype != SOCK_STREAM) {
+ proto = IPPROTO_UDP;
+ }
+ }
+
+ RAISE_ERRNO(net_context_get(family, socktype, proto, &socket->ctx));
+
+ return MP_OBJ_FROM_PTR(socket);
+}
+
+STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ struct sockaddr sockaddr;
+ parse_inet_addr(socket, addr_in, &sockaddr);
+
+ RAISE_ERRNO(net_context_bind(socket->ctx, &sockaddr, sizeof(sockaddr)));
+ // For DGRAM socket, we expect to receive packets after call to bind(),
+ // but for STREAM socket, next expected operation is listen(), which
+ // doesn't work if recv callback is set.
+ if (net_context_get_type(socket->ctx) == SOCK_DGRAM) {
+ DEBUG_printf("Setting recv cb after bind\n");
+ RAISE_ERRNO(net_context_recv(socket->ctx, sock_received_cb, K_NO_WAIT, socket));
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
+
+STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ struct sockaddr sockaddr;
+ parse_inet_addr(socket, addr_in, &sockaddr);
+
+ RAISE_ERRNO(net_context_connect(socket->ctx, &sockaddr, sizeof(sockaddr), NULL, K_FOREVER, NULL));
+ DEBUG_printf("Setting recv cb after connect()\n");
+ RAISE_ERRNO(net_context_recv(socket->ctx, sock_received_cb, K_NO_WAIT, socket));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
+
+STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ mp_int_t backlog = mp_obj_get_int(backlog_in);
+ RAISE_ERRNO(net_context_listen(socket->ctx, backlog));
+ RAISE_ERRNO(net_context_accept(socket->ctx, sock_accepted_cb, K_NO_WAIT, socket));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+
+STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ struct net_context *ctx = k_fifo_get(&socket->accept_q, K_FOREVER);
+ // Was overwritten by fifo
+ ctx->refcount = 1;
+
+ socket_obj_t *socket2 = socket_new();
+ socket2->ctx = ctx;
+ DEBUG_printf("Setting recv cb after accept()\n");
+ RAISE_ERRNO(net_context_recv(ctx, sock_received_cb, K_NO_WAIT, socket2));
+
+ mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
+ client->items[0] = MP_OBJ_FROM_PTR(socket2);
+ // TODO
+ client->items[1] = mp_const_none;
+
+ return MP_OBJ_FROM_PTR(client);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
+
+STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+
+ struct net_buf *send_buf = net_nbuf_get_tx(socket->ctx, K_FOREVER);
+ // TODO: Probably should limit how much data we send in one call still
+ if (!net_nbuf_append(send_buf, bufinfo.len, bufinfo.buf, K_FOREVER)) {
+ mp_raise_OSError(ENOSPC);
+ }
+
+ RAISE_ERRNO(net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL));
+
+ return mp_obj_new_int_from_uint(bufinfo.len);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
+
+STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ enum net_sock_type sock_type = net_context_get_type(socket->ctx);
+ mp_int_t max_len = mp_obj_get_int(len_in);
+ unsigned recv_len;
+ vstr_t vstr;
+
+ if (sock_type == SOCK_DGRAM) {
+
+ struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
+ // Restore ->frags overwritten by fifo
+ net_buf->frags = net_nbuf_token(net_buf);
+
+ recv_len = net_nbuf_appdatalen(net_buf);
+ DEBUG_printf("recv: net_buf=%p, appdatalen: %d\n", net_buf, recv_len);
+
+ if (recv_len > max_len) {
+ recv_len = max_len;
+ }
+
+ vstr_init_len(&vstr, recv_len);
+ net_buf_gather(net_buf, vstr.buf, recv_len);
+ net_nbuf_unref(net_buf);
+
+ } else if (sock_type == SOCK_STREAM) {
+
+ do {
+ if (socket->state == STATE_PEER_CLOSED) {
+ return mp_const_empty_bytes;
+ }
+
+ unsigned header_len = 0;
+ if (socket->cur_buf == NULL) {
+ DEBUG_printf("TCP recv: no cur_buf, getting\n");
+ struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
+ // Restore ->frags overwritten by fifo
+ net_buf->frags = net_nbuf_token(net_buf);
+
+ header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
+ DEBUG_printf("TCP recv: new cur_buf: %p, hdr_len: %u\n", net_buf, header_len);
+ socket->cur_buf = net_buf;
+ }
+
+ struct net_buf *frag = socket->cur_buf->frags;
+ if (frag == NULL) {
+ printf("net_buf has empty fragments on start!\n");
+ assert(0);
+ }
+
+ net_buf_pull(frag, header_len);
+ unsigned frag_len = frag->len;
+ recv_len = frag_len;
+ if (recv_len > max_len) {
+ recv_len = max_len;
+ }
+ DEBUG_printf("%d data bytes in head frag, going to read %d\n", frag_len, recv_len);
+
+ vstr_init_len(&vstr, recv_len);
+ memcpy(vstr.buf, frag->data, recv_len);
+
+ if (recv_len != frag_len) {
+ net_buf_pull(frag, recv_len);
+ } else {
+ frag = net_buf_frag_del(socket->cur_buf, frag);
+ if (frag == NULL) {
+ DEBUG_printf("Finished processing net_buf %p\n", socket->cur_buf);
+ // If "buf_sent" flag was set, it's last packet and we reached EOF
+ if (net_nbuf_buf_sent(socket->cur_buf)) {
+ socket->state = STATE_PEER_CLOSED;
+ }
+ net_nbuf_unref(socket->cur_buf);
+ socket->cur_buf = NULL;
+ }
+ }
+ // Keep repeating while we're getting empty fragments
+ // Zephyr IP stack appears to feed empty net_buf's with empty
+ // frags for various TCP control packets.
+ } while (recv_len == 0);
+
+ } else {
+ mp_not_implemented("");
+ }
+
+ mp_obj_t ret = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
+ 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 *socket = self_in;
+ if (socket->ctx != NULL) {
+ RAISE_ERRNO(net_context_put(socket->ctx));
+ socket->ctx = NULL;
+ }
+ 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___del__), (mp_obj_t)&socket_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_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 },
+};
+STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
+
+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 mp_module_usocket_globals_table[] = {
+ { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
+ // objects
+ { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
+ // class constants
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(AF_INET6) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
+
+const mp_obj_module_t mp_module_usocket = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&mp_module_usocket_globals,
+};
+
+#endif // MICROPY_PY_USOCKET
diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h
index e1e85df9c..2c57ede4d 100644
--- a/zephyr/mpconfigport.h
+++ b/zephyr/mpconfigport.h
@@ -27,6 +27,8 @@
// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles
#include "autoconf.h"
+// Included here to get basic Zephyr environment (macros, etc.)
+#include <zephyr.h>
// Usually passed from Makefile
#ifndef MICROPY_HEAP_SIZE
@@ -56,8 +58,14 @@
#define MICROPY_PY_IO (0)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_MACHINE (1)
+#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_PY_STRUCT (0)
+#ifdef CONFIG_NETWORKING
+// If we have networking, we likely want errno comfort
+#define MICROPY_PY_UERRNO (1)
+#define MICROPY_PY_USOCKET (1)
+#endif
#define MICROPY_PY_UTIME (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_ZEPHYR (1)
@@ -92,8 +100,6 @@ 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 \
@@ -101,8 +107,17 @@ typedef long mp_off_t;
extern const struct _mp_obj_module_t mp_module_machine;
extern const struct _mp_obj_module_t mp_module_time;
+extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_zephyr;
+#if MICROPY_PY_USOCKET
+#define MICROPY_PY_USOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) },
+#define MICROPY_PY_USOCKET_WEAK_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) },
+#else
+#define MICROPY_PY_USOCKET_DEF
+#define MICROPY_PY_USOCKET_WEAK_DEF
+#endif
+
#if MICROPY_PY_UTIME
#define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) },
#else
@@ -117,11 +132,13 @@ extern const struct _mp_obj_module_t mp_module_zephyr;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
+ MICROPY_PY_USOCKET_DEF \
MICROPY_PY_UTIME_DEF \
MICROPY_PY_ZEPHYR_DEF \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) }, \
+ MICROPY_PY_USOCKET_WEAK_DEF \
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
diff --git a/zephyr/mpconfigport_minimal.h b/zephyr/mpconfigport_minimal.h
index 459b0816c..772335c0a 100644
--- a/zephyr/mpconfigport_minimal.h
+++ b/zephyr/mpconfigport_minimal.h
@@ -27,6 +27,8 @@
// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles
#include "autoconf.h"
+// Included here to get basic Zephyr environment (macros, etc.)
+#include <zephyr.h>
// Usually passed from Makefile
#ifndef MICROPY_HEAP_SIZE
@@ -83,8 +85,6 @@ 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 \
diff --git a/zephyr/prj_base.conf b/zephyr/prj_base.conf
index 295963023..fc51ccec6 100644
--- a/zephyr/prj_base.conf
+++ b/zephyr/prj_base.conf
@@ -1,3 +1,5 @@
+CONFIG_LEGACY_KERNEL=n
+
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y
CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS=y
@@ -9,5 +11,13 @@ CONFIG_MAIN_STACK_SIZE=4096
CONFIG_NETWORKING=y
CONFIG_NET_IPV4=y
CONFIG_NET_IPV6=y
+CONFIG_NET_UDP=y
+CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_NBUF_RX_COUNT=5
+
+# Uncomment to enable "INFO" level net_buf logging
+#CONFIG_NET_LOG=y
+#CONFIG_NET_DEBUG_NET_BUF=y
+# Change to 4 for "DEBUG" level
+#CONFIG_SYS_LOG_NET_LEVEL=3
diff --git a/zephyr/src/zephyr_getchar.c b/zephyr/src/zephyr_getchar.c
index 95912f3df..52b3394d0 100644
--- a/zephyr/src/zephyr_getchar.c
+++ b/zephyr/src/zephyr_getchar.c
@@ -23,7 +23,7 @@
extern int mp_interrupt_char;
void mp_keyboard_interrupt(void);
-static struct nano_sem uart_sem;
+static struct k_sem uart_sem;
#define UART_BUFSIZE 256
static uint8_t uart_ringbuf[UART_BUFSIZE];
static uint8_t i_get, i_put;
@@ -44,6 +44,7 @@ static int console_irq_input_hook(uint8_t ch)
}
//printk("%x\n", ch);
k_sem_give(&uart_sem);
+ k_yield();
return 1;
}