Merge branch 'master' into nrf5_no_sdk

This commit is contained in:
Glenn Ruben Bakke 2017-04-23 18:39:24 +02:00
commit 9d91e990f7
86 changed files with 950 additions and 545 deletions

View File

@ -59,8 +59,6 @@ typedef struct _pyb_i2c_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
#define PYBI2C_MASTER (0)
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
@ -79,7 +77,6 @@ typedef struct _pyb_i2c_obj_t {
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
STATIC const mp_obj_t pyb_i2c_def_pin[2] = {&pin_GP13, &pin_GP23};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@ -289,33 +286,34 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
mp_printf(print, "I2C(0, I2C.MASTER, baudrate=%u)", self->baudrate);
mp_printf(print, "I2C(0, baudrate=%u)", self->baudrate);
} else {
mp_print_str(print, "I2C(0)");
}
}
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *args) {
// verify that mode is master
if (args[0].u_int != PYBI2C_MASTER) {
goto invalid_args;
}
STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
enum { ARG_scl, ARG_sda, ARG_freq };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// make sure the baudrate is between the valid range
self->baudrate = MIN(MAX(args[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
self->baudrate = MIN(MAX(args[ARG_freq].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
// assign the pins
mp_obj_t pins_o = args[2].u_obj;
if (pins_o != mp_const_none) {
mp_obj_t *pins;
if (pins_o == MP_OBJ_NULL) {
// use the default pins
pins = (mp_obj_t *)pyb_i2c_def_pin;
} else {
mp_obj_get_array_fixed_n(pins_o, 2, &pins);
}
pin_assign_pins_af (pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
mp_obj_t pins[2] = {&pin_GP13, &pin_GP23}; // default (SDA, SCL) pins
if (args[ARG_scl].u_obj != MP_OBJ_NULL) {
pins[1] = args[ARG_scl].u_obj;
}
if (args[ARG_sda].u_obj != MP_OBJ_NULL) {
pins[0] = args[ARG_sda].u_obj;
}
pin_assign_pins_af(pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
// init the I2C bus
i2c_init(self);
@ -324,44 +322,34 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *arg
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
return mp_const_none;
invalid_args:
mp_raise_ValueError(mpexception_value_invalid_arguments);
}
STATIC const mp_arg_t pyb_i2c_init_args[] = {
{ MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
{ MP_QSTR_mode, MP_ARG_INT, {.u_int = PYBI2C_MASTER} },
{ MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
{ MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
};
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
// check the id argument, if given
if (n_args > 0) {
if (all_args[0] != MP_OBJ_NEW_SMALL_INT(0)) {
mp_raise_OSError(MP_ENODEV);
}
--n_args;
++all_args;
}
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args)];
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_i2c_init_args, args);
// check the peripheral id
if (args[0].u_int != 0) {
mp_raise_OSError(MP_ENODEV);
}
// setup the object
pyb_i2c_obj_t *self = &pyb_i2c_obj;
self->base.type = &pyb_i2c_type;
// start the peripheral
pyb_i2c_init_helper(self, &args[1]);
pyb_i2c_init_helper(self, n_args, all_args, &kw_args);
return (mp_obj_t)self;
}
STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
// parse args
mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args) - 1];
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_i2c_init_args[1], args);
return pyb_i2c_init_helper(pos_args[0], args);
STATIC mp_obj_t pyb_i2c_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
return pyb_i2c_init_helper(pos_args[0], n_args - 1, pos_args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
@ -489,7 +477,7 @@ STATIC mp_obj_t pyb_i2c_readfrom_mem_into(mp_uint_t n_args, const mp_obj_t *pos_
// get the buffer to read into
vstr_t vstr;
pyb_i2c_readmem_into (args, &vstr);
return mp_obj_new_int(vstr.len);
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_into_obj, 1, pyb_i2c_readfrom_mem_into);
@ -513,8 +501,7 @@ STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args,
// write the register address to write to.
if (pyb_i2c_mem_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len)) {
// return the number of bytes written
return mp_obj_new_int(bufinfo.len);
return mp_const_none;
}
mp_raise_OSError(MP_EIO);
@ -532,9 +519,6 @@ STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&pyb_i2c_readfrom_mem_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem_into), (mp_obj_t)&pyb_i2c_readfrom_mem_into_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_writeto_mem), (mp_obj_t)&pyb_i2c_writeto_mem_obj },
// class constants
{ MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);

View File

@ -88,7 +88,7 @@ Use the :mod:`time <utime>` module::
Timers
------
Virtual (RTOS-based) timers are supported. Use the ``machine.Timer`` class
Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer <machine.Timer>` class
with timer ID of -1::
from machine import Timer
@ -102,7 +102,7 @@ The period is in milliseconds.
Pins and GPIO
-------------
Use the ``machine.Pin`` class::
Use the :ref:`machine.Pin <machine.Pin>` class::
from machine import Pin
@ -155,7 +155,7 @@ ADC (analog to digital conversion)
ADC is available on a dedicated pin.
Note that input voltages on the ADC pin must be between 0v and 1.0v.
Use the ``machine.ADC`` class::
Use the :ref:`machine.ADC <machine.ADC>` class::
from machine import ADC
@ -166,7 +166,8 @@ Software SPI bus
----------------
There are two SPI drivers. One is implemented in software (bit-banging)
and works on all pins::
and works on all pins, and is accessed via the :ref:`machine.SPI <machine.SPI>`
class::
from machine import Pin, SPI
@ -208,7 +209,8 @@ constructor and init (as those are fixed)::
I2C bus
-------
The I2C driver is implemented in software and works on all pins::
The I2C driver is implemented in software and works on all pins,
and is accessed via the :ref:`machine.I2C <machine.I2C>` class::
from machine import Pin, I2C

View File

@ -20,9 +20,12 @@ characteristic of a board is how much flash it has, how the GPIO pins are
connected to the outside world, and whether it includes a built-in USB-serial
convertor to make the UART available to your PC.
The minimum requirement for flash size is 512k. A board with this amount of
flash will not have room for a filesystem, but otherwise is fully functional.
If your board has 1Mbyte or more of flash then it will support a filesystem.
The minimum requirement for flash size is 1Mbyte. There is also a special
build for boards with 512KB, but it is highly limited comparing to the
normal build: there is no support for filesystem, and thus features which
depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will
be more interesting for users who build from source and fine-tune parameters
for their particular application.
Names of pins will be given in this tutorial using the chip names (eg GPIO0)
and it should be straightforward to find which pin this corresponds to on your

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.ADC:
class ADC -- analog to digital conversion
=========================================

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.I2C:
class I2C -- a two-wire serial protocol
=======================================
@ -9,86 +10,55 @@ level it consists of 2 wires: SCL and SDA, the clock and data lines respectively
I2C objects are created attached to a specific bus. They can be initialised
when created, or initialised later on.
.. only:: port_wipy
Printing the I2C object gives you information about its configuration.
Example::
Example usage::
from machine import I2C
from machine import I2C
i2c = I2C(0) # create on bus 0
i2c = I2C(0, I2C.MASTER) # create and init as a master
i2c.init(I2C.MASTER, baudrate=20000) # init as a master
i2c.deinit() # turn off the peripheral
i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
# depending on the port, extra parameters may be required
# to select the peripheral and/or pins to use
Printing the i2c object gives you information about its configuration.
i2c.scan() # scan for slaves, returning a list of 7-bit addresses
.. only:: port_wipy
i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42
i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42
A master must specify the recipient's address::
i2c.init(I2C.MASTER)
i2c.writeto(0x42, '123') # send 3 bytes to slave with address 0x42
i2c.writeto(addr=0x42, b'456') # keyword for address
Master also has other methods::
i2c.scan() # scan for slaves on the bus, returning
# a list of valid addresses
i2c.readfrom_mem(0x42, 2, 3) # read 3 bytes from memory of slave 0x42,
# starting at address 2 in the slave
i2c.writeto_mem(0x42, 2, 'abc') # write 'abc' (3 bytes) to memory of slave 0x42
# starting at address 2 in the slave, timeout after 1 second
i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42,
# starting at memory-address 8 in the slave
i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42
# starting at address 2 in the slave
Constructors
------------
.. only:: port_wipy
.. class:: I2C(id=-1, \*, scl, sda, freq=400000)
.. class:: I2C(bus, ...)
Construct and return a new I2C object using the following parameters:
Construct an I2C object on the given bus. `bus` can only be 0.
If the bus is not given, the default one will be selected (0).
.. only:: not port_wipy
.. class:: I2C(id=-1, \*, scl, sda, freq=400000)
Construct and return a new I2C object using the following parameters:
- `id` identifies the particular I2C peripheral. The default
value of -1 selects a software implementation of I2C which can
work (in most cases) with arbitrary pins for SCL and SDA.
If `id` is -1 then `scl` and `sda` must be specified. Other
allowed values for `id` depend on the particular port/board,
and specifying `scl` and `sda` may or may not be required or
allowed in this case.
- `scl` should be a pin object specifying the pin to use for SCL.
- `sda` should be a pin object specifying the pin to use for SDA.
- `freq` should be an integer which sets the maximum frequency
for SCL.
- `id` identifies the particular I2C peripheral. The default
value of -1 selects a software implementation of I2C which can
work (in most cases) with arbitrary pins for SCL and SDA.
If `id` is -1 then `scl` and `sda` must be specified. Other
allowed values for `id` depend on the particular port/board,
and specifying `scl` and `sda` may or may not be required or
allowed in this case.
- `scl` should be a pin object specifying the pin to use for SCL.
- `sda` should be a pin object specifying the pin to use for SDA.
- `freq` should be an integer which sets the maximum frequency
for SCL.
General Methods
---------------
.. only:: port_wipy
.. method:: I2C.init(scl, sda, \*, freq=400000)
.. method:: I2C.init(mode, \*, baudrate=100000, pins=(SDA, SCL))
Initialise the I2C bus with the given arguments:
Initialise the I2C bus with the given parameters:
- ``mode`` must be ``I2C.MASTER``
- ``baudrate`` is the SCL clock rate
- ``pins`` is an optional tuple with the pins to assign to the I2C bus.
.. only:: port_esp8266
.. method:: I2C.init(scl, sda, \*, freq=400000)
Initialise the I2C bus with the given arguments:
- `scl` is a pin object for the SCL line
- `sda` is a pin object for the SDA line
- `freq` is the SCL clock rate
- `scl` is a pin object for the SCL line
- `sda` is a pin object for the SDA line
- `freq` is the SCL clock rate
.. method:: I2C.deinit()
@ -102,8 +72,6 @@ General Methods
those that respond. A device responds if it pulls the SDA line low after
its address (including a write bit) is sent on the bus.
Note: on WiPy the I2C object must be in master mode for this method to be valid.
Primitive I2C operations
------------------------
@ -192,8 +160,7 @@ methods are convenience functions to communicate with such devices.
The argument `addrsize` specifies the address size in bits (on ESP8266
this argument is not recognised and the address size is always 8 bits).
On WiPy the return value is the number of bytes read. Otherwise the
return value is `None`.
The method returns `None`.
.. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8)
@ -202,14 +169,4 @@ methods are convenience functions to communicate with such devices.
The argument `addrsize` specifies the address size in bits (on ESP8266
this argument is not recognised and the address size is always 8 bits).
On WiPy the return value is the number of bytes written. Otherwise the
return value is `None`.
Constants
---------
.. data:: I2C.MASTER
for initialising the bus to master mode
Availability: WiPy.
The method returns `None`.

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.Pin:
class Pin -- control I/O pins
=============================

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.RTC:
class RTC -- real time clock
============================

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.SD:
class SD -- secure digital memory card
======================================

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.SPI:
class SPI -- a Serial Peripheral Interface bus protocol (master side)
=====================================================================
@ -44,7 +45,7 @@ Methods
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver
(``id`` = -1).
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to
specify them as a tuple of ``pins`` parameter.
specify them as a tuple of ``pins`` parameter.
.. method:: SPI.deinit()

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.Timer:
class Timer -- control hardware timers
======================================

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.UART:
class UART -- duplex serial communication bus
=============================================
@ -32,17 +33,6 @@ using the standard stream methods::
uart.readinto(buf) # read and store into the given buffer
uart.write('abc') # write the 3 characters
.. only:: port_pyboard
Individual characters can be read/written using::
uart.readchar() # read 1 character and returns it as an integer
uart.writechar(42) # write 1 character
To check if there is anything to be read, use::
uart.any() # returns True if any characters waiting
Constructors
------------
@ -69,15 +59,14 @@ Methods
When no pins are given, then the default set of TX and RX pins is taken, and hardware
flow control will be disabled. If pins=None, no pin assignment will be made.
.. only:: not port_esp8266
.. method:: UART.deinit()
.. method:: UART.deinit()
Turn off the UART bus.
Turn off the UART bus.
.. method:: UART.any()
.. method:: UART.any()
Return the number of characters available for reading.
Return true value if there're characters available for reading. On some
boards, the number of available characters is returned.
.. method:: UART.read([nbytes])
@ -107,13 +96,10 @@ Methods
Return value: number of bytes written or ``None`` on timeout.
.. only:: not port_esp8266
.. method:: UART.sendbreak()
.. method:: UART.sendbreak()
Send a break condition on the bus. This drives the bus low for a duration
of 13 bits.
Return value: ``None``.
Send a break condition on the bus. This drives the bus low for a duration
longer than required for a normal transmission of a character.
.. only:: port_wipy
@ -140,8 +126,6 @@ Methods
Returns an irq object.
.. only:: not port_esp8266
Constants
---------

View File

@ -1,4 +1,5 @@
.. currentmodule:: machine
.. _machine.WDT:
class WDT -- watchdog timer
===========================

View File

@ -17,7 +17,7 @@ A note of callbacks used by functions and class methods of ``machine`` module:
all these callbacks should be considered as executing in an interrupt context.
This is true for both physical devices with IDs >= 0 and "virtual" devices
with negative IDs like -1 (these "virtual" devices are still thin shims on
top of real hardware and real hardware intrerrupts). See :ref:`isr_rules`.
top of real hardware and real hardware interrupts). See :ref:`isr_rules`.
Reset related functions
-----------------------
@ -85,13 +85,6 @@ Miscellaneous functions
.. only:: port_wipy
.. function:: main(filename)
Set the filename of the main script to run after boot.py is finished. If
this function is not called then the default file main.py will be executed.
It only makes sense to call this function from within boot.py.
.. function:: rng()
Return a 24-bit software generated random number.

View File

@ -7,26 +7,6 @@
Functions
---------
.. only:: port_pyboard or port_unix
.. function:: mem_info([verbose])
Print information about currently used memory. If the ``verbose`` argument
is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the amount of stack and heap used. In verbose mode it prints out
the entire heap indicating which blocks are used and which are free.
.. function:: qstr_info([verbose])
Print information about currently interned strings. If the ``verbose``
argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the number of interned strings and the amount of RAM they use. In
verbose mode it prints out the names of all RAM-interned strings.
.. function:: alloc_emergency_exception_buf(size)
Allocate ``size`` bytes of RAM for the emergency exception buffer (a good
@ -37,3 +17,21 @@ Functions
A good way to use this function is to put it at the start of your main script
(eg boot.py or main.py) and then the emergency exception buffer will be active
for all the code following it.
.. function:: mem_info([verbose])
Print information about currently used memory. If the ``verbose`` argument
is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the amount of stack and heap used. In verbose mode it prints out
the entire heap indicating which blocks are used and which are free.
.. function:: qstr_info([verbose])
Print information about currently interned strings. If the ``verbose``
argument is given then extra information is printed.
The information that is printed is implementation dependent, but currently
includes the number of interned strings and the amount of RAM they use. In
verbose mode it prints out the names of all RAM-interned strings.

View File

@ -88,8 +88,8 @@ Functions
.. function:: urandom(n)
Return a bytes object with n random bytes, generated by the hardware
random number generator.
Return a bytes object with n random bytes. Whenever possible, it is
generated by the hardware random number generator.
.. only:: port_wipy

View File

@ -1,86 +1,46 @@
:mod:`ussl` -- ssl module
===============================
:mod:`ussl` -- SSL/TLS module
=============================
.. module:: ussl
:synopsis: TLS/SSL wrapper for socket objects
This module provides access to Transport Layer Security (often known as
“Secure Sockets Layer”) encryption and peer authentication facilities for
network sockets, both client-side and server-side.
This module provides access to Transport Layer Security (previously and
widely known as “Secure Sockets Layer”) encryption and peer authentication
facilities for network sockets, both client-side and server-side.
.. only:: not port_wipy
Functions
---------
Functions
---------
.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
.. function:: ssl.wrap_socket(sock, server_side=False)
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
an SSL context. Returned object has the usual stream interface methods like
`read()`, `write()`, etc. In MicroPython, the returned object does not expose
socket interface and methods like `recv()`, `send()`. In particular, a
server-side SSL socket should be created from a normal socket returned from
`accept()` on a non-SSL listening server socket.
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
an SSL context. Returned object has the usual stream interface methods like
`read()`, `write()`, etc. In MicroPython, the returned object does not expose
socket interface and methods like `recv()`, `send()`. In particular, a
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.
.. warning::
.. warning::
Currently, this function does NOT validate server certificates, which makes
an SSL connection established prone to man-in-the-middle attacks.
Some implementations of ``ssl`` module do NOT validate server certificates,
which makes an SSL connection established prone to man-in-the-middle attacks.
Exceptions
----------
.. only:: port_wipy
.. data:: ssl.SSLError
Functions
---------
This exception does NOT exist. Instead its base class, OSError, is used.
.. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
Constants
---------
Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
.. data:: ssl.CERT_NONE
ssl.CERT_OPTIONAL
ssl.CERT_REQUIRED
import socket
import ssl
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1])
Certificates must be used in order to validate the other side of the connection, and also to
authenticate ourselves with the other end. Such certificates must be stored as files using the
FTP server, and they must be placed in specific paths with specific names.
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
- The key for our own certificate goes in: **'/flash/cert/private.key'**
.. note::
When these files are stored, they are placed inside the internal **hidden** file system
(just like firmware updates), and therefore they are never visible.
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_
and put it in '/flash/cert/'. Then do::
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
Exceptions
----------
.. data:: ssl.SSLError
Constants
---------
.. data:: ssl.CERT_NONE
.. data:: ssl.CERT_OPTIONAL
.. data:: ssl.CERT_REQUIRED
supported values in ``cert_reqs``
Supported values for `cert_reqs` parameter.

View File

@ -240,6 +240,23 @@ Additional Pin methods:
Returns a list of the alternate functions supported by the pin. List items are
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
Additional details for machine.I2C
----------------------------------
On the WiPy there is a single hardware I2C peripheral, identified by "0". By
default this is the peripheral that is used when constructing an I2C instance.
The default pins are GP23 for SCL and GP13 for SDA, and one can create the
default I2C peripheral simply by doing::
i2c = machine.I2C()
The pins and frequency can be specified as::
i2c = machine.I2C(freq=400000, scl='GP23', sda='GP13')
Only certain pins can be used as SCL/SDA. Please refer to the pinout for further
information.
Known issues
------------
@ -254,6 +271,29 @@ SSL sockets need to be created the following way before wrapping them with.
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
Certificates must be used in order to validate the other side of the connection, and also to
authenticate ourselves with the other end. Such certificates must be stored as files using the
FTP server, and they must be placed in specific paths with specific names.
- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
- The key for our own certificate goes in: **'/flash/cert/private.key'**
.. note::
When these files are stored, they are placed inside the internal **hidden** file system
(just like firmware updates), and therefore they are never visible.
For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
in the `blynk examples folder <https://github.com/wipy/wipy/tree/master/examples/blynk>`_.
and put it in '/flash/cert/'. Then do::
import socket
import ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
Incompatibilities in uhashlib module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -273,3 +313,13 @@ Example::
...
hash.update('12345') # last chunk may be of any length
hash.digest()
Unrelated function in machine module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. function:: main(filename)
Set the filename of the main script to run after boot.py is finished. If
this function is not called then the default file main.py will be executed.
It only makes sense to call this function from within boot.py.

View File

@ -112,7 +112,7 @@ See :ref:`machine.I2C <machine.I2C>`. ::
from machine import I2C
# configure the I2C bus
i2c = I2C(0, I2C.MASTER, baudrate=100000)
i2c = I2C(baudrate=100000)
i2c.scan() # returns list of slave addresses
i2c.writeto(0x42, 'hello') # send 5 bytes to slave with address 0x42
i2c.readfrom(0x42, 5) # receive 5 bytes from slave

View File

@ -79,6 +79,16 @@ $ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy
The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000.
__512KB FlashROM version__
The normal build described above requires modules with at least 1MB of FlashROM
onboard. There's a special configuration for 512KB modules, which can be
built with `make 512k`. This configuration is highly limited, lacks filesystem
support, WebREPL, and has many other features disabled. It's mostly suitable
for advanced users who are interested to fine-tune options to achieve a required
setup. If you are an end user, please consider using a module with at least 1MB
of FlashROM.
First start
-----------
@ -110,7 +120,7 @@ http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
Troubleshooting
---------------
While the port is still in alpha, it's known to be generally stable. If you
While the port is in beta, it's known to be generally stable. If you
experience strange bootloops, crashes, lockups, here's a list to check against:
- You didn't erase flash before programming MicroPython firmware.

View File

@ -287,7 +287,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
}
// constructor(id, ...)
STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
@ -436,7 +436,7 @@ const mp_obj_type_t pyb_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = pyb_pin_print,
.make_new = pyb_pin_make_new,
.make_new = mp_pin_make_new,
.call = pyb_pin_call,
.protocol = &pin_pin_p,
.locals_dict = (mp_obj_t)&pyb_pin_locals_dict,

