Merge branch 'master' into nrf5_no_sdk
This commit is contained in:
commit
360243af92
11
README.md
11
README.md
@ -1,8 +1,4 @@
|
||||
[![Build Status][travis-img]][travis-repo] [![Coverage Status][coveralls-img]][coveralls-repo]
|
||||
[travis-img]: https://travis-ci.org/micropython/micropython.png?branch=master
|
||||
[travis-repo]: https://travis-ci.org/micropython/micropython
|
||||
[coveralls-img]: https://coveralls.io/repos/micropython/micropython/badge.png?branch=master
|
||||
[coveralls-repo]: https://coveralls.io/r/micropython/micropython?branch=master
|
||||
[](https://travis-ci.org/micropython/micropython) [](https://coveralls.io/r/micropython/micropython?branch=master)
|
||||
|
||||
The MicroPython project
|
||||
=======================
|
||||
@ -38,7 +34,9 @@ Major components in this repository:
|
||||
- minimal/ -- a minimal MicroPython port. Start with this if you want
|
||||
to port MicroPython to another microcontroller.
|
||||
- tests/ -- test framework and test scripts.
|
||||
- docs/ -- user documentation in Sphinx reStructuredText format.
|
||||
- docs/ -- user documentation in Sphinx reStructuredText format. Rendered
|
||||
HTML documentation is available at http://docs.micropython.org (be sure
|
||||
to select needed board/port at the bottom left corner).
|
||||
|
||||
Additional components:
|
||||
- bare-arm/ -- a bare minimum version of MicroPython for ARM MCUs. Used
|
||||
@ -48,6 +46,7 @@ Additional components:
|
||||
- pic16bit/ -- a version of MicroPython for 16-bit PIC microcontrollers.
|
||||
- cc3200/ -- a version of MicroPython that runs on the CC3200 from TI.
|
||||
- esp8266/ -- an experimental port for ESP8266 WiFi modules.
|
||||
- extmod/ -- additional (non-core) modules implemented in C.
|
||||
- tools/ -- various tools, including the pyboard.py module.
|
||||
- examples/ -- a few example Python scripts.
|
||||
|
||||
|
@ -13,7 +13,7 @@ INC += -I..
|
||||
INC += -I$(BUILD)
|
||||
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
|
||||
#Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
|
@ -46,8 +46,6 @@
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define BYTES_PER_WORD (4)
|
||||
|
||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
|
||||
|
||||
#define UINT_FMT "%lu"
|
||||
|
@ -20,7 +20,7 @@ include ../py/mkenv.mk
|
||||
CROSS_COMPILE ?= arm-none-eabi-
|
||||
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -march=armv7e-m -mabi=aapcs -mcpu=cortex-m4 -msoft-float -mfloat-abi=soft -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
|
||||
CFLAGS = -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) -Os
|
||||
CFLAGS += -g -ffunction-sections -fdata-sections -fno-common -fsigned-char -mno-unaligned-access
|
||||
CFLAGS += -Iboards/$(BOARD)
|
||||
CFLAGS += $(CFLAGS_MOD)
|
||||
|
@ -18,9 +18,6 @@ APP_INC += -Iutil
|
||||
APP_INC += -Ibootmgr
|
||||
APP_INC += -I$(BUILD)
|
||||
APP_INC += -I$(BUILD)/genhdr
|
||||
APP_INC += -I../lib/mp-readline
|
||||
APP_INC += -I../lib/netutils
|
||||
APP_INC += -I../lib/timeutils
|
||||
APP_INC += -I../stmhal
|
||||
|
||||
APP_CPPDEFINES = -Dgcc -DTARGET_IS_CC3200 -DSL_FULL -DUSE_FREERTOS
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "py/mpstate.h"
|
||||
#include "py/obj.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "extmod/vfs.h"
|
||||
#include "extmod/vfs_fat.h"
|
||||
@ -48,7 +49,6 @@
|
||||
#include "fifo.h"
|
||||
#include "socketfifo.h"
|
||||
#include "updater.h"
|
||||
#include "timeutils.h"
|
||||
#include "moduos.h"
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -111,10 +111,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info)
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_t machine_freq(void) {
|
||||
mp_obj_t tuple[1] = {
|
||||
mp_obj_new_int(HAL_FCPU_HZ),
|
||||
};
|
||||
return mp_obj_new_tuple(1, tuple);
|
||||
return mp_obj_new_int(HAL_FCPU_HZ);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "py/objtuple.h"
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "lib/oofatfs/diskio.h"
|
||||
#include "genhdr/mpversion.h"
|
||||
@ -43,7 +44,6 @@
|
||||
#include "random.h"
|
||||
#include "mpexception.h"
|
||||
#include "version.h"
|
||||
#include "timeutils.h"
|
||||
#include "pybsd.h"
|
||||
#include "pybuart.h"
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "py/objstr.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/stream.h"
|
||||
#include "netutils.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
#include "modnetwork.h"
|
||||
#include "modusocket.h"
|
||||
#include "mpexception.h"
|
||||
@ -737,7 +737,7 @@ STATIC const mp_obj_type_t socket_type = {
|
||||
// function usocket.getaddrinfo(host, port)
|
||||
/// \function getaddrinfo(host, port)
|
||||
STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
||||
mp_uint_t hlen;
|
||||
size_t hlen;
|
||||
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
||||
mp_int_t port = mp_obj_get_int(port_in);
|
||||
|
||||
|
@ -33,8 +33,8 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/smallint.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
#include "timeutils.h"
|
||||
#include "inc/hw_types.h"
|
||||
#include "inc/hw_ints.h"
|
||||
#include "inc/hw_memmap.h"
|
||||
@ -102,7 +102,7 @@ STATIC mp_obj_t time_localtime(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
|
||||
|
||||
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
mp_obj_t *elem;
|
||||
|
||||
mp_obj_get_array(tuple, &len, &elem);
|
||||
@ -131,24 +131,6 @@ STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep);
|
||||
|
||||
STATIC mp_obj_t time_sleep_ms (mp_obj_t ms_in) {
|
||||
mp_int_t ms = mp_obj_get_int(ms_in);
|
||||
if (ms > 0) {
|
||||
mp_hal_delay_ms(ms);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms);
|
||||
|
||||
STATIC mp_obj_t time_sleep_us (mp_obj_t usec_in) {
|
||||
mp_int_t usec = mp_obj_get_int(usec_in);
|
||||
if (usec > 0) {
|
||||
mp_hal_delay_us(usec);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us);
|
||||
|
||||
STATIC const mp_map_elem_t time_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) },
|
||||
|
||||
@ -158,8 +140,8 @@ STATIC const mp_map_elem_t time_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj },
|
||||
|
||||
// MicroPython additions
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj },
|
||||
|
@ -773,7 +773,7 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
|
||||
wlan_validate_mode(mode);
|
||||
|
||||
// get the ssid
|
||||
mp_uint_t ssid_len = 0;
|
||||
size_t ssid_len = 0;
|
||||
const char *ssid = NULL;
|
||||
if (args[1].u_obj != NULL) {
|
||||
ssid = mp_obj_str_get_data(args[1].u_obj, &ssid_len);
|
||||
@ -782,7 +782,7 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
|
||||
|
||||
// get the auth config
|
||||
uint8_t auth = SL_SEC_TYPE_OPEN;
|
||||
mp_uint_t key_len = 0;
|
||||
size_t key_len = 0;
|
||||
const char *key = NULL;
|
||||
if (args[2].u_obj != mp_const_none) {
|
||||
mp_obj_t *sec;
|
||||
@ -922,13 +922,13 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
||||
mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get the ssid
|
||||
mp_uint_t ssid_len;
|
||||
size_t ssid_len;
|
||||
const char *ssid = mp_obj_str_get_data(args[0].u_obj, &ssid_len);
|
||||
wlan_validate_ssid_len(ssid_len);
|
||||
|
||||
// get the auth config
|
||||
uint8_t auth = SL_SEC_TYPE_OPEN;
|
||||
mp_uint_t key_len = 0;
|
||||
size_t key_len = 0;
|
||||
const char *key = NULL;
|
||||
if (args[1].u_obj != mp_const_none) {
|
||||
mp_obj_t *sec;
|
||||
@ -1077,7 +1077,7 @@ STATIC mp_obj_t wlan_ssid (mp_uint_t n_args, const mp_obj_t *args) {
|
||||
if (n_args == 1) {
|
||||
return mp_obj_new_str((const char *)self->ssid, strlen((const char *)self->ssid), false);
|
||||
} else {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *ssid = mp_obj_str_get_data(args[1], &len);
|
||||
wlan_validate_ssid_len(len);
|
||||
wlan_set_ssid(ssid, len, false);
|
||||
@ -1101,7 +1101,7 @@ STATIC mp_obj_t wlan_auth (mp_uint_t n_args, const mp_obj_t *args) {
|
||||
} else {
|
||||
// get the auth config
|
||||
uint8_t auth = SL_SEC_TYPE_OPEN;
|
||||
mp_uint_t key_len = 0;
|
||||
size_t key_len = 0;
|
||||
const char *key = NULL;
|
||||
if (args[1] != mp_const_none) {
|
||||
mp_obj_t *sec;
|
||||
|
@ -278,6 +278,8 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
|
||||
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
} else {
|
||||
mp_raise_OSError(MP_EIO);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "inc/hw_types.h"
|
||||
#include "inc/hw_ints.h"
|
||||
#include "inc/hw_memmap.h"
|
||||
@ -37,7 +38,6 @@
|
||||
#include "pybrtc.h"
|
||||
#include "mpirq.h"
|
||||
#include "pybsleep.h"
|
||||
#include "timeutils.h"
|
||||
#include "simplelink.h"
|
||||
#include "modnetwork.h"
|
||||
#include "modwlan.h"
|
||||
@ -196,7 +196,7 @@ STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) {
|
||||
|
||||
// set date and time
|
||||
mp_obj_t *items;
|
||||
uint len;
|
||||
size_t len;
|
||||
mp_obj_get_array(datetime, &len, &items);
|
||||
|
||||
// verify the tuple
|
||||
|
@ -375,10 +375,13 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
|
||||
config |= UART_CONFIG_PAR_NONE;
|
||||
} else {
|
||||
uint parity = mp_obj_get_int(args[2].u_obj);
|
||||
if (parity != UART_CONFIG_PAR_ODD && parity != UART_CONFIG_PAR_EVEN) {
|
||||
if (parity == 0) {
|
||||
config |= UART_CONFIG_PAR_EVEN;
|
||||
} else if (parity == 1) {
|
||||
config |= UART_CONFIG_PAR_ODD;
|
||||
} else {
|
||||
goto error;
|
||||
}
|
||||
config |= parity;
|
||||
}
|
||||
// stop bits
|
||||
config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
|
||||
@ -388,7 +391,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
|
||||
uint flowcontrol = UART_FLOWCONTROL_NONE;
|
||||
if (pins_o != mp_const_none) {
|
||||
mp_obj_t *pins;
|
||||
mp_uint_t n_pins = 2;
|
||||
size_t n_pins = 2;
|
||||
if (pins_o == MP_OBJ_NULL) {
|
||||
// use the default pins
|
||||
pins = (mp_obj_t *)pyb_uart_def_pin[self->uart_id];
|
||||
@ -454,7 +457,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
|
||||
if (args[0].u_obj == MP_OBJ_NULL) {
|
||||
if (args[5].u_obj != MP_OBJ_NULL) {
|
||||
mp_obj_t *pins;
|
||||
mp_uint_t n_pins = 2;
|
||||
size_t n_pins = 2;
|
||||
mp_obj_get_array(args[5].u_obj, &n_pins, &pins);
|
||||
// check the Tx pin (or the Rx if Tx is None)
|
||||
if (pins[0] == mp_const_none) {
|
||||
@ -577,8 +580,6 @@ STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
|
||||
|
||||
// class constants
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EVEN), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_EVEN) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ODD), MP_OBJ_NEW_SMALL_INT(UART_CONFIG_PAR_ODD) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_RX_ANY), MP_OBJ_NEW_SMALL_INT(UART_TRIGGER_RX_ANY) },
|
||||
};
|
||||
|
||||
|
@ -200,7 +200,6 @@ extern const struct _mp_obj_module_t mp_module_ussl;
|
||||
|
||||
|
||||
// type definitions for the specific machine
|
||||
#define BYTES_PER_WORD (4)
|
||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
|
||||
#define MP_SSIZE_MAX (0x7FFFFFFF)
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/mphal.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "lib/oofatfs/diskio.h"
|
||||
#include "extmod/vfs.h"
|
||||
@ -51,7 +52,6 @@
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "gccollect.h"
|
||||
#include "gchelper.h"
|
||||
#include "readline.h"
|
||||
#include "mperror.h"
|
||||
#include "simplelink.h"
|
||||
#include "modnetwork.h"
|
||||
|
@ -107,8 +107,16 @@ This will allow to keep the structure of your application clear, as well as
|
||||
allow to install multiple applications on a board, and switch among them.
|
||||
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
Real-time clock
|
||||
---------------
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As
|
||||
a workaround, to measure short enough intervals you can use
|
||||
``utime.time()``, etc. functions, and for wall clock time, synchronize from
|
||||
the net using included ``ntpdate.py`` module.
|
||||
|
||||
Due to limitations of the ESP8266 chip the internal real-time clock (RTC)
|
||||
will overflow every 7:45h. If a long-term working RTC time is required then
|
||||
|
144
docs/library/btree.rst
Normal file
144
docs/library/btree.rst
Normal file
@ -0,0 +1,144 @@
|
||||
:mod:`btree` -- simple BTree database
|
||||
=====================================
|
||||
|
||||
.. module:: btree
|
||||
:synopsis: simple BTree database
|
||||
|
||||
The ``btree`` module implements a simple key-value database using external
|
||||
storage (disk files, or in general case, a random-access stream). Keys are
|
||||
stored sorted in the database, and besides efficient retrieval by a key
|
||||
value, a database also supports efficient ordered range scans (retrieval
|
||||
of values with the keys in a given range). On the application interface
|
||||
side, BTree database work as close a possible to a way standard `dict`
|
||||
type works, one notable difference is that both keys and values must
|
||||
be `bytes` objects (so, if you want to store objects of other types, you
|
||||
need to serialize them to `bytes` first).
|
||||
|
||||
The module is based on the well-known BerkelyDB library, version 1.xx.
|
||||
|
||||
Example::
|
||||
|
||||
import btree
|
||||
|
||||
# First, we need to open a stream which holds a database
|
||||
# This is usually a file, but can be in-memory database
|
||||
# using uio.BytesIO, a raw flash section, etc.
|
||||
f = open("mydb", "w+b")
|
||||
|
||||
# Now open a database itself
|
||||
db = btree.open(f)
|
||||
|
||||
# The keys you add will be sorted internally in the database
|
||||
db[b"3"] = b"three"
|
||||
db[b"1"] = b"one"
|
||||
db[b"2"] = b"two"
|
||||
|
||||
# Prints b'two'
|
||||
print(db[b"2"])
|
||||
|
||||
# Iterate over sorted keys in the database, starting from b"2"
|
||||
# until the end of the database, returning only values.
|
||||
# Mind that arguments passed to values() method are *key* values.
|
||||
# Prints:
|
||||
# b'two'
|
||||
# b'three'
|
||||
for word in db.values(b"2"):
|
||||
print(word)
|
||||
|
||||
del db[b"2"]
|
||||
|
||||
# No longer true, prints False
|
||||
print(b"2" in db)
|
||||
|
||||
# Prints:
|
||||
# b"1"
|
||||
# b"3"
|
||||
for key in db:
|
||||
print(key)
|
||||
|
||||
db.close()
|
||||
|
||||
# Don't forget to close the underlying stream!
|
||||
f.close()
|
||||
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
.. function:: open(stream, \*, flags=0, cachesize=0, pagesize=0, minkeypage=0)
|
||||
|
||||
Open a database from a random-access `stream` (like an open file). All
|
||||
other parameters are optional and keyword-only, and allow to tweak advanced
|
||||
paramters of the database operation (most users will not need them):
|
||||
|
||||
* `flags` - Currently unused.
|
||||
* `cachesize` - Suggested maximum memory cache size in bytes. For a
|
||||
board with enough memory using larger values may improve performance.
|
||||
The value is only a recommendation, the module may use more memory if
|
||||
values set too low.
|
||||
* `pagesize` - Page size used for the nodes in BTree. Acceptable range
|
||||
is 512-65536. If 0, underlying I/O block size will be used (the best
|
||||
compromise between memory usage and performance).
|
||||
* `minkeypage` - Minimum number of keys to store per page. Default value
|
||||
of 0 equivalent to 2.
|
||||
|
||||
Returns a `BTree` object, which implements a dictionary protocol (set
|
||||
of methods), and some additional methods described below.
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
.. method:: btree.close()
|
||||
|
||||
Close the database. It's mandatory to close the database at the end of
|
||||
processing, as some unwritten data may be still in the cache. Note that
|
||||
this does not close underlying streamw with which the database was opened,
|
||||
it should be closed separately (which is also mandatory to make sure that
|
||||
data flushed from buffer to the underlying storage).
|
||||
|
||||
.. method:: btree.flush()
|
||||
|
||||
Flush any data in cache to the underlying stream.
|
||||
|
||||
.. method:: btree.__getitem__(key)
|
||||
.. method:: btree.get(key, default=None)
|
||||
.. method:: btree.__setitem__(key, val)
|
||||
.. method:: btree.__detitem__(key)
|
||||
.. method:: btree.__contains__(key)
|
||||
|
||||
Standard dictionary methods.
|
||||
|
||||
.. method:: btree.__iter__()
|
||||
|
||||
A BTree object can be iterated over directly (similar to a dictionary)
|
||||
to get access to all keys in order.
|
||||
|
||||
.. method:: btree.keys([start_key, [end_key, [flags]]])
|
||||
.. method:: btree.values([start_key, [end_key, [flags]]])
|
||||
.. method:: btree.items([start_key, [end_key, [flags]]])
|
||||
|
||||
These methods are similar to standard dictionary methods, but also can
|
||||
take optional parameters to iterate over a key sub-range, instead of
|
||||
the entire database. Note that for all 3 methods, `start_key` and
|
||||
`end_key` arguments represent key values. For example, ``values()``
|
||||
method will iterate over values corresponding to they key range
|
||||
given. None values for `start_key` means "from the first key", no
|
||||
`end_key` or its value of None means "until the end of database".
|
||||
By default, range is inclusive of `start_key` and exclusive of
|
||||
`end_key`, you can include `end_key` in iteration by passing `flags`
|
||||
of `btree.INCL`. You can iterate in descending key direction
|
||||
by passing `flags` of `btree.DESC`. The flags values can be ORed
|
||||
together.
|
||||
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: INCL
|
||||
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be inclusive of the end key.
|
||||
|
||||
.. data:: DESC
|
||||
|
||||
A flag for `keys()`, `values()`, `items()` methods to specify that
|
||||
scanning should be in descending direction of keys.
|
@ -67,6 +67,16 @@ All builtin functions are described here. They are also available via
|
||||
|
||||
.. class:: int()
|
||||
|
||||
.. classmethod:: from_bytes(bytes, byteorder)
|
||||
|
||||
In MicroPython, `byteorder` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. method:: to_bytes(size, byteorder)
|
||||
|
||||
In MicroPython, `byteorder` parameter must be positional (this is
|
||||
compatible with CPython).
|
||||
|
||||
.. function:: isinstance()
|
||||
|
||||
.. function:: issubclass()
|
||||
|
@ -116,9 +116,32 @@ Other methods
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: framebuf.MVLSB
|
||||
.. data:: framebuf.MONO_VLSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are vertically mapped with
|
||||
bit 0 being nearest the top of the screen. Consequently each byte occupies
|
||||
8 vertical pixels. Subsequent bytes appear at successive horizontal
|
||||
locations until the rightmost edge is reached. Further bytes are rendered
|
||||
at locations starting at the leftmost edge, 8 pixels lower.
|
||||
|
||||
.. data:: framebuf.MONO_HLSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are horizontally mapped.
|
||||
Each byte occupies 8 horizontal pixels with bit 0 being the leftmost.
|
||||
Subsequent bytes appear at successive horizontal locations until the
|
||||
rightmost edge is reached. Further bytes are rendered on the next row, one
|
||||
pixel lower.
|
||||
|
||||
.. data:: framebuf.MONO_HMSB
|
||||
|
||||
Monochrome (1-bit) color format
|
||||
This defines a mapping where the bits in a byte are horizontally mapped.
|
||||
Each byte occupies 8 horizontal pixels with bit 7 being the leftmost.
|
||||
Subsequent bytes appear at successive horizontal locations until the
|
||||
rightmost edge is reached. Further bytes are rendered on the next row, one
|
||||
pixel lower.
|
||||
|
||||
.. data:: framebuf.RGB565
|
||||
|
||||
|
@ -153,6 +153,7 @@ the following libraries.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
btree.rst
|
||||
framebuf.rst
|
||||
machine.rst
|
||||
micropython.rst
|
||||
|
@ -100,7 +100,7 @@ General Methods
|
||||
|
||||
Scan all I2C addresses between 0x08 and 0x77 inclusive and return a list of
|
||||
those that respond. A device responds if it pulls the SDA line low after
|
||||
its address (including a read bit) is sent on the bus.
|
||||
its address (including a write bit) is sent on the bus.
|
||||
|
||||
Note: on WiPy the I2C object must be in master mode for this method to be valid.
|
||||
|
||||
|
@ -38,58 +38,6 @@ Usage Model::
|
||||
# configure an irq callback
|
||||
p0.irq(lambda p:print(p))
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
On the WiPy board the pins are identified by their string id::
|
||||
|
||||
from machine import Pin
|
||||
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
||||
|
||||
You can also configure the Pin to generate interrupts. For instance::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
def pincb(pin):
|
||||
print(pin.id())
|
||||
|
||||
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
|
||||
pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
|
||||
# the callback can be triggered manually
|
||||
pin_int.irq()()
|
||||
# to disable the callback
|
||||
pin_int.irq().disable()
|
||||
|
||||
Now every time a falling edge is seen on the gpio pin, the callback will be
|
||||
executed. Caution: mechanical push buttons have "bounce" and pushing or
|
||||
releasing a switch will often generate multiple edges.
|
||||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
|
||||
explanation, along with various techniques for debouncing.
|
||||
|
||||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
For the ``drive`` parameter the strengths are:
|
||||
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
|
||||
For the ``alt`` parameter please refer to the pinout and alternate functions
|
||||
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
|
||||
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
||||
``wake`` parameter has the following properties:
|
||||
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
@ -277,16 +225,6 @@ Methods
|
||||
|
||||
This method returns a callback object.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. method:: Pin.alt_list()
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
Availability: WiPy.
|
||||
|
||||
|
||||
Attributes
|
||||
----------
|
||||
|
||||
|
@ -10,18 +10,6 @@ SS (Slave Select), to select a particular device on a bus with which
|
||||
communication takes place. Management of an SS signal should happen in
|
||||
user code (via machine.Pin class).
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
See usage model of I2C; SPI is very similar. Main difference is
|
||||
parameters to init the SPI bus::
|
||||
|
||||
from machine import SPI
|
||||
spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
|
||||
|
||||
Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
|
||||
1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
|
||||
sample data on the first or second clock edge respectively.
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
|
@ -15,17 +15,13 @@ UART objects can be created and initialised using::
|
||||
uart = UART(1, 9600) # init with given baudrate
|
||||
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
|
||||
|
||||
.. only:: port_machineoard
|
||||
Supported paramters differ on a board:
|
||||
|
||||
Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
|
||||
|
||||
*Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
|
||||
only 7 and 8 bits are supported.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Bits can be 5, 6, 7, 8. Parity can be ``None``, ``UART.EVEN`` or ``UART.ODD``. Stop can be 1 or 2.
|
||||
Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With `parity=None`,
|
||||
only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits
|
||||
are supported.
|
||||
|
||||
WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2.
|
||||
|
||||
A UART object acts like a stream object and reading and writing is done
|
||||
using the standard stream methods::
|
||||
@ -47,22 +43,12 @@ using the standard stream methods::
|
||||
|
||||
uart.any() # returns True if any characters waiting
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
To check if there is anything to be read, use::
|
||||
|
||||
uart.any() # returns the number of characters available for reading
|
||||
|
||||
Constructors
|
||||
------------
|
||||
|
||||
.. only:: port_wipy
|
||||
.. class:: UART(id, ...)
|
||||
|
||||
.. class:: UART(bus, ...)
|
||||
|
||||
Construct a UART object on the given bus. ``bus`` can be 0 or 1.
|
||||
If the bus is not given, the default one will be selected (0) or the selection
|
||||
will be made based on the given pins.
|
||||
Construct a UART object of the given id.
|
||||
|
||||
Methods
|
||||
-------
|
||||
@ -75,7 +61,7 @@ Methods
|
||||
|
||||
- ``baudrate`` is the clock rate.
|
||||
- ``bits`` is the number of bits per character, 7, 8 or 9.
|
||||
- ``parity`` is the parity, ``None``, ``UART.EVEN`` or ``UART.ODD``.
|
||||
- ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
|
||||
- ``stop`` is the number of stop bits, 1 or 2.
|
||||
- ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order).
|
||||
Any of the pins can be None if one wants the UART to operate with limited functionality.
|
||||
@ -159,11 +145,6 @@ Methods
|
||||
Constants
|
||||
---------
|
||||
|
||||
.. data:: UART.EVEN
|
||||
.. data:: UART.ODD
|
||||
|
||||
parity types (along with ``None``)
|
||||
|
||||
.. data:: UART.RX_ANY
|
||||
|
||||
IRQ trigger sources
|
||||
|
@ -52,16 +52,7 @@ Power related functions
|
||||
|
||||
.. function:: freq()
|
||||
|
||||
.. only:: not port_wipy
|
||||
|
||||
Returns CPU frequency in hertz.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
Returns a tuple of clock frequencies: ``(sysclk,)``
|
||||
These correspond to:
|
||||
|
||||
- sysclk: frequency of the CPU
|
||||
Returns CPU frequency in hertz.
|
||||
|
||||
.. function:: idle()
|
||||
|
||||
|
@ -37,36 +37,6 @@ Constructors
|
||||
|
||||
Create an MD5 hasher object and optionally feed ``data`` into it.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. class:: uhashlib.sha1([data[, block_size]])
|
||||
|
||||
Create a sha1 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
|
||||
|
||||
.. class:: uhashlib.sha256([data[, block_size]])
|
||||
|
||||
Create a sha256 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
|
||||
|
||||
.. admonition:: CPython extension
|
||||
:class: attention
|
||||
|
||||
Due to hardware implementation details of the WiPy, data must be buffered before being
|
||||
digested, which would make it impossible to calculate the hash of big blocks of data that
|
||||
do not fit in RAM. In this case, since most likely the total size of the data is known
|
||||
in advance, the size can be passed to the constructor and hence the HASH hardware engine
|
||||
of the WiPy can be properly initialized without needing buffering. If ``block_size`` is
|
||||
to be given, an initial chunk of ``data`` must be passed as well. **When using this extension,
|
||||
care must be taken to make sure that the length of all intermediate chunks (including the
|
||||
initial one) is a multiple of 4 bytes.** The last chunk may be of any length.
|
||||
|
||||
Example::
|
||||
|
||||
hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
|
||||
hash.update('1234') # also multiple of 4 bytes
|
||||
...
|
||||
hash.update('12345') # last chunk may be of any length
|
||||
hash.digest()
|
||||
|
||||
Methods
|
||||
-------
|
||||
|
||||
|
@ -61,28 +61,26 @@ Functions
|
||||
|
||||
Get the status of a file or directory.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_esp8266
|
||||
.. function:: statvfs(path)
|
||||
|
||||
.. function:: statvfs(path)
|
||||
Get the status of a fileystem.
|
||||
|
||||
Get the status of a fileystem.
|
||||
Returns a tuple with the filesystem information in the following order:
|
||||
|
||||
Returns a tuple with the filesystem information in the following order:
|
||||
* ``f_bsize`` -- file system block size
|
||||
* ``f_frsize`` -- fragment size
|
||||
* ``f_blocks`` -- size of fs in f_frsize units
|
||||
* ``f_bfree`` -- number of free blocks
|
||||
* ``f_bavail`` -- number of free blocks for unpriviliged users
|
||||
* ``f_files`` -- number of inodes
|
||||
* ``f_ffree`` -- number of free inodes
|
||||
* ``f_favail`` -- number of free inodes for unpriviliged users
|
||||
* ``f_flag`` -- mount flags
|
||||
* ``f_namemax`` -- maximum filename length
|
||||
|
||||
* ``f_bsize`` -- file system block size
|
||||
* ``f_frsize`` -- fragment size
|
||||
* ``f_blocks`` -- size of fs in f_frsize units
|
||||
* ``f_bfree`` -- number of free blocks
|
||||
* ``f_bavail`` -- number of free blocks for unpriviliged users
|
||||
* ``f_files`` -- number of inodes
|
||||
* ``f_ffree`` -- number of free inodes
|
||||
* ``f_favail`` -- number of free inodes for unpriviliged users
|
||||
* ``f_flag`` -- mount flags
|
||||
* ``f_namemax`` -- maximum filename length
|
||||
|
||||
Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
|
||||
and the ``f_flags`` parameter may return ``0`` as they can be unavailable
|
||||
in a port-specific implementation.
|
||||
Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
|
||||
and the ``f_flags`` parameter may return ``0`` as they can be unavailable
|
||||
in a port-specific implementation.
|
||||
|
||||
.. function:: sync()
|
||||
|
||||
|
@ -41,18 +41,6 @@ Functions
|
||||
|
||||
Create a new socket using the given address family, socket type and protocol number.
|
||||
|
||||
.. only:: port_wipy
|
||||
|
||||
.. note::
|
||||
|
||||
SSL sockets need to be created the following way before wrapping them with
|
||||
``ssl.wrap_socket``::
|
||||
|
||||
import socket
|
||||
import ssl
|
||||
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
|
||||
ss = ssl.wrap_socket(s)
|
||||
|
||||
.. function:: socket.getaddrinfo(host, port)
|
||||
|
||||
Translate the host/port argument into a sequence of 5-tuples that contain all the
|
||||
|
@ -55,60 +55,50 @@ Functions
|
||||
which expresses a time as per localtime. It returns an integer which is
|
||||
the number of seconds since Jan 1, 2000.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_esp8266
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds. Seconds can be a floating-point number to
|
||||
sleep for a fractional number of seconds. Note that other MicroPython ports may
|
||||
not accept floating-point argument, for compatibility with them use ``sleep_ms()``
|
||||
and ``sleep_us()`` functions.
|
||||
Sleep for the given number of seconds. Some boards may accept `seconds` as a
|
||||
floating-point number to sleep for a fractional number of seconds. Note that
|
||||
other boards may not accept a floating-point argument, for compatibility with
|
||||
them use ``sleep_ms()`` and ``sleep_us()`` functions.
|
||||
|
||||
.. only:: port_wipy
|
||||
.. function:: sleep_ms(ms)
|
||||
|
||||
.. function:: sleep(seconds)
|
||||
|
||||
Sleep for the given number of seconds.
|
||||
Delay for given number of milliseconds, should be positive or 0.
|
||||
|
||||
.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
|
||||
.. function:: sleep_us(us)
|
||||
|
||||
.. function:: sleep_ms(ms)
|
||||
Delay for given number of microseconds, should be positive or 0.
|
||||
|
||||
Delay for given number of milliseconds, should be positive or 0.
|
||||
.. function:: ticks_ms()
|
||||
|
||||
.. function:: sleep_us(us)
|
||||
Returns an increasing millisecond counter with an arbitrary reference point, that
|
||||
wraps around after some value. This value is not explicitly exposed, but we will
|
||||
refer to it as ``TICKS_MAX`` to simplify discussion. Period of the values is
|
||||
``TICKS_PERIOD = TICKS_MAX + 1``. ``TICKS_PERIOD`` is guaranteed to be a power of
|
||||
two, but otherwise may differ from port to port. The same period value is used
|
||||
for all of ``ticks_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (for
|
||||
simplicity). Thus, these functions will return a value in range [``0`` ..
|
||||
``TICKS_MAX``], inclusive, total ``TICKS_PERIOD`` values. Note that only
|
||||
non-negative values are used. For the most part, you should treat values returned
|
||||
by these functions as opaque. The only operations available for them are
|
||||
``ticks_diff()`` and ``ticks_add()`` functions described below.
|
||||
|
||||
Delay for given number of microseconds, should be positive or 0
|
||||
Note: Performing standard mathematical operations (+, -) or relational
|
||||
operators (<, <=, >, >=) directly on these value will lead to invalid
|
||||
result. Performing mathematical operations and then passing their results
|
||||
as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
|
||||
invalid results from the latter functions.
|
||||
|
||||
.. function:: ticks_ms()
|
||||
.. function:: ticks_us()
|
||||
|
||||
Returns an increasing millisecond counter with an arbitrary reference point,
|
||||
that wraps around after some value. This value is not explicitly exposed,
|
||||
but we will refer to it as `TICKS_MAX` to simplify discussion. Period of
|
||||
the values is `TICKS_PERIOD = TICKS_MAX + 1`. `TICKS_PERIOD` is guaranteed
|
||||
to be a power of two, but otherwise may differ from port to port. The same
|
||||
period value is used for all of ticks_ms(), ticks_us(), ticks_cpu() functions
|
||||
(for simplicity). Thus, these functions will return a value in range
|
||||
[0 .. `TICKS_MAX`], inclusive, total `TICKS_PERIOD` values. Note that only
|
||||
non-negative values are used. For the most part, you should treat values
|
||||
returned by these functions as opaque. The only operations available for them
|
||||
are ``ticks_diff()`` and ``ticks_add()`` functions described below.
|
||||
Just like ``ticks_ms()`` above, but in microseconds.
|
||||
|
||||
Note: Performing standard mathematical operations (+, -) or relational
|
||||
operators (<, <=, >, >=) directly on these value will lead to invalid
|
||||
result. Performing mathematical operations and then passing their results
|
||||
as arguments to ``ticks_diff()`` or ``ticks_add()`` will also lead to
|
||||
invalid results from the latter functions.
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
.. function:: ticks_us()
|
||||
|
||||
Just like ``ticks_ms`` above, but in microseconds.
|
||||
|
||||
.. function:: ticks_cpu()
|
||||
|
||||
Similar to ``ticks_ms`` and ``ticks_us``, but with the highest possible resolution
|
||||
Similar to ``ticks_ms()`` and ``ticks_us()``, but with the highest possible resolution
|
||||
in the system. This is usually CPU clocks, and that's why the function is named that
|
||||
way. But it doesn't have to a CPU clock, some other timing source available in a
|
||||
way. But it doesn't have to be a CPU clock, some other timing source available in a
|
||||
system (e.g. high-resolution timer) can be used instead. The exact timing unit
|
||||
(resolution) of this function is not specified on ``utime`` module level, but
|
||||
documentation for a specific port may provide more specific information. This
|
||||
@ -118,13 +108,13 @@ Functions
|
||||
Availability: Not every port implements this function.
|
||||
|
||||
|
||||
.. function:: ticks_add(ticks, delta)
|
||||
.. function:: ticks_add(ticks, delta)
|
||||
|
||||
Offset ticks value by a given number, which can be either positive or negative.
|
||||
Given a ``ticks`` value, this function allows to calculate ticks value ``delta``
|
||||
ticks before or after it, following modular-arithmetic definition of tick values
|
||||
(see ``ticks_ms()`` above). ``ticks`` parameter must be a direct result of call
|
||||
to ``tick_ms()``, ``ticks_us()``, ``ticks_cpu()`` functions (or from previous
|
||||
to ``ticks_ms()``, ``ticks_us()``, or ``ticks_cpu()`` functions (or from previous
|
||||
call to ``ticks_add()``). However, ``delta`` can be an arbitrary integer number
|
||||
or numeric expression. ``ticks_add()`` is useful for calculating deadlines for
|
||||
events/tasks. (Note: you must use ``ticks_diff()`` function to work with
|
||||
@ -133,35 +123,37 @@ Functions
|
||||
Examples::
|
||||
|
||||
# Find out what ticks value there was 100ms ago
|
||||
print(tick_add(time.ticks_ms(), -100))
|
||||
print(ticks_add(time.ticks_ms(), -100))
|
||||
|
||||
# Calculate deadline for operation and test for it
|
||||
deadline = tick_add(time.ticks_ms(), 200)
|
||||
deadline = ticks_add(time.ticks_ms(), 200)
|
||||
while ticks_diff(deadline, time.ticks_ms()) > 0:
|
||||
do_a_little_of_something()
|
||||
|
||||
# Find out TICKS_MAX used by this port
|
||||
print(tick_add(0, -1))
|
||||
print(ticks_add(0, -1))
|
||||
|
||||
|
||||
.. function:: ticks_diff(ticks1, ticks2)
|
||||
.. function:: ticks_diff(ticks1, ticks2)
|
||||
|
||||
Measure ticks difference between values returned from ticks_ms(), ticks_us(), or ticks_cpu()
|
||||
functions. The argument order is the same as for subtraction operator,
|
||||
``tick_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``. However, values returned by
|
||||
ticks_ms(), etc. functions may wrap around, so directly using subtraction on them will
|
||||
produce incorrect result. That is why ticks_diff() is needed, it implements modular
|
||||
(or more specifically, ring) arithmetics to produce correct result even for wrap-around
|
||||
values (as long as they not too distant inbetween, see below). The function returns
|
||||
**signed** value in the range [`-TICKS_PERIOD/2` .. `TICKS_PERIOD/2-1`] (that's a typical
|
||||
range definition for two's-complement signed binary integers). If the result is negative,
|
||||
it means that `ticks1` occured earlier in time than `ticks2`. Otherwise, it means that
|
||||
`ticks1` occured after `ticks2`. This holds `only` if `ticks1` and `ticks2` are apart from
|
||||
each other for no more than `TICKS_PERIOD/2-1` ticks. If that does not hold, incorrect
|
||||
result will be returned. Specifically, if 2 tick values are apart for `TICKS_PERIOD/2-1`
|
||||
ticks, that value will be returned by the function. However, if `TICKS_PERIOD/2` of
|
||||
real-time ticks has passed between them, the function will return `-TICKS_PERIOD/2`
|
||||
instead, i.e. result value will wrap around to the negative range of possible values.
|
||||
Measure ticks difference between values returned from ``ticks_ms()``, ``ticks_us()``,
|
||||
or ``ticks_cpu()`` functions. The argument order is the same as for subtraction
|
||||
operator, ``ticks_diff(ticks1, ticks2)`` has the same meaning as ``ticks1 - ticks2``.
|
||||
However, values returned by ``ticks_ms()``, etc. functions may wrap around, so
|
||||
directly using subtraction on them will produce incorrect result. That is why
|
||||
``ticks_diff()`` is needed, it implements modular (or more specifically, ring)
|
||||
arithmetics to produce correct result even for wrap-around values (as long as they not
|
||||
too distant inbetween, see below). The function returns **signed** value in the range
|
||||
[``-TICKS_PERIOD/2`` .. ``TICKS_PERIOD/2-1``] (that's a typical range definition for
|
||||
two's-complement signed binary integers). If the result is negative, it means that
|
||||
``ticks1`` occured earlier in time than ``ticks2``. Otherwise, it means that
|
||||
``ticks1`` occured after ``ticks2``. This holds ``only`` if ``ticks1`` and ``ticks2``
|
||||
are apart from each other for no more than ``TICKS_PERIOD/2-1`` ticks. If that does
|
||||
not hold, incorrect result will be returned. Specifically, if two tick values are
|
||||
apart for ``TICKS_PERIOD/2-1`` ticks, that value will be returned by the function.
|
||||
However, if ``TICKS_PERIOD/2`` of real-time ticks has passed between them, the
|
||||
function will return ``-TICKS_PERIOD/2`` instead, i.e. result value will wrap around
|
||||
to the negative range of possible values.
|
||||
|
||||
Informal rationale of the constraints above: Suppose you are locked in a room with no
|
||||
means to monitor passing of time except a standard 12-notch clock. Then if you look at
|
||||
@ -200,20 +192,21 @@ Functions
|
||||
print("Oops, running late, tell task to run faster!")
|
||||
task.run(run_faster=true)
|
||||
|
||||
Note: Do not pass ``time()`` values to ``ticks_diff()``, and should use
|
||||
Note: Do not pass ``time()`` values to ``ticks_diff()``, you should use
|
||||
normal mathematical operations on them. But note that ``time()`` may (and will)
|
||||
also overflow. This is known as https://en.wikipedia.org/wiki/Year_2038_problem .
|
||||
|
||||
|
||||
.. function:: time()
|
||||
|
||||
Returns the number of seconds, as an integer, since the Epoch, assuming that underlying
|
||||
RTC is set and maintained as described above. If an RTC is not set, this function returns
|
||||
number of seconds since a port-specific reference point in time (for embedded boards without
|
||||
a battery-backed RTC, usually since power up or reset). If you want to develop portable
|
||||
MicroPython application, you should not rely on this function to provide higher than second
|
||||
precision. If you need higher precision, use ``ticks_ms()`` and ``ticks_us()`` functions,
|
||||
if you need calendar time, ``localtime()`` without an argument is a better choice.
|
||||
Returns the number of seconds, as an integer, since the Epoch, assuming that
|
||||
underlying RTC is set and maintained as described above. If an RTC is not set, this
|
||||
function returns number of seconds since a port-specific reference point in time (for
|
||||
embedded boards without a battery-backed RTC, usually since power up or reset). If you
|
||||
want to develop portable MicroPython application, you should not rely on this function
|
||||
to provide higher than second precision. If you need higher precision, use
|
||||
``ticks_ms()`` and ``ticks_us()`` functions, if you need calendar time,
|
||||
``localtime()`` without an argument is a better choice.
|
||||
|
||||
.. admonition:: Difference to CPython
|
||||
:class: attention
|
||||
|
@ -179,3 +179,97 @@ Details on sleep modes
|
||||
* ``machine.sleep()``: 950uA (in WLAN STA mode). Wake sources are ``Pin``, ``RTC``
|
||||
and ``WLAN``
|
||||
* ``machine.deepsleep()``: ~350uA. Wake sources are ``Pin`` and ``RTC``.
|
||||
|
||||
Additional details for machine.Pin
|
||||
----------------------------------
|
||||
|
||||
On the WiPy board the pins are identified by their string id::
|
||||
|
||||
from machine import Pin
|
||||
g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
|
||||
|
||||
You can also configure the Pin to generate interrupts. For instance::
|
||||
|
||||
from machine import Pin
|
||||
|
||||
def pincb(pin):
|
||||
print(pin.id())
|
||||
|
||||
pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
|
||||
pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
|
||||
# the callback can be triggered manually
|
||||
pin_int.irq()()
|
||||
# to disable the callback
|
||||
pin_int.irq().disable()
|
||||
|
||||
Now every time a falling edge is seen on the gpio pin, the callback will be
|
||||
executed. Caution: mechanical push buttons have "bounce" and pushing or
|
||||
releasing a switch will often generate multiple edges.
|
||||
See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
|
||||
explanation, along with various techniques for debouncing.
|
||||
|
||||
All pin objects go through the pin mapper to come up with one of the
|
||||
gpio pins.
|
||||
|
||||
For the ``drive`` parameter the strengths are:
|
||||
|
||||
- ``Pin.LOW_POWER`` - 2mA drive capability.
|
||||
- ``Pin.MED_POWER`` - 4mA drive capability.
|
||||
- ``Pin.HIGH_POWER`` - 6mA drive capability.
|
||||
|
||||
For the ``alt`` parameter please refer to the pinout and alternate functions
|
||||
table at <https://raw.githubusercontent.com/wipy/wipy/master/docs/PinOUT.png>`_
|
||||
for the specific alternate functions that each pin supports.
|
||||
|
||||
For interrupts, the ``priority`` can take values in the range 1-7. And the
|
||||
``wake`` parameter has the following properties:
|
||||
|
||||
- If ``wake_from=machine.Sleep.ACTIVE`` any pin can wake the board.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, GP17`` or ``GP24`` can wake the board. Note that only 1
|
||||
of this pins can be enabled as a wake source at the same time, so, only
|
||||
the last enabled pin as a ``machine.Sleep.SUSPENDED`` wake source will have effect.
|
||||
- If ``wake_from=machine.Sleep.SUSPENDED`` pins ``GP2``, ``GP4``, ``GP10``,
|
||||
``GP11``, ``GP17`` and ``GP24`` can wake the board. In this case all of the
|
||||
6 pins can be enabled as a ``machine.Sleep.HIBERNATE`` wake source at the same time.
|
||||
|
||||
Additional Pin methods:
|
||||
|
||||
.. method:: machine.Pin.alt_list()
|
||||
|
||||
Returns a list of the alternate functions supported by the pin. List items are
|
||||
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
|
||||
|
||||
Known issues
|
||||
------------
|
||||
|
||||
Incompatible way to create SSL sockets
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
SSL sockets need to be created the following way before wrapping them with.
|
||||
``ssl.wrap_socket``::
|
||||
|
||||
import socket
|
||||
import ssl
|
||||
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
|
||||
ss = ssl.wrap_socket(s)
|
||||
|
||||
Incompatibilities in uhashlib module
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Due to hardware implementation details of the WiPy, data must be buffered before being
|
||||
digested, which would make it impossible to calculate the hash of big blocks of data that
|
||||
do not fit in RAM. In this case, since most likely the total size of the data is known
|
||||
in advance, the size can be passed to the constructor and hence the HASH hardware engine
|
||||
of the WiPy can be properly initialized without needing buffering. If ``block_size`` is
|
||||
to be given, an initial chunk of ``data`` must be passed as well. **When using this extension,
|
||||
care must be taken to make sure that the length of all intermediate chunks (including the
|
||||
initial one) is a multiple of 4 bytes.** The last chunk may be of any length.
|
||||
|
||||
Example::
|
||||
|
||||
hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
|
||||
hash.update('1234') # also multiple of 4 bytes
|
||||
...
|
||||
hash.update('12345') # last chunk may be of any length
|
||||
hash.digest()
|
||||
|
@ -2,7 +2,7 @@
|
||||
"""
|
||||
|
||||
from micropython import const
|
||||
import pyb
|
||||
import utime
|
||||
|
||||
# nRF24L01+ registers
|
||||
CONFIG = const(0x00)
|
||||
@ -53,22 +53,24 @@ class NRF24L01:
|
||||
def __init__(self, spi, cs, ce, channel=46, payload_size=16):
|
||||
assert payload_size <= 32
|
||||
|
||||
# init the SPI bus and pins
|
||||
spi.init(spi.MASTER, baudrate=4000000, polarity=0, phase=0, firstbit=spi.MSB)
|
||||
cs.init(cs.OUT_PP, cs.PULL_NONE)
|
||||
ce.init(ce.OUT_PP, ce.PULL_NONE)
|
||||
self.buf = bytearray(1)
|
||||
|
||||
# store the pins
|
||||
self.spi = spi
|
||||
self.cs = cs
|
||||
self.ce = ce
|
||||
|
||||
# init the SPI bus and pins
|
||||
self.init_spi(4000000)
|
||||
cs.init(cs.OUT, value=1)
|
||||
ce.init(ce.OUT, value=0)
|
||||
|
||||
# reset everything
|
||||
self.ce.low()
|
||||
self.cs.high()
|
||||
self.payload_size = payload_size
|
||||
self.pipe0_read_addr = None
|
||||
pyb.delay(5)
|
||||
utime.sleep_ms(5)
|
||||
|
||||
# set address width to 5 bytes and check for device present
|
||||
self.reg_write(SETUP_AW, 0b11)
|
||||
@ -98,28 +100,44 @@ class NRF24L01:
|
||||
self.flush_rx()
|
||||
self.flush_tx()
|
||||
|
||||
def init_spi(self, baudrate):
|
||||
try:
|
||||
master = self.spi.MASTER
|
||||
except AttributeError:
|
||||
self.spi.init(baudrate=baudrate, polarity=0, phase=0)
|
||||
else:
|
||||
self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
|
||||
|
||||
def reg_read(self, reg):
|
||||
self.cs.low()
|
||||
self.spi.send_recv(reg)
|
||||
buf = self.spi.recv(1)
|
||||
self.spi.readinto(self.buf, reg)
|
||||
self.spi.readinto(self.buf)
|
||||
self.cs.high()
|
||||
return buf[0]
|
||||
return self.buf[0]
|
||||
|
||||
def reg_write(self, reg, buf):
|
||||
def reg_write_bytes(self, reg, buf):
|
||||
self.cs.low()
|
||||
status = self.spi.send_recv(0x20 | reg)[0]
|
||||
self.spi.send(buf)
|
||||
self.spi.readinto(self.buf, 0x20 | reg)
|
||||
self.spi.write(buf)
|
||||
self.cs.high()
|
||||
return status
|
||||
return self.buf[0]
|
||||
|
||||
def reg_write(self, reg, value):
|
||||
self.cs.low()
|
||||
self.spi.readinto(self.buf, 0x20 | reg)
|
||||
ret = self.buf[0]
|
||||
self.spi.readinto(self.buf, value)
|
||||
self.cs.high()
|
||||
return ret
|
||||
|
||||
def flush_rx(self):
|
||||
self.cs.low()
|
||||
self.spi.send(FLUSH_RX)
|
||||
self.spi.readinto(self.buf, FLUSH_RX)
|
||||
self.cs.high()
|
||||
|
||||
def flush_tx(self):
|
||||
self.cs.low()
|
||||
self.spi.send(FLUSH_TX)
|
||||
self.spi.readinto(self.buf, FLUSH_TX)
|
||||
self.cs.high()
|
||||
|
||||
# power is one of POWER_x defines; speed is one of SPEED_x defines
|
||||
@ -144,8 +162,8 @@ class NRF24L01:
|
||||
# address should be a bytes object 5 bytes long
|
||||
def open_tx_pipe(self, address):
|
||||
assert len(address) == 5
|
||||
self.reg_write(RX_ADDR_P0, address)
|
||||
self.reg_write(TX_ADDR, address)
|
||||
self.reg_write_bytes(RX_ADDR_P0, address)
|
||||
self.reg_write_bytes(TX_ADDR, address)
|
||||
self.reg_write(RX_PW_P0, self.payload_size)
|
||||
|
||||
# address should be a bytes object 5 bytes long
|
||||
@ -157,7 +175,7 @@ class NRF24L01:
|
||||
if pipe_id == 0:
|
||||
self.pipe0_read_addr = address
|
||||
if pipe_id < 2:
|
||||
self.reg_write(RX_ADDR_P0 + pipe_id, address)
|
||||
self.reg_write_bytes(RX_ADDR_P0 + pipe_id, address)
|
||||
else:
|
||||
self.reg_write(RX_ADDR_P0 + pipe_id, address[0])
|
||||
self.reg_write(RX_PW_P0 + pipe_id, self.payload_size)
|
||||
@ -168,12 +186,12 @@ class NRF24L01:
|
||||
self.reg_write(STATUS, RX_DR | TX_DS | MAX_RT)
|
||||
|
||||
if self.pipe0_read_addr is not None:
|
||||
self.reg_write(RX_ADDR_P0, self.pipe0_read_addr)
|
||||
self.reg_write_bytes(RX_ADDR_P0, self.pipe0_read_addr)
|
||||
|
||||
self.flush_rx()
|
||||
self.flush_tx()
|
||||
self.ce.high()
|
||||
pyb.udelay(130)
|
||||
utime.sleep_us(130)
|
||||
|
||||
def stop_listening(self):
|
||||
self.ce.low()
|
||||
@ -187,8 +205,8 @@ class NRF24L01:
|
||||
def recv(self):
|
||||
# get the data
|
||||
self.cs.low()
|
||||
self.spi.send(R_RX_PAYLOAD)
|
||||
buf = self.spi.recv(self.payload_size)
|
||||
self.spi.readinto(self.buf, R_RX_PAYLOAD)
|
||||
buf = self.spi.read(self.payload_size)
|
||||
self.cs.high()
|
||||
# clear RX ready flag
|
||||
self.reg_write(STATUS, RX_DR)
|
||||
@ -198,9 +216,9 @@ class NRF24L01:
|
||||
# blocking wait for tx complete
|
||||
def send(self, buf, timeout=500):
|
||||
send_nonblock = self.send_start(buf)
|
||||
start = pyb.millis()
|
||||
start = utime.ticks_ms()
|
||||
result = None
|
||||
while result is None and pyb.elapsed_millis(start) < timeout:
|
||||
while result is None and utime.ticks_diff(utime.ticks_ms(), start) < timeout:
|
||||
result = self.send_done() # 1 == success, 2 == fail
|
||||
if result == 2:
|
||||
raise OSError("send failed")
|
||||
@ -209,18 +227,18 @@ class NRF24L01:
|
||||
def send_start(self, buf):
|
||||
# power up
|
||||
self.reg_write(CONFIG, (self.reg_read(CONFIG) | PWR_UP) & ~PRIM_RX)
|
||||
pyb.udelay(150)
|
||||
utime.sleep_us(150)
|
||||
# send the data
|
||||
self.cs.low()
|
||||
self.spi.send(W_TX_PAYLOAD)
|
||||
self.spi.send(buf)
|
||||
self.spi.readinto(self.buf, W_TX_PAYLOAD)
|
||||
self.spi.write(buf)
|
||||
if len(buf) < self.payload_size:
|
||||
self.spi.send(b'\x00' * (self.payload_size - len(buf))) # pad out data
|
||||
self.spi.write(b'\x00' * (self.payload_size - len(buf))) # pad out data
|
||||
self.cs.high()
|
||||
|
||||
# enable the chip so it can send the data
|
||||
self.ce.high()
|
||||
pyb.udelay(15) # needs to be >10us
|
||||
utime.sleep_us(15) # needs to be >10us
|
||||
self.ce.low()
|
||||
|
||||
# returns None if send still in progress, 1 for success, 2 for fail
|
||||
|
@ -25,9 +25,6 @@ ESP_SDK = $(shell $(CC) -print-sysroot)/usr
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I../stmhal
|
||||
INC += -I../lib/mp-readline
|
||||
INC += -I../lib/netutils
|
||||
INC += -I../lib/timeutils
|
||||
INC += -I$(BUILD)
|
||||
INC += -I$(ESP_SDK)/include
|
||||
|
||||
@ -41,7 +38,7 @@ CFLAGS_XTENSA = -fsingle-precision-constant -Wdouble-promotion \
|
||||
-Wl,-EL -mlongcalls -mtext-section-literals -mforce-l32 \
|
||||
-DLWIP_OPEN_SRC
|
||||
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -ansi -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
|
||||
CFLAGS = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib -DUART_OS=$(UART_OS) \
|
||||
$(CFLAGS_XTENSA) $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
LDSCRIPT = esp8266.ld
|
||||
@ -108,7 +105,7 @@ LIB_SRC_C = $(addprefix lib/,\
|
||||
libc/string0.c \
|
||||
libm/math.c \
|
||||
libm/fmodf.c \
|
||||
libm/roundf.c \
|
||||
libm/nearbyintf.c \
|
||||
libm/ef_sqrt.c \
|
||||
libm/kf_rem_pio2.c \
|
||||
libm/kf_sin.c \
|
||||
|
@ -100,6 +100,7 @@ SECTIONS
|
||||
*py/qstr.o*(.literal* .text*)
|
||||
*py/repl.o*(.literal* .text*)
|
||||
*py/runtime.o*(.literal* .text*)
|
||||
*py/scheduler.o*(.literal* .text*)
|
||||
*py/scope.o*(.literal* .text*)
|
||||
*py/sequence.o*(.literal* .text*)
|
||||
*py/showbc.o*(.literal* .text*)
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "ets_alt_task.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/mpstate.h"
|
||||
#include "py/runtime.h"
|
||||
#include "extmod/misc.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
|
||||
@ -130,11 +131,7 @@ void mp_hal_delay_ms(uint32_t delay) {
|
||||
|
||||
void ets_event_poll(void) {
|
||||
ets_loop_iter();
|
||||
if (MP_STATE_VM(mp_pending_exception) != NULL) {
|
||||
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
|
||||
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
|
||||
nlr_raise(obj);
|
||||
}
|
||||
mp_handle_pending();
|
||||
}
|
||||
|
||||
void __assert_func(const char *file, int line, const char *func, const char *expr) {
|
||||
|
@ -25,8 +25,8 @@
|
||||
*/
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "lib/oofatfs/ff.h"
|
||||
#include "timeutils.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
DWORD get_fattime(void) {
|
||||
|
@ -87,11 +87,15 @@ STATIC uint8_t pin_mode[16 + 1];
|
||||
// forward declaration
|
||||
STATIC const pin_irq_obj_t pin_irq_obj[16];
|
||||
|
||||
// whether the irq is hard or soft
|
||||
STATIC bool pin_irq_is_hard[16];
|
||||
|
||||
void pin_init0(void) {
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
ETS_GPIO_INTR_ATTACH(pin_intr_handler_iram, NULL);
|
||||
// disable all interrupts
|
||||
memset(&MP_STATE_PORT(pin_irq_handler)[0], 0, 16 * sizeof(mp_obj_t));
|
||||
memset(pin_irq_is_hard, 0, sizeof(pin_irq_is_hard));
|
||||
for (int p = 0; p < 16; ++p) {
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << p);
|
||||
SET_TRIGGER(p, 0);
|
||||
@ -100,17 +104,23 @@ void pin_init0(void) {
|
||||
}
|
||||
|
||||
void pin_intr_handler(uint32_t status) {
|
||||
mp_sched_lock();
|
||||
gc_lock();
|
||||
status &= 0xffff;
|
||||
for (int p = 0; status; ++p, status >>= 1) {
|
||||
if (status & 1) {
|
||||
mp_obj_t handler = MP_STATE_PORT(pin_irq_handler)[p];
|
||||
if (handler != MP_OBJ_NULL) {
|
||||
mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
|
||||
if (pin_irq_is_hard[p]) {
|
||||
mp_call_function_1_protected(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
|
||||
} else {
|
||||
mp_sched_schedule(handler, MP_OBJ_FROM_PTR(&pyb_pin_obj[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
gc_unlock();
|
||||
mp_sched_unlock();
|
||||
}
|
||||
|
||||
pyb_pin_obj_t *mp_obj_get_pin_obj(mp_obj_t pin_in) {
|
||||
@ -342,12 +352,13 @@ STATIC mp_obj_t pyb_pin_high(mp_obj_t self_in) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_pin_high_obj, pyb_pin_high);
|
||||
|
||||
// pin.irq(*, trigger, handler=None)
|
||||
// pin.irq(handler=None, trigger=IRQ_FALLING|IRQ_RISING, hard=False)
|
||||
STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_trigger, ARG_handler };
|
||||
enum { ARG_handler, ARG_trigger, ARG_hard };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_trigger, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0} },
|
||||
{ MP_QSTR_handler, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_handler, MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||
{ MP_QSTR_trigger, MP_ARG_INT, {.u_int = GPIO_PIN_INTR_POSEDGE | GPIO_PIN_INTR_NEGEDGE} },
|
||||
{ MP_QSTR_hard, MP_ARG_BOOL, {.u_bool = false} },
|
||||
};
|
||||
pyb_pin_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]);
|
||||
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
||||
@ -357,15 +368,18 @@ STATIC mp_obj_t pyb_pin_irq(size_t n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "pin does not have IRQ capabilities"));
|
||||
}
|
||||
|
||||
if (args[ARG_trigger].u_int != 0) {
|
||||
if (n_args > 1 || kw_args->used != 0) {
|
||||
// configure irq
|
||||
mp_obj_t handler = args[ARG_handler].u_obj;
|
||||
uint32_t trigger = args[ARG_trigger].u_int;
|
||||
if (handler == mp_const_none) {
|
||||
handler = MP_OBJ_NULL;
|
||||
trigger = 0;
|
||||
}
|
||||
ETS_GPIO_INTR_DISABLE();
|
||||
MP_STATE_PORT(pin_irq_handler)[self->phys_port] = handler;
|
||||
SET_TRIGGER(self->phys_port, args[ARG_trigger].u_int);
|
||||
pin_irq_is_hard[self->phys_port] = args[ARG_hard].u_bool;
|
||||
SET_TRIGGER(self->phys_port, trigger);
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << self->phys_port);
|
||||
ETS_GPIO_INTR_ENABLE();
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
#include "timeutils.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
|
477
esp8266/modesp.c
477
esp8266/modesp.c
@ -25,492 +25,19 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "py/nlr.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/gc.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
#include "drivers/dht/dht.h"
|
||||
#include "netutils.h"
|
||||
#include "queue.h"
|
||||
#include "ets_sys.h"
|
||||
#include "uart.h"
|
||||
#include "user_interface.h"
|
||||
#include "espconn.h"
|
||||
#include "spi_flash.h"
|
||||
#include "mem.h"
|
||||
#include "espneopixel.h"
|
||||
#include "espapa102.h"
|
||||
#include "modmachine.h"
|
||||
|
||||
#define MODESP_ESPCONN (0)
|
||||
|
||||
#if MODESP_ESPCONN
|
||||
STATIC const mp_obj_type_t esp_socket_type;
|
||||
|
||||
typedef struct _esp_socket_obj_t {
|
||||
mp_obj_base_t base;
|
||||
struct espconn *espconn;
|
||||
|
||||
mp_obj_t cb_connect;
|
||||
mp_obj_t cb_recv;
|
||||
mp_obj_t cb_sent;
|
||||
mp_obj_t cb_disconnect;
|
||||
|
||||
uint8_t *recvbuf;
|
||||
mp_uint_t recvbuf_len;
|
||||
|
||||
bool fromserver;
|
||||
|
||||
mp_obj_list_t *connlist;
|
||||
} esp_socket_obj_t;
|
||||
|
||||
// Due to the onconnect callback not being able to recognize the parent esp_socket,
|
||||
// we can have only one esp_socket listening at a time
|
||||
// This should be solvable by some PIC hacking
|
||||
STATIC esp_socket_obj_t *esp_socket_listening;
|
||||
|
||||
STATIC mp_obj_t esp_socket_make_new_base() {
|
||||
esp_socket_obj_t *s = m_new_obj_with_finaliser(esp_socket_obj_t);
|
||||
s->recvbuf = NULL;
|
||||
s->base.type = (mp_obj_t)&esp_socket_type;
|
||||
s->cb_connect = mp_const_none;
|
||||
s->cb_recv = mp_const_none;
|
||||
s->cb_disconnect = mp_const_none;
|
||||
s->cb_sent = mp_const_none;
|
||||
s->fromserver = false;
|
||||
s->connlist = NULL;
|
||||
return s;
|
||||
}
|
||||
|
||||
// constructor esp_socket(family=AF_INET, type=SOCK_STREAM, proto=IPPROTO_TCP, fileno=None)
|
||||
// Arguments ignored as we do not support UDP (yet)
|
||||
STATIC mp_obj_t esp_socket_make_new(const mp_obj_type_t *type_in, mp_uint_t n_args,
|
||||
mp_uint_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 4, false);
|
||||
|
||||
esp_socket_obj_t *s = esp_socket_make_new_base();
|
||||
s->espconn = m_new_obj(struct espconn);
|
||||
|
||||
s->espconn->reverse = s;
|
||||
// TODO: UDP Support
|
||||
s->espconn->type = ESPCONN_TCP;
|
||||
s->espconn->state = ESPCONN_NONE;
|
||||
|
||||
s->espconn->proto.tcp = m_new_obj(esp_tcp);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
// method socket.close()
|
||||
STATIC mp_obj_t esp_socket_close(mp_obj_t self_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (esp_socket_listening == s) {
|
||||
esp_socket_listening = NULL;
|
||||
}
|
||||
|
||||
if (s->espconn->state != ESPCONN_NONE && s->espconn->state != ESPCONN_CLOSE) {
|
||||
espconn_disconnect(s->espconn);
|
||||
}
|
||||
|
||||
if (s->connlist != NULL) {
|
||||
mp_obj_list_set_len(s->connlist, 0);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_close_obj, esp_socket_close);
|
||||
|
||||
// method socket.__del__()
|
||||
STATIC mp_obj_t esp_socket___del__(mp_obj_t self_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
esp_socket_close(self_in);
|
||||
|
||||
if (s->fromserver) {
|
||||
espconn_delete(s->espconn);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket___del___obj, esp_socket___del__);
|
||||
|
||||
// method socket.bind(address)
|
||||
STATIC mp_obj_t esp_socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
mp_uint_t port = netutils_parse_inet_addr(addr_in,
|
||||
s->espconn->proto.tcp->remote_ip, NETUTILS_BIG);
|
||||
s->espconn->proto.tcp->local_port = port;
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_bind_obj, esp_socket_bind);
|
||||
|
||||
STATIC void esp_socket_recv_callback(void *arg, char *pdata, unsigned short len) {
|
||||
struct espconn *conn = arg;
|
||||
esp_socket_obj_t *s = conn->reverse;
|
||||
|
||||
if (s->cb_recv != mp_const_none) {
|
||||
call_function_2_protected(s->cb_recv, s, mp_obj_new_bytes((byte *)pdata, len));
|
||||
} else {
|
||||
if (s->recvbuf == NULL) {
|
||||
s->recvbuf = m_new(uint8_t, len);
|
||||
s->recvbuf_len = len;
|
||||
if (s->recvbuf != NULL) {
|
||||
memcpy(s->recvbuf, pdata, len);
|
||||
}
|
||||
} else {
|
||||
s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len + len);
|
||||
if (s->recvbuf != NULL) {
|
||||
memcpy(&s->recvbuf[s->recvbuf_len], pdata, len);
|
||||
s->recvbuf_len += len;
|
||||
}
|
||||
}
|
||||
if (s->recvbuf == NULL) {
|
||||
esp_socket_close(s);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void esp_socket_sent_callback(void *arg) {
|
||||
struct espconn *conn = arg;
|
||||
esp_socket_obj_t *s = conn->reverse;
|
||||
|
||||
if (s->cb_sent != mp_const_none) {
|
||||
call_function_1_protected(s->cb_sent, s);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void esp_socket_disconnect_callback(void *arg) {
|
||||
struct espconn *conn = arg;
|
||||
esp_socket_obj_t *s = conn->reverse;
|
||||
|
||||
if (s->cb_disconnect != mp_const_none) {
|
||||
call_function_1_protected(s->cb_disconnect, s);
|
||||
}
|
||||
|
||||
esp_socket_close(s);
|
||||
}
|
||||
|
||||
STATIC void esp_socket_connect_callback_server(void *arg) {
|
||||
struct espconn *conn = arg;
|
||||
|
||||
esp_socket_obj_t *s = esp_socket_make_new_base();
|
||||
s->espconn = conn;
|
||||
s->fromserver = true;
|
||||
conn->reverse = s;
|
||||
|
||||
espconn_regist_recvcb(conn, esp_socket_recv_callback);
|
||||
espconn_regist_sentcb(conn, esp_socket_sent_callback);
|
||||
espconn_regist_disconcb(conn, esp_socket_disconnect_callback);
|
||||
espconn_regist_time(conn, 15, 0);
|
||||
|
||||
if (esp_socket_listening->cb_connect != mp_const_none) {
|
||||
call_function_1_protected(esp_socket_listening->cb_connect, s);
|
||||
} else {
|
||||
mp_obj_list_append(esp_socket_listening->connlist, s);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC void esp_socket_connect_callback_client(void *arg) {
|
||||
struct espconn *conn = arg;
|
||||
esp_socket_obj_t *s = conn->reverse;
|
||||
|
||||
if (s->cb_connect != mp_const_none) {
|
||||
call_function_1_protected(s->cb_connect, s);
|
||||
}
|
||||
}
|
||||
|
||||
// method socket.listen(backlog)
|
||||
STATIC mp_obj_t esp_socket_listen(mp_obj_t self_in, mp_obj_t backlog) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (esp_socket_listening != NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"only one espconn can listen at a time"));
|
||||
}
|
||||
|
||||
esp_socket_listening = s;
|
||||
|
||||
s->connlist = mp_obj_new_list(0, NULL);
|
||||
|
||||
espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_server);
|
||||
espconn_accept(s->espconn);
|
||||
espconn_regist_time(s->espconn, 1500, 0);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_listen_obj, esp_socket_listen);
|
||||
|
||||
// method socket.accept()
|
||||
STATIC mp_obj_t esp_socket_accept(mp_obj_t self_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (s->connlist == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"not listening"));
|
||||
}
|
||||
|
||||
do {
|
||||
mp_uint_t len;
|
||||
mp_obj_t *items;
|
||||
|
||||
mp_obj_list_get(s->connlist, &len, &items);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
esp_socket_obj_t *rs = items[0];
|
||||
mp_obj_list_remove(s->connlist, rs);
|
||||
if (rs->espconn->state != ESPCONN_CLOSE) {
|
||||
return rs;
|
||||
}
|
||||
} while (true);
|
||||
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"no connection in queue"));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_accept_obj, esp_socket_accept);
|
||||
|
||||
// method socket.connect(address)
|
||||
STATIC mp_obj_t esp_socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (s->espconn == NULL || s->espconn->state != ESPCONN_NONE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"transport endpoint is already connected or closed"));
|
||||
}
|
||||
|
||||
espconn_regist_connectcb(s->espconn, esp_socket_connect_callback_client);
|
||||
espconn_regist_recvcb(s->espconn, esp_socket_recv_callback);
|
||||
espconn_regist_sentcb(s->espconn, esp_socket_sent_callback);
|
||||
espconn_regist_disconcb(s->espconn, esp_socket_disconnect_callback);
|
||||
|
||||
s->espconn->proto.tcp->remote_port =
|
||||
netutils_parse_inet_addr(addr_in, s->espconn->proto.tcp->remote_ip,
|
||||
NETUTILS_BIG);
|
||||
espconn_connect(s->espconn);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_connect_obj, esp_socket_connect);
|
||||
|
||||
// method socket.send(bytes)
|
||||
STATIC mp_obj_t esp_socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (s->espconn->state == ESPCONN_NONE || s->espconn->state == ESPCONN_CLOSE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"not connected"));
|
||||
}
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
|
||||
|
||||
espconn_sent(s->espconn, bufinfo.buf, bufinfo.len);
|
||||
|
||||
return mp_obj_new_int(bufinfo.len);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_send_obj, esp_socket_send);
|
||||
|
||||
// method socket.recv(bufsize)
|
||||
STATIC mp_obj_t esp_socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (s->recvbuf == NULL) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"no data available"));
|
||||
}
|
||||
|
||||
mp_uint_t mxl = mp_obj_get_int(len_in);
|
||||
if (mxl >= s->recvbuf_len) {
|
||||
mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, s->recvbuf_len);
|
||||
m_del(uint8_t, s->recvbuf, s->recvbuf_len);
|
||||
s->recvbuf = NULL;
|
||||
return trt;
|
||||
} else {
|
||||
mp_obj_t trt = mp_obj_new_bytes(s->recvbuf, mxl);
|
||||
memmove(s->recvbuf, &s->recvbuf[mxl], s->recvbuf_len - mxl);
|
||||
s->recvbuf = m_renew(uint8_t, s->recvbuf, s->recvbuf_len, s->recvbuf_len - mxl);
|
||||
s->recvbuf_len -= mxl;
|
||||
return trt;
|
||||
}
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recv_obj, esp_socket_recv);
|
||||
|
||||
// method socket.sendto(bytes, address)
|
||||
STATIC mp_obj_t esp_socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_socket_sendto_obj, esp_socket_sendto);
|
||||
|
||||
// method socket.recvfrom(bufsize)
|
||||
STATIC mp_obj_t esp_socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "UDP not supported"));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_recvfrom_obj, esp_socket_recvfrom);
|
||||
|
||||
// method socket.getpeername()
|
||||
STATIC mp_obj_t esp_socket_getpeername(mp_obj_t self_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
|
||||
if (s->espconn->state == ESPCONN_NONE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError,
|
||||
"not connected"));
|
||||
}
|
||||
|
||||
mp_obj_t tuple[2] = {
|
||||
netutils_format_ipv4_addr(s->espconn->proto.tcp->remote_ip, NETUTILS_BIG),
|
||||
mp_obj_new_int(s->espconn->proto.tcp->remote_port),
|
||||
};
|
||||
|
||||
return mp_obj_new_tuple(2, tuple);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(esp_socket_getpeername_obj, esp_socket_getpeername);
|
||||
|
||||
STATIC mp_obj_t esp_socket_onconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
s->cb_connect = lambda_in;
|
||||
|
||||
if (s->connlist != NULL) {
|
||||
do {
|
||||
mp_uint_t len;
|
||||
mp_obj_t *items;
|
||||
|
||||
mp_obj_list_get(s->connlist, &len, &items);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
esp_socket_obj_t *rs = items[0];
|
||||
mp_obj_list_remove(s->connlist, rs);
|
||||
if (s->espconn->state != ESPCONN_CLOSE) {
|
||||
call_function_1_protected(s->cb_connect, rs);
|
||||
}
|
||||
} while (true);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onconnect_obj, esp_socket_onconnect);
|
||||
|
||||
STATIC mp_obj_t esp_socket_onrecv(mp_obj_t self_in, mp_obj_t lambda_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
s->cb_recv = lambda_in;
|
||||
if (s->recvbuf != NULL) {
|
||||
call_function_2_protected(s->cb_recv, s,
|
||||
mp_obj_new_bytes((byte *)s->recvbuf, s->recvbuf_len));
|
||||
s->recvbuf = NULL;
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onrecv_obj, esp_socket_onrecv);
|
||||
|
||||
STATIC mp_obj_t esp_socket_onsent(mp_obj_t self_in, mp_obj_t lambda_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
s->cb_sent = lambda_in;
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_onsent_obj, esp_socket_onsent);
|
||||
|
||||
STATIC mp_obj_t esp_socket_ondisconnect(mp_obj_t self_in, mp_obj_t lambda_in) {
|
||||
esp_socket_obj_t *s = self_in;
|
||||
s->cb_disconnect = lambda_in;
|
||||
|
||||
if (s->espconn->state == ESPCONN_CLOSE) {
|
||||
call_function_1_protected(s->cb_disconnect, s);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(esp_socket_ondisconnect_obj, esp_socket_ondisconnect);
|
||||
|
||||
typedef struct _esp_getaddrinfo_cb_struct_t {
|
||||
mp_obj_t lambda;
|
||||
mp_uint_t port;
|
||||
} esp_getaddrinfo_cb_struct_t;
|
||||
|
||||
STATIC esp_getaddrinfo_cb_struct_t esp_getaddrinfo_cb_struct;
|
||||
|
||||
STATIC void esp_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg) {
|
||||
mp_obj_t namestr = mp_obj_new_str(name, strlen(name), true);
|
||||
if (ipaddr != NULL) {
|
||||
uint8_t ip[4];
|
||||
ip[0] = (ipaddr->addr >> 24) & 0xff;
|
||||
ip[1] = (ipaddr->addr >> 16) & 0xff;
|
||||
ip[2] = (ipaddr->addr >> 8) & 0xff;
|
||||
ip[3] = (ipaddr->addr >> 0) & 0xff;
|
||||
|
||||
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
||||
|
||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
||||
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||
tuple->items[4] = netutils_format_inet_addr(ip,
|
||||
esp_getaddrinfo_cb_struct.port, NETUTILS_LITTLE);
|
||||
call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, tuple);
|
||||
} else {
|
||||
call_function_2_protected(esp_getaddrinfo_cb_struct.lambda, namestr, mp_const_none);
|
||||
}
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in,
|
||||
mp_obj_t lambda_in) {
|
||||
mp_uint_t hlen;
|
||||
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
||||
ip_addr_t ipaddr;
|
||||
|
||||
esp_getaddrinfo_cb_struct.lambda = lambda_in;
|
||||
esp_getaddrinfo_cb_struct.port = mp_obj_get_int(port_in);
|
||||
|
||||
err_t ret = espconn_gethostbyname(NULL, host, &ipaddr,
|
||||
esp_getaddrinfo_cb);
|
||||
|
||||
if (ret == ESPCONN_OK) {
|
||||
esp_getaddrinfo_cb(host, &ipaddr, NULL);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(esp_getaddrinfo_obj, esp_getaddrinfo);
|
||||
|
||||
STATIC const mp_map_elem_t esp_socket_locals_dict_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&esp_socket___del___obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&esp_socket_close_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&esp_socket_bind_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&esp_socket_listen_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&esp_socket_accept_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&esp_socket_connect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&esp_socket_send_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&esp_socket_recv_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&esp_socket_sendto_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&esp_socket_recvfrom_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getpeername), (mp_obj_t)&esp_socket_getpeername_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_onconnect), (mp_obj_t)&esp_socket_onconnect_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_onrecv), (mp_obj_t)&esp_socket_onrecv_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_onsent), (mp_obj_t)&esp_socket_onsent_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ondisconnect), (mp_obj_t)&esp_socket_ondisconnect_obj },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(esp_socket_locals_dict, esp_socket_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t esp_socket_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_socket,
|
||||
.make_new = esp_socket_make_new,
|
||||
.locals_dict = (mp_obj_t)&esp_socket_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define MODESP_INCLUDE_CONSTANTS (1)
|
||||
|
||||
void error_check(bool status, const char *msg) {
|
||||
@ -834,10 +361,6 @@ STATIC const mp_map_elem_t esp_module_globals_table[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_erase), (mp_obj_t)&esp_flash_erase_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_size), (mp_obj_t)&esp_flash_size_obj },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_flash_user_start), (mp_obj_t)&esp_flash_user_start_obj },
|
||||
#if MODESP_ESPCONN
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&esp_socket_type },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&esp_getaddrinfo_obj },
|
||||
#endif
|
||||
#if MICROPY_ESP8266_NEOPIXEL
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_neopixel_write), (mp_obj_t)&esp_neopixel_write_obj },
|
||||
#endif
|
||||
|
@ -157,7 +157,7 @@ STATIC mp_obj_t esp_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
||||
|
||||
STATIC void esp_timer_cb(void *arg) {
|
||||
esp_timer_obj_t *self = arg;
|
||||
mp_call_function_1_protected(self->callback, self);
|
||||
mp_sched_schedule(self->callback, self);
|
||||
}
|
||||
|
||||
STATIC mp_obj_t esp_timer_init_helper(esp_timer_obj_t *self, mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "py/objlist.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "netutils.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
#include "queue.h"
|
||||
#include "user_interface.h"
|
||||
#include "espconn.h"
|
||||
@ -97,7 +97,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(esp_active_obj, 1, 2, esp_active);
|
||||
STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
require_if(args[0], STATION_IF);
|
||||
struct station_config config = {{0}};
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *p;
|
||||
|
||||
if (n_args > 1) {
|
||||
@ -311,7 +311,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
}
|
||||
case QS(MP_QSTR_essid): {
|
||||
req_if = SOFTAP_IF;
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(cfg.ap.ssid));
|
||||
memcpy(cfg.ap.ssid, s, len);
|
||||
@ -330,7 +330,7 @@ STATIC mp_obj_t esp_config(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs
|
||||
}
|
||||
case QS(MP_QSTR_password): {
|
||||
req_if = SOFTAP_IF;
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *s = mp_obj_str_get_data(kwargs->table[i].value, &len);
|
||||
len = MIN(len, sizeof(cfg.ap.password) - 1);
|
||||
memcpy(cfg.ap.password, s, len);
|
||||
|
@ -34,8 +34,8 @@
|
||||
#include "py/runtime.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/smallint.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
#include "modmachine.h"
|
||||
#include "timeutils.h"
|
||||
#include "user_interface.h"
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
||||
@ -84,7 +84,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(time_localtime_obj, 0, 1, time_localtime);
|
||||
/// which expresses a time as per localtime. It returns an integer which is
|
||||
/// the number of seconds since Jan 1, 2000.
|
||||
STATIC mp_obj_t time_mktime(mp_obj_t tuple) {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
mp_obj_t *elem;
|
||||
mp_obj_get_array(tuple, &len, &elem);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||
#define MICROPY_ENABLE_SCHEDULER (1)
|
||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||
#define MICROPY_PY_BUILTINS_COMPLEX (0)
|
||||
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
|
||||
@ -117,8 +118,6 @@
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define BYTES_PER_WORD (4)
|
||||
|
||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p)))
|
||||
|
||||
#define MP_SSIZE_MAX (0x7fffffff)
|
||||
@ -181,7 +180,6 @@ extern const struct _mp_obj_module_t onewire_module;
|
||||
|
||||
#define MICROPY_PORT_ROOT_POINTERS \
|
||||
const char *readline_hist[8]; \
|
||||
vstr_t *repl_line; \
|
||||
mp_obj_t pin_irq_handler[16]; \
|
||||
|
||||
// We need to provide a declaration/definition of alloca()
|
||||
|
@ -14,13 +14,12 @@ INC += -I.
|
||||
INC += -I..
|
||||
INC += -I$(MPTOP)
|
||||
INC += -I$(MPTOP)/unix
|
||||
#INC += -I../lib/timeutils
|
||||
INC += -I$(BUILD)
|
||||
|
||||
# compiler settings
|
||||
CWARN = -Wall -Werror
|
||||
CWARN += -Wpointer-arith -Wuninitialized
|
||||
CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
CFLAGS = $(INC) $(CWARN) -std=gnu99 -DUNIX $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
|
||||
# Debugging/Optimization
|
||||
ifdef DEBUG
|
||||
|
@ -119,8 +119,6 @@ typedef int mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
#endif
|
||||
|
||||
#define BYTES_PER_WORD sizeof(mp_int_t)
|
||||
|
||||
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
|
||||
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
|
||||
typedef long long mp_off_t;
|
||||
|
@ -97,12 +97,8 @@ STATIC mp_obj_t btree_put(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
DBT key, val;
|
||||
// Different ports may have different type sizes
|
||||
mp_uint_t v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[1], &v);
|
||||
key.size = v;
|
||||
val.data = (void*)mp_obj_str_get_data(args[2], &v);
|
||||
val.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
|
||||
val.data = (void*)mp_obj_str_get_data(args[2], &val.size);
|
||||
return MP_OBJ_NEW_SMALL_INT(__bt_put(self->db, &key, &val, 0));
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
|
||||
@ -110,10 +106,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(btree_put_obj, 3, 4, btree_put);
|
||||
STATIC mp_obj_t btree_get(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
DBT key, val;
|
||||
// Different ports may have different type sizes
|
||||
mp_uint_t v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[1], &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[1], &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
if (n_args > 2) {
|
||||
@ -132,10 +125,7 @@ STATIC mp_obj_t btree_seq(size_t n_args, const mp_obj_t *args) {
|
||||
int flags = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||
DBT key, val;
|
||||
if (n_args > 2) {
|
||||
// Different ports may have different type sizes
|
||||
mp_uint_t v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[2], &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(args[2], &key.size);
|
||||
}
|
||||
|
||||
int res = __bt_seq(self->db, &key, &val, flags);
|
||||
@ -206,14 +196,11 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
DBT key, val;
|
||||
int res;
|
||||
// Different ports may have different type sizes
|
||||
mp_uint_t v;
|
||||
bool desc = self->flags & FLAG_DESC;
|
||||
if (self->start_key != MP_OBJ_NULL) {
|
||||
int flags = R_FIRST;
|
||||
if (self->start_key != mp_const_none) {
|
||||
key.data = (void*)mp_obj_str_get_data(self->start_key, &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(self->start_key, &key.size);
|
||||
flags = R_CURSOR;
|
||||
} else if (desc) {
|
||||
flags = R_LAST;
|
||||
@ -231,8 +218,7 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
|
||||
|
||||
if (self->end_key != mp_const_none) {
|
||||
DBT end_key;
|
||||
end_key.data = (void*)mp_obj_str_get_data(self->end_key, &v);
|
||||
end_key.size = v;
|
||||
end_key.data = (void*)mp_obj_str_get_data(self->end_key, &end_key.size);
|
||||
BTREE *t = self->db->internal;
|
||||
int cmp = t->bt_cmp(&key, &end_key);
|
||||
if (desc) {
|
||||
@ -264,13 +250,10 @@ STATIC mp_obj_t btree_iternext(mp_obj_t self_in) {
|
||||
|
||||
STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
// Different ports may have different type sizes
|
||||
mp_uint_t v;
|
||||
if (value == MP_OBJ_NULL) {
|
||||
// delete
|
||||
DBT key;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &key.size);
|
||||
int res = __bt_delete(self->db, &key, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
|
||||
@ -280,8 +263,7 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
} else if (value == MP_OBJ_SENTINEL) {
|
||||
// load
|
||||
DBT key, val;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
if (res == RET_SPECIAL) {
|
||||
nlr_raise(mp_obj_new_exception(&mp_type_KeyError));
|
||||
@ -291,10 +273,8 @@ STATIC mp_obj_t btree_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
} else {
|
||||
// store
|
||||
DBT key, val;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &v);
|
||||
key.size = v;
|
||||
val.data = (void*)mp_obj_str_get_data(value, &v);
|
||||
val.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(index, &key.size);
|
||||
val.data = (void*)mp_obj_str_get_data(value, &val.size);
|
||||
int res = __bt_put(self->db, &key, &val, 0);
|
||||
CHECK_ERROR(res);
|
||||
return mp_const_none;
|
||||
@ -305,10 +285,8 @@ STATIC mp_obj_t btree_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in)
|
||||
mp_obj_btree_t *self = MP_OBJ_TO_PTR(lhs_in);
|
||||
switch (op) {
|
||||
case MP_BINARY_OP_IN: {
|
||||
mp_uint_t v;
|
||||
DBT key, val;
|
||||
key.data = (void*)mp_obj_str_get_data(rhs_in, &v);
|
||||
key.size = v;
|
||||
key.data = (void*)mp_obj_str_get_data(rhs_in, &key.size);
|
||||
int res = __bt_get(self->db, &key, &val, 0);
|
||||
CHECK_ERROR(res);
|
||||
return mp_obj_new_bool(res != RET_SPECIAL);
|
||||
|
@ -53,6 +53,41 @@ typedef struct _mp_framebuf_p_t {
|
||||
fill_rect_t fill_rect;
|
||||
} mp_framebuf_p_t;
|
||||
|
||||
// constants for formats
|
||||
#define FRAMEBUF_MVLSB (0)
|
||||
#define FRAMEBUF_RGB565 (1)
|
||||
#define FRAMEBUF_GS4_HMSB (2)
|
||||
#define FRAMEBUF_MHLSB (3)
|
||||
#define FRAMEBUF_MHMSB (4)
|
||||
|
||||
// Functions for MHLSB and MHMSB
|
||||
|
||||
STATIC void mono_horiz_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
|
||||
size_t index = (x + y * fb->stride) >> 3;
|
||||
int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
|
||||
((uint8_t*)fb->buf)[index] = (((uint8_t*)fb->buf)[index] & ~(0x01 << offset)) | ((color != 0) << offset);
|
||||
}
|
||||
|
||||
STATIC uint32_t mono_horiz_getpixel(const mp_obj_framebuf_t *fb, int x, int y) {
|
||||
size_t index = (x + y * fb->stride) >> 3;
|
||||
int offset = fb->format == FRAMEBUF_MHMSB ? x & 0x07 : 7 - (x & 0x07);
|
||||
return (((uint8_t*)fb->buf)[index] >> (offset)) & 0x01;
|
||||
}
|
||||
|
||||
STATIC void mono_horiz_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w, int h, uint32_t col) {
|
||||
int reverse = fb->format == FRAMEBUF_MHMSB;
|
||||
int advance = fb->stride >> 3;
|
||||
while (w--) {
|
||||
uint8_t *b = &((uint8_t*)fb->buf)[(x >> 3) + y * advance];
|
||||
int offset = reverse ? x & 7 : 7 - (x & 7);
|
||||
for (int hh = h; hh; --hh) {
|
||||
*b = (*b & ~(0x01 << offset)) | ((col != 0) << offset);
|
||||
b += advance;
|
||||
}
|
||||
++x;
|
||||
}
|
||||
}
|
||||
|
||||
// Functions for MVLSB format
|
||||
|
||||
STATIC void mvlsb_setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
|
||||
@ -148,15 +183,12 @@ STATIC void gs4_hmsb_fill_rect(const mp_obj_framebuf_t *fb, int x, int y, int w,
|
||||
}
|
||||
}
|
||||
|
||||
// constants for formats
|
||||
#define FRAMEBUF_MVLSB (0)
|
||||
#define FRAMEBUF_RGB565 (1)
|
||||
#define FRAMEBUF_GS4_HMSB (2)
|
||||
|
||||
STATIC mp_framebuf_p_t formats[] = {
|
||||
[FRAMEBUF_MVLSB] = {mvlsb_setpixel, mvlsb_getpixel, mvlsb_fill_rect},
|
||||
[FRAMEBUF_RGB565] = {rgb565_setpixel, rgb565_getpixel, rgb565_fill_rect},
|
||||
[FRAMEBUF_GS4_HMSB] = {gs4_hmsb_setpixel, gs4_hmsb_getpixel, gs4_hmsb_fill_rect},
|
||||
[FRAMEBUF_MHLSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
|
||||
[FRAMEBUF_MHMSB] = {mono_horiz_setpixel, mono_horiz_getpixel, mono_horiz_fill_rect},
|
||||
};
|
||||
|
||||
static inline void setpixel(const mp_obj_framebuf_t *fb, int x, int y, uint32_t color) {
|
||||
@ -207,6 +239,10 @@ STATIC mp_obj_t framebuf_make_new(const mp_obj_type_t *type, size_t n_args, size
|
||||
case FRAMEBUF_RGB565:
|
||||
case FRAMEBUF_GS4_HMSB:
|
||||
break;
|
||||
case FRAMEBUF_MHLSB:
|
||||
case FRAMEBUF_MHMSB:
|
||||
o->stride = (o->stride + 7) & ~7;
|
||||
break;
|
||||
default:
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"invalid format"));
|
||||
@ -543,8 +579,11 @@ STATIC const mp_rom_map_elem_t framebuf_module_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer), MP_ROM_PTR(&mp_type_framebuf) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_FrameBuffer1), MP_ROM_PTR(&legacy_framebuffer1_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MVLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_VLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MVLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_RGB565), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_RGB565) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_GS4_HMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_GS4_HMSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "py/mperrno.h"
|
||||
#include "py/mphal.h"
|
||||
|
||||
#include "netutils.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
#include "lwip/timers.h"
|
||||
@ -1264,8 +1264,7 @@ STATIC void lwip_getaddrinfo_cb(const char *name, ip_addr_t *ipaddr, void *arg)
|
||||
|
||||
// lwip.getaddrinfo
|
||||
STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
||||
mp_uint_t hlen;
|
||||
const char *host = mp_obj_str_get_data(host_in, &hlen);
|
||||
const char *host = mp_obj_str_get_str(host_in);
|
||||
mp_int_t port = mp_obj_get_int(port_in);
|
||||
|
||||
getaddrinfo_state_t state;
|
||||
|
@ -274,7 +274,7 @@ STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load);
|
||||
|
||||
STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *buf = mp_obj_str_get_data(obj, &len);
|
||||
vstr_t vstr = {len, len, (char*)buf, true};
|
||||
mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0};
|
||||
|
@ -96,7 +96,7 @@ STATIC mp_obj_t ure_exec(bool is_anchored, uint n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
Subject subj;
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
int caps_num = (self->re.sub + 1) * 2;
|
||||
@ -128,7 +128,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(re_search_obj, 2, 4, re_search);
|
||||
STATIC mp_obj_t re_split(size_t n_args, const mp_obj_t *args) {
|
||||
mp_obj_re_t *self = MP_OBJ_TO_PTR(args[0]);
|
||||
Subject subj;
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
subj.begin = mp_obj_str_get_data(args[1], &len);
|
||||
subj.end = subj.begin + len;
|
||||
int caps_num = (self->re.sub + 1) * 2;
|
||||
|
@ -113,7 +113,7 @@ STATIC mp_uint_t poll_map_poll(mp_map_t *poll_map, mp_uint_t *rwx_num) {
|
||||
/// \function select(rlist, wlist, xlist[, timeout])
|
||||
STATIC mp_obj_t select_select(uint n_args, const mp_obj_t *args) {
|
||||
// get array data from tuple/list arguments
|
||||
mp_uint_t rwx_len[3];
|
||||
size_t rwx_len[3];
|
||||
mp_obj_t *r_array, *w_array, *x_array;
|
||||
mp_obj_get_array(args[0], &rwx_len[0], &r_array);
|
||||
mp_obj_get_array(args[1], &rwx_len[1], &w_array);
|
||||
|
@ -156,13 +156,13 @@ STATIC mp_obj_ssl_socket_t *socket_new(mp_obj_t sock, struct ssl_args *args) {
|
||||
mbedtls_ssl_set_bio(&o->ssl, &o->sock, _mbedtls_ssl_send, _mbedtls_ssl_recv, NULL);
|
||||
|
||||
if (args->key.u_obj != MP_OBJ_NULL) {
|
||||
mp_uint_t key_len;
|
||||
size_t key_len;
|
||||
const byte *key = (const byte*)mp_obj_str_get_data(args->key.u_obj, &key_len);
|
||||
// len should include terminating null
|
||||
ret = mbedtls_pk_parse_key(&o->pkey, key, key_len + 1, NULL, 0);
|
||||
assert(ret == 0);
|
||||
|
||||
mp_uint_t cert_len;
|
||||
size_t cert_len;
|
||||
const byte *cert = (const byte*)mp_obj_str_get_data(args->cert.u_obj, &cert_len);
|
||||
// len should include terminating null
|
||||
ret = mbedtls_x509_crt_parse(&o->cert, cert, cert_len + 1);
|
||||
|
@ -166,6 +166,17 @@ STATIC mp_obj_t mod_utimeq_heappop(mp_obj_t heap_in, mp_obj_t list_ref) {
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_utimeq_heappop_obj, mod_utimeq_heappop);
|
||||
|
||||
STATIC mp_obj_t mod_utimeq_peektime(mp_obj_t heap_in) {
|
||||
mp_obj_utimeq_t *heap = get_heap(heap_in);
|
||||
if (heap->len == 0) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "empty heap"));
|
||||
}
|
||||
|
||||
struct qentry *item = &heap->items[0];
|
||||
return MP_OBJ_NEW_SMALL_INT(item->time);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_utimeq_peektime_obj, mod_utimeq_peektime);
|
||||
|
||||
#if DEBUG
|
||||
STATIC mp_obj_t mod_utimeq_dump(mp_obj_t heap_in) {
|
||||
mp_obj_utimeq_t *heap = get_heap(heap_in);
|
||||
@ -190,6 +201,7 @@ STATIC mp_obj_t utimeq_unary_op(mp_uint_t op, mp_obj_t self_in) {
|
||||
STATIC const mp_rom_map_elem_t utimeq_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_push), MP_ROM_PTR(&mod_utimeq_heappush_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pop), MP_ROM_PTR(&mod_utimeq_heappop_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_peektime), MP_ROM_PTR(&mod_utimeq_peektime_obj) },
|
||||
#if DEBUG
|
||||
{ MP_ROM_QSTR(MP_QSTR_dump), MP_ROM_PTR(&mod_utimeq_dump_obj) },
|
||||
#endif
|
||||
|
@ -308,7 +308,7 @@ STATIC mp_obj_t webrepl_close(mp_obj_t self_in) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(webrepl_close_obj, webrepl_close);
|
||||
|
||||
STATIC mp_obj_t webrepl_set_password(mp_obj_t passwd_in) {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *passwd = mp_obj_str_get_data(passwd_in, &len);
|
||||
if (len > sizeof(webrepl_passwd) - 1) {
|
||||
mp_raise_ValueError("");
|
||||
|
@ -37,13 +37,11 @@
|
||||
#include "extmod/utime_mphal.h"
|
||||
|
||||
STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o));
|
||||
#else
|
||||
mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o));
|
||||
#endif
|
||||
MP_THREAD_GIL_ENTER();
|
||||
return mp_const_none;
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
|
||||
@ -51,9 +49,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep);
|
||||
STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) {
|
||||
mp_int_t ms = mp_obj_get_int(arg);
|
||||
if (ms > 0) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_hal_delay_ms(ms);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
@ -62,9 +58,7 @@ MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms);
|
||||
STATIC mp_obj_t time_sleep_us(mp_obj_t arg) {
|
||||
mp_int_t us = mp_obj_get_int(arg);
|
||||
if (us > 0) {
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_hal_delay_us(us);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
|
||||
mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
||||
|
||||
// get the mount point
|
||||
mp_uint_t mnt_len;
|
||||
size_t mnt_len;
|
||||
const char *mnt_str = mp_obj_str_get_data(pos_args[1], &mnt_len);
|
||||
|
||||
// see if we need to auto-detect and create the filesystem
|
||||
@ -180,7 +180,7 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_mount_obj, 2, mp_vfs_mount);
|
||||
mp_obj_t mp_vfs_umount(mp_obj_t mnt_in) {
|
||||
// remove vfs from the mount table
|
||||
mp_vfs_mount_t *vfs = NULL;
|
||||
mp_uint_t mnt_len;
|
||||
size_t mnt_len;
|
||||
const char *mnt_str = NULL;
|
||||
if (MP_OBJ_IS_STR(mnt_in)) {
|
||||
mnt_str = mp_obj_str_get_data(mnt_in, &mnt_len);
|
||||
|
@ -268,7 +268,7 @@ STATIC mp_obj_t fat_vfs_statvfs(mp_obj_t vfs_in, mp_obj_t path_in) {
|
||||
|
||||
t->items[0] = MP_OBJ_NEW_SMALL_INT(fatfs->csize * SECSIZE(fatfs)); // f_bsize
|
||||
t->items[1] = t->items[0]; // f_frsize
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2) * fatfs->csize); // f_blocks
|
||||
t->items[2] = MP_OBJ_NEW_SMALL_INT((fatfs->n_fatent - 2)); // f_blocks
|
||||
t->items[3] = MP_OBJ_NEW_SMALL_INT(nclst); // f_bfree
|
||||
t->items[4] = t->items[3]; // f_bavail
|
||||
t->items[5] = MP_OBJ_NEW_SMALL_INT(0); // f_files
|
||||
|
21
lib/libm/nearbyintf.c
Normal file
21
lib/libm/nearbyintf.c
Normal file
@ -0,0 +1,21 @@
|
||||
// adapted from the rintf() function from musl-1.1.16
|
||||
|
||||
#include "libm.h"
|
||||
|
||||
float nearbyintf(float x)
|
||||
{
|
||||
union {float f; uint32_t i;} u = {x};
|
||||
int e = u.i>>23 & 0xff;
|
||||
int s = u.i>>31;
|
||||
float_t y;
|
||||
|
||||
if (e >= 0x7f+23)
|
||||
return x;
|
||||
if (s)
|
||||
y = x - 0x1p23f + 0x1p23f;
|
||||
else
|
||||
y = x + 0x1p23f - 0x1p23f;
|
||||
if (y == 0)
|
||||
return s ? -0.0f : 0.0f;
|
||||
return y;
|
||||
}
|
@ -31,7 +31,7 @@
|
||||
#include "py/mpstate.h"
|
||||
#include "py/repl.h"
|
||||
#include "py/mphal.h"
|
||||
#include "readline.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
|
||||
#if 0 // print debugging info
|
||||
#define DEBUG_PRINT (1)
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
#include "py/nlr.h"
|
||||
#include "netutils.h"
|
||||
#include "lib/netutils/netutils.h"
|
||||
|
||||
// Takes an array with a raw IPv4 address and returns something like '192.168.0.1'.
|
||||
mp_obj_t netutils_format_ipv4_addr(uint8_t *ip, netutils_endian_t endian) {
|
||||
@ -58,7 +58,7 @@ mp_obj_t netutils_format_inet_addr(uint8_t *ip, mp_uint_t port, netutils_endian_
|
||||
}
|
||||
|
||||
void netutils_parse_ipv4_addr(mp_obj_t addr_in, uint8_t *out_ip, netutils_endian_t endian) {
|
||||
mp_uint_t addr_len;
|
||||
size_t addr_len;
|
||||
const char *addr_str = mp_obj_str_get_data(addr_in, &addr_len);
|
||||
if (addr_len == 0) {
|
||||
// special case of no address given
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "py/obj.h"
|
||||
|
||||
#include "timeutils.h"
|
||||
#include "lib/timeutils/timeutils.h"
|
||||
|
||||
// LEAPOCH corresponds to 2000-03-01, which is a mod-400 year, immediately
|
||||
// after Feb 29. We calculate seconds as a signed integer relative to that.
|
||||
|
@ -46,4 +46,9 @@ void mp_keyboard_interrupt(void) {
|
||||
#else
|
||||
MP_STATE_VM(mp_pending_exception) = MP_STATE_PORT(mp_kbd_exception);
|
||||
#endif
|
||||
#if MICROPY_ENABLE_SCHEDULER
|
||||
if (MP_STATE_VM(sched_state) == MP_SCHED_IDLE) {
|
||||
MP_STATE_VM(sched_state) = MP_SCHED_PENDING;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ endif
|
||||
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I../lib/mp-readline
|
||||
INC += -I../stmhal
|
||||
INC += -I$(BUILD)
|
||||
|
||||
@ -22,9 +21,9 @@ ifeq ($(CROSS), 1)
|
||||
DFU = ../tools/dfu.py
|
||||
PYDFU = ../tools/pydfu.py
|
||||
CFLAGS_CORTEX_M4 = -mthumb -mtune=cortex-m4 -mabi=aapcs-linux -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -fsingle-precision-constant -Wdouble-promotion
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
CFLAGS = $(INC) -Wall -Werror -std=c99 -nostdlib $(CFLAGS_CORTEX_M4) $(COPT)
|
||||
else
|
||||
CFLAGS = -m32 $(INC) -Wall -Werror -ansi -std=gnu99 $(COPT)
|
||||
CFLAGS = -m32 $(INC) -Wall -Werror -std=c99 $(COPT)
|
||||
endif
|
||||
|
||||
#Debugging/Optimization
|
||||
|
@ -106,7 +106,7 @@ extern uint32_t _estack, _sidata, _sdata, _edata, _sbss, _ebss;
|
||||
void Reset_Handler(void) __attribute__((naked));
|
||||
void Reset_Handler(void) {
|
||||
// set stack pointer
|
||||
asm volatile ("ldr sp, =_estack");
|
||||
__asm volatile ("ldr sp, =_estack");
|
||||
// copy .data section from flash to RAM
|
||||
for (uint32_t *src = &_sidata, *dest = &_sdata; dest < &_edata;) {
|
||||
*dest++ = *src++;
|
||||
|
@ -57,8 +57,6 @@
|
||||
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define BYTES_PER_WORD (4)
|
||||
|
||||
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p) | 1))
|
||||
|
||||
// This port is intended to be 32-bit, but unfortunately, int32_t for
|
||||
|
@ -19,7 +19,7 @@ INC += -I$(BUILD)
|
||||
# compiler settings
|
||||
CWARN = -Wall -Werror
|
||||
CWARN += -Wpointer-arith -Wuninitialized
|
||||
CFLAGS = $(INC) $(CWARN) -ansi -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
CFLAGS = $(INC) $(CWARN) -std=gnu99 $(CFLAGS_MOD) $(COPT) $(CFLAGS_EXTRA)
|
||||
CFLAGS += -fdata-sections -ffunction-sections -fno-asynchronous-unwind-tables
|
||||
|
||||
# Debugging/Optimization
|
||||
|
@ -100,8 +100,6 @@ typedef int mp_int_t; // must be pointer size
|
||||
typedef unsigned int mp_uint_t; // must be pointer size
|
||||
#endif
|
||||
|
||||
#define BYTES_PER_WORD sizeof(mp_int_t)
|
||||
|
||||
// Cannot include <sys/types.h>, as it may lead to symbol name clashes
|
||||
#if _FILE_OFFSET_BITS == 64 && !defined(__LP64__)
|
||||
typedef long long mp_off_t;
|
||||
|
@ -14,14 +14,13 @@ PART = 33FJ256GP506
|
||||
|
||||
INC += -I.
|
||||
INC += -I..
|
||||
INC += -I../lib/mp-readline
|
||||
INC += -I../stmhal
|
||||
INC += -I$(BUILD)
|
||||
INC += -I$(XC16)/include
|
||||
INC += -I$(XC16)/support/$(PARTFAMILY)/h
|
||||
|
||||
CFLAGS_PIC16BIT = -mcpu=$(PART) -mlarge-code
|
||||
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
|
||||
CFLAGS = $(INC) -Wall -Werror -std=gnu99 -nostdlib $(CFLAGS_PIC16BIT) $(COPT)
|
||||
|
||||
#Debugging/Optimization
|
||||
ifeq ($(DEBUG), 1)
|
||||
|
@ -35,7 +35,7 @@
|
||||
#include "py/mphal.h"
|
||||
#include "py/mperrno.h"
|
||||
#include "lib/utils/pyexec.h"
|
||||
#include "readline.h"
|
||||
#include "lib/mp-readline/readline.h"
|
||||
#include "board.h"
|
||||
#include "modpyb.h"
|
||||
|
||||
|
@ -68,7 +68,6 @@
|
||||
// type definitions for the specific machine
|
||||
|
||||
#define MP_ENDIANNESS_LITTLE (1)
|
||||
#define BYTES_PER_WORD (2)
|
||||
#define MPZ_DIG_SIZE (8)
|
||||
|
||||
// The xc16 compiler doesn't seem to respect alignment (!!) so we
|
||||
|
@ -37,7 +37,7 @@ void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_ar
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_arg_error_terse_mismatch();
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments");
|
||||
mp_raise_TypeError("function does not take keyword arguments");
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n
|
||||
mp_arg_error_terse_mismatch();
|
||||
} else {
|
||||
// TODO better error message
|
||||
mp_raise_msg(&mp_type_TypeError, "extra positional arguments given");
|
||||
mp_raise_TypeError("extra positional arguments given");
|
||||
}
|
||||
}
|
||||
if (kws_found < kws->used) {
|
||||
@ -123,7 +123,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n
|
||||
mp_arg_error_terse_mismatch();
|
||||
} else {
|
||||
// TODO better error message
|
||||
mp_raise_msg(&mp_type_TypeError, "extra keyword arguments given");
|
||||
mp_raise_TypeError("extra keyword arguments given");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -136,7 +136,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args,
|
||||
|
||||
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER
|
||||
NORETURN void mp_arg_error_terse_mismatch(void) {
|
||||
mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch");
|
||||
mp_raise_TypeError("argument num/types mismatch");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
47
py/bc.c
47
py/bc.c
@ -54,6 +54,16 @@ mp_uint_t mp_decode_uint(const byte **ptr) {
|
||||
return unum;
|
||||
}
|
||||
|
||||
// This function is used to help reduce stack usage at the caller, for the case when
|
||||
// the caller doesn't need to increase the ptr argument. If ptr is a local variable
|
||||
// and the caller uses mp_decode_uint(&ptr) instead of this function, then the compiler
|
||||
// must allocate a slot on the stack for ptr, and this slot cannot be reused for
|
||||
// anything else in the function because the pointer may have been stored in a global
|
||||
// and reused later in the function.
|
||||
mp_uint_t mp_decode_uint_value(const byte *ptr) {
|
||||
return mp_decode_uint(&ptr);
|
||||
}
|
||||
|
||||
STATIC NORETURN void fun_pos_args_mismatch(mp_obj_fun_bc_t *f, size_t expected, size_t given) {
|
||||
#if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE
|
||||
// generic message, used also for other argument issues
|
||||
@ -86,25 +96,26 @@ STATIC void dump_args(const mp_obj_t *a, size_t sz) {
|
||||
|
||||
// On entry code_state should be allocated somewhere (stack/heap) and
|
||||
// contain the following valid entries:
|
||||
// - code_state->ip should contain the offset in bytes from the start of
|
||||
// the bytecode chunk to just after n_state and n_exc_stack
|
||||
// - code_state->n_state should be set to the state size (locals plus stack)
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// - code_state->fun_bc should contain a pointer to the function object
|
||||
// - code_state->ip should contain the offset in bytes from the pointer
|
||||
// code_state->fun_bc->bytecode to the entry n_state (0 for bytecode, non-zero for native)
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
// This function is pretty complicated. It's main aim is to be efficient in speed and RAM
|
||||
// usage for the common case of positional only args.
|
||||
size_t n_state = code_state->n_state;
|
||||
|
||||
// get the function object that we want to set up (could be bytecode or native code)
|
||||
mp_obj_fun_bc_t *self = code_state->fun_bc;
|
||||
|
||||
// ip comes in as an offset into bytecode, so turn it into a true pointer
|
||||
code_state->ip = self->bytecode + (size_t)code_state->ip;
|
||||
|
||||
// store pointer to constant table
|
||||
code_state->const_table = self->const_table;
|
||||
|
||||
#if MICROPY_STACKLESS
|
||||
code_state->prev = NULL;
|
||||
#endif
|
||||
|
||||
// get params
|
||||
size_t n_state = mp_decode_uint(&code_state->ip);
|
||||
mp_decode_uint(&code_state->ip); // skip n_exc_stack
|
||||
size_t scope_flags = *code_state->ip++;
|
||||
size_t n_pos_args = *code_state->ip++;
|
||||
size_t n_kwonly_args = *code_state->ip++;
|
||||
@ -168,7 +179,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz
|
||||
}
|
||||
|
||||
// get pointer to arg_names array
|
||||
const mp_obj_t *arg_names = (const mp_obj_t*)code_state->const_table;
|
||||
const mp_obj_t *arg_names = (const mp_obj_t*)self->const_table;
|
||||
|
||||
for (size_t i = 0; i < n_kw; i++) {
|
||||
// the keys in kwargs are expected to be qstr objects
|
||||
@ -185,7 +196,12 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz
|
||||
}
|
||||
// Didn't find name match with positional args
|
||||
if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) {
|
||||
mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments");
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_TypeError("unexpected keyword argument");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"unexpected keyword argument '%q'", MP_OBJ_QSTR_VALUE(wanted_arg_name)));
|
||||
}
|
||||
}
|
||||
mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]);
|
||||
continue2:;
|
||||
@ -234,7 +250,7 @@ continue2:;
|
||||
} else {
|
||||
// no keyword arguments given
|
||||
if (n_kwonly_args != 0) {
|
||||
mp_raise_msg(&mp_type_TypeError, "function missing keyword-only argument");
|
||||
mp_raise_TypeError("function missing keyword-only argument");
|
||||
}
|
||||
if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) {
|
||||
*var_pos_kw_args = mp_obj_new_dict(0);
|
||||
@ -244,13 +260,8 @@ continue2:;
|
||||
// get the ip and skip argument names
|
||||
const byte *ip = code_state->ip;
|
||||
|
||||
// store pointer to code_info and jump over it
|
||||
{
|
||||
code_state->code_info = ip;
|
||||
const byte *ip2 = ip;
|
||||
size_t code_info_size = mp_decode_uint(&ip2);
|
||||
ip += code_info_size;
|
||||
}
|
||||
// jump over code info (source file and line-number mapping)
|
||||
ip += mp_decode_uint_value(ip);
|
||||
|
||||
// bytecode prelude: initialise closed over variables
|
||||
size_t local_num;
|
||||
|
13
py/bc.h
13
py/bc.h
@ -28,6 +28,7 @@
|
||||
|
||||
#include "py/runtime.h"
|
||||
#include "py/obj.h"
|
||||
#include "py/objfun.h"
|
||||
|
||||
// bytecode layout:
|
||||
//
|
||||
@ -70,9 +71,12 @@ typedef struct _mp_exc_stack_t {
|
||||
} mp_exc_stack_t;
|
||||
|
||||
typedef struct _mp_code_state_t {
|
||||
const byte *code_info;
|
||||
// The fun_bc entry points to the underlying function object that is being executed.
|
||||
// It is needed to access the start of bytecode and the const_table.
|
||||
// It is also needed to prevent the GC from reclaiming the bytecode during execution,
|
||||
// because the ip pointer below will always point to the interior of the bytecode.
|
||||
mp_obj_fun_bc_t *fun_bc;
|
||||
const byte *ip;
|
||||
const mp_uint_t *const_table;
|
||||
mp_obj_t *sp;
|
||||
// bit 0 is saved currently_in_except_block value
|
||||
mp_exc_stack_t *exc_sp;
|
||||
@ -80,7 +84,6 @@ typedef struct _mp_code_state_t {
|
||||
#if MICROPY_STACKLESS
|
||||
struct _mp_code_state_t *prev;
|
||||
#endif
|
||||
size_t n_state;
|
||||
// Variable-length
|
||||
mp_obj_t state[0];
|
||||
// Variable-length, never accessed by name, only as (void*)(state + n_state)
|
||||
@ -88,11 +91,11 @@ typedef struct _mp_code_state_t {
|
||||
} mp_code_state_t;
|
||||
|
||||
mp_uint_t mp_decode_uint(const byte **ptr);
|
||||
mp_uint_t mp_decode_uint_value(const byte *ptr);
|
||||
|
||||
mp_vm_return_kind_t mp_execute_bytecode(mp_code_state_t *code_state, volatile mp_obj_t inject_exc);
|
||||
mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t func, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
struct _mp_obj_fun_bc_t;
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, struct _mp_obj_fun_bc_t *self, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
void mp_setup_code_state(mp_code_state_t *code_state, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
void mp_bytecode_print(const void *descr, const byte *code, mp_uint_t len, const mp_uint_t *const_table);
|
||||
void mp_bytecode_print2(const byte *code, size_t len, const mp_uint_t *const_table);
|
||||
const byte *mp_bytecode_print_str(const byte *ip);
|
||||
|
@ -78,7 +78,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args;
|
||||
|
||||
// get the source
|
||||
mp_uint_t str_len;
|
||||
size_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// get the filename
|
||||
@ -95,7 +95,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) {
|
||||
case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break;
|
||||
case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break;
|
||||
default:
|
||||
mp_raise_msg(&mp_type_ValueError, "bad compile mode");
|
||||
mp_raise_ValueError("bad compile mode");
|
||||
}
|
||||
|
||||
mp_obj_code_t *code = m_new_obj(mp_obj_code_t);
|
||||
@ -128,7 +128,7 @@ STATIC mp_obj_t eval_exec_helper(size_t n_args, const mp_obj_t *args, mp_parse_i
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_uint_t str_len;
|
||||
size_t str_len;
|
||||
const char *str = mp_obj_str_get_data(args[0], &str_len);
|
||||
|
||||
// create the lexer
|
||||
|
@ -97,7 +97,7 @@ STATIC mp_import_stat_t stat_dir_or_file(vstr_t *path) {
|
||||
STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *dest) {
|
||||
#if MICROPY_PY_SYS
|
||||
// extract the list of paths
|
||||
mp_uint_t path_num;
|
||||
size_t path_num;
|
||||
mp_obj_t *path_items;
|
||||
mp_obj_list_get(mp_sys_path, &path_num, &path_items);
|
||||
|
||||
@ -111,7 +111,7 @@ STATIC mp_import_stat_t find_file(const char *file_str, uint file_len, vstr_t *d
|
||||
// go through each path looking for a directory or file
|
||||
for (mp_uint_t i = 0; i < path_num; i++) {
|
||||
vstr_reset(dest);
|
||||
mp_uint_t p_len;
|
||||
size_t p_len;
|
||||
const char *p = mp_obj_str_get_data(path_items[i], &p_len);
|
||||
if (p_len > 0) {
|
||||
vstr_add_strn(dest, p, p_len);
|
||||
@ -265,7 +265,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
|
||||
}
|
||||
}
|
||||
|
||||
mp_uint_t mod_len;
|
||||
size_t mod_len;
|
||||
const char *mod_str = mp_obj_str_get_data(module_name, &mod_len);
|
||||
|
||||
if (level != 0) {
|
||||
@ -296,7 +296,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
|
||||
DEBUG_printf("\n");
|
||||
#endif
|
||||
|
||||
mp_uint_t this_name_l;
|
||||
size_t this_name_l;
|
||||
const char *this_name = mp_obj_str_get_data(this_name_q, &this_name_l);
|
||||
|
||||
const char *p = this_name + this_name_l;
|
||||
@ -341,7 +341,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
|
||||
qstr new_mod_q = qstr_from_strn(new_mod, new_mod_l);
|
||||
DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q));
|
||||
if (new_mod_q == MP_QSTR_) {
|
||||
mp_raise_msg(&mp_type_ValueError, "cannot perform relative import");
|
||||
mp_raise_ValueError("cannot perform relative import");
|
||||
}
|
||||
module_name = MP_OBJ_NEW_QSTR(new_mod_q);
|
||||
mod_str = new_mod;
|
||||
|
38
py/compile.c
38
py/compile.c
@ -456,8 +456,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
compile_syntax_error(comp, pn, "can't assign to literal");
|
||||
return;
|
||||
goto cannot_assign;
|
||||
}
|
||||
} else {
|
||||
// pn must be a struct
|
||||
@ -472,7 +471,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
|
||||
case PN_exprlist:
|
||||
// lhs is a tuple
|
||||
if (assign_kind != ASSIGN_STORE) {
|
||||
goto bad_aug;
|
||||
goto cannot_assign;
|
||||
}
|
||||
c_assign_tuple(comp, MP_PARSE_NODE_NULL, MP_PARSE_NODE_STRUCT_NUM_NODES(pns), pns->nodes);
|
||||
break;
|
||||
@ -485,7 +484,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
|
||||
} else {
|
||||
assert(MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_testlist_comp));
|
||||
if (assign_kind != ASSIGN_STORE) {
|
||||
goto bad_aug;
|
||||
goto cannot_assign;
|
||||
}
|
||||
pns = (mp_parse_node_struct_t*)pns->nodes[0];
|
||||
goto testlist_comp;
|
||||
@ -495,7 +494,7 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
|
||||
case PN_atom_bracket:
|
||||
// lhs is something in brackets
|
||||
if (assign_kind != ASSIGN_STORE) {
|
||||
goto bad_aug;
|
||||
goto cannot_assign;
|
||||
}
|
||||
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
|
||||
// empty list, assignment allowed
|
||||
@ -543,10 +542,6 @@ STATIC void c_assign(compiler_t *comp, mp_parse_node_t pn, assign_kind_t assign_
|
||||
|
||||
cannot_assign:
|
||||
compile_syntax_error(comp, pn, "can't assign to expression");
|
||||
return;
|
||||
|
||||
bad_aug:
|
||||
compile_syntax_error(comp, pn, "illegal expression for augmented assignment");
|
||||
}
|
||||
|
||||
// stuff for lambda and comprehensions and generators:
|
||||
@ -1449,8 +1444,9 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
pn_range_start = args[0];
|
||||
pn_range_end = args[1];
|
||||
pn_range_step = args[2];
|
||||
// We need to know sign of step. This is possible only if it's constant
|
||||
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)) {
|
||||
// the step must be a non-zero constant integer to do the optimisation
|
||||
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_range_step)
|
||||
|| MP_PARSE_NODE_LEAF_SMALL_INT(pn_range_step) == 0) {
|
||||
optimize = false;
|
||||
}
|
||||
}
|
||||
@ -1529,7 +1525,7 @@ STATIC void compile_try_except(compiler_t *comp, mp_parse_node_t pn_body, int n_
|
||||
if (MP_PARSE_NODE_IS_NULL(pns_except->nodes[0])) {
|
||||
// this is a catch all exception handler
|
||||
if (i + 1 != n_except) {
|
||||
compile_syntax_error(comp, pn_excepts[i], "default 'except:' must be last");
|
||||
compile_syntax_error(comp, pn_excepts[i], "default 'except' must be last");
|
||||
compile_decrease_except_level(comp);
|
||||
return;
|
||||
}
|
||||
@ -2190,9 +2186,10 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
|
||||
compile_load_id(comp, MP_QSTR___class__);
|
||||
// look for first argument to function (assumes it's "self")
|
||||
for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
|
||||
if (comp->scope_cur->id_info[i].flags & ID_FLAG_IS_PARAM) {
|
||||
id_info_t *id = &comp->scope_cur->id_info[i];
|
||||
if (id->flags & ID_FLAG_IS_PARAM) {
|
||||
// first argument found; load it and call super
|
||||
EMIT_LOAD_FAST(MP_QSTR_, comp->scope_cur->id_info[i].local_num);
|
||||
compile_load_id(comp, id->qst);
|
||||
EMIT_ARG(call_function, 2, 0, 0);
|
||||
return;
|
||||
}
|
||||
@ -2437,13 +2434,21 @@ STATIC void compile_atom_brace(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||
compile_node(comp, pn_i);
|
||||
if (is_dict) {
|
||||
if (!is_key_value) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dictionary");
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
|
||||
} else {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting key:value for dict");
|
||||
}
|
||||
return;
|
||||
}
|
||||
EMIT(store_map);
|
||||
} else {
|
||||
if (is_key_value) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "invalid syntax");
|
||||
} else {
|
||||
compile_syntax_error(comp, (mp_parse_node_t)pns, "expecting just a value for set");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -3005,6 +3010,7 @@ STATIC void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
|
||||
// There are 4 slots on the stack for the iterator, and the first one is
|
||||
// NULL to indicate that the second one points to the iterator object.
|
||||
if (scope->kind == SCOPE_GEN_EXPR) {
|
||||
// TODO static assert that MP_OBJ_ITER_BUF_NSLOTS == 4
|
||||
EMIT(load_null);
|
||||
compile_load_id(comp, qstr_arg);
|
||||
EMIT(load_null);
|
||||
|
@ -735,7 +735,7 @@ void mp_emit_bc_unwind_jump(emit_t *emit, mp_uint_t label, mp_uint_t except_dept
|
||||
// need to pop the iterator if we are breaking out of a for loop
|
||||
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
|
||||
// also pop the iter_buf
|
||||
for (size_t i = 0; i < sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1; ++i) {
|
||||
for (size_t i = 0; i < MP_OBJ_ITER_BUF_NSLOTS - 1; ++i) {
|
||||
emit_write_bytecode_byte(emit, MP_BC_POP_TOP);
|
||||
}
|
||||
}
|
||||
@ -778,7 +778,7 @@ void mp_emit_bc_end_finally(emit_t *emit) {
|
||||
}
|
||||
|
||||
void mp_emit_bc_get_iter(emit_t *emit, bool use_stack) {
|
||||
emit_bc_pre(emit, use_stack ? sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t) - 1 : 0);
|
||||
emit_bc_pre(emit, use_stack ? MP_OBJ_ITER_BUF_NSLOTS - 1 : 0);
|
||||
emit_write_bytecode_byte(emit, use_stack ? MP_BC_GET_ITER_STACK : MP_BC_GET_ITER);
|
||||
}
|
||||
|
||||
@ -788,7 +788,7 @@ void mp_emit_bc_for_iter(emit_t *emit, mp_uint_t label) {
|
||||
}
|
||||
|
||||
void mp_emit_bc_for_iter_end(emit_t *emit) {
|
||||
emit_bc_pre(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
|
||||
emit_bc_pre(emit, -MP_OBJ_ITER_BUF_NSLOTS);
|
||||
}
|
||||
|
||||
void mp_emit_bc_pop_block(emit_t *emit) {
|
||||
|
@ -407,43 +407,29 @@ STATIC void emit_native_start_pass(emit_t *emit, pass_kind_t pass, scope_t *scop
|
||||
#endif
|
||||
|
||||
// prepare incoming arguments for call to mp_setup_code_state
|
||||
|
||||
#if N_X86
|
||||
asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_2);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_3);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_4);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_5);
|
||||
#else
|
||||
#if N_THUMB
|
||||
ASM_MOV_REG_REG(emit->as, ASM_THUMB_REG_R4, REG_ARG_4);
|
||||
#elif N_ARM
|
||||
ASM_MOV_REG_REG(emit->as, ASM_ARM_REG_R4, REG_ARG_4);
|
||||
#else
|
||||
ASM_MOV_REG_REG(emit->as, REG_ARG_5, REG_ARG_4);
|
||||
#endif
|
||||
ASM_MOV_REG_REG(emit->as, REG_ARG_4, REG_ARG_3);
|
||||
ASM_MOV_REG_REG(emit->as, REG_ARG_3, REG_ARG_2);
|
||||
ASM_MOV_REG_REG(emit->as, REG_ARG_2, REG_ARG_1);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 0, REG_ARG_1);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 1, REG_ARG_2);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 2, REG_ARG_3);
|
||||
asm_x86_mov_arg_to_r32(emit->as, 3, REG_ARG_4);
|
||||
#endif
|
||||
|
||||
// set code_state.fun_bc
|
||||
ASM_MOV_REG_TO_LOCAL(emit->as, REG_ARG_1, offsetof(mp_code_state_t, fun_bc) / sizeof(uintptr_t));
|
||||
|
||||
// set code_state.ip (offset from start of this function to prelude info)
|
||||
// XXX this encoding may change size
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
|
||||
// set code_state.n_state
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->n_state, offsetof(mp_code_state_t, n_state) / sizeof(mp_uint_t), REG_ARG_1);
|
||||
ASM_MOV_IMM_TO_LOCAL_USING(emit->as, emit->prelude_offset, offsetof(mp_code_state_t, ip) / sizeof(uintptr_t), REG_ARG_1);
|
||||
|
||||
// put address of code_state into first arg
|
||||
ASM_MOV_LOCAL_ADDR_TO_REG(emit->as, 0, REG_ARG_1);
|
||||
|
||||
// call mp_setup_code_state to prepare code_state structure
|
||||
#if N_THUMB
|
||||
asm_thumb_op16(emit->as, 0xb400 | (1 << ASM_THUMB_REG_R4)); // push 5th arg
|
||||
asm_thumb_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_THUMB_REG_R4);
|
||||
asm_thumb_op16(emit->as, 0xbc00 | (1 << REG_RET)); // pop dummy (was 5th arg)
|
||||
#elif N_ARM
|
||||
asm_arm_push(emit->as, 1 << ASM_ARM_REG_R4); // push 5th arg
|
||||
asm_arm_bl_ind(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE, ASM_ARM_REG_R4);
|
||||
asm_arm_pop(emit->as, 1 << REG_RET); // pop dummy (was 5th arg)
|
||||
#else
|
||||
ASM_CALL_IND(emit->as, mp_fun_table[MP_F_SETUP_CODE_STATE], MP_F_SETUP_CODE_STATE);
|
||||
#endif
|
||||
@ -477,6 +463,9 @@ STATIC void emit_native_end_pass(emit_t *emit) {
|
||||
|
||||
if (!emit->do_viper_types) {
|
||||
emit->prelude_offset = mp_asm_base_get_code_pos(&emit->as->base);
|
||||
mp_asm_base_data(&emit->as->base, 1, 0x80 | ((emit->n_state >> 7) & 0x7f));
|
||||
mp_asm_base_data(&emit->as->base, 1, emit->n_state & 0x7f);
|
||||
mp_asm_base_data(&emit->as->base, 1, 0); // n_exc_stack
|
||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->scope_flags);
|
||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->num_pos_args);
|
||||
mp_asm_base_data(&emit->as->base, 1, emit->scope->num_kwonly_args);
|
||||
@ -1772,7 +1761,7 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
|
||||
emit_pre_pop_reg(emit, &vtype, REG_ARG_1);
|
||||
assert(vtype == VTYPE_PYOBJ);
|
||||
if (use_stack) {
|
||||
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
|
||||
emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, MP_OBJ_ITER_BUF_NSLOTS);
|
||||
emit_call(emit, MP_F_NATIVE_GETITER);
|
||||
} else {
|
||||
// mp_getiter will allocate the iter_buf on the heap
|
||||
@ -1784,8 +1773,8 @@ STATIC void emit_native_get_iter(emit_t *emit, bool use_stack) {
|
||||
|
||||
STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
|
||||
emit_native_pre(emit);
|
||||
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t));
|
||||
adjust_stack(emit, 4);
|
||||
emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_1, MP_OBJ_ITER_BUF_NSLOTS);
|
||||
adjust_stack(emit, MP_OBJ_ITER_BUF_NSLOTS);
|
||||
emit_call(emit, MP_F_NATIVE_ITERNEXT);
|
||||
ASM_MOV_IMM_TO_REG(emit->as, (mp_uint_t)MP_OBJ_STOP_ITERATION, REG_TEMP1);
|
||||
ASM_JUMP_IF_REG_EQ(emit->as, REG_RET, REG_TEMP1, label);
|
||||
@ -1795,7 +1784,7 @@ STATIC void emit_native_for_iter(emit_t *emit, mp_uint_t label) {
|
||||
STATIC void emit_native_for_iter_end(emit_t *emit) {
|
||||
// adjust stack counter (we get here from for_iter ending, which popped the value for us)
|
||||
emit_native_pre(emit);
|
||||
adjust_stack(emit, -(sizeof(mp_obj_iter_buf_t) / sizeof(mp_obj_t)));
|
||||
adjust_stack(emit, -MP_OBJ_ITER_BUF_NSLOTS);
|
||||
emit_post(emit);
|
||||
}
|
||||
|
||||
|
83
py/lexer.c
83
py/lexer.c
@ -159,7 +159,6 @@ STATIC void next_char(mp_lexer_t *lex) {
|
||||
|
||||
STATIC void indent_push(mp_lexer_t *lex, size_t indent) {
|
||||
if (lex->num_indent_level >= lex->alloc_indent_level) {
|
||||
// TODO use m_renew_maybe and somehow indicate an error if it fails... probably by using MP_TOKEN_MEMORY_ERROR
|
||||
lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);
|
||||
lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC;
|
||||
}
|
||||
@ -177,7 +176,6 @@ STATIC void indent_pop(mp_lexer_t *lex) {
|
||||
// some tricky operator encoding:
|
||||
// <op> = begin with <op>, if this opchar matches then begin here
|
||||
// e<op> = end with <op>, if this opchar matches then end
|
||||
// E<op> = mandatory end with <op>, this opchar must match, then end
|
||||
// c<op> = continue with <op>, if this opchar matches then continue matching
|
||||
// this means if the start of two ops are the same then they are equal til the last char
|
||||
|
||||
@ -194,7 +192,7 @@ STATIC const char *const tok_enc =
|
||||
"%e=" // % %=
|
||||
"^e=" // ^ ^=
|
||||
"=e=" // = ==
|
||||
"!E="; // !=
|
||||
"!."; // start of special cases: != . ...
|
||||
|
||||
// TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries
|
||||
STATIC const uint8_t tok_enc_kind[] = {
|
||||
@ -214,7 +212,6 @@ STATIC const uint8_t tok_enc_kind[] = {
|
||||
MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,
|
||||
MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
|
||||
MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
|
||||
MP_TOKEN_OP_NOT_EQUAL,
|
||||
};
|
||||
|
||||
// must have the same order as enum in lexer.h
|
||||
@ -604,20 +601,6 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
|
||||
}
|
||||
}
|
||||
|
||||
} else if (is_char(lex, '.')) {
|
||||
// special handling for . and ... operators, because .. is not a valid operator
|
||||
|
||||
// get first char
|
||||
next_char(lex);
|
||||
|
||||
if (is_char_and(lex, '.', '.')) {
|
||||
next_char(lex);
|
||||
next_char(lex);
|
||||
lex->tok_kind = MP_TOKEN_ELLIPSIS;
|
||||
} else {
|
||||
lex->tok_kind = MP_TOKEN_DEL_PERIOD;
|
||||
}
|
||||
|
||||
} else {
|
||||
// search for encoded delimiter or operator
|
||||
|
||||
@ -626,9 +609,6 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
|
||||
for (; *t != 0 && !is_char(lex, *t); t += 1) {
|
||||
if (*t == 'e' || *t == 'c') {
|
||||
t += 1;
|
||||
} else if (*t == 'E') {
|
||||
tok_enc_index -= 1;
|
||||
t += 1;
|
||||
}
|
||||
tok_enc_index += 1;
|
||||
}
|
||||
@ -639,55 +619,48 @@ void mp_lexer_to_next(mp_lexer_t *lex) {
|
||||
// didn't match any delimiter or operator characters
|
||||
lex->tok_kind = MP_TOKEN_INVALID;
|
||||
|
||||
} else if (*t == '!') {
|
||||
// "!=" is a special case because "!" is not a valid operator
|
||||
if (is_char(lex, '=')) {
|
||||
next_char(lex);
|
||||
lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;
|
||||
} else {
|
||||
lex->tok_kind = MP_TOKEN_INVALID;
|
||||
}
|
||||
|
||||
} else if (*t == '.') {
|
||||
// "." and "..." are special cases because ".." is not a valid operator
|
||||
if (is_char_and(lex, '.', '.')) {
|
||||
next_char(lex);
|
||||
next_char(lex);
|
||||
lex->tok_kind = MP_TOKEN_ELLIPSIS;
|
||||
} else {
|
||||
lex->tok_kind = MP_TOKEN_DEL_PERIOD;
|
||||
}
|
||||
|
||||
} else {
|
||||
// matched a delimiter or operator character
|
||||
|
||||
// get the maximum characters for a valid token
|
||||
t += 1;
|
||||
size_t t_index = tok_enc_index;
|
||||
for (;;) {
|
||||
for (; *t == 'e'; t += 1) {
|
||||
t += 1;
|
||||
t_index += 1;
|
||||
if (is_char(lex, *t)) {
|
||||
next_char(lex);
|
||||
tok_enc_index = t_index;
|
||||
while (*t == 'c' || *t == 'e') {
|
||||
t_index += 1;
|
||||
if (is_char(lex, t[1])) {
|
||||
next_char(lex);
|
||||
tok_enc_index = t_index;
|
||||
if (*t == 'e') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (*t == 'E') {
|
||||
t += 1;
|
||||
if (is_char(lex, *t)) {
|
||||
next_char(lex);
|
||||
tok_enc_index = t_index;
|
||||
} else {
|
||||
lex->tok_kind = MP_TOKEN_INVALID;
|
||||
goto tok_enc_no_match;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (*t == 'c') {
|
||||
t += 1;
|
||||
t_index += 1;
|
||||
if (is_char(lex, *t)) {
|
||||
next_char(lex);
|
||||
tok_enc_index = t_index;
|
||||
t += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
} else if (*t == 'c') {
|
||||
break;
|
||||
}
|
||||
t += 2;
|
||||
}
|
||||
|
||||
// set token kind
|
||||
lex->tok_kind = tok_enc_kind[tok_enc_index];
|
||||
|
||||
tok_enc_no_match:
|
||||
|
||||
// compute bracket level for implicit line joining
|
||||
if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) {
|
||||
lex->nested_bracket_level += 1;
|
||||
|
@ -142,8 +142,15 @@ clean-prog:
|
||||
endif
|
||||
|
||||
LIBMICROPYTHON = libmicropython.a
|
||||
|
||||
# We can execute extra commands after library creation using
|
||||
# LIBMICROPYTHON_EXTRA_CMD. This may be needed e.g. to integrate
|
||||
# with 3rd-party projects which don't have proper dependency
|
||||
# tracking. Then LIBMICROPYTHON_EXTRA_CMD can e.g. touch some
|
||||
# other file to cause needed effect, e.g. relinking with new lib.
|
||||
lib $(LIBMICROPYTHON): $(OBJ)
|
||||
$(AR) rcs $(LIBMICROPYTHON) $^
|
||||
$(LIBMICROPYTHON_EXTRA_CMD)
|
||||
|
||||
clean:
|
||||
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)
|
||||
|
@ -180,7 +180,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
|
||||
str[3] = (c & 0x3F) | 0x80;
|
||||
len = 4;
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)");
|
||||
mp_raise_ValueError("chr() arg not in range(0x110000)");
|
||||
}
|
||||
return mp_obj_new_str(str, len, true);
|
||||
#else
|
||||
@ -189,7 +189,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) {
|
||||
char str[1] = {ord};
|
||||
return mp_obj_new_str(str, 1, true);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(256)");
|
||||
mp_raise_ValueError("chr() arg not in range(256)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -289,7 +289,7 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t
|
||||
if (default_elem != NULL) {
|
||||
best_obj = default_elem->value;
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_ValueError, "arg is an empty sequence");
|
||||
mp_raise_ValueError("arg is an empty sequence");
|
||||
}
|
||||
}
|
||||
return best_obj;
|
||||
@ -336,7 +336,7 @@ STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) {
|
||||
MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) {
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
const char *str = mp_obj_str_get_data(o_in, &len);
|
||||
#if MICROPY_PY_BUILTINS_STR_UNICODE
|
||||
if (MP_OBJ_IS_STR(o_in)) {
|
||||
@ -397,9 +397,9 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *
|
||||
mp_map_elem_t *sep_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_MAP_LOOKUP);
|
||||
mp_map_elem_t *end_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_end), MP_MAP_LOOKUP);
|
||||
const char *sep_data = " ";
|
||||
mp_uint_t sep_len = 1;
|
||||
size_t sep_len = 1;
|
||||
const char *end_data = "\n";
|
||||
mp_uint_t end_len = 1;
|
||||
size_t end_len = 1;
|
||||
if (sep_elem != NULL && sep_elem->value != mp_const_none) {
|
||||
sep_data = mp_obj_str_get_data(sep_elem->value, &sep_len);
|
||||
}
|
||||
@ -473,22 +473,16 @@ STATIC mp_obj_t mp_builtin_round(size_t n_args, const mp_obj_t *args) {
|
||||
mp_float_t val = mp_obj_get_float(o_in);
|
||||
mp_float_t mult = MICROPY_FLOAT_C_FUN(pow)(10, num_dig);
|
||||
// TODO may lead to overflow
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val * mult) / mult;
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val * mult) / mult;
|
||||
return mp_obj_new_float(rounded);
|
||||
}
|
||||
mp_float_t val = mp_obj_get_float(o_in);
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(round)(val);
|
||||
mp_int_t r = rounded;
|
||||
// make rounded value even if it was halfway between ints
|
||||
if (val - rounded == 0.5) {
|
||||
r = (r + 1) & (~1);
|
||||
} else if (val - rounded == -0.5) {
|
||||
r &= ~1;
|
||||
}
|
||||
mp_float_t rounded = MICROPY_FLOAT_C_FUN(nearbyint)(val);
|
||||
return mp_obj_new_int_from_float(rounded);
|
||||
#else
|
||||
mp_int_t r = mp_obj_get_int(o_in);
|
||||
#endif
|
||||
return mp_obj_new_int(r);
|
||||
#endif
|
||||
}
|
||||
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_round_obj, 1, 2, mp_builtin_round);
|
||||
|
||||
@ -510,7 +504,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum);
|
||||
|
||||
STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
||||
if (n_args > 1) {
|
||||
mp_raise_msg(&mp_type_TypeError, "must use keyword argument for key function");
|
||||
mp_raise_TypeError("must use keyword argument for key function");
|
||||
}
|
||||
mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args);
|
||||
mp_obj_list_sort(1, &self, kwargs);
|
||||
|
@ -57,7 +57,7 @@ STATIC NORETURN void math_error(void) {
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_1_TO_INT(py_name, c_name) \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { mp_int_t x = MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj)); return mp_obj_new_int(x); } \
|
||||
STATIC mp_obj_t mp_math_ ## py_name(mp_obj_t x_obj) { return mp_obj_new_int_from_float(MICROPY_FLOAT_C_FUN(c_name)(mp_obj_get_float(x_obj))); } \
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_math_## py_name ## _obj, mp_math_ ## py_name);
|
||||
|
||||
#define MATH_FUN_1_ERRCOND(py_name, c_name, error_condition) \
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "py/mpstate.h"
|
||||
#include "py/builtin.h"
|
||||
#include "py/stackctrl.h"
|
||||
#include "py/runtime.h"
|
||||
#include "py/gc.h"
|
||||
|
||||
// Various builtins specific to MicroPython runtime,
|
||||
@ -128,6 +129,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf);
|
||||
#endif
|
||||
|
||||
#if MICROPY_ENABLE_SCHEDULER
|
||||
STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) {
|
||||
if (!mp_sched_schedule(function, arg)) {
|
||||
mp_raise_msg(&mp_type_RuntimeError, "schedule stack full");
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mp_micropython_schedule_obj, mp_micropython_schedule);
|
||||
#endif
|
||||
|
||||
STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) },
|
||||
@ -151,6 +162,9 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },
|
||||
#endif
|
||||
#if MICROPY_ENABLE_SCHEDULER
|
||||
{ MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) },
|
||||
#endif
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_micropython_globals, mp_module_micropython_globals_table);
|
||||
|
@ -215,7 +215,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
|
||||
thread_entry_args_t *th_args;
|
||||
|
||||
// get positional arguments
|
||||
mp_uint_t pos_args_len;
|
||||
size_t pos_args_len;
|
||||
mp_obj_t *pos_args_items;
|
||||
mp_obj_get_array(args[1], &pos_args_len, &pos_args_items);
|
||||
|
||||
@ -227,7 +227,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
|
||||
} else {
|
||||
// positional and keyword arguments
|
||||
if (mp_obj_get_type(args[2]) != &mp_type_dict) {
|
||||
mp_raise_msg(&mp_type_TypeError, "expecting a dict for keyword args");
|
||||
mp_raise_TypeError("expecting a dict for keyword args");
|
||||
}
|
||||
mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map;
|
||||
th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used);
|
||||
|
@ -556,6 +556,15 @@ typedef double mp_float_t;
|
||||
#define MICROPY_CPYTHON_COMPAT (1)
|
||||
#endif
|
||||
|
||||
// Perform full checks as done by CPython. Disabling this
|
||||
// may produce incorrect results, if incorrect data is fed,
|
||||
// but should not lead to MicroPython crashes or similar
|
||||
// grave issues (in other words, only user app should be,
|
||||
// affected, not system).
|
||||
#ifndef MICROPY_FULL_CHECKS
|
||||
#define MICROPY_FULL_CHECKS (1)
|
||||
#endif
|
||||
|
||||
// Whether POSIX-semantics non-blocking streams are supported
|
||||
#ifndef MICROPY_STREAMS_NON_BLOCK
|
||||
#define MICROPY_STREAMS_NON_BLOCK (0)
|
||||
@ -616,6 +625,16 @@ typedef double mp_float_t;
|
||||
#define MICROPY_USE_INTERNAL_PRINTF (1)
|
||||
#endif
|
||||
|
||||
// Support for internal scheduler
|
||||
#ifndef MICROPY_ENABLE_SCHEDULER
|
||||
#define MICROPY_ENABLE_SCHEDULER (0)
|
||||
#endif
|
||||
|
||||
// Maximum number of entries in the scheduler
|
||||
#ifndef MICROPY_SCHEDULER_DEPTH
|
||||
#define MICROPY_SCHEDULER_DEPTH (4)
|
||||
#endif
|
||||
|
||||
// Support for generic VFS sub-system
|
||||
#ifndef MICROPY_VFS
|
||||
#define MICROPY_VFS (0)
|
||||
@ -1095,6 +1114,11 @@ typedef double mp_float_t;
|
||||
#define STATIC static
|
||||
#endif
|
||||
|
||||
// Number of bytes in a word
|
||||
#ifndef BYTES_PER_WORD
|
||||
#define BYTES_PER_WORD (sizeof(mp_uint_t))
|
||||
#endif
|
||||
|
||||
#define BITS_PER_BYTE (8)
|
||||
#define BITS_PER_WORD (BITS_PER_BYTE * BYTES_PER_WORD)
|
||||
// mp_int_t value with most significant bit set
|
||||
|
17
py/mpstate.h
17
py/mpstate.h
@ -50,6 +50,16 @@ typedef struct mp_dynamic_compiler_t {
|
||||
extern mp_dynamic_compiler_t mp_dynamic_compiler;
|
||||
#endif
|
||||
|
||||
// These are the values for sched_state
|
||||
#define MP_SCHED_IDLE (1)
|
||||
#define MP_SCHED_LOCKED (-1)
|
||||
#define MP_SCHED_PENDING (0) // 0 so it's a quick check in the VM
|
||||
|
||||
typedef struct _mp_sched_item_t {
|
||||
mp_obj_t func;
|
||||
mp_obj_t arg;
|
||||
} mp_sched_item_t;
|
||||
|
||||
// This structure hold information about the memory allocation system.
|
||||
typedef struct _mp_state_mem_t {
|
||||
#if MICROPY_MEM_STATS
|
||||
@ -129,6 +139,12 @@ typedef struct _mp_state_vm_t {
|
||||
// pending exception object (MP_OBJ_NULL if not pending)
|
||||
volatile mp_obj_t mp_pending_exception;
|
||||
|
||||
#if MICROPY_ENABLE_SCHEDULER
|
||||
volatile int16_t sched_state;
|
||||
uint16_t sched_sp;
|
||||
mp_sched_item_t sched_stack[MICROPY_SCHEDULER_DEPTH];
|
||||
#endif
|
||||
|
||||
// current exception being handled, for sys.exc_info()
|
||||
#if MICROPY_PY_SYS_EXC_INFO
|
||||
mp_obj_base_t *cur_exception;
|
||||
@ -222,7 +238,6 @@ typedef struct _mp_state_ctx_t {
|
||||
|
||||
extern mp_state_ctx_t mp_state_ctx;
|
||||
|
||||
#define MP_STATE_CTX(x) MP_STATE_THREAD(x)
|
||||
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
|
||||
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
|
||||
|
||||
|
@ -49,10 +49,9 @@ unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||
__asm volatile (
|
||||
// Check for Zephyr, which uses a different calling convention
|
||||
// by default.
|
||||
// TODO: Better check for Zephyr.
|
||||
// TODE: Better support for various x86 calling conventions
|
||||
// (unfortunately, __attribute__((naked)) is not supported on x86).
|
||||
#ifndef CONFIG_SOC_IA32
|
||||
#ifndef __ZEPHYR__
|
||||
"pop %ebp \n" // undo function's prelude
|
||||
#endif
|
||||
"mov 4(%esp), %edx \n" // load nlr_buf
|
||||
|
32
py/obj.c
32
py/obj.c
@ -229,7 +229,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) {
|
||||
return mp_obj_int_get_checked(arg);
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "can't convert to int");
|
||||
mp_raise_TypeError("can't convert to int");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"can't convert %s to int", mp_obj_get_type_str(arg)));
|
||||
@ -279,7 +279,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) {
|
||||
return mp_obj_float_get(arg);
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "can't convert to float");
|
||||
mp_raise_TypeError("can't convert to float");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"can't convert %s to float", mp_obj_get_type_str(arg)));
|
||||
@ -310,7 +310,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||
mp_obj_complex_get(arg, real, imag);
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "can't convert to complex");
|
||||
mp_raise_TypeError("can't convert to complex");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"can't convert %s to complex", mp_obj_get_type_str(arg)));
|
||||
@ -321,14 +321,14 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) {
|
||||
#endif
|
||||
|
||||
// note: returned value in *items may point to the interior of a GC block
|
||||
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
|
||||
void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items) {
|
||||
if (MP_OBJ_IS_TYPE(o, &mp_type_tuple)) {
|
||||
mp_obj_tuple_get(o, len, items);
|
||||
} else if (MP_OBJ_IS_TYPE(o, &mp_type_list)) {
|
||||
mp_obj_list_get(o, len, items);
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "expected tuple/list");
|
||||
mp_raise_TypeError("expected tuple/list");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"object '%s' is not a tuple or list", mp_obj_get_type_str(o)));
|
||||
@ -337,12 +337,12 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) {
|
||||
}
|
||||
|
||||
// note: returned value in *items may point to the interior of a GC block
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
|
||||
mp_uint_t seq_len;
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items) {
|
||||
size_t seq_len;
|
||||
mp_obj_get_array(o, &seq_len, items);
|
||||
if (seq_len != len) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_ValueError, "tuple/list has wrong length");
|
||||
mp_raise_ValueError("tuple/list has wrong length");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError,
|
||||
"requested length %d but object has length %d", (int)len, (int)seq_len));
|
||||
@ -351,13 +351,13 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) {
|
||||
}
|
||||
|
||||
// is_slice determines whether the index is a slice index
|
||||
mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice) {
|
||||
size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice) {
|
||||
mp_int_t i;
|
||||
if (MP_OBJ_IS_SMALL_INT(index)) {
|
||||
i = MP_OBJ_SMALL_INT_VALUE(index);
|
||||
} else if (!mp_obj_get_int_maybe(index, &i)) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "indices must be integers");
|
||||
mp_raise_TypeError("indices must be integers");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"%q indices must be integers, not %s",
|
||||
@ -384,7 +384,9 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index,
|
||||
}
|
||||
}
|
||||
}
|
||||
return i;
|
||||
|
||||
// By this point 0 <= i <= len and so fits in a size_t
|
||||
return (size_t)i;
|
||||
}
|
||||
|
||||
mp_obj_t mp_obj_id(mp_obj_t o_in) {
|
||||
@ -410,7 +412,7 @@ mp_obj_t mp_obj_len(mp_obj_t o_in) {
|
||||
mp_obj_t len = mp_obj_len_maybe(o_in);
|
||||
if (len == MP_OBJ_NULL) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "object has no len");
|
||||
mp_raise_TypeError("object has no len");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"object of type '%s' has no len()", mp_obj_get_type_str(o_in)));
|
||||
@ -451,7 +453,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
if (value == MP_OBJ_NULL) {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "object does not support item deletion");
|
||||
mp_raise_TypeError("object does not support item deletion");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"'%s' object does not support item deletion", mp_obj_get_type_str(base)));
|
||||
@ -466,7 +468,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) {
|
||||
}
|
||||
} else {
|
||||
if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) {
|
||||
mp_raise_msg(&mp_type_TypeError, "object does not support item assignment");
|
||||
mp_raise_TypeError("object does not support item assignment");
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError,
|
||||
"'%s' object does not support item assignment", mp_obj_get_type_str(base)));
|
||||
@ -500,7 +502,7 @@ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
|
||||
void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) {
|
||||
if (!mp_get_buffer(obj, bufinfo, flags)) {
|
||||
mp_raise_msg(&mp_type_TypeError, "object with buffer protocol required");
|
||||
mp_raise_TypeError("object with buffer protocol required");
|
||||
}
|
||||
}
|
||||
|
||||
|
34
py/obj.h
34
py/obj.h
@ -422,6 +422,10 @@ typedef struct _mp_obj_iter_buf_t {
|
||||
mp_obj_t buf[3];
|
||||
} mp_obj_iter_buf_t;
|
||||
|
||||
// The number of slots that an mp_obj_iter_buf_t needs on the Python value stack.
|
||||
// It's rounded up in case mp_obj_base_t is smaller than mp_obj_t (eg for OBJ_REPR_D).
|
||||
#define MP_OBJ_ITER_BUF_NSLOTS ((sizeof(mp_obj_iter_buf_t) + sizeof(mp_obj_t) - 1) / sizeof(mp_obj_t))
|
||||
|
||||
typedef void (*mp_print_fun_t)(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind);
|
||||
typedef mp_obj_t (*mp_make_new_fun_t)(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
typedef mp_obj_t (*mp_call_fun_t)(mp_obj_t fun, size_t n_args, size_t n_kw, const mp_obj_t *args);
|
||||
@ -672,9 +676,9 @@ mp_float_t mp_obj_get_float(mp_obj_t self_in);
|
||||
void mp_obj_get_complex(mp_obj_t self_in, mp_float_t *real, mp_float_t *imag);
|
||||
#endif
|
||||
//qstr mp_obj_get_qstr(mp_obj_t arg);
|
||||
void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items); // *items may point inside a GC block
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items); // *items may point inside a GC block
|
||||
mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, bool is_slice);
|
||||
void mp_obj_get_array(mp_obj_t o, size_t *len, mp_obj_t **items); // *items may point inside a GC block
|
||||
void mp_obj_get_array_fixed_n(mp_obj_t o, size_t len, mp_obj_t **items); // *items may point inside a GC block
|
||||
size_t mp_get_index(const mp_obj_type_t *type, size_t len, mp_obj_t index, bool is_slice);
|
||||
mp_obj_t mp_obj_id(mp_obj_t o_in);
|
||||
mp_obj_t mp_obj_len(mp_obj_t o_in);
|
||||
mp_obj_t mp_obj_len_maybe(mp_obj_t o_in); // may return MP_OBJ_NULL
|
||||
@ -708,12 +712,13 @@ void mp_init_emergency_exception_buf(void);
|
||||
bool mp_obj_str_equal(mp_obj_t s1, mp_obj_t s2);
|
||||
qstr mp_obj_str_get_qstr(mp_obj_t self_in); // use this if you will anyway convert the string to a qstr
|
||||
const char *mp_obj_str_get_str(mp_obj_t self_in); // use this only if you need the string to be null terminated
|
||||
const char *mp_obj_str_get_data(mp_obj_t self_in, mp_uint_t *len);
|
||||
const char *mp_obj_str_get_data(mp_obj_t self_in, size_t *len);
|
||||
mp_obj_t mp_obj_str_intern(mp_obj_t str);
|
||||
void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t str_len, bool is_bytes);
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
// float
|
||||
static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }
|
||||
mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
|
||||
|
||||
// complex
|
||||
@ -724,7 +729,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t
|
||||
#endif
|
||||
|
||||
// tuple
|
||||
void mp_obj_tuple_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items);
|
||||
void mp_obj_tuple_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);
|
||||
void mp_obj_tuple_del(mp_obj_t self_in);
|
||||
mp_int_t mp_obj_tuple_hash(mp_obj_t self_in);
|
||||
|
||||
@ -733,7 +738,7 @@ struct _mp_obj_list_t;
|
||||
void mp_obj_list_init(struct _mp_obj_list_t *o, size_t n);
|
||||
mp_obj_t mp_obj_list_append(mp_obj_t self_in, mp_obj_t arg);
|
||||
mp_obj_t mp_obj_list_remove(mp_obj_t self_in, mp_obj_t value);
|
||||
void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items);
|
||||
void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items);
|
||||
void mp_obj_list_set_len(mp_obj_t self_in, size_t len);
|
||||
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value);
|
||||
mp_obj_t mp_obj_list_sort(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs);
|
||||
@ -819,17 +824,17 @@ typedef struct {
|
||||
mp_int_t step;
|
||||
} mp_bound_slice_t;
|
||||
|
||||
void mp_seq_multiply(const void *items, mp_uint_t item_sz, mp_uint_t len, mp_uint_t times, void *dest);
|
||||
void mp_seq_multiply(const void *items, size_t item_sz, size_t len, size_t times, void *dest);
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
bool mp_seq_get_fast_slice_indexes(mp_uint_t len, mp_obj_t slice, mp_bound_slice_t *indexes);
|
||||
#endif
|
||||
#define mp_seq_copy(dest, src, len, item_t) memcpy(dest, src, len * sizeof(item_t))
|
||||
#define mp_seq_cat(dest, src1, len1, src2, len2, item_t) { memcpy(dest, src1, (len1) * sizeof(item_t)); memcpy(dest + (len1), src2, (len2) * sizeof(item_t)); }
|
||||
bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, mp_uint_t len1, const byte *data2, mp_uint_t len2);
|
||||
bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, mp_uint_t len1, const mp_obj_t *items2, mp_uint_t len2);
|
||||
mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value);
|
||||
mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
|
||||
bool mp_seq_cmp_bytes(mp_uint_t op, const byte *data1, size_t len1, const byte *data2, size_t len2);
|
||||
bool mp_seq_cmp_objs(mp_uint_t op, const mp_obj_t *items1, size_t len1, const mp_obj_t *items2, size_t len2);
|
||||
mp_obj_t mp_seq_index_obj(const mp_obj_t *items, size_t len, size_t n_args, const mp_obj_t *args);
|
||||
mp_obj_t mp_seq_count_obj(const mp_obj_t *items, size_t len, mp_obj_t value);
|
||||
mp_obj_t mp_seq_extract_slice(size_t len, const mp_obj_t *seq, mp_bound_slice_t *indexes);
|
||||
// Helper to clear stale pointers from allocated, but unused memory, to preclude GC problems
|
||||
#define mp_seq_clear(start, len, alloc_len, item_sz) memset((byte*)(start) + (len) * (item_sz), 0, ((alloc_len) - (len)) * (item_sz))
|
||||
#define mp_seq_replace_slice_no_grow(dest, dest_len, beg, end, slice, slice_len, item_sz) \
|
||||
@ -838,9 +843,10 @@ mp_obj_t mp_seq_extract_slice(mp_uint_t len, const mp_obj_t *seq, mp_bound_slice
|
||||
/*printf("memmove(%p, %p, %d)\n", dest + (beg + slice_len), dest + end, (dest_len - end) * (item_sz));*/ \
|
||||
memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), (dest_len - end) * (item_sz));
|
||||
|
||||
// Note: dest and slice regions may overlap
|
||||
#define mp_seq_replace_slice_grow_inplace(dest, dest_len, beg, end, slice, slice_len, len_adj, item_sz) \
|
||||
/*printf("memmove(%p, %p, %d)\n", dest + beg + len_adj, dest + beg, (dest_len - beg) * (item_sz));*/ \
|
||||
memmove(((char*)dest) + (beg + len_adj) * (item_sz), ((char*)dest) + (beg) * (item_sz), (dest_len - beg) * (item_sz)); \
|
||||
memcpy(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));
|
||||
memmove(((char*)dest) + (beg + slice_len) * (item_sz), ((char*)dest) + (end) * (item_sz), ((dest_len) + (len_adj) - ((beg) + (slice_len))) * (item_sz)); \
|
||||
memmove(((char*)dest) + (beg) * (item_sz), slice, slice_len * (item_sz));
|
||||
|
||||
#endif // __MICROPY_INCLUDED_PY_OBJ_H__
|
||||
|
@ -162,8 +162,7 @@ STATIC mp_obj_t array_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
||||
mp_arg_check_num(n_args, n_kw, 1, 2, false);
|
||||
|
||||
// get typecode
|
||||
mp_uint_t l;
|
||||
const char *typecode = mp_obj_str_get_data(args[0], &l);
|
||||
const char *typecode = mp_obj_str_get_str(args[0]);
|
||||
|
||||
if (n_args == 1) {
|
||||
// 1 arg: make an empty array
|
||||
@ -392,7 +391,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value);
|
||||
if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) {
|
||||
compat_error:
|
||||
mp_raise_msg(&mp_type_ValueError, "lhs and rhs should be compatible");
|
||||
mp_raise_ValueError("lhs and rhs should be compatible");
|
||||
}
|
||||
src_len = src_slice->len;
|
||||
src_items = src_slice->items;
|
||||
@ -471,7 +470,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
||||
return MP_OBJ_FROM_PTR(res);
|
||||
#endif
|
||||
} else {
|
||||
mp_uint_t index = mp_get_index(o->base.type, o->len, index_in, false);
|
||||
size_t index = mp_get_index(o->base.type, o->len, index_in, false);
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (o->base.type == &mp_type_memoryview) {
|
||||
index += o->free;
|
||||
|
@ -80,7 +80,7 @@ STATIC mp_obj_t complex_make_new(const mp_obj_type_t *type_in, size_t n_args, si
|
||||
case 1:
|
||||
if (MP_OBJ_IS_STR(args[0])) {
|
||||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
size_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_decimal(s, l, true, true, NULL);
|
||||
} else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) {
|
||||
@ -117,6 +117,7 @@ STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
|
||||
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);
|
||||
case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag));
|
||||
case MP_UNARY_OP_POSITIVE: return o_in;
|
||||
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
|
@ -386,7 +386,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg
|
||||
if (key == MP_OBJ_STOP_ITERATION
|
||||
|| value == MP_OBJ_STOP_ITERATION
|
||||
|| stop != MP_OBJ_STOP_ITERATION) {
|
||||
mp_raise_msg(&mp_type_ValueError, "dictionary update sequence has the wrong length");
|
||||
mp_raise_ValueError("dict update sequence has wrong length");
|
||||
} else {
|
||||
mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value;
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ STATIC mp_obj_t float_make_new(const mp_obj_type_t *type_in, size_t n_args, size
|
||||
default:
|
||||
if (MP_OBJ_IS_STR(args[0])) {
|
||||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
size_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_decimal(s, l, false, false, NULL);
|
||||
} else if (mp_obj_is_float(args[0])) {
|
||||
@ -106,6 +106,7 @@ STATIC mp_obj_t float_unary_op(mp_uint_t op, mp_obj_t o_in) {
|
||||
mp_float_t val = mp_obj_float_get(o_in);
|
||||
switch (op) {
|
||||
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(val != 0);
|
||||
case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(val));
|
||||
case MP_UNARY_OP_POSITIVE: return o_in;
|
||||
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_float(-val);
|
||||
default: return MP_OBJ_NULL; // op not supported
|
||||
|
16
py/objfun.c
16
py/objfun.c
@ -220,9 +220,9 @@ mp_code_state_t *mp_obj_fun_bc_prepare_codestate(mp_obj_t self_in, size_t n_args
|
||||
return NULL;
|
||||
}
|
||||
|
||||
code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack
|
||||
code_state->n_state = n_state;
|
||||
mp_setup_code_state(code_state, self, n_args, n_kw, args);
|
||||
code_state->fun_bc = self;
|
||||
code_state->ip = 0;
|
||||
mp_setup_code_state(code_state, n_args, n_kw, args);
|
||||
|
||||
// execute the byte code with the correct globals context
|
||||
code_state->old_globals = mp_globals_get();
|
||||
@ -265,9 +265,9 @@ STATIC mp_obj_t fun_bc_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const
|
||||
state_size = 0; // indicate that we allocated using alloca
|
||||
}
|
||||
|
||||
code_state->ip = (byte*)(ip - self->bytecode); // offset to after n_state/n_exc_stack
|
||||
code_state->n_state = n_state;
|
||||
mp_setup_code_state(code_state, self, n_args, n_kw, args);
|
||||
code_state->fun_bc = self;
|
||||
code_state->ip = 0;
|
||||
mp_setup_code_state(code_state, n_args, n_kw, args);
|
||||
|
||||
// execute the byte code with the correct globals context
|
||||
code_state->old_globals = mp_globals_get();
|
||||
@ -501,7 +501,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
||||
return mp_obj_int_get_truncated(obj);
|
||||
} else if (MP_OBJ_IS_STR(obj)) {
|
||||
// pointer to the string (it's probably constant though!)
|
||||
mp_uint_t l;
|
||||
size_t l;
|
||||
return (mp_uint_t)mp_obj_str_get_data(obj, &l);
|
||||
} else {
|
||||
mp_obj_type_t *type = mp_obj_get_type(obj);
|
||||
@ -513,7 +513,7 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
||||
#endif
|
||||
} else if (type == &mp_type_tuple || type == &mp_type_list) {
|
||||
// pointer to start of tuple (could pass length, but then could use len(x) for that)
|
||||
mp_uint_t len;
|
||||
size_t len;
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array(obj, &len, &items);
|
||||
return (mp_uint_t)items;
|
||||
|
@ -67,9 +67,9 @@ STATIC mp_obj_t gen_wrap_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons
|
||||
o->base.type = &mp_type_gen_instance;
|
||||
|
||||
o->globals = self_fun->globals;
|
||||
o->code_state.n_state = n_state;
|
||||
o->code_state.ip = (byte*)(ip - self_fun->bytecode); // offset to prelude
|
||||
mp_setup_code_state(&o->code_state, self_fun, n_args, n_kw, args);
|
||||
o->code_state.fun_bc = self_fun;
|
||||
o->code_state.ip = 0;
|
||||
mp_setup_code_state(&o->code_state, n_args, n_kw, args);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun) {
|
||||
STATIC void gen_instance_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
|
||||
(void)kind;
|
||||
mp_obj_gen_instance_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_printf(print, "<generator object '%q' at %p>", mp_obj_code_get_name(self->code_state.code_info), self);
|
||||
mp_printf(print, "<generator object '%q' at %p>", mp_obj_fun_get_name(MP_OBJ_FROM_PTR(self->code_state.fun_bc)), self);
|
||||
}
|
||||
|
||||
mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_obj_t throw_value, mp_obj_t *ret_val) {
|
||||
@ -105,7 +105,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
|
||||
}
|
||||
if (self->code_state.sp == self->code_state.state - 1) {
|
||||
if (send_value != mp_const_none) {
|
||||
mp_raise_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator");
|
||||
mp_raise_TypeError("can't send non-None value to a just-started generator");
|
||||
}
|
||||
} else {
|
||||
*self->code_state.sp = send_value;
|
||||
@ -134,10 +134,12 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_
|
||||
}
|
||||
break;
|
||||
|
||||
case MP_VM_RETURN_EXCEPTION:
|
||||
case MP_VM_RETURN_EXCEPTION: {
|
||||
size_t n_state = mp_decode_uint_value(self->code_state.fun_bc->bytecode);
|
||||
self->code_state.ip = 0;
|
||||
*ret_val = self->code_state.state[self->code_state.n_state - 1];
|
||||
*ret_val = self->code_state.state[n_state - 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret_kind;
|
||||
|
67
py/objint.c
67
py/objint.c
@ -56,7 +56,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
|
||||
return args[0];
|
||||
} else if (MP_OBJ_IS_STR_OR_BYTES(args[0])) {
|
||||
// a string, parse it
|
||||
mp_uint_t l;
|
||||
size_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_integer(s, l, 0, NULL);
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
@ -72,7 +72,7 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
|
||||
default: {
|
||||
// should be a string, parse it
|
||||
// TODO proper error checking of argument types
|
||||
mp_uint_t l;
|
||||
size_t l;
|
||||
const char *s = mp_obj_str_get_data(args[0], &l);
|
||||
return mp_parse_num_integer(s, l, mp_obj_get_int(args[1]), NULL);
|
||||
}
|
||||
@ -80,7 +80,14 @@ STATIC mp_obj_t mp_obj_int_make_new(const mp_obj_type_t *type_in, size_t n_args,
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
|
||||
|
||||
typedef enum {
|
||||
MP_FP_CLASS_FIT_SMALLINT,
|
||||
MP_FP_CLASS_FIT_LONGINT,
|
||||
MP_FP_CLASS_OVERFLOW
|
||||
} mp_fp_as_int_class_t;
|
||||
|
||||
STATIC mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
|
||||
union {
|
||||
mp_float_t f;
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
|
||||
@ -103,7 +110,12 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
|
||||
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
|
||||
e |= u.i[MP_ENDIANNESS_BIG] != 0;
|
||||
#endif
|
||||
e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
|
||||
if ((e & ~(1 << MP_FLOAT_SIGN_SHIFT_I32)) == 0) {
|
||||
// handle case of -0 (when sign is set but rest of bits are zero)
|
||||
e = 0;
|
||||
} else {
|
||||
e += ((1 << MP_FLOAT_EXP_BITS) - 1) << MP_FLOAT_EXP_SHIFT_I32;
|
||||
}
|
||||
} else {
|
||||
e &= ~((1 << MP_FLOAT_EXP_SHIFT_I32) - 1);
|
||||
}
|
||||
@ -125,6 +137,35 @@ mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val) {
|
||||
}
|
||||
#undef MP_FLOAT_SIGN_SHIFT_I32
|
||||
#undef MP_FLOAT_EXP_SHIFT_I32
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
|
||||
int cl = fpclassify(val);
|
||||
if (cl == FP_INFINITE) {
|
||||
nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "can't convert inf to int"));
|
||||
} else if (cl == FP_NAN) {
|
||||
mp_raise_ValueError("can't convert NaN to int");
|
||||
} else {
|
||||
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
|
||||
if (icl == MP_FP_CLASS_FIT_SMALLINT) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_MPZ
|
||||
} else {
|
||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
||||
mpz_set_from_float(&o->mpz, val);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
#else
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
} else if (icl == MP_FP_CLASS_FIT_LONGINT) {
|
||||
return mp_obj_new_int_from_ll((long long)val);
|
||||
#endif
|
||||
} else {
|
||||
mp_raise_ValueError("float too big");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
|
||||
@ -318,24 +359,6 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
|
||||
int cl = fpclassify(val);
|
||||
if (cl == FP_INFINITE) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
|
||||
} else if (cl == FP_NAN) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
|
||||
} else {
|
||||
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
|
||||
if (icl == MP_FP_CLASS_FIT_SMALLINT) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_obj_new_int(mp_int_t value) {
|
||||
if (MP_SMALL_INT_FITS(value)) {
|
||||
return MP_OBJ_NEW_SMALL_INT(value);
|
||||
|
11
py/objint.h
11
py/objint.h
@ -41,18 +41,13 @@ typedef struct _mp_obj_int_t {
|
||||
extern const mp_obj_int_t mp_maxsize_obj;
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
typedef enum {
|
||||
MP_FP_CLASS_FIT_SMALLINT,
|
||||
MP_FP_CLASS_FIT_LONGINT,
|
||||
MP_FP_CLASS_OVERFLOW
|
||||
} mp_fp_as_int_class_t;
|
||||
|
||||
mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val);
|
||||
mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in);
|
||||
#endif // MICROPY_PY_BUILTINS_FLOAT
|
||||
#endif
|
||||
|
||||
size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma);
|
||||
|
||||
mp_obj_int_t *mp_obj_int_new_mpz(void);
|
||||
|
||||
void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
|
||||
char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
|
||||
int base, const char *prefix, char base_char, char comma);
|
||||
|
@ -263,26 +263,6 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
|
||||
return o;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
|
||||
int cl = fpclassify(val);
|
||||
if (cl == FP_INFINITE) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
|
||||
} else if (cl == FP_NAN) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
|
||||
} else {
|
||||
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
|
||||
if (icl == MP_FP_CLASS_FIT_SMALLINT) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
|
||||
} else if (icl == MP_FP_CLASS_FIT_LONGINT) {
|
||||
return mp_obj_new_int_from_ll((long long)val);
|
||||
} else {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
||||
// TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
|
||||
// TODO check overflow
|
||||
|
@ -74,7 +74,7 @@ const mp_obj_int_t mp_maxsize_obj = {
|
||||
#undef NUM_DIG
|
||||
#endif
|
||||
|
||||
STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
|
||||
mp_obj_int_t *mp_obj_int_new_mpz(void) {
|
||||
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
|
||||
o->base.type = &mp_type_int;
|
||||
mpz_init_zero(&o->mpz);
|
||||
@ -277,7 +277,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) {
|
||||
case MP_BINARY_OP_INPLACE_RSHIFT: {
|
||||
mp_int_t irhs = mp_obj_int_get_checked(rhs_in);
|
||||
if (irhs < 0) {
|
||||
mp_raise_msg(&mp_type_ValueError, "negative shift count");
|
||||
mp_raise_ValueError("negative shift count");
|
||||
}
|
||||
if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) {
|
||||
mpz_shl_inpl(&res->mpz, zlhs, irhs);
|
||||
@ -387,26 +387,6 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
|
||||
return mp_obj_new_int_from_ull(value);
|
||||
}
|
||||
|
||||
#if MICROPY_PY_BUILTINS_FLOAT
|
||||
mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
|
||||
int cl = fpclassify(val);
|
||||
if (cl == FP_INFINITE) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
|
||||
} else if (cl == FP_NAN) {
|
||||
nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
|
||||
} else {
|
||||
mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
|
||||
if (icl == MP_FP_CLASS_FIT_SMALLINT) {
|
||||
return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
|
||||
} else {
|
||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
||||
mpz_set_from_float(&o->mpz, val);
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
|
||||
mp_obj_int_t *o = mp_obj_int_new_mpz();
|
||||
size_t n = mpz_set_from_str(&o->mpz, *str, len, neg, base);
|
||||
|
10
py/objlist.c
10
py/objlist.c
@ -186,13 +186,13 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
return MP_OBJ_FROM_PTR(res);
|
||||
}
|
||||
#endif
|
||||
mp_uint_t index_val = mp_get_index(self->base.type, self->len, index, false);
|
||||
size_t index_val = mp_get_index(self->base.type, self->len, index, false);
|
||||
return self->items[index_val];
|
||||
} else {
|
||||
#if MICROPY_PY_BUILTINS_SLICE
|
||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_uint_t value_len; mp_obj_t *value_items;
|
||||
size_t value_len; mp_obj_t *value_items;
|
||||
mp_obj_get_array(value, &value_len, &value_items);
|
||||
mp_bound_slice_t slice_out;
|
||||
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
|
||||
@ -268,7 +268,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) {
|
||||
if (self->len == 0) {
|
||||
mp_raise_msg(&mp_type_IndexError, "pop from empty list");
|
||||
}
|
||||
mp_uint_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
|
||||
size_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false);
|
||||
mp_obj_t ret = self->items[index];
|
||||
self->len -= 1;
|
||||
memmove(self->items + index, self->items + index + 1, (self->len - index) * sizeof(mp_obj_t));
|
||||
@ -475,7 +475,7 @@ mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items) {
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
void mp_obj_list_get(mp_obj_t self_in, mp_uint_t *len, mp_obj_t **items) {
|
||||
void mp_obj_list_get(mp_obj_t self_in, size_t *len, mp_obj_t **items) {
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
*len = self->len;
|
||||
*items = self->items;
|
||||
@ -490,7 +490,7 @@ void mp_obj_list_set_len(mp_obj_t self_in, size_t len) {
|
||||
|
||||
void mp_obj_list_store(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||
mp_uint_t i = mp_get_index(self->base.type, self->len, index, false);
|
||||
size_t i = mp_get_index(self->base.type, self->len, index, false);
|
||||
self->items[i] = value;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user