diff options
| author | Scott Shawcroft <scott@chickadee.tech> | 2016-09-19 13:32:29 -0700 |
|---|---|---|
| committer | Scott Shawcroft <scott@chickadee.tech> | 2016-09-19 13:32:29 -0700 |
| commit | bb03afdb77c95b9cb23e531e5763167ccb09c8e4 (patch) | |
| tree | 509722778a03b10c933963a35c93eb5670a5cdb5 | |
| parent | 345dd1484c4e68f53ea242c5778a2de99119db9a (diff) | |
| parent | 60592fd23c8acd4ed4f70d8fbe8f8b11ea58082c (diff) | |
Merge remote-tracking branch 'micropython/master'
82 files changed, 925 insertions, 376 deletions
diff --git a/.travis.yml b/.travis.yml index f9ee2ab0f..8f164598e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,7 +12,7 @@ before_script: - sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded - sudo dpkg --add-architecture i386 - sudo apt-get update -qq || true - - sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system mingw32 + - sudo apt-get install -y python3 gcc-multilib pkg-config libffi-dev libffi-dev:i386 qemu-system gcc-mingw-w64 - sudo apt-get install -y --force-yes gcc-arm-none-eabi # For teensy build - sudo apt-get install realpath @@ -23,6 +23,7 @@ before_script: - python3 --version script: + - make -C mpy-cross - make -C minimal test - make -C unix deplibs - make -C unix @@ -35,7 +36,7 @@ script: - make -C teensy - make -C cc3200 BTARGET=application BTYPE=release - make -C cc3200 BTARGET=bootloader BTYPE=release - - make -C windows CROSS_COMPILE=i586-mingw32msvc- + - make -C windows CROSS_COMPILE=i686-w64-mingw32- # run tests without coverage info #- (cd tests && MICROPY_CPYTHON3=python3.4 ./run-tests) diff --git a/bare-arm/mpconfigport.h b/bare-arm/mpconfigport.h index 7c448d13c..79b2b7328 100644 --- a/bare-arm/mpconfigport.h +++ b/bare-arm/mpconfigport.h @@ -42,6 +42,7 @@ #define MICROPY_CPYTHON_COMPAT (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE) #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE) +#define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine diff --git a/cc3200/application.mk b/cc3200/application.mk index dca6fcbc6..300262c97 100644 --- a/cc3200/application.mk +++ b/cc3200/application.mk @@ -154,7 +154,6 @@ APP_LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) APP_STM_SRC_C = $(addprefix stmhal/,\ diff --git a/cc3200/mods/modmachine.c b/cc3200/mods/modmachine.c index 704defb33..410d5b944 100644 --- a/cc3200/mods/modmachine.c +++ b/cc3200/mods/modmachine.c @@ -198,7 +198,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) }, { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, // legacy constant + { MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) }, { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) }, { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) }, diff --git a/docs/conf.py b/docs/conf.py index fbc89afc6..a737e43ef 100755 --- a/docs/conf.py +++ b/docs/conf.py @@ -99,7 +99,7 @@ copyright = '2014-2016, Damien P. George and contributors' # The short X.Y version. version = '1.8' # The full version, including alpha/beta/rc tags. -release = '1.8.3' +release = '1.8.4' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst index d20987136..d06fe5a6f 100644 --- a/docs/esp8266/quickref.rst +++ b/docs/esp8266/quickref.rst @@ -162,10 +162,11 @@ Use the ``machine.ADC`` class:: adc = ADC(0) # create ADC object on ADC pin adc.read() # read value, 0-1024 -SPI bus -------- +Software SPI bus +---------------- -There are two SPI drivers. One is implemented in software and works on all pins:: +There are two SPI drivers. One is implemented in software (bit-banging) +and works on all pins:: from machine import Pin, SPI @@ -190,18 +191,19 @@ There are two SPI drivers. One is implemented in software and works on all pins: spi.write_readinto(buf, buf) # write buf to MOSI and read MISO back into buf -Hardware SPI ------------- +Hardware SPI bus +---------------- The hardware SPI is faster (up to 80Mhz), but only works on following pins: -``MISO`` is gpio12, ``MOSI`` is gpio13, and ``SCK`` is gpio14. It has the same -methods as SPI, except for the pin parameters for the constructor and init -(as those are fixed). +``MISO`` is GPIO12, ``MOSI`` is GPIO13, and ``SCK`` is GPIO14. It has the same +methods as the bitbanging SPI class above, except for the pin parameters for the +constructor and init (as those are fixed):: from machine import Pin, SPI - hspi = SPI(0, baudrate=80000000, polarity=0, phase=0) + hspi = SPI(1, baudrate=80000000, polarity=0, phase=0) +(``SPI(0)`` is used for FlashROM and not available to users.) I2C bus ------- diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst index ff534fd9b..1d79b4c4e 100644 --- a/docs/library/machine.WDT.rst +++ b/docs/library/machine.WDT.rst @@ -14,7 +14,7 @@ Example usage:: wdt = WDT(timeout=2000) # enable it with a timeout of 2s wdt.feed() -Availability of this class: WiPy. +Availability of this class: pyboard, WiPy. Constructors ------------ diff --git a/docs/library/machine.rst b/docs/library/machine.rst index 0f361a7cb..46d8eea71 100644 --- a/docs/library/machine.rst +++ b/docs/library/machine.rst @@ -125,7 +125,7 @@ Constants irq wake values -.. data:: machine.POWER_ON +.. data:: machine.PWRON_RESET .. data:: machine.HARD_RESET .. data:: machine.WDT_RESET .. data:: machine.DEEPSLEEP_RESET diff --git a/docs/library/pyb.SPI.rst b/docs/library/pyb.SPI.rst index 54ecc65b6..fd110be19 100644 --- a/docs/library/pyb.SPI.rst +++ b/docs/library/pyb.SPI.rst @@ -68,6 +68,7 @@ Methods - ``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. + - ``bits`` can be 8 or 16, and is the number of bits in each transferred word. - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. - ``crc`` can be None for no CRC, or a polynomial specifier. diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst index b33e4dd6f..23dcfd01f 100644 --- a/docs/reference/isr_rules.rst +++ b/docs/reference/isr_rules.rst @@ -110,6 +110,19 @@ the flag. The memory allocation occurs in the main program code when the object The MicroPython library I/O methods usually provide an option to use a pre-allocated buffer. For example ``pyb.i2c.recv()`` can accept a mutable buffer as its first argument: this enables its use in an ISR. +A means of creating an object without employing a class or globals is as follows: + +.. code:: python + + def set_volume(t, buf=bytearray(3)): + buf[0] = 0xa5 + buf[1] = t >> 4 + buf[2] = 0x5a + return buf + +The compiler instantiates the default ``buf`` argument when the function is +loaded for the first time (usually when the module it's in is imported). + Use of Python objects ~~~~~~~~~~~~~~~~~~~~~ @@ -300,3 +313,20 @@ that access to the critical variables is denied. A simple example of a mutex may but only for the duration of eight machine instructions: the benefit of this approach is that other interrupts are virtually unaffected. +Interrupts and the REPL +~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupt handlers, such as those associated with timers, can continue to run +after a program terminates. This may produce unexpected results where you might +have expected the object raising the callback to have gone out of scope. For +example on the Pyboard: + +.. code:: python + + def bar(): + foo = pyb.Timer(2, freq=4, callback=lambda t: print('.', end='')) + + bar() + +This continues to run until the timer is explicitly disabled or the board is +reset with ``ctrl D``. diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst index 3ce7e0132..ac7eec132 100644 --- a/docs/wipy/quickref.rst +++ b/docs/wipy/quickref.rst @@ -51,11 +51,10 @@ See :ref:`machine.Timer <machine.Timer>` and :ref:`machine.Pin <machine.Pin>`. : tim = Timer(0, mode=Timer.PERIODIC) tim_a = tim.channel(Timer.A, freq=1000) - tim_a.time() # get the value in microseconds tim_a.freq(5) # 5 Hz p_out = Pin('GP2', mode=Pin.OUT) - tim_a.irq(handler=lambda t: p_out.toggle()) + tim_a.irq(trigger=Timer.TIMEOUT, handler=lambda t: p_out.toggle()) PWM (pulse width modulation) ---------------------------- @@ -135,10 +134,9 @@ Real time clock (RTC) See :ref:`machine.RTC <machine.RTC>` :: - import machine from machine import RTC - rtc = machine.RTC() # init with default time and date + rtc = RTC() # init with default time and date rtc = RTC(datetime=(2015, 8, 29, 9, 0, 0, 0, None)) # init with a specific time and date print(rtc.now()) diff --git a/esp8266/Makefile b/esp8266/Makefile index 278651038..26b5e8626 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -14,7 +14,7 @@ MPY_CROSS = ../mpy-cross/mpy-cross MPY_TOOL = ../tools/mpy-tool.py MAKE_FROZEN = ../tools/make-frozen.py -SCRIPTDIR = scripts +FROZEN_DIR = scripts FROZEN_MPY_DIR = modules PORT ?= /dev/ttyACM0 BAUD ?= 115200 @@ -79,7 +79,6 @@ SRC_C = \ modpybadc.c \ modpybuart.c \ modmachinewdt.c \ - modmachinespi.c \ modpybspi.c \ modpybhspi.c \ modesp.c \ @@ -129,7 +128,6 @@ LIB_SRC_C = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ fatfs/ff.c \ fatfs/option/ccsbcs.c \ ) @@ -141,7 +139,7 @@ DRIVERS_SRC_C = $(addprefix drivers/,\ SRC_S = \ gchelper.s \ -FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py') +FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) OBJ = @@ -166,16 +164,14 @@ CONFVARS_FILE = $(BUILD)/confvars ifeq ($(wildcard $(CONFVARS_FILE)),) $(shell $(MKDIR) -p $(BUILD)) -$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE)) -else ifneq ($(shell cat $(CONFVARS_FILE)), $(SCRIPTDIR) $(UART_OS)) -$(shell echo $(SCRIPTDIR) $(UART_OS) > $(CONFVARS_FILE)) +$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE)) +else ifneq ($(shell cat $(CONFVARS_FILE)), $(FROZEN_DIR) $(UART_OS)) +$(shell echo $(FROZEN_DIR) $(UART_OS) > $(CONFVARS_FILE)) endif $(BUILD)/uart.o: $(CONFVARS_FILE) -$(BUILD)/frozen.c: $(wildcard $(SCRIPTDIR)/*) $(CONFVARS_FILE) - $(ECHO) "Generating $@" - $(Q)$(MAKE_FROZEN) $(SCRIPTDIR) > $@ +FROZEN_EXTRA_DEPS = $(CONFVARS_FILE) # to build .mpy files from .py files $(BUILD)/$(FROZEN_MPY_DIR)/%.mpy: $(FROZEN_MPY_DIR)/%.py diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld index dec3bf5a3..c726790d3 100644 --- a/esp8266/esp8266.ld +++ b/esp8266/esp8266.ld @@ -141,7 +141,7 @@ SECTIONS *modpybadc.o(.literal*, .text*) *modpybuart.o(.literal*, .text*) *modpybi2c.o(.literal*, .text*) - *modmachinespi.o(.literal*, .text*) + *modmachinewdt.o(.literal*, .text*) *modpybspi.o(.literal*, .text*) *modpybhspi.o(.literal*, .text*) *hspi.o(.literal*, .text*) diff --git a/esp8266/esp_mphal.c b/esp8266/esp_mphal.c index 06049e395..7c9590ab6 100644 --- a/esp8266/esp_mphal.c +++ b/esp8266/esp_mphal.c @@ -36,10 +36,6 @@ #include "extmod/misc.h" #include "lib/utils/pyexec.h" -extern void ets_wdt_disable(void); -extern void wdt_feed(void); -extern void ets_delay_us(); - STATIC byte input_buf_array[256]; ringbuf_t input_buf = {input_buf_array, sizeof(input_buf_array)}; void mp_hal_debug_tx_strn_cooked(void *env, const char *str, uint32_t len); @@ -64,7 +60,14 @@ int mp_hal_stdin_rx_chr(void) { if (c != -1) { return c; } + #if 0 + // Idles CPU but need more testing before enabling + if (!ets_loop_iter()) { + asm("waiti 0"); + } + #else mp_hal_delay_us(1); + #endif } } diff --git a/esp8266/espneopixel.c b/esp8266/espneopixel.c index 0f12f4c82..e16c874f2 100644 --- a/esp8266/espneopixel.c +++ b/esp8266/espneopixel.c @@ -41,6 +41,7 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32 } #endif + uint32_t irq_state = mp_hal_quiet_timing_enter(); for(t = time0;; t = time0) { if(pix & mask) t = time1; // Bit high duration while(((c = mp_hal_ticks_cpu()) - startTime) < period); // Wait for bit start @@ -55,4 +56,5 @@ void /*ICACHE_RAM_ATTR*/ esp_neopixel_write(uint8_t pin, uint8_t *pixels, uint32 } } while((mp_hal_ticks_cpu() - startTime) < period); // Wait for last bit + mp_hal_quiet_timing_exit(irq_state); } diff --git a/esp8266/ets_alt_task.c b/esp8266/ets_alt_task.c index 62872affb..ef1d8aaed 100644 --- a/esp8266/ets_alt_task.c +++ b/esp8266/ets_alt_task.c @@ -87,7 +87,7 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) { if (emu_tasks[id].i_put == -1) { // queue is full printf("ets_post: task %d queue full\n", prio); - return false; + return 1; } q = &q[emu_tasks[id].i_put++]; q->sig = sig; @@ -104,7 +104,7 @@ bool ets_post(uint8 prio, os_signal_t sig, os_param_t param) { ets_intr_unlock(); - return true; + return 0; #endif } diff --git a/esp8266/etshal.h b/esp8266/etshal.h index dd61ddec9..e7326a43b 100644 --- a/esp8266/etshal.h +++ b/esp8266/etshal.h @@ -20,6 +20,9 @@ void ets_timer_arm_new(os_timer_t *tim, uint32_t millis, bool repeat, bool is_mi void ets_timer_setfn(os_timer_t *tim, ETSTimerFunc callback, void *cb_data); void ets_timer_disarm(os_timer_t *tim); +extern void ets_wdt_disable(void); +extern void wdt_feed(void); + // Opaque structure typedef char MD5_CTX[64]; diff --git a/esp8266/modmachine.c b/esp8266/modmachine.c index 0972ce29f..b0b7f3a1a 100644 --- a/esp8266/modmachine.c +++ b/esp8266/modmachine.c @@ -254,17 +254,17 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) }, { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) }, { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) }, - { MP_ROM_QSTR(MP_QSTR_SoftSPI), MP_ROM_PTR(&pyb_spi_type) }, - { MP_ROM_QSTR(MP_QSTR_HSPI), MP_ROM_PTR(&pyb_hspi_type) }, - { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_spi_type) }, + { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_hspi_type) }, // wake abilities { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(MACHINE_WAKE_DEEPSLEEP) }, // reset causes - { MP_ROM_QSTR(MP_QSTR_PWR_ON_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) }, + { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) }, { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(REASON_EXT_SYS_RST) }, { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(REASON_DEEP_SLEEP_AWAKE) }, + { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(REASON_WDT_RST) }, + { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(REASON_SOFT_RESTART) }, }; STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table); diff --git a/esp8266/modmachinespi.c b/esp8266/modmachinespi.c deleted file mode 100644 index 1c6a37369..000000000 --- a/esp8266/modmachinespi.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2016 Damien P. George - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#include <stdio.h> -#include <stdint.h> -#include <string.h> - -#include "ets_sys.h" -#include "etshal.h" -#include "ets_alt_task.h" - -#include "py/runtime.h" -#include "py/stream.h" -#include "py/mphal.h" - - -mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args); -mp_obj_t pyb_hspi_make_new(const mp_obj_type_t *type, size_t n_args, - size_t n_kw, const mp_obj_t *args); - - -STATIC mp_obj_t machine_spi_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); - switch (mp_obj_get_int(args[0])) { - case -1: - return pyb_spi_make_new(type, n_args - 1, n_kw, args + 1); - case 0: - return pyb_hspi_make_new(type, n_args - 1, n_kw, args + 1); - default: - nlr_raise(mp_obj_new_exception_msg_varg( - &mp_type_ValueError, "no such SPI peripheral")); - } -} - - -STATIC const mp_rom_map_elem_t machine_spi_locals_dict_table[] = {}; - -STATIC MP_DEFINE_CONST_DICT(machine_spi_locals_dict, - machine_spi_locals_dict_table); - -const mp_obj_type_t machine_spi_type = { - { &mp_type_type }, - .name = MP_QSTR_SPI, - .make_new = machine_spi_make_new, - .locals_dict = (mp_obj_dict_t*)&machine_spi_locals_dict, -}; diff --git a/esp8266/modmachinewdt.c b/esp8266/modmachinewdt.c index e0b1ff5d7..6dc4c0d18 100644 --- a/esp8266/modmachinewdt.c +++ b/esp8266/modmachinewdt.c @@ -31,6 +31,7 @@ #include "py/obj.h" #include "py/runtime.h" #include "user_interface.h" +#include "etshal.h" const mp_obj_type_t esp_wdt_type; @@ -63,8 +64,16 @@ STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed); +STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) { + (void)self_in; + ets_wdt_disable(); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit); + STATIC const mp_map_elem_t machine_wdt_locals_dict_table[] = { - { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj } + { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&machine_wdt_feed_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&machine_wdt_deinit_obj }, }; STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table); diff --git a/esp8266/modnetwork.c b/esp8266/modnetwork.c index 7cfa3ff77..7031197fa 100644 --- a/esp8266/modnetwork.c +++ b/esp8266/modnetwork.c @@ -130,17 +130,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_status_obj, esp_status); STATIC mp_obj_t *esp_scan_list = NULL; -STATIC void esp_scan_cb(scaninfo *si, STATUS status) { +STATIC void esp_scan_cb(void *result, STATUS status) { if (esp_scan_list == NULL) { // called unexpectedly return; } - if (si->pbss && status == 0) { + if (result && status == 0) { // we need to catch any memory errors nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { - struct bss_info *bs; - STAILQ_FOREACH(bs, si->pbss, next) { + for (struct bss_info *bs = result; bs; bs = STAILQ_NEXT(bs, next)) { mp_obj_tuple_t *t = mp_obj_new_tuple(6, NULL); #if 1 // struct bss_info::ssid_len is not documented in SDK API Guide, diff --git a/esp8266/modpybhspi.c b/esp8266/modpybhspi.c index c4d4dcee8..c1cd7f662 100644 --- a/esp8266/modpybhspi.c +++ b/esp8266/modpybhspi.c @@ -39,6 +39,8 @@ #include "hspi.h" +mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, + size_t n_kw, const mp_obj_t *args); typedef struct _pyb_hspi_obj_t { mp_obj_base_t base; @@ -105,13 +107,14 @@ STATIC void hspi_transfer(mp_obj_base_t *self_in, size_t src_len, const uint8_t STATIC void pyb_hspi_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { pyb_hspi_obj_t *self = MP_OBJ_TO_PTR(self_in); - mp_printf(print, "HSPI(baudrate=%u, polarity=%u, phase=%u)", + mp_printf(print, "HSPI(id=1, baudrate=%u, polarity=%u, phase=%u)", self->baudrate, self->polarity, self->phase); } STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - enum { ARG_baudrate, ARG_polarity, ARG_phase }; + enum { ARG_id, ARG_baudrate, ARG_polarity, ARG_phase }; static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_baudrate, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_polarity, MP_ARG_INT, {.u_int = -1} }, { MP_QSTR_phase, MP_ARG_INT, {.u_int = -1} }, @@ -160,7 +163,25 @@ STATIC void pyb_hspi_init_helper(pyb_hspi_obj_t *self, size_t n_args, const mp_o } mp_obj_t pyb_hspi_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, MP_OBJ_FUN_ARGS_MAX, true); + mp_arg_check_num(n_args, n_kw, 0, 1, true); + mp_int_t id = -1; + if (n_args > 0) { + id = mp_obj_get_int(args[0]); + } + + if (id == -1) { + // Multiplex to bitbanging SPI + if (n_args > 0) { + args++; + } + return pyb_spi_make_new(type, 0, n_kw, args); + } + + if (id != 1) { + // FlashROM is on SPI0, so far we don't support its usage + mp_raise_ValueError(""); + } + pyb_hspi_obj_t *self = m_new_obj(pyb_hspi_obj_t); self->base.type = &pyb_hspi_type; // set defaults diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c index 84f1246fb..3c884c689 100644 --- a/extmod/modframebuf.c +++ b/extmod/modframebuf.c @@ -33,7 +33,7 @@ #if MICROPY_PY_FRAMEBUF -#include "font_petme128_8x8.h" +#include "stmhal/font_petme128_8x8.h" // 1-bit frame buffer, each byte is a column of 8 pixels typedef struct _mp_obj_framebuf1_t { @@ -103,7 +103,7 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y mp_int_t xstep = mp_obj_get_int(xstep_in); mp_int_t ystep = mp_obj_get_int(ystep_in); int end = (self->height + 7) >> 3; - if (xstep == 0 && ystep > 0) { + if (ystep > 0) { for (int y = end; y > 0;) { --y; for (int x = 0; x < self->width; ++x) { @@ -114,7 +114,7 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y self->buf[y * self->stride + x] = (self->buf[y * self->stride + x] << ystep) | prev; } } - } else if (xstep == 0 && ystep < 0) { + } else if (ystep < 0) { for (int y = 0; y < end; ++y) { for (int x = 0; x < self->width; ++x) { int prev = 0; @@ -125,7 +125,20 @@ STATIC mp_obj_t framebuf1_scroll(mp_obj_t self_in, mp_obj_t xstep_in, mp_obj_t y } } } - // TODO xstep!=0 + if (xstep < 0) { + for (int y = 0; y < end; ++y) { + for (int x = 0; x < self->width + xstep; ++x) { + self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep]; + } + } + } else if (xstep > 0) { + for (int y = 0; y < end; ++y) { + for (int x = self->width - 1; x >= xstep; --x) { + self->buf[y * self->stride + x] = self->buf[y * self->stride + x - xstep]; + } + } + } + // TODO: Should we clear the margin created by scrolling? return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_3(framebuf1_scroll_obj, framebuf1_scroll); diff --git a/extmod/moduzlib.c b/extmod/moduzlib.c index dbf513527..65cbc5eb0 100644 --- a/extmod/moduzlib.c +++ b/extmod/moduzlib.c @@ -67,17 +67,31 @@ STATIC unsigned char read_src_stream(TINF_DATA *data) { return c; } -#define DICT_SIZE 32768 - STATIC mp_obj_t decompio_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, 1, false); + mp_arg_check_num(n_args, n_kw, 1, 2, false); mp_obj_decompio_t *o = m_new_obj(mp_obj_decompio_t); o->base.type = type; memset(&o->decomp, 0, sizeof(o->decomp)); - uzlib_uncompress_init(&o->decomp, m_new(byte, DICT_SIZE), DICT_SIZE); o->decomp.readSource = read_src_stream; o->src_stream = args[0]; o->eof = false; + + mp_int_t dict_opt = 0; + int dict_sz; + if (n_args > 1) { + dict_opt = mp_obj_get_int(args[1]); + } + if (dict_opt >= 0) { + dict_opt = uzlib_zlib_parse_header(&o->decomp); + if (dict_opt < 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "zlib header")); + } + dict_sz = 1 << dict_opt; + } else { + dict_sz = 1 << -dict_opt; + } + + uzlib_uncompress_init(&o->decomp, m_new(byte, dict_sz), dict_sz); return MP_OBJ_FROM_PTR(o); } diff --git a/lib/utils/printf.c b/lib/utils/printf.c index 308525b6e..303edfcca 100644 --- a/lib/utils/printf.c +++ b/lib/utils/printf.c @@ -24,6 +24,10 @@ * THE SOFTWARE. */ +#include "py/mpconfig.h" + +#if MICROPY_USE_INTERNAL_PRINTF + #include <stdint.h> #include <string.h> #include <stdarg.h> @@ -127,3 +131,5 @@ int snprintf(char *str, size_t size, const char *fmt, ...) { va_end(ap); return ret; } + +#endif //MICROPY_USE_INTERNAL_PRINTF diff --git a/minimal/Makefile b/minimal/Makefile index 02096f9f0..0cecd1c0f 100644 --- a/minimal/Makefile +++ b/minimal/Makefile @@ -46,7 +46,6 @@ SRC_C = \ main.c \ uart_core.c \ lib/utils/stdout_helpers.c \ - lib/utils/printf.c \ lib/utils/pyexec.c \ lib/libc/string0.c \ lib/mp-readline/readline.c \ diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h index c919e4291..c0a404103 100644 --- a/mpy-cross/mpconfigport.h +++ b/mpy-cross/mpconfigport.h @@ -59,6 +59,7 @@ #define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_DOUBLE) #define MICROPY_CPYTHON_COMPAT (1) +#define MICROPY_USE_INTERNAL_PRINTF (0) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) diff --git a/py/asmthumb.c b/py/asmthumb.c index 8341c958e..1aae3d38e 100644 --- a/py/asmthumb.c +++ b/py/asmthumb.c @@ -90,6 +90,15 @@ void asm_thumb_start_pass(asm_thumb_t *as, uint pass) { void asm_thumb_end_pass(asm_thumb_t *as) { (void)as; // could check labels are resolved... + + #if defined(MCU_SERIES_F7) + if (as->pass == ASM_THUMB_PASS_EMIT) { + // flush D-cache, so the code emited is stored in memory + SCB_CleanDCache_by_Addr((uint32_t*)as->code_base, as->code_size); + // invalidate I-cache + SCB_InvalidateICache(); + } + #endif } // all functions must go through this one to emit bytes @@ -82,13 +82,11 @@ #define MP_BC_BUILD_TUPLE (0x50) // uint #define MP_BC_BUILD_LIST (0x51) // uint -#define MP_BC_LIST_APPEND (0x52) // uint #define MP_BC_BUILD_MAP (0x53) // uint #define MP_BC_STORE_MAP (0x54) -#define MP_BC_MAP_ADD (0x55) // uint #define MP_BC_BUILD_SET (0x56) // uint -#define MP_BC_SET_ADD (0x57) // uint #define MP_BC_BUILD_SLICE (0x58) // uint +#define MP_BC_STORE_COMP (0x57) // uint #define MP_BC_UNPACK_SEQUENCE (0x59) // uint #define MP_BC_UNPACK_EX (0x5a) // uint diff --git a/py/compile.c b/py/compile.c index c8b4e5470..7207ac2e0 100644 --- a/py/compile.c +++ b/py/compile.c @@ -2869,17 +2869,11 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn if (MP_PARSE_NODE_IS_NULL(pn_iter)) { // no more nested if/for; compile inner expression compile_node(comp, pn_inner_expr); - if (comp->scope_cur->kind == SCOPE_LIST_COMP) { - EMIT_ARG(list_append, for_depth + 2); - } else if (comp->scope_cur->kind == SCOPE_DICT_COMP) { - EMIT_ARG(map_add, for_depth + 2); - #if MICROPY_PY_BUILTINS_SET - } else if (comp->scope_cur->kind == SCOPE_SET_COMP) { - EMIT_ARG(set_add, for_depth + 2); - #endif - } else { + if (comp->scope_cur->kind == SCOPE_GEN_EXPR) { EMIT(yield_value); EMIT(pop_top); + } else { + EMIT_ARG(store_comp, comp->scope_cur->kind, for_depth + 2); } } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) { // if condition @@ -119,17 +119,15 @@ typedef struct _emit_method_table_t { void (*binary_op)(emit_t *emit, mp_binary_op_t op); void (*build_tuple)(emit_t *emit, mp_uint_t n_args); void (*build_list)(emit_t *emit, mp_uint_t n_args); - void (*list_append)(emit_t *emit, mp_uint_t list_stack_index); void (*build_map)(emit_t *emit, mp_uint_t n_args); void (*store_map)(emit_t *emit); - void (*map_add)(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void (*build_set)(emit_t *emit, mp_uint_t n_args); - void (*set_add)(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void (*build_slice)(emit_t *emit, mp_uint_t n_args); #endif + void (*store_comp)(emit_t *emit, scope_kind_t kind, mp_uint_t set_stack_index); void (*unpack_sequence)(emit_t *emit, mp_uint_t n_args); void (*unpack_ex)(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void (*make_function)(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); @@ -240,17 +238,15 @@ void mp_emit_bc_unary_op(emit_t *emit, mp_unary_op_t op); void mp_emit_bc_binary_op(emit_t *emit, mp_binary_op_t op); void mp_emit_bc_build_tuple(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index); void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_store_map(emit_t *emit); -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index); #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args); -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index); #endif #if MICROPY_PY_BUILTINS_SLICE void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args); #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t list_stack_index); void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args); void mp_emit_bc_unpack_ex(emit_t *emit, mp_uint_t n_left, mp_uint_t n_right); void mp_emit_bc_make_function(emit_t *emit, scope_t *scope, mp_uint_t n_pos_defaults, mp_uint_t n_kw_defaults); diff --git a/py/emitbc.c b/py/emitbc.c index d871aa4ce..8c712e1fd 100644 --- a/py/emitbc.c +++ b/py/emitbc.c @@ -837,11 +837,6 @@ void mp_emit_bc_build_list(emit_t *emit, mp_uint_t n_args) { emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_LIST, n_args); } -void mp_emit_bc_list_append(emit_t *emit, mp_uint_t list_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_LIST_APPEND, list_stack_index); -} - void mp_emit_bc_build_map(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_MAP, n_args); @@ -852,21 +847,11 @@ void mp_emit_bc_store_map(emit_t *emit) { emit_write_bytecode_byte(emit, MP_BC_STORE_MAP); } -void mp_emit_bc_map_add(emit_t *emit, mp_uint_t map_stack_index) { - emit_bc_pre(emit, -2); - emit_write_bytecode_byte_uint(emit, MP_BC_MAP_ADD, map_stack_index); -} - #if MICROPY_PY_BUILTINS_SET void mp_emit_bc_build_set(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, 1 - n_args); emit_write_bytecode_byte_uint(emit, MP_BC_BUILD_SET, n_args); } - -void mp_emit_bc_set_add(emit_t *emit, mp_uint_t set_stack_index) { - emit_bc_pre(emit, -1); - emit_write_bytecode_byte_uint(emit, MP_BC_SET_ADD, set_stack_index); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -876,6 +861,24 @@ void mp_emit_bc_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +void mp_emit_bc_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_stack_index) { + int t; + int n; + if (kind == SCOPE_LIST_COMP) { + n = 0; + t = 0; + } else if (!MICROPY_PY_BUILTINS_SET || kind == SCOPE_DICT_COMP) { + n = 1; + t = 1; + } else if (MICROPY_PY_BUILTINS_SET) { + n = 0; + t = 2; + } + emit_bc_pre(emit, -1 - n); + // the lower 2 bits of the opcode argument indicate the collection type + emit_write_bytecode_byte_uint(emit, MP_BC_STORE_COMP, ((collection_stack_index + n) << 2) | t); +} + void mp_emit_bc_unpack_sequence(emit_t *emit, mp_uint_t n_args) { emit_bc_pre(emit, -1 + n_args); emit_write_bytecode_byte_uint(emit, MP_BC_UNPACK_SEQUENCE, n_args); @@ -1028,17 +1031,15 @@ const emit_method_table_t emit_bc_method_table = { mp_emit_bc_binary_op, mp_emit_bc_build_tuple, mp_emit_bc_build_list, - mp_emit_bc_list_append, mp_emit_bc_build_map, mp_emit_bc_store_map, - mp_emit_bc_map_add, #if MICROPY_PY_BUILTINS_SET mp_emit_bc_build_set, - mp_emit_bc_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE mp_emit_bc_build_slice, #endif + mp_emit_bc_store_comp, mp_emit_bc_unpack_sequence, mp_emit_bc_unpack_ex, mp_emit_bc_make_function, diff --git a/py/emitglue.c b/py/emitglue.c index 0b5903092..f4b59df3e 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -379,7 +379,7 @@ mp_raw_code_t *mp_raw_code_load_mem(const byte *buf, size_t len) { // here we define mp_raw_code_load_file depending on the port // TODO abstract this away properly -#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || (defined(__arm__) && (defined(__unix__))) +#if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) || defined(__unix__) // unix file reader #include <sys/stat.h> diff --git a/py/emitnative.c b/py/emitnative.c index 2cf4711fe..b54f263d6 100644 --- a/py/emitnative.c +++ b/py/emitnative.c @@ -2344,17 +2344,6 @@ STATIC void emit_native_build_list(emit_t *emit, mp_uint_t n_args) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new list } -STATIC void emit_native_list_append(emit_t *emit, mp_uint_t list_index) { - // only used in list comprehension - vtype_kind_t vtype_list, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, list_index, &vtype_list, REG_ARG_1); - assert(vtype_list == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_LIST_APPEND); - emit_post(emit); -} - STATIC void emit_native_build_map(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); emit_call_with_imm_arg(emit, MP_F_BUILD_MAP, n_args, REG_ARG_1); @@ -2371,18 +2360,6 @@ STATIC void emit_native_store_map(emit_t *emit) { emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // map } -STATIC void emit_native_map_add(emit_t *emit, mp_uint_t map_index) { - // only used in list comprehension - vtype_kind_t vtype_map, vtype_key, vtype_value; - emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); - emit_access_stack(emit, map_index, &vtype_map, REG_ARG_1); - assert(vtype_map == VTYPE_PYOBJ); - assert(vtype_key == VTYPE_PYOBJ); - assert(vtype_value == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_MAP); - emit_post(emit); -} - #if MICROPY_PY_BUILTINS_SET STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_native_pre(emit); @@ -2390,17 +2367,6 @@ STATIC void emit_native_build_set(emit_t *emit, mp_uint_t n_args) { emit_call_with_imm_arg(emit, MP_F_BUILD_SET, n_args, REG_ARG_1); emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET); // new set } - -STATIC void emit_native_set_add(emit_t *emit, mp_uint_t set_index) { - // only used in set comprehension - vtype_kind_t vtype_set, vtype_item; - emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); - emit_access_stack(emit, set_index, &vtype_set, REG_ARG_1); - assert(vtype_set == VTYPE_PYOBJ); - assert(vtype_item == VTYPE_PYOBJ); - emit_call(emit, MP_F_STORE_SET); - emit_post(emit); -} #endif #if MICROPY_PY_BUILTINS_SLICE @@ -2426,6 +2392,35 @@ STATIC void emit_native_build_slice(emit_t *emit, mp_uint_t n_args) { } #endif +STATIC void emit_native_store_comp(emit_t *emit, scope_kind_t kind, mp_uint_t collection_index) { + mp_fun_kind_t f; + if (kind == SCOPE_LIST_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_LIST_APPEND; + #if MICROPY_PY_BUILTINS_SET + } else if (kind == SCOPE_SET_COMP) { + vtype_kind_t vtype_item; + emit_pre_pop_reg(emit, &vtype_item, REG_ARG_2); + assert(vtype_item == VTYPE_PYOBJ); + f = MP_F_STORE_SET; + #endif + } else { + // SCOPE_DICT_COMP + vtype_kind_t vtype_key, vtype_value; + emit_pre_pop_reg_reg(emit, &vtype_key, REG_ARG_2, &vtype_value, REG_ARG_3); + assert(vtype_key == VTYPE_PYOBJ); + assert(vtype_value == VTYPE_PYOBJ); + f = MP_F_STORE_MAP; + } + vtype_kind_t vtype_collection; + emit_access_stack(emit, collection_index, &vtype_collection, REG_ARG_1); + assert(vtype_collection == VTYPE_PYOBJ); + emit_call(emit, f); + emit_post(emit); +} + STATIC void emit_native_unpack_sequence(emit_t *emit, mp_uint_t n_args) { DEBUG_printf("unpack_sequence %d\n", n_args); vtype_kind_t vtype_base; @@ -2674,17 +2669,15 @@ const emit_method_table_t EXPORT_FUN(method_table) = { emit_native_binary_op, emit_native_build_tuple, emit_native_build_list, - emit_native_list_append, emit_native_build_map, emit_native_store_map, - emit_native_map_add, #if MICROPY_PY_BUILTINS_SET emit_native_build_set, - emit_native_set_add, #endif #if MICROPY_PY_BUILTINS_SLICE emit_native_build_slice, #endif + emit_native_store_comp, emit_native_unpack_sequence, emit_native_unpack_ex, emit_native_make_function, diff --git a/py/lexer.c b/py/lexer.c index 820f91be7..b2c9c5ff7 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -723,7 +723,8 @@ mp_lexer_t *mp_lexer_new(qstr src_name, void *stream_data, mp_lexer_stream_next_ vstr_init(&lex->vstr, 32); // check for memory allocation error - if (lex->indent_level == NULL || vstr_had_error(&lex->vstr)) { + // note: vstr_init above may fail on malloc, but so may mp_lexer_next_token_into below + if (lex->indent_level == NULL) { mp_lexer_free(lex); return NULL; } diff --git a/py/makeqstrdefs.py b/py/makeqstrdefs.py index c309e33c9..9001bf996 100644 --- a/py/makeqstrdefs.py +++ b/py/makeqstrdefs.py @@ -23,7 +23,7 @@ elif platform.python_version_tuple()[0] == '3': # Blacklist of qstrings that are specially handled in further # processing and should be ignored -QSTRING_BLACK_LIST = {'NULL', 'number_of', } +QSTRING_BLACK_LIST = set(['NULL', 'number_of']) # add some custom names to map characters that aren't in HTML name2codepoint['hyphen'] = ord('-') @@ -139,7 +139,6 @@ typedef struct _vstr_t { size_t alloc; size_t len; char *buf; - bool had_error : 1; bool fixed_buf : 1; } vstr_t; @@ -155,10 +154,9 @@ void vstr_clear(vstr_t *vstr); vstr_t *vstr_new(void); vstr_t *vstr_new_size(size_t alloc); void vstr_free(vstr_t *vstr); -void vstr_reset(vstr_t *vstr); -bool vstr_had_error(vstr_t *vstr); -char *vstr_str(vstr_t *vstr); -size_t vstr_len(vstr_t *vstr); +static inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; } +static inline char *vstr_str(vstr_t *vstr) { return vstr->buf; } +static inline size_t vstr_len(vstr_t *vstr) { return vstr->len; } void vstr_hint_size(vstr_t *vstr, size_t size); char *vstr_extend(vstr_t *vstr, size_t size); char *vstr_add_len(vstr_t *vstr, size_t len); diff --git a/py/mkenv.mk b/py/mkenv.mk index b7f8c2aff..e7262907c 100644 --- a/py/mkenv.mk +++ b/py/mkenv.mk @@ -58,6 +58,8 @@ CXX += -m32 LD += -m32 endif +MAKE_FROZEN = ../tools/make-frozen.py + all: .PHONY: all diff --git a/py/mkrules.mk b/py/mkrules.mk index a3a408dc8..26e4aeab3 100644 --- a/py/mkrules.mk +++ b/py/mkrules.mk @@ -100,6 +100,12 @@ $(OBJ_DIRS): $(HEADER_BUILD): $(MKDIR) -p $@ +ifneq ($(FROZEN_DIR),) +$(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DEPS) + $(ECHO) "Generating $@" + $(Q)$(MAKE_FROZEN) $(FROZEN_DIR) > $@ +endif + ifneq ($(PROG),) # Build a standalone executable (unix does this) diff --git a/py/mpconfig.h b/py/mpconfig.h index 455f870ac..e33a41f7a 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -581,6 +581,11 @@ typedef double mp_float_t; #define MICROPY_USE_INTERNAL_ERRNO (0) #endif +// Whether to use internally defined *printf() functions (otherwise external ones) +#ifndef MICROPY_USE_INTERNAL_PRINTF +#define MICROPY_USE_INTERNAL_PRINTF (1) +#endif + // Support for user-space VFS mount (selected ports) #ifndef MICROPY_FSUSERMOUNT #define MICROPY_FSUSERMOUNT (0) diff --git a/py/objnone.c b/py/objnone.c index 69eab03fe..5d5b83540 100644 --- a/py/objnone.c +++ b/py/objnone.c @@ -43,20 +43,11 @@ STATIC void none_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_ } } -STATIC mp_obj_t none_unary_op(mp_uint_t op, mp_obj_t o_in) { - (void)o_in; - switch (op) { - case MP_UNARY_OP_BOOL: return mp_const_false; - case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT((mp_uint_t)o_in); - default: return MP_OBJ_NULL; // op not supported - } -} - const mp_obj_type_t mp_type_NoneType = { { &mp_type_type }, .name = MP_QSTR_NoneType, .print = none_print, - .unary_op = none_unary_op, + .unary_op = mp_generic_unary_op, }; const mp_obj_none_t mp_const_none_obj = {{&mp_type_NoneType}}; @@ -223,6 +223,7 @@ PY_O_BASENAME = \ ../extmod/vfs_fat_misc.o \ ../extmod/moduos_dupterm.o \ ../lib/embed/abort_.o \ + ../lib/utils/printf.o \ # prepend the build destination prefix to the py object files PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) @@ -275,7 +275,6 @@ size_t qstr_len(qstr q) { return Q_GET_LENGTH(qd); } -// XXX to remove! const char *qstr_str(qstr q) { const byte *qd = find_qstr(q); return (const char*)Q_GET_DATA(qd); diff --git a/py/showbc.c b/py/showbc.c index dd5959f4a..0f335ffef 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -409,11 +409,6 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("BUILD_LIST " UINT_FMT, unum); break; - case MP_BC_LIST_APPEND: - DECODE_UINT; - printf("LIST_APPEND " UINT_FMT, unum); - break; - case MP_BC_BUILD_MAP: DECODE_UINT; printf("BUILD_MAP " UINT_FMT, unum); @@ -423,21 +418,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { printf("STORE_MAP"); break; - case MP_BC_MAP_ADD: - DECODE_UINT; - printf("MAP_ADD " UINT_FMT, unum); - break; - case MP_BC_BUILD_SET: DECODE_UINT; printf("BUILD_SET " UINT_FMT, unum); break; - case MP_BC_SET_ADD: - DECODE_UINT; - printf("SET_ADD " UINT_FMT, unum); - break; - #if MICROPY_PY_BUILTINS_SLICE case MP_BC_BUILD_SLICE: DECODE_UINT; @@ -445,6 +430,11 @@ const byte *mp_bytecode_print_str(const byte *ip) { break; #endif + case MP_BC_STORE_COMP: + DECODE_UINT; + printf("STORE_COMP " UINT_FMT, unum); + break; + case MP_BC_UNPACK_SEQUENCE: DECODE_UINT; printf("UNPACK_SEQUENCE " UINT_FMT, unum); @@ -777,15 +777,6 @@ unwind_jump:; DISPATCH(); } - ENTRY(MP_BC_LIST_APPEND): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[unum] is a list - mp_obj_list_append(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } - ENTRY(MP_BC_BUILD_MAP): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; @@ -799,15 +790,6 @@ unwind_jump:; mp_obj_dict_store(sp[0], sp[2], sp[1]); DISPATCH(); - ENTRY(MP_BC_MAP_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum - 1] is a map - mp_obj_dict_store(sp[-unum - 1], sp[0], sp[-1]); - sp -= 2; - DISPATCH(); - } - #if MICROPY_PY_BUILTINS_SET ENTRY(MP_BC_BUILD_SET): { MARK_EXC_IP_SELECTIVE(); @@ -816,15 +798,6 @@ unwind_jump:; SET_TOP(mp_obj_new_set(unum, sp)); DISPATCH(); } - - ENTRY(MP_BC_SET_ADD): { - MARK_EXC_IP_SELECTIVE(); - DECODE_UINT; - // I think it's guaranteed by the compiler that sp[-unum] is a set - mp_obj_set_store(sp[-unum], sp[0]); - sp--; - DISPATCH(); - } #endif #if MICROPY_PY_BUILTINS_SLICE @@ -845,6 +818,25 @@ unwind_jump:; } #endif + ENTRY(MP_BC_STORE_COMP): { + MARK_EXC_IP_SELECTIVE(); + DECODE_UINT; + mp_obj_t obj = sp[-(unum >> 2)]; + if ((unum & 3) == 0) { + mp_obj_list_append(obj, sp[0]); + sp--; + } else if (!MICROPY_PY_BUILTINS_SET || (unum & 3) == 1) { + mp_obj_dict_store(obj, sp[0], sp[-1]); + sp -= 2; + #if MICROPY_PY_BUILTINS_SET + } else { + mp_obj_set_store(obj, sp[0]); + sp--; + #endif + } + DISPATCH(); + } + ENTRY(MP_BC_UNPACK_SEQUENCE): { MARK_EXC_IP_SELECTIVE(); DECODE_UINT; diff --git a/py/vmentrytable.h b/py/vmentrytable.h index 9df1e40a3..dd30dd7a5 100644 --- a/py/vmentrytable.h +++ b/py/vmentrytable.h @@ -78,17 +78,15 @@ static const void *const entry_table[256] = { [MP_BC_POP_EXCEPT] = &&entry_MP_BC_POP_EXCEPT, [MP_BC_BUILD_TUPLE] = &&entry_MP_BC_BUILD_TUPLE, [MP_BC_BUILD_LIST] = &&entry_MP_BC_BUILD_LIST, - [MP_BC_LIST_APPEND] = &&entry_MP_BC_LIST_APPEND, [MP_BC_BUILD_MAP] = &&entry_MP_BC_BUILD_MAP, [MP_BC_STORE_MAP] = &&entry_MP_BC_STORE_MAP, - [MP_BC_MAP_ADD] = &&entry_MP_BC_MAP_ADD, #if MICROPY_PY_BUILTINS_SET [MP_BC_BUILD_SET] = &&entry_MP_BC_BUILD_SET, - [MP_BC_SET_ADD] = &&entry_MP_BC_SET_ADD, #endif #if MICROPY_PY_BUILTINS_SLICE [MP_BC_BUILD_SLICE] = &&entry_MP_BC_BUILD_SLICE, #endif + [MP_BC_STORE_COMP] = &&entry_MP_BC_STORE_COMP, [MP_BC_UNPACK_SEQUENCE] = &&entry_MP_BC_UNPACK_SEQUENCE, [MP_BC_UNPACK_EX] = &&entry_MP_BC_UNPACK_EX, [MP_BC_MAKE_FUNCTION] = &&entry_MP_BC_MAKE_FUNCTION, @@ -44,11 +44,6 @@ void vstr_init(vstr_t *vstr, size_t alloc) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = m_new(char, vstr->alloc); - if (vstr->buf == NULL) { - vstr->had_error = true; - return; - } - vstr->had_error = false; vstr->fixed_buf = false; } @@ -63,7 +58,6 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf) { vstr->alloc = alloc; vstr->len = 0; vstr->buf = buf; - vstr->had_error = false; vstr->fixed_buf = true; } @@ -107,39 +101,12 @@ void vstr_free(vstr_t *vstr) { } } -void vstr_reset(vstr_t *vstr) { - vstr->len = 0; - vstr->had_error = false; -} - -bool vstr_had_error(vstr_t *vstr) { - return vstr->had_error; -} - -char *vstr_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } - return vstr->buf; -} - -size_t vstr_len(vstr_t *vstr) { - if (vstr->had_error) { - return 0; - } - return vstr->len; -} - // Extend vstr strictly by requested size, return pointer to newly added chunk. char *vstr_extend(vstr_t *vstr, size_t size) { if (vstr->fixed_buf) { return NULL; } char *new_buf = m_renew(char, vstr->buf, vstr->alloc, vstr->alloc + size); - if (new_buf == NULL) { - vstr->had_error = true; - return NULL; - } char *p = new_buf + vstr->alloc; vstr->alloc += size; vstr->buf = new_buf; @@ -153,10 +120,6 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } size_t new_alloc = ROUND_ALLOC((vstr->len + size) + 16); char *new_buf = m_renew(char, vstr->buf, vstr->alloc, new_alloc); - if (new_buf == NULL) { - vstr->had_error = true; - return false; - } vstr->alloc = new_alloc; vstr->buf = new_buf; } @@ -164,14 +127,11 @@ STATIC bool vstr_ensure_extra(vstr_t *vstr, size_t size) { } void vstr_hint_size(vstr_t *vstr, size_t size) { - // it's not an error if we fail to allocate for the size hint - bool er = vstr->had_error; vstr_ensure_extra(vstr, size); - vstr->had_error = er; } char *vstr_add_len(vstr_t *vstr, size_t len) { - if (vstr->had_error || !vstr_ensure_extra(vstr, len)) { + if (!vstr_ensure_extra(vstr, len)) { return NULL; } char *buf = vstr->buf + vstr->len; @@ -181,9 +141,6 @@ char *vstr_add_len(vstr_t *vstr, size_t len) { // Doesn't increase len, just makes sure there is a null byte at the end char *vstr_null_terminated_str(vstr_t *vstr) { - if (vstr->had_error) { - return NULL; - } // If there's no more room, add single byte if (vstr->alloc == vstr->len) { if (vstr_extend(vstr, 1) == NULL) { @@ -248,7 +205,7 @@ void vstr_add_str(vstr_t *vstr, const char *str) { } void vstr_add_strn(vstr_t *vstr, const char *str, size_t len) { - if (vstr->had_error || !vstr_ensure_extra(vstr, len)) { + if (!vstr_ensure_extra(vstr, len)) { // if buf is fixed, we got here because there isn't enough room left // so just try to copy as much as we can, with room for a possible null byte if (vstr->fixed_buf && vstr->len < vstr->alloc) { @@ -263,9 +220,6 @@ copy: } STATIC char *vstr_ins_blank_bytes(vstr_t *vstr, size_t byte_pos, size_t byte_len) { - if (vstr->had_error) { - return NULL; - } size_t l = vstr->len; if (byte_pos > l) { byte_pos = l; @@ -303,9 +257,6 @@ void vstr_cut_head_bytes(vstr_t *vstr, size_t bytes_to_cut) { } void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { - if (vstr->had_error) { - return; - } if (len > vstr->len) { vstr->len = 0; } else { @@ -314,7 +265,7 @@ void vstr_cut_tail_bytes(vstr_t *vstr, size_t len) { } void vstr_cut_out_bytes(vstr_t *vstr, size_t byte_pos, size_t bytes_to_cut) { - if (vstr->had_error || byte_pos >= vstr->len) { + if (byte_pos >= vstr->len) { return; } else if (byte_pos + bytes_to_cut >= vstr->len) { vstr->len = byte_pos; diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h index 57277b156..1f23148c2 100644 --- a/qemu-arm/mpconfigport.h +++ b/qemu-arm/mpconfigport.h @@ -23,6 +23,7 @@ #define MICROPY_PY_IO (0) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine diff --git a/stmhal/Makefile b/stmhal/Makefile index 2c6ea806e..b320e0c89 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -111,7 +111,6 @@ SRC_LIB = $(addprefix lib/,\ timeutils/timeutils.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) SRC_C = \ @@ -138,6 +137,7 @@ SRC_C = \ uart.c \ can.c \ usb.c \ + wdt.c \ gccollect.c \ pybstdio.c \ help.c \ @@ -284,7 +284,7 @@ endif ifneq ($(FROZEN_MPY_DIR),) # To use frozen bytecode, put your .py files in a subdirectory (eg frozen/) and # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). -FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py') +FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY diff --git a/stmhal/accel.c b/stmhal/accel.c index 34e9d8e0e..e75f1c994 100644 --- a/stmhal/accel.c +++ b/stmhal/accel.c @@ -27,8 +27,7 @@ #include <stdio.h> #include <string.h> -#include STM32_HAL_H - +#include "py/mphal.h" #include "py/nlr.h" #include "py/runtime.h" #include "pin.h" @@ -61,7 +60,7 @@ void accel_init(void) { GPIO_InitTypeDef GPIO_InitStructure; // PB5 is connected to AVDD; pull high to enable MMA accel device - MICROPY_HW_MMA_AVDD_PIN.gpio->BSRRH = MICROPY_HW_MMA_AVDD_PIN.pin_mask; // turn off AVDD + GPIO_clear_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn off AVDD GPIO_InitStructure.Pin = MICROPY_HW_MMA_AVDD_PIN.pin_mask; GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStructure.Speed = GPIO_SPEED_LOW; @@ -82,9 +81,9 @@ STATIC void accel_start(void) { i2c_init(&I2CHandle1); // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again - MICROPY_HW_MMA_AVDD_PIN.gpio->BSRRH = MICROPY_HW_MMA_AVDD_PIN.pin_mask; // turn off + GPIO_clear_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn off HAL_Delay(30); - MICROPY_HW_MMA_AVDD_PIN.gpio->BSRRL = MICROPY_HW_MMA_AVDD_PIN.pin_mask; // turn on + GPIO_set_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn on HAL_Delay(30); HAL_StatusTypeDef status; diff --git a/stmhal/boards/OLIMEX_E407/mpconfigboard.h b/stmhal/boards/OLIMEX_E407/mpconfigboard.h index 4d1f7ff83..c9241fe63 100644 --- a/stmhal/boards/OLIMEX_E407/mpconfigboard.h +++ b/stmhal/boards/OLIMEX_E407/mpconfigboard.h @@ -23,10 +23,8 @@ #define MICROPY_HW_CLK_PLLQ (7) // UART config -#if MICROPY_HW_HAS_SWITCH == 0 #define MICROPY_HW_UART1_PORT (GPIOB) #define MICROPY_HW_UART1_PINS (GPIO_PIN_6 | GPIO_PIN_7) -#endif #define MICROPY_HW_UART2_PORT (GPIOA) #define MICROPY_HW_UART2_PINS (GPIO_PIN_2 | GPIO_PIN_3) @@ -50,8 +48,8 @@ #define MICROPY_HW_UART6_PINS (GPIO_PIN_6 | GPIO_PIN_7) // I2C busses -#define MICROPY_HW_I2C1_SCL (pin_B6) -#define MICROPY_HW_I2C1_SDA (pin_B7) +#define MICROPY_HW_I2C1_SCL (pin_B8) +#define MICROPY_HW_I2C1_SDA (pin_B9) #define MICROPY_HW_I2C2_SCL (pin_B10) #define MICROPY_HW_I2C2_SDA (pin_B11) diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h index c0e47c3ce..a1dbc0f46 100644 --- a/stmhal/boards/STM32F7DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h @@ -20,12 +20,19 @@ void STM32F7DISC_board_early_init(void); // HSE is 25MHz +// VCOClock = HSE * PLLN / PLLM = 25 MHz * 432 / 25 = 432 MHz +// SYSCLK = VCOClock / PLLP = 432 MHz / 2 = 216 MHz +// USB/SDMMC/RNG Clock = VCOClock / PLLQ = 432 MHz / 9 = 48 MHz #define MICROPY_HW_CLK_PLLM (25) -#define MICROPY_HW_CLK_PLLN (336) +#define MICROPY_HW_CLK_PLLN (432) #define MICROPY_HW_CLK_PLLP (RCC_PLLP_DIV2) -#define MICROPY_HW_CLK_PLLQ (7) +#define MICROPY_HW_CLK_PLLQ (9) -#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_6 +// From the reference manual, for 2.7V to 3.6V +// 151-180 MHz => 5 wait states +// 181-210 MHz => 6 wait states +// 211-216 MHz => 7 wait states +#define MICROPY_HW_FLASH_LATENCY FLASH_LATENCY_7 // 210-216 MHz needs 7 wait states // UART config #define MICROPY_HW_UART1_TX_PORT (GPIOA) diff --git a/stmhal/boards/pllvalues.py b/stmhal/boards/pllvalues.py new file mode 100644 index 000000000..183313f30 --- /dev/null +++ b/stmhal/boards/pllvalues.py @@ -0,0 +1,115 @@ +""" +This is an auxiliary script that is used to compute valid PLL values to set +the CPU frequency to a given value. The algorithm here appears as C code +for the machine.freq() function. +""" + +def close_int(x): + return abs(x - round(x)) < 0.01 + +# original version that requires N/M to be an integer (for simplicity) +def compute_pll(hse, sys): + for P in (2, 4, 6, 8): # allowed values of P + Q = sys * P / 48 + NbyM = sys * P / hse + # N/M and Q must be integers + if not (close_int(NbyM) and close_int(Q)): + continue + # VCO_OUT must be between 192MHz and 432MHz + if not (192 <= hse * NbyM <= 432): + continue + # compute M + M = int(192 // NbyM) + while hse > 2 * M or NbyM * M < 192: + M += 1 + # VCO_IN must be between 1MHz and 2MHz (2MHz recommended) + if not (M <= hse): + continue + # compute N + N = NbyM * M + # N and Q are restricted + if not (192 <= N <= 432 and 2 <= Q <= 15): + continue + # found valid values + assert NbyM == N // M + return (M, N, P, Q) + # no valid values found + return None + +# improved version that doesn't require N/M to be an integer +def compute_pll2(hse, sys): + for P in (2, 4, 6, 8): # allowed values of P + Q = sys * P / 48 + # Q must be an integer in a set range + if not (close_int(Q) and 2 <= Q <= 15): + continue + NbyM = sys * P / hse + # VCO_OUT must be between 192MHz and 432MHz + if not (192 <= hse * NbyM <= 432): + continue + # compute M + M = 192 // NbyM # starting value + while hse > 2 * M or NbyM * M < 192 or not close_int(NbyM * M): + M += 1 + # VCO_IN must be between 1MHz and 2MHz (2MHz recommended) + if not (M <= hse): + continue + # compute N + N = NbyM * M + # N must be an integer + if not close_int(N): + continue + # N is restricted + if not (192 <= N <= 432): + continue + # found valid values + return (M, N, P, Q) + # no valid values found + return None + +def verify_and_print_pll(hse, sys, pll): + M, N, P, Q = pll + + # compute derived quantities + vco_in = hse / M + vco_out = hse * N / M + pllck = hse / M * N / P + pll48ck = hse / M * N / Q + + # verify ints + assert close_int(M) + assert close_int(N) + assert close_int(P) + assert close_int(Q) + + # verify range + assert 2 <= M <= 63 + assert 192 <= N <= 432 + assert P in (2, 4, 6, 8) + assert 2 <= Q <= 15 + assert 1 <= vco_in <= 2 + assert 192 <= vco_out <= 432 + + # print out values + print(out_format % (sys, M, N, P, Q, vco_in, vco_out, pllck, pll48ck)) + +def main(): + global out_format + import sys + if len(sys.argv) != 2: + print("usage: pllvalues.py <hse in MHz>") + sys.exit(1) + hse_value = int(sys.argv[1]) + print("HSE =", hse_value, "MHz") + print("sys : M N P Q : VCO_IN VCO_OUT PLLCK PLL48CK") + out_format = "%3u : %2u %.1f %.2f %.2f : %5.2f %6.2f %6.2f %6.2f" + n_valid = 0 + for sysclk in range(1, 217): + pll = compute_pll2(hse_value, sysclk) + if pll is not None: + n_valid += 1 + verify_and_print_pll(hse_value, sysclk, pll) + print("found %u valid configurations" % n_valid) + +if __name__ == "__main__": + main() diff --git a/stmhal/dac.c b/stmhal/dac.c index 7493bb59a..a9b1b9eca 100644 --- a/stmhal/dac.c +++ b/stmhal/dac.c @@ -171,6 +171,14 @@ STATIC mp_obj_t pyb_dac_init_helper(pyb_dac_obj_t *self, mp_uint_t n_args, const #endif // stop anything already going on + __DMA1_CLK_ENABLE(); + DMA_HandleTypeDef DMA_Handle; + /* Get currently configured dma */ + dma_init_handle(&DMA_Handle, self->tx_dma_descr, (void*)NULL); + // Need to deinit DMA first + DMA_Handle.State = HAL_DMA_STATE_READY; + HAL_DMA_DeInit(&DMA_Handle); + HAL_DAC_Stop(&DAC_Handle, self->dac_channel); if ((self->dac_channel == DAC_CHANNEL_1 && DAC_Handle.DMA_Handle1 != NULL) || (self->dac_channel == DAC_CHANNEL_2 && DAC_Handle.DMA_Handle2 != NULL)) { diff --git a/stmhal/extint.c b/stmhal/extint.c index c0471719b..02b06fde5 100644 --- a/stmhal/extint.c +++ b/stmhal/extint.c @@ -251,10 +251,13 @@ void extint_swint(uint line) { if (line >= EXTI_NUM_VECTORS) { return; } + // we need 0 to 1 transition to trigger the interrupt #if defined(MCU_SERIES_L4) - EXTI->SWIER1 = (1 << line); + EXTI->SWIER1 &= ~(1 << line); + EXTI->SWIER1 |= (1 << line); #else - EXTI->SWIER = (1 << line); + EXTI->SWIER &= ~(1 << line); + EXTI->SWIER |= (1 << line); #endif } diff --git a/stmhal/lcd.c b/stmhal/lcd.c index 143ef9bbd..92f19b818 100644 --- a/stmhal/lcd.c +++ b/stmhal/lcd.c @@ -26,8 +26,8 @@ #include <stdio.h> #include <string.h> -#include STM32_HAL_H +#include "py/mphal.h" #include "py/nlr.h" #include "py/runtime.h" @@ -113,14 +113,16 @@ STATIC void lcd_delay(void) { STATIC void lcd_out(pyb_lcd_obj_t *lcd, int instr_data, uint8_t i) { lcd_delay(); - lcd->pin_cs1->gpio->BSRRH = lcd->pin_cs1->pin_mask; // CS=0; enable + GPIO_clear_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); // CS=0; enable if (instr_data == LCD_INSTR) { - lcd->pin_a0->gpio->BSRRH = lcd->pin_a0->pin_mask; // A0=0; select instr reg + GPIO_clear_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); // A0=0; select instr reg } else { - lcd->pin_a0->gpio->BSRRL = lcd->pin_a0->pin_mask; // A0=1; select data reg + GPIO_set_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); // A0=1; select data reg } lcd_delay(); HAL_SPI_Transmit(lcd->spi, &i, 1, 1000); + lcd_delay(); + GPIO_set_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); // CS=1; disable } // write a string to the LCD at the current cursor location @@ -260,10 +262,10 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp spi_init(lcd->spi, false); // set the pins to default values - lcd->pin_cs1->gpio->BSRRL = lcd->pin_cs1->pin_mask; - lcd->pin_rst->gpio->BSRRL = lcd->pin_rst->pin_mask; - lcd->pin_a0->gpio->BSRRL = lcd->pin_a0->pin_mask; - lcd->pin_bl->gpio->BSRRH = lcd->pin_bl->pin_mask; + GPIO_set_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); + GPIO_set_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); + GPIO_set_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); + GPIO_clear_pin(lcd->pin_bl->gpio, lcd->pin_bl->pin_mask); // init the pins to be push/pull outputs GPIO_InitTypeDef GPIO_InitStructure; @@ -285,9 +287,9 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp // init the LCD HAL_Delay(1); // wait a bit - lcd->pin_rst->gpio->BSRRH = lcd->pin_rst->pin_mask; // RST=0; reset + GPIO_clear_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); // RST=0; reset HAL_Delay(1); // wait for reset; 2us min - lcd->pin_rst->gpio->BSRRL = lcd->pin_rst->pin_mask; // RST=1; enable + GPIO_set_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); // RST=1; enable HAL_Delay(1); // wait for reset; 2us min lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display) @@ -370,9 +372,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_contrast_obj, pyb_lcd_contrast); STATIC mp_obj_t pyb_lcd_light(mp_obj_t self_in, mp_obj_t value) { pyb_lcd_obj_t *self = self_in; if (mp_obj_is_true(value)) { - self->pin_bl->gpio->BSRRL = self->pin_bl->pin_mask; // set pin high to turn backlight on + GPIO_set_pin(self->pin_bl->gpio, self->pin_bl->pin_mask); // set pin high to turn backlight on } else { - self->pin_bl->gpio->BSRRH = self->pin_bl->pin_mask; // set pin low to turn backlight off + GPIO_clear_pin(self->pin_bl->gpio, self->pin_bl->pin_mask); // set pin low to turn backlight off } return mp_const_none; } diff --git a/stmhal/main.c b/stmhal/main.c index 32baae532..244622503 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -44,6 +44,7 @@ #include "pendsv.h" #include "gccollect.h" #include "readline.h" +#include "modmachine.h" #include "i2c.h" #include "spi.h" #include "uart.h" @@ -410,6 +411,8 @@ soft_reset: led_state(4, 0); uint reset_mode = update_reset_mode(1); + machine_init(); + #if MICROPY_HW_ENABLE_RTC if (first_soft_reset) { rtc_init_start(false); diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 0b01058fa..ca17eff80 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -44,6 +44,50 @@ #include "rtc.h" #include "i2c.h" #include "spi.h" +#include "wdt.h" + +#if defined(MCU_SERIES_F4) +// the HAL does not define these constants +#define RCC_CSR_IWDGRSTF (0x20000000) +#define RCC_CSR_PINRSTF (0x04000000) +#elif defined(MCU_SERIES_L4) +// L4 does not have a POR, so use BOR instead +#define RCC_CSR_PORRSTF RCC_CSR_BORRSTF +#endif + +#define PYB_RESET_SOFT (0) +#define PYB_RESET_POWER_ON (1) +#define PYB_RESET_HARD (2) +#define PYB_RESET_WDT (3) +#define PYB_RESET_DEEPSLEEP (4) + +STATIC uint32_t reset_cause; + +void machine_init(void) { + #if defined(MCU_SERIES_F4) + if (PWR->CSR & PWR_CSR_SBF) { + // came out of standby + reset_cause = PYB_RESET_DEEPSLEEP; + PWR->CR = PWR_CR_CSBF; + } else + #endif + { + // get reset cause from RCC flags + uint32_t state = RCC->CSR; + if (state & RCC_CSR_IWDGRSTF || state & RCC_CSR_WWDGRSTF) { + reset_cause = PYB_RESET_WDT; + } else if (state & RCC_CSR_PORRSTF || state & RCC_CSR_BORRSTF) { + reset_cause = PYB_RESET_POWER_ON; + } else if (state & RCC_CSR_PINRSTF) { + reset_cause = PYB_RESET_HARD; + } else { + // default is soft reset + reset_cause = PYB_RESET_SOFT; + } + } + // clear RCC reset flags + RCC->CSR = RCC_CSR_RMVF; +} // machine.info([dump_alloc_table]) // Print out lots of information about the board. @@ -447,13 +491,10 @@ STATIC mp_obj_t machine_deepsleep(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_deepsleep_obj, machine_deepsleep); -#if 0 STATIC mp_obj_t machine_reset_cause(void) { - return mp_obj_new_int(0); - //return mp_obj_new_int(pyb_sleep_get_reset_cause()); + return MP_OBJ_NEW_SMALL_INT(reset_cause); } STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause); -#endif STATIC const mp_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_umachine) }, @@ -468,8 +509,8 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&pyb_wfi_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&machine_sleep_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&machine_deepsleep_obj }, -#if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&machine_reset_cause_obj }, +#if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&machine_wake_reason_obj }, #endif @@ -490,10 +531,10 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = { // initialize master mode on the peripheral. { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&machine_i2c_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type }, #if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_type }, { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type }, @@ -501,11 +542,13 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) }, { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) }, { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_POWER_ON), MP_OBJ_NEW_SMALL_INT(PYB_SLP_PWRON_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HARD_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WDT_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_HIB_RESET) }, - { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_SLP_SOFT_RESET) }, +#endif + { MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_POWER_ON) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_HARD) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_WDT) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_DEEPSLEEP) }, + { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_SOFT) }, +#if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) }, { MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) }, { MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) }, diff --git a/stmhal/modmachine.h b/stmhal/modmachine.h index 981728c27..042afb850 100644 --- a/stmhal/modmachine.h +++ b/stmhal/modmachine.h @@ -31,6 +31,8 @@ #include "py/nlr.h" #include "py/obj.h" +void machine_init(void); + MP_DECLARE_CONST_FUN_OBJ(machine_info_obj); MP_DECLARE_CONST_FUN_OBJ(machine_unique_id_obj); MP_DECLARE_CONST_FUN_OBJ(machine_reset_obj); diff --git a/stmhal/wdt.c b/stmhal/wdt.c new file mode 100644 index 000000000..d9a089d01 --- /dev/null +++ b/stmhal/wdt.c @@ -0,0 +1,108 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include STM32_HAL_H + +#include "py/runtime.h" +#include "wdt.h" + +typedef struct _pyb_wdt_obj_t { + mp_obj_base_t base; +} pyb_wdt_obj_t; + +STATIC pyb_wdt_obj_t pyb_wdt = {{&pyb_wdt_type}}; + +STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { + // parse arguments + enum { ARG_id, ARG_timeout }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_timeout, MP_ARG_INT, {.u_int = 5000} }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + mp_int_t id = args[ARG_id].u_int; + if (id != 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "WDT(%d) does not exist", id)); + } + + // timeout is in milliseconds + mp_int_t timeout = args[ARG_timeout].u_int; + + // compute prescaler + uint32_t prescaler; + for (prescaler = 0; prescaler < 6 && timeout >= 512; ++prescaler, timeout /= 2) { + } + + // convert milliseconds to ticks + timeout *= 8; // 32kHz / 4 = 8 ticks per millisecond (approx) + if (timeout <= 0) { + mp_raise_ValueError("WDT timeout too short"); + } else if (timeout > 0xfff) { + mp_raise_ValueError("WDT timeout too long"); + } + timeout -= 1; + + // set the reload register + while (IWDG->SR & 2) { + } + IWDG->KR = 0x5555; + IWDG->RLR = timeout; + + // set the prescaler + while (IWDG->SR & 1) { + } + IWDG->KR = 0x5555; + IWDG->PR = prescaler; + + // start the watch dog + IWDG->KR = 0xcccc; + + return (mp_obj_t)&pyb_wdt; +} + +STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) { + (void)self_in; + IWDG->KR = 0xaaaa; + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed); + +STATIC const mp_map_elem_t pyb_wdt_locals_dict_table[] = { + { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&pyb_wdt_feed_obj }, +}; + +STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table); + +const mp_obj_type_t pyb_wdt_type = { + { &mp_type_type }, + .name = MP_QSTR_WDT, + .make_new = pyb_wdt_make_new, + .locals_dict = (mp_obj_t)&pyb_wdt_locals_dict, +}; diff --git a/stmhal/wdt.h b/stmhal/wdt.h new file mode 100644 index 000000000..362d6ef68 --- /dev/null +++ b/stmhal/wdt.h @@ -0,0 +1,27 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +extern const mp_obj_type_t pyb_wdt_type; diff --git a/teensy/Makefile b/teensy/Makefile index 7b34ba90e..5eb871661 100644 --- a/teensy/Makefile +++ b/teensy/Makefile @@ -110,7 +110,6 @@ LIB_SRC_C = $(addprefix lib/,\ mp-readline/readline.c \ utils/pyexec.c \ utils/pyhelp.c \ - utils/printf.c \ ) SRC_TEENSY = $(addprefix core/,\ @@ -155,24 +154,15 @@ endif # USE_MEMZIP ifeq ($(USE_FROZEN),1) -CFLAGS += -DMICROPY_MODULE_FROZEN_STR - -SRC_C += \ - lexerfrozen.c - -OBJ += $(BUILD)/frozen-files.o - -MAKE_FROZEN = ../tools/make-frozen.py ifeq ($(FROZEN_DIR),) FROZEN_DIR = memzip_files endif -$(BUILD)/frozen-files.o: $(BUILD)/frozen-files.c - $(call compile_c) +CFLAGS += -DMICROPY_MODULE_FROZEN_STR -$(BUILD)/frozen-files.c: $(shell find ${FROZEN_DIR} -type f) - @$(ECHO) "Creating $@" - $(Q)$(PYTHON) $(MAKE_FROZEN) $(FROZEN_DIR) > $@ +SRC_C += \ + lexerfrozen.c \ + $(BUILD)/frozen.c endif # USE_FROZEN diff --git a/tests/basics/array1.py b/tests/basics/array1.py index bce22cc57..e5ea6683c 100644 --- a/tests/basics/array1.py +++ b/tests/basics/array1.py @@ -6,6 +6,12 @@ i = array.array('I', [1, 2, 3]) print(i, len(i)) print(a[0]) print(i[-1]) +a = array.array('l', [-1]) +print(len(a), a[0]) +a1 = array.array('l', [1, 2, 3]) +a2 = array.array('L', [1, 2, 3]) +print(a2[1]) +print(a1 == a2) # Empty arrays print(len(array.array('h'))) diff --git a/tests/basics/errno1.py b/tests/basics/errno1.py new file mode 100644 index 000000000..680104481 --- /dev/null +++ b/tests/basics/errno1.py @@ -0,0 +1,15 @@ +# test errno's and uerrno module + +try: + import uerrno +except ImportError: + print("SKIP") + import sys + sys.exit() + +# check that constants exist and are integers +print(type(uerrno.EIO)) + +# check that errors are rendered in a nice way +msg = str(OSError(uerrno.EIO)) +print(msg[:7], msg[-5:]) diff --git a/tests/basics/errno1.py.exp b/tests/basics/errno1.py.exp new file mode 100644 index 000000000..e60fdf049 --- /dev/null +++ b/tests/basics/errno1.py.exp @@ -0,0 +1,2 @@ +<class 'int'> +[Errno ] EIO diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py index 857e171c1..1abe34b4c 100644 --- a/tests/basics/struct1.py +++ b/tests/basics/struct1.py @@ -10,6 +10,8 @@ print(struct.unpack(">bI", b"\x80\0\0\x01\0")) # 32-bit little-endian specific #print(struct.unpack("bI", b"\x80\xaa\x55\xaa\0\0\x01\0")) +print(struct.pack("<l", 1)) +print(struct.pack(">l", 1)) print(struct.pack("<i", 1)) print(struct.pack(">i", 1)) print(struct.pack("<h", 1)) diff --git a/tests/extmod/framebuf1.py b/tests/extmod/framebuf1.py new file mode 100644 index 000000000..f550b6b4f --- /dev/null +++ b/tests/extmod/framebuf1.py @@ -0,0 +1,41 @@ +try: + import framebuf +except ImportError: + print("SKIP") + import sys + sys.exit() + +w = 5 +h = 16 +buf = bytearray(w * h // 8) +fbuf = framebuf.FrameBuffer1(buf, w, h, w) + +# 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) + +# get pixel +print(fbuf.pixel(0, 0), fbuf.pixel(1, 1)) + +# 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) diff --git a/tests/extmod/framebuf1.py.exp b/tests/extmod/framebuf1.py.exp new file mode 100644 index 000000000..8fd8c3709 --- /dev/null +++ b/tests/extmod/framebuf1.py.exp @@ -0,0 +1,9 @@ +bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') +bytearray(b'\x01\x00\x00\x00\x01\x80\x00\x00\x00\x80') +1 0 +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x01\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\x00\x00\x00') +bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01') diff --git a/tests/extmod/machine_pulse.py b/tests/extmod/machine_pulse.py new file mode 100644 index 000000000..b6e126435 --- /dev/null +++ b/tests/extmod/machine_pulse.py @@ -0,0 +1,54 @@ +try: + import umachine as machine +except ImportError: + import machine +try: + machine.PinBase + machine.time_pulse_us +except AttributeError: + print("SKIP") + import sys + sys.exit() + + +class ConstPin(machine.PinBase): + + def __init__(self, value): + self.v = value + + def value(self, v=None): + if v is None: + return self.v + else: + self.v = v + + +class TogglePin(machine.PinBase): + + def __init__(self): + self.v = 0 + + def value(self, v=None): + if v is None: + self.v = 1 - self.v + print("value:", self.v) + return self.v + + +p = TogglePin() + +t = machine.time_pulse_us(p, 1) +print(type(t)) +t = machine.time_pulse_us(p, 0) +print(type(t)) + +p = ConstPin(0) +try: + machine.time_pulse_us(p, 1, 10) +except OSError: + print("OSError") + +try: + machine.time_pulse_us(p, 0, 10) +except OSError: + print("OSError") diff --git a/tests/extmod/machine_pulse.py.exp b/tests/extmod/machine_pulse.py.exp new file mode 100644 index 000000000..f9a474218 --- /dev/null +++ b/tests/extmod/machine_pulse.py.exp @@ -0,0 +1,9 @@ +value: 1 +value: 0 +<class 'int'> +value: 1 +value: 0 +value: 1 +<class 'int'> +OSError +OSError diff --git a/tests/extmod/urandom_basic.py b/tests/extmod/urandom_basic.py index 7e4d8bf34..bf00035bd 100644 --- a/tests/extmod/urandom_basic.py +++ b/tests/extmod/urandom_basic.py @@ -17,3 +17,9 @@ random.seed(1) r = random.getrandbits(16) random.seed(1) print(random.getrandbits(16) == r) + +# check that it throws an error for zero bits +try: + random.getrandbits(0) +except ValueError: + print('ValueError') diff --git a/tests/extmod/urandom_extra.py b/tests/extmod/urandom_extra.py index a9ecd881d..004fb10cc 100644 --- a/tests/extmod/urandom_extra.py +++ b/tests/extmod/urandom_extra.py @@ -16,6 +16,31 @@ for i in range(50): assert 2 <= random.randrange(2, 6) < 6 assert -2 <= random.randrange(-2, 2) < 2 assert random.randrange(1, 9, 2) in (1, 3, 5, 7) + assert random.randrange(2, 1, -1) in (1, 2) + +# empty range +try: + random.randrange(0) +except ValueError: + print('ValueError') + +# empty range +try: + random.randrange(2, 1) +except ValueError: + print('ValueError') + +# zero step +try: + random.randrange(2, 1, 0) +except ValueError: + print('ValueError') + +# empty range +try: + random.randrange(2, 1, 1) +except ValueError: + print('ValueError') print('randint') for i in range(50): @@ -23,11 +48,23 @@ for i in range(50): assert 2 <= random.randint(2, 6) <= 6 assert -2 <= random.randint(-2, 2) <= 2 +# empty range +try: + random.randint(2, 1) +except ValueError: + print('ValueError') + print('choice') lst = [1, 2, 5, 6] for i in range(50): assert random.choice(lst) in lst +# empty sequence +try: + random.choice([]) +except IndexError: + print('IndexError') + print('random') for i in range(50): assert 0 <= random.random() < 1 diff --git a/tests/extmod/uzlib_decompio.py b/tests/extmod/uzlib_decompio.py index ee3204d07..75a6df0ca 100644 --- a/tests/extmod/uzlib_decompio.py +++ b/tests/extmod/uzlib_decompio.py @@ -7,7 +7,7 @@ import uio as io # Raw DEFLATE bitstream buf = io.BytesIO(b'\xcbH\xcd\xc9\xc9\x07\x00') -inp = zlib.DecompIO(buf) +inp = zlib.DecompIO(buf, -8) print(buf.seek(0, 1)) print(inp.read(1)) print(buf.seek(0, 1)) @@ -17,3 +17,16 @@ print(buf.seek(0, 1)) print(inp.read(1)) print(inp.read()) print(buf.seek(0, 1)) + + +# zlib bitstream +inp = zlib.DecompIO(io.BytesIO(b'x\x9c30\xa0=\x00\x00\xb3q\x12\xc1')) +print(inp.read(10)) +print(inp.read()) + +# zlib bitstream, wrong checksum +inp = zlib.DecompIO(io.BytesIO(b'x\x9c30\xa0=\x00\x00\xb3q\x12\xc0')) +try: + print(inp.read()) +except OSError as e: + print(repr(e)) diff --git a/tests/extmod/uzlib_decompio.py.exp b/tests/extmod/uzlib_decompio.py.exp index 6ef811d7d..3f5f360fa 100644 --- a/tests/extmod/uzlib_decompio.py.exp +++ b/tests/extmod/uzlib_decompio.py.exp @@ -7,3 +7,6 @@ b'lo' b'' b'' 7 +b'0000000000' +b'000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' +OSError(22,) diff --git a/tests/pyb/extint.py b/tests/pyb/extint.py index 47d84c8b5..a8ba484b1 100644 --- a/tests/pyb/extint.py +++ b/tests/pyb/extint.py @@ -1,8 +1,17 @@ import pyb +# test basic functionality ext = pyb.ExtInt('X1', pyb.ExtInt.IRQ_RISING, pyb.Pin.PULL_DOWN, lambda l:print('line:', l)) ext.disable() ext.enable() print(ext.line()) ext.swint() + +# test swint while disabled, then again after re-enabled +ext.disable() +ext.swint() +ext.enable() +ext.swint() + +# disable now that the test is finished ext.disable() diff --git a/tests/pyb/extint.py.exp b/tests/pyb/extint.py.exp index 28019d75c..daed01c7f 100644 --- a/tests/pyb/extint.py.exp +++ b/tests/pyb/extint.py.exp @@ -1,2 +1,3 @@ 0 line: 0 +line: 0 diff --git a/tests/run-tests b/tests/run-tests index 5e8819729..059e4e910 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -203,6 +203,7 @@ def run_tests(pyb, tests, args): skip_tests.add('thread/thread_gc1.py') # has reliability issues skip_tests.add('thread/thread_lock4.py') # has reliability issues skip_tests.add('thread/stress_heap.py') # has reliability issues + skip_tests.add('thread/stress_recurse.py') # has reliability issues if not has_complex: skip_tests.add('float/complex1.py') diff --git a/unix/Makefile b/unix/Makefile index 3afa80dfa..956b1daef 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -157,7 +157,6 @@ endif LIB_SRC_C = $(addprefix lib/,\ $(LIB_SRC_C_EXTRA) \ - utils/printf.c \ timeutils/timeutils.c \ ) @@ -183,7 +182,7 @@ ifneq ($(FROZEN_MPY_DIR),) # then invoke make with FROZEN_MPY_DIR=frozen (be sure to build from scratch). MPY_CROSS = ../mpy-cross/mpy-cross MPY_TOOL = ../tools/mpy-tool.py -FROZEN_MPY_PY_FILES := $(shell find $(FROZEN_MPY_DIR) -type f -name '*.py') +FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py') FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/,$(FROZEN_MPY_PY_FILES:.py=.mpy)) CFLAGS += -DMICROPY_QSTR_EXTRA_POOL=mp_qstr_frozen_const_pool CFLAGS += -DMICROPY_MODULE_FROZEN_MPY diff --git a/unix/modjni.c b/unix/modjni.c index 20804e5a5..c06e68eaa 100644 --- a/unix/modjni.c +++ b/unix/modjni.c @@ -65,6 +65,7 @@ STATIC const mp_obj_type_t jmethod_type; STATIC mp_obj_t new_jobject(jobject jo); STATIC mp_obj_t new_jclass(jclass jc); STATIC mp_obj_t call_method(jobject obj, const char *name, jarray methods, bool is_constr, mp_uint_t n_args, const mp_obj_t *args); +STATIC bool py2jvalue(const char **jtypesig, mp_obj_t arg, jvalue *out); typedef struct _mp_obj_jclass_t { mp_obj_base_t base; @@ -244,11 +245,36 @@ STATIC void get_jclass_name(jobject obj, char *buf) { STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_jobject_t *self = self_in; + mp_uint_t idx = mp_obj_get_int(index); + char class_name[64]; + get_jclass_name(self->obj, class_name); + //printf("class: %s\n", class_name); + + if (class_name[0] == '[') { + if (class_name[1] == 'L' || class_name[1] == '[') { + if (value == MP_OBJ_NULL) { + // delete + assert(0); + } else if (value == MP_OBJ_SENTINEL) { + // load + jobject el = JJ(GetObjectArrayElement, self->obj, idx); + return new_jobject(el); + } else { + // store + jvalue jval; + const char *t = class_name + 1; + py2jvalue(&t, value, &jval); + JJ(SetObjectArrayElement, self->obj, idx, jval.l); + return mp_const_none; + } + } + mp_not_implemented(""); + } + if (!JJ(IsInstanceOf, self->obj, List_class)) { return MP_OBJ_NULL; } - mp_uint_t idx = mp_obj_get_int(index); if (value == MP_OBJ_NULL) { // delete @@ -628,6 +654,54 @@ STATIC mp_obj_t mod_jni_cls(mp_obj_t cls_name_in) { } MP_DEFINE_CONST_FUN_OBJ_1(mod_jni_cls_obj, mod_jni_cls); +STATIC mp_obj_t mod_jni_array(mp_obj_t type_in, mp_obj_t size_in) { + if (!env) { + create_jvm(); + } + mp_int_t size = mp_obj_get_int(size_in); + jobject res = NULL; + + if (MP_OBJ_IS_TYPE(type_in, &jclass_type)) { + + mp_obj_jclass_t *jcls = type_in; + res = JJ(NewObjectArray, size, jcls->cls, NULL); + + } else if (MP_OBJ_IS_STR(type_in)) { + const char *type = mp_obj_str_get_str(type_in); + switch (*type) { + case 'Z': + res = JJ(NewBooleanArray, size); + break; + case 'B': + res = JJ(NewByteArray, size); + break; + case 'C': + res = JJ(NewCharArray, size); + break; + case 'S': + res = JJ(NewShortArray, size); + break; + case 'I': + res = JJ(NewIntArray, size); + break; + case 'J': + res = JJ(NewLongArray, size); + break; + case 'F': + res = JJ(NewFloatArray, size); + break; + case 'D': + res = JJ(NewDoubleArray, size); + break; + } + + } + + return new_jobject(res); +} +MP_DEFINE_CONST_FUN_OBJ_2(mod_jni_array_obj, mod_jni_array); + + STATIC mp_obj_t mod_jni_env() { return mp_obj_new_int((mp_int_t)env); } @@ -636,6 +710,7 @@ MP_DEFINE_CONST_FUN_OBJ_0(mod_jni_env_obj, mod_jni_env); STATIC const mp_map_elem_t mp_module_jni_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_jni) }, { MP_OBJ_NEW_QSTR(MP_QSTR_cls), (mp_obj_t)&mod_jni_cls_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_array), (mp_obj_t)&mod_jni_array_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_env), (mp_obj_t)&mod_jni_env_obj }, }; diff --git a/unix/moduselect.c b/unix/moduselect.c index 38f8d11ed..e670c3814 100644 --- a/unix/moduselect.c +++ b/unix/moduselect.c @@ -40,7 +40,9 @@ #include "py/mphal.h" #include "fdfile.h" +#if MICROPY_PY_SOCKET extern const mp_obj_type_t mp_type_socket; +#endif // Flags for poll() #define FLAG_ONESHOT (1) @@ -57,7 +59,11 @@ typedef struct _mp_obj_poll_t { STATIC int get_fd(mp_obj_t fdlike) { int fd; // Shortcut for fdfile compatible types - if (MP_OBJ_IS_TYPE(fdlike, &mp_type_fileio) || MP_OBJ_IS_TYPE(fdlike, &mp_type_socket)) { + if (MP_OBJ_IS_TYPE(fdlike, &mp_type_fileio) + #if MICROPY_PY_SOCKET + || MP_OBJ_IS_TYPE(fdlike, &mp_type_socket) + #endif + ) { mp_obj_fdfile_t *fdfile = MP_OBJ_TO_PTR(fdlike); fd = fdfile->fd; } else { diff --git a/unix/mpconfigport_coverage.h b/unix/mpconfigport_coverage.h index f9a6fbd9d..5fd5b82c1 100644 --- a/unix/mpconfigport_coverage.h +++ b/unix/mpconfigport_coverage.h @@ -35,3 +35,4 @@ #undef MICROPY_VFS_FAT #define MICROPY_FSUSERMOUNT (1) #define MICROPY_VFS_FAT (1) +#define MICROPY_PY_FRAMEBUF (1) diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h index ccf8768bf..da49bc0dc 100644 --- a/windows/mpconfigport.h +++ b/windows/mpconfigport.h @@ -82,6 +82,7 @@ #define MICROPY_STACKLESS (0) #define MICROPY_STACKLESS_STRICT (0) +#define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UCTYPES (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_UJSON (1) |