View File

@ -73,6 +73,7 @@
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_LWIP (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)

View File

@ -2,4 +2,4 @@ from machine import Pin, Signal
# ESP12 module as used by many boards
# Blue LED on pin 2, active low (inverted)
LED = Signal(Pin(2, Pin.OUT), inverted=True)
LED = Signal(Pin(2, Pin.OUT), invert=True)

View File

@ -27,6 +27,8 @@
#include "py/mpconfig.h"
#if MICROPY_PY_MACHINE
#include <string.h>
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/virtpin.h"
@ -37,24 +39,77 @@
typedef struct _machine_signal_t {
mp_obj_base_t base;
mp_obj_t pin;
bool inverted;
bool invert;
} machine_signal_t;
STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
enum { ARG_pin, ARG_inverted };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_, MP_ARG_OBJ | MP_ARG_REQUIRED },
{ MP_QSTR_inverted, MP_ARG_BOOL, {.u_bool = false} },
};
mp_obj_t pin = args[0];
bool invert = false;
mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)];
#if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
mp_pin_p_t *pin_p = NULL;
mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args);
if (MP_OBJ_IS_OBJ(pin)) {
mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
pin_p = (mp_pin_p_t*)pin_base->type->protocol;
}
if (pin_p == NULL) {
// If first argument isn't a Pin-like object, we filter out "invert"
// from keyword arguments and pass them all to the exported Pin
// constructor to create one.
mp_obj_t pin_args[n_args + n_kw * 2];
memcpy(pin_args, args, n_args * sizeof(mp_obj_t));
const mp_obj_t *src = args + n_args;
mp_obj_t *dst = pin_args + n_args;
mp_obj_t *sig_value = NULL;
for (size_t cnt = n_kw; cnt; cnt--) {
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
invert = mp_obj_is_true(src[1]);
n_kw--;
} else {
*dst++ = *src;
*dst++ = src[1];
}
if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) {
// Value is pertained to Signal, so we should invert
// it for Pin if needed, and we should do it only when
// inversion status is guaranteedly known.
sig_value = dst - 1;
}
src += 2;
}
if (invert && sig_value != NULL) {
*sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1);
}
// Here we pass NULL as a type, hoping that mp_pin_make_new()
// will just ignore it as set a concrete type. If not, we'd need
// to expose port's "default" pin type too.
pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
}
else
#endif
// Otherwise there should be 1 or 2 args
{
if (n_args == 1) {
if (n_kw == 0) {
} else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
invert = mp_obj_is_true(args[1]);
} else {
goto error;
}
} else {
error:
mp_raise_TypeError(NULL);
}
}
machine_signal_t *o = m_new_obj(machine_signal_t);
o->base.type = type;
o->pin = parsed_args[ARG_pin].u_obj;
o->inverted = parsed_args[ARG_inverted].u_bool;
o->pin = pin;
o->invert = invert;
return MP_OBJ_FROM_PTR(o);
}
@ -64,10 +119,10 @@ STATIC mp_uint_t signal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg
switch (request) {
case MP_PIN_READ: {
return mp_virtual_pin_read(self->pin) ^ self->inverted;
return mp_virtual_pin_read(self->pin) ^ self->invert;
}
case MP_PIN_WRITE: {
mp_virtual_pin_write(self->pin, arg ^ self->inverted);
mp_virtual_pin_write(self->pin, arg ^ self->invert);
return 0;
}
}

