aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Shawcroft <scott.shawcroft@gmail.com>2017-11-02 12:41:50 -0700
committerScott Shawcroft <scott.shawcroft@gmail.com>2017-11-02 12:41:50 -0700
commit7b393bc406bfa50f7bbfacd573d0fdab04dcb5f4 (patch)
tree26edf5d84c27d5a86247e2c11b10905607371d3e
parent3cfb06042ec46b1214576bb7013a996a287697a6 (diff)
parentfe45d78b1edd6d2202c3544797885cb0b12d4f03 (diff)
Merge tag 'v1.9.3'
Introduction of ports subdirectory where all ports are moved to The main change in this release is the introduction of a "ports/" subdirectory at the top-level of the repository, and all of the ports are moved here. In the process the "stmhal" port is renamed to "stm32" to better reflect the MCU that it targets. In addition, the STM32 CMSIS and HAL sources are moved to a new submodule called "stm32lib". The bytecode has changed in this release, compared to the previous release, and as a consequence the .mpy version number has increased to version 3. This means that scripts compiled with the previous mpy-cross must be recompiled to work with this new version. There have also been various enhancements and optimisations, such as: check for valid UTF-8 when creating str objects, support for reverse special binary operations like __radd__, full domain checking in the math module, support for floor-division and modulo in the viper emitter, and addition of stack overflow checking when executing a regex. The stm32 port sees improved support for F7 MCUs, addition of a new board B_L475E_IOT01A based on the STM32L475, and support for the Wiznet W5500 chipset along with improved socket behaviour. A detailed list of changes follows. py core: - objstr: startswith, endswith: check arg to be a string - nlrx86,x64: replace #define of defined() with portable macro usage - objtype: handle NotImplemented return from binary special methods - objtype: mp_obj_class_lookup: improve debug logging - map: remove unused new/free functions - make m_malloc_fail() have void return type, since it doesn't return - modstruct: in struct.pack, stop converting if there are no args left - modstruct: check and prevent buffer-read overflow in struct unpacking - modstruct: check and prevent buffer-write overflow in struct packing - nlrthumb: get working again on standard Thumb arch (ie not Thumb2) - objfloat: fix binary ops with incompatible objects - obj: fix comparison of float/complex NaN with itself - objtype: implement fallback for instance inplace special methods - objtuple: properly implement comparison with incompatible types - objstr: add check for valid UTF-8 when making a str from bytes - objlist: properly implement comparison with incompatible types - runtime0.h: move relational ops to the beginning of mp_binary_op_t - runtime0.h: move MP_BINARY_OP_DIVMOD to the end of mp_binary_op_t - objtype: make sure mp_binary_op_method_name has full size again - runtime0.h: put inplace arith ops in front of normal operations - builtinhelp: simplify code slightly by extracting object type - runtime: implement dispatch for "reverse op" special methods - nlrx86: fix building for Android/x86 - builtinhelp: change signature of help text var from pointer to array - runtime.h: change empty mp_warning macro so var-args are non empty - modbuiltins: implement abs() by dispatching to MP_UNARY_OP_ABS - {objfloat,objcomplex}: optimise MP_UNARY_OP_ABS by reusing variables - mpconfig.h: add note that using computed gotos in VM is not C99 - objstr: strip: don't strip "\0" by default - objexcept: prevent infinite recursion when allocating exceptions - stream: remove unnecessary checks for NULL return from vstr_add_len - vstr: raise a RuntimeError if fixed vstr buffer overflows - vm: use lowercase letter at start of exception message - persistentcode: define mp_raw_code_save_file() for any unix target - add config option to print warnings/errors to stderr - objfloat: support raising a negative number to a fractional power - objset: simplify set and frozenset by separating their locals dicts - objset: check that RHS of a binary op is a set/frozenset - objset: include the failed key in a KeyError raised from set.remove - objtype: change type of enum-to-qstr table to uint16_t to save space - objstr: make empty bytes object have a null-terminating byte - mpprint: only check for null string printing when NDEBUG not defined - objtype: clean up unary- and binary-op enum-to-qstr mapping tables - persistentcode: bump .mpy version number to version 3 - bc: update opcode_format_table to match the bytecode - modmath: add full checks for math domain errors - modmath: convert log2 macro into a function - formatfloat: don't print the negative sign of a NaN value - formatfloat: use standard isinf, isnan funcs instead of custom ones - modbuiltins: use existing utf8_get_char helper in builtin ord func - emitnative: implement floor-division and modulo for viper emitter - objtype: use CPython compatible method name for sizeof - objtype: fit qstrs for special methods in byte type - objtype: define all special methods if requested - objtype: introduce MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS extmod: - modubinascii: only include uzlib/tinf.h when it's really needed - modussl_mbedtls: allow to compile with MBEDTLS_DEBUG_C disabled - machine_pinbase: put PinBase singleton in ROM - re1.5: upgrade to v0.8.2, adds hook for stack overflow checking - modure: add stack overflow checking when executing a regex - uos_dupterm: update uos.dupterm() and helper funcs to have index - uos_dupterm: swallow any errors from dupterm closing the stream - vfs: replace VLA in proxy func with small, static sized array - modussl: add finaliser support for ussl objects - modussl_mbedtls: allow to compile with unix coverage build lib: - add new submodule, stm32lib containing STM32 CMSIS and HAL source - embed/abort_: use mp_raise_msg helper function - libm: fix tanhf so that it correctly handles +/- infinity args - libm: remove implementation of log2f, use MP_NEED_LOG2 instead - axtls: update, support for SSL_EAGAIN return code - berkeley-db-1.xx: update, allow to override MINCACHE, DEFPSIZE drivers: - memory/spiflash: change from hard-coded soft SPI to generic SPI - display/ssd1306.py: improve performance of graphics methods - nrf24l01: make nRF24L01 test script more portable - display/ssd1306: implement SSD1306_I2C poweron method - display/ssd1306: make poweron() work the same with SSD1306_SPI - wiznet5k: improve the performance of socket ops with threading - wiznet5k: get low-level W5500 driver working tools: - upip: upgrade to 1.2.2 - pyboard: use repr() when quoting data in error messages - pyboard: update docstring for additional device support tests: - object_new: better messages, check user __new__() method - class_new: add checks for __init__ being called and other improvements - class_new: add another testcase for __new__/__init__ interaction - class_inplace_op: test for inplace op fallback to normal one - run-bench-tests: update locations of executables, now in ports/ - class_reverse_op: test for reverse arith ops special methods - run-tests: skip class_inplace_op for minimal profile - run-tests: fix copy-paste mistake in var name - cpydiff: add cases for locals() discrepancies - extmod: add test for ure regexes leading to infinite recursion - extmod: add test for '-' in character class in regex - run-tests: close device under test using "finally" - net_inet: update tls test to work with CPython and incl new site unix port: - rename modsocket.c to modusocket.c - modusocket: remove #if MICROPY_SOCKET_EXTRA code blocks - enable MICROPY_PY_REVERSE_SPECIAL_METHODS stm32 port: - modmachine: make machine.bootloader() work when MPU is enabled - modmachine: improve support for sleep/deepsleep on F7 MCUs - compute PLL freq table during build instead of at run time - modmachine: for F7 MCU, save power by reducing internal volt reg - boards/pllvalues.py: make script work with both Python 2 and 3 - Makefile: use lib/stm32lib instead of local cmsis and hal files - remove cmsis and hal files, they are now a submodule - Makefile: automatically fetch stm32lib submodule if needed - update to new STM Cube HAL library - fix clock initialisation of L4 MCUs - rename stmhal port directory to stm32 - remove unused usbd_msc.c file - boards: change remaining stm32f4xx_hal_conf.h to unix line ending - boards: change linker scripts to use "K" instead of hex byte size - boards: fix I2C1 pin mapping on NUCLEO_F401RE/F411RE boards - i2c: when scanning for I2C devices only do 1 probe per address - modnwwiznet5k: release the GIL on blocking network operations - boards: add new board B_L475E_IOT01A based on STM32L475 - make-stmconst.py: make sure mpz const data lives in ROM - timer: make pyb.Timer() instances persistent - mpconfigport.h: add configuration for max periphs on L4 series - usbdev: make the USBD callback struct const so it can go in ROM - usbdev: change static function variable to non-static - usbdev: put all CDC state in a struct - usbdev: put all HID state in a struct - usbdev: simplify CDC tx/rx buffer passing - usbdev: simplify HID tx/rx buffer passing - usbdev/core: add state parameter to all callback functions - usbdev: put all state for the USB device driver in a struct - usbdev: simplify pointers to MSC state and block dev operations - usbdev: merge all global USB device state into a single struct - usbdev: make device descriptor callbacks take a state pointer - usbdev: move all the USB device descriptor state into its struct - timer: enable ARPE so that timer freq can be changed smoothly - modnwwiznet5k: get the IP address of an established socket - boards: fix typos in stm32f767_af.csv table - usbd_cdc_interface: don't reset CDC output buf on initialisation - modnwwiznet5k: implement WIZNET5K.isconnected() method - modusocket: make getaddrinfo() work when passed an IP address - modusocket: return OSError(-2) if getaddrinfo fails - mpconfigport.h: add MICROPY_THREAD_YIELD() macro - modnwwiznet5k: add support for W5500 Ethernet chip - modnwwiznet5k: increase SPI bus speed to 42MHz - modnwwiznet5k: implement stream ioctl for the Wiznet driver - mphalport: improve efficiency of mp_hal_stdout_tx_strn_cooked - make uos.dupterm() conform to specs by using extmod version cc3200 port: - enable micropython.kbd_intr() method - use standard implementation of keyboard interrupt esp8266 port: - rename axtls_helpers.c to posix_helpers.c - posix_helpers: set ENOMEM on memory alloc failure - set DEFPSIZE=1024, MINCACHE=3 for "btree" module - esp_mphal: send data in chunks to mp_uos_dupterm_tx_strn - modnetwork: add "bssid" keyword arg to WLAN.connect() method - modules/webrepl_setup: add info about allowed password length zephyr port: - Makefile: revamp "test" target after ports were moved to ports/ - use CONFIG_NET_APP_SETTINGS to setup initial network addresses - switch to interrupt-driven pull-style console pic16bit port: - add definition of SEEK_SET to unistd.h docs: - pyboard/tutorial: add "timeout=0" to UART in pass-through example - more xrefs to "MicroPython port" in glossary - library/network: fix ref to "socket" module (should be "usocket") - machine.Signal: improve style/grammar and add usage example - library: add description of "index" parameter to uos.dupterm() - library/micropython: fix typo in RST formatting - library/framebuf.rst: generalise constructor to all colour formats - btree: describe page caching policy of the underlying implementation - esp8266/tutorial: update neopixel with example of using 4 bbp - library/network: clarify usage of "bssid" arg in connect() method - pyboard/quickref: add info for Switch, RTC, CAN, Accel classes - pyboard/tutorial: update now that yellow LED also supports PWM - esp8266/quickref: add quickref info for RTC class - library: add missing cross-ref links for classes in pyb module - library/network: update docs to state that W5500 is supported - uselect: document one-shot polling mode - usocket: elaborate descriptions - usocket: document inet_ntop(), inet_pton() - library/network: add dhcp_hostname parameter - reference/isr_rules: minor typo correction - ussl: fix module name refs and use "MicroPython port" term - esp8266/general: add section on TLS limitations - usocket: document that settimeout() isn't supported by all ports - ure: add "|" (alternative) to the list of supported operators - reference/isr_rules.rst: add tutorial on use of micropython.schedule() travis: - use --upgrade when pip is installing cpp-coveralls - update build command now that stm32 Wiznet config has changed examples: - hwconfig_console: add .on()/.off() methods all: - convert mp_uint_t to mp_unary_op_t/mp_binary_op_t where appropriate - convert remaining "mp_uint_t n_args" to "size_t n_args" - make new ports/ sub-directory and move all ports there - update Makefiles and others to build with new ports/ dir layout - remove inclusion of internal py header files - use NULL instead of "" when calling mp_raise exception helpers README: - update "Dependencies" section - add explicit section on contributing - add gcc and arm-none-eabi-newlib to list of required components .gitattributes: - remove obsolete entries for stmhal/hal, stmhal/cmsis - add entries for files that will move to ports/ dir
-rw-r--r--docs/esp8266/general.rst40
-rw-r--r--docs/esp8266/quickref.rst11
-rw-r--r--docs/library/network.rst38
-rw-r--r--docs/library/pyb.Accel.rst1
-rw-r--r--docs/library/pyb.CAN.rst1
-rw-r--r--docs/library/pyb.LCD.rst1
-rw-r--r--docs/library/pyb.Switch.rst1
-rw-r--r--docs/library/pyb.USB_HID.rst1
-rw-r--r--docs/library/pyb.USB_VCP.rst1
-rw-r--r--docs/library/ure.rst2
-rw-r--r--docs/library/uselect.rst10
-rw-r--r--docs/library/usocket.rst59
-rw-r--r--docs/library/ussl.rst14
-rw-r--r--docs/pyboard/quickref.rst54
-rw-r--r--docs/pyboard/tutorial/leds.rst8
-rw-r--r--docs/reference/isr_rules.rst2
-rw-r--r--drivers/display/ssd1306.py21
-rw-r--r--drivers/wiznet5k/ethernet/socket.c13
-rw-r--r--drivers/wiznet5k/ethernet/w5500/w5500.c10
-rw-r--r--drivers/wiznet5k/ethernet/w5500/w5500.h1
-rw-r--r--drivers/wiznet5k/ethernet/wizchip_conf.h2
-rw-r--r--examples/hwapi/hwconfig_console.py6
-rw-r--r--extmod/misc.h3
-rw-r--r--extmod/modlwip.c2
-rw-r--r--extmod/modussl_axtls.c9
-rw-r--r--extmod/modussl_mbedtls.c26
-rw-r--r--extmod/modutimeq.c2
-rw-r--r--extmod/modwebrepl.c2
-rw-r--r--extmod/uos_dupterm.c104
-rw-r--r--extmod/vfs.c7
m---------lib/axtls0
-rw-r--r--lib/libm/math.c10
-rw-r--r--ports/esp8266/esp_mphal.c37
-rw-r--r--ports/esp8266/machine_hspi.c2
-rw-r--r--ports/esp8266/machine_wdt.c2
-rw-r--r--ports/esp8266/main.c3
-rw-r--r--ports/esp8266/modnetwork.c44
-rw-r--r--ports/esp8266/modules/webrepl_setup.py9
-rw-r--r--ports/minimal/frozentest.mpybin255 -> 255 bytes
-rw-r--r--ports/stm32/Makefile6
-rw-r--r--ports/stm32/boards/stm32f767_af.csv8
-rw-r--r--ports/stm32/modnwcc3k.c2
-rw-r--r--ports/stm32/modnwwiznet5k.c48
-rw-r--r--ports/stm32/modpyb.c26
-rw-r--r--ports/stm32/moduos.c25
-rw-r--r--ports/stm32/modusocket.c55
-rw-r--r--ports/stm32/mpconfigport.h8
-rw-r--r--ports/stm32/mpconfigport.mk5
-rw-r--r--ports/stm32/mphalport.c26
-rw-r--r--ports/stm32/uart.c15
-rw-r--r--ports/stm32/uart.h1
-rw-r--r--ports/stm32/usb.c14
-rw-r--r--ports/stm32/usb.h1
-rw-r--r--ports/stm32/usbd_cdc_interface.c6
-rw-r--r--ports/stm32/usbd_cdc_interface.h4
-rw-r--r--ports/teensy/teensy_hal.c1
-rw-r--r--ports/teensy/uart.c2
-rw-r--r--ports/unix/Makefile2
-rw-r--r--ports/unix/modjni.c2
-rw-r--r--ports/unix/modusocket.c (renamed from ports/unix/modsocket.c)26
-rw-r--r--ports/unix/mpconfigport.h1
-rw-r--r--ports/unix/unix_mphal.c17
-rw-r--r--ports/zephyr/main.c5
-rw-r--r--ports/zephyr/prj_base.conf14
-rw-r--r--ports/zephyr/prj_qemu_cortex_m3.conf4
-rw-r--r--ports/zephyr/prj_qemu_x86.conf4
-rw-r--r--ports/zephyr/src/zephyr_start.c5
-rw-r--r--ports/zephyr/uart_core.c14
-rw-r--r--py/argcheck.c2
-rw-r--r--py/bc.c6
-rw-r--r--py/bc0.h4
-rw-r--r--py/emitnative.c43
-rw-r--r--py/formatfloat.c13
-rw-r--r--py/makeqstrdata.py10
-rw-r--r--py/mkenv.mk6
-rw-r--r--py/mkrules.mk6
-rw-r--r--py/modbuiltins.c25
-rw-r--r--py/modmath.c73
-rw-r--r--py/mpconfig.h22
-rw-r--r--py/mpstate.h2
-rw-r--r--py/nativeglue.c3
-rw-r--r--py/objarray.c2
-rw-r--r--py/objlist.c4
-rw-r--r--py/objtype.c98
-rw-r--r--py/persistentcode.c2
-rw-r--r--py/runtime.c7
-rw-r--r--py/runtime.h4
-rw-r--r--py/runtime0.h38
-rw-r--r--py/showbc.c4
-rw-r--r--py/vmentrytable.h4
-rw-r--r--shared-module/multiterminal/__init__.c8
-rw-r--r--tests/cmdline/cmd_showbc.py.exp14
-rw-r--r--tests/extmod/ure1.py5
-rw-r--r--tests/float/complex1.py1
-rw-r--r--tests/float/float1.py1
-rw-r--r--tests/float/math_domain.py51
-rw-r--r--tests/float/math_domain_special.py36
-rw-r--r--tests/micropython/viper_binop_divmod.py18
-rw-r--r--tests/micropython/viper_binop_divmod.py.exp28
-rw-r--r--tests/net_inet/test_tls_sites.py5
-rw-r--r--tests/net_inet/test_tls_sites.py.exp1
-rwxr-xr-xtests/run-tests9
-rw-r--r--tests/unix/extra_coverage.py.exp4
-rwxr-xr-xtools/mpy-tool.py8
-rwxr-xr-xtools/pyboard.py9
105 files changed, 1006 insertions, 476 deletions
diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst
index e23acb469..96a454532 100644
--- a/docs/esp8266/general.rst
+++ b/docs/esp8266/general.rst
@@ -145,3 +145,43 @@ or by an exeption, for example using try/finally::
# Use sock
finally:
sock.close()
+
+
+SSL/TLS limitations
+~~~~~~~~~~~~~~~~~~~
+
+ESP8266 uses `axTLS <http://axtls.sourceforge.net/>`_ library, which is one
+of the smallest TLS libraries with the compatible licensing. However, it
+also has some known issues/limitations:
+
+1. No support for Diffie-Hellman (DH) key exchange and Elliptic-curve
+ cryptography (ECC). This means it can't work with sites which force
+ the use of these features (it works ok with classic RSA certifactes).
+2. Half-duplex communication nature. axTLS uses a single buffer for both
+ sending and receiving, which leads to considerable memory saving and
+ works well with protocols like HTTP. But there may be problems with
+ protocols which don't follow classic request-response model.
+
+Besides axTLS own limitations, the configuration used for MicroPython is
+highly optimized for code size, which leads to additional limitations
+(these may be lifted in the future):
+
+3. Optimized RSA algorithms are not enabled, which may lead to slow
+ SSL handshakes.
+4. Stored sessions are not supported (may allow faster repeated connections
+ to the same site in some circumstances).
+
+Besides axTLS specific limitations described above, there's another generic
+limitation with usage of TLS on the low-memory devices:
+
+5. The TLS standard specifies the maximum length of the TLS record (unit
+ of TLS communication, the entire record must be buffered before it can
+ be processed) as 16KB. That's almost half of the available ESP8266 memory,
+ and inside a more or less advanced application would be hard to allocate
+ due to memory fragmentation issues. As a compromise, a smaller buffer is
+ used, with the idea that the most interesting usage for SSL would be
+ accessing various REST APIs, which usually require much smaller messages.
+ The buffers size is on the order of 5KB, and is adjusted from time to
+ time, taking as a reference being able to access https://google.com .
+ The smaller buffer hower means that some sites can't be accessed using
+ it, and it's not possible to stream large amounts of data.
diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst
index ccf6365c8..c510e4064 100644
--- a/docs/esp8266/quickref.rst
+++ b/docs/esp8266/quickref.rst
@@ -223,6 +223,17 @@ and is accessed via the :ref:`machine.I2C <machine.I2C>` class::
buf = bytearray(10) # create a buffer with 10 bytes
i2c.writeto(0x3a, buf) # write the given buffer to the slave
+Real time clock (RTC)
+---------------------
+
+See :ref:`machine.RTC <machine.RTC>` ::
+
+ from machine import RTC
+
+ rtc = RTC()
+ rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime() # get date and time
+
Deep-sleep mode
---------------
diff --git a/docs/library/network.rst b/docs/library/network.rst
index def6bee74..99a7c242c 100644
--- a/docs/library/network.rst
+++ b/docs/library/network.rst
@@ -72,8 +72,7 @@ parameter should be `id`.
connection parameters. For various medium types, there are different
sets of predefined/recommended parameters, among them:
- * WiFi: *bssid* keyword to connect by BSSID (MAC address) instead
- of access point name
+ * WiFi: *bssid* keyword to connect to a specific BSSID (MAC address)
.. method:: disconnect()
@@ -225,7 +224,9 @@ parameter should be `id`.
==============
This class allows you to control WIZnet5x00 Ethernet adaptors based on
- the W5200 and W5500 chipsets (only W5200 tested).
+ the W5200 and W5500 chipsets. The particular chipset that is supported
+ by the firmware is selected at compile-time via the MICROPY_PY_WIZNET5K
+ option.
Example usage::
@@ -269,6 +270,11 @@ parameter should be `id`.
Methods
-------
+ .. method:: wiznet5k.isconnected()
+
+ Returns ``True`` if the physical Ethernet link is connected and up.
+ Returns ``False`` otherwise.
+
.. method:: wiznet5k.ifconfig([(ip, subnet, gateway, dns)])
Get/set IP address, subnet mask, gateway and DNS.
@@ -333,9 +339,12 @@ parameter should be `id`.
argument is passed. Otherwise, query current state if no argument is
provided. Most other methods require active interface.
- .. method:: wlan.connect(ssid, password)
+ .. method:: wlan.connect(ssid=None, password=None, \*, bssid=None)
Connect to the specified wireless network, using the specified password.
+ If *bssid* is given then the connection will be restricted to the
+ access-point with that MAC address (the *ssid* must also be specified
+ in this case).
.. method:: wlan.disconnect()
@@ -413,16 +422,17 @@ parameter should be `id`.
Following are commonly supported parameters (availability of a specific parameter
depends on network technology type, driver, and `MicroPython port`).
- ========= ===========
- Parameter Description
- ========= ===========
- mac MAC address (bytes)
- essid WiFi access point name (string)
- channel WiFi channel (integer)
- hidden Whether ESSID is hidden (boolean)
- authmode Authentication mode supported (enumeration, see module constants)
- password Access password (string)
- ========= ===========
+ ============= ===========
+ Parameter Description
+ ============= ===========
+ mac MAC address (bytes)
+ essid WiFi access point name (string)
+ channel WiFi channel (integer)
+ hidden Whether ESSID is hidden (boolean)
+ authmode Authentication mode supported (enumeration, see module constants)
+ password Access password (string)
+ dhcp_hostname The DHCP hostname to use
+ ============= ===========
diff --git a/docs/library/pyb.Accel.rst b/docs/library/pyb.Accel.rst
index 061996485..9ade5c5c8 100644
--- a/docs/library/pyb.Accel.rst
+++ b/docs/library/pyb.Accel.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.Accel:
class Accel -- accelerometer control
====================================
diff --git a/docs/library/pyb.CAN.rst b/docs/library/pyb.CAN.rst
index 9e71f12b0..232d04d96 100644
--- a/docs/library/pyb.CAN.rst
+++ b/docs/library/pyb.CAN.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.CAN:
class CAN -- controller area network communication bus
======================================================
diff --git a/docs/library/pyb.LCD.rst b/docs/library/pyb.LCD.rst
index 83cf890b6..5ab127edc 100644
--- a/docs/library/pyb.LCD.rst
+++ b/docs/library/pyb.LCD.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.LCD:
class LCD -- LCD control for the LCD touch-sensor pyskin
========================================================
diff --git a/docs/library/pyb.Switch.rst b/docs/library/pyb.Switch.rst
index 0d5dc63b7..e5ab6bd84 100644
--- a/docs/library/pyb.Switch.rst
+++ b/docs/library/pyb.Switch.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.Switch:
class Switch -- switch object
=============================
diff --git a/docs/library/pyb.USB_HID.rst b/docs/library/pyb.USB_HID.rst
index 7d17c3099..702704435 100644
--- a/docs/library/pyb.USB_HID.rst
+++ b/docs/library/pyb.USB_HID.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.USB_HID:
class USB_HID -- USB Human Interface Device (HID)
=================================================
diff --git a/docs/library/pyb.USB_VCP.rst b/docs/library/pyb.USB_VCP.rst
index 4c4fe4516..80cc40cdd 100644
--- a/docs/library/pyb.USB_VCP.rst
+++ b/docs/library/pyb.USB_VCP.rst
@@ -1,4 +1,5 @@
.. currentmodule:: pyb
+.. _pyb.USB_VCP:
class USB_VCP -- USB virtual comm port
======================================
diff --git a/docs/library/ure.rst b/docs/library/ure.rst
index 67f4f54a1..ebae1db5f 100644
--- a/docs/library/ure.rst
+++ b/docs/library/ure.rst
@@ -34,6 +34,8 @@ Supported operators are:
``'+?'``
+``'|'``
+
``'()'``
Grouping. Each group is capturing (a substring it captures can be accessed
with `match.group()` method).
diff --git a/docs/library/uselect.rst b/docs/library/uselect.rst
index e330207db..beffce69a 100644
--- a/docs/library/uselect.rst
+++ b/docs/library/uselect.rst
@@ -66,12 +66,18 @@ Methods
Tuples returned may contain more than 2 elements as described above.
-.. method:: poll.ipoll([timeout])
+.. method:: poll.ipoll(timeout=-1, flags=0)
Like :meth:`poll.poll`, but instead returns an iterator which yields
- callee-owned tuples. This function provides efficient, allocation-free
+ `callee-owned tuples`. This function provides efficient, allocation-free
way to poll on streams.
+ If *flags* is 1, one-shot behavior for events is employed: streams for
+ which events happened, event mask will be automatically reset (equivalent
+ to ``poll.modify(obj, 0)``), so new events for such a stream won't be
+ processed until new mask is set with `poll.modify()`. This behavior is
+ useful for asynchronous I/O schedulers.
+
.. admonition:: Difference to CPython
:class: attention
diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst
index dfdcd68bc..fab05b652 100644
--- a/docs/library/usocket.rst
+++ b/docs/library/usocket.rst
@@ -68,7 +68,16 @@ Functions
.. function:: socket(af=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP)
- Create a new socket using the given address family, socket type and protocol number.
+ Create a new socket using the given address family, socket type and
+ protocol number. Note that specifying *proto* in most cases is not
+ required (and not recommended, as some MicroPython ports may omit
+ ``IPPROTO_*`` constants). Instead, *type* argument will select needed
+ protocol automatically::
+
+ # Create STREAM TCP socket
+ socket(AF_INET, SOCK_STREAM)
+ # Create DGRAM UDP socket
+ socket(AF_INET, SOCK_DGRAM)
.. function:: getaddrinfo(host, port)
@@ -80,8 +89,8 @@ Functions
The following example shows how to connect to a given url::
- s = socket.socket()
- s.connect(socket.getaddrinfo('www.micropython.org', 80)[0][-1])
+ s = usocket.socket()
+ s.connect(usocket.getaddrinfo('www.micropython.org', 80)[0][-1])
.. admonition:: Difference to CPython
:class: attention
@@ -96,13 +105,29 @@ Functions
from an exception object). The use of negative values is a provisional
detail which may change in the future.
+.. function:: inet_ntop(af, bin_addr)
+
+ Convert a binary network address *bin_addr* of the given address family *af*
+ to a textual representation::
+
+ >>> usocket.inet_ntop(usocket.AF_INET, b"\x7f\0\0\1")
+ '127.0.0.1'
+
+.. function:: inet_pton(af, txt_addr)
+
+ Convert a textual network address *txt_addr* of the given address family *af*
+ to a binary representation::
+
+ >>> usocket.inet_pton(usocket.AF_INET, "1.2.3.4")
+ b'\x01\x02\x03\x04'
+
Constants
---------
.. data:: AF_INET
AF_INET6
- Address family types. Availability depends on a particular board.
+ Address family types. Availability depends on a particular `MicroPython port`.
.. data:: SOCK_STREAM
SOCK_DGRAM
@@ -112,7 +137,11 @@ Constants
.. data:: IPPROTO_UDP
IPPROTO_TCP
- IP protocol numbers.
+ IP protocol numbers. Availability depends on a particular `MicroPython port`.
+ Note that you don't need to specify these in a call to `usocket.socket()`,
+ because `SOCK_STREAM` socket type automatically selects `IPPROTO_TCP`, and
+ `SOCK_DGRAM` - `IPPROTO_UDP`. Thus, the only real use of these constants
+ is as an argument to `setsockopt()`.
.. data:: usocket.SOL_*
@@ -208,12 +237,30 @@ Methods
.. method:: socket.settimeout(value)
+ **Note**: Not every port supports this method, see below.
+
Set a timeout on blocking socket operations. The value argument can be a nonnegative floating
point number expressing seconds, or None. If a non-zero value is given, subsequent socket operations
will raise an `OSError` exception if the timeout period value has elapsed before the operation has
completed. If zero is given, the socket is put in non-blocking mode. If None is given, the socket
is put in blocking mode.
+ Not every `MicroPython port` supports this method. A more portable and
+ generic solution is to use `uselect.poll` object. This allows to wait on
+ multiple objects at the same time (and not just on sockets, but on generic
+ stream objects which support polling). Example::
+
+ # Instead of:
+ s.settimeout(1.0) # time in seconds
+ s.read(10) # may timeout
+
+ # Use:
+ poller = uselect.poll()
+ poller.register(s, uselect.POLLIN)
+ res = poller.poll(1000) # time in milliseconds
+ if not res:
+ # s is still not ready for input, i.e. operation timed out
+
.. admonition:: Difference to CPython
:class: attention
@@ -281,7 +328,7 @@ Methods
Return value: number of bytes written.
-.. exception:: socket.error
+.. exception:: usocket.error
MicroPython does NOT have this exception.
diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst
index c71b283cc..3ec609f67 100644
--- a/docs/library/ussl.rst
+++ b/docs/library/ussl.rst
@@ -13,7 +13,7 @@ facilities for network sockets, both client-side and server-side.
Functions
---------
-.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
+.. function:: ussl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
Takes a stream *sock* (usually usocket.socket instance of ``SOCK_STREAM`` type),
and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
@@ -23,12 +23,12 @@ Functions
server-side SSL socket should be created from a normal socket returned from
`accept()` on a non-SSL listening server socket.
- Depending on the underlying module implementation for a particular board,
- some or all keyword arguments above may be not supported.
+ Depending on the underlying module implementation in a particular
+ `MicroPython port`, some or all keyword arguments above may be not supported.
.. warning::
- Some implementations of ``ssl`` module do NOT validate server certificates,
+ Some implementations of ``ussl`` module do NOT validate server certificates,
which makes an SSL connection established prone to man-in-the-middle attacks.
Exceptions
@@ -41,8 +41,8 @@ Exceptions
Constants
---------
-.. data:: ssl.CERT_NONE
- ssl.CERT_OPTIONAL
- ssl.CERT_REQUIRED
+.. data:: ussl.CERT_NONE
+ ussl.CERT_OPTIONAL
+ ussl.CERT_REQUIRED
Supported values for *cert_reqs* parameter.
diff --git a/docs/pyboard/quickref.rst b/docs/pyboard/quickref.rst
index 5690dddb0..48798aad3 100644
--- a/docs/pyboard/quickref.rst
+++ b/docs/pyboard/quickref.rst
@@ -39,17 +39,32 @@ Use the :mod:`time <utime>` module::
start = time.ticks_ms() # get value of millisecond counter
delta = time.ticks_diff(time.ticks_ms(), start) # compute time difference
-LEDs
-----
+Internal LEDs
+-------------
See :ref:`pyb.LED <pyb.LED>`. ::
from pyb import LED
- led = LED(1) # red led
+ led = LED(1) # 1=red, 2=green, 3=yellow, 4=blue
led.toggle()
led.on()
led.off()
+
+ # LEDs 3 and 4 support PWM intensity (0-255)
+ LED(4).intensity() # get intensity
+ LED(4).intensity(128) # set intensity to half
+
+Internal switch
+---------------
+
+See :ref:`pyb.Switch <pyb.Switch>`. ::
+
+ from pyb import Switch
+
+ sw = Switch()
+ sw.value() # returns True or False
+ sw.callback(lambda: pyb.LED(1).toggle())
Pins and GPIO
-------------
@@ -99,6 +114,17 @@ See :ref:`pyb.Timer <pyb.Timer>`. ::
tim.freq(0.5) # 0.5 Hz
tim.callback(lambda t: pyb.LED(1).toggle())
+RTC (real time clock)
+---------------------
+
+See :ref:`pyb.RTC <pyb.RTC>` ::
+
+ from pyb import RTC
+
+ rtc = RTC()
+ rtc.datetime((2017, 8, 23, 1, 12, 48, 0, 0)) # set a specific date and time
+ rtc.datetime() # get date and time
+
PWM (pulse width modulation)
----------------------------
@@ -167,3 +193,25 @@ See :ref:`pyb.I2C <pyb.I2C>`. ::
i2c.recv(5, 0x42) # receive 5 bytes from slave
i2c.mem_read(2, 0x42, 0x10) # read 2 bytes from slave 0x42, slave memory 0x10
i2c.mem_write('xy', 0x42, 0x10) # write 2 bytes to slave 0x42, slave memory 0x10
+
+CAN bus (controller area network)
+---------------------------------
+
+See :ref:`pyb.CAN <pyb.CAN>`. ::
+
+ from pyb import CAN
+
+ can = CAN(1, CAN.LOOPBACK)
+ can.setfilter(0, CAN.LIST16, 0, (123, 124, 125, 126))
+ can.send('message!', 123) # send a message with id 123
+ can.recv(0) # receive message on FIFO 0
+
+Internal accelerometer
+----------------------
+
+See :ref:`pyb.Accel <pyb.Accel>`. ::
+
+ from pyb import Accel
+
+ accel = Accel()
+ print(accel.x(), accel.y(), accel.z(), accel.tilt())
diff --git a/docs/pyboard/tutorial/leds.rst b/docs/pyboard/tutorial/leds.rst
index 763eedf01..6b05f5db0 100644
--- a/docs/pyboard/tutorial/leds.rst
+++ b/docs/pyboard/tutorial/leds.rst
@@ -60,10 +60,10 @@ One problem you might find is that if you stop the script and then start it agai
for l in leds:
l.off()
-The Fourth Special LED
-----------------------
+The Special LEDs
+----------------
-The blue LED is special. As well as turning it on and off, you can control the intensity using the intensity() method. This takes a number between 0 and 255 that determines how bright it is. The following script makes the blue LED gradually brighter then turns it off again. ::
+The yellow and blue LEDs are special. As well as turning them on and off, you can control their intensity using the intensity() method. This takes a number between 0 and 255 that determines how bright it is. The following script makes the blue LED gradually brighter then turns it off again. ::
led = pyb.LED(4)
intensity = 0
@@ -72,4 +72,4 @@ The blue LED is special. As well as turning it on and off, you can control the i
led.intensity(intensity)
pyb.delay(20)
-You can call intensity() on the other LEDs but they can only be off or on. 0 sets them off and any other number up to 255 turns them on.
+You can call intensity() on LEDs 1 and 2 but they can only be off or on. 0 sets them off and any other number up to 255 turns them on.
diff --git a/docs/reference/isr_rules.rst b/docs/reference/isr_rules.rst
index 5009f30f7..2db261c09 100644
--- a/docs/reference/isr_rules.rst
+++ b/docs/reference/isr_rules.rst
@@ -80,7 +80,7 @@ example causes two LED's to flash at different rates.
self.led.toggle()
red = Foo(pyb.Timer(4, freq=1), pyb.LED(1))
- greeen = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2))
+ green = Foo(pyb.Timer(2, freq=0.8), pyb.LED(2))
In this example the ``red`` instance associates timer 4 with LED 1: when a timer 4 interrupt occurs ``red.cb()``
is called causing LED 1 to change state. The ``green`` instance operates similarly: a timer 2 interrupt
diff --git a/drivers/display/ssd1306.py b/drivers/display/ssd1306.py
index d65f2d350..cd358d00e 100644
--- a/drivers/display/ssd1306.py
+++ b/drivers/display/ssd1306.py
@@ -1,7 +1,6 @@
# MicroPython SSD1306 OLED driver, I2C and SPI interfaces
from micropython import const
-import time
import framebuf
@@ -47,7 +46,6 @@ class SSD1306:
self.text = fb.text
self.scroll = fb.scroll
self.blit = fb.blit
- self.poweron()
self.init_display()
def init_display(self):
@@ -80,6 +78,9 @@ class SSD1306:
def poweroff(self):
self.write_cmd(SET_DISP | 0x00)
+ def poweron(self):
+ self.write_cmd(SET_DISP | 0x01)
+
def contrast(self, contrast):
self.write_cmd(SET_CONTRAST)
self.write_cmd(contrast)
@@ -123,9 +124,6 @@ class SSD1306_I2C(SSD1306):
self.i2c.write(buf)
self.i2c.stop()
- def poweron(self):
- pass
-
class SSD1306_SPI(SSD1306):
def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):
@@ -137,6 +135,12 @@ class SSD1306_SPI(SSD1306):
self.dc = dc
self.res = res
self.cs = cs
+ import time
+ self.res(1)
+ time.sleep_ms(1)
+ self.res(0)
+ time.sleep_ms(10)
+ self.res(1)
super().__init__(width, height, external_vcc)
def write_cmd(self, cmd):
@@ -154,10 +158,3 @@ class SSD1306_SPI(SSD1306):
self.cs(0)
self.spi.write(buf)
self.cs(1)
-
- def poweron(self):
- self.res(1)
- time.sleep_ms(1)
- self.res(0)
- time.sleep_ms(10)
- self.res(1)
diff --git a/drivers/wiznet5k/ethernet/socket.c b/drivers/wiznet5k/ethernet/socket.c
index 129473ad4..ec25fcc79 100644
--- a/drivers/wiznet5k/ethernet/socket.c
+++ b/drivers/wiznet5k/ethernet/socket.c
@@ -52,10 +52,9 @@
#include <string.h>
+#include "py/mpthread.h"
#include "socket.h"
-extern void HAL_Delay(uint32_t);
-
#define SOCK_ANY_PORT_NUM 0xC000;
static uint16_t sock_any_port = SOCK_ANY_PORT_NUM;
@@ -242,7 +241,7 @@ int8_t WIZCHIP_EXPORT(connect)(uint8_t sn, uint8_t * addr, uint16_t port)
#endif
return SOCKERR_TIMEOUT;
}
- HAL_Delay(1);
+ MICROPY_THREAD_YIELD();
}
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
@@ -317,6 +316,7 @@ int32_t WIZCHIP_EXPORT(send)(uint8_t sn, uint8_t * buf, uint16_t len)
}
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
if(len <= freesize) break;
+ MICROPY_THREAD_YIELD();
}
wiz_send_data(sn, buf, len);
#if _WIZCHIP_ == 5200
@@ -368,7 +368,7 @@ int32_t WIZCHIP_EXPORT(recv)(uint8_t sn, uint8_t * buf, uint16_t len)
}
if((sock_io_mode & (1<<sn)) && (recvsize == 0)) return SOCK_BUSY;
if(recvsize != 0) break;
- HAL_Delay(1);
+ MICROPY_THREAD_YIELD();
};
if(recvsize < len) len = recvsize;
wiz_recv_data(sn, buf, len);
@@ -416,7 +416,7 @@ int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if( (sock_io_mode & (1<<sn)) && (len > freesize) ) return SOCK_BUSY;
if(len <= freesize) break;
- HAL_Delay(1);
+ MICROPY_THREAD_YIELD();
};
wiz_send_data(sn, buf, len);
@@ -446,7 +446,7 @@ int32_t WIZCHIP_EXPORT(sendto)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_t
return SOCKERR_TIMEOUT;
}
////////////
- HAL_Delay(1);
+ MICROPY_THREAD_YIELD();
}
#if _WIZCHIP_ == 5200 // for W5200 ARP errata
setSUBR((uint8_t*)"\x00\x00\x00\x00");
@@ -486,6 +486,7 @@ int32_t WIZCHIP_EXPORT(recvfrom)(uint8_t sn, uint8_t * buf, uint16_t len, uint8_
if(getSn_SR(sn) == SOCK_CLOSED) return SOCKERR_SOCKCLOSED;
if( (sock_io_mode & (1<<sn)) && (pack_len == 0) ) return SOCK_BUSY;
if(pack_len != 0) break;
+ MICROPY_THREAD_YIELD();
};
}
sock_pack_info[sn] = PACK_COMPLETED;
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.c b/drivers/wiznet5k/ethernet/w5500/w5500.c
index 6b3111f99..3107b1b71 100644
--- a/drivers/wiznet5k/ethernet/w5500/w5500.c
+++ b/drivers/wiznet5k/ethernet/w5500/w5500.c
@@ -57,6 +57,16 @@
////////////////////////////////////////////////////
+#define LPC_SSP0 (0)
+
+static void Chip_SSP_ReadFrames_Blocking(int dummy, uint8_t *buf, uint32_t len) {
+ WIZCHIP.IF.SPI._read_bytes(buf, len);
+}
+
+static void Chip_SSP_WriteFrames_Blocking(int dummy, const uint8_t *buf, uint32_t len) {
+ WIZCHIP.IF.SPI._write_bytes(buf, len);
+}
+
uint8_t WIZCHIP_READ(uint32_t AddrSel)
{
uint8_t ret;
diff --git a/drivers/wiznet5k/ethernet/w5500/w5500.h b/drivers/wiznet5k/ethernet/w5500/w5500.h
index f0ffcb0c8..c2afb180e 100644
--- a/drivers/wiznet5k/ethernet/w5500/w5500.h
+++ b/drivers/wiznet5k/ethernet/w5500/w5500.h
@@ -44,7 +44,6 @@
#include <stdint.h>
#include "../wizchip_conf.h"
-#include "board.h"
#define _W5500_IO_BASE_ 0x00000000
diff --git a/drivers/wiznet5k/ethernet/wizchip_conf.h b/drivers/wiznet5k/ethernet/wizchip_conf.h
index 55c79ae0a..4a7a7bd69 100644
--- a/drivers/wiznet5k/ethernet/wizchip_conf.h
+++ b/drivers/wiznet5k/ethernet/wizchip_conf.h
@@ -56,7 +56,9 @@
* @todo You should select one, \b 5100, \b 5200 ,\b 5500 or etc. \n\n
* ex> <code> #define \_WIZCHIP_ 5500 </code>
*/
+#ifndef _WIZCHIP_
#define _WIZCHIP_ 5200 // 5100, 5200, 5500
+#endif
#define _WIZCHIP_IO_MODE_NONE_ 0x0000
#define _WIZCHIP_IO_MODE_BUS_ 0x0100 /**< Bus interface mode */
diff --git a/examples/hwapi/hwconfig_console.py b/examples/hwapi/hwconfig_console.py
index 4b0b0d79b..bbcc0e816 100644
--- a/examples/hwapi/hwconfig_console.py
+++ b/examples/hwapi/hwconfig_console.py
@@ -8,6 +8,12 @@ class LEDClass:
def value(self, v):
print(self.id, v)
+ def on(self):
+ self.value(1)
+
+ def off(self):
+ self.value(0)
+
LED = LEDClass(1)
LED2 = LEDClass(12)
diff --git a/extmod/misc.h b/extmod/misc.h
index 6c13592c7..d6f6d859c 100644
--- a/extmod/misc.h
+++ b/extmod/misc.h
@@ -35,8 +35,9 @@
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj);
#if MICROPY_PY_OS_DUPTERM
+int mp_uos_dupterm_rx_chr(void);
void mp_uos_dupterm_tx_strn(const char *str, size_t len);
-void mp_uos_deactivate(const char *msg, mp_obj_t exc);
+void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc);
#else
#define mp_uos_dupterm_tx_strn(s, l)
#endif
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index f7e776af9..bbb01b5d7 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -1032,7 +1032,7 @@ STATIC mp_obj_t lwip_socket_sendall(mp_obj_t self_in, mp_obj_t buf_in) {
break;
}
case MOD_NETWORK_SOCK_DGRAM:
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
break;
}
diff --git a/extmod/modussl_axtls.c b/extmod/modussl_axtls.c
index 88a89a23d..3ad65ebf3 100644
--- a/extmod/modussl_axtls.c
+++ b/extmod/modussl_axtls.c
@@ -51,7 +51,11 @@ struct ssl_args {
STATIC const mp_obj_type_t ussl_socket_type;
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
+#if MICROPY_PY_USSL_FINALISER
+ mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
+#else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
+#endif
o->base.type = &ussl_socket_type;
o->buf = NULL;
o->bytes_left = 0;
@@ -152,7 +156,7 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) {
// Currently supports only blocking mode
(void)self_in;
if (!mp_obj_is_true(flag_in)) {
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
}
return mp_const_none;
}
@@ -178,6 +182,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
+#if MICROPY_PY_USSL_FINALISER
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socket_close_obj) },
+#endif
};
STATIC MP_DEFINE_CONST_DICT(ussl_socket_locals_dict, ussl_socket_locals_dict_table);
diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c
index d7316cb4a..69a64d2f7 100644
--- a/extmod/modussl_mbedtls.c
+++ b/extmod/modussl_mbedtls.c
@@ -65,23 +65,30 @@ struct ssl_args {
STATIC const mp_obj_type_t ussl_socket_type;
-void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
+#ifdef MBEDTLS_DEBUG_C
+STATIC void mbedtls_debug(void *ctx, int level, const char *file, int line, const char *str) {
+ (void)ctx;
+ (void)level;
printf("DBG:%s:%04d: %s\n", file, line, str);
}
+#endif
// TODO: FIXME!
-int null_entropy_func(void *data, unsigned char *output, size_t len) {
+STATIC int null_entropy_func(void *data, unsigned char *output, size_t len) {
+ (void)data;
+ (void)output;
+ (void)len;
// enjoy random bytes
return 0;
}
-int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
+STATIC int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t*)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_WRITE);
int err;
- int out_sz = sock_stream->write(sock, buf, len, &err);
+ mp_uint_t out_sz = sock_stream->write(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_WRITE;
@@ -92,13 +99,13 @@ int _mbedtls_ssl_send(void *ctx, const byte *buf, size_t len) {
}
}
-int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
+STATIC int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
mp_obj_t sock = *(mp_obj_t*)ctx;
const mp_stream_p_t *sock_stream = mp_get_stream_raise(sock, MP_STREAM_OP_READ);
int err;
- int out_sz = sock_stream->read(sock, buf, len, &err);
+ mp_uint_t out_sz = sock_stream->read(sock, buf, len, &err);
if (out_sz == MP_STREAM_ERROR) {
if (mp_is_nonblocking_error(err)) {
return MBEDTLS_ERR_SSL_WANT_READ;
@@ -111,7 +118,11 @@ int _mbedtls_ssl_recv(void *ctx, byte *buf, size_t len) {
STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
+#if MICROPY_PY_USSL_FINALISER
+ mp_obj_ssl_socket_t *o = m_new_obj_with_finaliser(mp_obj_ssl_socket_t);
+#else
mp_obj_ssl_socket_t *o = m_new_obj(mp_obj_ssl_socket_t);
+#endif
o->base.type = &ussl_socket_type;
int ret;
@@ -272,6 +283,9 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
{ MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
{ MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
+#if MICROPY_PY_USSL_FINALISER
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socket_close_obj) },
+#endif
{ MP_ROM_QSTR(MP_QSTR_getpeercert), MP_ROM_PTR(&mod_ssl_getpeercert_obj) },
};
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
index 0a836c7cc..28bbcc521 100644
--- a/extmod/modutimeq.c
+++ b/extmod/modutimeq.c
@@ -146,7 +146,7 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
}
mp_obj_list_t *ret = MP_OBJ_TO_PTR(list_ref);
if (!MP_OBJ_IS_TYPE(list_ref, &mp_type_list) || ret->len < 3) {
- mp_raise_TypeError("");
+ mp_raise_TypeError(NULL);
}
struct qentry *item = &heap->items[0];
diff --git a/extmod/modwebrepl.c b/extmod/modwebrepl.c
index c5087ac29..38b88821b 100644
--- a/extmod/modwebrepl.c
+++ b/extmod/modwebrepl.c
@@ -308,7 +308,7 @@ STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
size_t len;
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
if (len > sizeof(webrepl_passwd) - 1) {
- mp_raise_ValueError("");
+ mp_raise_ValueError(NULL);
}
strcpy(webrepl_passwd, passwd);
return mp_const_none;
diff --git a/extmod/uos_dupterm.c b/extmod/uos_dupterm.c
index 54fb23a79..e5e6663b0 100644
--- a/extmod/uos_dupterm.c
+++ b/extmod/uos_dupterm.c
@@ -4,6 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2016 Paul Sokolovsky
+ * 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
@@ -31,61 +32,114 @@
#include "py/objtuple.h"
#include "py/objarray.h"
#include "py/stream.h"
+#include "lib/utils/interrupt_char.h"
#ifdef MICROPY_PY_OS_DUPTERM
-void mp_uos_deactivate(const char *msg, mp_obj_t exc) {
- mp_obj_t term = MP_STATE_PORT(term_obj);
- MP_STATE_PORT(term_obj) = NULL;
+void mp_uos_deactivate(size_t dupterm_idx, const char *msg, mp_obj_t exc) {
+ mp_obj_t term = MP_STATE_VM(dupterm_objs[dupterm_idx]);
+ MP_STATE_VM(dupterm_objs[dupterm_idx]) = MP_OBJ_NULL;
mp_printf(&mp_plat_print, msg);
if (exc != MP_OBJ_NULL) {
mp_obj_print_exception(&mp_plat_print, exc);
}
- mp_stream_close(term);
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_stream_close(term);
+ nlr_pop();
+ } else {
+ // Ignore any errors during stream closing
+ }
+}
+
+int mp_uos_dupterm_rx_chr(void) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
+
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ mp_obj_t readinto_m[3];
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_readinto, readinto_m);
+ readinto_m[2] = MP_STATE_VM(dupterm_arr_obj);
+ mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
+ if (res == mp_const_none) {
+ nlr_pop();
+ } else if (res == MP_OBJ_NEW_SMALL_INT(0)) {
+ nlr_pop();
+ mp_uos_deactivate(idx, "dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
+ } else {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(MP_STATE_VM(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
+ nlr_pop();
+ if (*(byte*)bufinfo.buf == mp_interrupt_char) {
+ // Signal keyboard interrupt to be raised as soon as the VM resumes
+ mp_keyboard_interrupt();
+ return -2;
+ }
+ return *(byte*)bufinfo.buf;
+ }
+ } else {
+ mp_uos_deactivate(idx, "dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
+ }
+ }
+
+ // No chars available
+ return -1;
}
void mp_uos_dupterm_tx_strn(const char *str, size_t len) {
- if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
+ for (size_t idx = 0; idx < MICROPY_PY_OS_DUPTERM; ++idx) {
+ if (MP_STATE_VM(dupterm_objs[idx]) == MP_OBJ_NULL) {
+ continue;
+ }
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t write_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_write, write_m);
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_write, write_m);
- mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
+ mp_obj_array_t *arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
void *org_items = arr->items;
arr->items = (void*)str;
arr->len = len;
- write_m[2] = MP_STATE_PORT(dupterm_arr_obj);
+ write_m[2] = MP_STATE_VM(dupterm_arr_obj);
mp_call_method_n_kw(1, 0, write_m);
- arr = MP_OBJ_TO_PTR(MP_STATE_PORT(dupterm_arr_obj));
+ arr = MP_OBJ_TO_PTR(MP_STATE_VM(dupterm_arr_obj));
arr->items = org_items;
arr->len = 1;
nlr_pop();
} else {
- mp_uos_deactivate("dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
+ mp_uos_deactivate(idx, "dupterm: Exception in write() method, deactivating: ", nlr.ret_val);
}
}
}
STATIC mp_obj_t mp_uos_dupterm(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) {
- return mp_const_none;
- } else {
- return MP_STATE_PORT(term_obj);
- }
+ mp_int_t idx = 0;
+ if (n_args == 2) {
+ idx = mp_obj_get_int(args[1]);
+ }
+
+ if (idx < 0 || idx >= MICROPY_PY_OS_DUPTERM) {
+ mp_raise_ValueError("invalid dupterm index");
+ }
+
+ mp_obj_t previous_obj = MP_STATE_VM(dupterm_objs[idx]);
+ if (previous_obj == MP_OBJ_NULL) {
+ previous_obj = mp_const_none;
+ }
+ if (args[0] == mp_const_none) {
+ MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
} else {
- if (args[0] == mp_const_none) {
- MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
- } else {
- MP_STATE_PORT(term_obj) = args[0];
- if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
- MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
- }
+ MP_STATE_VM(dupterm_objs[idx]) = args[0];
+ if (MP_STATE_VM(dupterm_arr_obj) == MP_OBJ_NULL) {
+ MP_STATE_VM(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
- return mp_const_none;
}
+
+ return previous_obj;
}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 0, 1, mp_uos_dupterm);
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_uos_dupterm_obj, 1, 2, mp_uos_dupterm);
#endif
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 586bb4b01..e83646d8d 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -38,6 +38,10 @@
#include "extmod/vfs_fat.h"
#endif
+// For mp_vfs_proxy_call, the maximum number of additional args that can be passed.
+// A fixed maximum size is used to avoid the need for a costly variable array.
+#define PROXY_MAX_ARGS (2)
+
// path is the path to lookup and *path_out holds the path within the VFS
// object (starts with / if an absolute path).
// Returns MP_VFS_ROOT for root dir (and then path_out is undefined) and
@@ -97,6 +101,7 @@ STATIC mp_vfs_mount_t *lookup_path(mp_obj_t path_in, mp_obj_t *path_out) {
}
STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_args, const mp_obj_t *args) {
+ assert(n_args <= PROXY_MAX_ARGS);
if (vfs == MP_VFS_NONE) {
// mount point not found
mp_raise_OSError(MP_ENODEV);
@@ -105,7 +110,7 @@ STATIC mp_obj_t mp_vfs_proxy_call(mp_vfs_mount_t *vfs, qstr meth_name, size_t n_
// can't do operation on root dir
mp_raise_OSError(MP_EPERM);
}
- mp_obj_t meth[n_args + 2];
+ mp_obj_t meth[2 + PROXY_MAX_ARGS];
mp_load_method(vfs->obj, meth_name, meth);
if (args != NULL) {
memcpy(meth + 2, args, n_args * sizeof(*args));
diff --git a/lib/axtls b/lib/axtls
-Subproject 9b3092eb3b4b230a63c0c389bfbd3c55682c620
+Subproject dac9176cac58cc5e49669a9a4d404a6f6dd7cc1
diff --git a/lib/libm/math.c b/lib/libm/math.c
index 327a149b1..39c6a68a5 100644
--- a/lib/libm/math.c
+++ b/lib/libm/math.c
@@ -48,16 +48,6 @@ float copysignf(float x, float y) {
}
#endif
-// some compilers define log2f in terms of logf
-#ifdef log2f
-#undef log2f
-#endif
-// some compilers have _M_LN2 defined in math.h, some don't
-#ifndef _M_LN2
-#define _M_LN2 (0.69314718055994530942)
-#endif
-float log2f(float x) { return logf(x) / (float)_M_LN2; }
-
static const float _M_LN10 = 2.30258509299404; // 0x40135d8e
float log10f(float x) { return logf(x) / (float)_M_LN10; }
diff --git a/ports/esp8266/esp_mphal.c b/ports/esp8266/esp_mphal.c
index 4f3ca5836..93ebc450a 100644
--- a/ports/esp8266/esp_mphal.c
+++ b/ports/esp8266/esp_mphal.c
@@ -159,41 +159,6 @@ void mp_hal_signal_input(void) {
#endif
}
-static int call_dupterm_read(void) {
- if (MP_STATE_PORT(term_obj) == NULL) {
- return -1;
- }
-
- nlr_buf_t nlr;
- if (nlr_push(&nlr) == 0) {
- mp_obj_t readinto_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_readinto, readinto_m);
- readinto_m[2] = MP_STATE_PORT(dupterm_arr_obj);
- mp_obj_t res = mp_call_method_n_kw(1, 0, readinto_m);
- if (res == mp_const_none) {
- nlr_pop();
- return -2;
- }
- if (res == MP_OBJ_NEW_SMALL_INT(0)) {
- mp_uos_deactivate("dupterm: EOF received, deactivating\n", MP_OBJ_NULL);
- nlr_pop();
- return -1;
- }
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(MP_STATE_PORT(dupterm_arr_obj), &bufinfo, MP_BUFFER_READ);
- nlr_pop();
- if (*(byte*)bufinfo.buf == mp_interrupt_char) {
- mp_keyboard_interrupt();
- return -2;
- }
- return *(byte*)bufinfo.buf;
- } else {
- mp_uos_deactivate("dupterm: Exception in read() method, deactivating: ", nlr.ret_val);
- }
-
- return -1;
-}
-
STATIC void dupterm_task_handler(os_event_t *evt) {
static byte lock;
if (lock) {
@@ -201,7 +166,7 @@ STATIC void dupterm_task_handler(os_event_t *evt) {
}
lock = 1;
while (1) {
- int c = call_dupterm_read();
+ int c = mp_uos_dupterm_rx_chr();
if (c < 0) {
break;
}
diff --git a/ports/esp8266/machine_hspi.c b/ports/esp8266/machine_hspi.c
index eaabbab7e..9fd0f4868 100644
--- a/ports/esp8266/machine_hspi.c
+++ b/ports/esp8266/machine_hspi.c
@@ -149,7 +149,7 @@ mp_obj_t machine_hspi_make_new(const mp_obj_type_t *type, size_t n_args, size_t
// args[0] holds the id of the peripheral
if (args[0] != MP_OBJ_NEW_SMALL_INT(1)) {
// FlashROM is on SPI0, so far we don't support its usage
- mp_raise_ValueError("");
+ mp_raise_ValueError(NULL);
}
machine_hspi_obj_t *self = m_new_obj(machine_hspi_obj_t);
diff --git a/ports/esp8266/machine_wdt.c b/ports/esp8266/machine_wdt.c
index 04b42782e..4432297fa 100644
--- a/ports/esp8266/machine_wdt.c
+++ b/ports/esp8266/machine_wdt.c
@@ -51,7 +51,7 @@ STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args
case 0:
return &wdt_default;
default:
- mp_raise_ValueError("");
+ mp_raise_ValueError(NULL);
}
}
diff --git a/ports/esp8266/main.c b/ports/esp8266/main.c
index 04ea82761..c590ab59e 100644
--- a/ports/esp8266/main.c
+++ b/ports/esp8266/main.c
@@ -101,8 +101,7 @@ STATIC void mp_reset(void) {
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_FROZEN_FAKE_DIR_QSTR));
mp_obj_list_init(mp_sys_argv, 0);
- MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
- MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
+
reset_pins();
#if MICROPY_EMIT_XTENSA || MICROPY_EMIT_INLINE_XTENSA
extern void esp_native_code_init(void);
diff --git a/ports/esp8266/modnetwork.c b/ports/esp8266/modnetwork.c
index 2c61e5dcd..b41a11f59 100644
--- a/ports/esp8266/modnetwork.c
+++ b/ports/esp8266/modnetwork.c
@@ -93,29 +93,55 @@ STATIC mp_obj_t esp_active(size_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
-STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) {
- require_if(args[0], STATION_IF);
+STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_ssid, ARG_password, ARG_bssid };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_, MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ { MP_QSTR_bssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
+ };
+
+ // parse args
+ 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);
+
+ require_if(pos_args[0], STATION_IF);
struct station_config config = {{0}};
size_t len;
const char *p;
+ bool set_config = false;
- if (n_args > 1) {
- p = mp_obj_str_get_data(args[1], &len);
+ // set parameters based on given args
+ if (args[ARG_ssid].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_ssid].u_obj, &len);
len = MIN(len, sizeof(config.ssid));
memcpy(config.ssid, p, len);
- if (n_args > 2) {
- p = mp_obj_str_get_data(args[2], &len);
- len = MIN(len, sizeof(config.password));
- memcpy(config.password, p, len);
+ set_config = true;
+ }
+ if (args[ARG_password].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_password].u_obj, &len);
+ len = MIN(len, sizeof(config.password));
+ memcpy(config.password, p, len);
+ set_config = true;
+ }
+ if (args[ARG_bssid].u_obj != mp_const_none) {
+ p = mp_obj_str_get_data(args[ARG_bssid].u_obj, &len);
+ if (len != sizeof(config.bssid)) {
+ mp_raise_ValueError(NULL);
}
+ config.bssid_set = 1;
+ memcpy(config.bssid, p, sizeof(config.bssid));
+ set_config = true;
+ }
+ if (set_config) {
error_check(wifi_station_set_config(&config), "Cannot set STA config");
}
error_check(wifi_station_connect(), "Cannot connect to AP");
return mp_const_none;
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_connect_obj, 1, 7, esp_connect);
+STATIC MP_DEFINE_CONST_FUN_OBJ_KW(esp_connect_obj, 1, esp_connect);
STATIC mp_obj_t esp_disconnect(mp_obj_t self_in) {
require_if(self_in, STATION_IF);
diff --git a/ports/esp8266/modules/webrepl_setup.py b/ports/esp8266/modules/webrepl_setup.py
index 52c76863a..50d866b55 100644
--- a/ports/esp8266/modules/webrepl_setup.py
+++ b/ports/esp8266/modules/webrepl_setup.py
@@ -16,12 +16,9 @@ def getpass(prompt):
def input_pass():
while 1:
- passwd1 = getpass("New password: ")
- if len(passwd1) < 4:
- print("Password too short")
- continue
- elif len(passwd1) > 9:
- print("Password too long")
+ passwd1 = getpass("New password (4-9 chars): ")
+ if len(passwd1) < 4 or len(passwd1) > 9:
+ print("Invalid password length")
continue
passwd2 = getpass("Confirm password: ")
if passwd1 == passwd2:
diff --git a/ports/minimal/frozentest.mpy b/ports/minimal/frozentest.mpy
index 87f9581bf..7c6809bf6 100644
--- a/ports/minimal/frozentest.mpy
+++ b/ports/minimal/frozentest.mpy
Binary files differ
diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile
index e3cb1b217..a6e82b24d 100644
--- a/ports/stm32/Makefile
+++ b/ports/stm32/Makefile
@@ -287,13 +287,13 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\
class/src/usbd_msc_data.c \
)
-ifeq ($(MICROPY_PY_WIZNET5K),1)
+ifneq ($(MICROPY_PY_WIZNET5K),0)
WIZNET5K_DIR=drivers/wiznet5k
INC += -I$(TOP)/$(WIZNET5K_DIR)
-CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=1
+CFLAGS_MOD += -DMICROPY_PY_WIZNET5K=$(MICROPY_PY_WIZNET5K) -D_WIZCHIP_=$(MICROPY_PY_WIZNET5K)
SRC_MOD += modnwwiznet5k.c
SRC_MOD += $(addprefix $(WIZNET5K_DIR)/,\
- ethernet/w5200/w5200.c \
+ ethernet/w$(MICROPY_PY_WIZNET5K)/w$(MICROPY_PY_WIZNET5K).c \
ethernet/wizchip_conf.c \
ethernet/socket.c \
internet/dns/dns.c \
diff --git a/ports/stm32/boards/stm32f767_af.csv b/ports/stm32/boards/stm32f767_af.csv
index db27818c6..1708dfcca 100644
--- a/ports/stm32/boards/stm32f767_af.csv
+++ b/ports/stm32/boards/stm32f767_af.csv
@@ -15,9 +15,9 @@ 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
+PortA,PA15,JTDI,TIM2_CH1/TIM2_ETR,,,HDMICEC,SPI1_NSS/I2S1_WS,SPI3_NSS/I2S3_WS,,UART4_RTS,,,,,,,EVENTOUT
+PortB,PB0,,TIM1_CH2N,TIM3_CH3T,TIM8_CH2N,,,,,UART4_CTS,LCD_R3,OTG_HS_ULPI_D1,ETH_MII_RXD2,,,,EVENTOUT
+PortB,PB1,,TIM1_CH3N,TIM3_CH4T,TIM8_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,,,,SDMMC2_D2,,,,,EVENTOUT
PortB,PB4,NJTRST,,TIM3_CH1,,,SPI1_MISO,SPI3_MISO,SPI2_NSS/I2S2_WS,,,SDMMC2_D3,,,,,EVENTOUT
@@ -41,7 +41,7 @@ PortC,PC5,,,,,,,,,SPDIFRX_IN3,,,ETH_MII_RXD1/ETH_RMII_RXD1,FMC_SDCKE0,,,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,PC9,MCO2,,TIM3_CH4,TIM8_CH4,I2C3_SDA,I2S2_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
diff --git a/ports/stm32/modnwcc3k.c b/ports/stm32/modnwcc3k.c
index 551206da8..8cc0a613d 100644
--- a/ports/stm32/modnwcc3k.c
+++ b/ports/stm32/modnwcc3k.c
@@ -125,7 +125,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
if (ip == 0) {
// unknown host
- return MP_ENOENT;
+ return -2;
}
out_ip[0] = ip >> 24;
diff --git a/ports/stm32/modnwwiznet5k.c b/ports/stm32/modnwwiznet5k.c
index 21e4dbbbf..763137c70 100644
--- a/ports/stm32/modnwwiznet5k.c
+++ b/ports/stm32/modnwwiznet5k.c
@@ -30,6 +30,7 @@
#include "py/objlist.h"
#include "py/runtime.h"
+#include "py/stream.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "lib/netutils/netutils.h"
@@ -92,7 +93,7 @@ STATIC int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len,
return 0;
} else {
// failure
- return MP_ENOENT;
+ return -2;
}
}
@@ -173,11 +174,7 @@ STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_
int sr = getSn_SR((uint8_t)socket->u_param.fileno);
if (sr == SOCK_ESTABLISHED) {
socket2->u_param = socket->u_param;
- // TODO need to populate this with the correct values
- ip[0] = 0;
- ip[1] = 0;
- ip[2] = 0;
- ip[3] = 0;
+ getSn_DIPR((uint8_t)socket2->u_param.fileno, ip);
*port = getSn_PORT(socket2->u_param.fileno);
// WIZnet turns the listening socket into the client socket, so we
@@ -309,9 +306,19 @@ STATIC int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_
}
STATIC int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
- // TODO
- *_errno = MP_EINVAL;
- return -1;
+ if (request == MP_STREAM_POLL) {
+ int ret = 0;
+ if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->u_param.fileno) != 0) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->u_param.fileno) != 0) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ return ret;
+ } else {
+ *_errno = MP_EINVAL;
+ return MP_STREAM_ERROR;
+ }
}
#if 0
@@ -350,7 +357,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
wiznet5k_obj.spi->Init.CLKPolarity = SPI_POLARITY_LOW; // clock is low when idle
wiznet5k_obj.spi->Init.CLKPhase = SPI_PHASE_1EDGE; // data latched on first edge, which is rising edge for low-idle
wiznet5k_obj.spi->Init.NSS = SPI_NSS_SOFT;
- wiznet5k_obj.spi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz
+ wiznet5k_obj.spi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; // clock freq = f_PCLK / this_prescale_value; Wiz820i can do up to 80MHz
wiznet5k_obj.spi->Init.FirstBit = SPI_FIRSTBIT_MSB;
wiznet5k_obj.spi->Init.TIMode = SPI_TIMODE_DISABLED;
wiznet5k_obj.spi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
@@ -402,7 +409,12 @@ STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
if (i % 16 == 0) {
printf("\n %04x:", i);
}
- printf(" %02x", WIZCHIP_READ(i));
+ #if MICROPY_PY_WIZNET5K == 5200
+ uint32_t reg = i;
+ #else
+ uint32_t reg = _W5500_IO_BASE_ | i << 8;
+ #endif
+ printf(" %02x", WIZCHIP_READ(reg));
}
for (int sn = 0; sn < 4; ++sn) {
printf("\nWiz SREG[%d]:", sn);
@@ -410,7 +422,12 @@ STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
if (i % 16 == 0) {
printf("\n %04x:", i);
}
- printf(" %02x", WIZCHIP_READ(WIZCHIP_SREG_ADDR(sn, i)));
+ #if MICROPY_PY_WIZNET5K == 5200
+ uint32_t reg = WIZCHIP_SREG_ADDR(sn, i);
+ #else
+ uint32_t reg = _W5500_IO_BASE_ | i << 8 | WIZCHIP_SREG_BLOCK(sn) << 3;
+ #endif
+ printf(" %02x", WIZCHIP_READ(reg));
}
}
printf("\n");
@@ -418,6 +435,12 @@ STATIC mp_obj_t wiznet5k_regs(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_regs_obj, wiznet5k_regs);
+STATIC mp_obj_t wiznet5k_isconnected(mp_obj_t self_in) {
+ (void)self_in;
+ return mp_obj_new_bool(wizphy_getphylink() == PHY_LINK_ON);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_isconnected_obj, wiznet5k_isconnected);
+
/// \method ifconfig([(ip, subnet, gateway, dns)])
/// Get/set IP address, subnet mask, gateway and DNS.
STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
@@ -449,6 +472,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k
STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) },
{ MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&wiznet5k_isconnected_obj) },
};
STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c
index 176fc8466..81cbdcc19 100644
--- a/ports/stm32/modpyb.c
+++ b/ports/stm32/modpyb.c
@@ -27,7 +27,7 @@
#include <stdint.h>
#include <stdio.h>
-#include "py/obj.h"
+#include "py/runtime.h"
#include "py/gc.h"
#include "py/builtin.h"
#include "py/mphal.h"
@@ -104,6 +104,28 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c
+// Get or set the UART object that the REPL is repeated on.
+// This is a legacy function, use of uos.dupterm is preferred.
+STATIC mp_obj_t pyb_repl_uart(size_t n_args, const mp_obj_t *args) {
+ if (n_args == 0) {
+ if (MP_STATE_PORT(pyb_stdio_uart) == NULL) {
+ return mp_const_none;
+ } else {
+ return MP_STATE_PORT(pyb_stdio_uart);
+ }
+ } else {
+ if (args[0] == mp_const_none) {
+ MP_STATE_PORT(pyb_stdio_uart) = NULL;
+ } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
+ MP_STATE_PORT(pyb_stdio_uart) = args[0];
+ } else {
+ mp_raise_ValueError("need a UART object");
+ }
+ return mp_const_none;
+ }
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_repl_uart_obj, 0, 1, pyb_repl_uart);
+
STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) },
@@ -126,7 +148,7 @@ STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_sleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_standby), MP_ROM_PTR(&machine_deepsleep_obj) },
{ MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) },
- { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&mod_os_dupterm_obj) },
+ { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&pyb_repl_uart_obj) },
{ MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) },
{ MP_ROM_QSTR(MP_QSTR_hid_mouse), MP_ROM_PTR(&pyb_usb_hid_mouse_obj) },
diff --git a/ports/stm32/moduos.c b/ports/stm32/moduos.c
index f661b3b5e..f6e1483d3 100644
--- a/ports/stm32/moduos.c
+++ b/ports/stm32/moduos.c
@@ -33,6 +33,7 @@
#include "lib/timeutils/timeutils.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
+#include "extmod/misc.h"
#include "extmod/vfs.h"
#include "extmod/vfs_fat.h"
#include "genhdr/mpversion.h"
@@ -105,28 +106,6 @@ STATIC mp_obj_t os_urandom(mp_obj_t num) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_urandom_obj, os_urandom);
#endif
-// Get or set the UART object that the REPL is repeated on.
-// TODO should accept any object with read/write methods.
-STATIC mp_obj_t os_dupterm(size_t n_args, const mp_obj_t *args) {
- if (n_args == 0) {
- if (MP_STATE_PORT(pyb_stdio_uart) == NULL) {
- return mp_const_none;
- } else {
- return MP_STATE_PORT(pyb_stdio_uart);
- }
- } else {
- if (args[0] == mp_const_none) {
- MP_STATE_PORT(pyb_stdio_uart) = NULL;
- } else if (mp_obj_get_type(args[0]) == &pyb_uart_type) {
- MP_STATE_PORT(pyb_stdio_uart) = args[0];
- } else {
- mp_raise_ValueError("need a UART object");
- }
- return mp_const_none;
- }
-}
-MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj, 0, 1, os_dupterm);
-
STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
@@ -154,7 +133,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
#endif
// these are MicroPython extensions
- { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mod_os_dupterm_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mp_uos_dupterm_obj) },
{ MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
{ MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
diff --git a/ports/stm32/modusocket.c b/ports/stm32/modusocket.c
index c5ab3b6d7..71a237b0d 100644
--- a/ports/stm32/modusocket.c
+++ b/ports/stm32/modusocket.c
@@ -390,29 +390,48 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
size_t hlen;
const char *host = mp_obj_str_get_data(host_in, &hlen);
mp_int_t port = mp_obj_get_int(port_in);
+ uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE];
+ bool have_ip = false;
+
+ if (hlen > 0) {
+ // check if host is already in IP form
+ nlr_buf_t nlr;
+ if (nlr_push(&nlr) == 0) {
+ netutils_parse_ipv4_addr(host_in, out_ip, NETUTILS_BIG);
+ have_ip = true;
+ nlr_pop();
+ } else {
+ // swallow exception: host was not in IP form so need to do DNS lookup
+ }
+ }
- // find a NIC that can do a name lookup
- for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
- mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
- mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
- if (nic_type->gethostbyname != NULL) {
- uint8_t out_ip[MOD_NETWORK_IPADDR_BUF_SIZE];
- int ret = nic_type->gethostbyname(nic, host, hlen, out_ip);
- if (ret != 0) {
- // TODO CPython raises: socket.gaierror: [Errno -2] Name or service not known
- mp_raise_OSError(ret);
+ if (!have_ip) {
+ // find a NIC that can do a name lookup
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) {
+ mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i];
+ mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic);
+ if (nic_type->gethostbyname != NULL) {
+ int ret = nic_type->gethostbyname(nic, host, hlen, out_ip);
+ if (ret != 0) {
+ mp_raise_OSError(ret);
+ }
+ have_ip = true;
+ break;
}
- mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
- tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
- tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
- 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(out_ip, port, NETUTILS_BIG);
- return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
}
- nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC"));
+ if (!have_ip) {
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "no available NIC"));
+ }
+
+ mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM);
+ 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(out_ip, port, NETUTILS_BIG);
+ return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo);
diff --git a/ports/stm32/mpconfigport.h b/ports/stm32/mpconfigport.h
index 7888b5355..51d442561 100644
--- a/ports/stm32/mpconfigport.h
+++ b/ports/stm32/mpconfigport.h
@@ -126,6 +126,7 @@
#define MICROPY_PY_USELECT (1)
#define MICROPY_PY_UTIMEQ (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
+#define MICROPY_PY_OS_DUPTERM (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
@@ -326,6 +327,8 @@ static inline mp_uint_t disable_irq(void) {
__WFI(); \
} \
} while (0);
+
+#define MICROPY_THREAD_YIELD() pyb_thread_yield()
#else
#define MICROPY_EVENT_POLL_HOOK \
do { \
@@ -333,8 +336,13 @@ static inline mp_uint_t disable_irq(void) {
mp_handle_pending(); \
__WFI(); \
} while (0);
+
+#define MICROPY_THREAD_YIELD()
#endif
+// We need an implementation of the log2 function which is not a macro
+#define MP_NEED_LOG2 (1)
+
// There is no classical C heap in bare-metal ports, only Python
// garbage-collected heap. For completeness, emulate C heap via
// GC heap. Note that MicroPython core never uses malloc() and friends,
diff --git a/ports/stm32/mpconfigport.mk b/ports/stm32/mpconfigport.mk
index 64145383e..e708de6c1 100644
--- a/ports/stm32/mpconfigport.mk
+++ b/ports/stm32/mpconfigport.mk
@@ -1,6 +1,9 @@
# Enable/disable extra modules
-# wiznet5k module for ethernet support
+# wiznet5k module for ethernet support; valid values are:
+# 0 : no Wiznet support
+# 5200 : support for W5200 module
+# 5500 : support for W5500 module
MICROPY_PY_WIZNET5K ?= 0
# cc3k module for wifi support
diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c
index ab3dc227a..e9c4f28f7 100644
--- a/ports/stm32/mphalport.c
+++ b/ports/stm32/mphalport.c
@@ -3,6 +3,7 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
+#include "extmod/misc.h"
#include "usb.h"
#include "uart.h"
@@ -38,6 +39,10 @@ int mp_hal_stdin_rx_chr(void) {
} else if (MP_STATE_PORT(pyb_stdio_uart) != NULL && uart_rx_any(MP_STATE_PORT(pyb_stdio_uart))) {
return uart_rx_char(MP_STATE_PORT(pyb_stdio_uart));
}
+ int dupterm_c = mp_uos_dupterm_rx_chr();
+ if (dupterm_c >= 0) {
+ return dupterm_c;
+ }
MICROPY_EVENT_POLL_HOOK
}
}
@@ -56,15 +61,26 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
if (usb_vcp_is_enabled()) {
usb_vcp_send_strn(str, len);
}
+ mp_uos_dupterm_tx_strn(str, len);
}
+// Efficiently convert "\n" to "\r\n"
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
- // send stdout to UART and USB CDC VCP
- if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
- uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len);
+ const char *last = str;
+ while (len--) {
+ if (*str == '\n') {
+ if (str > last) {
+ mp_hal_stdout_tx_strn(last, str - last);
+ }
+ mp_hal_stdout_tx_strn("\r\n", 2);
+ ++str;
+ last = str;
+ } else {
+ ++str;
+ }
}
- if (usb_vcp_is_enabled()) {
- usb_vcp_send_strn_cooked(str, len);
+ if (str > last) {
+ mp_hal_stdout_tx_strn(last, str - last);
}
}
diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c
index a8913a055..8f0513e8c 100644
--- a/ports/stm32/uart.c
+++ b/ports/stm32/uart.c
@@ -454,26 +454,11 @@ STATIC size_t uart_tx_data(pyb_uart_obj_t *self, const void *src_in, size_t num_
return num_tx;
}
-STATIC void uart_tx_char(pyb_uart_obj_t *uart_obj, int c) {
- uint16_t ch = c;
- int errcode;
- uart_tx_data(uart_obj, &ch, 1, &errcode);
-}
-
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
int errcode;
uart_tx_data(uart_obj, str, len, &errcode);
}
-void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len) {
- for (const char *top = str + len; str < top; str++) {
- if (*str == '\n') {
- uart_tx_char(uart_obj, '\r');
- }
- uart_tx_char(uart_obj, *str);
- }
-}
-
// this IRQ handler is set up to handle RXNE interrupts only
void uart_irq_handler(mp_uint_t uart_id) {
// get the uart object
diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h
index e96b25b5f..d176520a1 100644
--- a/ports/stm32/uart.h
+++ b/ports/stm32/uart.h
@@ -48,6 +48,5 @@ void uart_irq_handler(mp_uint_t uart_id);
mp_uint_t uart_rx_any(pyb_uart_obj_t *uart_obj);
int uart_rx_char(pyb_uart_obj_t *uart_obj);
void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len);
-void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
#endif // MICROPY_INCLUDED_STMHAL_UART_H
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 906eb1989..5017bb930 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -178,20 +178,6 @@ void usb_vcp_send_strn(const char *str, int len) {
#endif
}
-void usb_vcp_send_strn_cooked(const char *str, int len) {
-#ifdef USE_DEVICE_MODE
- if (usb_device.enabled) {
- for (const char *top = str + len; str < top; str++) {
- if (*str == '\n') {
- usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)"\r\n", 2);
- } else {
- usbd_cdc_tx_always(&usb_device.usbd_cdc_itf, (const uint8_t*)str, 1);
- }
- }
- }
-#endif
-}
-
/******************************************************************************/
// MicroPython bindings for USB
diff --git a/ports/stm32/usb.h b/ports/stm32/usb.h
index f60ea8033..41c461fb2 100644
--- a/ports/stm32/usb.h
+++ b/ports/stm32/usb.h
@@ -63,7 +63,6 @@ void pyb_usb_dev_deinit(void);
bool usb_vcp_is_enabled(void);
int usb_vcp_recv_byte(uint8_t *c); // if a byte is available, return 1 and put the byte in *c, else return 0
void usb_vcp_send_strn(const char* str, int len);
-void usb_vcp_send_strn_cooked(const char *str, int len);
void pyb_usb_host_init(void);
void pyb_usb_host_process(void);
diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c
index 4c49c9321..2e9fba917 100644
--- a/ports/stm32/usbd_cdc_interface.c
+++ b/ports/stm32/usbd_cdc_interface.c
@@ -57,10 +57,14 @@
#define CDC_SEND_BREAK 0x23
uint8_t *usbd_cdc_init(usbd_cdc_itf_t *cdc, usbd_cdc_msc_hid_state_t *usbd) {
+ // Link the parent state
cdc->usbd = usbd;
+
+ // Reset all the CDC state
+ // Note: we don't reset tx_buf_ptr_in in order to allow the output buffer to
+ // be filled (by usbd_cdc_tx_always) before the USB device is connected.
cdc->rx_buf_put = 0;
cdc->rx_buf_get = 0;
- cdc->tx_buf_ptr_in = 0;
cdc->tx_buf_ptr_out = 0;
cdc->tx_buf_ptr_out_shadow = 0;
cdc->tx_buf_ptr_wait_count = 0;
diff --git a/ports/stm32/usbd_cdc_interface.h b/ports/stm32/usbd_cdc_interface.h
index 6dcab7d47..98b8fc077 100644
--- a/ports/stm32/usbd_cdc_interface.h
+++ b/ports/stm32/usbd_cdc_interface.h
@@ -43,8 +43,8 @@ typedef struct _usbd_cdc_itf_t {
uint16_t rx_buf_get; // circular buffer index
uint8_t tx_buf[USBD_CDC_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer
- uint16_t tx_buf_ptr_in; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available
- volatile uint16_t tx_buf_ptr_out; // increment this pointer modulo APP_TX_DATA_SIZE when data is drained
+ uint16_t tx_buf_ptr_in; // increment this pointer modulo USBD_CDC_TX_DATA_SIZE when new data is available
+ volatile uint16_t tx_buf_ptr_out; // increment this pointer modulo USBD_CDC_TX_DATA_SIZE when data is drained
uint16_t tx_buf_ptr_out_shadow; // shadow of above
uint8_t tx_buf_ptr_wait_count; // used to implement a timeout waiting for low-level USB driver
uint8_t tx_need_empty_packet; // used to flush the USB IN endpoint if the last packet was exactly the endpoint packet size
diff --git a/ports/teensy/teensy_hal.c b/ports/teensy/teensy_hal.c
index 84d68cff8..7ce82f1d2 100644
--- a/ports/teensy/teensy_hal.c
+++ b/ports/teensy/teensy_hal.c
@@ -49,6 +49,7 @@ void mp_hal_stdout_tx_strn(const char *str, size_t len) {
void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) {
// send stdout to UART and USB CDC VCP
if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
+ void uart_tx_strn_cooked(pyb_uart_obj_t *uart_obj, const char *str, uint len);
uart_tx_strn_cooked(MP_STATE_PORT(pyb_stdio_uart), str, len);
}
if (usb_vcp_is_enabled()) {
diff --git a/ports/teensy/uart.c b/ports/teensy/uart.c
index 3d5111217..a8cfd63ea 100644
--- a/ports/teensy/uart.c
+++ b/ports/teensy/uart.c
@@ -426,11 +426,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_send_obj, 1, pyb_uart_send);
///
/// Return value: if `recv` is an integer then a new buffer of the bytes received,
/// otherwise the same buffer that was passed in to `recv`.
+#if 0
STATIC const mp_arg_t pyb_uart_recv_args[] = {
{ MP_QSTR_recv, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_timeout, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 5000} },
};
#define PYB_UART_RECV_NUM_ARGS MP_ARRAY_SIZE(pyb_uart_recv_args)
+#endif
STATIC mp_obj_t pyb_uart_recv(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) {
// TODO assumes transmission size is 8-bits wide
diff --git a/ports/unix/Makefile b/ports/unix/Makefile
index dbe3e592e..5bdcf4e1a 100644
--- a/ports/unix/Makefile
+++ b/ports/unix/Makefile
@@ -97,7 +97,7 @@ SRC_MOD += modtermios.c
endif
ifeq ($(MICROPY_PY_SOCKET),1)
CFLAGS_MOD += -DMICROPY_PY_SOCKET=1
-SRC_MOD += modsocket.c
+SRC_MOD += modusocket.c
endif
ifeq ($(MICROPY_PY_THREAD),1)
CFLAGS_MOD += -DMICROPY_PY_THREAD=1 -DMICROPY_PY_THREAD_GIL=0
diff --git a/ports/unix/modjni.c b/ports/unix/modjni.c
index 15b6d9cd7..f29c095cf 100644
--- a/ports/unix/modjni.c
+++ b/ports/unix/modjni.c
@@ -266,7 +266,7 @@ STATIC mp_obj_t jobject_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value)
return mp_const_none;
}
}
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
}
if (!JJ(IsInstanceOf, self->obj, List_class)) {
diff --git a/ports/unix/modsocket.c b/ports/unix/modusocket.c
index 7e82554c7..cfb6a9f5e 100644
--- a/ports/unix/modsocket.c
+++ b/ports/unix/modusocket.c
@@ -60,8 +60,6 @@
should be add to separate modules (C or Python level).
*/
-#define MICROPY_SOCKET_EXTRA (0)
-
// This type must "inherit" from mp_obj_fdfile_t, i.e. matching subset of
// fields should have the same layout.
typedef struct _mp_obj_socket_t {
@@ -382,26 +380,6 @@ const mp_obj_type_t mp_type_socket = {
.locals_dict = (mp_obj_dict_t*)&usocket_locals_dict,
};
-#if MICROPY_SOCKET_EXTRA
-STATIC mp_obj_t mod_socket_htons(mp_obj_t arg) {
- return MP_OBJ_NEW_SMALL_INT(htons(MP_OBJ_SMALL_INT_VALUE(arg)));
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_htons_obj, mod_socket_htons);
-
-
-STATIC mp_obj_t mod_socket_gethostbyname(mp_obj_t arg) {
- const char *s = mp_obj_str_get_str(arg);
- struct hostent *h = gethostbyname(s);
- if (h == NULL) {
- // CPython: socket.herror
- mp_raise_OSError(h_errno);
- }
- assert(h->h_length == 4);
- return mp_obj_new_int(*(int*)*h->h_addr_list);
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_socket_gethostbyname_obj, mod_socket_gethostbyname);
-#endif // MICROPY_SOCKET_EXTRA
-
#define BINADDR_MAX_LEN sizeof(struct in6_addr)
STATIC mp_obj_t mod_socket_inet_pton(mp_obj_t family_in, mp_obj_t addr_in) {
int family = mp_obj_get_int(family_in);
@@ -549,10 +527,6 @@ STATIC const mp_rom_map_elem_t mp_module_socket_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_inet_pton), MP_ROM_PTR(&mod_socket_inet_pton_obj) },
{ MP_ROM_QSTR(MP_QSTR_inet_ntop), MP_ROM_PTR(&mod_socket_inet_ntop_obj) },
{ MP_ROM_QSTR(MP_QSTR_sockaddr), MP_ROM_PTR(&mod_socket_sockaddr_obj) },
-#if MICROPY_SOCKET_EXTRA
- { MP_ROM_QSTR(MP_QSTR_htons), MP_ROM_PTR(&mod_socket_htons_obj) },
- { MP_ROM_QSTR(MP_QSTR_gethostbyname), MP_ROM_PTR(&mod_socket_gethostbyname_obj) },
-#endif
#define C(name) { MP_ROM_QSTR(MP_QSTR_ ## name), MP_ROM_INT(name) }
C(AF_UNIX),
diff --git a/ports/unix/mpconfigport.h b/ports/unix/mpconfigport.h
index 50b979279..db382e0a7 100644
--- a/ports/unix/mpconfigport.h
+++ b/ports/unix/mpconfigport.h
@@ -85,6 +85,7 @@
#define MICROPY_PY_BUILTINS_POW3 (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
+#define MICROPY_PY_REVERSE_SPECIAL_METHODS (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1)
#define MICROPY_PY_SYS_EXIT (1)
diff --git a/ports/unix/unix_mphal.c b/ports/unix/unix_mphal.c
index 2b273d834..f27c62fd1 100644
--- a/ports/unix/unix_mphal.c
+++ b/ports/unix/unix_mphal.c
@@ -108,11 +108,11 @@ void mp_hal_stdio_mode_orig(void) {
#endif
#if MICROPY_PY_OS_DUPTERM
-static int call_dupterm_read(void) {
+static int call_dupterm_read(size_t idx) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_obj_t read_m[3];
- mp_load_method(MP_STATE_PORT(term_obj), MP_QSTR_read, read_m);
+ mp_load_method(MP_STATE_VM(dupterm_objs[idx]), MP_QSTR_read, read_m);
read_m[2] = MP_OBJ_NEW_SMALL_INT(1);
mp_obj_t res = mp_call_method_n_kw(1, 0, read_m);
if (res == mp_const_none) {
@@ -122,18 +122,18 @@ static int call_dupterm_read(void) {
mp_get_buffer_raise(res, &bufinfo, MP_BUFFER_READ);
if (bufinfo.len == 0) {
mp_printf(&mp_plat_print, "dupterm: EOF received, deactivating\n");
- MP_STATE_PORT(term_obj) = NULL;
+ MP_STATE_VM(dupterm_objs[idx]) = MP_OBJ_NULL;
return -1;
}
nlr_pop();
return *(byte*)bufinfo.buf;
} else {
// Temporarily disable dupterm to avoid infinite recursion
- mp_obj_t save_term = MP_STATE_PORT(term_obj);
- MP_STATE_PORT(term_obj) = NULL;
+ mp_obj_t save_term = MP_STATE_VM(dupterm_objs[idx]);
+ MP_STATE_VM(dupterm_objs[idx]) = NULL;
mp_printf(&mp_plat_print, "dupterm: ");
mp_obj_print_exception(&mp_plat_print, nlr.ret_val);
- MP_STATE_PORT(term_obj) = save_term;
+ MP_STATE_VM(dupterm_objs[idx]) = save_term;
}
return -1;
@@ -143,10 +143,11 @@ static int call_dupterm_read(void) {
int mp_hal_stdin_rx_chr(void) {
unsigned char c;
#if MICROPY_PY_OS_DUPTERM
- if (MP_STATE_PORT(term_obj) != MP_OBJ_NULL) {
+ // TODO only support dupterm one slot at the moment
+ if (MP_STATE_VM(dupterm_objs[0]) != MP_OBJ_NULL) {
int c;
do {
- c = call_dupterm_read();
+ c = call_dupterm_read(0);
} while (c == -2);
if (c == -1) {
goto main_term;
diff --git a/ports/zephyr/main.c b/ports/zephyr/main.c
index 7255d981f..7eb9da3e1 100644
--- a/ports/zephyr/main.c
+++ b/ports/zephyr/main.c
@@ -60,7 +60,9 @@ static char *stack_top;
static char heap[MICROPY_HEAP_SIZE];
void init_zephyr(void) {
- // TODO: Make addresses configurable
+ // We now rely on CONFIG_NET_APP_SETTINGS to set up bootstrap
+ // network addresses.
+#if 0
#ifdef CONFIG_NETWORKING
if (net_if_get_default() == NULL) {
// If there's no default networking interface,
@@ -81,6 +83,7 @@ void init_zephyr(void) {
static struct in6_addr in6addr_my = {{{0x20, 0x01, 0x0d, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}};
net_if_ipv6_addr_add(net_if_get_default(), &in6addr_my, NET_ADDR_MANUAL, 0);
#endif
+#endif
}
int real_main(void) {
diff --git a/ports/zephyr/prj_base.conf b/ports/zephyr/prj_base.conf
index c3ba2812f..fbcedf260 100644
--- a/ports/zephyr/prj_base.conf
+++ b/ports/zephyr/prj_base.conf
@@ -4,6 +4,12 @@ CONFIG_REBOOT=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y
CONFIG_UART_CONSOLE_DEBUG_SERVER_HOOKS=y
+
+CONFIG_CONSOLE_PULL=y
+CONFIG_CONSOLE_GETCHAR=y
+CONFIG_CONSOLE_GETCHAR_BUFSIZE=128
+CONFIG_CONSOLE_PUTCHAR_BUFSIZE=128
+
CONFIG_NEWLIB_LIBC=y
CONFIG_FLOAT=y
CONFIG_MAIN_STACK_SIZE=4096
@@ -18,6 +24,14 @@ CONFIG_NET_SOCKETS=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_NBUF_RX_COUNT=5
+CONFIG_NET_APP_SETTINGS=y
+CONFIG_NET_APP_INIT_TIMEOUT=3
+CONFIG_NET_APP_NEED_IPV6=y
+CONFIG_NET_APP_NEED_IPV4=y
+CONFIG_NET_APP_MY_IPV6_ADDR="2001:db8::1"
+CONFIG_NET_APP_MY_IPV4_ADDR="192.0.2.1"
+CONFIG_NET_APP_MY_IPV4_GW="192.0.2.2"
+
# DNS
CONFIG_DNS_RESOLVER=y
CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
diff --git a/ports/zephyr/prj_qemu_cortex_m3.conf b/ports/zephyr/prj_qemu_cortex_m3.conf
index 09614c362..1ade981e2 100644
--- a/ports/zephyr/prj_qemu_cortex_m3.conf
+++ b/ports/zephyr/prj_qemu_cortex_m3.conf
@@ -1,3 +1,7 @@
+# Interrupt-driven UART console has emulation artifacts under QEMU,
+# disable it
+CONFIG_CONSOLE_PULL=n
+
# Networking drivers
# SLIP driver for QEMU
CONFIG_NET_SLIP_TAP=y
diff --git a/ports/zephyr/prj_qemu_x86.conf b/ports/zephyr/prj_qemu_x86.conf
index ef60cfec9..9bc81259a 100644
--- a/ports/zephyr/prj_qemu_x86.conf
+++ b/ports/zephyr/prj_qemu_x86.conf
@@ -1,3 +1,7 @@
+# Interrupt-driven UART console has emulation artifacts under QEMU,
+# disable it
+CONFIG_CONSOLE_PULL=n
+
# Networking drivers
# SLIP driver for QEMU
CONFIG_NET_SLIP_TAP=y
diff --git a/ports/zephyr/src/zephyr_start.c b/ports/zephyr/src/zephyr_start.c
index 9e8a90beb..452e304ca 100644
--- a/ports/zephyr/src/zephyr_start.c
+++ b/ports/zephyr/src/zephyr_start.c
@@ -24,11 +24,16 @@
* THE SOFTWARE.
*/
#include <zephyr.h>
+#include <console.h>
#include "zephyr_getchar.h"
int real_main(void);
void main(void) {
+#ifdef CONFIG_CONSOLE_PULL
+ console_init();
+#else
zephyr_getchar_init();
+#endif
real_main();
}
diff --git a/ports/zephyr/uart_core.c b/ports/zephyr/uart_core.c
index 1e85053cd..e41fb9acc 100644
--- a/ports/zephyr/uart_core.c
+++ b/ports/zephyr/uart_core.c
@@ -28,6 +28,7 @@
#include "src/zephyr_getchar.h"
// Zephyr headers
#include <uart.h>
+#include <console.h>
/*
* Core UART functions to implement for a port
@@ -35,11 +36,23 @@
// Receive single character
int mp_hal_stdin_rx_chr(void) {
+#ifdef CONFIG_CONSOLE_PULL
+ return console_getchar();
+#else
return zephyr_getchar();
+#endif
}
// Send string of given length
void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
+#ifdef CONFIG_CONSOLE_PULL
+ while (len--) {
+ char c = *str++;
+ while (console_putchar(c) == -1) {
+ k_sleep(1);
+ }
+ }
+#else
static struct device *uart_console_dev;
if (uart_console_dev == NULL) {
uart_console_dev = device_get_binding(CONFIG_UART_CONSOLE_ON_DEV_NAME);
@@ -48,4 +61,5 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
while (len--) {
uart_poll_out(uart_console_dev, *str++);
}
+#endif
}
diff --git a/py/argcheck.c b/py/argcheck.c
index 46be126ac..2a606d613 100644
--- a/py/argcheck.c
+++ b/py/argcheck.c
@@ -136,11 +136,9 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
mp_arg_parse_all(n_pos, args, &kw_args, n_allowed, allowed, out_vals);
}
-#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || defined(_MSC_VER)
NORETURN void mp_arg_error_terse_mismatch(void) {
mp_raise_TypeError("argument num/types mismatch");
}
-#endif
#if MICROPY_CPYTHON_COMPAT
NORETURN void mp_arg_error_unimpl_kw(void) {
diff --git a/py/bc.c b/py/bc.c
index 1f6819295..381daa24d 100644
--- a/py/bc.c
+++ b/py/bc.c
@@ -322,7 +322,7 @@ STATIC const byte opcode_format_table[64] = {
OC4(O, O, U, U), // 0x38-0x3b
OC4(U, O, B, O), // 0x3c-0x3f
OC4(O, B, B, O), // 0x40-0x43
- OC4(B, B, O, U), // 0x44-0x47
+ OC4(B, B, O, B), // 0x44-0x47
OC4(U, U, U, U), // 0x48-0x4b
OC4(U, U, U, U), // 0x4c-0x4f
OC4(V, V, U, V), // 0x50-0x53
@@ -362,7 +362,7 @@ STATIC const byte opcode_format_table[64] = {
OC4(B, B, B, B), // 0xcc-0xcf
OC4(B, B, B, B), // 0xd0-0xd3
- OC4(B, B, B, B), // 0xd4-0xd7
+ OC4(U, U, U, B), // 0xd4-0xd7
OC4(B, B, B, B), // 0xd8-0xdb
OC4(B, B, B, B), // 0xdc-0xdf
@@ -373,7 +373,7 @@ STATIC const byte opcode_format_table[64] = {
OC4(B, B, B, B), // 0xf0-0xf3
OC4(B, B, B, B), // 0xf4-0xf7
- OC4(B, B, B, U), // 0xf8-0xfb
+ OC4(U, U, U, U), // 0xf8-0xfb
OC4(U, U, U, U), // 0xfc-0xff
};
#undef OC4
diff --git a/py/bc0.h b/py/bc0.h
index 38e23c0fd..70acfb0ca 100644
--- a/py/bc0.h
+++ b/py/bc0.h
@@ -113,7 +113,7 @@
#define MP_BC_LOAD_CONST_SMALL_INT_MULTI (0x70) // + N(64)
#define MP_BC_LOAD_FAST_MULTI (0xb0) // + N(16)
#define MP_BC_STORE_FAST_MULTI (0xc0) // + N(16)
-#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(<MP_UNARY_OP_NON_BYTECODE)
-#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(36)
+#define MP_BC_UNARY_OP_MULTI (0xd0) // + op(<MP_UNARY_OP_NUM_BYTECODE)
+#define MP_BC_BINARY_OP_MULTI (0xd7) // + op(<MP_BINARY_OP_NUM_BYTECODE)
#endif // MICROPY_INCLUDED_PY_BC0_H
diff --git a/py/emitnative.c b/py/emitnative.c
index b2c9a7366..8e97dda11 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -123,6 +123,8 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_NEW_CELL] = 1,
[MP_F_MAKE_CLOSURE_FROM_RAW_CODE] = 3,
[MP_F_SETUP_CODE_STATE] = 5,
+ [MP_F_SMALL_INT_FLOOR_DIVIDE] = 2,
+ [MP_F_SMALL_INT_MODULO] = 2,
};
#include "py/asmx86.h"
@@ -1823,18 +1825,20 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
vtype_kind_t vtype_lhs = peek_vtype(emit, 1);
vtype_kind_t vtype_rhs = peek_vtype(emit, 0);
if (vtype_lhs == VTYPE_INT && vtype_rhs == VTYPE_INT) {
+ // for integers, inplace and normal ops are equivalent, so use just normal ops
+ if (MP_BINARY_OP_INPLACE_OR <= op && op <= MP_BINARY_OP_INPLACE_POWER) {
+ op += MP_BINARY_OP_OR - MP_BINARY_OP_INPLACE_OR;
+ }
+
#if N_X64 || N_X86
// special cases for x86 and shifting
- if (op == MP_BINARY_OP_LSHIFT
- || op == MP_BINARY_OP_INPLACE_LSHIFT
- || op == MP_BINARY_OP_RSHIFT
- || op == MP_BINARY_OP_INPLACE_RSHIFT) {
+ if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_RSHIFT) {
#if N_X64
emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X64_REG_RCX, &vtype_lhs, REG_RET);
#else
emit_pre_pop_reg_reg(emit, &vtype_rhs, ASM_X86_REG_ECX, &vtype_lhs, REG_RET);
#endif
- if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
+ if (op == MP_BINARY_OP_LSHIFT) {
ASM_LSL_REG(emit->as, REG_RET);
} else {
ASM_ASR_REG(emit->as, REG_RET);
@@ -1843,35 +1847,48 @@ STATIC void emit_native_binary_op(emit_t *emit, mp_binary_op_t op) {
return;
}
#endif
+
+ // special cases for floor-divide and module because we dispatch to helper functions
+ if (op == MP_BINARY_OP_FLOOR_DIVIDE || op == MP_BINARY_OP_MODULO) {
+ emit_pre_pop_reg_reg(emit, &vtype_rhs, REG_ARG_2, &vtype_lhs, REG_ARG_1);
+ if (op == MP_BINARY_OP_FLOOR_DIVIDE) {
+ emit_call(emit, MP_F_SMALL_INT_FLOOR_DIVIDE);
+ } else {
+ emit_call(emit, MP_F_SMALL_INT_MODULO);
+ }
+ emit_post_push_reg(emit, VTYPE_INT, REG_RET);
+ return;
+ }
+
int reg_rhs = REG_ARG_3;
emit_pre_pop_reg_flexible(emit, &vtype_rhs, &reg_rhs, REG_RET, REG_ARG_2);
emit_pre_pop_reg(emit, &vtype_lhs, REG_ARG_2);
if (0) {
// dummy
#if !(N_X64 || N_X86)
- } else if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
+ } else if (op == MP_BINARY_OP_LSHIFT) {
ASM_LSL_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_RSHIFT || op == MP_BINARY_OP_INPLACE_RSHIFT) {
+ } else if (op == MP_BINARY_OP_RSHIFT) {
ASM_ASR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
#endif
- } else if (op == MP_BINARY_OP_OR || op == MP_BINARY_OP_INPLACE_OR) {
+ } else if (op == MP_BINARY_OP_OR) {
ASM_OR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_XOR || op == MP_BINARY_OP_INPLACE_XOR) {
+ } else if (op == MP_BINARY_OP_XOR) {
ASM_XOR_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_AND || op == MP_BINARY_OP_INPLACE_AND) {
+ } else if (op == MP_BINARY_OP_AND) {
ASM_AND_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_ADD || op == MP_BINARY_OP_INPLACE_ADD) {
+ } else if (op == MP_BINARY_OP_ADD) {
ASM_ADD_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_SUBTRACT || op == MP_BINARY_OP_INPLACE_SUBTRACT) {
+ } else if (op == MP_BINARY_OP_SUBTRACT) {
ASM_SUB_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
- } else if (op == MP_BINARY_OP_MULTIPLY || op == MP_BINARY_OP_INPLACE_MULTIPLY) {
+ } else if (op == MP_BINARY_OP_MULTIPLY) {
ASM_MUL_REG_REG(emit->as, REG_ARG_2, reg_rhs);
emit_post_push_reg(emit, VTYPE_INT, REG_ARG_2);
} else if (MP_BINARY_OP_LESS <= op && op <= MP_BINARY_OP_NOT_EQUAL) {
diff --git a/py/formatfloat.c b/py/formatfloat.c
index 35cd5d51a..4228f99ff 100644
--- a/py/formatfloat.c
+++ b/py/formatfloat.c
@@ -30,6 +30,7 @@
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
+#include <math.h>
#include "py/formatfloat.h"
/***********************************************************************
@@ -68,12 +69,10 @@ union floatbits {
uint32_t u;
};
static inline int fp_signbit(float x) { union floatbits fb = {x}; return fb.u & FLT_SIGN_MASK; }
-static inline int fp_isspecial(float x) { union floatbits fb = {x}; return (fb.u & FLT_EXP_MASK) == FLT_EXP_MASK; }
-static inline int fp_isinf(float x) { union floatbits fb = {x}; return (fb.u & FLT_MAN_MASK) == 0; }
+#define fp_isnan(x) isnan(x)
+#define fp_isinf(x) isinf(x)
static inline int fp_iszero(float x) { union floatbits fb = {x}; return fb.u == 0; }
static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u < 0x3f800000; }
-// Assumes both fp_isspecial() and fp_isinf() were applied before
-#define fp_isnan(x) 1
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
@@ -82,9 +81,7 @@ static inline int fp_isless1(float x) { union floatbits fb = {x}; return fb.u <
#define FPROUND_TO_ONE 0.999999999995
#define FPDECEXP 256
#define FPMIN_BUF_SIZE 7 // +9e+199
-#include <math.h>
#define fp_signbit(x) signbit(x)
-#define fp_isspecial(x) 1
#define fp_isnan(x) isnan(x)
#define fp_isinf(x) isinf(x)
#define fp_iszero(x) (x == 0)
@@ -122,7 +119,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
}
return buf_size >= 2;
}
- if (fp_signbit(f)) {
+ if (fp_signbit(f) && !fp_isnan(f)) {
*s++ = '-';
f = -f;
} else {
@@ -135,7 +132,7 @@ int mp_format_float(FPTYPE f, char *buf, size_t buf_size, char fmt, int prec, ch
// It is buf_size minus room for the sign and null byte.
int buf_remaining = buf_size - 1 - (s - buf);
- if (fp_isspecial(f)) {
+ {
char uc = fmt & 0x20;
if (fp_isinf(f)) {
*s++ = 'I' ^ uc;
diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py
index 7249769f4..38fde1a9c 100644
--- a/py/makeqstrdata.py
+++ b/py/makeqstrdata.py
@@ -108,7 +108,15 @@ def parse_input_headers(infiles):
continue
# add the qstr to the list, with order number to retain original order in file
- qstrs[ident] = (len(qstrs), ident, qstr)
+ order = len(qstrs)
+ # but put special method names like __add__ at the top of list, so
+ # that their id's fit into a byte
+ if ident == "":
+ # Sort empty qstr above all still
+ order = -200000
+ elif ident.startswith("__"):
+ order -= 100000
+ qstrs[ident] = (order, ident, qstr)
if not qcfgs:
sys.stderr.write("ERROR: Empty preprocessor output - check for errors above\n")
diff --git a/py/mkenv.mk b/py/mkenv.mk
index 507fa6eab..5a118854a 100644
--- a/py/mkenv.mk
+++ b/py/mkenv.mk
@@ -68,13 +68,7 @@ LD += -m32
endif
MAKE_FROZEN = $(TOP)/tools/make-frozen.py
-# allow mpy-cross (for WSL) and mpy-cross.exe (for cygwin) to coexist
-ifeq ($(OS),Windows_NT)
-MPY_CROSS = $(TOP)/mpy-cross/mpy-cross.exe
-PROG_EXT = .exe
-else
MPY_CROSS = $(TOP)/mpy-cross/mpy-cross
-endif
MPY_TOOL = $(TOP)/tools/mpy-tool.py
all:
diff --git a/py/mkrules.mk b/py/mkrules.mk
index e26b94939..1d6f11fc9 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -144,13 +144,13 @@ $(PROG): $(OBJ)
# we may want to compile using Thumb, but link with non-Thumb libc.
$(Q)$(CC) -o $@ $^ $(LIB) $(LDFLAGS)
ifndef DEBUG
- $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)$(PROG_EXT)
+ $(Q)$(STRIP) $(STRIPFLAGS_EXTRA) $(PROG)
endif
- $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG)$(PROG_EXT)
+ $(Q)$(SIZE) $$(find $(BUILD) -path "$(BUILD)/build/frozen*.o") $(PROG)
clean: clean-prog
clean-prog:
- $(RM) -f $(PROG)$(PROG_EXT)
+ $(RM) -f $(PROG)
$(RM) -f $(PROG).map
.PHONY: clean-prog
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index 991feda8c..728309292 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -348,31 +348,16 @@ STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
if (MP_OBJ_IS_STR(o_in)) {
len = unichar_charlen(str, len);
if (len == 1) {
- if (!UTF8_IS_NONASCII(*str)) {
- goto return_first_byte;
- }
- mp_int_t ord = *str++ & 0x7F;
- for (mp_int_t mask = 0x40; ord & mask; mask >>= 1) {
- ord &= ~mask;
- }
- while (UTF8_IS_CONT(*str)) {
- ord = (ord << 6) | (*str++ & 0x3F);
- }
- return mp_obj_new_int(ord);
+ return mp_obj_new_int(utf8_get_char((const byte*)str));
}
- } else {
- // a bytes object
+ } else
+ #endif
+ {
+ // a bytes object, or a str without unicode support (don't sign extend the char)
if (len == 1) {
- return_first_byte:
return MP_OBJ_NEW_SMALL_INT(((const byte*)str)[0]);
}
}
- #else
- if (len == 1) {
- // don't sign extend when converting to ord
- return mp_obj_new_int(((const byte*)str)[0]);
- }
- #endif
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
mp_raise_TypeError("ord expects a character");
diff --git a/py/modmath.c b/py/modmath.c
index 909780596..56ceb14bd 100644
--- a/py/modmath.c
+++ b/py/modmath.c
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2013-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
@@ -40,14 +40,31 @@ STATIC NORETURN void math_error(void) {
mp_raise_ValueError("math domain error");
}
+STATIC mp_obj_t math_generic_1(mp_obj_t x_obj, mp_float_t (*f)(mp_float_t)) {
+ mp_float_t x = mp_obj_get_float(x_obj);
+ mp_float_t ans = f(x);
+ if ((isnan(ans) && !isnan(x)) || (isinf(ans) && !isinf(x))) {
+ math_error();
+ }
+ return mp_obj_new_float(ans);
+}
+
+STATIC mp_obj_t math_generic_2(mp_obj_t x_obj, mp_obj_t y_obj, mp_float_t (*f)(mp_float_t, mp_float_t)) {
+ mp_float_t x = mp_obj_get_float(x_obj);
+ mp_float_t y = mp_obj_get_float(y_obj);
+ mp_float_t ans = f(x, y);
+ if ((isnan(ans) && !isnan(x) && !isnan(y)) || (isinf(ans) && !isinf(x))) {
+ math_error();
+ }
+ return mp_obj_new_float(ans);
+}
+
#define MATH_FUN_1(py_name, c_name) \
- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \
+ return math_generic_1(x_obj, MICROPY_FLOAT_C_FUN(c_name)); \
+ } \
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
-#define MATH_FUN_2(py_name, c_name) \
- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_float(y_obj))); } \
- STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
-
#define MATH_FUN_1_TO_BOOL(py_name, c_name) \
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_bool(c_name(mp_obj_get_float(x_obj))); } \
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
@@ -56,23 +73,29 @@ STATIC NORETURN void math_error(void) {
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) \
- STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { \
- mp_float_t x = mp_obj_get_float(x_obj); \
- if (error_condition) { \
- math_error(); \
- } \
- return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(x)); \
+#define MATH_FUN_2(py_name, c_name) \
+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \
+ return math_generic_2(x_obj, y_obj, MICROPY_FLOAT_C_FUN(c_name)); \
} \
- STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
-#ifdef MP_NEED_LOG2
+#define MATH_FUN_2_FLT_INT(py_name, c_name) \
+ STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj, mp_obj_t y_obj) { \
+ return mp_obj_new_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj), mp_obj_get_int(y_obj))); \
+ } \
+ STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_math_## py_name ## _obj, mp_math_ ## py_name);
+
+#if MP_NEED_LOG2
+#undef log2
+#undef log2f
// 1.442695040888963407354163704 is 1/_M_LN2
-#define log2(x) (log(x) * 1.442695040888963407354163704)
+mp_float_t MICROPY_FLOAT_C_FUN(log2)(mp_float_t x) {
+ return MICROPY_FLOAT_C_FUN(log)(x) * MICROPY_FLOAT_CONST(1.442695040888963407354163704);
+}
#endif
// sqrt(x): returns the square root of x
-MATH_FUN_1_ERRCOND(sqrt, sqrt, (x < (mp_float_t)0.0))
+MATH_FUN_1(sqrt, sqrt)
// pow(x, y): returns x to the power of y
MATH_FUN_2(pow, pow)
// exp(x)
@@ -81,9 +104,9 @@ MATH_FUN_1(exp, exp)
// expm1(x)
MATH_FUN_1(expm1, expm1)
// log2(x)
-MATH_FUN_1_ERRCOND(log2, log2, (x <= (mp_float_t)0.0))
+MATH_FUN_1(log2, log2)
// log10(x)
-MATH_FUN_1_ERRCOND(log10, log10, (x <= (mp_float_t)0.0))
+MATH_FUN_1(log10, log10)
// cosh(x)
MATH_FUN_1(cosh, cosh)
// sinh(x)
@@ -114,9 +137,15 @@ MATH_FUN_2(atan2, atan2)
// ceil(x)
MATH_FUN_1_TO_INT(ceil, ceil)
// copysign(x, y)
-MATH_FUN_2(copysign, copysign)
+STATIC mp_float_t MICROPY_FLOAT_C_FUN(copysign_func)(mp_float_t x, mp_float_t y) {
+ return MICROPY_FLOAT_C_FUN(copysign)(x, y);
+}
+MATH_FUN_2(copysign, copysign_func)
// fabs(x)
-MATH_FUN_1(fabs, fabs)
+STATIC mp_float_t MICROPY_FLOAT_C_FUN(fabs_func)(mp_float_t x) {
+ return MICROPY_FLOAT_C_FUN(fabs)(x);
+}
+MATH_FUN_1(fabs, fabs_func)
// floor(x)
MATH_FUN_1_TO_INT(floor, floor) //TODO: delegate to x.__floor__() if x is not a float
// fmod(x, y)
@@ -130,7 +159,7 @@ MATH_FUN_1_TO_BOOL(isnan, isnan)
// trunc(x)
MATH_FUN_1_TO_INT(trunc, trunc)
// ldexp(x, exp)
-MATH_FUN_2(ldexp, ldexp)
+MATH_FUN_2_FLT_INT(ldexp, ldexp)
#if MICROPY_PY_MATH_SPECIAL_FUNCTIONS
// erf(x): return the error function of x
MATH_FUN_1(erf, erf)
diff --git a/py/mpconfig.h b/py/mpconfig.h
index cec9fb748..252ab7f37 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -775,16 +775,24 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (0)
#endif
-// Whether to support complete set of special methods
-// for user classes, or only the most used ones. "Reverse"
-// methods are controlled by MICROPY_PY_REVERSE_SPECIAL_METHODS
-// below.
+// Whether to support complete set of special methods for user
+// classes, or only the most used ones. "Inplace" methods are
+// controlled by MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS below.
+// "Reverse" methods are controlled by
+// MICROPY_PY_REVERSE_SPECIAL_METHODS below.
#ifndef MICROPY_PY_ALL_SPECIAL_METHODS
#define MICROPY_PY_ALL_SPECIAL_METHODS (0)
#endif
-// Whether to support reverse arithmetic operarions methods
-// (__radd__, etc.)
+// Whether to support all inplace arithmetic operarion methods
+// (__imul__, etc.)
+#ifndef MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS
+#define MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS (0)
+#endif
+
+// Whether to support reverse arithmetic operarion methods
+// (__radd__, etc.). Additionally gated by
+// MICROPY_PY_ALL_SPECIAL_METHODS.
#ifndef MICROPY_PY_REVERSE_SPECIAL_METHODS
#define MICROPY_PY_REVERSE_SPECIAL_METHODS (0)
#endif
@@ -1111,6 +1119,8 @@ typedef double mp_float_t;
#ifndef MICROPY_PY_USSL
#define MICROPY_PY_USSL (0)
+// Whether to add finaliser code to ussl objects
+#define MICROPY_PY_USSL_FINALISER (0)
#endif
#ifndef MICROPY_PY_WEBSOCKET
diff --git a/py/mpstate.h b/py/mpstate.h
index 1ffb5213c..23133cb7e 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -168,7 +168,7 @@ typedef struct _mp_state_vm_t {
// root pointers for extmod
#ifdef MICROPY_PY_OS_DUPTERM
- mp_obj_t term_obj;
+ mp_obj_t dupterm_objs[MICROPY_PY_OS_DUPTERM];
mp_obj_t dupterm_arr_obj;
#endif
diff --git a/py/nativeglue.c b/py/nativeglue.c
index 61b624ec7..e63c2fcda 100644
--- a/py/nativeglue.c
+++ b/py/nativeglue.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include "py/runtime.h"
+#include "py/smallint.h"
#include "py/emitglue.h"
#include "py/bc.h"
@@ -170,6 +171,8 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_obj_new_cell,
mp_make_closure_from_raw_code,
mp_setup_code_state,
+ mp_small_int_floor_divide,
+ mp_small_int_modulo,
};
/*
diff --git a/py/objarray.c b/py/objarray.c
index b8dca32f7..a1a979b56 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -286,7 +286,7 @@ STATIC mp_obj_t array_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs
// Otherwise, can only look for a scalar numeric value in an array
if (MP_OBJ_IS_INT(rhs_in) || mp_obj_is_float(rhs_in)) {
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
}
return mp_const_false;
diff --git a/py/objlist.c b/py/objlist.c
index c6e85f2c8..0cbf68c2f 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -158,7 +158,7 @@ STATIC mp_obj_t list_subscr(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_bound_slice_t slice;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice)) {
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
}
mp_int_t len_adj = slice.start - slice.stop;
@@ -198,7 +198,7 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
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)) {
- mp_raise_NotImplementedError("");
+ mp_raise_NotImplementedError(NULL);
}
mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
//printf("Len adj: %d\n", len_adj);
diff --git a/py/objtype.c b/py/objtype.c
index d57cec703..2fefc65ad 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -335,7 +335,9 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size
return MP_OBJ_FROM_PTR(o);
}
-const uint16_t mp_unary_op_method_name[] = {
+// Qstrs for special methods are guaranteed to have a small value, so we use byte
+// type to represent them.
+const byte mp_unary_op_method_name[MP_UNARY_OP_NUM_RUNTIME] = {
[MP_UNARY_OP_BOOL] = MP_QSTR___bool__,
[MP_UNARY_OP_LEN] = MP_QSTR___len__,
[MP_UNARY_OP_HASH] = MP_QSTR___hash__,
@@ -343,11 +345,11 @@ const uint16_t mp_unary_op_method_name[] = {
[MP_UNARY_OP_POSITIVE] = MP_QSTR___pos__,
[MP_UNARY_OP_NEGATIVE] = MP_QSTR___neg__,
[MP_UNARY_OP_INVERT] = MP_QSTR___invert__,
+ [MP_UNARY_OP_ABS] = MP_QSTR___abs__,
#endif
#if MICROPY_PY_SYS_GETSIZEOF
- [MP_UNARY_OP_SIZEOF] = MP_QSTR_getsizeof,
+ [MP_UNARY_OP_SIZEOF] = MP_QSTR___sizeof__,
#endif
- [MP_UNARY_OP_NOT] = MP_QSTR_, // don't need to implement this, used to make sure array has full size
};
STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
@@ -409,59 +411,69 @@ STATIC mp_obj_t instance_unary_op(mp_unary_op_t op, mp_obj_t self_in) {
}
}
-const uint16_t mp_binary_op_method_name[] = {
- /*
- MP_BINARY_OP_OR,
- MP_BINARY_OP_XOR,
- MP_BINARY_OP_AND,
- MP_BINARY_OP_LSHIFT,
- MP_BINARY_OP_RSHIFT,
- */
+// Binary-op enum values not listed here will have the default value of 0 in the
+// table, corresponding to MP_QSTR_NULL, and are therefore unsupported (a lookup will
+// fail). They can be added at the expense of code size for the qstr.
+// Qstrs for special methods are guaranteed to have a small value, so we use byte
+// type to represent them.
+const byte mp_binary_op_method_name[MP_BINARY_OP_NUM_RUNTIME] = {
+ [MP_BINARY_OP_LESS] = MP_QSTR___lt__,
+ [MP_BINARY_OP_MORE] = MP_QSTR___gt__,
+ [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
+ [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__,
+ [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__,
+ // MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result
+ [MP_BINARY_OP_IN] = MP_QSTR___contains__,
+
+ // All inplace methods are optional, and normal methods will be used
+ // as a fallback.
+ [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__,
+ [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__,
+ #if MICROPY_PY_ALL_INPLACE_SPECIAL_METHODS
+ [MP_BINARY_OP_INPLACE_MULTIPLY] = MP_QSTR___imul__,
+ [MP_BINARY_OP_INPLACE_FLOOR_DIVIDE] = MP_QSTR___ifloordiv__,
+ [MP_BINARY_OP_INPLACE_TRUE_DIVIDE] = MP_QSTR___itruediv__,
+ [MP_BINARY_OP_INPLACE_MODULO] = MP_QSTR___imod__,
+ [MP_BINARY_OP_INPLACE_POWER] = MP_QSTR___ipow__,
+ [MP_BINARY_OP_INPLACE_OR] = MP_QSTR___ior__,
+ [MP_BINARY_OP_INPLACE_XOR] = MP_QSTR___ixor__,
+ [MP_BINARY_OP_INPLACE_AND] = MP_QSTR___iand__,
+ [MP_BINARY_OP_INPLACE_LSHIFT] = MP_QSTR___ilshift__,
+ [MP_BINARY_OP_INPLACE_RSHIFT] = MP_QSTR___irshift__,
+ #endif
+
[MP_BINARY_OP_ADD] = MP_QSTR___add__,
[MP_BINARY_OP_SUBTRACT] = MP_QSTR___sub__,
#if MICROPY_PY_ALL_SPECIAL_METHODS
[MP_BINARY_OP_MULTIPLY] = MP_QSTR___mul__,
[MP_BINARY_OP_FLOOR_DIVIDE] = MP_QSTR___floordiv__,
[MP_BINARY_OP_TRUE_DIVIDE] = MP_QSTR___truediv__,
+ [MP_BINARY_OP_MODULO] = MP_QSTR___mod__,
+ [MP_BINARY_OP_DIVMOD] = MP_QSTR___divmod__,
+ [MP_BINARY_OP_POWER] = MP_QSTR___pow__,
+ [MP_BINARY_OP_OR] = MP_QSTR___or__,
+ [MP_BINARY_OP_XOR] = MP_QSTR___xor__,
+ [MP_BINARY_OP_AND] = MP_QSTR___and__,
+ [MP_BINARY_OP_LSHIFT] = MP_QSTR___lshift__,
+ [MP_BINARY_OP_RSHIFT] = MP_QSTR___rshift__,
#endif
- /*
- MP_BINARY_OP_MODULO,
- MP_BINARY_OP_POWER,
- MP_BINARY_OP_DIVMOD,
- MP_BINARY_OP_INPLACE_OR,
- MP_BINARY_OP_INPLACE_XOR,
- MP_BINARY_OP_INPLACE_AND,
- MP_BINARY_OP_INPLACE_LSHIFT,
- MP_BINARY_OP_INPLACE_RSHIFT,*/
- #if MICROPY_PY_ALL_SPECIAL_METHODS
- [MP_BINARY_OP_INPLACE_ADD] = MP_QSTR___iadd__,
- [MP_BINARY_OP_INPLACE_SUBTRACT] = MP_QSTR___isub__,
- #endif
- /*MP_BINARY_OP_INPLACE_MULTIPLY,
- MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,
- MP_BINARY_OP_INPLACE_TRUE_DIVIDE,
- MP_BINARY_OP_INPLACE_MODULO,
- MP_BINARY_OP_INPLACE_POWER,*/
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
[MP_BINARY_OP_REVERSE_ADD] = MP_QSTR___radd__,
[MP_BINARY_OP_REVERSE_SUBTRACT] = MP_QSTR___rsub__,
+ #if MICROPY_PY_ALL_SPECIAL_METHODS
[MP_BINARY_OP_REVERSE_MULTIPLY] = MP_QSTR___rmul__,
+ [MP_BINARY_OP_REVERSE_FLOOR_DIVIDE] = MP_QSTR___rfloordiv__,
+ [MP_BINARY_OP_REVERSE_TRUE_DIVIDE] = MP_QSTR___rtruediv__,
+ [MP_BINARY_OP_REVERSE_MODULO] = MP_QSTR___rmod__,
+ [MP_BINARY_OP_REVERSE_POWER] = MP_QSTR___rpow__,
+ [MP_BINARY_OP_REVERSE_OR] = MP_QSTR___ror__,
+ [MP_BINARY_OP_REVERSE_XOR] = MP_QSTR___rxor__,
+ [MP_BINARY_OP_REVERSE_AND] = MP_QSTR___rand__,
+ [MP_BINARY_OP_REVERSE_LSHIFT] = MP_QSTR___rlshift__,
+ [MP_BINARY_OP_REVERSE_RSHIFT] = MP_QSTR___rrshift__,
+ #endif
#endif
-
- [MP_BINARY_OP_LESS] = MP_QSTR___lt__,
- [MP_BINARY_OP_MORE] = MP_QSTR___gt__,
- [MP_BINARY_OP_EQUAL] = MP_QSTR___eq__,
- [MP_BINARY_OP_LESS_EQUAL] = MP_QSTR___le__,
- [MP_BINARY_OP_MORE_EQUAL] = MP_QSTR___ge__,
- /*
- MP_BINARY_OP_NOT_EQUAL, // a != b calls a == b and inverts result
- */
- [MP_BINARY_OP_IN] = MP_QSTR___contains__,
- /*
- MP_BINARY_OP_IS,
- */
- [MP_BINARY_OP_LAST] = 0, // used to make sure array has full size, TODO: FIXME
};
STATIC mp_obj_t instance_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 42efcbfbb..477ba7501 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -39,7 +39,7 @@
#include "py/smallint.h"
// The current version of .mpy files
-#define MPY_VERSION (2)
+#define MPY_VERSION (3)
// The feature flags byte encodes the compile-time config options that
// affect the generate bytecode.
diff --git a/py/runtime.c b/py/runtime.c
index 4af17dd09..cbec82f17 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -108,6 +108,13 @@ void mp_init(void) {
MP_STATE_VM(mp_module_builtins_override_dict) = NULL;
#endif
+ #ifdef MICROPY_PY_OS_DUPTERM
+ for (size_t i = 0; i < MICROPY_PY_OS_DUPTERM; ++i) {
+ MP_STATE_VM(dupterm_objs[i]) = MP_OBJ_NULL;
+ }
+ MP_STATE_VM(dupterm_arr_obj) = MP_OBJ_NULL;
+ #endif
+
#ifdef MICROPY_FSUSERMOUNT
// zero out the pointers to the user-mounted devices
memset(MP_STATE_VM(fs_user_mount) + MICROPY_FATFS_NUM_PERSISTENT, 0,
diff --git a/py/runtime.h b/py/runtime.h
index 79f5cbc92..a8b6312ff 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -57,8 +57,8 @@ typedef struct _mp_arg_t {
} mp_arg_t;
// Tables mapping operator enums to qstrs, defined in objtype.c
-extern const uint16_t mp_unary_op_method_name[];
-extern const uint16_t mp_binary_op_method_name[];
+extern const byte mp_unary_op_method_name[];
+extern const byte mp_binary_op_method_name[];
void mp_init(void);
void mp_deinit(void);
diff --git a/py/runtime0.h b/py/runtime0.h
index 8e95b68cf..4709430fb 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -53,41 +53,38 @@ typedef enum {
MP_UNARY_OP_NOT,
// Following ops cannot appear in the bytecode
- MP_UNARY_OP_NON_BYTECODE,
+ MP_UNARY_OP_NUM_BYTECODE,
- MP_UNARY_OP_BOOL = MP_UNARY_OP_NON_BYTECODE, // __bool__
+ MP_UNARY_OP_BOOL = MP_UNARY_OP_NUM_BYTECODE, // __bool__
MP_UNARY_OP_LEN, // __len__
MP_UNARY_OP_HASH, // __hash__; must return a small int
MP_UNARY_OP_ABS, // __abs__
MP_UNARY_OP_SIZEOF, // for sys.getsizeof()
+
+ MP_UNARY_OP_NUM_RUNTIME,
} mp_unary_op_t;
-// Note: the first 35 of these are used in bytecode and changing
+// Note: the first 9+12+12 of these are used in bytecode and changing
// them requires changing the bytecode version.
typedef enum {
- // Relational operations, should return a bool
+ // 9 relational operations, should return a bool
MP_BINARY_OP_LESS,
MP_BINARY_OP_MORE,
MP_BINARY_OP_EQUAL,
MP_BINARY_OP_LESS_EQUAL,
MP_BINARY_OP_MORE_EQUAL,
MP_BINARY_OP_NOT_EQUAL,
-
MP_BINARY_OP_IN,
MP_BINARY_OP_IS,
MP_BINARY_OP_EXCEPTION_MATCH,
- // these are not supported by the runtime and must be synthesised by the emitter
- MP_BINARY_OP_NOT_IN,
- MP_BINARY_OP_IS_NOT,
- // Arithmetic operations
+ // 12 inplace arithmetic operations
MP_BINARY_OP_INPLACE_OR,
MP_BINARY_OP_INPLACE_XOR,
MP_BINARY_OP_INPLACE_AND,
MP_BINARY_OP_INPLACE_LSHIFT,
MP_BINARY_OP_INPLACE_RSHIFT,
MP_BINARY_OP_INPLACE_ADD,
-
MP_BINARY_OP_INPLACE_SUBTRACT,
MP_BINARY_OP_INPLACE_MULTIPLY,
MP_BINARY_OP_INPLACE_FLOOR_DIVIDE,
@@ -95,13 +92,13 @@ typedef enum {
MP_BINARY_OP_INPLACE_MODULO,
MP_BINARY_OP_INPLACE_POWER,
+ // 12 normal arithmetic operations
MP_BINARY_OP_OR,
MP_BINARY_OP_XOR,
MP_BINARY_OP_AND,
MP_BINARY_OP_LSHIFT,
MP_BINARY_OP_RSHIFT,
MP_BINARY_OP_ADD,
-
MP_BINARY_OP_SUBTRACT,
MP_BINARY_OP_MULTIPLY,
MP_BINARY_OP_FLOOR_DIVIDE,
@@ -111,16 +108,16 @@ typedef enum {
// Operations below this line don't appear in bytecode, they
// just identify special methods.
+ MP_BINARY_OP_NUM_BYTECODE,
// MP_BINARY_OP_REVERSE_* must follow immediately after MP_BINARY_OP_*
#if MICROPY_PY_REVERSE_SPECIAL_METHODS
- MP_BINARY_OP_REVERSE_OR,
+ MP_BINARY_OP_REVERSE_OR = MP_BINARY_OP_NUM_BYTECODE,
MP_BINARY_OP_REVERSE_XOR,
MP_BINARY_OP_REVERSE_AND,
MP_BINARY_OP_REVERSE_LSHIFT,
MP_BINARY_OP_REVERSE_RSHIFT,
MP_BINARY_OP_REVERSE_ADD,
-
MP_BINARY_OP_REVERSE_SUBTRACT,
MP_BINARY_OP_REVERSE_MULTIPLY,
MP_BINARY_OP_REVERSE_FLOOR_DIVIDE,
@@ -129,9 +126,18 @@ typedef enum {
MP_BINARY_OP_REVERSE_POWER,
#endif
- MP_BINARY_OP_DIVMOD, // not emitted by the compiler but supported by the runtime
+ // This is not emitted by the compiler but is supported by the runtime
+ MP_BINARY_OP_DIVMOD
+ #if !MICROPY_PY_REVERSE_SPECIAL_METHODS
+ = MP_BINARY_OP_NUM_BYTECODE
+ #endif
+ ,
+
+ MP_BINARY_OP_NUM_RUNTIME,
- MP_BINARY_OP_LAST,
+ // These 2 are not supported by the runtime and must be synthesised by the emitter
+ MP_BINARY_OP_NOT_IN,
+ MP_BINARY_OP_IS_NOT,
} mp_binary_op_t;
typedef enum {
@@ -181,6 +187,8 @@ typedef enum {
MP_F_NEW_CELL,
MP_F_MAKE_CLOSURE_FROM_RAW_CODE,
MP_F_SETUP_CODE_STATE,
+ MP_F_SMALL_INT_FLOOR_DIVIDE,
+ MP_F_SMALL_INT_MODULO,
MP_F_NUMBER_OF,
} mp_fun_kind_t;
diff --git a/py/showbc.c b/py/showbc.c
index 728d8d983..3deb18cd3 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -539,9 +539,9 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("LOAD_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_LOAD_FAST_MULTI);
} else if (ip[-1] < MP_BC_STORE_FAST_MULTI + 16) {
printf("STORE_FAST " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_STORE_FAST_MULTI);
- } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE) {
+ } else if (ip[-1] < MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE) {
printf("UNARY_OP " UINT_FMT, (mp_uint_t)ip[-1] - MP_BC_UNARY_OP_MULTI);
- } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + 36) {
+ } else if (ip[-1] < MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE) {
mp_uint_t op = ip[-1] - MP_BC_BINARY_OP_MULTI;
printf("BINARY_OP " UINT_FMT " %s", op, qstr_str(mp_binary_op_method_name[op]));
} else {
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index e634e2b41..615f4e2ce 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -109,8 +109,8 @@ static const void *const entry_table[256] = {
[MP_BC_LOAD_CONST_SMALL_INT_MULTI ... MP_BC_LOAD_CONST_SMALL_INT_MULTI + 63] = &&entry_MP_BC_LOAD_CONST_SMALL_INT_MULTI,
[MP_BC_LOAD_FAST_MULTI ... MP_BC_LOAD_FAST_MULTI + 15] = &&entry_MP_BC_LOAD_FAST_MULTI,
[MP_BC_STORE_FAST_MULTI ... MP_BC_STORE_FAST_MULTI + 15] = &&entry_MP_BC_STORE_FAST_MULTI,
- [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NON_BYTECODE - 1] = &&entry_MP_BC_UNARY_OP_MULTI,
- [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + 35] = &&entry_MP_BC_BINARY_OP_MULTI,
+ [MP_BC_UNARY_OP_MULTI ... MP_BC_UNARY_OP_MULTI + MP_UNARY_OP_NUM_BYTECODE - 1] = &&entry_MP_BC_UNARY_OP_MULTI,
+ [MP_BC_BINARY_OP_MULTI ... MP_BC_BINARY_OP_MULTI + MP_BINARY_OP_NUM_BYTECODE - 1] = &&entry_MP_BC_BINARY_OP_MULTI,
};
#if __clang__
diff --git a/shared-module/multiterminal/__init__.c b/shared-module/multiterminal/__init__.c
index 5f6e298f0..361a6dcc7 100644
--- a/shared-module/multiterminal/__init__.c
+++ b/shared-module/multiterminal/__init__.c
@@ -30,21 +30,21 @@
#include "shared-bindings/multiterminal/__init__.h"
mp_obj_t shared_module_multiterminal_get_secondary_terminal() {
- if (MP_STATE_PORT(term_obj) == MP_OBJ_NULL) {
+ if (MP_STATE_VM(dupterm_objs[0]) == MP_OBJ_NULL) {
return mp_const_none;
} else {
- return MP_STATE_PORT(term_obj);
+ return MP_STATE_VM(dupterm_objs[0]);
}
}
void shared_module_multiterminal_set_secondary_terminal(mp_obj_t secondary_terminal) {
- MP_STATE_PORT(term_obj) = secondary_terminal;
+ MP_STATE_VM(dupterm_objs[0]) = secondary_terminal;
if (MP_STATE_PORT(dupterm_arr_obj) == MP_OBJ_NULL) {
MP_STATE_PORT(dupterm_arr_obj) = mp_obj_new_bytearray(1, "");
}
}
void shared_module_multiterminal_clear_secondary_terminal() {
- MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
+ MP_STATE_VM(dupterm_objs[0]) = MP_OBJ_NULL;
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
}
diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp
index 09fbff6fa..1274cda00 100644
--- a/tests/cmdline/cmd_showbc.py.exp
+++ b/tests/cmdline/cmd_showbc.py.exp
@@ -43,9 +43,9 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
bc=\\d\+ line=126
00 LOAD_CONST_NONE
01 LOAD_CONST_FALSE
-02 BINARY_OP 28 __add__
+02 BINARY_OP 26 __add__
03 LOAD_CONST_TRUE
-04 BINARY_OP 28 __add__
+04 BINARY_OP 26 __add__
05 STORE_FAST 0
06 LOAD_CONST_SMALL_INT 0
07 STORE_FAST 0
@@ -84,7 +84,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
\\d\+ STORE_FAST 7
\\d\+ LOAD_FAST 0
\\d\+ LOAD_DEREF 14
-\\d\+ BINARY_OP 28 __add__
+\\d\+ BINARY_OP 26 __add__
\\d\+ STORE_FAST 8
\\d\+ LOAD_FAST 0
\\d\+ UNARY_OP 1
@@ -132,7 +132,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
\\d\+ DUP_TOP_TWO
\\d\+ LOAD_SUBSCR
\\d\+ LOAD_FAST 12
-\\d\+ BINARY_OP 16 __iadd__
+\\d\+ BINARY_OP 14 __iadd__
\\d\+ ROT_THREE
\\d\+ STORE_SUBSCR
\\d\+ LOAD_DEREF 14
@@ -369,7 +369,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
42 STORE_FAST_N 19
44 LOAD_FAST 9
45 LOAD_FAST_N 19
-47 BINARY_OP 28 __add__
+47 BINARY_OP 26 __add__
48 POP_TOP
49 LOAD_CONST_NONE
50 RETURN_VALUE
@@ -521,7 +521,7 @@ arg names: *
bc=\\d\+ line=113
00 LOAD_DEREF 0
02 LOAD_CONST_SMALL_INT 1
-03 BINARY_OP 28 __add__
+03 BINARY_OP 26 __add__
04 STORE_FAST 1
05 LOAD_CONST_SMALL_INT 1
06 STORE_DEREF 0
@@ -540,7 +540,7 @@ arg names: * b
bc=\\d\+ line=139
00 LOAD_FAST 1
01 LOAD_DEREF 0
-03 BINARY_OP 28 __add__
+03 BINARY_OP 26 __add__
04 RETURN_VALUE
mem: total=\\d\+, current=\\d\+, peak=\\d\+
stack: \\d\+ out of \\d\+
diff --git a/tests/extmod/ure1.py b/tests/extmod/ure1.py
index 6075990fc..54471ed4f 100644
--- a/tests/extmod/ure1.py
+++ b/tests/extmod/ure1.py
@@ -48,7 +48,12 @@ m = r.match("d")
print(m.group(0))
m = r.match("A")
print(m.group(0))
+print("===")
+# '-' character within character class block
+print(re.match("[-a]+", "-a]d").group(0))
+print(re.match("[a-]+", "-a]d").group(0))
+print("===")
r = re.compile("o+")
m = r.search("foobar")
diff --git a/tests/float/complex1.py b/tests/float/complex1.py
index 854410545..479b4b348 100644
--- a/tests/float/complex1.py
+++ b/tests/float/complex1.py
@@ -59,6 +59,7 @@ ans = (-1.2) ** -3.4; print("%.5g %.5g" % (ans.real, ans.imag))
# check printing of inf/nan
print(float('nan') * 1j)
+print(float('-nan') * 1j)
print(float('inf') * (1 + 1j))
print(float('-inf') * (1 + 1j))
diff --git a/tests/float/float1.py b/tests/float/float1.py
index 137dacc23..c64f965a7 100644
--- a/tests/float/float1.py
+++ b/tests/float/float1.py
@@ -21,6 +21,7 @@ print(float("INF"))
print(float("infinity"))
print(float("INFINITY"))
print(float("nan"))
+print(float("-nan"))
print(float("NaN"))
try:
float("")
diff --git a/tests/float/math_domain.py b/tests/float/math_domain.py
new file mode 100644
index 000000000..0cf10fb2a
--- /dev/null
+++ b/tests/float/math_domain.py
@@ -0,0 +1,51 @@
+# Tests domain errors in math functions
+
+try:
+ import math
+except ImportError:
+ print("SKIP")
+ raise SystemExit
+
+inf = float('inf')
+nan = float('nan')
+
+# single argument functions
+for name, f, args in (
+ ('fabs', math.fabs, ()),
+ ('ceil', math.ceil, ()),
+ ('floor', math.floor, ()),
+ ('trunc', math.trunc, ()),
+ ('sqrt', math.sqrt, (-1, 0)),
+ ('exp', math.exp, ()),
+ ('sin', math.sin, ()),
+ ('cos', math.cos, ()),
+ ('tan', math.tan, ()),
+ ('asin', math.asin, (-1.1, 1, 1.1)),
+ ('acos', math.acos, (-1.1, 1, 1.1)),
+ ('atan', math.atan, ()),
+ ('ldexp', lambda x: math.ldexp(x, 0), ()),
+ ('radians', math.radians, ()),
+ ('degrees', math.degrees, ()),
+ ):
+ for x in args + (inf, nan):
+ try:
+ ans = f(x)
+ print('%.4f' % ans)
+ except ValueError:
+ print(name, 'ValueError')
+ except OverflowError:
+ print(name, 'OverflowError')
+
+# double argument functions
+for name, f, args in (
+ ('pow', math.pow, ((0, 2), (-1, 2), (0, -1), (-1, 2.3))),
+ ('fmod', math.fmod, ((1.2, inf), (1.2, 0), (inf, 1.2))),
+ ('atan2', math.atan2, ((0, 0),)),
+ ('copysign', math.copysign, ()),
+ ):
+ for x in args + ((0, inf), (inf, 0), (inf, inf), (inf, nan), (nan, inf), (nan, nan)):
+ try:
+ ans = f(*x)
+ print('%.4f' % ans)
+ except ValueError:
+ print(name, 'ValueError')
diff --git a/tests/float/math_domain_special.py b/tests/float/math_domain_special.py
new file mode 100644
index 000000000..388920350
--- /dev/null
+++ b/tests/float/math_domain_special.py
@@ -0,0 +1,36 @@
+# Tests domain errors in special math functions
+
+try:
+ import math
+ math.erf
+except (ImportError, AttributeError):
+ print("SKIP")
+ raise SystemExit
+
+inf = float('inf')
+nan = float('nan')
+
+# single argument functions
+for name, f, args in (
+ ('expm1', math.exp, ()),
+ ('log2', math.log2, (-1, 0)),
+ ('log10', math.log10, (-1, 0)),
+ ('sinh', math.sinh, ()),
+ ('cosh', math.cosh, ()),
+ ('tanh', math.tanh, ()),
+ ('asinh', math.asinh, ()),
+ ('acosh', math.acosh, (-1, 0.9, 1)),
+ ('atanh', math.atanh, (-1, 1)),
+ ('erf', math.erf, ()),
+ ('erfc', math.erfc, ()),
+ ('gamma', math.gamma, (-2, -1, 0, 1)),
+ ('lgamma', math.lgamma, (-2, -1, 0, 1)),
+ ):
+ for x in args + (inf, nan):
+ try:
+ ans = f(x)
+ print('%.4f' % ans)
+ except ValueError:
+ print(name, 'ValueError')
+ except OverflowError:
+ print(name, 'OverflowError')
diff --git a/tests/micropython/viper_binop_divmod.py b/tests/micropython/viper_binop_divmod.py
new file mode 100644
index 000000000..822424982
--- /dev/null
+++ b/tests/micropython/viper_binop_divmod.py
@@ -0,0 +1,18 @@
+# test floor-division and modulo operators
+
+@micropython.viper
+def div(x:int, y:int) -> int:
+ return x // y
+
+@micropython.viper
+def mod(x:int, y:int) -> int:
+ return x % y
+
+def dm(x, y):
+ print(div(x, y), mod(x, y))
+
+for x in (-6, 6):
+ for y in range(-7, 8):
+ if y == 0:
+ continue
+ dm(x, y)
diff --git a/tests/micropython/viper_binop_divmod.py.exp b/tests/micropython/viper_binop_divmod.py.exp
new file mode 100644
index 000000000..4fc971d46
--- /dev/null
+++ b/tests/micropython/viper_binop_divmod.py.exp
@@ -0,0 +1,28 @@
+0 -6
+1 0
+1 -1
+1 -2
+2 0
+3 0
+6 0
+-6 0
+-3 0
+-2 0
+-2 2
+-2 4
+-1 0
+-1 1
+-1 -1
+-1 0
+-2 -4
+-2 -2
+-2 0
+-3 0
+-6 0
+6 0
+3 0
+2 0
+1 2
+1 1
+1 0
+0 6
diff --git a/tests/net_inet/test_tls_sites.py b/tests/net_inet/test_tls_sites.py
index 67345fd0b..bf8071d08 100644
--- a/tests/net_inet/test_tls_sites.py
+++ b/tests/net_inet/test_tls_sites.py
@@ -6,6 +6,8 @@ try:
import ussl as ssl
except:
import ssl
+ # CPython only supports server_hostname with SSLContext
+ ssl = ssl.SSLContext()
def test_one(site, opts):
@@ -22,7 +24,7 @@ def test_one(site, opts):
else:
s = ssl.wrap_socket(s)
- s.write(b"GET / HTTP/1.0\r\n\r\n")
+ s.write(b"GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % bytes(site, 'latin'))
resp = s.read(4096)
# print(resp)
@@ -34,6 +36,7 @@ SITES = [
"google.com",
"www.google.com",
"api.telegram.org",
+ {"host": "api.pushbullet.com", "sni": True},
# "w9rybpfril.execute-api.ap-southeast-2.amazonaws.com",
{"host": "w9rybpfril.execute-api.ap-southeast-2.amazonaws.com", "sni": True},
]
diff --git a/tests/net_inet/test_tls_sites.py.exp b/tests/net_inet/test_tls_sites.py.exp
index 12732d1fa..2f3c113d2 100644
--- a/tests/net_inet/test_tls_sites.py.exp
+++ b/tests/net_inet/test_tls_sites.py.exp
@@ -1,4 +1,5 @@
google.com ok
www.google.com ok
api.telegram.org ok
+api.pushbullet.com ok
w9rybpfril.execute-api.ap-southeast-2.amazonaws.com ok
diff --git a/tests/run-tests b/tests/run-tests
index 4024d61df..f1035c435 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -506,9 +506,12 @@ def main():
# we need to access feature_check's from the same directory as the
# run-tests script itself.
base_path = os.path.dirname(sys.argv[0]) or "."
- res = run_tests(pyb, tests, args, base_path)
- if pyb:
- pyb.close()
+ try:
+ res = run_tests(pyb, tests, args, base_path)
+ finally:
+ if pyb:
+ pyb.close()
+
if not res:
sys.exit(1)
diff --git a/tests/unix/extra_coverage.py.exp b/tests/unix/extra_coverage.py.exp
index 4c4f66663..1db46ab8f 100644
--- a/tests/unix/extra_coverage.py.exp
+++ b/tests/unix/extra_coverage.py.exp
@@ -39,8 +39,8 @@ ementation
0
0
# runtime utils
-TypeError: unsupported type for : 'str'
-TypeError: unsupported types for : 'str', 'str'
+TypeError: unsupported type for __abs__: 'str'
+TypeError: unsupported types for __divmod__: 'str', 'str'
Warning: test
# format float
?
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index ded962487..ac7b2c1cc 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -57,7 +57,7 @@ class FreezeError(Exception):
return 'error while freezing %s: %s' % (self.rawcode.source_file, self.msg)
class Config:
- MPY_VERSION = 2
+ MPY_VERSION = 3
MICROPY_LONGINT_IMPL_NONE = 0
MICROPY_LONGINT_IMPL_LONGLONG = 1
MICROPY_LONGINT_IMPL_MPZ = 2
@@ -105,7 +105,7 @@ def make_opcode_format():
OC4(O, O, U, U), # 0x38-0x3b
OC4(U, O, B, O), # 0x3c-0x3f
OC4(O, B, B, O), # 0x40-0x43
- OC4(B, B, O, U), # 0x44-0x47
+ OC4(B, B, O, B), # 0x44-0x47
OC4(U, U, U, U), # 0x48-0x4b
OC4(U, U, U, U), # 0x4c-0x4f
OC4(V, V, U, V), # 0x50-0x53
@@ -145,7 +145,7 @@ def make_opcode_format():
OC4(B, B, B, B), # 0xcc-0xcf
OC4(B, B, B, B), # 0xd0-0xd3
- OC4(B, B, B, B), # 0xd4-0xd7
+ OC4(U, U, U, B), # 0xd4-0xd7
OC4(B, B, B, B), # 0xd8-0xdb
OC4(B, B, B, B), # 0xdc-0xdf
@@ -156,7 +156,7 @@ def make_opcode_format():
OC4(B, B, B, B), # 0xf0-0xf3
OC4(B, B, B, B), # 0xf4-0xf7
- OC4(B, B, B, U), # 0xf8-0xfb
+ OC4(U, U, U, U), # 0xf8-0xfb
OC4(U, U, U, U), # 0xfc-0xff
))
diff --git a/tools/pyboard.py b/tools/pyboard.py
index d15f520ac..16ee41f70 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -5,6 +5,7 @@
# The MIT License (MIT)
#
# Copyright (c) 2014-2016 Damien P. George
+# Copyright (c) 2017 Paul Sokolovsky
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
@@ -28,7 +29,11 @@
pyboard interface
This module provides the Pyboard class, used to communicate with and
-control the pyboard over a serial USB connection.
+control a MicroPython device over a communication channel. Both real
+boards and emulated devices (e.g. running in QEMU) are supported.
+Various communication channels are supported, including a serial
+connection, telnet-style network connection, external process
+connection.
Example usage:
@@ -343,7 +348,7 @@ class Pyboard:
# check if we could exec command
data = self.serial.read(2)
if data != b'OK':
- raise PyboardError('could not exec command (response: %s)' % data)
+ raise PyboardError('could not exec command (response: %r)' % data)
def exec_raw(self, command, timeout=10, data_consumer=None):
self.exec_raw_no_follow(command);