View File

@ -360,7 +360,7 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
return;
}
#endif
mp_int_t v = mp_obj_get_int(val);
mp_int_t v = mp_obj_get_int_truncated(val);
switch (val_type) {
case UINT8:
((uint8_t*)p)[index] = (uint8_t)v; return;

View File

@ -38,3 +38,6 @@ typedef struct _mp_pin_p_t {
int mp_virtual_pin_read(mp_obj_t pin);
void mp_virtual_pin_write(mp_obj_t pin, int value);
// If a port exposes a Pin object, it's constructor should be like this
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);

Binary file not shown.

View File

@ -125,7 +125,7 @@ void Default_Handler(void) {
}
}
uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = {
const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = {
(uint32_t)&_estack,
(uint32_t)&Reset_Handler,
(uint32_t)&Default_Handler, // NMI_Handler

View File

@ -44,6 +44,7 @@
#define MICROPY_COMP_CONST (1)
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)

View File

@ -304,7 +304,7 @@ STATIC const byte opcode_format_table[64] = {
OC4(U, U, U, U), // 0x0c-0x0f
OC4(B, B, B, U), // 0x10-0x13
OC4(V, U, Q, V), // 0x14-0x17
OC4(B, U, V, V), // 0x18-0x1b
OC4(B, V, V, Q), // 0x18-0x1b
OC4(Q, Q, Q, Q), // 0x1c-0x1f
OC4(B, B, V, V), // 0x20-0x23
OC4(Q, Q, Q, B), // 0x24-0x27

View File

@ -37,12 +37,13 @@
#define MP_BC_LOAD_CONST_OBJ (0x17) // ptr
#define MP_BC_LOAD_NULL (0x18)
#define MP_BC_LOAD_FAST_N (0x1a) // uint
#define MP_BC_LOAD_DEREF (0x1b) // uint
#define MP_BC_LOAD_NAME (0x1c) // qstr
#define MP_BC_LOAD_GLOBAL (0x1d) // qstr
#define MP_BC_LOAD_ATTR (0x1e) // qstr
#define MP_BC_LOAD_METHOD (0x1f) // qstr
#define MP_BC_LOAD_FAST_N (0x19) // uint
#define MP_BC_LOAD_DEREF (0x1a) // uint
#define MP_BC_LOAD_NAME (0x1b) // qstr
#define MP_BC_LOAD_GLOBAL (0x1c) // qstr
#define MP_BC_LOAD_ATTR (0x1d) // qstr
#define MP_BC_LOAD_METHOD (0x1e) // qstr
#define MP_BC_LOAD_SUPER_METHOD (0x1f) // qstr
#define MP_BC_LOAD_BUILD_CLASS (0x20)
#define MP_BC_LOAD_SUBSCR (0x21)

View File

@ -115,7 +115,6 @@ typedef struct _compiler_t {
uint8_t is_repl;
uint8_t pass; // holds enum type pass_kind_t
uint8_t func_arg_is_super; // used to compile special case of super() function call
uint8_t have_star;
// try to keep compiler clean from nlr
@ -586,8 +585,16 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int
}
STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)
|| MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_star)) {
// For efficiency of the code below we extract the parse-node kind here
int pn_kind;
if (MP_PARSE_NODE_IS_ID(pn)) {
pn_kind = -1;
} else {
assert(MP_PARSE_NODE_IS_STRUCT(pn));
pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn);
}
if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
comp->have_star = true;
/* don't need to distinguish bare from named star
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@ -598,8 +605,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
}
*/
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)
|| MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_dbl_star)) {
} else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {
// named double star
// TODO do we need to do anything with this?
@ -607,14 +613,14 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
mp_parse_node_t pn_id;
mp_parse_node_t pn_colon;
mp_parse_node_t pn_equal;
if (MP_PARSE_NODE_IS_ID(pn)) {
if (pn_kind == -1) {
// this parameter is just an id
pn_id = pn;
pn_colon = MP_PARSE_NODE_NULL;
pn_equal = MP_PARSE_NODE_NULL;
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
} else if (pn_kind == PN_typedargslist_name) {
// this parameter has a colon and/or equal specifier
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@ -623,7 +629,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
pn_equal = pns->nodes[2];
} else {
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_name)); // should be
assert(pn_kind == PN_varargslist_name); // should be
// this parameter has an equal specifier
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@ -755,7 +761,6 @@ STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pn
if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
parents = MP_PARSE_NODE_NULL;
}
comp->func_arg_is_super = false;
compile_trailer_paren_helper(comp, parents, false, 2);
// return its name (the 'C' in class C(...):")
@ -829,7 +834,6 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
// nodes[1] contains arguments to the decorator function, if any
if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
// call the decorator function with the arguments in nodes[1]
comp->func_arg_is_super = false;
compile_node(comp, pns_decorator->nodes[1]);
}
}
@ -973,7 +977,8 @@ STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// no argument to 'return', so return None
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
} else if (MICROPY_COMP_RETURN_IF_EXPR
&& MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
// special case when returning an if-expression; to match CPython optimisation
mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
@ -1422,7 +1427,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
&& MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
&& MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)) {
&& MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) {
mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
mp_parse_node_t *args;
int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
@ -1689,7 +1694,7 @@ STATIC void compile_yield_from(compiler_t *comp) {
#if MICROPY_PY_ASYNC_AWAIT
STATIC void compile_await_object_method(compiler_t *comp, qstr method) {
EMIT_ARG(load_method, method);
EMIT_ARG(load_method, method, false);
EMIT_ARG(call_method, 0, 0, 0);
compile_yield_from(comp);
}
@ -1780,7 +1785,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
}
compile_load_id(comp, context);
EMIT_ARG(load_method, MP_QSTR___aexit__);
EMIT_ARG(load_method, MP_QSTR___aexit__, false);
EMIT_ARG(setup_except, try_exception_label);
compile_increase_except_level(comp);
@ -2167,10 +2172,85 @@ STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
// this is to handle special super() call
comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
// compile the subject of the expression
compile_node(comp, pns->nodes[0]);
compile_generic_all_nodes(comp, pns);
// compile_atom_expr_await may call us with a NULL node
if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
return;
}
// get the array of trailers (known to be an array of PARSE_NODE_STRUCT)
size_t num_trail = 1;
mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1];
if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {
num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);
pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0];
}
// the current index into the array of trailers
size_t i = 0;
// handle special super() call
if (comp->scope_cur->kind == SCOPE_FUNCTION
&& MP_PARSE_NODE_IS_ID(pns->nodes[0])
&& MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super
&& MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
&& MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) {
// at this point we have matched "super()" within a function
// load the class for super to search for a parent
compile_load_id(comp, MP_QSTR___class__);
// look for first argument to function (assumes it's "self")
bool found = false;
id_info_t *id = &comp->scope_cur->id_info[0];
for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {
if (id->flags & ID_FLAG_IS_PARAM) {
// first argument found; load it
compile_load_id(comp, id->qst);
found = true;
break;
}
}
if (!found) {
compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0],
"super() can't find self"); // really a TypeError
return;
}
if (num_trail >= 3
&& MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period
&& MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) {
// optimisation for method calls super().f(...), to eliminate heap allocation
mp_parse_node_struct_t *pns_period = pns_trail[1];
mp_parse_node_struct_t *pns_paren = pns_trail[2];
EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true);
compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
i = 3;
} else {
// a super() call
EMIT_ARG(call_function, 2, 0, 0);
i = 1;
}
}
// compile the remaining trailers
for (; i < num_trail; i++) {
if (i + 1 < num_trail
&& MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period
&& MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {
// optimisation for method calls a.f(...), following PyPy
mp_parse_node_struct_t *pns_period = pns_trail[i];
mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);
compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
i += 1;
} else {
// node is one of: trailer_paren, trailer_bracket, trailer_period
compile_node(comp, (mp_parse_node_t)pns_trail[i]);
}
}
}
STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
@ -2181,23 +2261,6 @@ STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
// function to call is on top of stack
// this is to handle special super() call
if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
compile_load_id(comp, MP_QSTR___class__);
// look for first argument to function (assumes it's "self")
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
id_info_t *id = &comp->scope_cur->id_info[i];
if (id->flags & ID_FLAG_IS_PARAM) {
// first argument found; load it and call super
compile_load_id(comp, id->qst);
EMIT_ARG(call_function, 2, 0, 0);
return;
}
}
compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError
return;
}
// get the list of arguments
mp_parse_node_t *args;
int n_args = mp_parse_node_extract_list(&pn_arglist, PN_arglist, &args);
@ -2277,23 +2340,6 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
}
}
STATIC void compile_atom_expr_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
for (int i = 0; i < num_nodes; i++) {
if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) {
// optimisation for method calls a.f(...), following PyPy
mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
i += 1;
} else {
compile_node(comp, pns->nodes[i]);
}
comp->func_arg_is_super = false;
}
}
// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
@ -2825,14 +2871,14 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn
} else {
EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
}
} else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
} else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) {
// if condition
mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
pn_iter = pns_comp_if->nodes[1];
goto tail_recursion;
} else {
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)); // should be
assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be
// for loop
mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
compile_node(comp, pns_comp_for2->nodes[1]);

View File

@ -88,7 +88,7 @@ typedef struct _emit_method_table_t {
void (*load_const_obj)(emit_t *emit, mp_obj_t obj);
void (*load_null)(emit_t *emit);
void (*load_attr)(emit_t *emit, qstr qst);
void (*load_method)(emit_t *emit, qstr qst);
void (*load_method)(emit_t *emit, qstr qst, bool is_super);
void (*load_build_class)(emit_t *emit);
void (*load_subscr)(emit_t *emit);
void (*store_attr)(emit_t *emit, qstr qst);
@ -205,7 +205,7 @@ void mp_emit_bc_load_const_str(emit_t *emit, qstr qst);
void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj);
void mp_emit_bc_load_null(emit_t *emit);
void mp_emit_bc_load_attr(emit_t *emit, qstr qst);
void mp_emit_bc_load_method(emit_t *emit, qstr qst);
void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super);
void mp_emit_bc_load_build_class(emit_t *emit);
void mp_emit_bc_load_subscr(emit_t *emit);
void mp_emit_bc_store_attr(emit_t *emit, qstr qst);

View File

@ -594,9 +594,9 @@ void mp_emit_bc_load_attr(emit_t *emit, qstr qst) {
}
}
void mp_emit_bc_load_method(emit_t *emit, qstr qst) {
emit_bc_pre(emit, 1);
emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst);
void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) {
emit_bc_pre(emit, 1 - 2 * is_super);
emit_write_bytecode_byte_qstr(emit, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst);
}
void mp_emit_bc_load_build_class(emit_t *emit) {

View File

@ -85,6 +85,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_LOAD_BUILD_CLASS] = 0,
[MP_F_LOAD_ATTR] = 2,
[MP_F_LOAD_METHOD] = 3,
[MP_F_LOAD_SUPER_METHOD] = 2,
[MP_F_STORE_NAME] = 2,
[MP_F_STORE_GLOBAL] = 2,
[MP_F_STORE_ATTR] = 3,
@ -1065,12 +1066,18 @@ STATIC void emit_native_load_attr(emit_t *emit, qstr qst) {
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
STATIC void emit_native_load_method(emit_t *emit, qstr qst) {
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
assert(vtype_base == VTYPE_PYOBJ);
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name
STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) {
if (is_super) {
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr
emit_call_with_imm_arg(emit, MP_F_LOAD_SUPER_METHOD, qst, REG_ARG_1); // arg1 = method name
} else {
vtype_kind_t vtype_base;
emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
assert(vtype_base == VTYPE_PYOBJ);
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name
}
}
STATIC void emit_native_load_build_class(emit_t *emit) {

14
py/gc.c
View File

@ -258,18 +258,20 @@ STATIC void gc_sweep(void) {
case AT_HEAD:
#if MICROPY_ENABLE_FINALISER
if (FTB_GET(block)) {
#if MICROPY_PY_THREAD
// TODO need to think about reentrancy with finaliser code
assert(!"finaliser with threading not implemented");
#endif
mp_obj_base_t *obj = (mp_obj_base_t*)PTR_FROM_BLOCK(block);
if (obj->type != NULL) {
// if the object has a type then see if it has a __del__ method
mp_obj_t dest[2];
mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest);
if (dest[0] != MP_OBJ_NULL) {
// load_method returned a method
mp_call_method_n_kw(0, 0, dest);
// load_method returned a method, execute it in a protected environment
#if MICROPY_ENABLE_SCHEDULER
mp_sched_lock();
#endif
mp_call_function_1_protected(dest[0], dest[1]);
#if MICROPY_ENABLE_SCHEDULER
mp_sched_unlock();
#endif
}
}
// clear finaliser flag

View File

@ -261,7 +261,7 @@ DEF_RULE(atom_expr_await, c(atom_expr_await), and(3), tok(KW_AWAIT), rule(atom),
DEF_RULE_NC(atom_expr, or(1), rule(atom_expr_normal))
#endif
DEF_RULE(atom_expr_normal, c(atom_expr_normal), and_ident(2), rule(atom), opt_rule(atom_expr_trailers))
DEF_RULE(atom_expr_trailers, c(atom_expr_trailers), one_or_more, rule(trailer))
DEF_RULE_NC(atom_expr_trailers, one_or_more, rule(trailer))
DEF_RULE_NC(power_dbl_star, and_ident(2), tok(OP_DBL_STAR), rule(factor))
// atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False'

View File

@ -31,6 +31,7 @@
#include "py/stackctrl.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "py/mphal.h"
// Various builtins specific to MicroPython runtime,
// living in micropython module
@ -129,6 +130,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf);
#endif
#if MICROPY_KBD_EXCEPTION
STATIC mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) {
mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr);
#endif
#if MICROPY_ENABLE_SCHEDULER
STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) {
if (!mp_sched_schedule(function, arg)) {
@ -162,6 +171,9 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },
{ MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },
#endif
#if MICROPY_KBD_EXCEPTION
{ MP_ROM_QSTR(MP_QSTR_kbd_intr), MP_ROM_PTR(&mp_micropython_kbd_intr_obj) },
#endif
#if MICROPY_ENABLE_SCHEDULER
{ MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) },
#endif

View File

@ -353,6 +353,12 @@
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
#endif
// Whether to enable optimisation of: return a if b else c
// Costs about 80 bytes (Thumb2) and saves 2 bytes of bytecode for each use
#ifndef MICROPY_COMP_RETURN_IF_EXPR
#define MICROPY_COMP_RETURN_IF_EXPR (0)
#endif
/*****************************************************************************/
/* Internal debugging stuff */
@ -445,7 +451,7 @@
# endif
#endif
// Whether to provide the mp_kbd_exception object
// Whether to provide the mp_kbd_exception object, and micropython.kbd_intr function
#ifndef MICROPY_KBD_EXCEPTION
#define MICROPY_KBD_EXCEPTION (0)
#endif
@ -548,6 +554,12 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
#endif
// Whether to provide a high-quality hash for float and complex numbers.
// Otherwise the default is a very simple but correct hashing function.
#ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)
#endif
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not

View File

@ -120,8 +120,8 @@ typedef struct _mp_state_vm_t {
// memory for exception arguments if we can't allocate RAM
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
#if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0
// statically allocated buf
byte mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE];
// statically allocated buf (needs to be aligned to mp_obj_t)
mp_obj_t mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE / sizeof(mp_obj_t)];
#else
// dynamically allocated buf
byte *mp_emergency_exception_buf;

View File

@ -133,6 +133,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_load_build_class,
mp_load_attr,
mp_load_method,
mp_load_super_method,
mp_store_name,
mp_store_global,
mp_store_attr,

View File

@ -29,10 +29,14 @@
#if MICROPY_NLR_SETJMP
void nlr_setjmp_jump(void *val) {
nlr_buf_t *buf = MP_STATE_THREAD(nlr_top);
MP_STATE_THREAD(nlr_top) = buf->prev;
buf->ret_val = val;
longjmp(buf->jmpbuf, 1);
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
nlr_buf_t *top = *top_ptr;
if (top == NULL) {
nlr_jump_fail(val);
}
top->ret_val = val;
*top_ptr = top->prev;
longjmp(top->jmpbuf, 1);
}
#endif

View File

@ -470,16 +470,27 @@ typedef struct _mp_stream_p_t {
} mp_stream_p_t;
struct _mp_obj_type_t {
// A type is an object so must start with this entry, which points to mp_type_type.
mp_obj_base_t base;
// The name of this type.
qstr name;
// Corresponds to __repr__ and __str__ special methods.
mp_print_fun_t print;
mp_make_new_fun_t make_new; // to make an instance of the type
// Corresponds to __new__ and __init__ special methods, to make an instance of the type.
mp_make_new_fun_t make_new;
// Corresponds to __call__ special method, ie T(...).
mp_call_fun_t call;
mp_unary_op_fun_t unary_op; // can return MP_OBJ_NULL if op not supported
mp_binary_op_fun_t binary_op; // can return MP_OBJ_NULL if op not supported
// implements load, store and delete attribute
// Implements unary and binary operations.
// Can return MP_OBJ_NULL if the operation is not supported.
mp_unary_op_fun_t unary_op;
mp_binary_op_fun_t binary_op;
// Implements load, store and delete attribute.
//
// dest[0] = MP_OBJ_NULL means load
// return: for fail, do nothing
@ -492,35 +503,36 @@ struct _mp_obj_type_t {
// for success set dest[0] = MP_OBJ_NULL
mp_attr_fun_t attr;
mp_subscr_fun_t subscr; // implements load, store, delete subscripting
// value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store
// can return MP_OBJ_NULL if op not supported
// Implements load, store and delete subscripting:
// - value = MP_OBJ_SENTINEL means load
// - value = MP_OBJ_NULL means delete
// - all other values mean store the value
// Can return MP_OBJ_NULL if operation not supported.
mp_subscr_fun_t subscr;
// corresponds to __iter__ special method
// can use given mp_obj_iter_buf_t to store iterator
// otherwise can return a pointer to an object on the heap
// Corresponds to __iter__ special method.
// Can use the given mp_obj_iter_buf_t to store iterator object,
// otherwise can return a pointer to an object on the heap.
mp_getiter_fun_t getiter;
mp_fun_1_t iternext; // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() (with no args)
// Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION
// as an optimisation instead of raising StopIteration() with no args.
mp_fun_1_t iternext;
// Implements the buffer protocol if supported by this type.
mp_buffer_p_t buffer_p;
// One of disjoint protocols (interfaces), like mp_stream_p_t, etc.
const void *protocol;
// these are for dynamically created types (classes)
struct _mp_obj_tuple_t *bases_tuple;
// A pointer to the parents of this type:
// - 0 parents: pointer is NULL (object is implicitly the single parent)
// - 1 parent: a pointer to the type of that parent
// - 2 or more parents: pointer to a tuple object containing the parent types
const void *parent;
// A dict mapping qstrs to objects local methods/constants/etc.
struct _mp_obj_dict_t *locals_dict;
/*
What we might need to add here:
len str tuple list map
abs float complex
hash bool int none str
equal int str
unpack seq list tuple
*/
};
// Constant types, globally accessible
@ -649,7 +661,6 @@ mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(size_t n_args);
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf);
mp_obj_t mp_obj_new_module(qstr module_name);
@ -718,7 +729,11 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t s
#if MICROPY_PY_BUILTINS_FLOAT
// float
#if MICROPY_FLOAT_HIGH_QUALITY_HASH
mp_int_t mp_float_hash(mp_float_t val);
#else
static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }
#endif
mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
// complex

View File

@ -50,7 +50,11 @@ STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
const int precision = 6;
#else
const int precision = 7;
#endif
#else
char buf[32];
const int precision = 16;

View File

@ -577,8 +577,6 @@ const mp_obj_type_t mp_type_dict = {
};
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
STATIC const mp_rom_obj_tuple_t ordereddict_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_dict)}};
const mp_obj_type_t mp_type_ordereddict = {
{ &mp_type_type },
.name = MP_QSTR_OrderedDict,
@ -588,7 +586,7 @@ const mp_obj_type_t mp_type_ordereddict = {
.binary_op = dict_binary_op,
.subscr = dict_subscr,
.getiter = dict_getiter,
.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&ordereddict_base_tuple,
.parent = &mp_type_dict,
.locals_dict = (mp_obj_dict_t*)&dict_locals_dict,
};
#endif

View File

@ -197,9 +197,6 @@ const mp_obj_type_t mp_type_BaseException = {
.locals_dict = (mp_obj_dict_t*)&exc_locals_dict,
};
#define MP_DEFINE_EXCEPTION_BASE(base_name) \
STATIC const mp_rom_obj_tuple_t mp_type_ ## base_name ## _base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_ ## base_name)}};\
#define MP_DEFINE_EXCEPTION(exc_name, base_name) \
const mp_obj_type_t mp_type_ ## exc_name = { \
{ &mp_type_type }, \
@ -207,23 +204,20 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
.print = mp_obj_exception_print, \
.make_new = mp_obj_exception_make_new, \
.attr = exception_attr, \
.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&mp_type_ ## base_name ## _base_tuple, \
.parent = &mp_type_ ## base_name, \
};
// List of all exceptions, arranged as in the table at:
// http://docs.python.org/3/library/exceptions.html
MP_DEFINE_EXCEPTION_BASE(BaseException)
MP_DEFINE_EXCEPTION(SystemExit, BaseException)
MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION_BASE(Exception)
#if MICROPY_PY_ASYNC_AWAIT
MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception)
#endif
MP_DEFINE_EXCEPTION(StopIteration, Exception)
MP_DEFINE_EXCEPTION(ArithmeticError, Exception)
MP_DEFINE_EXCEPTION_BASE(ArithmeticError)
//MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError)
MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError)
MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError)
@ -235,18 +229,15 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(ImportError, Exception)
//MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead
MP_DEFINE_EXCEPTION(LookupError, Exception)
MP_DEFINE_EXCEPTION_BASE(LookupError)
MP_DEFINE_EXCEPTION(IndexError, LookupError)
MP_DEFINE_EXCEPTION(KeyError, LookupError)
MP_DEFINE_EXCEPTION(MemoryError, Exception)
MP_DEFINE_EXCEPTION(NameError, Exception)
/*
MP_DEFINE_EXCEPTION_BASE(NameError)
MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)
*/
MP_DEFINE_EXCEPTION(OSError, Exception)
#if MICROPY_PY_BUILTINS_TIMEOUTERROR
MP_DEFINE_EXCEPTION_BASE(OSError)
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
#endif
/*
@ -267,30 +258,24 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(ReferenceError, Exception)
*/
MP_DEFINE_EXCEPTION(RuntimeError, Exception)
MP_DEFINE_EXCEPTION_BASE(RuntimeError)
MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError)
MP_DEFINE_EXCEPTION(SyntaxError, Exception)
MP_DEFINE_EXCEPTION_BASE(SyntaxError)
MP_DEFINE_EXCEPTION(IndentationError, SyntaxError)
/*
MP_DEFINE_EXCEPTION_BASE(IndentationError)
MP_DEFINE_EXCEPTION(TabError, IndentationError)
*/
//MP_DEFINE_EXCEPTION(SystemError, Exception)
MP_DEFINE_EXCEPTION(TypeError, Exception)
#if MICROPY_EMIT_NATIVE
MP_DEFINE_EXCEPTION_BASE(TypeError)
MP_DEFINE_EXCEPTION(ViperTypeError, TypeError)
#endif
MP_DEFINE_EXCEPTION(ValueError, Exception)
#if MICROPY_PY_BUILTINS_STR_UNICODE
MP_DEFINE_EXCEPTION_BASE(ValueError)
MP_DEFINE_EXCEPTION(UnicodeError, ValueError)
//TODO: Implement more UnicodeError subclasses which take arguments
#endif
/*
MP_DEFINE_EXCEPTION(Warning, Exception)
MP_DEFINE_EXCEPTION_BASE(Warning)
MP_DEFINE_EXCEPTION(DeprecationWarning, Warning)
MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning)
MP_DEFINE_EXCEPTION(RuntimeWarning, Warning)
@ -348,7 +333,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
tuple->items[0] = MP_OBJ_FROM_PTR(str);
byte *str_data = (byte *)&str[1];
uint max_len = MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
size_t max_len = (byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
- str_data;
vstr_t vstr;
@ -366,14 +351,14 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
o->args = tuple;
uint offset = &str_data[str->len] - MP_STATE_VM(mp_emergency_exception_buf);
size_t offset = &str_data[str->len] - (byte*)MP_STATE_VM(mp_emergency_exception_buf);
offset += sizeof(void *) - 1;
offset &= ~(sizeof(void *) - 1);
if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) {
// We have room to store some traceback.
o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset);
o->traceback_alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);
o->traceback_alloc = ((byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);
o->traceback_len = 0;
}
}

View File

@ -59,12 +59,65 @@ const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};
#endif
#if MICROPY_FLOAT_HIGH_QUALITY_HASH
// must return actual integer value if it fits in mp_int_t
mp_int_t mp_float_hash(mp_float_t src) {
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
typedef uint64_t mp_float_uint_t;
#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
typedef uint32_t mp_float_uint_t;
#endif
union {
mp_float_t f;
#if MP_ENDIANNESS_LITTLE
struct { mp_float_uint_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;
#else
struct { mp_float_uint_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;
#endif
mp_float_uint_t i;
} u = {.f = src};
mp_int_t val;
const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS;
if (adj_exp < 0) {
// value < 1; must be sure to handle 0.0 correctly (ie return 0)
val = u.i;
} else {
// if adj_exp is max then: u.p.frc==0 indicates inf, else NaN
// else: 1 <= value
mp_float_uint_t frc = u.p.frc | ((mp_float_uint_t)1 << MP_FLOAT_FRAC_BITS);
if (adj_exp <= MP_FLOAT_FRAC_BITS) {
// number may have a fraction; xor the integer part with the fractional part
val = (frc >> (MP_FLOAT_FRAC_BITS - adj_exp))
^ (frc & ((1 << (MP_FLOAT_FRAC_BITS - adj_exp)) - 1));
} else if ((unsigned int)adj_exp < BITS_PER_BYTE * sizeof(mp_int_t) - 1) {
// the number is a (big) whole integer and will fit in val's signed-width
val = (mp_int_t)frc << (adj_exp - MP_FLOAT_FRAC_BITS);
} else {
// integer part will overflow val's width so just use what bits we can
val = frc;
}
}
if (u.p.sgn) {
val = -val;
}
return val;
}
#endif
STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_float_t o_val = mp_obj_float_get(o_in);
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
const int precision = 6;
#else
const int precision = 7;
#endif
#else
char buf[32];
const int precision = 16;

View File

@ -170,8 +170,10 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef mp_longint_impl_t fmt_int_t;
typedef unsigned long long fmt_uint_t;
#else
typedef mp_int_t fmt_int_t;
typedef mp_uint_t fmt_uint_t;
#endif
void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@ -224,7 +226,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co
fmt_int_t num;
if (MP_OBJ_IS_SMALL_INT(self_in)) {
// A small int; get the integer value to format.
num = mp_obj_get_int(self_in);
num = MP_OBJ_SMALL_INT_VALUE(self_in);
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
} else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
// Not a small int.
@ -265,8 +267,9 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co
*(--b) = '0';
} else {
do {
int c = num % base;
num /= base;
// The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic
int c = (fmt_uint_t)num % base;
num = (fmt_uint_t)num / base;
if (c >= 10) {
c += base_char - 10;
} else {

View File

@ -116,6 +116,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
memset(buf, 0, len);
mpz_as_bytes(&self->mpz, big_endian, len, buf);
}

View File

@ -134,8 +134,6 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
return MP_OBJ_FROM_PTR(tuple);
}
STATIC const mp_rom_obj_tuple_t namedtuple_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_tuple)}};
STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) {
mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields);
memset(&o->base, 0, sizeof(o->base));
@ -148,7 +146,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t
o->base.attr = namedtuple_attr;
o->base.subscr = mp_obj_tuple_subscr;
o->base.getiter = mp_obj_tuple_getiter;
o->base.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&namedtuple_base_tuple;
o->base.parent = &mp_type_tuple;
o->n_fields = n_fields;
for (size_t i = 0; i < n_fields; i++) {
o->fields[i] = mp_obj_str_get_qstr(fields[i]);

View File

@ -57,26 +57,34 @@ STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs)
}
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
int count = 0;
for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(items[i]);
if (bt == &mp_type_object) {
// Not a "real" type
continue;
}
if (mp_obj_is_native_type(bt)) {
*last_native_base = bt;
count++;
for (;;) {
if (type == &mp_type_object) {
// Not a "real" type, end search here.
return count;
} else if (mp_obj_is_native_type(type)) {
// Native types don't have parents (at least not from our perspective) so end.
*last_native_base = type;
return count + 1;
} else if (type->parent == NULL) {
// No parents so end search here.
return count;
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
// Multiple parents, search through them all recursively.
const mp_obj_tuple_t *parent_tuple = type->parent;
const mp_obj_t *item = parent_tuple->items;
const mp_obj_t *top = item + parent_tuple->len;
for (; item < top; ++item) {
assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
count += instance_count_native_bases(bt, last_native_base);
}
return count;
} else {
count += instance_count_native_bases(bt, last_native_base);
// A single parent, use iteration to continue the search.
type = type->parent;
}
}
return count;
}
// TODO
@ -160,32 +168,31 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
// attribute not found, keep searching base classes
// for a const struct, this entry might be NULL
if (type->bases_tuple == NULL) {
if (type->parent == NULL) {
return;
}
size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
if (len == 0) {
return;
}
for (size_t i = 0; i < len - 1; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]);
if (bt == &mp_type_object) {
// Not a "real" type
continue;
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = type->parent;
const mp_obj_t *item = parent_tuple->items;
const mp_obj_t *top = item + parent_tuple->len - 1;
for (; item < top; ++item) {
assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);
if (bt == &mp_type_object) {
// Not a "real" type
continue;
}
mp_obj_class_lookup(lookup, bt);
if (lookup->dest[0] != MP_OBJ_NULL) {
return;
}
}
mp_obj_class_lookup(lookup, bt);
if (lookup->dest[0] != MP_OBJ_NULL) {
return;
}
}
// search last base (simple tail recursion elimination)
assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type));
type = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[len - 1]);
// search last base (simple tail recursion elimination)
assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
type = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);
} else {
type = type->parent;
}
if (type == &mp_type_object) {
// Not a "real" type
return;
@ -946,14 +953,21 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
o->getiter = instance_getiter;
//o->iternext = ; not implemented
o->buffer_p.get_buffer = instance_get_buffer;
// Inherit protocol from a base class. This allows to define an
// abstract base class which would translate C-level protocol to
// Python method calls, and any subclass inheriting from it will
// support this feature.
if (len > 0) {
// Inherit protocol from a base class. This allows to define an
// abstract base class which would translate C-level protocol to
// Python method calls, and any subclass inheriting from it will
// support this feature.
o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(items[0]))->protocol;
if (len >= 2) {
o->parent = MP_OBJ_TO_PTR(bases_tuple);
} else {
o->parent = MP_OBJ_TO_PTR(items[0]);
}
}
o->bases_tuple = MP_OBJ_TO_PTR(bases_tuple);
o->locals_dict = MP_OBJ_TO_PTR(locals_dict);
const mp_obj_type_t *native_base;
@ -999,7 +1013,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size
// 0 arguments are turned into 2 in the compiler
// 1 argument is not yet implemented
mp_arg_check_num(n_args, n_kw, 2, 2, false);
return mp_obj_new_super(args[0], args[1]);
mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
*o = (mp_obj_super_t){{type_in}, args[0], args[1]};
return MP_OBJ_FROM_PTR(o);
}
STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
@ -1015,13 +1031,6 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type);
// for a const struct, this entry might be NULL
if (type->bases_tuple == NULL) {
return;
}
size_t len = type->bases_tuple->len;
mp_obj_t *items = type->bases_tuple->items;
struct class_lookup_data lookup = {
.obj = MP_OBJ_TO_PTR(self->obj),
.attr = attr,
@ -1029,13 +1038,27 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
.dest = dest,
.is_type = false,
};
for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
if (type->parent == NULL) {
// no parents, do nothing
} else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
const mp_obj_tuple_t *parent_tuple = type->parent;
size_t len = parent_tuple->len;
const mp_obj_t *items = parent_tuple->items;
for (size_t i = 0; i < len; i++) {
assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
if (dest[0] != MP_OBJ_NULL) {
return;
}
}
} else {
mp_obj_class_lookup(&lookup, type->parent);
if (dest[0] != MP_OBJ_NULL) {
return;
}
}
mp_obj_class_lookup(&lookup, &mp_type_object);
}
@ -1047,10 +1070,9 @@ const mp_obj_type_t mp_type_super = {
.attr = super_attr,
};
mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
*o = (mp_obj_super_t){{&mp_type_super}, type, obj};
return MP_OBJ_FROM_PTR(o);
void mp_load_super_method(qstr attr, mp_obj_t *dest) {
mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]};
mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest);
}
/******************************************************************************/
@ -1073,27 +1095,28 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
const mp_obj_type_t *self = MP_OBJ_TO_PTR(object);
// for a const struct, this entry might be NULL
if (self->bases_tuple == NULL) {
if (self->parent == NULL) {
// type has no parents
return false;
}
} else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) {
// get the base objects (they should be type objects)
const mp_obj_tuple_t *parent_tuple = self->parent;
const mp_obj_t *item = parent_tuple->items;
const mp_obj_t *top = item + parent_tuple->len - 1;
// get the base objects (they should be type objects)
size_t len = self->bases_tuple->len;
mp_obj_t *items = self->bases_tuple->items;
if (len == 0) {
return false;
}
// iterate through the base objects
for (size_t i = 0; i < len - 1; i++) {
if (mp_obj_is_subclass_fast(items[i], classinfo)) {
return true;
// iterate through the base objects
for (; item < top; ++item) {
if (mp_obj_is_subclass_fast(*item, classinfo)) {
return true;
}
}
}
// search last base (simple tail recursion elimination)
object = items[len - 1];
// search last base (simple tail recursion elimination)
object = *item;
} else {
// type has 1 parent
object = MP_OBJ_FROM_PTR(self->parent);
}
}
}

View File

@ -39,7 +39,7 @@
#include "py/smallint.h"
// The current version of .mpy files
#define MPY_VERSION (1)
#define MPY_VERSION (2)
// The feature flags byte encodes the compile-time config options that
// affect the generate bytecode.

View File

@ -78,7 +78,7 @@ void mp_init(void) {
MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0;
MP_STATE_VM(mp_kbd_exception).traceback_len = 0;
MP_STATE_VM(mp_kbd_exception).traceback_data = NULL;
MP_STATE_VM(mp_kbd_exception).args = mp_const_empty_tuple;
MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
#endif
// call port specific initialization if any

View File

@ -131,6 +131,7 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_super_method(qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);

View File

@ -107,6 +107,7 @@ typedef enum {
MP_F_LOAD_BUILD_CLASS,
MP_F_LOAD_ATTR,
MP_F_LOAD_METHOD,
MP_F_LOAD_SUPER_METHOD,
MP_F_STORE_NAME,
MP_F_STORE_GLOBAL,
MP_F_STORE_ATTR,

View File

@ -245,6 +245,11 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("LOAD_METHOD %s", qstr_str(qst));
break;
case MP_BC_LOAD_SUPER_METHOD:
DECODE_QSTR;
printf("LOAD_SUPER_METHOD %s", qstr_str(qst));
break;
case MP_BC_LOAD_BUILD_CLASS:
printf("LOAD_BUILD_CLASS");
break;

View File

@ -376,6 +376,14 @@ dispatch_loop:
DISPATCH();
}
ENTRY(MP_BC_LOAD_SUPER_METHOD): {
MARK_EXC_IP_SELECTIVE();
DECODE_QSTR;
sp -= 1;
mp_load_super_method(qst, sp - 1);
DISPATCH();
}
ENTRY(MP_BC_LOAD_BUILD_CLASS):
MARK_EXC_IP_SELECTIVE();
PUSH(mp_load_build_class());

View File

@ -44,6 +44,7 @@ static const void *const entry_table[256] = {
[MP_BC_LOAD_GLOBAL] = &&entry_MP_BC_LOAD_GLOBAL,
[MP_BC_LOAD_ATTR] = &&entry_MP_BC_LOAD_ATTR,
[MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD,
[MP_BC_LOAD_SUPER_METHOD] = &&entry_MP_BC_LOAD_SUPER_METHOD,
[MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS,
[MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR,
[MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N,

View File

@ -45,6 +45,7 @@
// compiler configuration
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_RETURN_IF_EXPR (1)
// optimisations
#define MICROPY_OPT_COMPUTED_GOTO (1)
@ -123,6 +124,7 @@
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new
#define MICROPY_PY_MACHINE_SPI (1)

View File

@ -245,7 +245,7 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, cons
/// \classmethod \constructor(id, ...)
/// Create a new Pin object associated with the id. If additional arguments are given,
/// they are used to initialise the pin. See `init`.
STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// Run an argument through the mapper and return the result.
@ -567,7 +567,7 @@ const mp_obj_type_t pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = pin_print,
.make_new = pin_make_new,
.make_new = mp_pin_make_new,
.call = pin_call,
.protocol = &pin_pin_p,
.locals_dict = (mp_obj_t)&pin_locals_dict,

View File

@ -1302,6 +1302,7 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
} else if (mp_obj_is_callable(callback)) {
self->callback = callback;
uint8_t tim_id = self->timer->tim_id;
__HAL_TIM_CLEAR_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel));
if (tim_id == 1) {
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
#if defined(TIM8) // STM32F401 doesn't have a TIM8

View File

@ -20,3 +20,17 @@ class A:
def p(self):
print(str(super())[:18])
A().p()
# test compiler's handling of long expressions with super
class A:
bar = 123
def foo(self):
print('A foo')
return [1, 2, 3]
class B(A):
def foo(self):
print('B foo')
print(super().bar) # accessing attribute after super()
return super().foo().count(2) # calling a subsequent method
print(B().foo())

View File

@ -3,7 +3,7 @@
tok(4)
[ 4] rule(22) (n=4)
id(i)
[ 4] rule(45) (n=1)
[ 4] rule(44) (n=1)
NULL
[ 5] rule(8) (n=0)
NULL

View File

@ -150,3 +150,7 @@ class Class:
# delete name
del Class
# load super method
def f(self):
super().f()

View File

@ -7,7 +7,7 @@ arg names:
(N_EXC_STACK 0)
bc=-1 line=1
########
bc=\\d\+ line=152
bc=\\d\+ line=155
00 MAKE_FUNCTION \.\+
\\d\+ STORE_NAME f
\\d\+ MAKE_FUNCTION \.\+
@ -25,6 +25,8 @@ arg names:
\\d\+ CALL_FUNCTION n=2 nkw=0
\\d\+ STORE_NAME Class
\\d\+ DELETE_NAME Class
\\d\+ MAKE_FUNCTION \.\+
\\d\+ STORE_NAME f
\\d\+ LOAD_CONST_NONE
\\d\+ RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
@ -428,6 +430,23 @@ arg names:
10 STORE_NAME __qualname__
13 LOAD_CONST_NONE
14 RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
########
\.\+5b
arg names: self
(N_STATE 4)
(N_EXC_STACK 0)
bc=-1 line=1
bc=0 line=156
00 LOAD_GLOBAL super (cache=0)
\\d\+ LOAD_GLOBAL __class__ (cache=0)
\\d\+ LOAD_FAST 0
\\d\+ LOAD_SUPER_METHOD f
\\d\+ CALL_METHOD n=0 nkw=0
\\d\+ POP_TOP
\\d\+ LOAD_CONST_NONE
\\d\+ RETURN_VALUE
File cmdline/cmd_showbc.py, code block '<genexpr>' (descriptor: \.\+, bytecode @\.\+ bytes)
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
########

View File

@ -33,7 +33,7 @@ print(p.value(), s.value())
# test inverted, and using on/off methods
p = Pin()
s = machine.Signal(p, inverted=True)
s = machine.Signal(p, invert=True)
s.off()
print(p.value(), s.value())
s.on()

View File

@ -0,0 +1,54 @@
# This test checks previously known problem values for 32-bit ports.
# It's less useful for 64-bit ports.
try:
import uctypes
except ImportError:
import sys
print("SKIP")
sys.exit()
buf = b"12345678abcd"
struct = uctypes.struct(
uctypes.addressof(buf),
{"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4},
uctypes.LITTLE_ENDIAN
)
struct.f32 = 0x7fffffff
print(buf)
struct.f32 = 0x80000000
print(buf)
struct.f32 = 0xff010203
print(buf)
struct.f64 = 0x80000000
print(buf)
struct.f64 = 0x80000000 * 2
print(buf)
print("=")
buf = b"12345678abcd"
struct = uctypes.struct(
uctypes.addressof(buf),
{"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4},
uctypes.BIG_ENDIAN
)
struct.f32 = 0x7fffffff
print(buf)
struct.f32 = 0x80000000
print(buf)
struct.f32 = 0xff010203
print(buf)
struct.f64 = 0x80000000
print(buf)
struct.f64 = 0x80000000 * 2
print(buf)

View File

@ -0,0 +1,11 @@
b'\xff\xff\xff\x7f5678abcd'
b'\x00\x00\x00\x805678abcd'
b'\x03\x02\x01\xff5678abcd'
b'\x03\x02\x01\xff\x00\x00\x00\x80\x00\x00\x00\x00'
b'\x03\x02\x01\xff\x00\x00\x00\x00\x01\x00\x00\x00'
=
b'\x7f\xff\xff\xff5678abcd'
b'\x80\x00\x00\x005678abcd'
b'\xff\x01\x02\x035678abcd'
b'\xff\x01\x02\x03\x00\x00\x00\x00\x80\x00\x00\x00'
b'\xff\x01\x02\x03\x00\x00\x00\x01\x00\x00\x00\x00'

View File

@ -34,6 +34,41 @@ try:
except IndexError:
pass
# unsupported unary op
try:
~h
assert False
except TypeError:
pass
# pushing on full queue
h = utimeq(1)
h.push(1, 0, 0)
try:
h.push(2, 0, 0)
assert False
except IndexError:
pass
# popping into invalid type
try:
h.pop([])
assert False
except TypeError:
pass
# length
assert len(h) == 1
# peektime
assert h.peektime() == 1
# peektime with empty queue
try:
utimeq(1).peektime()
assert False
except IndexError:
pass
def pop_all(h):
l = []

View File

@ -0,0 +1,17 @@
# test super() operations which don't require allocation
import micropython
class A:
def foo(self):
print('A foo')
return 42
class B(A):
def foo(self):
print('B foo')
print(super().foo())
b = B()
micropython.heap_lock()
b.foo()
micropython.heap_unlock()

View File

@ -0,0 +1,3 @@
B foo
A foo
42

View File

@ -0,0 +1,13 @@
# test the micropython.kbd_intr() function
import micropython
try:
micropython.kbd_intr
except AttributeError:
print('SKIP')
import sys
sys.exit()
# just check we can actually call it
micropython.kbd_intr(3)

View File

View File

@ -49,15 +49,15 @@ def convert_regex_escapes(line):
return bytes(''.join(cs), 'utf8')
def run_micropython(pyb, args, test_file):
def run_micropython(pyb, args, test_file, is_special=False):
special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py', 'basics/builtin_help.py', 'thread/thread_exc2.py')
is_special = False
if pyb is None:
# run on PC
if test_file.startswith(('cmdline/', 'feature_check/')) or test_file in special_tests:
# special handling for tests of the unix cmdline program
is_special = True
if is_special:
# check for any cmdline options needed for this test
args = [MICROPYTHON]
with open(test_file, 'rb') as f:
@ -145,7 +145,7 @@ def run_micropython(pyb, args, test_file):
output_mupy = output_mupy.replace(b'\r\n', b'\n')
# don't try to convert the output if we should skip this test
if output_mupy == b'SKIP\n':
if output_mupy in (b'SKIP\n', b'CRASH'):
return output_mupy
if is_special or test_file in special_tests:
@ -189,7 +189,12 @@ def run_micropython(pyb, args, test_file):
return output_mupy
def run_tests(pyb, tests, args):
def run_feature_check(pyb, args, base_path, test_file):
return run_micropython(pyb, args, base_path + "/feature_check/" + test_file, is_special=True)
def run_tests(pyb, tests, args, base_path="."):
test_count = 0
testcase_count = 0
passed_count = 0
@ -204,39 +209,39 @@ def run_tests(pyb, tests, args):
skip_const = False
# Check if micropython.native is supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/native_check.py')
native = run_feature_check(pyb, args, base_path, 'native_check.py')
if native == b'CRASH':
skip_native = True
# Check if arbitrary-precision integers are supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/int_big.py')
native = run_feature_check(pyb, args, base_path, 'int_big.py')
if native != b'1000000000000000000000000000000000000000000000\n':
skip_int_big = True
# Check if set type (and set literals) is supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/set_check.py')
native = run_feature_check(pyb, args, base_path, 'set_check.py')
if native == b'CRASH':
skip_set_type = True
# Check if async/await keywords are supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/async_check.py')
native = run_feature_check(pyb, args, base_path, 'async_check.py')
if native == b'CRASH':
skip_async = True
# Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not
native = run_micropython(pyb, args, 'feature_check/const.py')
native = run_feature_check(pyb, args, base_path, 'const.py')
if native == b'CRASH':
skip_const = True
# Check if emacs repl is supported, and skip such tests if it's not
t = run_micropython(pyb, args, 'feature_check/repl_emacs_check.py')
t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py')
if not 'True' in str(t, 'ascii'):
skip_tests.add('cmdline/repl_emacs_keys.py')
upy_byteorder = run_micropython(pyb, args, 'feature_check/byteorder.py')
has_complex = run_micropython(pyb, args, 'feature_check/complex.py') == b'complex\n'
has_coverage = run_micropython(pyb, args, 'feature_check/coverage.py') == b'coverage\n'
cpy_byteorder = subprocess.check_output([CPYTHON3, 'feature_check/byteorder.py'])
upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py')
has_complex = run_feature_check(pyb, args, base_path, 'complex.py') == b'complex\n'
has_coverage = run_feature_check(pyb, args, base_path, 'coverage.py') == b'coverage\n'
cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py'])
skip_endian = (upy_byteorder != cpy_byteorder)
# Some tests shouldn't be run under Travis CI
@ -468,7 +473,11 @@ def main():
# clear search path to make sure tests use only builtin modules
os.environ['MICROPYPATH'] = ''
res = run_tests(pyb, tests, args)
# Even if we run completely different tests in a different directory,
# 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()
if not res:

View File

@ -57,7 +57,7 @@ class FreezeError(Exception):
return 'error while freezing %s: %s' % (self.rawcode.source_file, self.msg)
class Config:
MPY_VERSION = 1
MPY_VERSION = 2
MICROPY_LONGINT_IMPL_NONE = 0
MICROPY_LONGINT_IMPL_LONGLONG = 1
MICROPY_LONGINT_IMPL_MPZ = 2
@ -94,7 +94,7 @@ def make_opcode_format():
OC4(U, U, U, U), # 0x0c-0x0f
OC4(B, B, B, U), # 0x10-0x13
OC4(V, U, Q, V), # 0x14-0x17
OC4(B, U, V, V), # 0x18-0x1b
OC4(B, V, V, Q), # 0x18-0x1b
OC4(Q, Q, Q, Q), # 0x1c-0x1f
OC4(B, B, V, V), # 0x20-0x23
OC4(Q, Q, Q, B), # 0x24-0x27

View File

@ -425,9 +425,6 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_init();
// create keyboard interrupt object
MP_STATE_VM(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
char *home = getenv("HOME");
char *path = getenv("MICROPYPATH");
if (path == NULL) {

View File

@ -45,6 +45,7 @@
#endif
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_STACK_CHECK (1)
@ -156,6 +157,7 @@
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256)
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_ASYNC_KBD_INTR (1)
extern const struct _mp_obj_module_t mp_module_machine;
@ -283,7 +285,6 @@ void mp_unix_mark_exec(void);
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[50]; \
mp_obj_t keyboard_interrupt_obj; \
void *mmap_region_head; \
// We need to provide a declaration/definition of alloca()

View File

@ -32,6 +32,7 @@
#include <mpconfigport.h>
#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_PY_DELATTR_SETATTR (1)
#define MICROPY_PY_BUILTINS_HELP (1)

View File

@ -47,6 +47,7 @@
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_WARNINGS (0)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_STREAMS_NON_BLOCK (0)
@ -99,7 +100,6 @@ extern const struct _mp_obj_module_t mp_module_os;
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \
#define MICROPY_PORT_ROOT_POINTERS \
mp_obj_t keyboard_interrupt_obj;
//////////////////////////////////////////
// Do not change anything beyond this line

View File

@ -40,20 +40,20 @@
STATIC void sighandler(int signum) {
if (signum == SIGINT) {
#if MICROPY_ASYNC_KBD_INTR
mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
sigset_t mask;
sigemptyset(&mask);
// On entry to handler, its signal is blocked, and unblocked on
// normal exit. As we instead perform longjmp, unblock it manually.
sigprocmask(SIG_SETMASK, &mask, NULL);
nlr_raise(MP_STATE_VM(keyboard_interrupt_obj));
nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
#else
if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
// this is the second time we are called, so die straight away
exit(1);
}
mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
#endif
}
}

View File

@ -32,17 +32,20 @@
#endif
#define MICROPY_ALLOC_PATH_MAX (260) //see minwindef.h for msvc or limits.h for mingw
#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1)
#define MICROPY_MEM_STATS (1)
#define MICROPY_DEBUG_PRINTERS (1)
#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print
#define MICROPY_READER_POSIX (1)
#define MICROPY_USE_READLINE_HISTORY (1)
#define MICROPY_HELPER_REPL (1)
@ -59,11 +62,14 @@
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_DESCRIPTORS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
#define MICROPY_PY_BUILTINS_STR_CENTER (1)
#define MICROPY_PY_BUILTINS_STR_PARTITION (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_COMPILE (1)
#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1)
#define MICROPY_PY_BUILTINS_POW3 (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
@ -83,27 +89,35 @@
#define MICROPY_STACKLESS (0)
#define MICROPY_STACKLESS_STRICT (0)
#define MICROPY_PY_UTIME (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UTIMEQ (1)
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_UBINASCII (1)
#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_URANDOM (1)
#define MICROPY_PY_UTIME (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr
#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
#define MICROPY_WARNINGS (1)
#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
#ifdef _MSC_VER
#define MICROPY_GCREGS_SETJMP (1)
#endif
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256)
#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_PORT_INIT_FUNC init()
#define MICROPY_PORT_DEINIT_FUNC deinit()
@ -161,8 +175,7 @@ extern const struct _mp_obj_module_t mp_module_time;
#if MICROPY_USE_READLINE == 1
#define MICROPY_PORT_ROOT_POINTERS \
char *readline_hist[50]; \
mp_obj_t keyboard_interrupt_obj;
char *readline_hist[50];
#endif
#define MP_STATE_PORT MP_STATE_VM

View File

@ -15,6 +15,7 @@
<ClCompile Include="$(PyBaseDir)unix\modmachine.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_mem.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_pinbase.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_pulse.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_signal.c" />
<ClCompile Include="$(PyBaseDir)extmod\modubinascii.c" />
<ClCompile Include="$(PyBaseDir)extmod\moductypes.c" />
@ -23,6 +24,7 @@
<ClCompile Include="$(PyBaseDir)extmod\modujson.c" />
<ClCompile Include="$(PyBaseDir)extmod\modurandom.c" />
<ClCompile Include="$(PyBaseDir)extmod\modure.c" />
<ClCompile Include="$(PyBaseDir)extmod\modutimeq.c" />
<ClCompile Include="$(PyBaseDir)extmod\moduzlib.c" />
<ClCompile Include="$(PyBaseDir)extmod\utime_mphal.c" />
<ClCompile Include="$(PyBaseDir)extmod\virtpin.c" />

View File

@ -79,12 +79,12 @@ void mp_hal_stdio_mode_orig(void) {
// the thread created for handling it might not be running yet so we'd miss the notification.
BOOL WINAPI console_sighandler(DWORD evt) {
if (evt == CTRL_C_EVENT) {
if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
// this is the second time we are called, so die straight away
exit(1);
}
mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
return TRUE;
}
return FALSE;

View File

@ -66,6 +66,10 @@ void init_zephyr(void) {
#ifdef CONFIG_NET_IPV4
static struct in_addr in4addr_my = {{{192, 0, 2, 1}}};
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0);
static struct in_addr in4netmask_my = {{{255, 255, 255, 0}}};
net_if_ipv4_set_netmask(net_if_get_default(), &in4netmask_my);
static struct in_addr in4gw_my = {{{192, 0, 2, 2}}};
net_if_ipv4_set_gw(net_if_get_default(), &in4gw_my);
#endif
#ifdef CONFIG_NET_IPV6
// 2001:db8::1

View File

@ -28,6 +28,7 @@
#include <stdint.h>
#include <stdio.h>
#include <misc/reboot.h>
#include "py/obj.h"
#include "py/runtime.h"
@ -40,7 +41,8 @@
#if MICROPY_PY_MACHINE
STATIC mp_obj_t machine_reset(void) {
printf("Warning: %s is not implemented\n", __func__);
sys_reboot(SYS_REBOOT_COLD);
// Won't get here, Zephyr has infiniloop on its side
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
@ -53,7 +55,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
#ifdef CONFIG_REBOOT
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },

View File

@ -36,7 +36,8 @@
#include <net/net_context.h>
#include <net/nbuf.h>
#if 0 // print debugging info
#define DEBUG 0
#if DEBUG // print debugging info
#define DEBUG_printf printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
@ -119,8 +120,6 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
// to the fact that it copies data byte by byte).
static char *net_buf_gather(struct net_buf *buf, char *to, unsigned max_len) {
struct net_buf *tmp = buf->frags;
unsigned header_len = net_nbuf_appdata(buf) - tmp->data;
net_buf_pull(tmp, header_len);
while (tmp && max_len) {
unsigned len = tmp->len;
@ -144,6 +143,9 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
DEBUG_printf(" (sz=%d, l=%d), token: %p", net_buf->size, net_buf->len, net_nbuf_token(net_buf));
}
DEBUG_printf("\n");
#if DEBUG > 1
net_nbuf_print_frags(net_buf);
#endif
// if net_buf == NULL, EOF
if (net_buf == NULL) {
@ -162,6 +164,10 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
// Make sure that "EOF flag" is not set
net_nbuf_set_buf_sent(net_buf, false);
// We don't care about packet header, so get rid of it asap
unsigned header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
net_buf_pull(net_buf->frags, header_len);
// net_buf->frags will be overwritten by fifo, so save it
net_nbuf_set_token(net_buf, net_buf->frags);
k_fifo_put(&socket->recv_q, net_buf);
@ -302,14 +308,22 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
struct net_buf *send_buf = net_nbuf_get_tx(socket->ctx, K_FOREVER);
// TODO: Probably should limit how much data we send in one call still
if (!net_nbuf_append(send_buf, bufinfo.len, bufinfo.buf, K_FOREVER)) {
mp_raise_OSError(ENOSPC);
unsigned len = net_if_get_mtu(net_context_get_iface(socket->ctx));
// Arbitrary value to account for protocol headers
len -= 64;
if (len > bufinfo.len) {
len = bufinfo.len;
}
if (!net_nbuf_append(send_buf, len, bufinfo.buf, K_FOREVER)) {
len = net_buf_frags_len(send_buf);
//mp_raise_OSError(ENOSPC);
}
RAISE_ERRNO(net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL));
return mp_obj_new_int_from_uint(bufinfo.len);
return mp_obj_new_int_from_uint(len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
@ -346,15 +360,13 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return mp_const_empty_bytes;
}
unsigned header_len = 0;
if (socket->cur_buf == NULL) {
DEBUG_printf("TCP recv: no cur_buf, getting\n");
struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
// Restore ->frags overwritten by fifo
net_buf->frags = net_nbuf_token(net_buf);
header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
DEBUG_printf("TCP recv: new cur_buf: %p, hdr_len: %u\n", net_buf, header_len);
DEBUG_printf("TCP recv: new cur_buf: %p\n", net_buf);
socket->cur_buf = net_buf;
}
@ -364,7 +376,6 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
assert(0);
}
net_buf_pull(frag, header_len);
unsigned frag_len = frag->len;
recv_len = frag_len;
if (recv_len > max_len) {

View File

@ -1,4 +1,5 @@
CONFIG_LEGACY_KERNEL=n
CONFIG_REBOOT=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y