From 7df4558df8cac13e09b4edf81a8dc6a2522df89e Mon Sep 17 00:00:00 2001
From: Damien George
Date: Mon, 3 Apr 2017 16:10:46 +1000
Subject: [PATCH 001/826] esp8266: Remove unused entry in port root pointers.
---
esp8266/mpconfigport.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h
index d40eaba91..b25bb8bb4 100644
--- a/esp8266/mpconfigport.h
+++ b/esp8266/mpconfigport.h
@@ -180,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()
From 831e15722674905b3cd895fee8481cd86a4849f8 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 3 Apr 2017 10:20:41 +0300
Subject: [PATCH 002/826] tests/run-tests: Introduce generic "minimal" target.
Used e.g. by Zephyr port.
---
tests/run-tests | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/tests/run-tests b/tests/run-tests
index 773f3dc39..177c9a5c8 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -290,6 +290,9 @@ def run_tests(pyb, tests, args):
skip_tests.add('float/bytes_construct.py') # requires fp32
skip_tests.add('float/bytearray_construct.py') # requires fp32
skip_tests.add('misc/rge_sm.py') # too large
+ elif args.target == 'minimal':
+ skip_tests.add('misc/rge_sm.py') # too large
+ skip_tests.add('micropython/opt_level.py') # don't assume line numbers are stored
# Some tests are known to fail on 64-bit machines
if pyb is None and platform.architecture()[0] == '64bit':
@@ -429,7 +432,7 @@ def main():
cmd_parser.add_argument('files', nargs='*', help='input test files')
args = cmd_parser.parse_args()
- EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266')
+ EXTERNAL_TARGETS = ('pyboard', 'wipy', 'esp8266', 'minimal')
if args.target in EXTERNAL_TARGETS:
import pyboard
pyb = pyboard.Pyboard(args.device, args.baudrate, args.user, args.password)
@@ -444,7 +447,7 @@ def main():
if args.target == 'pyboard':
# run pyboard tests
test_dirs = ('basics', 'micropython', 'float', 'misc', 'stress', 'extmod', 'pyb', 'pybnative', 'inlineasm')
- elif args.target == 'esp8266':
+ elif args.target in ('esp8266', 'minimal'):
test_dirs = ('basics', 'micropython', 'float', 'misc', 'extmod')
elif args.target == 'wipy':
# run WiPy tests
From 4c392243ae947545553904d6436e7db462207446 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 3 Apr 2017 12:07:56 +0300
Subject: [PATCH 003/826] zephyr/prj_base.conf: Add config for net_buf logging.
Disabled by default.
---
zephyr/prj_base.conf | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/zephyr/prj_base.conf b/zephyr/prj_base.conf
index 9a12241bc..fc51ccec6 100644
--- a/zephyr/prj_base.conf
+++ b/zephyr/prj_base.conf
@@ -15,3 +15,9 @@ CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_NBUF_RX_COUNT=5
+
+# Uncomment to enable "INFO" level net_buf logging
+#CONFIG_NET_LOG=y
+#CONFIG_NET_DEBUG_NET_BUF=y
+# Change to 4 for "DEBUG" level
+#CONFIG_SYS_LOG_NET_LEVEL=3
From bb296482c385d51f1eb8041e18beb5aa9668637c Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 4 Apr 2017 00:29:23 +0300
Subject: [PATCH 004/826] docs/library/btree: Add btree module docs.
---
docs/library/btree.rst | 144 +++++++++++++++++++++++++++++++++++++++++
docs/library/index.rst | 1 +
2 files changed, 145 insertions(+)
create mode 100644 docs/library/btree.rst
diff --git a/docs/library/btree.rst b/docs/library/btree.rst
new file mode 100644
index 000000000..aebcbc160
--- /dev/null
+++ b/docs/library/btree.rst
@@ -0,0 +1,144 @@
+:mod:`btree` -- simple BTree database
+=====================================
+
+.. module:: btree
+ :synopsis: simple BTree database
+
+The ``btree`` module implements a simple key-value database using external
+storage (disk files, or in general case, a random-access stream). Keys are
+stored sorted in the database, and besides efficient retrieval by a key
+value, a database also supports efficient ordered range scans (retrieval
+of values with the keys in a given range). On the application interface
+side, BTree database work as close a possible to a way standard `dict`
+type works, one notable difference is that both keys and values must
+be `bytes` objects (so, if you want to store objects of other types, you
+need to serialize them to `bytes` first).
+
+The module is based on the well-known BerkelyDB library, version 1.xx.
+
+Example::
+
+ import btree
+
+ # First, we need to open a stream which holds a database
+ # This is usually a file, but can be in-memory database
+ # using uio.BytesIO, a raw flash section, etc.
+ f = open("mydb", "w+b")
+
+ # Now open a database itself
+ db = btree.open(f)
+
+ # The keys you add will be sorted internally in the database
+ db[b"3"] = b"three"
+ db[b"1"] = b"one"
+ db[b"2"] = b"two"
+
+ # Prints b'two'
+ print(db[b"2"])
+
+ # Iterate over sorted keys in the database, starting from b"2"
+ # until the end of the database, returning only values.
+ # Mind that arguments passed to values() method are *key* values.
+ # Prints:
+ # b'two'
+ # b'three'
+ for word in db.values(b"2"):
+ print(word)
+
+ del db[b"2"]
+
+ # No longer true, prints False
+ print(b"2" in db)
+
+ # Prints:
+ # b"1"
+ # b"3"
+ for key in db:
+ print(key)
+
+ db.close()
+
+ # Don't forget to close the underlying stream!
+ f.close()
+
+
+Functions
+---------
+
+.. function:: open(stream, \*, flags=0, cachesize=0, pagesize=0, minkeypage=0)
+
+ Open a database from a random-access `stream` (like an open file). All
+ other parameters are optional and keyword-only, and allow to tweak advanced
+ paramters of the database operation (most users will not need them):
+
+ * `flags` - Currently unused.
+ * `cachesize` - Suggested maximum memory cache size in bytes. For a
+ board with enough memory using larger values may improve performance.
+ The value is only a recommendation, the module may use more memory if
+ values set too low.
+ * `pagesize` - Page size used for the nodes in BTree. Acceptable range
+ is 512-65536. If 0, underlying I/O block size will be used (the best
+ compromise between memory usage and performance).
+ * `minkeypage` - Minimum number of keys to store per page. Default value
+ of 0 equivalent to 2.
+
+ Returns a `BTree` object, which implements a dictionary protocol (set
+ of methods), and some additional methods described below.
+
+Methods
+-------
+
+.. method:: btree.close()
+
+ Close the database. It's mandatory to close the database at the end of
+ processing, as some unwritten data may be still in the cache. Note that
+ this does not close underlying streamw with which the database was opened,
+ it should be closed separately (which is also mandatory to make sure that
+ data flushed from buffer to the underlying storage).
+
+.. method:: btree.flush()
+
+ Flush any data in cache to the underlying stream.
+
+.. method:: btree.__getitem__(key)
+.. method:: btree.get(key, default=None)
+.. method:: btree.__setitem__(key, val)
+.. method:: btree.__detitem__(key)
+.. method:: btree.__contains__(key)
+
+ Standard dictionary methods.
+
+.. method:: btree.__iter__()
+
+ A BTree object can be iterated over directly (similar to a dictionary)
+ to get access to all keys in order.
+
+.. method:: btree.keys([start_key, [end_key, [flags]]])
+.. method:: btree.values([start_key, [end_key, [flags]]])
+.. method:: btree.items([start_key, [end_key, [flags]]])
+
+ These methods are similar to standard dictionary methods, but also can
+ take optional parameters to iterate over a key sub-range, instead of
+ the entire database. Note that for all 3 methods, `start_key` and
+ `end_key` arguments represent key values. For example, ``values()``
+ method will iterate over values corresponding to they key range
+ given. None values for `start_key` means "from the first key", no
+ `end_key` or its value of None means "until the end of database".
+ By default, range is inclusive of `start_key` and exclusive of
+ `end_key`, you can include `end_key` in iteration by passing `flags`
+ of `btree.INCL`. You can iterate in descending key direction
+ by passing `flags` of `btree.DESC`. The flags values can be ORed
+ together.
+
+Constants
+---------
+
+.. data:: INCL
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be inclusive of the end key.
+
+.. data:: DESC
+
+ A flag for `keys()`, `values()`, `items()` methods to specify that
+ scanning should be in descending direction of keys.
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 5d64d01f7..1a61f6882 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -153,6 +153,7 @@ the following libraries.
.. toctree::
:maxdepth: 1
+ btree.rst
framebuf.rst
machine.rst
micropython.rst
From 19f2e47d59b539f94a49137c379c88f0aed53cf1 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 11:57:21 +1000
Subject: [PATCH 005/826] py: Add very simple but correct hashing for float and
complex numbers.
Hashing of float and complex numbers that are exact (real) integers should
return the same integer hash value as hashing the corresponding integer
value. Eg hash(1), hash(1.0) and hash(1+0j) should all be the same (this
is how Python is specified: if x==y then hash(x)==hash(y)).
This patch implements the simplest way of doing float/complex hashing by
just converting the value to int and returning that value.
---
py/obj.h | 1 +
py/objcomplex.c | 1 +
py/objfloat.c | 1 +
3 files changed, 3 insertions(+)
diff --git a/py/obj.h b/py/obj.h
index b19aca29a..49ba645f7 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -718,6 +718,7 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t s
#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
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 8118fb813..7ec47edb5 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -117,6 +117,7 @@ STATIC mp_obj_t complex_unary_op(mp_uint_t op, mp_obj_t o_in) {
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
switch (op) {
case MP_UNARY_OP_BOOL: return mp_obj_new_bool(o->real != 0 || o->imag != 0);
+ case MP_UNARY_OP_HASH: return MP_OBJ_NEW_SMALL_INT(mp_float_hash(o->real) ^ mp_float_hash(o->imag));
case MP_UNARY_OP_POSITIVE: return o_in;
case MP_UNARY_OP_NEGATIVE: return mp_obj_new_complex(-o->real, -o->imag);
default: return MP_OBJ_NULL; // op not supported
diff --git a/py/objfloat.c b/py/objfloat.c
index 6d80d6c0e..2c355d355 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -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
From 677fb3101525bc655d9fd548b8c2cecfc8deefd2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 12:14:34 +1000
Subject: [PATCH 006/826] tests/float: Add tests for hashing float and complex
numbers.
---
tests/float/builtin_float_hash.py | 22 ++++++++++++++++++++++
tests/float/complex1.py | 4 ++++
2 files changed, 26 insertions(+)
create mode 100644 tests/float/builtin_float_hash.py
diff --git a/tests/float/builtin_float_hash.py b/tests/float/builtin_float_hash.py
new file mode 100644
index 000000000..ba6b63907
--- /dev/null
+++ b/tests/float/builtin_float_hash.py
@@ -0,0 +1,22 @@
+# test builtin hash function with float args
+
+# these should hash to an integer with a specific value
+for val in (
+ '0.0',
+ '1.0',
+ '2.0',
+ '-12.0',
+ '12345.0',
+ ):
+ print(val, hash(float(val)))
+
+# just check that these values are hashable
+for val in (
+ '0.1',
+ '-0.1',
+ '10.3',
+ 'inf',
+ '-inf',
+ 'nan',
+ ):
+ print(val, type(hash(float(val))))
diff --git a/tests/float/complex1.py b/tests/float/complex1.py
index 8c8d285e1..a6038de04 100644
--- a/tests/float/complex1.py
+++ b/tests/float/complex1.py
@@ -41,6 +41,10 @@
print(abs(1j))
print("%.5g" % abs(1j + 2))
+# builtin hash
+print(hash(1 + 0j))
+print(type(hash(1j)))
+
# float on lhs should delegate to complex
print(1.2 + 3j)
From 805b1c8bc3424003a86c9ad270661ef31a8f6f56 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 12:26:43 +1000
Subject: [PATCH 007/826] tests/run-tests: Update names of tests that may need
skipping.
---
tests/run-tests | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tests/run-tests b/tests/run-tests
index 177c9a5c8..87d12ba36 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -249,6 +249,7 @@ def run_tests(pyb, tests, args):
if not has_complex:
skip_tests.add('float/complex1.py')
+ skip_tests.add('float/complex1_intbig.py')
skip_tests.add('float/int_big_float.py')
skip_tests.add('float/true_value.py')
skip_tests.add('float/types.py')
@@ -285,7 +286,7 @@ def run_tests(pyb, tests, args):
skip_tests.add('extmod/urandom_basic.py') # requires urandom
skip_tests.add('extmod/urandom_extra.py') # requires urandom
elif args.target == 'esp8266':
- skip_tests.add('float/float2int.py') # requires at least fp32, there's float2int_fp30.py instead
+ skip_tests.add('float/float2int_intbig.py') # requires at least fp32, there's float2int_fp30_intbig.py instead
skip_tests.add('float/string_format.py') # requires at least fp32, there's string_format_fp30.py instead
skip_tests.add('float/bytes_construct.py') # requires fp32
skip_tests.add('float/bytearray_construct.py') # requires fp32
From 6e99a8c94e1c217f33e7116d60817ba1028d395e Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 4 Apr 2017 06:19:23 +0300
Subject: [PATCH 008/826] zephyr/modusocket: Be sure to use MP_OBJ_FROM_PTR.
---
zephyr/modusocket.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 45991d42e..025cb0c92 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -172,7 +172,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
RAISE_ERRNO(net_context_get(family, socktype, proto, &socket->ctx));
- return socket;
+ return MP_OBJ_FROM_PTR(socket);
}
STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
From 2908c3ca4168f963958e4a97e54800667ff34ccf Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 4 Apr 2017 06:28:14 +0300
Subject: [PATCH 009/826] zephyr/modusocket: Factor out socket_new() function.
It will be reused e.g. for accept() implementation.
---
zephyr/modusocket.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 025cb0c92..155ed69b8 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -128,6 +128,15 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
k_fifo_put(&socket->recv_q, net_buf);
}
+socket_obj_t *socket_new(void) {
+ socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
+ socket->base.type = (mp_obj_t)&socket_type;
+ k_fifo_init(&socket->recv_q);
+ socket->cur_buf = NULL;
+ socket->state = STATE_NEW;
+ return socket;
+}
+
// Methods
STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -143,11 +152,7 @@ STATIC void socket_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 4, false);
- socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
- socket->base.type = type;
- k_fifo_init(&socket->recv_q);
- socket->cur_buf = NULL;
- socket->state = STATE_NEW;
+ socket_obj_t *socket = socket_new();
int family = AF_INET;
int socktype = SOCK_STREAM;
From 9a8e7f7a8e93e9319d2ff5795f4b8a6b9e4ba5ad Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 15:18:58 +1000
Subject: [PATCH 010/826] stmhal/usbd_cdc_interface: Increase in-endpoint
timeout to 500ms.
The previous timeout value of 150ms could lead to data being lost (ie never
received by the host) in some rare cases, eg when the host is under load.
A value of 500ms is quite conservative and allows the host plenty of time
to read our data.
---
stmhal/usbd_cdc_interface.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index 1c12cdc1c..647fe09e9 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -261,8 +261,10 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
if (UserTxBufPtrOut != UserTxBufPtrOutShadow) {
// We have sent data and are waiting for the low-level USB driver to
// finish sending it over the USB in-endpoint.
- // SOF occurs every 1ms, so we have a 150 * 1ms = 150ms timeout
- if (UserTxBufPtrWaitCount < 150) {
+ // SOF occurs every 1ms, so we have a 500 * 1ms = 500ms timeout
+ // We have a relatively large timeout because the USB host may be busy
+ // doing other things and we must give it a chance to read our data.
+ if (UserTxBufPtrWaitCount < 500) {
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
if (USBx_INEP(CDC_IN_EP & 0x7f)->DIEPTSIZ & USB_OTG_DIEPTSIZ_XFRSIZ) {
// USB in-endpoint is still reading the data
From 3b447ede78970df04e08eeb1cc549a574a733667 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 16:23:25 +1000
Subject: [PATCH 011/826] stmhal/usbd_cdc_interface: Change CDC RX to use a
circular buffer.
This should be a little more efficient (since we anyway scan the input
packet for the interrupt char), and it should also fix any non-atomic read
issues with the buffer state being changed during an interrupt.
Throughput tests show that RX rate is unchanged by this patch.
---
stmhal/usbd_cdc_interface.c | 85 +++++++++++++------------------------
1 file changed, 30 insertions(+), 55 deletions(-)
diff --git a/stmhal/usbd_cdc_interface.c b/stmhal/usbd_cdc_interface.c
index 647fe09e9..941025515 100644
--- a/stmhal/usbd_cdc_interface.c
+++ b/stmhal/usbd_cdc_interface.c
@@ -61,7 +61,7 @@
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
-#define APP_RX_DATA_SIZE 1024 // I think this must be at least CDC_DATA_FS_OUT_PACKET_SIZE=64 (APP_RX_DATA_SIZE was 2048)
+#define APP_RX_DATA_SIZE 1024 // this must be 2 or greater, and a power of 2
#define APP_TX_DATA_SIZE 1024 // I think this can be any value (was 2048)
/* Private macro -------------------------------------------------------------*/
@@ -69,9 +69,10 @@
static __IO uint8_t dev_is_connected = 0; // indicates if we are connected
-static uint8_t UserRxBuffer[APP_RX_DATA_SIZE]; // received data from USB OUT endpoint is stored in this buffer
-static uint16_t UserRxBufCur = 0; // points to next available character in UserRxBuffer
-static uint16_t UserRxBufLen = 0; // counts number of valid characters in UserRxBuffer
+static uint8_t cdc_rx_packet_buf[CDC_DATA_FS_MAX_PACKET_SIZE]; // received data from USB OUT endpoint is stored in this buffer
+static uint8_t cdc_rx_user_buf[APP_RX_DATA_SIZE]; // received data is buffered here until the user reads it
+static volatile uint16_t cdc_rx_buf_put = 0; // circular buffer index
+static uint16_t cdc_rx_buf_get = 0; // circular buffer index
static uint8_t UserTxBuffer[APP_TX_DATA_SIZE]; // data for USB IN endpoind is stored in this buffer
static uint16_t UserTxBufPtrIn = 0; // increment this pointer modulo APP_TX_DATA_SIZE when new data is available
@@ -141,10 +142,10 @@ static int8_t CDC_Itf_Init(void)
/*##-5- Set Application Buffers ############################################*/
USBD_CDC_SetTxBuffer(&hUSBDDevice, UserTxBuffer, 0);
- USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer);
+ USBD_CDC_SetRxBuffer(&hUSBDDevice, cdc_rx_packet_buf);
- UserRxBufCur = 0;
- UserRxBufLen = 0;
+ cdc_rx_buf_put = 0;
+ cdc_rx_buf_get = 0;
return (USBD_OK);
}
@@ -313,7 +314,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) {
* @param Buf: Buffer of data received
* @param Len: Number of data received (in bytes)
* @retval Result of the opeartion: USBD_OK if all operations are OK else USBD_FAIL
- * @note The buffer we are passed here is just UserRxBuffer, so we are
+ * @note The buffer we are passed here is just cdc_rx_packet_buf, so we are
* free to modify it.
*/
static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
@@ -322,54 +323,23 @@ static int8_t CDC_Itf_Receive(uint8_t* Buf, uint32_t *Len) {
HAL_UART_Transmit_DMA(&UartHandle, Buf, *Len);
#endif
- // TODO improve this function to implement a circular buffer
-
- // if we have processed all the characters, reset the buffer counters
- if (UserRxBufCur > 0 && UserRxBufCur >= UserRxBufLen) {
- memmove(UserRxBuffer, UserRxBuffer + UserRxBufLen, *Len);
- UserRxBufCur = 0;
- UserRxBufLen = 0;
- }
-
- uint32_t delta_len;
-
- if (mp_interrupt_char == -1) {
- // no special interrupt character
- delta_len = *Len;
-
- } else {
- // filter out special interrupt character from the buffer
- bool char_found = false;
- uint8_t *dest = Buf;
- uint8_t *src = Buf;
- uint8_t *buf_top = Buf + *Len;
- for (; src < buf_top; src++) {
- if (*src == mp_interrupt_char) {
- char_found = true;
- // raise KeyboardInterrupt when interrupts are finished
- pendsv_kbd_intr();
- } else {
- if (char_found) {
- *dest = *src;
- }
- dest++;
+ // copy the incoming data into the circular buffer
+ for (uint8_t *src = Buf, *top = Buf + *Len; src < top; ++src) {
+ if (mp_interrupt_char != -1 && *src == mp_interrupt_char) {
+ pendsv_kbd_intr();
+ } else {
+ uint16_t next_put = (cdc_rx_buf_put + 1) & (APP_RX_DATA_SIZE - 1);
+ if (next_put == cdc_rx_buf_get) {
+ // overflow, we just discard the rest of the chars
+ break;
}
+ cdc_rx_user_buf[cdc_rx_buf_put] = *src;
+ cdc_rx_buf_put = next_put;
}
-
- // length of remaining characters
- delta_len = dest - Buf;
- }
-
- if (UserRxBufLen + delta_len + CDC_DATA_FS_MAX_PACKET_SIZE > APP_RX_DATA_SIZE) {
- // if we keep this data then the buffer can overflow on the next USB rx
- // so we don't increment the length, and throw this data away
- } else {
- // data fits, leaving room for another CDC_DATA_FS_OUT_PACKET_SIZE
- UserRxBufLen += delta_len;
}
- // initiate next USB packet transfer, to append to existing data in buffer
- USBD_CDC_SetRxBuffer(&hUSBDDevice, UserRxBuffer + UserRxBufLen);
+ // initiate next USB packet transfer
+ USBD_CDC_SetRxBuffer(&hUSBDDevice, cdc_rx_packet_buf);
USBD_CDC_ReceivePacket(&hUSBDDevice);
return USBD_OK;
@@ -463,7 +433,11 @@ void USBD_CDC_TxAlways(const uint8_t *buf, uint32_t len) {
// Returns number of bytes in the rx buffer.
int USBD_CDC_RxNum(void) {
- return UserRxBufLen - UserRxBufCur;
+ int32_t rx_waiting = (int32_t)cdc_rx_buf_put - (int32_t)cdc_rx_buf_get;
+ if (rx_waiting < 0) {
+ rx_waiting += APP_RX_DATA_SIZE;
+ }
+ return rx_waiting;
}
// timout in milliseconds.
@@ -473,7 +447,7 @@ int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) {
for (uint32_t i = 0; i < len; i++) {
// Wait until we have at least 1 byte to read
uint32_t start = HAL_GetTick();
- while (UserRxBufLen == UserRxBufCur) {
+ while (cdc_rx_buf_put == cdc_rx_buf_get) {
// Wraparound of tick is taken care of by 2's complement arithmetic.
if (HAL_GetTick() - start >= timeout) {
// timeout
@@ -487,7 +461,8 @@ int USBD_CDC_Rx(uint8_t *buf, uint32_t len, uint32_t timeout) {
}
// Copy byte from device to user buffer
- buf[i] = UserRxBuffer[UserRxBufCur++];
+ buf[i] = cdc_rx_user_buf[cdc_rx_buf_get];
+ cdc_rx_buf_get = (cdc_rx_buf_get + 1) & (APP_RX_DATA_SIZE - 1);
}
// Success, return number of bytes read
From fc245d1ca4367f9876ac32c7e08e169da7db79b9 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 4 Apr 2017 16:45:49 +1000
Subject: [PATCH 012/826] py/objint: Consolidate mp_obj_new_int_from_float to
one implementation.
This reduces code duplication and allows to make mp_classify_fp_as_int
static, which reduces code size.
---
py/objint.c | 56 +++++++++++++++++++++++++++++---------------
py/objint.h | 11 +++------
py/objint_longlong.c | 20 ----------------
py/objint_mpz.c | 22 +----------------
4 files changed, 41 insertions(+), 68 deletions(-)
diff --git a/py/objint.c b/py/objint.c
index 2e8fe4f22..46f9b1666 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -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
@@ -130,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
@@ -323,24 +359,6 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) {
return mp_const_none;
}
-#if MICROPY_PY_BUILTINS_FLOAT
-mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- int cl = fpclassify(val);
- if (cl == FP_INFINITE) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
- } else if (cl == FP_NAN) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else {
- mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
- if (icl == MP_FP_CLASS_FIT_SMALLINT) {
- return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
- } else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
- }
- }
-}
-#endif
-
mp_obj_t mp_obj_new_int(mp_int_t value) {
if (MP_SMALL_INT_FITS(value)) {
return MP_OBJ_NEW_SMALL_INT(value);
diff --git a/py/objint.h b/py/objint.h
index 7205761ad..da56c1862 100644
--- a/py/objint.h
+++ b/py/objint.h
@@ -41,18 +41,13 @@ typedef struct _mp_obj_int_t {
extern const mp_obj_int_t mp_maxsize_obj;
#if MICROPY_PY_BUILTINS_FLOAT
-typedef enum {
- MP_FP_CLASS_FIT_SMALLINT,
- MP_FP_CLASS_FIT_LONGINT,
- MP_FP_CLASS_OVERFLOW
-} mp_fp_as_int_class_t;
-
-mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val);
mp_float_t mp_obj_int_as_float_impl(mp_obj_t self_in);
-#endif // MICROPY_PY_BUILTINS_FLOAT
+#endif
size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma);
+mp_obj_int_t *mp_obj_int_new_mpz(void);
+
void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind);
char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in,
int base, const char *prefix, char base_char, char comma);
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 4ab49f337..540cfebd0 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -263,26 +263,6 @@ mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) {
return o;
}
-#if MICROPY_PY_BUILTINS_FLOAT
-mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
- int cl = fpclassify(val);
- if (cl == FP_INFINITE) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OverflowError, "can't convert inf to int"));
- } else if (cl == FP_NAN) {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "can't convert NaN to int"));
- } else {
- mp_fp_as_int_class_t icl = mp_classify_fp_as_int(val);
- if (icl == MP_FP_CLASS_FIT_SMALLINT) {
- return MP_OBJ_NEW_SMALL_INT((mp_int_t)val);
- } else if (icl == MP_FP_CLASS_FIT_LONGINT) {
- return mp_obj_new_int_from_ll((long long)val);
- } else {
- nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "float too big"));
- }
- }
-}
-#endif
-
mp_obj_t mp_obj_new_int_from_str_len(const char **str, size_t len, bool neg, unsigned int base) {
// TODO this does not honor the given length of the string, but it all cases it should anyway be null terminated
// TODO check overflow
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index ca989e8ad..2353bd8d6 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -74,7 +74,7 @@ const mp_obj_int_t mp_maxsize_obj = {
#undef NUM_DIG
#endif
-STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) {
+mp_obj_int_t *mp_obj_int_new_mpz(void) {
mp_obj_int_t *o = m_new_obj(mp_obj_int_t);
o->base.type = &mp_type_int;
mpz_init_zero(&o->mpz);
@@ -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);
From 468c6f9da147d6e752e437a32211e317a116b6df Mon Sep 17 00:00:00 2001
From: Peter Hinch
Date: Sat, 1 Apr 2017 07:00:09 +0100
Subject: [PATCH 013/826] extmod/modframebuf: Make monochrome bitmap formats
start with MONO_.
MONO_xxx is much easier to read if you're not familiar with the code.
MVLSB is deprecated but kept for backwards compatibility, for the time
being.
This patch also updates the associated docs and tests.
---
docs/library/framebuf.rst | 25 ++++++++++++++++++++++++-
extmod/modframebuf.c | 5 +++--
tests/extmod/framebuf1.py | 7 ++++---
tests/extmod/framebuf1.py.exp | 7 ++++---
4 files changed, 35 insertions(+), 9 deletions(-)
diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst
index 91fc362fd..61f0635f3 100644
--- a/docs/library/framebuf.rst
+++ b/docs/library/framebuf.rst
@@ -116,9 +116,32 @@ Other methods
Constants
---------
-.. data:: framebuf.MVLSB
+.. data:: framebuf.MONO_VLSB
Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are vertically mapped with
+ bit 0 being nearest the top of the screen. Consequently each byte occupies
+ 8 vertical pixels. Subsequent bytes appear at successive horizontal
+ locations until the rightmost edge is reached. Further bytes are rendered
+ at locations starting at the leftmost edge, 8 pixels lower.
+
+.. data:: framebuf.MONO_HLSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 0 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
+
+.. data:: framebuf.MONO_HMSB
+
+ Monochrome (1-bit) color format
+ This defines a mapping where the bits in a byte are horizontally mapped.
+ Each byte occupies 8 horizontal pixels with bit 7 being the leftmost.
+ Subsequent bytes appear at successive horizontal locations until the
+ rightmost edge is reached. Further bytes are rendered on the next row, one
+ pixel lower.
.. data:: framebuf.RGB565
diff --git a/extmod/modframebuf.c b/extmod/modframebuf.c
index 33985dd00..b8e84fe1c 100644
--- a/extmod/modframebuf.c
+++ b/extmod/modframebuf.c
@@ -579,10 +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_MHLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB) },
- { MP_ROM_QSTR(MP_QSTR_MHMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB) },
+ { MP_ROM_QSTR(MP_QSTR_MONO_HLSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHLSB) },
+ { MP_ROM_QSTR(MP_QSTR_MONO_HMSB), MP_OBJ_NEW_SMALL_INT(FRAMEBUF_MHMSB) },
};
STATIC MP_DEFINE_CONST_DICT(framebuf_module_globals, framebuf_module_globals_table);
diff --git a/tests/extmod/framebuf1.py b/tests/extmod/framebuf1.py
index 0a8e1ae55..990b0b120 100644
--- a/tests/extmod/framebuf1.py
+++ b/tests/extmod/framebuf1.py
@@ -9,9 +9,9 @@
h = 16
size = w * h // 8
buf = bytearray(size)
-maps = {framebuf.MVLSB : 'MVLSB',
- framebuf.MHLSB : 'MHLSB',
- framebuf.MHMSB : 'MHMSB'}
+maps = {framebuf.MONO_VLSB : 'MONO_VLSB',
+ framebuf.MONO_HLSB : 'MONO_HLSB',
+ framebuf.MONO_HMSB : 'MONO_HMSB'}
for mapping in maps.keys():
for x in range(size):
@@ -107,3 +107,4 @@
# test legacy constructor
fbuf = framebuf.FrameBuffer1(buf, w, h)
fbuf = framebuf.FrameBuffer1(buf, w, h, w)
+print(framebuf.MVLSB == framebuf.MONO_VLSB)
diff --git a/tests/extmod/framebuf1.py.exp b/tests/extmod/framebuf1.py.exp
index 736ad7a45..d954623de 100644
--- a/tests/extmod/framebuf1.py.exp
+++ b/tests/extmod/framebuf1.py.exp
@@ -1,4 +1,4 @@
-MVLSB
+MONO_VLSB
0
bytearray(b'\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
@@ -20,7 +20,7 @@ bytearray(b'\x00\x7f\x7f\x04\x04\x00\x00\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\xaaU\xaaU\xaa\x00\x00\x00\x00\x00')
-MHLSB
+MONO_HLSB
0
bytearray(b'\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8\xf8')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
@@ -42,7 +42,7 @@ bytearray(b'``x````\x00\x00\x00')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'P\xa8P\xa8P\xa8P\xa8\x00\x00')
-MHMSB
+MONO_HMSB
0
bytearray(b'\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f')
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
@@ -65,3 +65,4 @@ bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
bytearray(b'\n\x15\n\x15\n\x15\n\x15\x00\x00')
ValueError
+True
From 58168c8e6bcf3619d281a8c877ef20e5efe049d2 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 4 Apr 2017 15:36:03 +0300
Subject: [PATCH 014/826] zephyr/zephyr_getchar: Explicitly yield to other
threads on char availability.
Without this, if there's a large chunk of data coming from hardware (e.g.
clipboard paste, or fed programmatically from the other side of the console),
there's a behavior of initial mass fill-in of the buffer without any
consumption, which starts much later and doesn't catch up with further
filling, leading to buffer overflow.
---
zephyr/src/zephyr_getchar.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/zephyr/src/zephyr_getchar.c b/zephyr/src/zephyr_getchar.c
index 246d86a2e..52b3394d0 100644
--- a/zephyr/src/zephyr_getchar.c
+++ b/zephyr/src/zephyr_getchar.c
@@ -44,6 +44,7 @@ static int console_irq_input_hook(uint8_t ch)
}
//printk("%x\n", ch);
k_sem_give(&uart_sem);
+ k_yield();
return 1;
}
From 647e72ca63a345a5d6de16fe359bbc3b7c6615ec Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 4 Apr 2017 17:46:02 +0300
Subject: [PATCH 015/826] tools/pyboard: Add "exec" and "execpty"
pseudo-devices support.
This allows to execute a command and communicate with its stdin/stdout
via pipes ("exec") or with command-created pseudo-terminal ("execpty"),
to emulate serial access. Immediate usecase is controlling a QEMU process
which emulates board's serial via normal console, but it could be used
e.g. with helper binaries to access real board over other hadware
protocols, etc.
An example of device specification for these cases is:
--device exec:../zephyr/qemu.sh
--device execpty:../zephyr/qemu2.sh
Where qemu.sh contains long-long qemu startup line, or calls another
command. There's a special support in this patch for running the command
in a new terminal session, to support shell wrappers like that (without
new terminal session, only wrapper script would be terminated, but its
child processes would continue to run).
---
tools/pyboard.py | 85 +++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 84 insertions(+), 1 deletion(-)
diff --git a/tools/pyboard.py b/tools/pyboard.py
index f368455f5..131634c90 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -39,6 +39,7 @@
import sys
import time
+import os
try:
stdout = sys.stdout.buffer
@@ -116,9 +117,91 @@ def inWaiting(self):
else:
return n_waiting
+
+class ProcessToSerial:
+ "Execute a process and emulate serial connection using its stdin/stdout."
+
+ def __init__(self, cmd):
+ import subprocess
+ self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=True, preexec_fn=os.setsid,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+
+ # Initially was implemented with selectors, but that adds Python3
+ # dependency. However, there can be race conditions communicating
+ # with a particular child process (like QEMU), and selectors may
+ # still work better in that case, so left inplace for now.
+ #
+ #import selectors
+ #self.sel = selectors.DefaultSelector()
+ #self.sel.register(self.subp.stdout, selectors.EVENT_READ)
+
+ import select
+ self.poll = select.poll()
+ self.poll.register(self.subp.stdout.fileno())
+
+ def close(self):
+ import signal
+ os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM)
+
+ def read(self, size=1):
+ data = b""
+ while len(data) < size:
+ data += self.subp.stdout.read(size - len(data))
+ return data
+
+ def write(self, data):
+ self.subp.stdin.write(data)
+ return len(data)
+
+ def inWaiting(self):
+ #res = self.sel.select(0)
+ res = self.poll.poll(0)
+ if res:
+ return 1
+ return 0
+
+
+class ProcessPtyToTerminal:
+ """Execute a process which creates a PTY and prints slave PTY as
+ first line of its output, and emulate serial connection using
+ this PTY."""
+
+ def __init__(self, cmd):
+ import subprocess
+ import re
+ import serial
+ self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=True, preexec_fn=os.setsid,
+ stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ pty_line = self.subp.stderr.readline().decode("utf-8")
+ m = re.search(r"/dev/pts/[0-9]+", pty_line)
+ if not m:
+ print("Error: unable to find PTY device in startup line:", pty_line)
+ self.close()
+ sys.exit(1)
+ pty = m.group()
+ self.ser = serial.Serial(pty, interCharTimeout=1)
+
+ def close(self):
+ import signal
+ os.killpg(os.getpgid(self.subp.pid), signal.SIGTERM)
+
+ def read(self, size=1):
+ return self.ser.read(size)
+
+ def write(self, data):
+ return self.ser.write(data)
+
+ def inWaiting(self):
+ return self.ser.inWaiting()
+
+
class Pyboard:
def __init__(self, device, baudrate=115200, user='micro', password='python', wait=0):
- if device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3:
+ if device.startswith("exec:"):
+ self.serial = ProcessToSerial(device[len("exec:"):])
+ elif device.startswith("execpty:"):
+ self.serial = ProcessPtyToTerminal(device[len("qemupty:"):])
+ elif device and device[0].isdigit() and device[-1].isdigit() and device.count('.') == 3:
# device looks like an IP address
self.serial = TelnetToSerial(device, user, password, read_timeout=10)
else:
From a9e6f08adb6dbe84ee59e9545895aa9dfc5ade17 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 00:37:35 +0300
Subject: [PATCH 016/826] zephyr/Makefile: Add "test" target, runs testsuite in
QEMU.
---
zephyr/Makefile | 3 +++
1 file changed, 3 insertions(+)
diff --git a/zephyr/Makefile b/zephyr/Makefile
index b78b4be95..057a88862 100644
--- a/zephyr/Makefile
+++ b/zephyr/Makefile
@@ -93,3 +93,6 @@ z_clean:
.PHONY: prj.conf
prj.conf: prj_base.conf
$(PYTHON) makeprj.py prj_base.conf prj_$(BOARD).conf $@
+
+test:
+ cd ../tests && ./run-tests --target minimal --device "execpty:make -C ../zephyr run BOARD=$(BOARD) QEMU_PTY=1"
From 546ef301a12ccd6015137964637983432c64d11f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 00:44:59 +0300
Subject: [PATCH 017/826] tools/pyboard: execpty: Use shell=False to workaround
some curdir issues.
Without this, Zephyr's port "make test" doesn't work.
---
tools/pyboard.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/pyboard.py b/tools/pyboard.py
index 131634c90..b7babdc30 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -170,7 +170,7 @@ def __init__(self, cmd):
import subprocess
import re
import serial
- self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=True, preexec_fn=os.setsid,
+ self.subp = subprocess.Popen(cmd.split(), bufsize=0, shell=False, preexec_fn=os.setsid,
stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
pty_line = self.subp.stderr.readline().decode("utf-8")
m = re.search(r"/dev/pts/[0-9]+", pty_line)
From de9b53695d1bf8d7580e8371e4bc502a29334e6f Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 5 Apr 2017 10:50:26 +1000
Subject: [PATCH 018/826] py: Raise a ValueError if range() step is zero.
Following CPython. Otherwise one gets either an infinite loop (if code is
optimised by the uPy compiler) or possibly a divide-by-zero CPU exception.
---
py/compile.c | 5 +++--
py/objrange.c | 4 +++-
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/py/compile.c b/py/compile.c
index b2811e958..cf9e5079b 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1444,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;
}
}
diff --git a/py/objrange.c b/py/objrange.c
index 5bf0bc7a9..c78c53f11 100644
--- a/py/objrange.c
+++ b/py/objrange.c
@@ -105,8 +105,10 @@ STATIC mp_obj_t range_make_new(const mp_obj_type_t *type, size_t n_args, size_t
o->start = mp_obj_get_int(args[0]);
o->stop = mp_obj_get_int(args[1]);
if (n_args == 3) {
- // TODO check step is non-zero
o->step = mp_obj_get_int(args[2]);
+ if (o->step == 0) {
+ mp_raise_ValueError("zero step");
+ }
}
}
From dcd8f52766784c8a32f9472e1d5b5bfd61324242 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 5 Apr 2017 10:52:29 +1000
Subject: [PATCH 019/826] tests/basics: Add tests for raising ValueError when
range() gets 0 step.
---
tests/basics/builtin_range.py | 6 ++++++
tests/basics/for_range.py | 7 +++++++
2 files changed, 13 insertions(+)
diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py
index 7c3e5beef..6371ab56c 100644
--- a/tests/basics/builtin_range.py
+++ b/tests/basics/builtin_range.py
@@ -34,6 +34,12 @@
print(range(1, 4)[:-1])
print(range(7, -2, -4)[:])
+# zero step
+try:
+ range(1, 2, 0)
+except ValueError:
+ print("ValueError")
+
# bad unary op
try:
-range(1)
diff --git a/tests/basics/for_range.py b/tests/basics/for_range.py
index 58a8f7caa..fc736277d 100644
--- a/tests/basics/for_range.py
+++ b/tests/basics/for_range.py
@@ -6,6 +6,13 @@
for x in range(1, *(6, 2)):
print(x)
+# zero step
+try:
+ for x in range(1, 2, 0):
+ pass
+except ValueError:
+ print('ValueError')
+
# apply args using **
try:
for x in range(**{'end':1}):
From 81d2ca2b12ddb8815a08941b8e00ee15174a0c40 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 5 Apr 2017 12:38:02 +1000
Subject: [PATCH 020/826] py/objtuple: Add support for inplace add (same as
normal add).
---
py/objtuple.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/py/objtuple.c b/py/objtuple.c
index fa5309aae..eaf0e37f4 100644
--- a/py/objtuple.c
+++ b/py/objtuple.c
@@ -138,7 +138,8 @@ mp_obj_t mp_obj_tuple_unary_op(mp_uint_t op, mp_obj_t self_in) {
mp_obj_t mp_obj_tuple_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
mp_obj_tuple_t *o = MP_OBJ_TO_PTR(lhs);
switch (op) {
- case MP_BINARY_OP_ADD: {
+ case MP_BINARY_OP_ADD:
+ case MP_BINARY_OP_INPLACE_ADD: {
if (!mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(rhs)), MP_OBJ_FROM_PTR(&mp_type_tuple))) {
return MP_OBJ_NULL; // op not supported
}
From b6fff4186de098946cc1e4c0204f78936f73044f Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 5 Apr 2017 12:38:18 +1000
Subject: [PATCH 021/826] tests/basics: Add test for tuple inplace add.
---
tests/basics/tuple1.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/basics/tuple1.py b/tests/basics/tuple1.py
index 2993391d5..a7956c107 100644
--- a/tests/basics/tuple1.py
+++ b/tests/basics/tuple1.py
@@ -17,6 +17,10 @@
print(x + (10, 100, 10000))
+# inplace add operator
+x += (10, 11, 12)
+print(x)
+
# construction of tuple from large iterator (tests implementation detail of uPy)
print(tuple(range(20)))
From 0a861db91c9566e9cc6021dc3620c7ecd9af3edd Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 11:39:34 +0300
Subject: [PATCH 022/826] docs/utime: De-conditionalize description of
sleep_ms() and friends.
These are basic MicroPython API, and all ports should implement them.
---
docs/library/utime.rst | 48 ++++++++++++++++++++----------------------
1 file changed, 23 insertions(+), 25 deletions(-)
diff --git a/docs/library/utime.rst b/docs/library/utime.rst
index 0b47a036e..980fefe13 100644
--- a/docs/library/utime.rst
+++ b/docs/library/utime.rst
@@ -70,39 +70,37 @@ Functions
Sleep for the given number of seconds.
-.. only:: port_unix or port_pyboard or port_wipy or port_esp8266
+.. function:: sleep_ms(ms)
- .. function:: sleep_ms(ms)
+ Delay for given number of milliseconds, should be positive or 0.
- Delay for given number of milliseconds, should be positive or 0.
+.. function:: sleep_us(us)
- .. function:: sleep_us(us)
+ Delay for given number of microseconds, should be positive or 0.
- Delay for given number of microseconds, should be positive or 0.
+.. function:: ticks_ms()
- .. function:: ticks_ms()
+ 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.
- 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.
+ 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.
- 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_us()
- .. function:: ticks_us()
-
- Just like ``ticks_ms()`` above, but in microseconds.
+ Just like ``ticks_ms()`` above, but in microseconds.
.. function:: ticks_cpu()
From 906d58f6f29e9a293e2a7cd3485d9191614c66df Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 11:44:10 +0300
Subject: [PATCH 023/826] docs/uos: De-conditionalize statvfs() description.
It's a standard function, and it's already described (in the library
intro) that for any given port, any function may be missing.
---
docs/library/uos.rst | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/docs/library/uos.rst b/docs/library/uos.rst
index cd0c5cae8..bb3c20017 100644
--- a/docs/library/uos.rst
+++ b/docs/library/uos.rst
@@ -61,28 +61,26 @@ Functions
Get the status of a file or directory.
-.. only:: port_unix or port_pyboard or port_esp8266
-
- .. function:: statvfs(path)
-
- Get the status of a fileystem.
-
- Returns a tuple with the filesystem information in the following order:
-
- * ``f_bsize`` -- file system block size
- * ``f_frsize`` -- fragment size
- * ``f_blocks`` -- size of fs in f_frsize units
- * ``f_bfree`` -- number of free blocks
- * ``f_bavail`` -- number of free blocks for unpriviliged users
- * ``f_files`` -- number of inodes
- * ``f_ffree`` -- number of free inodes
- * ``f_favail`` -- number of free inodes for unpriviliged users
- * ``f_flag`` -- mount flags
- * ``f_namemax`` -- maximum filename length
-
- Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
- and the ``f_flags`` parameter may return ``0`` as they can be unavailable
- in a port-specific implementation.
+.. function:: statvfs(path)
+
+ Get the status of a fileystem.
+
+ Returns a tuple with the filesystem information in the following order:
+
+ * ``f_bsize`` -- file system block size
+ * ``f_frsize`` -- fragment size
+ * ``f_blocks`` -- size of fs in f_frsize units
+ * ``f_bfree`` -- number of free blocks
+ * ``f_bavail`` -- number of free blocks for unpriviliged users
+ * ``f_files`` -- number of inodes
+ * ``f_ffree`` -- number of free inodes
+ * ``f_favail`` -- number of free inodes for unpriviliged users
+ * ``f_flag`` -- mount flags
+ * ``f_namemax`` -- maximum filename length
+
+ Parameters related to inodes: ``f_files``, ``f_ffree``, ``f_avail``
+ and the ``f_flags`` parameter may return ``0`` as they can be unavailable
+ in a port-specific implementation.
.. function:: sync()
From 4333b2fb539b60b7f536db70a63595620919b3b6 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 11:47:15 +0300
Subject: [PATCH 024/826] docs/machine.SPI: Remove outdated wipy chunk.
---
docs/library/machine.SPI.rst | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst
index e8a8a2d8c..82858629f 100644
--- a/docs/library/machine.SPI.rst
+++ b/docs/library/machine.SPI.rst
@@ -10,18 +10,6 @@ SS (Slave Select), to select a particular device on a bus with which
communication takes place. Management of an SS signal should happen in
user code (via machine.Pin class).
-.. only:: port_wipy
-
- See usage model of I2C; SPI is very similar. Main difference is
- parameters to init the SPI bus::
-
- from machine import SPI
- spi = SPI(0, mode=SPI.MASTER, baudrate=1000000, polarity=0, phase=0, firstbit=SPI.MSB)
-
- Only required parameter is mode, must be SPI.MASTER. Polarity can be 0 or
- 1, and is the level the idle clock line sits at. Phase can be 0 or 1 to
- sample data on the first or second clock edge respectively.
-
Constructors
------------
From 9a38b7afe0058620c09cf54b0bbc1c20f32a5e22 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 11:58:17 +0300
Subject: [PATCH 025/826] cc3200/modmachine: Return frequency value directly,
like other ports.
---
cc3200/mods/modmachine.c | 5 +----
docs/library/machine.rst | 11 +----------
2 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/cc3200/mods/modmachine.c b/cc3200/mods/modmachine.c
index 3c4e5a116..fd1485607 100644
--- a/cc3200/mods/modmachine.c
+++ b/cc3200/mods/modmachine.c
@@ -111,10 +111,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(machine_info_obj, 0, 1, machine_info)
#endif
STATIC mp_obj_t machine_freq(void) {
- mp_obj_t tuple[1] = {
- mp_obj_new_int(HAL_FCPU_HZ),
- };
- return mp_obj_new_tuple(1, tuple);
+ return mp_obj_new_int(HAL_FCPU_HZ);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_freq_obj, machine_freq);
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index c677bcbf0..1007f142f 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -52,16 +52,7 @@ Power related functions
.. function:: freq()
- .. only:: not port_wipy
-
- Returns CPU frequency in hertz.
-
- .. only:: port_wipy
-
- Returns a tuple of clock frequencies: ``(sysclk,)``
- These correspond to:
-
- - sysclk: frequency of the CPU
+ Returns CPU frequency in hertz.
.. function:: idle()
From d46899626e93b35de549edd6d8954527398a8036 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 12:09:36 +0300
Subject: [PATCH 026/826] docs/machine.Pin: Move wipy-specific details to its
own docs.
---
docs/library/machine.Pin.rst | 52 -----------------------------------
docs/wipy/general.rst | 53 ++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+), 52 deletions(-)
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index 952131f09..d3aa37b45 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -38,58 +38,6 @@ Usage Model::
# configure an irq callback
p0.irq(lambda p:print(p))
-.. only:: port_wipy
-
- On the WiPy board the pins are identified by their string id::
-
- from machine import Pin
- g = machine.Pin('GP9', mode=Pin.OUT, pull=None, drive=Pin.MED_POWER, alt=-1)
-
- You can also configure the Pin to generate interrupts. For instance::
-
- from machine import Pin
-
- def pincb(pin):
- print(pin.id())
-
- pin_int = Pin('GP10', mode=Pin.IN, pull=Pin.PULL_DOWN)
- pin_int.irq(trigger=Pin.IRQ_RISING, handler=pincb)
- # the callback can be triggered manually
- pin_int.irq()()
- # to disable the callback
- pin_int.irq().disable()
-
- Now every time a falling edge is seen on the gpio pin, the callback will be
- executed. Caution: mechanical push buttons have "bounce" and pushing or
- releasing a switch will often generate multiple edges.
- See: http://www.eng.utah.edu/~cs5780/debouncing.pdf for a detailed
- explanation, along with various techniques for debouncing.
-
- All pin objects go through the pin mapper to come up with one of the
- gpio pins.
-
- For the ``drive`` parameter the strengths are:
-
- - ``Pin.LOW_POWER`` - 2mA drive capability.
- - ``Pin.MED_POWER`` - 4mA drive capability.
- - ``Pin.HIGH_POWER`` - 6mA drive capability.
-
- For the ``alt`` parameter please refer to the pinout and alternate functions
- table at `_
- 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
------------
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index 0991dbaea..0d0327f4b 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -179,3 +179,56 @@ 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 `_
+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.
From 2cbe99783432b29bc303dc2e2cfe6823fe4a6c4f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 12:30:39 +0300
Subject: [PATCH 027/826] tools/pyboard: ProcessPtyToTerminal: Add workaround
for PySerial bug.
When working with a "virtual" port, like PTY. The issue described in
http://stackoverflow.com/questions/34831131/pyserial-does-not-play-well-with-virtual-port
---
tools/pyboard.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/tools/pyboard.py b/tools/pyboard.py
index b7babdc30..d96ccc328 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -179,7 +179,9 @@ def __init__(self, cmd):
self.close()
sys.exit(1)
pty = m.group()
- self.ser = serial.Serial(pty, interCharTimeout=1)
+ # rtscts, dsrdtr params are to workaround pyserial bug:
+ # http://stackoverflow.com/questions/34831131/pyserial-does-not-play-well-with-virtual-port
+ self.ser = serial.Serial(pty, interCharTimeout=1, rtscts=True, dsrdtr=True)
def close(self):
import signal
From 390d5a3bf101eba5952c3f757f27b82ff0bdfed1 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 13:05:04 +0300
Subject: [PATCH 028/826] docs/machine.Pin: Move wipy-specific methods to its
docs.
---
docs/library/machine.Pin.rst | 10 ----------
docs/wipy/general.rst | 7 +++++++
2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index d3aa37b45..216ebcb2a 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -225,16 +225,6 @@ Methods
This method returns a callback object.
-.. only:: port_wipy
-
- .. method:: Pin.alt_list()
-
- Returns a list of the alternate functions supported by the pin. List items are
- a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
-
- Availability: WiPy.
-
-
Attributes
----------
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index 0d0327f4b..d7b35cc4e 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -232,3 +232,10 @@ For interrupts, the ``priority`` can take values in the range 1-7. And the
- 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)``
From faf333c04f3dddb9ca1a6b7fc5ff74eabcfe51b0 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 5 Apr 2017 13:34:37 +0300
Subject: [PATCH 029/826] zephyr/modusocket: Factor out "extended k_fifo API".
Internal structure of k_fifo changed between 1.7 and 1.8, so we need
to abstract it away. This adds more functions than currently used, for
future work.
---
zephyr/modusocket.c | 35 +++++++++++++++++++++++++++++++++--
1 file changed, 33 insertions(+), 2 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 155ed69b8..0bcbbce60 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -31,6 +31,8 @@
#include
#include
+// Zephyr's generated version header
+#include
#include
#include
@@ -55,6 +57,36 @@ typedef struct _socket_obj_t {
STATIC const mp_obj_type_t socket_type;
+// k_fifo extended API
+
+static inline void *_k_fifo_peek_head(struct k_fifo *fifo)
+{
+#if KERNEL_VERSION_NUMBER < 0x010763 /* 1.7.99 */
+ return sys_slist_peek_head(&fifo->data_q);
+#else
+ return sys_slist_peek_head(&fifo->_queue.data_q);
+#endif
+}
+
+static inline void *_k_fifo_peek_tail(struct k_fifo *fifo)
+{
+#if KERNEL_VERSION_NUMBER < 0x010763 /* 1.7.99 */
+ return sys_slist_peek_tail(&fifo->data_q);
+#else
+ return sys_slist_peek_tail(&fifo->_queue.data_q);
+#endif
+}
+
+static inline void _k_fifo_wait_non_empty(struct k_fifo *fifo, int32_t timeout)
+{
+ struct k_poll_event events[] = {
+ K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, K_POLL_MODE_NOTIFY_ONLY, fifo),
+ };
+
+ k_poll(events, MP_ARRAY_SIZE(events), timeout);
+ DEBUG_printf("poll res: %d\n", events[0].state);
+}
+
// Helper functions
#define RAISE_ERRNO(x) { int _err = x; if (_err < 0) mp_raise_OSError(-_err); }
@@ -112,8 +144,7 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
// if net_buf == NULL, EOF
if (net_buf == NULL) {
- // TODO: k_fifo accessor for this?
- struct net_buf *last_buf = (struct net_buf*)sys_slist_peek_tail(&socket->recv_q.data_q);
+ struct net_buf *last_buf = _k_fifo_peek_tail(&socket->recv_q);
// We abuse "buf_sent" flag to store EOF flag
net_nbuf_set_buf_sent(last_buf, true);
DEBUG_printf("Set EOF flag on %p\n", last_buf);
From 1da840464759f73efbc42238a91733f436991eaf Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 6 Apr 2017 10:11:04 +0300
Subject: [PATCH 030/826] modusocket: Handle a case when recv_q is empty when
EOF is signaled.
In this case, we can mark socket as closed directly.
---
zephyr/modusocket.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 0bcbbce60..a5ed5c1b0 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -145,9 +145,14 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
// if net_buf == NULL, EOF
if (net_buf == NULL) {
struct net_buf *last_buf = _k_fifo_peek_tail(&socket->recv_q);
- // We abuse "buf_sent" flag to store EOF flag
- net_nbuf_set_buf_sent(last_buf, true);
- DEBUG_printf("Set EOF flag on %p\n", last_buf);
+ if (last_buf == NULL) {
+ socket->state = STATE_PEER_CLOSED;
+ DEBUG_printf("Marked socket %p as peer-closed\n", socket);
+ } else {
+ // We abuse "buf_sent" flag to store EOF flag
+ net_nbuf_set_buf_sent(last_buf, true);
+ DEBUG_printf("Set EOF flag on %p\n", last_buf);
+ }
return;
}
From 3e1310d6e23777d7322016d7390a00da3284afbb Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 7 Apr 2017 01:04:47 +0300
Subject: [PATCH 031/826] tools/pyboard: Provide more details when expected
reply not received.
When trying to execute a command via raw REPL and expected "OK" reply
not received, show what was received instead.
---
tools/pyboard.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/pyboard.py b/tools/pyboard.py
index d96ccc328..5eac030bd 100755
--- a/tools/pyboard.py
+++ b/tools/pyboard.py
@@ -319,7 +319,7 @@ def exec_raw_no_follow(self, command):
# check if we could exec command
data = self.serial.read(2)
if data != b'OK':
- raise PyboardError('could not exec command')
+ raise PyboardError('could not exec command (response: %s)' % data)
def exec_raw(self, command, timeout=10, data_consumer=None):
self.exec_raw_no_follow(command);
From d7310fabc22ebf45aedcaade1c531ece96c33bf0 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 7 Apr 2017 15:54:21 +1000
Subject: [PATCH 032/826] drivers/nrf24l01: Update to work on newer ports,
using machine, utime.
Changes made are:
- Use the time module in place of the pyb module for delays.
- Use spi.read/spi.write instead of spi.send/spi.receive.
- Drop some non-portable parameters to spi and pin initialization.
Thanks to @deshipu for the original patch.
---
drivers/nrf24l01/nrf24l01.py | 76 ++++++++++++++++++++++--------------
1 file changed, 47 insertions(+), 29 deletions(-)
diff --git a/drivers/nrf24l01/nrf24l01.py b/drivers/nrf24l01/nrf24l01.py
index 3c79650bf..788906dc0 100644
--- a/drivers/nrf24l01/nrf24l01.py
+++ b/drivers/nrf24l01/nrf24l01.py
@@ -2,7 +2,7 @@
"""
from micropython import const
-import pyb
+import utime
# nRF24L01+ registers
CONFIG = const(0x00)
@@ -53,22 +53,24 @@ class NRF24L01:
def __init__(self, spi, cs, ce, channel=46, payload_size=16):
assert payload_size <= 32
- # init the SPI bus and pins
- spi.init(spi.MASTER, baudrate=4000000, polarity=0, phase=0, firstbit=spi.MSB)
- cs.init(cs.OUT_PP, cs.PULL_NONE)
- ce.init(ce.OUT_PP, ce.PULL_NONE)
+ self.buf = bytearray(1)
# store the pins
self.spi = spi
self.cs = cs
self.ce = ce
+ # init the SPI bus and pins
+ self.init_spi(4000000)
+ cs.init(cs.OUT, value=1)
+ ce.init(ce.OUT, value=0)
+
# reset everything
self.ce.low()
self.cs.high()
self.payload_size = payload_size
self.pipe0_read_addr = None
- pyb.delay(5)
+ utime.sleep_ms(5)
# set address width to 5 bytes and check for device present
self.reg_write(SETUP_AW, 0b11)
@@ -98,28 +100,44 @@ def __init__(self, spi, cs, ce, channel=46, payload_size=16):
self.flush_rx()
self.flush_tx()
+ def init_spi(self, baudrate):
+ try:
+ master = self.spi.MASTER
+ except AttributeError:
+ self.spi.init(baudrate=baudrate, polarity=0, phase=0)
+ else:
+ self.spi.init(master, baudrate=baudrate, polarity=0, phase=0)
+
def reg_read(self, reg):
self.cs.low()
- self.spi.send_recv(reg)
- buf = self.spi.recv(1)
+ self.spi.readinto(self.buf, reg)
+ self.spi.readinto(self.buf)
+ self.cs.high()
+ return self.buf[0]
+
+ def reg_write_bytes(self, reg, buf):
+ self.cs.low()
+ self.spi.readinto(self.buf, 0x20 | reg)
+ self.spi.write(buf)
self.cs.high()
- return buf[0]
+ return self.buf[0]
- def reg_write(self, reg, buf):
+ def reg_write(self, reg, value):
self.cs.low()
- status = self.spi.send_recv(0x20 | reg)[0]
- self.spi.send(buf)
+ self.spi.readinto(self.buf, 0x20 | reg)
+ ret = self.buf[0]
+ self.spi.readinto(self.buf, value)
self.cs.high()
- return status
+ return ret
def flush_rx(self):
self.cs.low()
- self.spi.send(FLUSH_RX)
+ self.spi.readinto(self.buf, FLUSH_RX)
self.cs.high()
def flush_tx(self):
self.cs.low()
- self.spi.send(FLUSH_TX)
+ self.spi.readinto(self.buf, FLUSH_TX)
self.cs.high()
# power is one of POWER_x defines; speed is one of SPEED_x defines
@@ -144,8 +162,8 @@ def set_channel(self, channel):
# 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 @@ def open_rx_pipe(self, pipe_id, address):
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 @@ def start_listening(self):
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 @@ def any(self):
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 @@ def recv(self):
# 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 @@ def send(self, buf, timeout=500):
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
From e5278b98fe2aad840d58e33a0c06af2e2b55cbde Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 7 Apr 2017 10:52:50 +0300
Subject: [PATCH 033/826] docs/esp8266/general: Start explicit "Known Issues",
mentioned RTC inaccuracy.
---
docs/esp8266/general.rst | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/docs/esp8266/general.rst b/docs/esp8266/general.rst
index cd659f80a..47df80d7b 100644
--- a/docs/esp8266/general.rst
+++ b/docs/esp8266/general.rst
@@ -107,8 +107,16 @@ This will allow to keep the structure of your application clear, as well as
allow to install multiple applications on a board, and switch among them.
+Known Issues
+------------
+
Real-time clock
----------------
+~~~~~~~~~~~~~~~
+
+RTC in ESP8266 has very bad accuracy, drift may be seconds per minute. As
+a workaround, to measure short enough intervals you can use
+``utime.time()``, etc. functions, and for wall clock time, synchronize from
+the net using included ``ntpdate.py`` module.
Due to limitations of the ESP8266 chip the internal real-time clock (RTC)
will overflow every 7:45h. If a long-term working RTC time is required then
From f1c0676a70c771abb6e319a0ec2708740a2bf222 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 7 Apr 2017 16:47:10 +0300
Subject: [PATCH 034/826] zephyr/modusocket: Implement listen().
---
zephyr/modusocket.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index a5ed5c1b0..6dd257266 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -244,6 +244,16 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_connect_obj, socket_connect);
+STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ mp_int_t backlog = mp_obj_get_int(backlog_in);
+ RAISE_ERRNO(net_context_listen(socket->ctx, backlog));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+
STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
socket_obj_t *socket = self_in;
socket_check_closed(socket);
@@ -368,6 +378,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
};
From 96166ec16526e8cbb3a18df478da68fe5d8208ee Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 8 Apr 2017 00:30:17 +0300
Subject: [PATCH 035/826] zephyr/modusocket: socket_bind: Don't set recv
callback on STREAM sockets.
For stream sockets, next exected operation is listen().
---
zephyr/modusocket.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 6dd257266..7898f5576 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -224,8 +224,13 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
parse_inet_addr(socket, addr_in, &sockaddr);
RAISE_ERRNO(net_context_bind(socket->ctx, &sockaddr, sizeof(sockaddr)));
- DEBUG_printf("Setting recv cb after bind\n");
- RAISE_ERRNO(net_context_recv(socket->ctx, sock_received_cb, K_NO_WAIT, socket));
+ // For DGRAM socket, we expect to receive packets after call to bind(),
+ // but for STREAM socket, next expected operation is listen(), which
+ // doesn't work if recv callback is set.
+ if (net_context_get_type(socket->ctx) == SOCK_DGRAM) {
+ DEBUG_printf("Setting recv cb after bind\n");
+ RAISE_ERRNO(net_context_recv(socket->ctx, sock_received_cb, K_NO_WAIT, socket));
+ }
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_bind_obj, socket_bind);
From 8ef469f7cab0e820ec8bc4f175eecf81a404da4f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 8 Apr 2017 00:33:09 +0300
Subject: [PATCH 036/826] zephyr/modusocket: Implement accept().
---
zephyr/modusocket.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 7898f5576..36ccdbc3b 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -45,7 +45,10 @@
typedef struct _socket_obj_t {
mp_obj_base_t base;
struct net_context *ctx;
- struct k_fifo recv_q;
+ union {
+ struct k_fifo recv_q;
+ struct k_fifo accept_q;
+ };
struct net_buf *cur_buf;
#define STATE_NEW 0
@@ -164,6 +167,15 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
k_fifo_put(&socket->recv_q, net_buf);
}
+// Callback for incoming connections.
+static void sock_accepted_cb(struct net_context *new_ctx, struct sockaddr *addr, socklen_t addrlen, int status, void *user_data) {
+ socket_obj_t *socket = (socket_obj_t*)user_data;
+ DEBUG_printf("accept cb: context: %p, status: %d, new ctx: %p\n", socket->ctx, status, new_ctx);
+ DEBUG_printf("new_ctx ref_cnt: %d\n", new_ctx->refcount);
+
+ k_fifo_put(&socket->accept_q, new_ctx);
+}
+
socket_obj_t *socket_new(void) {
socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
socket->base.type = (mp_obj_t)&socket_type;
@@ -255,10 +267,33 @@ STATIC mp_obj_t socket_listen(mp_obj_t self_in, mp_obj_t backlog_in) {
mp_int_t backlog = mp_obj_get_int(backlog_in);
RAISE_ERRNO(net_context_listen(socket->ctx, backlog));
+ RAISE_ERRNO(net_context_accept(socket->ctx, sock_accepted_cb, K_NO_WAIT, socket));
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_listen_obj, socket_listen);
+STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
+ socket_obj_t *socket = self_in;
+ socket_check_closed(socket);
+
+ struct net_context *ctx = k_fifo_get(&socket->accept_q, K_FOREVER);
+ // Was overwritten by fifo
+ ctx->refcount = 1;
+
+ socket_obj_t *socket2 = socket_new();
+ socket2->ctx = ctx;
+ DEBUG_printf("Setting recv cb after accept()\n");
+ RAISE_ERRNO(net_context_recv(ctx, sock_received_cb, K_NO_WAIT, socket2));
+
+ mp_obj_tuple_t *client = mp_obj_new_tuple(2, NULL);
+ client->items[0] = MP_OBJ_FROM_PTR(socket2);
+ // TODO
+ client->items[1] = mp_const_none;
+
+ return MP_OBJ_FROM_PTR(client);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
+
STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
socket_obj_t *socket = self_in;
socket_check_closed(socket);
@@ -384,6 +419,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
};
From cf70f9a474a40a4b263bce8a63ef5bdf342673c8 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 8 Apr 2017 00:38:51 +0300
Subject: [PATCH 037/826] zephyr/mpconfigport.h: Fix build if usocket module is
disabled.
---
zephyr/mpconfigport.h | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h
index 0949d1374..936783451 100644
--- a/zephyr/mpconfigport.h
+++ b/zephyr/mpconfigport.h
@@ -109,6 +109,14 @@ extern const struct _mp_obj_module_t mp_module_time;
extern const struct _mp_obj_module_t mp_module_usocket;
extern const struct _mp_obj_module_t mp_module_zephyr;
+#if MICROPY_PY_USOCKET
+#define MICROPY_PY_USOCKET_DEF { MP_ROM_QSTR(MP_QSTR_usocket), MP_ROM_PTR(&mp_module_usocket) },
+#define MICROPY_PY_USOCKET_WEAK_DEF { MP_OBJ_NEW_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) },
+#else
+#define MICROPY_PY_USOCKET_DEF
+#define MICROPY_PY_USOCKET_WEAK_DEF
+#endif
+
#if MICROPY_PY_UTIME
#define MICROPY_PY_UTIME_DEF { MP_ROM_QSTR(MP_QSTR_utime), MP_ROM_PTR(&mp_module_time) },
#else
@@ -123,13 +131,13 @@ extern const struct _mp_obj_module_t mp_module_zephyr;
#define MICROPY_PORT_BUILTIN_MODULES \
{ MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&mp_module_machine }, \
- { MP_OBJ_NEW_QSTR(MP_QSTR_usocket), (mp_obj_t)&mp_module_usocket }, \
+ MICROPY_PY_USOCKET_DEF \
MICROPY_PY_UTIME_DEF \
MICROPY_PY_ZEPHYR_DEF \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_time), MP_ROM_PTR(&mp_module_time) }, \
- { MP_OBJ_NEW_QSTR(MP_QSTR_socket), MP_ROM_PTR(&mp_module_usocket) }, \
+ MICROPY_PY_USOCKET_WEAK_DEF \
// extra built in names to add to the global namespace
#define MICROPY_PORT_BUILTINS \
From e05cb4183a6ab06123eaa9eac91d6d134ebc083b Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 8 Apr 2017 00:50:19 +0300
Subject: [PATCH 038/826] zephyr/modmachine: Add Signal class.
---
zephyr/modmachine.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/zephyr/modmachine.c b/zephyr/modmachine.c
index 6194a95da..4013815d1 100644
--- a/zephyr/modmachine.c
+++ b/zephyr/modmachine.c
@@ -32,6 +32,7 @@
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/machine_mem.h"
+#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
#include "extmod/machine_i2c.h"
#include "modmachine.h"
@@ -56,6 +57,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
// reset causes
/*{ MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(REASON_DEFAULT_RST) },*/
From 0a88b44248a7fafb01e98019e4b79547772ea206 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 8 Apr 2017 14:27:36 +0300
Subject: [PATCH 039/826] zephyr/machine_pin: Implement pin protocol for
machine.Signal support.
---
zephyr/machine_pin.c | 27 +++++++++++++++++++++++++--
zephyr/mpconfigport.h | 1 +
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/zephyr/machine_pin.c b/zephyr/machine_pin.c
index 049255e9f..5bf273909 100644
--- a/zephyr/machine_pin.c
+++ b/zephyr/machine_pin.c
@@ -81,7 +81,7 @@ STATIC mp_obj_t machine_pin_obj_init_helper(machine_pin_obj_t *self, mp_uint_t n
}
// constructor(drv_name, pin, ...)
-STATIC mp_obj_t machine_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted port
@@ -154,6 +154,24 @@ STATIC mp_obj_t machine_pin_high(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_pin_high_obj, machine_pin_high);
+STATIC mp_uint_t machine_pin_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg, int *errcode) {
+ (void)errcode;
+ machine_pin_obj_t *self = self_in;
+
+ switch (request) {
+ case MP_PIN_READ: {
+ uint32_t pin_val;
+ gpio_pin_read(self->port, self->pin, &pin_val);
+ return pin_val;
+ }
+ case MP_PIN_WRITE: {
+ gpio_pin_write(self->port, self->pin, arg);
+ return 0;
+ }
+ }
+ return -1;
+}
+
STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
// instance methods
{ MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&machine_pin_init_obj },
@@ -170,11 +188,16 @@ STATIC const mp_map_elem_t machine_pin_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(machine_pin_locals_dict, machine_pin_locals_dict_table);
+STATIC const mp_pin_p_t machine_pin_pin_p = {
+ .ioctl = machine_pin_ioctl,
+};
+
const mp_obj_type_t machine_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = machine_pin_print,
- .make_new = machine_pin_make_new,
+ .make_new = mp_pin_make_new,
.call = machine_pin_call,
+ .protocol = &machine_pin_pin_p,
.locals_dict = (mp_obj_t)&machine_pin_locals_dict,
};
diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h
index 936783451..2c57ede4d 100644
--- a/zephyr/mpconfigport.h
+++ b/zephyr/mpconfigport.h
@@ -58,6 +58,7 @@
#define MICROPY_PY_IO (0)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_MACHINE (1)
+#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_PY_STRUCT (0)
#ifdef CONFIG_NETWORKING
From bcf3c8bf17caad7a2f46ee69f1d9563d884c2f23 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:06:54 +0300
Subject: [PATCH 040/826] docs/library/builtins: int: Add notice on byteorder
param for to/from_bytes.
---
docs/library/builtins.rst | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/docs/library/builtins.rst b/docs/library/builtins.rst
index d53c4d377..46f762660 100644
--- a/docs/library/builtins.rst
+++ b/docs/library/builtins.rst
@@ -67,6 +67,16 @@ All builtin functions are described here. They are also available via
.. class:: int()
+ .. classmethod:: from_bytes(bytes, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
+ .. method:: to_bytes(size, byteorder)
+
+ In MicroPython, `byteorder` parameter must be positional (this is
+ compatible with CPython).
+
.. function:: isinstance()
.. function:: issubclass()
From e322b2afbf5a8795033a2e9807b561a05ea744bf Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:17:29 +0300
Subject: [PATCH 041/826] cc3200/pybuart: Make parity specifications consistent
with HW API.
parity=0 means even parity, parity=1 - odd.
---
cc3200/mods/pybuart.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
index 7fb51d83d..92bb3e46e 100644
--- a/cc3200/mods/pybuart.c
+++ b/cc3200/mods/pybuart.c
@@ -375,10 +375,13 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a
config |= UART_CONFIG_PAR_NONE;
} else {
uint parity = mp_obj_get_int(args[2].u_obj);
- if (parity != UART_CONFIG_PAR_ODD && parity != UART_CONFIG_PAR_EVEN) {
+ if (parity == 0) {
+ config |= UART_CONFIG_PAR_EVEN;
+ } else if (parity == 1) {
+ config |= UART_CONFIG_PAR_ODD;
+ } else {
goto error;
}
- config |= parity;
}
// stop bits
config |= (args[3].u_int == 1 ? UART_CONFIG_STOP_ONE : UART_CONFIG_STOP_TWO);
@@ -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) },
};
From 1d74559b6b3eb1e9f0eb2aceceb898f6d24f5dd4 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:25:27 +0300
Subject: [PATCH 042/826] docs/library/machine.UART: Remove some conditionals.
---
docs/library/machine.UART.rst | 35 ++++++++---------------------------
1 file changed, 8 insertions(+), 27 deletions(-)
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index 0b6b24e89..fe7597eb5 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -15,17 +15,13 @@ UART objects can be created and initialised using::
uart = UART(1, 9600) # init with given baudrate
uart.init(9600, bits=8, parity=None, stop=1) # init with given parameters
-.. only:: port_machineoard
+Supported paramters differ on a board:
- Bits can be 7, 8 or 9. Parity can be None, 0 (even) or 1 (odd). Stop can be 1 or 2.
-
- *Note:* with parity=None, only 8 and 9 bits are supported. With parity enabled,
- only 7 and 8 bits are supported.
-
-.. only:: port_wipy
-
- Bits can be 5, 6, 7, 8. Parity can be ``None``, ``UART.EVEN`` or ``UART.ODD``. Stop can be 1 or 2.
+Pyboard: Bits can be 7, 8 or 9. Stop can be 1 or 2. With `parity=None`,
+only 8 and 9 bits are supported. With parity enabled, only 7 and 8 bits
+are supported.
+WiPy/CC3200: Bits can be 5, 6, 7, 8. Stop can be 1 or 2.
A UART object acts like a stream object and reading and writing is done
using the standard stream methods::
@@ -47,22 +43,12 @@ using the standard stream methods::
uart.any() # returns True if any characters waiting
-.. only:: port_wipy
-
- To check if there is anything to be read, use::
-
- uart.any() # returns the number of characters available for reading
-
Constructors
------------
-.. only:: port_wipy
+.. class:: UART(id, ...)
- .. class:: UART(bus, ...)
-
- Construct a UART object on the given bus. ``bus`` can be 0 or 1.
- If the bus is not given, the default one will be selected (0) or the selection
- will be made based on the given pins.
+ Construct a UART object of the given id.
Methods
-------
@@ -75,7 +61,7 @@ Methods
- ``baudrate`` is the clock rate.
- ``bits`` is the number of bits per character, 7, 8 or 9.
- - ``parity`` is the parity, ``None``, ``UART.EVEN`` or ``UART.ODD``.
+ - ``parity`` is the parity, ``None``, 0 (even) or 1 (odd).
- ``stop`` is the number of stop bits, 1 or 2.
- ``pins`` is a 4 or 2 item list indicating the TX, RX, RTS and CTS pins (in that order).
Any of the pins can be None if one wants the UART to operate with limited functionality.
@@ -159,11 +145,6 @@ Methods
Constants
---------
- .. data:: UART.EVEN
- .. data:: UART.ODD
-
- parity types (along with ``None``)
-
.. data:: UART.RX_ANY
IRQ trigger sources
From 3acace588a51b5f45a28ae3f63d662b6be0e8d4d Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:42:32 +0300
Subject: [PATCH 043/826] docs/utime: Deconditionalize description of sleep().
---
docs/library/utime.rst | 18 +++++-------------
1 file changed, 5 insertions(+), 13 deletions(-)
diff --git a/docs/library/utime.rst b/docs/library/utime.rst
index 980fefe13..871f6c678 100644
--- a/docs/library/utime.rst
+++ b/docs/library/utime.rst
@@ -55,20 +55,12 @@ 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.
-
-.. only:: port_wipy
-
- .. function:: sleep(seconds)
-
- Sleep for the given number of seconds.
+ 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.
.. function:: sleep_ms(ms)
From 2e58474580fe459c03e52c7662d28786f3885fdf Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:48:28 +0300
Subject: [PATCH 044/826] docs/usocket: Deconditionalize.
Notes on WiPy incompatibilities with the standard socket module API are
moved under "Known issues" to its documentation.
---
docs/library/usocket.rst | 12 ------------
docs/wipy/general.rst | 14 ++++++++++++++
2 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/docs/library/usocket.rst b/docs/library/usocket.rst
index dd0f5708b..71deaebc4 100644
--- a/docs/library/usocket.rst
+++ b/docs/library/usocket.rst
@@ -41,18 +41,6 @@ Functions
Create a new socket using the given address family, socket type and protocol number.
- .. only:: port_wipy
-
- .. note::
-
- SSL sockets need to be created the following way before wrapping them with
- ``ssl.wrap_socket``::
-
- import socket
- import ssl
- s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
- ss = ssl.wrap_socket(s)
-
.. function:: socket.getaddrinfo(host, port)
Translate the host/port argument into a sequence of 5-tuples that contain all the
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index d7b35cc4e..9b3f54df2 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -239,3 +239,17 @@ Additional Pin methods:
Returns a list of the alternate functions supported by the pin. List items are
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
+
+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)
From b87432b8fb8332548be11b63c9139065ce565f91 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 9 Apr 2017 00:57:16 +0300
Subject: [PATCH 045/826] docs/uhashlib: Deconditionalize.
Notes on WiPy incompatibilities with the standard module API are
moved under "Known issues" to its documentation.
---
docs/library/uhashlib.rst | 30 ------------------------------
docs/wipy/general.rst | 20 ++++++++++++++++++++
2 files changed, 20 insertions(+), 30 deletions(-)
diff --git a/docs/library/uhashlib.rst b/docs/library/uhashlib.rst
index 2c340e40b..cd0216dae 100644
--- a/docs/library/uhashlib.rst
+++ b/docs/library/uhashlib.rst
@@ -37,36 +37,6 @@ Constructors
Create an MD5 hasher object and optionally feed ``data`` into it.
-.. only:: port_wipy
-
- .. class:: uhashlib.sha1([data[, block_size]])
-
- Create a sha1 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
-
- .. class:: uhashlib.sha256([data[, block_size]])
-
- Create a sha256 hasher object and optionally feed ``data`` or ``data and block_size`` into it.
-
- .. admonition:: CPython extension
- :class: attention
-
- Due to hardware implementation details of the WiPy, data must be buffered before being
- digested, which would make it impossible to calculate the hash of big blocks of data that
- do not fit in RAM. In this case, since most likely the total size of the data is known
- in advance, the size can be passed to the constructor and hence the HASH hardware engine
- of the WiPy can be properly initialized without needing buffering. If ``block_size`` is
- to be given, an initial chunk of ``data`` must be passed as well. **When using this extension,
- care must be taken to make sure that the length of all intermediate chunks (including the
- initial one) is a multiple of 4 bytes.** The last chunk may be of any length.
-
- Example::
-
- hash = uhashlib.sha1('abcd1234', 1001) # length of the initial piece is multiple of 4 bytes
- hash.update('1234') # also multiple of 4 bytes
- ...
- hash.update('12345') # last chunk may be of any length
- hash.digest()
-
Methods
-------
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index 9b3f54df2..eca9bbe45 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -253,3 +253,23 @@ SSL sockets need to be created the following way before wrapping them with.
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()
From ee86de1f1a22c45548bc39916fcd2b72dd26ebca Mon Sep 17 00:00:00 2001
From: Damien George
Date: Mon, 10 Apr 2017 16:02:56 +1000
Subject: [PATCH 046/826] py: Make sure that static emg-exc-buffer is aligned
to size of mp_obj_t.
This buffer is used to allocate objects temporarily, and such objects
require that their underlying memory be correctly aligned for their data
type. Aligning for mp_obj_t should be sufficient for emergency exceptions,
but in general the memory buffer should aligned to the maximum alignment of
the machine (eg on a 32-bit machine with mp_obj_t being 4 bytes, a double
may not be correctly aligned).
This patch fixes a bug for certain nan-boxing builds, where mp_obj_t is 8
bytes and must be aligned to 8 bytes (even though the machine is 32 bit).
---
py/mpstate.h | 4 ++--
py/objexcept.c | 6 +++---
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/py/mpstate.h b/py/mpstate.h
index 0134dd8e8..2b8f29a6a 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -120,8 +120,8 @@ typedef struct _mp_state_vm_t {
// memory for exception arguments if we can't allocate RAM
#if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF
#if MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE > 0
- // statically allocated buf
- byte mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE];
+ // statically allocated buf (needs to be aligned to mp_obj_t)
+ mp_obj_t mp_emergency_exception_buf[MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE / sizeof(mp_obj_t)];
#else
// dynamically allocated buf
byte *mp_emergency_exception_buf;
diff --git a/py/objexcept.c b/py/objexcept.c
index 1f1009ff7..dcc7800dc 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -348,7 +348,7 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
tuple->items[0] = MP_OBJ_FROM_PTR(str);
byte *str_data = (byte *)&str[1];
- uint max_len = MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
+ size_t max_len = (byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size
- str_data;
vstr_t vstr;
@@ -366,14 +366,14 @@ mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char
o->args = tuple;
- uint offset = &str_data[str->len] - MP_STATE_VM(mp_emergency_exception_buf);
+ size_t offset = &str_data[str->len] - (byte*)MP_STATE_VM(mp_emergency_exception_buf);
offset += sizeof(void *) - 1;
offset &= ~(sizeof(void *) - 1);
if ((mp_emergency_exception_buf_size - offset) > (sizeof(o->traceback_data[0]) * 3)) {
// We have room to store some traceback.
o->traceback_data = (size_t*)((byte *)MP_STATE_VM(mp_emergency_exception_buf) + offset);
- o->traceback_alloc = (MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);
+ o->traceback_alloc = ((byte*)MP_STATE_VM(mp_emergency_exception_buf) + mp_emergency_exception_buf_size - (byte *)o->traceback_data) / sizeof(o->traceback_data[0]);
o->traceback_len = 0;
}
}
From 79ce6649524b08732e15d86c4ff61266c3ec14ed Mon Sep 17 00:00:00 2001
From: Damien George
Date: Mon, 10 Apr 2017 17:07:26 +1000
Subject: [PATCH 047/826] py/runtime: When init'ing kbd intr exc, use tuple ptr
instead of object.
---
py/runtime.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/py/runtime.c b/py/runtime.c
index 1df6740b2..bf2bfb8ea 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -78,7 +78,7 @@ void mp_init(void) {
MP_STATE_VM(mp_kbd_exception).traceback_alloc = 0;
MP_STATE_VM(mp_kbd_exception).traceback_len = 0;
MP_STATE_VM(mp_kbd_exception).traceback_data = NULL;
- MP_STATE_VM(mp_kbd_exception).args = mp_const_empty_tuple;
+ MP_STATE_VM(mp_kbd_exception).args = (mp_obj_tuple_t*)&mp_const_empty_tuple_obj;
#endif
// call port specific initialization if any
From 605ff91efdeb3cd7e4948c0398c839a9ae06044a Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 11 Apr 2017 00:12:20 +0300
Subject: [PATCH 048/826] extmod/machine_signal: Support all Pin's arguments to
the constructor.
This implements the orginal idea is that Signal is a subclass of Pin, and
thus can accept all the same argument as Pin, and additionally, "inverted"
param. On the practical side, it allows to avoid many enclosed parenses for
a typical declararion, e.g. for Zephyr:
Signal(Pin(("GPIO_0", 1))).
Of course, passing a Pin to Signal constructor is still supported and is the
most generic form (e.g. Unix port will only support such form, as it doesn't
have "builtin" Pins), what's introduces here is just practical readability
optimization.
"value" kwarg is treated as applying to a Signal (i.e. accounts for possible
inversion).
---
esp8266/machine_pin.c | 4 +--
esp8266/mpconfigport.h | 1 +
extmod/machine_signal.c | 73 ++++++++++++++++++++++++++++++++++++-----
extmod/virtpin.h | 3 ++
4 files changed, 70 insertions(+), 11 deletions(-)
diff --git a/esp8266/machine_pin.c b/esp8266/machine_pin.c
index d4c6d3dea..1a263601b 100644
--- a/esp8266/machine_pin.c
+++ b/esp8266/machine_pin.c
@@ -287,7 +287,7 @@ STATIC mp_obj_t pyb_pin_obj_init_helper(pyb_pin_obj_t *self, mp_uint_t n_args, c
}
// constructor(id, ...)
-STATIC mp_obj_t pyb_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// get the wanted pin object
@@ -436,7 +436,7 @@ const mp_obj_type_t pyb_pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = pyb_pin_print,
- .make_new = pyb_pin_make_new,
+ .make_new = mp_pin_make_new,
.call = pyb_pin_call,
.protocol = &pin_pin_p,
.locals_dict = (mp_obj_t)&pyb_pin_locals_dict,
diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h
index b25bb8bb4..d0b4a7b4b 100644
--- a/esp8266/mpconfigport.h
+++ b/esp8266/mpconfigport.h
@@ -73,6 +73,7 @@
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_LWIP (1)
#define MICROPY_PY_MACHINE (1)
+#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_PULSE (1)
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_SPI (1)
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index de6c3ff32..b10d90166 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -27,6 +27,8 @@
#include "py/mpconfig.h"
#if MICROPY_PY_MACHINE
+#include
+
#include "py/obj.h"
#include "py/runtime.h"
#include "extmod/virtpin.h"
@@ -41,20 +43,73 @@ typedef struct _machine_signal_t {
} machine_signal_t;
STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
- enum { ARG_pin, ARG_inverted };
- static const mp_arg_t allowed_args[] = {
- { MP_QSTR_, MP_ARG_OBJ | MP_ARG_REQUIRED },
- { MP_QSTR_inverted, MP_ARG_BOOL, {.u_bool = false} },
- };
+ mp_obj_t pin = args[0];
+ bool inverted = false;
+
+ #if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
+ mp_pin_p_t *pin_p = NULL;
+
+ if (MP_OBJ_IS_OBJ(pin)) {
+ mp_obj_base_t *pin_base = (mp_obj_base_t*)MP_OBJ_TO_PTR(args[0]);
+ pin_p = (mp_pin_p_t*)pin_base->type->protocol;
+ }
+
+ if (pin_p == NULL) {
+ // If first argument isn't a Pin-like object, we filter out "inverted"
+ // from keyword arguments and pass them all to the exported Pin
+ // constructor to create one.
+ mp_obj_t pin_args[n_args + n_kw * 2];
+ memcpy(pin_args, args, n_args * sizeof(mp_obj_t));
+ const mp_obj_t *src = args + n_args;
+ mp_obj_t *dst = pin_args + n_args;
+ mp_obj_t *sig_value = NULL;
+ for (size_t cnt = n_kw; cnt; cnt--) {
+ if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) {
+ inverted = mp_obj_is_true(src[1]);
+ n_kw--;
+ } else {
+ *dst++ = *src;
+ *dst++ = src[1];
+ }
+ if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_value)) {
+ // Value is pertained to Signal, so we should invert
+ // it for Pin if needed, and we should do it only when
+ // inversion status is guaranteedly known.
+ sig_value = dst - 1;
+ }
+ src += 2;
+ }
- mp_arg_val_t parsed_args[MP_ARRAY_SIZE(allowed_args)];
+ if (inverted && sig_value != NULL) {
+ *sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1);
+ }
- mp_arg_parse_all_kw_array(n_args, n_kw, args, MP_ARRAY_SIZE(allowed_args), allowed_args, parsed_args);
+ // Here we pass NULL as a type, hoping that mp_pin_make_new()
+ // will just ignore it as set a concrete type. If not, we'd need
+ // to expose port's "default" pin type too.
+ pin = MICROPY_PY_MACHINE_PIN_MAKE_NEW(NULL, n_args, n_kw, pin_args);
+ }
+ else
+ #endif
+ // Otherwise there should be 1 or 2 args
+ {
+ if (n_args == 1) {
+ if (n_kw == 0) {
+ } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) {
+ inverted = mp_obj_is_true(args[1]);
+ } else {
+ goto error;
+ }
+ } else {
+ error:
+ mp_raise_TypeError(NULL);
+ }
+ }
machine_signal_t *o = m_new_obj(machine_signal_t);
o->base.type = type;
- o->pin = parsed_args[ARG_pin].u_obj;
- o->inverted = parsed_args[ARG_inverted].u_bool;
+ o->pin = pin;
+ o->inverted = inverted;
return MP_OBJ_FROM_PTR(o);
}
diff --git a/extmod/virtpin.h b/extmod/virtpin.h
index 3821f9dec..041010350 100644
--- a/extmod/virtpin.h
+++ b/extmod/virtpin.h
@@ -38,3 +38,6 @@ typedef struct _mp_pin_p_t {
int mp_virtual_pin_read(mp_obj_t pin);
void mp_virtual_pin_write(mp_obj_t pin, int value);
+
+// If a port exposes a Pin object, it's constructor should be like this
+mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args);
From 747cbbcbf64e725402f0f3b36136eea92f51b427 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 11 Apr 2017 12:58:23 +1000
Subject: [PATCH 049/826] esp32: Update to latest ESP IDF.
---
esp32/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp32/Makefile b/esp32/Makefile
index 2564aee21..a3d5f8f72 100644
--- a/esp32/Makefile
+++ b/esp32/Makefile
@@ -29,7 +29,7 @@ ESPCOMP = $(ESPIDF)/components
ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py
# verify the ESP IDF version
-ESPIDF_SUPHASH := 47b8f78cb0e15fa43647788a808dac353167a485
+ESPIDF_SUPHASH := 375b28650bd1c90d6ac706f63cde9a64d9a7e3e5
ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H')
ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH))
$(info ** WARNING **)
From 9156c8b460a4b013312466744b47bc4bb5506269 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 11 Apr 2017 13:12:54 +1000
Subject: [PATCH 050/826] stmhal: Enable parsing of all Pin constructor args by
machine.Signal.
---
stmhal/mpconfigport.h | 1 +
stmhal/pin.c | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 3f3683199..2186e2ed6 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -123,6 +123,7 @@
#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_MACHINE (1)
#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_PY_MACHINE_PIN_MAKE_NEW mp_pin_make_new
#define MICROPY_PY_MACHINE_I2C (1)
#define MICROPY_PY_MACHINE_I2C_MAKE_NEW machine_hard_i2c_make_new
#define MICROPY_PY_MACHINE_SPI (1)
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 29370e6a2..845126e28 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -245,7 +245,7 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *pin, mp_uint_t n_args, cons
/// \classmethod \constructor(id, ...)
/// Create a new Pin object associated with the id. If additional arguments are given,
/// they are used to initialise the pin. See `init`.
-STATIC mp_obj_t pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
+mp_obj_t mp_pin_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 1, MP_OBJ_FUN_ARGS_MAX, true);
// Run an argument through the mapper and return the result.
@@ -567,7 +567,7 @@ const mp_obj_type_t pin_type = {
{ &mp_type_type },
.name = MP_QSTR_Pin,
.print = pin_print,
- .make_new = pin_make_new,
+ .make_new = mp_pin_make_new,
.call = pin_call,
.protocol = &pin_pin_p,
.locals_dict = (mp_obj_t)&pin_locals_dict,
From 6c564aa408faf5d2769785b7ffc438a489310c3b Mon Sep 17 00:00:00 2001
From: Damien George
Date: Mon, 10 Apr 2017 17:17:22 +1000
Subject: [PATCH 051/826] unix, windows: Use core-provided KeyboardInterrupt
exception object.
---
unix/main.c | 3 ---
unix/mpconfigport.h | 2 +-
unix/mpconfigport_minimal.h | 2 +-
unix/unix_mphal.c | 10 +++++-----
windows/mpconfigport.h | 4 ++--
windows/windows_mphal.c | 6 +++---
6 files changed, 12 insertions(+), 15 deletions(-)
diff --git a/unix/main.c b/unix/main.c
index a1c204cab..edea7900d 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -425,9 +425,6 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_init();
- // create keyboard interrupt object
- MP_STATE_VM(keyboard_interrupt_obj) = mp_obj_new_exception(&mp_type_KeyboardInterrupt);
-
char *home = getenv("HOME");
char *path = getenv("MICROPYPATH");
if (path == NULL) {
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 7ecfc28c0..4067e1950 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -156,6 +156,7 @@
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256)
+#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_ASYNC_KBD_INTR (1)
extern const struct _mp_obj_module_t mp_module_machine;
@@ -283,7 +284,6 @@ void mp_unix_mark_exec(void);
#define MICROPY_PORT_ROOT_POINTERS \
const char *readline_hist[50]; \
- mp_obj_t keyboard_interrupt_obj; \
void *mmap_region_head; \
// We need to provide a declaration/definition of alloca()
diff --git a/unix/mpconfigport_minimal.h b/unix/mpconfigport_minimal.h
index 788c8519d..b4d9f8143 100644
--- a/unix/mpconfigport_minimal.h
+++ b/unix/mpconfigport_minimal.h
@@ -47,6 +47,7 @@
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_TERSE)
#define MICROPY_WARNINGS (0)
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (0)
+#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_FLOAT_IMPL (MICROPY_FLOAT_IMPL_NONE)
#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_NONE)
#define MICROPY_STREAMS_NON_BLOCK (0)
@@ -99,7 +100,6 @@ extern const struct _mp_obj_module_t mp_module_os;
{ MP_OBJ_NEW_QSTR(MP_QSTR_uos), (mp_obj_t)&mp_module_os }, \
#define MICROPY_PORT_ROOT_POINTERS \
- mp_obj_t keyboard_interrupt_obj;
//////////////////////////////////////////
// Do not change anything beyond this line
diff --git a/unix/unix_mphal.c b/unix/unix_mphal.c
index 6c6666236..800484498 100644
--- a/unix/unix_mphal.c
+++ b/unix/unix_mphal.c
@@ -40,20 +40,20 @@
STATIC void sighandler(int signum) {
if (signum == SIGINT) {
#if MICROPY_ASYNC_KBD_INTR
- mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
+ mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
sigset_t mask;
sigemptyset(&mask);
// On entry to handler, its signal is blocked, and unblocked on
// normal exit. As we instead perform longjmp, unblock it manually.
sigprocmask(SIG_SETMASK, &mask, NULL);
- nlr_raise(MP_STATE_VM(keyboard_interrupt_obj));
+ nlr_raise(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
#else
- if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
+ if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
// this is the second time we are called, so die straight away
exit(1);
}
- mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
- MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
+ mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
#endif
}
}
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index 844e2618f..b91662af4 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -104,6 +104,7 @@
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256)
+#define MICROPY_KBD_EXCEPTION (1)
#define MICROPY_PORT_INIT_FUNC init()
#define MICROPY_PORT_DEINIT_FUNC deinit()
@@ -161,8 +162,7 @@ extern const struct _mp_obj_module_t mp_module_time;
#if MICROPY_USE_READLINE == 1
#define MICROPY_PORT_ROOT_POINTERS \
- char *readline_hist[50]; \
- mp_obj_t keyboard_interrupt_obj;
+ char *readline_hist[50];
#endif
#define MP_STATE_PORT MP_STATE_VM
diff --git a/windows/windows_mphal.c b/windows/windows_mphal.c
index 3ad693905..1dd3105d8 100644
--- a/windows/windows_mphal.c
+++ b/windows/windows_mphal.c
@@ -79,12 +79,12 @@ void mp_hal_stdio_mode_orig(void) {
// the thread created for handling it might not be running yet so we'd miss the notification.
BOOL WINAPI console_sighandler(DWORD evt) {
if (evt == CTRL_C_EVENT) {
- if (MP_STATE_VM(mp_pending_exception) == MP_STATE_VM(keyboard_interrupt_obj)) {
+ if (MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception))) {
// this is the second time we are called, so die straight away
exit(1);
}
- mp_obj_exception_clear_traceback(MP_STATE_VM(keyboard_interrupt_obj));
- MP_STATE_VM(mp_pending_exception) = MP_STATE_VM(keyboard_interrupt_obj);
+ mp_obj_exception_clear_traceback(MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception)));
+ MP_STATE_VM(mp_pending_exception) = MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_kbd_exception));
return TRUE;
}
return FALSE;
From f66df1efc85fe9fc7fd0b2125792d02001de48bb Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 11 Apr 2017 15:16:09 +1000
Subject: [PATCH 052/826] py/objint: Extract small int value directly because
type is known.
---
py/objint.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/py/objint.c b/py/objint.c
index 46f9b1666..719fd4970 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -224,7 +224,7 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co
fmt_int_t num;
if (MP_OBJ_IS_SMALL_INT(self_in)) {
// A small int; get the integer value to format.
- num = mp_obj_get_int(self_in);
+ num = MP_OBJ_SMALL_INT_VALUE(self_in);
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
} else if (MP_OBJ_IS_TYPE(self_in, &mp_type_int)) {
// Not a small int.
From e31fbd9b41315963aaca732e7585fc4cb10ccbcd Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 11 Apr 2017 15:18:35 +1000
Subject: [PATCH 053/826] py/objint: Use unsigned arithmetic when formatting an
integer.
Otherwise the edge case of the most negative integer value will not convert
correctly.
---
py/objint.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/py/objint.c b/py/objint.c
index 719fd4970..99c54a310 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -170,8 +170,10 @@ mp_obj_t mp_obj_new_int_from_float(mp_float_t val) {
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
typedef mp_longint_impl_t fmt_int_t;
+typedef unsigned long long fmt_uint_t;
#else
typedef mp_int_t fmt_int_t;
+typedef mp_uint_t fmt_uint_t;
#endif
void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
@@ -265,8 +267,9 @@ char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_co
*(--b) = '0';
} else {
do {
- int c = num % base;
- num /= base;
+ // The cast to fmt_uint_t is because num is positive and we want unsigned arithmetic
+ int c = (fmt_uint_t)num % base;
+ num = (fmt_uint_t)num / base;
if (c >= 10) {
c += base_char - 10;
} else {
From 81d302b8f8a9a6b1c3547b4d00fc938e4ff730b5 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 11 Apr 2017 15:24:33 +0300
Subject: [PATCH 054/826] zephyr/modusocket: Call net_nbuf_print_frags() in
recv callback if DEBUG > 1.
---
zephyr/modusocket.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 36ccdbc3b..0eb6e9dac 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -36,7 +36,8 @@
#include
#include
-#if 0 // print debugging info
+#define DEBUG 0
+#if DEBUG // print debugging info
#define DEBUG_printf printf
#else // don't print debugging info
#define DEBUG_printf(...) (void)0
@@ -144,6 +145,9 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
DEBUG_printf(" (sz=%d, l=%d), token: %p", net_buf->size, net_buf->len, net_nbuf_token(net_buf));
}
DEBUG_printf("\n");
+ #if DEBUG > 1
+ net_nbuf_print_frags(net_buf);
+ #endif
// if net_buf == NULL, EOF
if (net_buf == NULL) {
From dc82def1f482c17517e5bcaeae4191787623fa0e Mon Sep 17 00:00:00 2001
From: Daniel Campora
Date: Sat, 8 Apr 2017 23:20:59 +0200
Subject: [PATCH 055/826] esp32: Add threading implementation, disabled for the
time being.
---
esp32/Makefile | 1 +
esp32/mpthreadport.c | 226 +++++++++++++++++++++++++++++++++++++++++++
esp32/mpthreadport.h | 45 +++++++++
esp32/sdkconfig.h | 4 +-
4 files changed, 275 insertions(+), 1 deletion(-)
create mode 100644 esp32/mpthreadport.c
create mode 100644 esp32/mpthreadport.h
diff --git a/esp32/Makefile b/esp32/Makefile
index a3d5f8f72..5b42e479c 100644
--- a/esp32/Makefile
+++ b/esp32/Makefile
@@ -128,6 +128,7 @@ SRC_C = \
modesp.c \
espneopixel.c \
machine_hw_spi.c \
+ mpthreadport.c \
$(SRC_MOD)
STM_SRC_C = $(addprefix stmhal/,\
diff --git a/esp32/mpthreadport.c b/esp32/mpthreadport.c
new file mode 100644
index 000000000..76d9431c0
--- /dev/null
+++ b/esp32/mpthreadport.c
@@ -0,0 +1,226 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ * Copyright (c) 2017 Pycom Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "stdio.h"
+
+#include "py/mpconfig.h"
+#include "py/mpstate.h"
+#include "py/gc.h"
+#include "py/mpthread.h"
+#include "mpthreadport.h"
+
+#include "esp_task.h"
+
+#if MICROPY_PY_THREAD
+
+#define MP_THREAD_MIN_STACK_SIZE (4 * 1024)
+#define MP_THREAD_DEFAULT_STACK_SIZE (MP_THREAD_MIN_STACK_SIZE + 1024)
+#define MP_THREAD_PRIORITY (ESP_TASK_PRIO_MIN + 1)
+
+// this structure forms a linked list, one node per active thread
+typedef struct _thread_t {
+ TaskHandle_t id; // system id of thread
+ int ready; // whether the thread is ready and running
+ void *arg; // thread Python args, a GC root pointer
+ void *stack; // pointer to the stack
+ StaticTask_t *tcb; // pointer to the Task Control Block
+ size_t stack_len; // number of words in the stack
+ struct _thread_t *next;
+} thread_t;
+
+// the mutex controls access to the linked list
+STATIC mp_thread_mutex_t thread_mutex;
+STATIC thread_t thread_entry0;
+STATIC thread_t *thread; // root pointer, handled by mp_thread_gc_others
+
+void mp_thread_init(void *stack, uint32_t stack_len) {
+ mp_thread_set_state(&mp_state_ctx.thread);
+ // create the first entry in the linked list of all threads
+ thread = &thread_entry0;
+ thread->id = xTaskGetCurrentTaskHandle();
+ thread->ready = 1;
+ thread->arg = NULL;
+ thread->stack = stack;
+ thread->stack_len = stack_len;
+ thread->next = NULL;
+ mp_thread_mutex_init(&thread_mutex);
+}
+
+void mp_thread_gc_others(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ gc_collect_root((void**)&th, 1);
+ gc_collect_root(&th->arg, 1); // probably not needed
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ continue;
+ }
+ if (!th->ready) {
+ continue;
+ }
+ gc_collect_root(th->stack, th->stack_len); // probably not needed
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+mp_state_thread_t *mp_thread_get_state(void) {
+ return pvTaskGetThreadLocalStoragePointer(NULL, 1);
+}
+
+void mp_thread_set_state(void *state) {
+ vTaskSetThreadLocalStoragePointer(NULL, 1, state);
+}
+
+void mp_thread_start(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ th->ready = 1;
+ break;
+ }
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+STATIC void *(*ext_thread_entry)(void*) = NULL;
+
+STATIC void freertos_entry(void *arg) {
+ if (ext_thread_entry) {
+ ext_thread_entry(arg);
+ }
+ vTaskDelete(NULL);
+ for (;;);
+}
+
+void mp_thread_create_ex(void *(*entry)(void*), void *arg, size_t *stack_size, int priority, char *name) {
+ // store thread entry function into a global variable so we can access it
+ ext_thread_entry = entry;
+
+ if (*stack_size == 0) {
+ *stack_size = MP_THREAD_DEFAULT_STACK_SIZE; // default stack size
+ } else if (*stack_size < MP_THREAD_MIN_STACK_SIZE) {
+ *stack_size = MP_THREAD_MIN_STACK_SIZE; // minimum stack size
+ }
+
+ // allocate TCB, stack and linked-list node (must be outside thread_mutex lock)
+ StaticTask_t *tcb = m_new(StaticTask_t, 1);
+ StackType_t *stack = m_new(StackType_t, *stack_size / sizeof(StackType_t));
+ thread_t *th = m_new_obj(thread_t);
+
+ mp_thread_mutex_lock(&thread_mutex, 1);
+
+ // create thread
+ TaskHandle_t id = xTaskCreateStaticPinnedToCore(freertos_entry, name, *stack_size / sizeof(StackType_t), arg, priority, stack, tcb, 0);
+ if (id == NULL) {
+ mp_thread_mutex_unlock(&thread_mutex);
+ nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread"));
+ }
+
+ // adjust the stack_size to provide room to recover from hitting the limit
+ *stack_size -= 1024;
+
+ // add thread to linked list of all threads
+ th->id = id;
+ th->ready = 0;
+ th->arg = arg;
+ th->stack = stack;
+ th->tcb = tcb;
+ th->stack_len = *stack_size / sizeof(StackType_t);
+ th->next = thread;
+ thread = th;
+
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) {
+ mp_thread_create_ex(entry, arg, stack_size, MP_THREAD_PRIORITY, "mp_thread");
+}
+
+void mp_thread_finish(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ th->ready = 0;
+ break;
+ }
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+void vPortCleanUpTCB(void *tcb) {
+ thread_t *prev = NULL;
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; prev = th, th = th->next) {
+ // unlink the node from the list
+ if (th->tcb == tcb) {
+ if (prev != NULL) {
+ prev->next = th->next;
+ } else {
+ // move the start pointer
+ thread = th->next;
+ }
+ // explicitly release all its memory
+ m_del(StaticTask_t, th->tcb, 1);
+ m_del(StackType_t, th->stack, th->stack_len);
+ m_del(thread_t, th, 1);
+ break;
+ }
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+}
+
+void mp_thread_mutex_init(mp_thread_mutex_t *mutex) {
+ mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer);
+}
+
+int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) {
+ return (pdTRUE == xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0));
+}
+
+void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) {
+ xSemaphoreGive(mutex->handle);
+}
+
+void mp_thread_deinit(void) {
+ mp_thread_mutex_lock(&thread_mutex, 1);
+ for (thread_t *th = thread; th != NULL; th = th->next) {
+ // don't delete the current task
+ if (th->id == xTaskGetCurrentTaskHandle()) {
+ continue;
+ }
+ vTaskDelete(th->id);
+ }
+ mp_thread_mutex_unlock(&thread_mutex);
+ // allow FreeRTOS to clean-up the threads
+ vTaskDelay(2);
+}
+
+#else
+
+void vPortCleanUpTCB(void *tcb) {
+}
+
+#endif // MICROPY_PY_THREAD
diff --git a/esp32/mpthreadport.h b/esp32/mpthreadport.h
new file mode 100644
index 000000000..54e35d61c
--- /dev/null
+++ b/esp32/mpthreadport.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2016 Damien P. George on behalf of Pycom Ltd
+ * Copyright (c) 2017 Pycom Limited
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_ESP32_MPTHREADPORT_H
+#define MICROPY_INCLUDED_ESP32_MPTHREADPORT_H
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+
+typedef struct _mp_thread_mutex_t {
+ SemaphoreHandle_t handle;
+ StaticSemaphore_t buffer;
+} mp_thread_mutex_t;
+
+void mp_thread_init(void *stack, uint32_t stack_len);
+void mp_thread_gc_others(void);
+void mp_thread_deinit(void);
+
+#endif // MICROPY_INCLUDED_ESP32_MPTHREADPORT_H
diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h
index a7084dfb2..44bacd23c 100644
--- a/esp32/sdkconfig.h
+++ b/esp32/sdkconfig.h
@@ -36,10 +36,12 @@
#define CONFIG_FREERTOS_ASSERT_FAIL_ABORT 1
#define CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION 1
#define CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE 1
-#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 1
+#define CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS 2
#define CONFIG_FREERTOS_ISR_STACKSIZE 1536
#define CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG 1
#define CONFIG_FREERTOS_MAX_TASK_NAME_LEN 16
+#define CONFIG_SUPPORT_STATIC_ALLOCATION 1
+#define CONFIG_ENABLE_STATIC_TASK_CLEAN_UP_HOOK 1
#define CONFIG_MAIN_TASK_STACK_SIZE 4096
#define CONFIG_BTC_TASK_STACK_SIZE 3072
From f704375b2083863866502a5e3b67bfb6480af8b5 Mon Sep 17 00:00:00 2001
From: Daniel Campora
Date: Sat, 8 Apr 2017 23:24:04 +0200
Subject: [PATCH 056/826] esp32: Trace the registers when doing a gc collect.
Also make it thread ready.
---
esp32/gccollect.c | 42 ++++++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 16 deletions(-)
diff --git a/esp32/gccollect.c b/esp32/gccollect.c
index 3f1c4401a..9843cef00 100644
--- a/esp32/gccollect.c
+++ b/esp32/gccollect.c
@@ -6,6 +6,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
+ * Copyright (c) 2017 Pycom Limited
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -28,29 +29,38 @@
#include
+#include "py/mpconfig.h"
+#include "py/mpstate.h"
#include "py/gc.h"
+#include "py/mpthread.h"
#include "gccollect.h"
+#include "soc/cpu.h"
+#include "xtensa/hal.h"
-// As we do not have control over the application entry point, there is no way
-// to figure out the real stack base on runtime, so it needs to be hardcoded
-#define STACK_END 0x40000000
-mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs) {
- // TODO properly
- return (mp_uint_t)regs;
+static void gc_collect_inner(int level) {
+ if (level < XCHAL_NUM_AREGS / 8) {
+ gc_collect_inner(level + 1);
+ if (level != 0) {
+ return;
+ }
+ }
+
+ if (level == XCHAL_NUM_AREGS / 8) {
+ // get the sp
+ volatile uint32_t sp = (uint32_t)get_sp();
+ gc_collect_root((void**)sp, ((mp_uint_t)MP_STATE_THREAD(stack_top) - sp) / sizeof(uint32_t));
+ return;
+ }
+
+ // trace root pointers from any threads
+ #if MICROPY_PY_THREAD
+ mp_thread_gc_others();
+ #endif
}
void gc_collect(void) {
- // start the GC
gc_collect_start();
-
- // get the registers and the sp
- mp_uint_t regs[8];
- mp_uint_t sp = gc_helper_get_regs_and_sp(regs);
-
- // trace the stack, including the registers (since they live on the stack in this function)
- gc_collect_root((void**)sp, (STACK_END - sp) / sizeof(uint32_t));
-
- // end the GC
+ gc_collect_inner(0);
gc_collect_end();
}
From ff0ca1e782b3e6f3640b7ea2019f9ea716b2a52a Mon Sep 17 00:00:00 2001
From: Daniel Campora
Date: Sat, 8 Apr 2017 23:26:36 +0200
Subject: [PATCH 057/826] esp32: Enable threading; be sure to exit GIL when a
thread will block.
---
esp32/main.c | 25 ++++++++++++++++++-------
esp32/modnetwork.c | 4 ++++
esp32/modsocket.c | 20 +++++++++++++++++++-
esp32/mpconfigport.h | 14 ++++++++++++++
esp32/mphalport.c | 6 ++++++
5 files changed, 61 insertions(+), 8 deletions(-)
diff --git a/esp32/main.c b/esp32/main.c
index c20897a7b..dcd06a92b 100644
--- a/esp32/main.c
+++ b/esp32/main.c
@@ -34,6 +34,7 @@
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_task.h"
+#include "soc/cpu.h"
#include "py/stackctrl.h"
#include "py/nlr.h"
@@ -46,6 +47,7 @@
#include "lib/utils/pyexec.h"
#include "uart.h"
#include "modmachine.h"
+#include "mpthreadport.h"
// MicroPython runs as a task under FreeRTOS
#define MP_TASK_PRIORITY (ESP_TASK_PRIO_MIN + 1)
@@ -53,15 +55,21 @@
#define MP_TASK_STACK_LEN (MP_TASK_STACK_SIZE / sizeof(StackType_t))
#define MP_TASK_HEAP_SIZE (96 * 1024)
-//STATIC StaticTask_t mp_task_tcb;
-//STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
+STATIC StaticTask_t mp_task_tcb;
+STATIC StackType_t mp_task_stack[MP_TASK_STACK_LEN] __attribute__((aligned (8)));
STATIC uint8_t mp_task_heap[MP_TASK_HEAP_SIZE];
void mp_task(void *pvParameter) {
+ volatile uint32_t sp = (uint32_t)get_sp();
+ #if MICROPY_PY_THREAD
+ mp_thread_init(&mp_task_stack[0], MP_TASK_STACK_LEN);
+ #endif
uart_init();
+
soft_reset:
- mp_stack_set_top((void*)&pvParameter);
- mp_stack_set_limit(MP_TASK_STACK_SIZE - 512);
+ // initialise the stack pointer for the main thread
+ mp_stack_set_top((void *)sp);
+ mp_stack_set_limit(MP_TASK_STACK_SIZE - 1024);
gc_init(mp_task_heap, mp_task_heap + sizeof(mp_task_heap));
mp_init();
mp_obj_list_init(mp_sys_path, 0);
@@ -92,6 +100,10 @@ void mp_task(void *pvParameter) {
}
}
+ #if MICROPY_PY_THREAD
+ mp_thread_deinit();
+ #endif
+
mp_hal_stdout_tx_str("PYB: soft reboot\r\n");
// deinitialise peripherals
@@ -104,9 +116,8 @@ void mp_task(void *pvParameter) {
void app_main(void) {
nvs_flash_init();
- // TODO use xTaskCreateStatic (needs custom FreeRTOSConfig.h)
- xTaskCreatePinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, NULL, 0);
- //xTaskCreateStatic(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY, &mp_task_stack[0], &mp_task_tcb);
+ xTaskCreateStaticPinnedToCore(mp_task, "mp_task", MP_TASK_STACK_LEN, NULL, MP_TASK_PRIORITY,
+ &mp_task_stack[0], &mp_task_tcb, 0);
}
void nlr_jump_fail(void *val) {
diff --git a/esp32/modnetwork.c b/esp32/modnetwork.c
index bb42defd0..5cac3ee85 100644
--- a/esp32/modnetwork.c
+++ b/esp32/modnetwork.c
@@ -241,7 +241,9 @@ STATIC mp_obj_t esp_connect(size_t n_args, const mp_obj_t *args) {
memcpy(wifi_sta_config.sta.password, p, MIN(len, sizeof(wifi_sta_config.sta.password)));
ESP_EXCEPTIONS( esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_sta_config) );
}
+ MP_THREAD_GIL_EXIT();
ESP_EXCEPTIONS( esp_wifi_connect() );
+ MP_THREAD_GIL_ENTER();
wifi_sta_connected = true;
return mp_const_none;
@@ -274,7 +276,9 @@ STATIC mp_obj_t esp_scan(mp_obj_t self_in) {
mp_obj_t list = mp_obj_new_list(0, NULL);
wifi_scan_config_t config = { 0 };
// XXX how do we scan hidden APs (and if we can scan them, are they really hidden?)
+ MP_THREAD_GIL_EXIT();
esp_err_t status = esp_wifi_scan_start(&config, 1);
+ MP_THREAD_GIL_ENTER();
if (status == 0) {
uint16_t count = 0;
ESP_EXCEPTIONS( esp_wifi_scan_get_ap_num(&count) );
diff --git a/esp32/modsocket.c b/esp32/modsocket.c
index c6f96a459..5d554b764 100644
--- a/esp32/modsocket.c
+++ b/esp32/modsocket.c
@@ -112,7 +112,11 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
const char *host_str = mp_obj_str_get_data(host, &host_len);
const char *port_str = mp_obj_str_get_data(port, &port_len);
- return lwip_getaddrinfo(host_str, port_str, &hints, resp);
+ MP_THREAD_GIL_EXIT();
+ int res = lwip_getaddrinfo(host_str, port_str, &hints, resp);
+ MP_THREAD_GIL_ENTER();
+
+ return res;
}
int _socket_getaddrinfo(const mp_obj_t addrtuple, struct addrinfo **resp) {
@@ -151,7 +155,9 @@ STATIC mp_obj_t socket_accept(const mp_obj_t arg0) {
int new_fd = -1;
for (int i=0; i<=self->retries; i++) {
+ MP_THREAD_GIL_EXIT();
new_fd = lwip_accept_r(self->fd, &addr, &addr_len);
+ MP_THREAD_GIL_ENTER();
if (new_fd >= 0) break;
if (errno != EAGAIN) exception_from_errno(errno);
check_for_exceptions();
@@ -182,7 +188,9 @@ STATIC mp_obj_t socket_connect(const mp_obj_t arg0, const mp_obj_t arg1) {
socket_obj_t *self = MP_OBJ_TO_PTR(arg0);
struct addrinfo *res;
_socket_getaddrinfo(arg1, &res);
+ MP_THREAD_GIL_EXIT();
int r = lwip_connect_r(self->fd, res->ai_addr, res->ai_addrlen);
+ MP_THREAD_GIL_ENTER();
lwip_freeaddrinfo(res);
if (r != 0) {
exception_from_errno(errno);
@@ -255,7 +263,9 @@ mp_obj_t _socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in,
// XXX Would be nicer to use RTC to handle timeouts
for (int i=0; i<=sock->retries; i++) {
+ MP_THREAD_GIL_EXIT();
int r = lwip_recvfrom_r(sock->fd, vstr.buf, len, 0, from, from_len);
+ MP_THREAD_GIL_ENTER();
if (r >= 0) { vstr.len = r; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
if (errno != EWOULDBLOCK) exception_from_errno(errno);
check_for_exceptions();
@@ -286,7 +296,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recvfrom_obj, socket_recvfrom);
int _socket_send(socket_obj_t *sock, const char *data, size_t datalen) {
int sentlen = 0;
for (int i=0; iretries && sentlen < datalen; i++) {
+ MP_THREAD_GIL_EXIT();
int r = lwip_write_r(sock->fd, data+sentlen, datalen-sentlen);
+ MP_THREAD_GIL_ENTER();
if (r < 0 && errno != EWOULDBLOCK) exception_from_errno(errno);
if (r > 0) sentlen += r;
check_for_exceptions();
@@ -331,7 +343,9 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
// send the data
for (int i=0; iretries; i++) {
+ MP_THREAD_GIL_EXIT();
int ret = lwip_sendto_r(self->fd, bufinfo.buf, bufinfo.len, 0, (struct sockaddr*)&to, sizeof(to));
+ MP_THREAD_GIL_ENTER();
if (ret > 0) return mp_obj_new_int_from_uint(ret);
if (ret == -1 && errno != EWOULDBLOCK) {
exception_from_errno(errno);
@@ -364,7 +378,9 @@ STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size,
// XXX Would be nicer to use RTC to handle timeouts
for (int i=0; i<=sock->retries; i++) {
+ MP_THREAD_GIL_EXIT();
int x = lwip_recvfrom_r(sock->fd, buf, size, 0, NULL, NULL);
+ MP_THREAD_GIL_ENTER();
if (x >= 0) return x;
if (x < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
check_for_exceptions();
@@ -375,7 +391,9 @@ STATIC mp_uint_t socket_stream_read(mp_obj_t self_in, void *buf, mp_uint_t size,
STATIC mp_uint_t socket_stream_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
socket_obj_t *sock = self_in;
for (int i=0; iretries; i++) {
+ MP_THREAD_GIL_EXIT();
int r = lwip_write_r(sock->fd, buf, size);
+ MP_THREAD_GIL_ENTER();
if (r > 0) return r;
if (r < 0 && errno != EWOULDBLOCK) { *errcode = errno; return MP_STREAM_ERROR; }
check_for_exceptions();
diff --git a/esp32/mpconfigport.h b/esp32/mpconfigport.h
index b08fa726c..ee2e27c15 100644
--- a/esp32/mpconfigport.h
+++ b/esp32/mpconfigport.h
@@ -108,6 +108,9 @@
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_USELECT (1)
#define MICROPY_PY_UTIME_MP_HAL (1)
+#define MICROPY_PY_THREAD (1)
+#define MICROPY_PY_THREAD_GIL (1)
+#define MICROPY_PY_THREAD_GIL_VM_DIVISOR (32)
// extended modules
#define MICROPY_PY_UCTYPES (1)
@@ -202,12 +205,23 @@ extern const struct _mp_obj_module_t mp_module_network;
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void*)((mp_uint_t)(p)))
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define MP_SSIZE_MAX (0x7fffffff)
+
+#if MICROPY_PY_THREAD
+#define MICROPY_EVENT_POLL_HOOK \
+ do { \
+ extern void mp_handle_pending(void); \
+ mp_handle_pending(); \
+ MP_THREAD_GIL_EXIT(); \
+ MP_THREAD_GIL_ENTER(); \
+ } while (0);
+#else
#define MICROPY_EVENT_POLL_HOOK \
do { \
extern void mp_handle_pending(void); \
mp_handle_pending(); \
asm("waiti 0"); \
} while (0);
+#endif
#define UINT_FMT "%u"
#define INT_FMT "%d"
diff --git a/esp32/mphalport.c b/esp32/mphalport.c
index 1a0b2b5ad..e588fc65a 100644
--- a/esp32/mphalport.c
+++ b/esp32/mphalport.c
@@ -59,24 +59,30 @@ void mp_hal_stdout_tx_char(char c) {
}
void mp_hal_stdout_tx_str(const char *str) {
+ MP_THREAD_GIL_EXIT();
while (*str) {
mp_hal_stdout_tx_char(*str++);
}
+ MP_THREAD_GIL_ENTER();
}
void mp_hal_stdout_tx_strn(const char *str, uint32_t len) {
+ MP_THREAD_GIL_EXIT();
while (len--) {
mp_hal_stdout_tx_char(*str++);
}
+ MP_THREAD_GIL_ENTER();
}
void mp_hal_stdout_tx_strn_cooked(const char *str, uint32_t len) {
+ MP_THREAD_GIL_EXIT();
while (len--) {
if (*str == '\n') {
mp_hal_stdout_tx_char('\r');
}
mp_hal_stdout_tx_char(*str++);
}
+ MP_THREAD_GIL_ENTER();
}
uint32_t mp_hal_ticks_ms(void) {
From 05520cbfbd9ab7e4b86f71a6594b05ae785c4652 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 12:48:02 +1000
Subject: [PATCH 058/826] esp32/main: Restart the MCU if there is a failed NLR
jump.
---
esp32/main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/esp32/main.c b/esp32/main.c
index dcd06a92b..bc63ce00c 100644
--- a/esp32/main.c
+++ b/esp32/main.c
@@ -122,8 +122,7 @@ void app_main(void) {
void nlr_jump_fail(void *val) {
printf("NLR jump failed, val=%p\n", val);
- for (;;) {
- }
+ esp_restart();
}
// modussl_mbedtls uses this function but it's not enabled in ESP IDF
From 74b102bdf7c6429207c9fb0a5890b4173b2f811a Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 12:51:00 +1000
Subject: [PATCH 059/826] esp32/mpconfigport.h: Provide ATOMIC_SECTION macros.
---
esp32/mpconfigport.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/esp32/mpconfigport.h b/esp32/mpconfigport.h
index ee2e27c15..741a81617 100644
--- a/esp32/mpconfigport.h
+++ b/esp32/mpconfigport.h
@@ -206,6 +206,13 @@ extern const struct _mp_obj_module_t mp_module_network;
#define MP_PLAT_PRINT_STRN(str, len) mp_hal_stdout_tx_strn_cooked(str, len)
#define MP_SSIZE_MAX (0x7fffffff)
+// Note: these "critical nested" macros do not ensure cross-CPU exclusion,
+// the only disable interrupts on the current CPU. To full manage exclusion
+// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
+#include "freertos/FreeRTOS.h"
+#define MICROPY_BEGIN_ATOMIC_SECTION() portENTER_CRITICAL_NESTED()
+#define MICROPY_END_ATOMIC_SECTION(state) portEXIT_CRITICAL_NESTED(state)
+
#if MICROPY_PY_THREAD
#define MICROPY_EVENT_POLL_HOOK \
do { \
From 47174e1f556fba87738151b7e5b074462d59ca62 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 13:11:24 +1000
Subject: [PATCH 060/826] esp32: Remove enable_irq/disable_irq and use
ATOMIC_SECTION instead.
There's really no need to have these aliases.
---
esp32/esponewire.c | 12 ++++++------
esp32/modmachine.c | 4 ++--
esp32/mphalport.h | 11 ++---------
3 files changed, 10 insertions(+), 17 deletions(-)
diff --git a/esp32/esponewire.c b/esp32/esponewire.c
index 4c1c0719b..781616cbe 100644
--- a/esp32/esponewire.c
+++ b/esp32/esponewire.c
@@ -44,30 +44,30 @@ uint16_t esp_onewire_timings[9] = {480, 40, 420, 5, 5, 40, 10, 50, 10};
int esp_onewire_reset(mp_hal_pin_obj_t pin) {
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_RESET1]);
- uint32_t i = disable_irq();
+ uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_RESET2]);
int status = !mp_hal_pin_read(pin);
- enable_irq(i);
+ MICROPY_END_ATOMIC_SECTION(i);
DELAY_US(esp_onewire_timings[TIMING_RESET3]);
return status;
}
int esp_onewire_readbit(mp_hal_pin_obj_t pin) {
mp_hal_pin_write(pin, 1);
- uint32_t i = disable_irq();
+ uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_READ1]);
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_READ2]);
int value = mp_hal_pin_read(pin);
- enable_irq(i);
+ MICROPY_END_ATOMIC_SECTION(i);
DELAY_US(esp_onewire_timings[TIMING_READ3]);
return value;
}
void esp_onewire_writebit(mp_hal_pin_obj_t pin, int value) {
- uint32_t i = disable_irq();
+ uint32_t i = MICROPY_BEGIN_ATOMIC_SECTION();
mp_hal_pin_write(pin, 0);
DELAY_US(esp_onewire_timings[TIMING_WRITE1]);
if (value) {
@@ -76,5 +76,5 @@ void esp_onewire_writebit(mp_hal_pin_obj_t pin, int value) {
DELAY_US(esp_onewire_timings[TIMING_WRITE2]);
mp_hal_pin_write(pin, 1);
DELAY_US(esp_onewire_timings[TIMING_WRITE3]);
- enable_irq(i);
+ MICROPY_END_ATOMIC_SECTION(i);
}
diff --git a/esp32/modmachine.c b/esp32/modmachine.c
index 24cb66699..0fb456ae7 100644
--- a/esp32/modmachine.c
+++ b/esp32/modmachine.c
@@ -77,14 +77,14 @@ STATIC mp_obj_t machine_idle(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_idle_obj, machine_idle);
STATIC mp_obj_t machine_disable_irq(void) {
- uint32_t state = disable_irq();
+ uint32_t state = MICROPY_BEGIN_ATOMIC_SECTION();
return mp_obj_new_int(state);
}
MP_DEFINE_CONST_FUN_OBJ_0(machine_disable_irq_obj, machine_disable_irq);
STATIC mp_obj_t machine_enable_irq(mp_obj_t state_in) {
uint32_t state = mp_obj_get_int(state_in);
- enable_irq(state);
+ MICROPY_END_ATOMIC_SECTION(state);
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(machine_enable_irq_obj, machine_enable_irq);
diff --git a/esp32/mphalport.h b/esp32/mphalport.h
index f51df05ae..8a0f1dc8b 100644
--- a/esp32/mphalport.h
+++ b/esp32/mphalport.h
@@ -29,18 +29,11 @@
#ifndef INCLUDED_MPHALPORT_H
#define INCLUDED_MPHALPORT_H
-#include "freertos/FreeRTOS.h"
#include "py/ringbuf.h"
#include "lib/utils/interrupt_char.h"
extern ringbuf_t stdin_ringbuf;
-// Note: these "critical nested" macros do not ensure cross-CPU exclusion,
-// the only disable interrupts on the current CPU. To full manage exclusion
-// one should use portENTER_CRITICAL/portEXIT_CRITICAL instead.
-#define disable_irq() portENTER_CRITICAL_NESTED()
-#define enable_irq(irq_state) portEXIT_CRITICAL_NESTED(irq_state)
-
uint32_t mp_hal_ticks_us(void);
__attribute__((always_inline)) static inline uint32_t mp_hal_ticks_cpu(void) {
uint32_t ccount;
@@ -53,8 +46,8 @@ void mp_hal_delay_us_fast(uint32_t);
void mp_hal_set_interrupt_char(int c);
uint32_t mp_hal_get_cpu_freq(void);
-#define mp_hal_quiet_timing_enter() disable_irq()
-#define mp_hal_quiet_timing_exit(irq_state) enable_irq(irq_state)
+#define mp_hal_quiet_timing_enter() MICROPY_BEGIN_ATOMIC_SECTION()
+#define mp_hal_quiet_timing_exit(irq_state) MICROPY_END_ATOMIC_SECTION(irq_state)
// C-level pin HAL
#include "py/obj.h"
From fc710169b7fd8738b285c141f1850b262b26c622 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Thu, 6 Apr 2017 10:25:32 +1000
Subject: [PATCH 061/826] py/obj: Clean up and add comments describing
mp_obj_type_t struct.
---
py/obj.h | 55 ++++++++++++++++++++++++++++++++-----------------------
1 file changed, 32 insertions(+), 23 deletions(-)
diff --git a/py/obj.h b/py/obj.h
index 49ba645f7..45579ce8f 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -470,16 +470,27 @@ typedef struct _mp_stream_p_t {
} mp_stream_p_t;
struct _mp_obj_type_t {
+ // A type is an object so must start with this entry, which points to mp_type_type.
mp_obj_base_t base;
+
+ // The name of this type.
qstr name;
+
+ // Corresponds to __repr__ and __str__ special methods.
mp_print_fun_t print;
- mp_make_new_fun_t make_new; // to make an instance of the type
+ // Corresponds to __new__ and __init__ special methods, to make an instance of the type.
+ mp_make_new_fun_t make_new;
+
+ // Corresponds to __call__ special method, ie T(...).
mp_call_fun_t call;
- mp_unary_op_fun_t unary_op; // can return MP_OBJ_NULL if op not supported
- mp_binary_op_fun_t binary_op; // can return MP_OBJ_NULL if op not supported
- // implements load, store and delete attribute
+ // Implements unary and binary operations.
+ // Can return MP_OBJ_NULL if the operation is not supported.
+ mp_unary_op_fun_t unary_op;
+ mp_binary_op_fun_t binary_op;
+
+ // Implements load, store and delete attribute.
//
// dest[0] = MP_OBJ_NULL means load
// return: for fail, do nothing
@@ -492,35 +503,33 @@ struct _mp_obj_type_t {
// for success set dest[0] = MP_OBJ_NULL
mp_attr_fun_t attr;
- mp_subscr_fun_t subscr; // implements load, store, delete subscripting
- // value=MP_OBJ_NULL means delete, value=MP_OBJ_SENTINEL means load, else store
- // can return MP_OBJ_NULL if op not supported
+ // Implements load, store and delete subscripting:
+ // - value = MP_OBJ_SENTINEL means load
+ // - value = MP_OBJ_NULL means delete
+ // - all other values mean store the value
+ // Can return MP_OBJ_NULL if operation not supported.
+ mp_subscr_fun_t subscr;
- // corresponds to __iter__ special method
- // can use given mp_obj_iter_buf_t to store iterator
- // otherwise can return a pointer to an object on the heap
+ // Corresponds to __iter__ special method.
+ // Can use the given mp_obj_iter_buf_t to store iterator object,
+ // otherwise can return a pointer to an object on the heap.
mp_getiter_fun_t getiter;
- mp_fun_1_t iternext; // may return MP_OBJ_STOP_ITERATION as an optimisation instead of raising StopIteration() (with no args)
+ // Corresponds to __next__ special method. May return MP_OBJ_STOP_ITERATION
+ // as an optimisation instead of raising StopIteration() with no args.
+ mp_fun_1_t iternext;
+ // Implements the buffer protocol if supported by this type.
mp_buffer_p_t buffer_p;
+
// One of disjoint protocols (interfaces), like mp_stream_p_t, etc.
const void *protocol;
- // these are for dynamically created types (classes)
+ // A tuple containing all the base types of this type.
struct _mp_obj_tuple_t *bases_tuple;
- struct _mp_obj_dict_t *locals_dict;
-
- /*
- What we might need to add here:
- len str tuple list map
- abs float complex
- hash bool int none str
- equal int str
-
- unpack seq list tuple
- */
+ // A dict mapping qstrs to objects local methods/constants/etc.
+ struct _mp_obj_dict_t *locals_dict;
};
// Constant types, globally accessible
From 816413e4b20ccd463321558458bb63c310712bca Mon Sep 17 00:00:00 2001
From: Damien George
Date: Thu, 6 Apr 2017 12:09:01 +1000
Subject: [PATCH 062/826] py: Optimise types for common case where type has a
single parent type.
The common cases for inheritance are 0 or 1 parent types, for both built-in
types (eg built-in exceptions) as well as user defined types. So it makes
sense to optimise the case of 1 parent type by storing just the type and
not a tuple of 1 value (that value being the single parent type).
This patch makes such an optimisation. Even though there is a bit more
code to handle the two cases (either a single type or a tuple with 2 or
more values) it helps reduce overall code size because it eliminates the
need to create a static tuple to hold single parents (eg for the built-in
exceptions). It also helps reduce RAM usage for user defined types that
only derive from a single parent.
Changes in code size (in bytes) due to this patch:
bare-arm: -16
minimal (x86): -176
unix (x86-64): -320
unix nanbox: -384
stmhal: -64
cc3200: -32
esp8266: -108
---
py/obj.h | 7 +-
py/objdict.c | 4 +-
py/objexcept.c | 17 +----
py/objnamedtuple.c | 4 +-
py/objtype.c | 166 +++++++++++++++++++++++++--------------------
5 files changed, 102 insertions(+), 96 deletions(-)
diff --git a/py/obj.h b/py/obj.h
index 45579ce8f..597c7c8d9 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -525,8 +525,11 @@ struct _mp_obj_type_t {
// One of disjoint protocols (interfaces), like mp_stream_p_t, etc.
const void *protocol;
- // A tuple containing all the base types of this type.
- struct _mp_obj_tuple_t *bases_tuple;
+ // A pointer to the parents of this type:
+ // - 0 parents: pointer is NULL (object is implicitly the single parent)
+ // - 1 parent: a pointer to the type of that parent
+ // - 2 or more parents: pointer to a tuple object containing the parent types
+ const void *parent;
// A dict mapping qstrs to objects local methods/constants/etc.
struct _mp_obj_dict_t *locals_dict;
diff --git a/py/objdict.c b/py/objdict.c
index f6929d23f..12ba61b2e 100644
--- a/py/objdict.c
+++ b/py/objdict.c
@@ -577,8 +577,6 @@ const mp_obj_type_t mp_type_dict = {
};
#if MICROPY_PY_COLLECTIONS_ORDEREDDICT
-STATIC const mp_rom_obj_tuple_t ordereddict_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_dict)}};
-
const mp_obj_type_t mp_type_ordereddict = {
{ &mp_type_type },
.name = MP_QSTR_OrderedDict,
@@ -588,7 +586,7 @@ const mp_obj_type_t mp_type_ordereddict = {
.binary_op = dict_binary_op,
.subscr = dict_subscr,
.getiter = dict_getiter,
- .bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&ordereddict_base_tuple,
+ .parent = &mp_type_dict,
.locals_dict = (mp_obj_dict_t*)&dict_locals_dict,
};
#endif
diff --git a/py/objexcept.c b/py/objexcept.c
index dcc7800dc..4722aca91 100644
--- a/py/objexcept.c
+++ b/py/objexcept.c
@@ -197,9 +197,6 @@ const mp_obj_type_t mp_type_BaseException = {
.locals_dict = (mp_obj_dict_t*)&exc_locals_dict,
};
-#define MP_DEFINE_EXCEPTION_BASE(base_name) \
-STATIC const mp_rom_obj_tuple_t mp_type_ ## base_name ## _base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_ ## base_name)}};\
-
#define MP_DEFINE_EXCEPTION(exc_name, base_name) \
const mp_obj_type_t mp_type_ ## exc_name = { \
{ &mp_type_type }, \
@@ -207,23 +204,20 @@ const mp_obj_type_t mp_type_ ## exc_name = { \
.print = mp_obj_exception_print, \
.make_new = mp_obj_exception_make_new, \
.attr = exception_attr, \
- .bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&mp_type_ ## base_name ## _base_tuple, \
+ .parent = &mp_type_ ## base_name, \
};
// List of all exceptions, arranged as in the table at:
// http://docs.python.org/3/library/exceptions.html
-MP_DEFINE_EXCEPTION_BASE(BaseException)
MP_DEFINE_EXCEPTION(SystemExit, BaseException)
MP_DEFINE_EXCEPTION(KeyboardInterrupt, BaseException)
MP_DEFINE_EXCEPTION(GeneratorExit, BaseException)
MP_DEFINE_EXCEPTION(Exception, BaseException)
- MP_DEFINE_EXCEPTION_BASE(Exception)
#if MICROPY_PY_ASYNC_AWAIT
MP_DEFINE_EXCEPTION(StopAsyncIteration, Exception)
#endif
MP_DEFINE_EXCEPTION(StopIteration, Exception)
MP_DEFINE_EXCEPTION(ArithmeticError, Exception)
- MP_DEFINE_EXCEPTION_BASE(ArithmeticError)
//MP_DEFINE_EXCEPTION(FloatingPointError, ArithmeticError)
MP_DEFINE_EXCEPTION(OverflowError, ArithmeticError)
MP_DEFINE_EXCEPTION(ZeroDivisionError, ArithmeticError)
@@ -235,18 +229,15 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(ImportError, Exception)
//MP_DEFINE_EXCEPTION(IOError, Exception) use OSError instead
MP_DEFINE_EXCEPTION(LookupError, Exception)
- MP_DEFINE_EXCEPTION_BASE(LookupError)
MP_DEFINE_EXCEPTION(IndexError, LookupError)
MP_DEFINE_EXCEPTION(KeyError, LookupError)
MP_DEFINE_EXCEPTION(MemoryError, Exception)
MP_DEFINE_EXCEPTION(NameError, Exception)
/*
- MP_DEFINE_EXCEPTION_BASE(NameError)
MP_DEFINE_EXCEPTION(UnboundLocalError, NameError)
*/
MP_DEFINE_EXCEPTION(OSError, Exception)
#if MICROPY_PY_BUILTINS_TIMEOUTERROR
- MP_DEFINE_EXCEPTION_BASE(OSError)
MP_DEFINE_EXCEPTION(TimeoutError, OSError)
#endif
/*
@@ -267,30 +258,24 @@ MP_DEFINE_EXCEPTION(Exception, BaseException)
MP_DEFINE_EXCEPTION(ReferenceError, Exception)
*/
MP_DEFINE_EXCEPTION(RuntimeError, Exception)
- MP_DEFINE_EXCEPTION_BASE(RuntimeError)
MP_DEFINE_EXCEPTION(NotImplementedError, RuntimeError)
MP_DEFINE_EXCEPTION(SyntaxError, Exception)
- MP_DEFINE_EXCEPTION_BASE(SyntaxError)
MP_DEFINE_EXCEPTION(IndentationError, SyntaxError)
/*
- MP_DEFINE_EXCEPTION_BASE(IndentationError)
MP_DEFINE_EXCEPTION(TabError, IndentationError)
*/
//MP_DEFINE_EXCEPTION(SystemError, Exception)
MP_DEFINE_EXCEPTION(TypeError, Exception)
#if MICROPY_EMIT_NATIVE
- MP_DEFINE_EXCEPTION_BASE(TypeError)
MP_DEFINE_EXCEPTION(ViperTypeError, TypeError)
#endif
MP_DEFINE_EXCEPTION(ValueError, Exception)
#if MICROPY_PY_BUILTINS_STR_UNICODE
- MP_DEFINE_EXCEPTION_BASE(ValueError)
MP_DEFINE_EXCEPTION(UnicodeError, ValueError)
//TODO: Implement more UnicodeError subclasses which take arguments
#endif
/*
MP_DEFINE_EXCEPTION(Warning, Exception)
- MP_DEFINE_EXCEPTION_BASE(Warning)
MP_DEFINE_EXCEPTION(DeprecationWarning, Warning)
MP_DEFINE_EXCEPTION(PendingDeprecationWarning, Warning)
MP_DEFINE_EXCEPTION(RuntimeWarning, Warning)
diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c
index 52468747b..cbd845dce 100644
--- a/py/objnamedtuple.c
+++ b/py/objnamedtuple.c
@@ -134,8 +134,6 @@ STATIC mp_obj_t namedtuple_make_new(const mp_obj_type_t *type_in, size_t n_args,
return MP_OBJ_FROM_PTR(tuple);
}
-STATIC const mp_rom_obj_tuple_t namedtuple_base_tuple = {{&mp_type_tuple}, 1, {MP_ROM_PTR(&mp_type_tuple)}};
-
STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t *fields) {
mp_obj_namedtuple_type_t *o = m_new_obj_var(mp_obj_namedtuple_type_t, qstr, n_fields);
memset(&o->base, 0, sizeof(o->base));
@@ -148,7 +146,7 @@ STATIC mp_obj_t mp_obj_new_namedtuple_type(qstr name, size_t n_fields, mp_obj_t
o->base.attr = namedtuple_attr;
o->base.subscr = mp_obj_tuple_subscr;
o->base.getiter = mp_obj_tuple_getiter;
- o->base.bases_tuple = (mp_obj_tuple_t*)(mp_rom_obj_tuple_t*)&namedtuple_base_tuple;
+ o->base.parent = &mp_type_tuple;
o->n_fields = n_fields;
for (size_t i = 0; i < n_fields; i++) {
o->fields[i] = mp_obj_str_get_qstr(fields[i]);
diff --git a/py/objtype.c b/py/objtype.c
index dd170b4c6..5e522bed2 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -57,26 +57,34 @@ STATIC mp_obj_t mp_obj_new_instance(const mp_obj_type_t *class, size_t subobjs)
}
STATIC int instance_count_native_bases(const mp_obj_type_t *type, const mp_obj_type_t **last_native_base) {
- size_t len = type->bases_tuple->len;
- mp_obj_t *items = type->bases_tuple->items;
-
int count = 0;
- for (size_t i = 0; i < len; i++) {
- assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
- const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(items[i]);
- if (bt == &mp_type_object) {
- // Not a "real" type
- continue;
- }
- if (mp_obj_is_native_type(bt)) {
- *last_native_base = bt;
- count++;
+ for (;;) {
+ if (type == &mp_type_object) {
+ // Not a "real" type, end search here.
+ return count;
+ } else if (mp_obj_is_native_type(type)) {
+ // Native types don't have parents (at least not from our perspective) so end.
+ *last_native_base = type;
+ return count + 1;
+ } else if (type->parent == NULL) {
+ // No parents so end search here.
+ return count;
+ } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
+ // Multiple parents, search through them all recursively.
+ const mp_obj_tuple_t *parent_tuple = type->parent;
+ const mp_obj_t *item = parent_tuple->items;
+ const mp_obj_t *top = item + parent_tuple->len;
+ for (; item < top; ++item) {
+ assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
+ const mp_obj_type_t *bt = (const mp_obj_type_t *)MP_OBJ_TO_PTR(*item);
+ count += instance_count_native_bases(bt, last_native_base);
+ }
+ return count;
} else {
- count += instance_count_native_bases(bt, last_native_base);
+ // A single parent, use iteration to continue the search.
+ type = type->parent;
}
}
-
- return count;
}
// TODO
@@ -160,32 +168,31 @@ STATIC void mp_obj_class_lookup(struct class_lookup_data *lookup, const mp_obj_
// attribute not found, keep searching base classes
- // for a const struct, this entry might be NULL
- if (type->bases_tuple == NULL) {
- return;
- }
-
- size_t len = type->bases_tuple->len;
- mp_obj_t *items = type->bases_tuple->items;
- if (len == 0) {
+ if (type->parent == NULL) {
return;
- }
- for (size_t i = 0; i < len - 1; i++) {
- assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
- mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]);
- if (bt == &mp_type_object) {
- // Not a "real" type
- continue;
- }
- mp_obj_class_lookup(lookup, bt);
- if (lookup->dest[0] != MP_OBJ_NULL) {
- return;
+ } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
+ const mp_obj_tuple_t *parent_tuple = type->parent;
+ const mp_obj_t *item = parent_tuple->items;
+ const mp_obj_t *top = item + parent_tuple->len - 1;
+ for (; item < top; ++item) {
+ assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
+ mp_obj_type_t *bt = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);
+ if (bt == &mp_type_object) {
+ // Not a "real" type
+ continue;
+ }
+ mp_obj_class_lookup(lookup, bt);
+ if (lookup->dest[0] != MP_OBJ_NULL) {
+ return;
+ }
}
- }
- // search last base (simple tail recursion elimination)
- assert(MP_OBJ_IS_TYPE(items[len - 1], &mp_type_type));
- type = (mp_obj_type_t*)MP_OBJ_TO_PTR(items[len - 1]);
+ // search last base (simple tail recursion elimination)
+ assert(MP_OBJ_IS_TYPE(*item, &mp_type_type));
+ type = (mp_obj_type_t*)MP_OBJ_TO_PTR(*item);
+ } else {
+ type = type->parent;
+ }
if (type == &mp_type_object) {
// Not a "real" type
return;
@@ -946,14 +953,21 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict)
o->getiter = instance_getiter;
//o->iternext = ; not implemented
o->buffer_p.get_buffer = instance_get_buffer;
- // Inherit protocol from a base class. This allows to define an
- // abstract base class which would translate C-level protocol to
- // Python method calls, and any subclass inheriting from it will
- // support this feature.
+
if (len > 0) {
+ // Inherit protocol from a base class. This allows to define an
+ // abstract base class which would translate C-level protocol to
+ // Python method calls, and any subclass inheriting from it will
+ // support this feature.
o->protocol = ((mp_obj_type_t*)MP_OBJ_TO_PTR(items[0]))->protocol;
+
+ if (len >= 2) {
+ o->parent = MP_OBJ_TO_PTR(bases_tuple);
+ } else {
+ o->parent = MP_OBJ_TO_PTR(items[0]);
+ }
}
- o->bases_tuple = MP_OBJ_TO_PTR(bases_tuple);
+
o->locals_dict = MP_OBJ_TO_PTR(locals_dict);
const mp_obj_type_t *native_base;
@@ -1015,13 +1029,6 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
mp_obj_type_t *type = MP_OBJ_TO_PTR(self->type);
- // for a const struct, this entry might be NULL
- if (type->bases_tuple == NULL) {
- return;
- }
-
- size_t len = type->bases_tuple->len;
- mp_obj_t *items = type->bases_tuple->items;
struct class_lookup_data lookup = {
.obj = MP_OBJ_TO_PTR(self->obj),
.attr = attr,
@@ -1029,13 +1036,27 @@ STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
.dest = dest,
.is_type = false,
};
- for (size_t i = 0; i < len; i++) {
- assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
- mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
+
+ if (type->parent == NULL) {
+ // no parents, do nothing
+ } else if (((mp_obj_base_t*)type->parent)->type == &mp_type_tuple) {
+ const mp_obj_tuple_t *parent_tuple = type->parent;
+ size_t len = parent_tuple->len;
+ const mp_obj_t *items = parent_tuple->items;
+ for (size_t i = 0; i < len; i++) {
+ assert(MP_OBJ_IS_TYPE(items[i], &mp_type_type));
+ mp_obj_class_lookup(&lookup, (mp_obj_type_t*)MP_OBJ_TO_PTR(items[i]));
+ if (dest[0] != MP_OBJ_NULL) {
+ return;
+ }
+ }
+ } else {
+ mp_obj_class_lookup(&lookup, type->parent);
if (dest[0] != MP_OBJ_NULL) {
return;
}
}
+
mp_obj_class_lookup(&lookup, &mp_type_object);
}
@@ -1073,27 +1094,28 @@ bool mp_obj_is_subclass_fast(mp_const_obj_t object, mp_const_obj_t classinfo) {
const mp_obj_type_t *self = MP_OBJ_TO_PTR(object);
- // for a const struct, this entry might be NULL
- if (self->bases_tuple == NULL) {
- return false;
- }
-
- // get the base objects (they should be type objects)
- size_t len = self->bases_tuple->len;
- mp_obj_t *items = self->bases_tuple->items;
- if (len == 0) {
+ if (self->parent == NULL) {
+ // type has no parents
return false;
- }
-
- // iterate through the base objects
- for (size_t i = 0; i < len - 1; i++) {
- if (mp_obj_is_subclass_fast(items[i], classinfo)) {
- return true;
+ } else if (((mp_obj_base_t*)self->parent)->type == &mp_type_tuple) {
+ // get the base objects (they should be type objects)
+ const mp_obj_tuple_t *parent_tuple = self->parent;
+ const mp_obj_t *item = parent_tuple->items;
+ const mp_obj_t *top = item + parent_tuple->len - 1;
+
+ // iterate through the base objects
+ for (; item < top; ++item) {
+ if (mp_obj_is_subclass_fast(*item, classinfo)) {
+ return true;
+ }
}
- }
- // search last base (simple tail recursion elimination)
- object = items[len - 1];
+ // search last base (simple tail recursion elimination)
+ object = *item;
+ } else {
+ // type has 1 parent
+ object = MP_OBJ_FROM_PTR(self->parent);
+ }
}
}
From a73501b1d63e5240cbced95b884383b79f5d6efd Mon Sep 17 00:00:00 2001
From: Damien George
Date: Thu, 6 Apr 2017 17:27:33 +1000
Subject: [PATCH 063/826] py/objfloat: Add implementation of high-quality float
hashing.
Disabled by default.
---
py/mpconfig.h | 6 ++++++
py/obj.h | 4 ++++
py/objfloat.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+)
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 06c19f72b..05cb5daaf 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -548,6 +548,12 @@ typedef double mp_float_t;
#define MICROPY_PY_BUILTINS_COMPLEX (MICROPY_PY_BUILTINS_FLOAT)
#endif
+// Whether to provide a high-quality hash for float and complex numbers.
+// Otherwise the default is a very simple but correct hashing function.
+#ifndef MICROPY_FLOAT_HIGH_QUALITY_HASH
+#define MICROPY_FLOAT_HIGH_QUALITY_HASH (0)
+#endif
+
// Enable features which improve CPython compatibility
// but may lead to more code size/memory usage.
// TODO: Originally intended as generic category to not
diff --git a/py/obj.h b/py/obj.h
index 597c7c8d9..b5a0c4190 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -730,7 +730,11 @@ void mp_str_print_quoted(const mp_print_t *print, const byte *str_data, size_t s
#if MICROPY_PY_BUILTINS_FLOAT
// float
+#if MICROPY_FLOAT_HIGH_QUALITY_HASH
+mp_int_t mp_float_hash(mp_float_t val);
+#else
static inline mp_int_t mp_float_hash(mp_float_t val) { return (mp_int_t)val; }
+#endif
mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs); // can return MP_OBJ_NULL if op not supported
// complex
diff --git a/py/objfloat.c b/py/objfloat.c
index 2c355d355..5cf995417 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -59,6 +59,55 @@ const mp_obj_float_t mp_const_float_pi_obj = {{&mp_type_float}, M_PI};
#endif
+#if MICROPY_FLOAT_HIGH_QUALITY_HASH
+// must return actual integer value if it fits in mp_int_t
+mp_int_t mp_float_hash(mp_float_t src) {
+#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_DOUBLE
+typedef uint64_t mp_float_uint_t;
+#elif MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
+typedef uint32_t mp_float_uint_t;
+#endif
+ union {
+ mp_float_t f;
+ #if MP_ENDIANNESS_LITTLE
+ struct { mp_float_uint_t frc:MP_FLOAT_FRAC_BITS, exp:MP_FLOAT_EXP_BITS, sgn:1; } p;
+ #else
+ struct { mp_float_uint_t sgn:1, exp:MP_FLOAT_EXP_BITS, frc:MP_FLOAT_FRAC_BITS; } p;
+ #endif
+ mp_float_uint_t i;
+ } u = {.f = src};
+
+ mp_int_t val;
+ const int adj_exp = (int)u.p.exp - MP_FLOAT_EXP_BIAS;
+ if (adj_exp < 0) {
+ // value < 1; must be sure to handle 0.0 correctly (ie return 0)
+ val = u.i;
+ } else {
+ // if adj_exp is max then: u.p.frc==0 indicates inf, else NaN
+ // else: 1 <= value
+ mp_float_uint_t frc = u.p.frc | ((mp_float_uint_t)1 << MP_FLOAT_FRAC_BITS);
+
+ if (adj_exp <= MP_FLOAT_FRAC_BITS) {
+ // number may have a fraction; xor the integer part with the fractional part
+ val = (frc >> (MP_FLOAT_FRAC_BITS - adj_exp))
+ ^ (frc & ((1 << (MP_FLOAT_FRAC_BITS - adj_exp)) - 1));
+ } else if ((unsigned int)adj_exp < BITS_PER_BYTE * sizeof(mp_int_t) - 1) {
+ // the number is a (big) whole integer and will fit in val's signed-width
+ val = (mp_int_t)frc << (adj_exp - MP_FLOAT_FRAC_BITS);
+ } else {
+ // integer part will overflow val's width so just use what bits we can
+ val = frc;
+ }
+ }
+
+ if (u.p.sgn) {
+ val = -val;
+ }
+
+ return val;
+}
+#endif
+
STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t kind) {
(void)kind;
mp_float_t o_val = mp_obj_float_get(o_in);
From fe79234ca0e371af4c252e31e218d81d8171deee Mon Sep 17 00:00:00 2001
From: Damien George
Date: Thu, 6 Apr 2017 17:28:54 +1000
Subject: [PATCH 064/826] unix: Enabled high-quality float hashing in coverage
build.
---
unix/mpconfigport_coverage.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/unix/mpconfigport_coverage.h b/unix/mpconfigport_coverage.h
index 387e182db..5fc8d7107 100644
--- a/unix/mpconfigport_coverage.h
+++ b/unix/mpconfigport_coverage.h
@@ -32,6 +32,7 @@
#include
+#define MICROPY_FLOAT_HIGH_QUALITY_HASH (1)
#define MICROPY_ENABLE_SCHEDULER (1)
#define MICROPY_PY_DELATTR_SETATTR (1)
#define MICROPY_PY_BUILTINS_HELP (1)
From 08242eed2677cde806fd9c0de33138a8491293a2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 13:50:31 +1000
Subject: [PATCH 065/826] py/nlrsetjmp: Add check for failed NLR jump.
Also optimise the function so it only needs to call the MP_STATE_THREAD
macro once (following how other nlr code is written).
---
py/nlrsetjmp.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/py/nlrsetjmp.c b/py/nlrsetjmp.c
index 43a13156f..c3873e0b6 100644
--- a/py/nlrsetjmp.c
+++ b/py/nlrsetjmp.c
@@ -29,10 +29,14 @@
#if MICROPY_NLR_SETJMP
void nlr_setjmp_jump(void *val) {
- nlr_buf_t *buf = MP_STATE_THREAD(nlr_top);
- MP_STATE_THREAD(nlr_top) = buf->prev;
- buf->ret_val = val;
- longjmp(buf->jmpbuf, 1);
+ nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
+ nlr_buf_t *top = *top_ptr;
+ if (top == NULL) {
+ nlr_jump_fail(val);
+ }
+ top->ret_val = val;
+ *top_ptr = top->prev;
+ longjmp(top->jmpbuf, 1);
}
#endif
From c7e8c6f7dec539aae4ca6445541533bfbc1a1405 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 13:52:04 +1000
Subject: [PATCH 066/826] py/gc: Execute finaliser code in a protected
environment.
If a finaliser raises an exception then it must not propagate through the
GC sweep function. This patch protects against such a thing by running
finaliser code via the mp_call_function_1_protected call.
This patch also adds scheduler lock/unlock calls around the finaliser
execution to further protect against any possible reentrancy issues: the
memory manager is already locked when doing a collection, but we also don't
want to allow any scheduled code to run, KeyboardInterrupts to interupt the
code, nor threads to switch.
---
py/gc.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/py/gc.c b/py/gc.c
index 7ed53cfc7..937dae44f 100644
--- a/py/gc.c
+++ b/py/gc.c
@@ -258,18 +258,20 @@ STATIC void gc_sweep(void) {
case AT_HEAD:
#if MICROPY_ENABLE_FINALISER
if (FTB_GET(block)) {
- #if MICROPY_PY_THREAD
- // TODO need to think about reentrancy with finaliser code
- assert(!"finaliser with threading not implemented");
- #endif
mp_obj_base_t *obj = (mp_obj_base_t*)PTR_FROM_BLOCK(block);
if (obj->type != NULL) {
// if the object has a type then see if it has a __del__ method
mp_obj_t dest[2];
mp_load_method_maybe(MP_OBJ_FROM_PTR(obj), MP_QSTR___del__, dest);
if (dest[0] != MP_OBJ_NULL) {
- // load_method returned a method
- mp_call_method_n_kw(0, 0, dest);
+ // load_method returned a method, execute it in a protected environment
+ #if MICROPY_ENABLE_SCHEDULER
+ mp_sched_lock();
+ #endif
+ mp_call_function_1_protected(dest[0], dest[1]);
+ #if MICROPY_ENABLE_SCHEDULER
+ mp_sched_unlock();
+ #endif
}
}
// clear finaliser flag
From f6547f640378be0da0fa3429989dedd40030a2af Mon Sep 17 00:00:00 2001
From: Eric Poulsen
Date: Wed, 12 Apr 2017 12:37:14 -0700
Subject: [PATCH 067/826] esp32: Move FAT FS to start at 0x200000 and increase
size to 2MiB.
This allows for more room (up to 2MiB) for the firmware, and also gives a
decent size filesystem.
After using this patch one is required to rebuild their filesystem.
---
esp32/modesp.c | 2 +-
esp32/modules/flashbdev.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/esp32/modesp.c b/esp32/modesp.c
index 1e9e65f31..805002655 100644
--- a/esp32/modesp.c
+++ b/esp32/modesp.c
@@ -77,7 +77,7 @@ STATIC mp_obj_t esp_flash_size(void) {
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
STATIC mp_obj_t esp_flash_user_start(void) {
- return MP_OBJ_NEW_SMALL_INT(0x100000);
+ return MP_OBJ_NEW_SMALL_INT(0x200000);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
diff --git a/esp32/modules/flashbdev.py b/esp32/modules/flashbdev.py
index 621b79194..935f5342f 100644
--- a/esp32/modules/flashbdev.py
+++ b/esp32/modules/flashbdev.py
@@ -31,4 +31,4 @@ def ioctl(self, op, arg):
bdev = None
else:
# for now we use a fixed size for the filesystem
- bdev = FlashBdev(256 * 1024 // FlashBdev.SEC_SIZE)
+ bdev = FlashBdev(2048 * 1024 // FlashBdev.SEC_SIZE)
From 7132bcdc353e1242ad1d59c911e50234ec804e30 Mon Sep 17 00:00:00 2001
From: Eric Poulsen
Date: Wed, 12 Apr 2017 12:52:49 -0700
Subject: [PATCH 068/826] esp32/Makefile: Change default FLASH_MODE to dio for
WROOM-32 module.
ESP-WROOM-32 (and therefore ESP-WROVER-KIT) is the reference module for
development, and the most common one out there, so makes sense to provide
default settings for it.
---
esp32/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp32/Makefile b/esp32/Makefile
index 5b42e479c..3cbf0b308 100644
--- a/esp32/Makefile
+++ b/esp32/Makefile
@@ -16,7 +16,7 @@ include ../py/py.mk
PORT ?= /dev/ttyUSB0
BAUD ?= 460800
-FLASH_MODE ?= qio
+FLASH_MODE ?= dio
FLASH_FREQ ?= 40m
FLASH_SIZE ?= 4MB
CROSS_COMPILE ?= xtensa-esp32-elf-
From 967cad7434ee8e814c07ecccc6b642704dc46eaf Mon Sep 17 00:00:00 2001
From: Damien George
Date: Thu, 13 Apr 2017 23:34:28 +1000
Subject: [PATCH 069/826] tests/extmod/utimeq1: Improve coverage of utimeq
module.
---
tests/extmod/utimeq1.py | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/tests/extmod/utimeq1.py b/tests/extmod/utimeq1.py
index 9af723674..68d69e25e 100644
--- a/tests/extmod/utimeq1.py
+++ b/tests/extmod/utimeq1.py
@@ -34,6 +34,41 @@ def dprint(*v):
except IndexError:
pass
+# unsupported unary op
+try:
+ ~h
+ assert False
+except TypeError:
+ pass
+
+# pushing on full queue
+h = utimeq(1)
+h.push(1, 0, 0)
+try:
+ h.push(2, 0, 0)
+ assert False
+except IndexError:
+ pass
+
+# popping into invalid type
+try:
+ h.pop([])
+ assert False
+except TypeError:
+ pass
+
+# length
+assert len(h) == 1
+
+# peektime
+assert h.peektime() == 1
+
+# peektime with empty queue
+try:
+ utimeq(1).peektime()
+ assert False
+except IndexError:
+ pass
def pop_all(h):
l = []
From 84e17063c3ab0feb25b0777dac752e6b333b2a4d Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 13 Apr 2017 22:19:16 +0300
Subject: [PATCH 070/826] zephyr/modusocket: Strip packet header right in the
receive callback.
Instead of complicating recv() implementation.
---
zephyr/modusocket.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 0eb6e9dac..1baabdba6 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -120,8 +120,6 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
// to the fact that it copies data byte by byte).
static char *net_buf_gather(struct net_buf *buf, char *to, unsigned max_len) {
struct net_buf *tmp = buf->frags;
- unsigned header_len = net_nbuf_appdata(buf) - tmp->data;
- net_buf_pull(tmp, header_len);
while (tmp && max_len) {
unsigned len = tmp->len;
@@ -166,6 +164,10 @@ static void sock_received_cb(struct net_context *context, struct net_buf *net_bu
// Make sure that "EOF flag" is not set
net_nbuf_set_buf_sent(net_buf, false);
+ // We don't care about packet header, so get rid of it asap
+ unsigned header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
+ net_buf_pull(net_buf->frags, header_len);
+
// net_buf->frags will be overwritten by fifo, so save it
net_nbuf_set_token(net_buf, net_buf->frags);
k_fifo_put(&socket->recv_q, net_buf);
@@ -350,15 +352,13 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
return mp_const_empty_bytes;
}
- unsigned header_len = 0;
if (socket->cur_buf == NULL) {
DEBUG_printf("TCP recv: no cur_buf, getting\n");
struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
// Restore ->frags overwritten by fifo
net_buf->frags = net_nbuf_token(net_buf);
- header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
- DEBUG_printf("TCP recv: new cur_buf: %p, hdr_len: %u\n", net_buf, header_len);
+ DEBUG_printf("TCP recv: new cur_buf: %p\n", net_buf);
socket->cur_buf = net_buf;
}
@@ -368,7 +368,6 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
assert(0);
}
- net_buf_pull(frag, header_len);
unsigned frag_len = frag->len;
recv_len = frag_len;
if (recv_len > max_len) {
From 40acbc2e10b8fc88b61ffc272729db4de65e5f72 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 14 Apr 2017 00:56:41 +0300
Subject: [PATCH 071/826] esp8266/README: Replace reference of alpha status to
beta status.
---
esp8266/README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp8266/README.md b/esp8266/README.md
index 54591fcc1..8a8ca7977 100644
--- a/esp8266/README.md
+++ b/esp8266/README.md
@@ -110,7 +110,7 @@ http://docs.micropython.org/en/latest/esp8266/esp8266/tutorial/intro.html
Troubleshooting
---------------
-While the port is still in alpha, it's known to be generally stable. If you
+While the port is in beta, it's known to be generally stable. If you
experience strange bootloops, crashes, lockups, here's a list to check against:
- You didn't erase flash before programming MicroPython firmware.
From fbe7a81e30906b7e2c991cf76cf10d582fd2e012 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 14 Apr 2017 01:03:46 +0300
Subject: [PATCH 072/826] esp8266/README: Add notice about 512K version.
---
esp8266/README.md | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/esp8266/README.md b/esp8266/README.md
index 8a8ca7977..897bb4737 100644
--- a/esp8266/README.md
+++ b/esp8266/README.md
@@ -79,6 +79,16 @@ $ make PORT=/dev/ttyUSB0 FLASH_MODE=qio FLASH_SIZE=32m deploy
The image produced is `build/firmware-combined.bin`, to be flashed at 0x00000.
+__512KB FlashROM version__
+
+The normal build described above requires modules with at least 1MB of FlashROM
+onboard. There's a special configuration for 512KB modules, which can be
+built with `make 512k`. This configuration is highly limited, lacks filesystem
+support, WebREPL, and has many other features disabled. It's mostly suitable
+for advanced users who are interested to fine-tune options to achieve a required
+setup. If you are an end user, please consider using a module with at least 1MB
+of FlashROM.
+
First start
-----------
From a1c39ffb69d711858e47e172d4ca8d98990d2bf9 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 14 Apr 2017 01:12:04 +0300
Subject: [PATCH 073/826] docs/esp8266/tutorial/intro: Reword section on flash
size requirement.
Give a clearly dissuading tone on end users trying 512KB version
- it has to many end-usery features lacking.
---
docs/esp8266/tutorial/intro.rst | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst
index e7a38d3e5..67ed0ba67 100644
--- a/docs/esp8266/tutorial/intro.rst
+++ b/docs/esp8266/tutorial/intro.rst
@@ -20,9 +20,12 @@ characteristic of a board is how much flash it has, how the GPIO pins are
connected to the outside world, and whether it includes a built-in USB-serial
convertor to make the UART available to your PC.
-The minimum requirement for flash size is 512k. A board with this amount of
-flash will not have room for a filesystem, but otherwise is fully functional.
-If your board has 1Mbyte or more of flash then it will support a filesystem.
+The minimum requirement for flash size is 1Mbyte. There is also a special
+build for boards with 512KB, but it is highly limited comparing to the
+normal build: there is no support for filesystem, and thus features which
+depend on it won't work (WebREPL, upip, etc.). As such, 512KB build will
+be more interesting for users who build from source and fine-tune parameters
+for their particular application.
Names of pins will be given in this tutorial using the chip names (eg GPIO0)
and it should be straightforward to find which pin this corresponds to on your
From 5b8122f2bb037644da953529afe7c3e8b57094e2 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 14 Apr 2017 17:07:13 +0300
Subject: [PATCH 074/826] tests/run-tests: Search feature checks wrt to main
script location.
If run-tests script is run from another dir, we still want to look up
feature checks in run-tests' dir.
---
tests/run-tests | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
diff --git a/tests/run-tests b/tests/run-tests
index 87d12ba36..61726cc87 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -49,15 +49,15 @@ def convert_regex_escapes(line):
return bytes(''.join(cs), 'utf8')
-def run_micropython(pyb, args, test_file):
+def run_micropython(pyb, args, test_file, is_special=False):
special_tests = ('micropython/meminfo.py', 'basics/bytes_compare3.py', 'basics/builtin_help.py', 'thread/thread_exc2.py')
- is_special = False
if pyb is None:
# run on PC
if test_file.startswith(('cmdline/', 'feature_check/')) or test_file in special_tests:
# special handling for tests of the unix cmdline program
is_special = True
+ if is_special:
# check for any cmdline options needed for this test
args = [MICROPYTHON]
with open(test_file, 'rb') as f:
@@ -189,7 +189,12 @@ def run_micropython(pyb, args, test_file):
return output_mupy
-def run_tests(pyb, tests, args):
+
+def run_feature_check(pyb, args, base_path, test_file):
+ return run_micropython(pyb, args, base_path + "/feature_check/" + test_file, is_special=True)
+
+
+def run_tests(pyb, tests, args, base_path="."):
test_count = 0
testcase_count = 0
passed_count = 0
@@ -204,39 +209,39 @@ def run_tests(pyb, tests, args):
skip_const = False
# Check if micropython.native is supported, and skip such tests if it's not
- native = run_micropython(pyb, args, 'feature_check/native_check.py')
+ native = run_feature_check(pyb, args, base_path, 'native_check.py')
if native == b'CRASH':
skip_native = True
# Check if arbitrary-precision integers are supported, and skip such tests if it's not
- native = run_micropython(pyb, args, 'feature_check/int_big.py')
+ native = run_feature_check(pyb, args, base_path, 'int_big.py')
if native != b'1000000000000000000000000000000000000000000000\n':
skip_int_big = True
# Check if set type (and set literals) is supported, and skip such tests if it's not
- native = run_micropython(pyb, args, 'feature_check/set_check.py')
+ native = run_feature_check(pyb, args, base_path, 'set_check.py')
if native == b'CRASH':
skip_set_type = True
# Check if async/await keywords are supported, and skip such tests if it's not
- native = run_micropython(pyb, args, 'feature_check/async_check.py')
+ native = run_feature_check(pyb, args, base_path, 'async_check.py')
if native == b'CRASH':
skip_async = True
# Check if const keyword (MicroPython extension) is supported, and skip such tests if it's not
- native = run_micropython(pyb, args, 'feature_check/const.py')
+ native = run_feature_check(pyb, args, base_path, 'const.py')
if native == b'CRASH':
skip_const = True
# Check if emacs repl is supported, and skip such tests if it's not
- t = run_micropython(pyb, args, 'feature_check/repl_emacs_check.py')
+ t = run_feature_check(pyb, args, base_path, 'repl_emacs_check.py')
if not 'True' in str(t, 'ascii'):
skip_tests.add('cmdline/repl_emacs_keys.py')
- upy_byteorder = run_micropython(pyb, args, 'feature_check/byteorder.py')
- has_complex = run_micropython(pyb, args, 'feature_check/complex.py') == b'complex\n'
- has_coverage = run_micropython(pyb, args, 'feature_check/coverage.py') == b'coverage\n'
- cpy_byteorder = subprocess.check_output([CPYTHON3, 'feature_check/byteorder.py'])
+ upy_byteorder = run_feature_check(pyb, args, base_path, 'byteorder.py')
+ has_complex = run_feature_check(pyb, args, base_path, 'complex.py') == b'complex\n'
+ has_coverage = run_feature_check(pyb, args, base_path, 'coverage.py') == b'coverage\n'
+ cpy_byteorder = subprocess.check_output([CPYTHON3, base_path + '/feature_check/byteorder.py'])
skip_endian = (upy_byteorder != cpy_byteorder)
# Some tests shouldn't be run under Travis CI
@@ -468,7 +473,11 @@ def main():
# clear search path to make sure tests use only builtin modules
os.environ['MICROPYPATH'] = ''
- res = run_tests(pyb, tests, args)
+ # Even if we run completely different tests in a different directory,
+ # we need to access feature_check's from the same directory as the
+ # run-tests script itself.
+ base_path = os.path.dirname(sys.argv[0]) or "."
+ res = run_tests(pyb, tests, args, base_path)
if pyb:
pyb.close()
if not res:
From 209eaec599b8b849dbef45fdb2d8f7138b8b7745 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 14 Apr 2017 19:46:27 +0300
Subject: [PATCH 075/826] socket_send: Don't send more than MTU allows.
As Zephyr currently doesn't handle MTU itself (ZEP-1998), limit amount
of data we send on our side.
Also, if we get unsuccessful result from net_nbuf_append(), calculate
how much data it has added still. This works around ZEP-1984.
---
zephyr/modusocket.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 1baabdba6..00e0bc789 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -308,14 +308,22 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
struct net_buf *send_buf = net_nbuf_get_tx(socket->ctx, K_FOREVER);
- // TODO: Probably should limit how much data we send in one call still
- if (!net_nbuf_append(send_buf, bufinfo.len, bufinfo.buf, K_FOREVER)) {
- mp_raise_OSError(ENOSPC);
+
+ unsigned len = net_if_get_mtu(net_context_get_iface(socket->ctx));
+ // Arbitrary value to account for protocol headers
+ len -= 64;
+ if (len > bufinfo.len) {
+ len = bufinfo.len;
+ }
+
+ if (!net_nbuf_append(send_buf, len, bufinfo.buf, K_FOREVER)) {
+ len = net_buf_frags_len(send_buf);
+ //mp_raise_OSError(ENOSPC);
}
RAISE_ERRNO(net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL));
- return mp_obj_new_int_from_uint(bufinfo.len);
+ return mp_obj_new_int_from_uint(len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
From 61616e84ce41e1b1a0fad62704488d79b87cfbe2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 12 Apr 2017 13:00:40 +1000
Subject: [PATCH 076/826] extmod/machine_signal: Rename "inverted" arg to
"invert", it's shorter.
A shorter name takes less code size, less room in scripts and is faster to
type at the REPL.
Tests and HW-API examples are updated to reflect the change.
---
examples/hwapi/hwconfig_esp8266_esp12.py | 2 +-
extmod/machine_signal.c | 22 +++++++++++-----------
tests/extmod/machine_signal.py | 2 +-
3 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/examples/hwapi/hwconfig_esp8266_esp12.py b/examples/hwapi/hwconfig_esp8266_esp12.py
index fb6d5fe90..198a652d0 100644
--- a/examples/hwapi/hwconfig_esp8266_esp12.py
+++ b/examples/hwapi/hwconfig_esp8266_esp12.py
@@ -2,4 +2,4 @@
# ESP12 module as used by many boards
# Blue LED on pin 2, active low (inverted)
-LED = Signal(Pin(2, Pin.OUT), inverted=True)
+LED = Signal(Pin(2, Pin.OUT), invert=True)
diff --git a/extmod/machine_signal.c b/extmod/machine_signal.c
index b10d90166..d08931296 100644
--- a/extmod/machine_signal.c
+++ b/extmod/machine_signal.c
@@ -39,12 +39,12 @@
typedef struct _machine_signal_t {
mp_obj_base_t base;
mp_obj_t pin;
- bool inverted;
+ bool invert;
} machine_signal_t;
STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_obj_t pin = args[0];
- bool inverted = false;
+ bool invert = false;
#if defined(MICROPY_PY_MACHINE_PIN_MAKE_NEW)
mp_pin_p_t *pin_p = NULL;
@@ -55,7 +55,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
}
if (pin_p == NULL) {
- // If first argument isn't a Pin-like object, we filter out "inverted"
+ // If first argument isn't a Pin-like object, we filter out "invert"
// from keyword arguments and pass them all to the exported Pin
// constructor to create one.
mp_obj_t pin_args[n_args + n_kw * 2];
@@ -64,8 +64,8 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
mp_obj_t *dst = pin_args + n_args;
mp_obj_t *sig_value = NULL;
for (size_t cnt = n_kw; cnt; cnt--) {
- if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) {
- inverted = mp_obj_is_true(src[1]);
+ if (*src == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
+ invert = mp_obj_is_true(src[1]);
n_kw--;
} else {
*dst++ = *src;
@@ -80,7 +80,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
src += 2;
}
- if (inverted && sig_value != NULL) {
+ if (invert && sig_value != NULL) {
*sig_value = mp_obj_is_true(*sig_value) ? MP_OBJ_NEW_SMALL_INT(0) : MP_OBJ_NEW_SMALL_INT(1);
}
@@ -95,8 +95,8 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
{
if (n_args == 1) {
if (n_kw == 0) {
- } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_inverted)) {
- inverted = mp_obj_is_true(args[1]);
+ } else if (n_kw == 1 && args[1] == MP_OBJ_NEW_QSTR(MP_QSTR_invert)) {
+ invert = mp_obj_is_true(args[1]);
} else {
goto error;
}
@@ -109,7 +109,7 @@ STATIC mp_obj_t signal_make_new(const mp_obj_type_t *type, size_t n_args, size_t
machine_signal_t *o = m_new_obj(machine_signal_t);
o->base.type = type;
o->pin = pin;
- o->inverted = inverted;
+ o->invert = invert;
return MP_OBJ_FROM_PTR(o);
}
@@ -119,10 +119,10 @@ STATIC mp_uint_t signal_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_t arg
switch (request) {
case MP_PIN_READ: {
- return mp_virtual_pin_read(self->pin) ^ self->inverted;
+ return mp_virtual_pin_read(self->pin) ^ self->invert;
}
case MP_PIN_WRITE: {
- mp_virtual_pin_write(self->pin, arg ^ self->inverted);
+ mp_virtual_pin_write(self->pin, arg ^ self->invert);
return 0;
}
}
diff --git a/tests/extmod/machine_signal.py b/tests/extmod/machine_signal.py
index 401533f23..96b8f43c7 100644
--- a/tests/extmod/machine_signal.py
+++ b/tests/extmod/machine_signal.py
@@ -33,7 +33,7 @@ def value(self, v=None):
# test inverted, and using on/off methods
p = Pin()
-s = machine.Signal(p, inverted=True)
+s = machine.Signal(p, invert=True)
s.off()
print(p.value(), s.value())
s.on()
From ae831ec0a8ff45a31d993798cd315027eba3d897 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 09:18:47 +0300
Subject: [PATCH 077/826] docs/library/micropython: Deconditionalize.
---
docs/library/micropython.rst | 38 +++++++++++++++++-------------------
1 file changed, 18 insertions(+), 20 deletions(-)
diff --git a/docs/library/micropython.rst b/docs/library/micropython.rst
index 14e4c917e..967f822ec 100644
--- a/docs/library/micropython.rst
+++ b/docs/library/micropython.rst
@@ -7,26 +7,6 @@
Functions
---------
-.. only:: port_pyboard or port_unix
-
- .. function:: mem_info([verbose])
-
- Print information about currently used memory. If the ``verbose`` argument
- is given then extra information is printed.
-
- The information that is printed is implementation dependent, but currently
- includes the amount of stack and heap used. In verbose mode it prints out
- the entire heap indicating which blocks are used and which are free.
-
- .. function:: qstr_info([verbose])
-
- Print information about currently interned strings. If the ``verbose``
- argument is given then extra information is printed.
-
- The information that is printed is implementation dependent, but currently
- includes the number of interned strings and the amount of RAM they use. In
- verbose mode it prints out the names of all RAM-interned strings.
-
.. function:: alloc_emergency_exception_buf(size)
Allocate ``size`` bytes of RAM for the emergency exception buffer (a good
@@ -37,3 +17,21 @@ Functions
A good way to use this function is to put it at the start of your main script
(eg boot.py or main.py) and then the emergency exception buffer will be active
for all the code following it.
+
+.. function:: mem_info([verbose])
+
+ Print information about currently used memory. If the ``verbose`` argument
+ is given then extra information is printed.
+
+ The information that is printed is implementation dependent, but currently
+ includes the amount of stack and heap used. In verbose mode it prints out
+ the entire heap indicating which blocks are used and which are free.
+
+.. function:: qstr_info([verbose])
+
+ Print information about currently interned strings. If the ``verbose``
+ argument is given then extra information is printed.
+
+ The information that is printed is implementation dependent, but currently
+ includes the number of interned strings and the amount of RAM they use. In
+ verbose mode it prints out the names of all RAM-interned strings.
From a0fb360f1b3f32131be6267c7ce0dbe74ed91f77 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 09:22:47 +0300
Subject: [PATCH 078/826] docs/library/uos: urandom: Generalize description.
Don't give a guarantee of HW RNG, only a possibility of its usage.
---
docs/library/uos.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/library/uos.rst b/docs/library/uos.rst
index bb3c20017..e1ea72967 100644
--- a/docs/library/uos.rst
+++ b/docs/library/uos.rst
@@ -88,8 +88,8 @@ Functions
.. function:: urandom(n)
- Return a bytes object with n random bytes, generated by the hardware
- random number generator.
+ Return a bytes object with n random bytes. Whenever possible, it is
+ generated by the hardware random number generator.
.. only:: port_wipy
From ac8843ceecb645b11737ea42d0f4248d742383cd Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 09:41:32 +0300
Subject: [PATCH 079/826] docs/library/ussl: Deconditionalize, wipy notes moved
to its documentation.
---
docs/library/ussl.rst | 100 +++++++++++++-----------------------------
docs/wipy/general.rst | 23 ++++++++++
2 files changed, 53 insertions(+), 70 deletions(-)
diff --git a/docs/library/ussl.rst b/docs/library/ussl.rst
index 5371ed129..36f6d65a4 100644
--- a/docs/library/ussl.rst
+++ b/docs/library/ussl.rst
@@ -1,86 +1,46 @@
-:mod:`ussl` -- ssl module
-===============================
+:mod:`ussl` -- SSL/TLS module
+=============================
.. module:: ussl
:synopsis: TLS/SSL wrapper for socket objects
-This module provides access to Transport Layer Security (often known as
-“Secure Sockets Layerâ€) encryption and peer authentication facilities for
-network sockets, both client-side and server-side.
+This module provides access to Transport Layer Security (previously and
+widely known as “Secure Sockets Layerâ€) encryption and peer authentication
+facilities for network sockets, both client-side and server-side.
-.. only:: not port_wipy
+Functions
+---------
- Functions
- ---------
+.. function:: ssl.wrap_socket(sock, server_side=False, keyfile=None, certfile=None, cert_reqs=CERT_NONE, ca_certs=None)
- .. function:: ssl.wrap_socket(sock, server_side=False)
+ Takes a stream `sock` (usually usocket.socket instance of ``SOCK_STREAM`` type),
+ and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
+ an SSL context. Returned object has the usual stream interface methods like
+ `read()`, `write()`, etc. In MicroPython, the returned object does not expose
+ socket interface and methods like `recv()`, `send()`. In particular, a
+ server-side SSL socket should be created from a normal socket returned from
+ `accept()` on a non-SSL listening server socket.
- Takes a stream `sock` (usually usocket.socket instance of ``SOCK_STREAM`` type),
- and returns an instance of ssl.SSLSocket, which wraps the underlying stream in
- an SSL context. Returned object has the usual stream interface methods like
- `read()`, `write()`, etc. In MicroPython, the returned object does not expose
- socket interface and methods like `recv()`, `send()`. In particular, a
- server-side SSL socket should be created from a normal socket returned from
- `accept()` on a non-SSL listening server socket.
+ Depending on the underlying module implementation for a particular board,
+ some or all keyword arguments above may be not supported.
- .. warning::
+.. warning::
- Currently, this function does NOT validate server certificates, which makes
- an SSL connection established prone to man-in-the-middle attacks.
+ Some implementations of ``ssl`` module do NOT validate server certificates,
+ which makes an SSL connection established prone to man-in-the-middle attacks.
+Exceptions
+----------
-.. only:: port_wipy
+.. data:: ssl.SSLError
- Functions
- ---------
+ This exception does NOT exist. Instead its base class, OSError, is used.
- .. function:: ssl.wrap_socket(sock, keyfile=None, certfile=None, server_side=False, cert_reqs=CERT_NONE, ca_certs=None)
+Constants
+---------
- Takes an instance sock of socket.socket, and returns an instance of ssl.SSLSocket, a subtype of
- ``socket.socket``, which wraps the underlying socket in an SSL context. sock must be a ``SOCK_STREAM``
- socket and protocol number ``socket.IPPROTO_SEC``; other socket types are unsupported. Example::
+.. data:: ssl.CERT_NONE
+ ssl.CERT_OPTIONAL
+ ssl.CERT_REQUIRED
- import socket
- import ssl
- s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
- ss = ssl.wrap_socket(s)
- ss.connect(socket.getaddrinfo('www.google.com', 443)[0][-1])
-
- Certificates must be used in order to validate the other side of the connection, and also to
- authenticate ourselves with the other end. Such certificates must be stored as files using the
- FTP server, and they must be placed in specific paths with specific names.
-
- - The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
- - The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
- - The key for our own certificate goes in: **'/flash/cert/private.key'**
-
- .. note::
-
- When these files are stored, they are placed inside the internal **hidden** file system
- (just like firmware updates), and therefore they are never visible.
-
- For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
- in the `blynk examples folder `_
- and put it in '/flash/cert/'. Then do::
-
- import socket
- import ssl
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
- ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
- ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
-
- SSL sockets inherit all methods and from the standard sockets, see the :mod:`usocket` module.
-
- Exceptions
- ----------
-
- .. data:: ssl.SSLError
-
- Constants
- ---------
-
- .. data:: ssl.CERT_NONE
- .. data:: ssl.CERT_OPTIONAL
- .. data:: ssl.CERT_REQUIRED
-
- supported values in ``cert_reqs``
+ Supported values for `cert_reqs` parameter.
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index eca9bbe45..024f78966 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -254,6 +254,29 @@ SSL sockets need to be created the following way before wrapping them with.
s = socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
ss = ssl.wrap_socket(s)
+Certificates must be used in order to validate the other side of the connection, and also to
+authenticate ourselves with the other end. Such certificates must be stored as files using the
+FTP server, and they must be placed in specific paths with specific names.
+
+- The certificate to validate the other side goes in: **'/flash/cert/ca.pem'**
+- The certificate to authenticate ourselves goes in: **'/flash/cert/cert.pem'**
+- The key for our own certificate goes in: **'/flash/cert/private.key'**
+
+.. note::
+
+ When these files are stored, they are placed inside the internal **hidden** file system
+ (just like firmware updates), and therefore they are never visible.
+
+For instance to connect to the Blynk servers using certificates, take the file ``ca.pem`` located
+in the `blynk examples folder `_.
+and put it in '/flash/cert/'. Then do::
+
+ import socket
+ import ssl
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, socket.IPPROTO_SEC)
+ ss = ssl.wrap_socket(s, cert_reqs=ssl.CERT_REQUIRED, ca_certs='/flash/cert/ca.pem')
+ ss.connect(socket.getaddrinfo('cloud.blynk.cc', 8441)[0][-1])
+
Incompatibilities in uhashlib module
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From a8ece0358fd5821dd0e9f215f8d852a62de834c0 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 09:54:55 +0300
Subject: [PATCH 080/826] docs/machine.UART: Deconditionalize normal methods.
---
docs/library/machine.UART.rst | 22 ++++++++--------------
1 file changed, 8 insertions(+), 14 deletions(-)
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index fe7597eb5..55a5f354d 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -69,15 +69,14 @@ Methods
When no pins are given, then the default set of TX and RX pins is taken, and hardware
flow control will be disabled. If pins=None, no pin assignment will be made.
-.. only:: not port_esp8266
+.. method:: UART.deinit()
- .. method:: UART.deinit()
+ Turn off the UART bus.
- Turn off the UART bus.
+.. method:: UART.any()
- .. method:: UART.any()
-
- Return the number of characters available for reading.
+ Return true value if there're characters available for reading. On some
+ boards, the number of available characters is returned.
.. method:: UART.read([nbytes])
@@ -107,13 +106,10 @@ Methods
Return value: number of bytes written or ``None`` on timeout.
-.. only:: not port_esp8266
-
- .. method:: UART.sendbreak()
+.. method:: UART.sendbreak()
- Send a break condition on the bus. This drives the bus low for a duration
- of 13 bits.
- Return value: ``None``.
+ Send a break condition on the bus. This drives the bus low for a duration
+ longer than required for a normal transmission of a character.
.. only:: port_wipy
@@ -140,8 +136,6 @@ Methods
Returns an irq object.
-.. only:: not port_esp8266
-
Constants
---------
From 9ef6bb5480e38b4ce3d195511e1d43a04094d48e Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 10:12:01 +0300
Subject: [PATCH 081/826] docs/machine: Move machine.main() misnomer to wipy's
known issues.
---
docs/library/machine.rst | 7 -------
docs/wipy/general.rst | 10 ++++++++++
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index 1007f142f..dbf8b8b4c 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -85,13 +85,6 @@ Miscellaneous functions
.. only:: port_wipy
- .. function:: main(filename)
-
- Set the filename of the main script to run after boot.py is finished. If
- this function is not called then the default file main.py will be executed.
-
- It only makes sense to call this function from within boot.py.
-
.. function:: rng()
Return a 24-bit software generated random number.
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index 024f78966..b3d8e7892 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -296,3 +296,13 @@ Example::
...
hash.update('12345') # last chunk may be of any length
hash.digest()
+
+Unrelated function in machine module
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. function:: main(filename)
+
+ Set the filename of the main script to run after boot.py is finished. If
+ this function is not called then the default file main.py will be executed.
+
+ It only makes sense to call this function from within boot.py.
From a78703f188f5caef33a0dc3230291c939f3c3034 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 10:14:05 +0300
Subject: [PATCH 082/826] docs/library/machine: Typo fix in machine_callbacks
section.
---
docs/library/machine.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index dbf8b8b4c..ea11a1ff4 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -17,7 +17,7 @@ A note of callbacks used by functions and class methods of ``machine`` module:
all these callbacks should be considered as executing in an interrupt context.
This is true for both physical devices with IDs >= 0 and "virtual" devices
with negative IDs like -1 (these "virtual" devices are still thin shims on
-top of real hardware and real hardware intrerrupts). See :ref:`isr_rules`.
+top of real hardware and real hardware interrupts). See :ref:`isr_rules`.
Reset related functions
-----------------------
From 57b5ee2fcf190e2dcd583d0d0c7712101194fade Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 16 Apr 2017 17:24:15 +0300
Subject: [PATCH 083/826] tests/run-tests: Don't post-process CRASH result in
any way.
If we got a CRASH result, return early, similar to SKIP. This is important
because previous refactor changed branching logic a bit, so CRASH now gets
post-processed into CRASH\n, which broke remote hardware tests.
---
tests/run-tests | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tests/run-tests b/tests/run-tests
index 61726cc87..f24fc0961 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -145,7 +145,7 @@ def run_micropython(pyb, args, test_file, is_special=False):
output_mupy = output_mupy.replace(b'\r\n', b'\n')
# don't try to convert the output if we should skip this test
- if output_mupy == b'SKIP\n':
+ if output_mupy in (b'SKIP\n', b'CRASH'):
return output_mupy
if is_special or test_file in special_tests:
From e75fd3a8e995d4368a86f3050743e6b0709716f9 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 10:17:24 +1000
Subject: [PATCH 084/826] minimal/main: Make Cortex-M vector table constant.
---
minimal/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/minimal/main.c b/minimal/main.c
index 5cc88ff66..114fb9695 100644
--- a/minimal/main.c
+++ b/minimal/main.c
@@ -125,7 +125,7 @@ void Default_Handler(void) {
}
}
-uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = {
+const uint32_t isr_vector[] __attribute__((section(".isr_vector"))) = {
(uint32_t)&_estack,
(uint32_t)&Reset_Handler,
(uint32_t)&Default_Handler, // NMI_Handler
From fabaa6143745cf09928dfc13367ddc91e0eb9ad2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 12:13:51 +1000
Subject: [PATCH 085/826] docs/library/machine.UART: Remove pyboard-specific
section.
stmhal doesn't have a machine.UART class so this section is not needed.
---
docs/library/machine.UART.rst | 11 -----------
1 file changed, 11 deletions(-)
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index 55a5f354d..c29d079b7 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -32,17 +32,6 @@ using the standard stream methods::
uart.readinto(buf) # read and store into the given buffer
uart.write('abc') # write the 3 characters
-.. only:: port_pyboard
-
- Individual characters can be read/written using::
-
- uart.readchar() # read 1 character and returns it as an integer
- uart.writechar(42) # write 1 character
-
- To check if there is anything to be read, use::
-
- uart.any() # returns True if any characters waiting
-
Constructors
------------
From 8f205c2c9bed1f3f167f2b0a5abba1e676a6aa01 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 13:16:05 +1000
Subject: [PATCH 086/826] cc3200/mods/pybi2c: Make machine.I2C constructor/init
conform to HW API.
This is a user-facing change to the cc3200's API, to make it conform to the
new machine hardware API. The changes are:
- change I2C constructor to: I2C(id=0, *, freq=100000, scl=None, sda=None)
- change I2C init to: init(*, freq, scl, sda)
- removal of machine.I2C.MASTER constant
- I2C str/repr no longer prints I2C.MASTER
To update existing code it should be enough to just remove the I2C.MASTER
constant from contructor/init for I2C.
---
cc3200/mods/pybi2c.c | 75 ++++++++++++++++++--------------------------
1 file changed, 30 insertions(+), 45 deletions(-)
diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c
index a6009cb77..b2e536056 100644
--- a/cc3200/mods/pybi2c.c
+++ b/cc3200/mods/pybi2c.c
@@ -59,8 +59,6 @@ typedef struct _pyb_i2c_obj_t {
/******************************************************************************
DEFINE CONSTANTS
******************************************************************************/
-#define PYBI2C_MASTER (0)
-
#define PYBI2C_MIN_BAUD_RATE_HZ (50000)
#define PYBI2C_MAX_BAUD_RATE_HZ (400000)
@@ -79,7 +77,6 @@ typedef struct _pyb_i2c_obj_t {
DECLARE PRIVATE DATA
******************************************************************************/
STATIC pyb_i2c_obj_t pyb_i2c_obj = {.baudrate = 0};
-STATIC const mp_obj_t pyb_i2c_def_pin[2] = {&pin_GP13, &pin_GP23};
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -289,33 +286,34 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
STATIC void pyb_i2c_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) {
pyb_i2c_obj_t *self = self_in;
if (self->baudrate > 0) {
- mp_printf(print, "I2C(0, I2C.MASTER, baudrate=%u)", self->baudrate);
+ mp_printf(print, "I2C(0, baudrate=%u)", self->baudrate);
} else {
mp_print_str(print, "I2C(0)");
}
}
-STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *args) {
- // verify that mode is master
- if (args[0].u_int != PYBI2C_MASTER) {
- goto invalid_args;
- }
+STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ enum { ARG_scl, ARG_sda, ARG_freq };
+ static const mp_arg_t allowed_args[] = {
+ { MP_QSTR_scl, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_sda, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
+ { MP_QSTR_freq, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
+ };
+ mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
+ mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
// make sure the baudrate is between the valid range
- self->baudrate = MIN(MAX(args[1].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
+ self->baudrate = MIN(MAX(args[ARG_freq].u_int, PYBI2C_MIN_BAUD_RATE_HZ), PYBI2C_MAX_BAUD_RATE_HZ);
// assign the pins
- mp_obj_t pins_o = args[2].u_obj;
- if (pins_o != mp_const_none) {
- mp_obj_t *pins;
- if (pins_o == MP_OBJ_NULL) {
- // use the default pins
- pins = (mp_obj_t *)pyb_i2c_def_pin;
- } else {
- mp_obj_get_array_fixed_n(pins_o, 2, &pins);
- }
- pin_assign_pins_af (pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
+ mp_obj_t pins[2] = {&pin_GP13, &pin_GP23}; // default (SDA, SCL) pins
+ if (args[ARG_scl].u_obj != MP_OBJ_NULL) {
+ pins[1] = args[ARG_scl].u_obj;
+ }
+ if (args[ARG_sda].u_obj != MP_OBJ_NULL) {
+ pins[0] = args[ARG_sda].u_obj;
}
+ pin_assign_pins_af(pins, 2, PIN_TYPE_STD_PU, PIN_FN_I2C, 0);
// init the I2C bus
i2c_init(self);
@@ -324,44 +322,34 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *arg
pyb_sleep_add ((const mp_obj_t)self, (WakeUpCB_t)i2c_init);
return mp_const_none;
-
-invalid_args:
- mp_raise_ValueError(mpexception_value_invalid_arguments);
}
-STATIC const mp_arg_t pyb_i2c_init_args[] = {
- { MP_QSTR_id, MP_ARG_INT, {.u_int = 0} },
- { MP_QSTR_mode, MP_ARG_INT, {.u_int = PYBI2C_MASTER} },
- { MP_QSTR_baudrate, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 100000} },
- { MP_QSTR_pins, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
-};
STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
+ // check the id argument, if given
+ if (n_args > 0) {
+ if (all_args[0] != MP_OBJ_NEW_SMALL_INT(0)) {
+ mp_raise_OSError(MP_ENODEV);
+ }
+ --n_args;
+ ++all_args;
+ }
+
// parse args
mp_map_t kw_args;
mp_map_init_fixed_table(&kw_args, n_kw, all_args + n_args);
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args)];
- mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_i2c_init_args, args);
-
- // check the peripheral id
- if (args[0].u_int != 0) {
- mp_raise_OSError(MP_ENODEV);
- }
// setup the object
pyb_i2c_obj_t *self = &pyb_i2c_obj;
self->base.type = &pyb_i2c_type;
// start the peripheral
- pyb_i2c_init_helper(self, &args[1]);
+ pyb_i2c_init_helper(self, n_args, all_args, &kw_args);
return (mp_obj_t)self;
}
-STATIC mp_obj_t pyb_i2c_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
- // parse args
- mp_arg_val_t args[MP_ARRAY_SIZE(pyb_i2c_init_args) - 1];
- mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_i2c_init_args[1], args);
- return pyb_i2c_init_helper(pos_args[0], args);
+STATIC mp_obj_t pyb_i2c_init(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
+ return pyb_i2c_init_helper(pos_args[0], n_args - 1, pos_args + 1, kw_args);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_init_obj, 1, pyb_i2c_init);
@@ -532,9 +520,6 @@ STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem), (mp_obj_t)&pyb_i2c_readfrom_mem_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readfrom_mem_into), (mp_obj_t)&pyb_i2c_readfrom_mem_into_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_writeto_mem), (mp_obj_t)&pyb_i2c_writeto_mem_obj },
-
- // class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYBI2C_MASTER) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
From 27f0862550fe9008d3a3b784ac31c105134f1a69 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 13:20:07 +1000
Subject: [PATCH 087/826] docs/wipy/quickref: Update reference for change to
I2C API.
---
docs/wipy/quickref.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/wipy/quickref.rst b/docs/wipy/quickref.rst
index 2505eb35f..f60c81f5f 100644
--- a/docs/wipy/quickref.rst
+++ b/docs/wipy/quickref.rst
@@ -112,7 +112,7 @@ See :ref:`machine.I2C `. ::
from machine import I2C
# configure the I2C bus
- i2c = I2C(0, I2C.MASTER, baudrate=100000)
+ i2c = I2C(baudrate=100000)
i2c.scan() # returns list of slave addresses
i2c.writeto(0x42, 'hello') # send 5 bytes to slave with address 0x42
i2c.readfrom(0x42, 5) # receive 5 bytes from slave
From c49b265389c487ebeb12290fcbf7c0af89cdb038 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:04:30 +1000
Subject: [PATCH 088/826] docs/wipy/general: Add section about specifics of I2C
implementation.
---
docs/wipy/general.rst | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/docs/wipy/general.rst b/docs/wipy/general.rst
index b3d8e7892..8b9b91c53 100644
--- a/docs/wipy/general.rst
+++ b/docs/wipy/general.rst
@@ -240,6 +240,23 @@ Additional Pin methods:
Returns a list of the alternate functions supported by the pin. List items are
a tuple of the form: ``('ALT_FUN_NAME', ALT_FUN_INDEX)``
+Additional details for machine.I2C
+----------------------------------
+
+On the WiPy there is a single hardware I2C peripheral, identified by "0". By
+default this is the peripheral that is used when constructing an I2C instance.
+The default pins are GP23 for SCL and GP13 for SDA, and one can create the
+default I2C peripheral simply by doing::
+
+ i2c = machine.I2C()
+
+The pins and frequency can be specified as::
+
+ i2c = machine.I2C(freq=400000, scl='GP23', sda='GP13')
+
+Only certain pins can be used as SCL/SDA. Please refer to the pinout for further
+information.
+
Known issues
------------
From 1f1a03d0c39f3b733372e523bc4906a2b40cfff0 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:04:51 +1000
Subject: [PATCH 089/826] docs/library/machine.I2C: Deconditionalise all
methods.
The cc3200 port is now similar enough to the standard machine.I2C API so
that all conditionals can be removed.
---
docs/library/machine.I2C.rst | 104 +++++++++++------------------------
1 file changed, 31 insertions(+), 73 deletions(-)
diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst
index 45944709e..e62d465e0 100644
--- a/docs/library/machine.I2C.rst
+++ b/docs/library/machine.I2C.rst
@@ -9,86 +9,55 @@ level it consists of 2 wires: SCL and SDA, the clock and data lines respectively
I2C objects are created attached to a specific bus. They can be initialised
when created, or initialised later on.
-.. only:: port_wipy
+Printing the I2C object gives you information about its configuration.
- Example::
+Example usage::
- from machine import I2C
+ from machine import I2C
- i2c = I2C(0) # create on bus 0
- i2c = I2C(0, I2C.MASTER) # create and init as a master
- i2c.init(I2C.MASTER, baudrate=20000) # init as a master
- i2c.deinit() # turn off the peripheral
+ i2c = I2C(freq=400000) # create I2C peripheral at frequency of 400kHz
+ # depending on the port, extra parameters may be required
+ # to select the peripheral and/or pins to use
-Printing the i2c object gives you information about its configuration.
+ i2c.scan() # scan for slaves, returning a list of 7-bit addresses
-.. only:: port_wipy
+ i2c.writeto(42, b'123') # write 3 bytes to slave with 7-bit address 42
+ i2c.readfrom(42, 4) # read 4 bytes from slave with 7-bit address 42
- A master must specify the recipient's address::
-
- i2c.init(I2C.MASTER)
- i2c.writeto(0x42, '123') # send 3 bytes to slave with address 0x42
- i2c.writeto(addr=0x42, b'456') # keyword for address
-
- Master also has other methods::
-
- i2c.scan() # scan for slaves on the bus, returning
- # a list of valid addresses
- i2c.readfrom_mem(0x42, 2, 3) # read 3 bytes from memory of slave 0x42,
- # starting at address 2 in the slave
- i2c.writeto_mem(0x42, 2, 'abc') # write 'abc' (3 bytes) to memory of slave 0x42
- # starting at address 2 in the slave, timeout after 1 second
+ i2c.readfrom_mem(42, 8, 3) # read 3 bytes from memory of slave 42,
+ # starting at memory-address 8 in the slave
+ i2c.writeto_mem(42, 2, b'\x10') # write 1 byte to memory of slave 42
+ # starting at address 2 in the slave
Constructors
------------
-.. only:: port_wipy
-
- .. class:: I2C(bus, ...)
-
- Construct an I2C object on the given bus. `bus` can only be 0.
- If the bus is not given, the default one will be selected (0).
+.. class:: I2C(id=-1, \*, scl, sda, freq=400000)
-.. only:: not port_wipy
+ Construct and return a new I2C object using the following parameters:
- .. class:: I2C(id=-1, \*, scl, sda, freq=400000)
-
- Construct and return a new I2C object using the following parameters:
-
- - `id` identifies the particular I2C peripheral. The default
- value of -1 selects a software implementation of I2C which can
- work (in most cases) with arbitrary pins for SCL and SDA.
- If `id` is -1 then `scl` and `sda` must be specified. Other
- allowed values for `id` depend on the particular port/board,
- and specifying `scl` and `sda` may or may not be required or
- allowed in this case.
- - `scl` should be a pin object specifying the pin to use for SCL.
- - `sda` should be a pin object specifying the pin to use for SDA.
- - `freq` should be an integer which sets the maximum frequency
- for SCL.
+ - `id` identifies the particular I2C peripheral. The default
+ value of -1 selects a software implementation of I2C which can
+ work (in most cases) with arbitrary pins for SCL and SDA.
+ If `id` is -1 then `scl` and `sda` must be specified. Other
+ allowed values for `id` depend on the particular port/board,
+ and specifying `scl` and `sda` may or may not be required or
+ allowed in this case.
+ - `scl` should be a pin object specifying the pin to use for SCL.
+ - `sda` should be a pin object specifying the pin to use for SDA.
+ - `freq` should be an integer which sets the maximum frequency
+ for SCL.
General Methods
---------------
-.. only:: port_wipy
-
- .. method:: I2C.init(mode, \*, baudrate=100000, pins=(SDA, SCL))
-
- Initialise the I2C bus with the given parameters:
+.. method:: I2C.init(scl, sda, \*, freq=400000)
- - ``mode`` must be ``I2C.MASTER``
- - ``baudrate`` is the SCL clock rate
- - ``pins`` is an optional tuple with the pins to assign to the I2C bus.
+ Initialise the I2C bus with the given arguments:
-.. only:: port_esp8266
-
- .. method:: I2C.init(scl, sda, \*, freq=400000)
-
- Initialise the I2C bus with the given arguments:
-
- - `scl` is a pin object for the SCL line
- - `sda` is a pin object for the SDA line
- - `freq` is the SCL clock rate
+ - `scl` is a pin object for the SCL line
+ - `sda` is a pin object for the SDA line
+ - `freq` is the SCL clock rate
.. method:: I2C.deinit()
@@ -102,8 +71,6 @@ General Methods
those that respond. A device responds if it pulls the SDA line low after
its address (including a write bit) is sent on the bus.
- Note: on WiPy the I2C object must be in master mode for this method to be valid.
-
Primitive I2C operations
------------------------
@@ -204,12 +171,3 @@ methods are convenience functions to communicate with such devices.
On WiPy the return value is the number of bytes written. Otherwise the
return value is `None`.
-
-Constants
----------
-
-.. data:: I2C.MASTER
-
- for initialising the bus to master mode
-
- Availability: WiPy.
From d4675e7674788546420ac6a89a42f8afda191488 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:27:37 +1000
Subject: [PATCH 090/826] docs/library/machine.*: Add cross-reference label to
individual classes.
---
docs/library/machine.ADC.rst | 1 +
docs/library/machine.I2C.rst | 1 +
docs/library/machine.Pin.rst | 1 +
docs/library/machine.RTC.rst | 1 +
docs/library/machine.SD.rst | 1 +
docs/library/machine.SPI.rst | 1 +
docs/library/machine.Timer.rst | 1 +
docs/library/machine.UART.rst | 1 +
docs/library/machine.WDT.rst | 1 +
9 files changed, 9 insertions(+)
diff --git a/docs/library/machine.ADC.rst b/docs/library/machine.ADC.rst
index 2752878ff..4c7a04d74 100644
--- a/docs/library/machine.ADC.rst
+++ b/docs/library/machine.ADC.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.ADC:
class ADC -- analog to digital conversion
=========================================
diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst
index e62d465e0..e2eb62ca3 100644
--- a/docs/library/machine.I2C.rst
+++ b/docs/library/machine.I2C.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.I2C:
class I2C -- a two-wire serial protocol
=======================================
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index 216ebcb2a..369c08f44 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.Pin:
class Pin -- control I/O pins
=============================
diff --git a/docs/library/machine.RTC.rst b/docs/library/machine.RTC.rst
index 6dc8b3e9a..2a53b9146 100644
--- a/docs/library/machine.RTC.rst
+++ b/docs/library/machine.RTC.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.RTC:
class RTC -- real time clock
============================
diff --git a/docs/library/machine.SD.rst b/docs/library/machine.SD.rst
index 21c28aa20..0eb024602 100644
--- a/docs/library/machine.SD.rst
+++ b/docs/library/machine.SD.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.SD:
class SD -- secure digital memory card
======================================
diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst
index 82858629f..fbb44d038 100644
--- a/docs/library/machine.SPI.rst
+++ b/docs/library/machine.SPI.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.SPI:
class SPI -- a Serial Peripheral Interface bus protocol (master side)
=====================================================================
diff --git a/docs/library/machine.Timer.rst b/docs/library/machine.Timer.rst
index eddb2ce78..ef46f9dd7 100644
--- a/docs/library/machine.Timer.rst
+++ b/docs/library/machine.Timer.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.Timer:
class Timer -- control hardware timers
======================================
diff --git a/docs/library/machine.UART.rst b/docs/library/machine.UART.rst
index c29d079b7..0b2ebbd0b 100644
--- a/docs/library/machine.UART.rst
+++ b/docs/library/machine.UART.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.UART:
class UART -- duplex serial communication bus
=============================================
diff --git a/docs/library/machine.WDT.rst b/docs/library/machine.WDT.rst
index 1d79b4c4e..5ca6dce45 100644
--- a/docs/library/machine.WDT.rst
+++ b/docs/library/machine.WDT.rst
@@ -1,4 +1,5 @@
.. currentmodule:: machine
+.. _machine.WDT:
class WDT -- watchdog timer
===========================
From daa5ba5629c8211a3f13e3854acea0bc36071f56 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:28:18 +1000
Subject: [PATCH 091/826] docs/esp8266/quickref: Add links from quickref page
to machine classes.
---
docs/esp8266/quickref.rst | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/docs/esp8266/quickref.rst b/docs/esp8266/quickref.rst
index 845a94ba7..5ff33e02b 100644
--- a/docs/esp8266/quickref.rst
+++ b/docs/esp8266/quickref.rst
@@ -88,7 +88,7 @@ Use the :mod:`time ` module::
Timers
------
-Virtual (RTOS-based) timers are supported. Use the ``machine.Timer`` class
+Virtual (RTOS-based) timers are supported. Use the :ref:`machine.Timer ` class
with timer ID of -1::
from machine import Timer
@@ -102,7 +102,7 @@ The period is in milliseconds.
Pins and GPIO
-------------
-Use the ``machine.Pin`` class::
+Use the :ref:`machine.Pin ` class::
from machine import Pin
@@ -155,7 +155,7 @@ ADC (analog to digital conversion)
ADC is available on a dedicated pin.
Note that input voltages on the ADC pin must be between 0v and 1.0v.
-Use the ``machine.ADC`` class::
+Use the :ref:`machine.ADC ` class::
from machine import ADC
@@ -166,7 +166,8 @@ Software SPI bus
----------------
There are two SPI drivers. One is implemented in software (bit-banging)
-and works on all pins::
+and works on all pins, and is accessed via the :ref:`machine.SPI `
+class::
from machine import Pin, SPI
@@ -208,7 +209,8 @@ constructor and init (as those are fixed)::
I2C bus
-------
-The I2C driver is implemented in software and works on all pins::
+The I2C driver is implemented in software and works on all pins,
+and is accessed via the :ref:`machine.I2C ` class::
from machine import Pin, I2C
From 9d7c53734c5eee6b4fbcc18be59148bbdaf95a1d Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:31:08 +1000
Subject: [PATCH 092/826] cc3200/mods/pybi2c: Make
readfnom_mem_into/writeto_mem return None.
This aligns the I2C class to match the standard machine.I2C API.
Note that this is a (small) breaking change to the existing cc3200 API.
The original API just returned the size of the input buffer so there's no
information lost by this change. To update scripts users should just use
the size of the buffer passed to these functions to get the number of bytes
that are read/written.
---
cc3200/mods/pybi2c.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c
index b2e536056..9fc97d914 100644
--- a/cc3200/mods/pybi2c.c
+++ b/cc3200/mods/pybi2c.c
@@ -477,7 +477,7 @@ STATIC mp_obj_t pyb_i2c_readfrom_mem_into(mp_uint_t n_args, const mp_obj_t *pos_
// get the buffer to read into
vstr_t vstr;
pyb_i2c_readmem_into (args, &vstr);
- return mp_obj_new_int(vstr.len);
+ return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_readfrom_mem_into_obj, 1, pyb_i2c_readfrom_mem_into);
@@ -501,8 +501,7 @@ STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args,
// write the register address to write to.
if (pyb_i2c_mem_write (i2c_addr, (byte *)&mem_addr, mem_addr_size, bufinfo.buf, bufinfo.len)) {
- // return the number of bytes written
- return mp_obj_new_int(bufinfo.len);
+ return mp_const_none;
}
mp_raise_OSError(MP_EIO);
From 850f79e552a170912cfd88f5001a9ac343a22f5d Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:39:27 +1000
Subject: [PATCH 093/826] docs/library/machine.I2C: Remove WiPy-specific return
values.
cc3200 has been updated to conform to the API and now returns None.
---
docs/library/machine.I2C.rst | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/docs/library/machine.I2C.rst b/docs/library/machine.I2C.rst
index e2eb62ca3..a1b417890 100644
--- a/docs/library/machine.I2C.rst
+++ b/docs/library/machine.I2C.rst
@@ -160,8 +160,7 @@ methods are convenience functions to communicate with such devices.
The argument `addrsize` specifies the address size in bits (on ESP8266
this argument is not recognised and the address size is always 8 bits).
- On WiPy the return value is the number of bytes read. Otherwise the
- return value is `None`.
+ The method returns `None`.
.. method:: I2C.writeto_mem(addr, memaddr, buf, \*, addrsize=8)
@@ -170,5 +169,4 @@ methods are convenience functions to communicate with such devices.
The argument `addrsize` specifies the address size in bits (on ESP8266
this argument is not recognised and the address size is always 8 bits).
- On WiPy the return value is the number of bytes written. Otherwise the
- return value is `None`.
+ The method returns `None`.
From 29b26f392283edbdd18808d450ab7dd649dbc200 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 15:40:04 +1000
Subject: [PATCH 094/826] docs/library/machine.SPI: Fix formatting of bullet
list to stop warning.
---
docs/library/machine.SPI.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst
index fbb44d038..080f6fdfb 100644
--- a/docs/library/machine.SPI.rst
+++ b/docs/library/machine.SPI.rst
@@ -45,7 +45,7 @@ Methods
a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver
(``id`` = -1).
- ``pins`` - WiPy port doesn't ``sck``, ``mosi``, ``miso`` arguments, and instead allows to
- specify them as a tuple of ``pins`` parameter.
+ specify them as a tuple of ``pins`` parameter.
.. method:: SPI.deinit()
From bbb4b9822f094825d7e7fd1f7df716adc2598685 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Mon, 10 Apr 2017 17:19:36 +1000
Subject: [PATCH 095/826] py/modmicropython: Add micropython.kbd_intr()
function.
It controls the character that's used to (asynchronously) raise a
KeyboardInterrupt exception. Passing "-1" allows to disable the
interception of the interrupt character (as long as a port allows such a
behaviour).
---
py/modmicropython.c | 12 ++++++++++++
py/mpconfig.h | 2 +-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/py/modmicropython.c b/py/modmicropython.c
index a74e6aa3c..d76706230 100644
--- a/py/modmicropython.c
+++ b/py/modmicropython.c
@@ -31,6 +31,7 @@
#include "py/stackctrl.h"
#include "py/runtime.h"
#include "py/gc.h"
+#include "py/mphal.h"
// Various builtins specific to MicroPython runtime,
// living in micropython module
@@ -129,6 +130,14 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_micropython_heap_unlock_obj, mp_micropython_
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_emergency_exception_buf);
#endif
+#if MICROPY_KBD_EXCEPTION
+STATIC mp_obj_t mp_micropython_kbd_intr(mp_obj_t int_chr_in) {
+ mp_hal_set_interrupt_char(mp_obj_get_int(int_chr_in));
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_micropython_kbd_intr_obj, mp_micropython_kbd_intr);
+#endif
+
#if MICROPY_ENABLE_SCHEDULER
STATIC mp_obj_t mp_micropython_schedule(mp_obj_t function, mp_obj_t arg) {
if (!mp_sched_schedule(function, arg)) {
@@ -162,6 +171,9 @@ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_heap_lock), MP_ROM_PTR(&mp_micropython_heap_lock_obj) },
{ MP_ROM_QSTR(MP_QSTR_heap_unlock), MP_ROM_PTR(&mp_micropython_heap_unlock_obj) },
#endif
+ #if MICROPY_KBD_EXCEPTION
+ { MP_ROM_QSTR(MP_QSTR_kbd_intr), MP_ROM_PTR(&mp_micropython_kbd_intr_obj) },
+ #endif
#if MICROPY_ENABLE_SCHEDULER
{ MP_ROM_QSTR(MP_QSTR_schedule), MP_ROM_PTR(&mp_micropython_schedule_obj) },
#endif
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 05cb5daaf..b6e24d205 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -445,7 +445,7 @@
# endif
#endif
-// Whether to provide the mp_kbd_exception object
+// Whether to provide the mp_kbd_exception object, and micropython.kbd_intr function
#ifndef MICROPY_KBD_EXCEPTION
#define MICROPY_KBD_EXCEPTION (0)
#endif
From c7c14f163458046767b539c567a421076ea9a6b7 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 16:21:47 +1000
Subject: [PATCH 096/826] tests/micropython: Add test for
micropython.kbd_intr().
---
tests/micropython/kbd_intr.py | 13 +++++++++++++
tests/micropython/kbd_intr.py.exp | 0
2 files changed, 13 insertions(+)
create mode 100644 tests/micropython/kbd_intr.py
create mode 100644 tests/micropython/kbd_intr.py.exp
diff --git a/tests/micropython/kbd_intr.py b/tests/micropython/kbd_intr.py
new file mode 100644
index 000000000..a7ce7464b
--- /dev/null
+++ b/tests/micropython/kbd_intr.py
@@ -0,0 +1,13 @@
+# test the micropython.kbd_intr() function
+
+import micropython
+
+try:
+ micropython.kbd_intr
+except AttributeError:
+ print('SKIP')
+ import sys
+ sys.exit()
+
+# just check we can actually call it
+micropython.kbd_intr(3)
diff --git a/tests/micropython/kbd_intr.py.exp b/tests/micropython/kbd_intr.py.exp
new file mode 100644
index 000000000..e69de29bb
From 1f3887dc28a7ee1f5671fcc194930fa33a60ece5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Henrik=20S=C3=B6lver?=
Date: Thu, 13 Apr 2017 21:38:17 +0200
Subject: [PATCH 097/826] stmhal/timer: Clear interrupt flag before setting
callback.
Sometimes when setting a channel callback the callback fires immediately,
even if the compare register is set to a value far into the future. This
happens when the free running counter has previously been equal to what
happens to be in the compare register.
This patch make sure that there is no pending interrupt when setting a
callback.
---
stmhal/timer.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 7f0a70c5e..5a574867b 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -1302,6 +1302,7 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
} else if (mp_obj_is_callable(callback)) {
self->callback = callback;
uint8_t tim_id = self->timer->tim_id;
+ __HAL_TIM_CLEAR_IT(&self->timer->tim, TIMER_IRQ_MASK(self->channel));
if (tim_id == 1) {
HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);
#if defined(TIM8) // STM32F401 doesn't have a TIM8
From 58467709972724ac94f6488fefe6d066bfa1589e Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 19 Apr 2017 13:27:51 +0300
Subject: [PATCH 098/826] zephyr/modmachine: Implement machine.reset().
---
zephyr/modmachine.c | 6 +++++-
zephyr/prj_base.conf | 1 +
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/zephyr/modmachine.c b/zephyr/modmachine.c
index 4013815d1..5909c37d6 100644
--- a/zephyr/modmachine.c
+++ b/zephyr/modmachine.c
@@ -28,6 +28,7 @@
#include
#include
+#include
#include "py/obj.h"
#include "py/runtime.h"
@@ -40,7 +41,8 @@
#if MICROPY_PY_MACHINE
STATIC mp_obj_t machine_reset(void) {
- printf("Warning: %s is not implemented\n", __func__);
+ sys_reboot(SYS_REBOOT_COLD);
+ // Won't get here, Zephyr has infiniloop on its side
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset);
@@ -53,7 +55,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ #ifdef CONFIG_REBOOT
{ MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
+ #endif
{ MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
{ MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&machine_pin_type) },
diff --git a/zephyr/prj_base.conf b/zephyr/prj_base.conf
index fc51ccec6..1a0b40711 100644
--- a/zephyr/prj_base.conf
+++ b/zephyr/prj_base.conf
@@ -1,4 +1,5 @@
CONFIG_LEGACY_KERNEL=n
+CONFIG_REBOOT=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_CONSOLE_HANDLER=y
From 67d141cb95d0ff57300d07e6f966ef469a4bbcae Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 21 Apr 2017 11:06:47 +1000
Subject: [PATCH 099/826] esp32: Update to latest ESP IDF.
---
esp32/Makefile | 30 ++++++++++++++++++++++--------
esp32/esp32.custom_common.ld | 8 +++++---
esp32/sdkconfig.h | 9 +++++++--
3 files changed, 34 insertions(+), 13 deletions(-)
diff --git a/esp32/Makefile b/esp32/Makefile
index 3cbf0b308..0a99f0e54 100644
--- a/esp32/Makefile
+++ b/esp32/Makefile
@@ -29,7 +29,7 @@ ESPCOMP = $(ESPIDF)/components
ESPTOOL ?= $(ESPCOMP)/esptool_py/esptool/esptool.py
# verify the ESP IDF version
-ESPIDF_SUPHASH := 375b28650bd1c90d6ac706f63cde9a64d9a7e3e5
+ESPIDF_SUPHASH := f73c6f875cc564fa6c9962be71eac4dbdc56aa63
ESPIDF_CURHASH := $(shell git -C $(ESPIDF) show -s --pretty=format:'%H')
ifneq ($(ESPIDF_CURHASH),$(ESPIDF_SUPHASH))
$(info ** WARNING **)
@@ -55,6 +55,7 @@ INC += -I$(ESPCOMP)/driver/include/driver
INC += -I$(ESPCOMP)/nghttp/port/include
INC += -I$(ESPCOMP)/nghttp/include
INC += -I$(ESPCOMP)/esp32/include
+INC += -I$(ESPCOMP)/soc/esp32/include
INC += -I$(ESPCOMP)/ethernet/include
INC += -I$(ESPCOMP)/expat/include/expat
INC += -I$(ESPCOMP)/expat/port/include
@@ -90,7 +91,7 @@ LDFLAGS = -nostdlib -Map=$(@:.elf=.map) --cref
LDFLAGS += --gc-sections -static -EL
LDFLAGS += -u call_user_start_cpu0 -u uxTopUsedPriority
LDFLAGS += -u __cxa_guard_dummy # so that implementation of static guards is taken from cxx_guards.o instead of libstdc++.a
-LDFLAGS += -L$(ESPCOMP)/esp32/ld -T $(BUILD)/esp32_out.ld -T ./esp32.custom_common.ld -T esp32.rom.ld -T esp32.peripherals.ld
+LDFLAGS += -L$(ESPCOMP)/esp32/ld -T $(BUILD)/esp32_out.ld -T ./esp32.custom_common.ld -T esp32.rom.ld -T esp32.rom.spiflash.ld -T esp32.peripherals.ld
LIBGCC_FILE_NAME = $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
LIBSTDCXX_FILE_NAME = $(shell $(CXX) $(CXXFLAGS) -print-file-name=libstdc++.a)
@@ -207,9 +208,12 @@ ESPIDF_DRIVER_O = $(addprefix $(ESPCOMP)/driver/,\
)
ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\
+ app_trace.o \
panic.o \
event_default_handlers.o \
task_wdt.o \
+ cache_err_int.o \
+ core_dump.o \
cpu_start.o \
gdbstub.o \
crosscore_int.o \
@@ -219,18 +223,26 @@ ESPIDF_ESP32_O = $(addprefix $(ESPCOMP)/esp32/,\
int_wdt.o \
event_loop.o \
cpu_freq.o \
- brownout.o \
hwcrypto/sha.o \
hwcrypto/aes.o \
lib_printf.o \
freertos_hooks.o \
- cpu_util.o \
system_api.o \
hw_random.o \
phy_init.o \
intr_alloc.o \
)
+ESPIDF_SOC_O = $(addprefix $(ESPCOMP)/soc/,\
+ esp32/brownout.o \
+ esp32/cpu_util.o \
+ esp32/rtc_clk.o \
+ esp32/rtc_init.o \
+ esp32/rtc_pm.o \
+ esp32/rtc_sleep.o \
+ esp32/rtc_time.o \
+ )
+
ESPIDF_CXX_O = $(addprefix $(ESPCOMP)/cxx/,\
cxx_guards.o \
)
@@ -254,7 +266,7 @@ ESPIDF_EXPAT_O = $(addprefix $(ESPCOMP)/expat/,\
# Assembler .S files need only basic flags, and in particular should not have
# -Os because that generates subtly different code.
-CFLAGS_ASM = -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I.
+CFLAGS_ASM = -I$(ESPCOMP)/esp32/include -I$(ESPCOMP)/soc/esp32/include -I$(ESPCOMP)/freertos/include/freertos -I.
$(BUILD)/$(ESPCOMP)/freertos/portasm.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/xtensa_context.o: CFLAGS = $(CFLAGS_ASM)
$(BUILD)/$(ESPCOMP)/freertos/xtensa_intr_asm.o: CFLAGS = $(CFLAGS_ASM)
@@ -368,7 +380,6 @@ ESPIDF_LWIP_O = $(addprefix $(ESPCOMP)/lwip/,\
api/err.o \
api/api_msg.o \
api/sockets.o \
- api/lwip_debug.o \
apps/sntp/sntp.o \
apps/dhcpserver.o \
core/ipv4/ip_frag.o \
@@ -523,6 +534,7 @@ OBJ_ESPIDF =
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_NEWLIB_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_DRIVER_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ESP32_O))
+OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_SOC_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_CXX_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_ETHERNET_O))
OBJ_ESPIDF += $(addprefix $(BUILD)/, $(ESPIDF_EXPAT_O))
@@ -574,7 +586,7 @@ APP_LD_ARGS += -L$(dir $(LIBSTDCXX_FILE_NAME)) -lstdc++
APP_LD_ARGS += $(ESPCOMP)/newlib/lib/libc.a
APP_LD_ARGS += $(ESPCOMP)/newlib/lib/libm.a
APP_LD_ARGS += $(ESPCOMP)/esp32/libhal.a
-APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lnet80211 -lphy -lrtc -lrtc_clk -lrtc_pm -lpp -lwpa -lsmartconfig -lcoexist
+APP_LD_ARGS += -L$(ESPCOMP)/esp32/lib -lcore -lnet80211 -lphy -lrtc -lpp -lwpa -lsmartconfig -lcoexist
APP_LD_ARGS += $(OBJ)
APP_LD_ARGS += --end-group
@@ -620,6 +632,7 @@ BOOTLOADER_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\
bootloader_support/src/flash_partitions.o \
log/log.o \
spi_flash/spi_flash_rom_patch.o \
+ soc/esp32/rtc_clk.o \
micro-ecc/micro-ecc/uECC.o \
bootloader/src/main/bootloader_start.o \
)
@@ -627,7 +640,7 @@ BOOTLOADER_OBJ = $(addprefix $(BUILD)/bootloader/$(ESPCOMP)/,\
BOOTLOADER_LIBS =
BOOTLOADER_LIBS += -Wl,--start-group
BOOTLOADER_LIBS += $(BOOTLOADER_OBJ)
-BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc -lrtc_clk
+BOOTLOADER_LIBS += -L$(ESPCOMP)/esp32/lib -lrtc
BOOTLOADER_LIBS += -L$(dir $(LIBGCC_FILE_NAME)) -lgcc
BOOTLOADER_LIBS += -Wl,--end-group
@@ -643,6 +656,7 @@ BOOTLOADER_LDFLAGS += -Wl,-Map=$(@:.elf=.map) -Wl,--cref
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/src/main/esp32.bootloader.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/bootloader/src/main/esp32.bootloader.rom.ld
BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.ld
+BOOTLOADER_LDFLAGS += -T $(ESPCOMP)/esp32/ld/esp32.rom.spiflash.ld
BOOTLOADER_OBJ_DIRS = $(sort $(dir $(BOOTLOADER_OBJ)))
$(BOOTLOADER_OBJ): | $(BOOTLOADER_OBJ_DIRS)
diff --git a/esp32/esp32.custom_common.ld b/esp32/esp32.custom_common.ld
index ed36525fb..2a329a29e 100644
--- a/esp32/esp32.custom_common.ld
+++ b/esp32/esp32.custom_common.ld
@@ -86,10 +86,10 @@ SECTIONS
*esp32/panic.o(.literal .text .literal.* .text.*)
*esp32/core_dump.o(.literal .text .literal.* .text.*)
*esp32/heap_alloc_caps.o(.literal .text .literal.* .text.*)
+ *esp32/app_trace.o(.literal .text .literal.* .text.*)
*libphy.a:(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
- *librtc_clk.a:(.literal .text .literal.* .text.*)
- *librtc_pm.a:(.literal .text .literal.* .text.*)
+ *libsoc.a:(.literal .text .literal.* .text.*)
*libpp.a:pp.o(.literal .text .literal.* .text.*)
*libpp.a:lmac.o(.literal .text .literal.* .text.*)
*libpp.a:wdev.o(.literal .text .literal.* .text.*)
@@ -97,6 +97,7 @@ SECTIONS
*libnet80211.a:ieee80211_misc.o(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libcoexist.a:(.literal .text .literal.* .text.*)
+ *spi_flash/spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
*py/scheduler.o*(.literal .text .literal.* .text.*)
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
@@ -116,7 +117,8 @@ SECTIONS
KEEP(*(.gnu.linkonce.s2.*))
KEEP(*(.jcr))
*(.dram1 .dram1.*)
- *libesp32.a:panic.o(.rodata .rodata.*)
+ *esp32/panic.o(.rodata .rodata.*)
+ *esp32/app_trace.o(.rodata .rodata.*)
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} >dram0_0_seg
diff --git a/esp32/sdkconfig.h b/esp32/sdkconfig.h
index 44bacd23c..886c31d28 100644
--- a/esp32/sdkconfig.h
+++ b/esp32/sdkconfig.h
@@ -4,6 +4,9 @@
#define CONFIG_PHY_DATA_OFFSET 0xf000
#define CONFIG_APP_OFFSET 0x10000
+#define CONFIG_SPI_FLASH_ROM_DRIVER_PATCH 1
+
+#define CONFIG_ESP32_APPTRACE_DEST_NONE 1
#define CONFIG_ESP32_PHY_AUTO_INIT 1
#define CONFIG_ESP32_PHY_MAX_TX_POWER 20
#define CONFIG_ESP32_PANIC_PRINT_REBOOT 1
@@ -15,11 +18,14 @@
#define CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY 0
#define CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE 1
#define CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE 1
+#define CONFIG_ESP32_WIFI_AMPDU_ENABLED 1
+#define CONFIG_ESP32_WIFI_NVS_ENABLED 1
#define CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM 10
#define CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM 0
#define CONFIG_ESP32_WIFI_TX_BUFFER_TYPE 1
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER 1
#define CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM 32
+#define CONFIG_FOUR_MAC_ADDRESS_FROM_EFUSE 1
#define CONFIG_NUMBER_OF_MAC_ADDRESS_GENERATED_FROM_EFUSE 4
#define CONFIG_INT_WDT 1
@@ -51,7 +57,6 @@
#define CONFIG_TIMER_TASK_STACK_DEPTH 2048
#define CONFIG_TIMER_QUEUE_LENGTH 10
-#define CONFIG_SECURE_BOOTLOADER_DISABLED 1
#define CONFIG_NEWLIB_STDOUT_ADDCR 1
#define CONFIG_PHY_ENABLED 1
#define CONFIG_WIFI_ENABLED 1
@@ -74,13 +79,13 @@
#define CONFIG_LOG_BOOTLOADER_LEVEL 2
#define CONFIG_LWIP_THREAD_LOCAL_STORAGE_INDEX 0
+#define CONFIG_LWIP_DHCP_DOES_ARP_CHECK 1
#define CONFIG_LWIP_DHCP_MAX_NTP_SERVERS 1
#define CONFIG_LWIP_MAX_SOCKETS 8
#define CONFIG_LWIP_SO_REUSE 1
#define CONFIG_TCP_MAXRTX 12
#define CONFIG_TCP_SYNMAXRTX 6
-#define CONFIG_MBEDTLS_MPI_INTERRUPT_NUM 18
#define CONFIG_MBEDTLS_HARDWARE_AES 1
#define CONFIG_MBEDTLS_HARDWARE_MPI 1
#define CONFIG_MBEDTLS_HARDWARE_SHA 1
From 7a72c0db5a6c2b1f0978516134a95bb6867706ef Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 19 Apr 2017 18:46:53 +1000
Subject: [PATCH 100/826] py: Reduce str/repr precision of float numbers when
floats are 30-bit.
With 30-bit floats there aren't enough bits to faithfully print 7 decimal
digits, so reduce the precision to 6 digits.
---
py/objcomplex.c | 4 ++++
py/objfloat.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/py/objcomplex.c b/py/objcomplex.c
index 7ec47edb5..5f9183f0e 100644
--- a/py/objcomplex.c
+++ b/py/objcomplex.c
@@ -50,7 +50,11 @@ STATIC void complex_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_
mp_obj_complex_t *o = MP_OBJ_TO_PTR(o_in);
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
+ #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
+ const int precision = 6;
+ #else
const int precision = 7;
+ #endif
#else
char buf[32];
const int precision = 16;
diff --git a/py/objfloat.c b/py/objfloat.c
index 5cf995417..d0e616612 100644
--- a/py/objfloat.c
+++ b/py/objfloat.c
@@ -113,7 +113,11 @@ STATIC void float_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t
mp_float_t o_val = mp_obj_float_get(o_in);
#if MICROPY_FLOAT_IMPL == MICROPY_FLOAT_IMPL_FLOAT
char buf[16];
+ #if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C
+ const int precision = 6;
+ #else
const int precision = 7;
+ #endif
#else
char buf[32];
const int precision = 16;
From 3e5cd35a9f6b2877f72f4af6865f14363826de4c Mon Sep 17 00:00:00 2001
From: stijn
Date: Fri, 21 Apr 2017 13:17:15 +0200
Subject: [PATCH 101/826] windows: Bring mpconfigport.h up-to-date with unix
port
Add definitions/source files for features which work on the windows
ports but weren't yet enabled.
UTIME related lines are moved a couple of lines up to make comparision
with unix/mpconfigport.h easier in the future.
---
windows/mpconfigport.h | 16 ++++++++++++++--
windows/msvc/sources.props | 2 ++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index b91662af4..cad76e781 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -32,6 +32,7 @@
#endif
#define MICROPY_ALLOC_PATH_MAX (260) //see minwindef.h for msvc or limits.h for mingw
+#define MICROPY_PERSISTENT_CODE_LOAD (1)
#define MICROPY_EMIT_X64 (0)
#define MICROPY_EMIT_THUMB (0)
#define MICROPY_EMIT_INLINE_THUMB (0)
@@ -43,6 +44,7 @@
#define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1)
#define MICROPY_MEM_STATS (1)
#define MICROPY_DEBUG_PRINTERS (1)
+#define MICROPY_DEBUG_PRINTER_DEST mp_stderr_print
#define MICROPY_READER_POSIX (1)
#define MICROPY_USE_READLINE_HISTORY (1)
#define MICROPY_HELPER_REPL (1)
@@ -59,11 +61,14 @@
#define MICROPY_PY_FUNCTION_ATTRS (1)
#define MICROPY_PY_DESCRIPTORS (1)
#define MICROPY_PY_BUILTINS_STR_UNICODE (1)
+#define MICROPY_PY_BUILTINS_STR_CENTER (1)
+#define MICROPY_PY_BUILTINS_STR_PARTITION (1)
#define MICROPY_PY_BUILTINS_STR_SPLITLINES (1)
#define MICROPY_PY_BUILTINS_MEMORYVIEW (1)
#define MICROPY_PY_BUILTINS_FROZENSET (1)
#define MICROPY_PY_BUILTINS_COMPILE (1)
#define MICROPY_PY_BUILTINS_NOTIMPLEMENTED (1)
+#define MICROPY_PY_BUILTINS_POW3 (1)
#define MICROPY_PY_MICROPYTHON_MEM_INFO (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_ARRAY_SLICE_ASSIGN (1)
@@ -83,21 +88,28 @@
#define MICROPY_STACKLESS (0)
#define MICROPY_STACKLESS_STRICT (0)
+#define MICROPY_PY_UTIME (1)
+#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_UERRNO (1)
#define MICROPY_PY_UCTYPES (1)
#define MICROPY_PY_UZLIB (1)
#define MICROPY_PY_UJSON (1)
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
+#define MICROPY_PY_UTIMEQ (1)
#define MICROPY_PY_UHASHLIB (1)
#define MICROPY_PY_UBINASCII (1)
+#define MICROPY_PY_UBINASCII_CRC32 (1)
#define MICROPY_PY_URANDOM (1)
-#define MICROPY_PY_UTIME (1)
-#define MICROPY_PY_UTIME_MP_HAL (1)
#define MICROPY_PY_MACHINE (1)
+#define MICROPY_PY_MACHINE_PULSE (1)
+#define MICROPY_MACHINE_MEM_GET_READ_ADDR mod_machine_mem_get_addr
+#define MICROPY_MACHINE_MEM_GET_WRITE_ADDR mod_machine_mem_get_addr
#define MICROPY_ERROR_REPORTING (MICROPY_ERROR_REPORTING_DETAILED)
#define MICROPY_WARNINGS (1)
+#define MICROPY_PY_STR_BYTES_CMP_WARN (1)
+
#ifdef _MSC_VER
#define MICROPY_GCREGS_SETJMP (1)
#endif
diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props
index e35df8352..a97686cdc 100644
--- a/windows/msvc/sources.props
+++ b/windows/msvc/sources.props
@@ -15,6 +15,7 @@
+
@@ -23,6 +24,7 @@
+
From 9e8f3163924c1f429f16f44a4a27b0cd33064719 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 21 Apr 2017 16:40:57 +0300
Subject: [PATCH 102/826] extmod/moductypes: Fix bigint handling for 32-bit
ports.
---
extmod/moductypes.c | 2 +-
py/objint_mpz.c | 1 +
tests/extmod/uctypes_32bit_intbig.py | 54 ++++++++++++++++++++++++
tests/extmod/uctypes_32bit_intbig.py.exp | 11 +++++
4 files changed, 67 insertions(+), 1 deletion(-)
create mode 100644 tests/extmod/uctypes_32bit_intbig.py
create mode 100644 tests/extmod/uctypes_32bit_intbig.py.exp
diff --git a/extmod/moductypes.c b/extmod/moductypes.c
index 6249a4940..d2d2e85de 100644
--- a/extmod/moductypes.c
+++ b/extmod/moductypes.c
@@ -360,7 +360,7 @@ STATIC void set_aligned(uint val_type, void *p, mp_int_t index, mp_obj_t val) {
return;
}
#endif
- mp_int_t v = mp_obj_get_int(val);
+ mp_int_t v = mp_obj_get_int_truncated(val);
switch (val_type) {
case UINT8:
((uint8_t*)p)[index] = (uint8_t)v; return;
diff --git a/py/objint_mpz.c b/py/objint_mpz.c
index 2353bd8d6..d818b6f40 100644
--- a/py/objint_mpz.c
+++ b/py/objint_mpz.c
@@ -116,6 +116,7 @@ mp_obj_t mp_obj_int_from_bytes_impl(bool big_endian, size_t len, const byte *buf
void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) {
assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int));
mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in);
+ memset(buf, 0, len);
mpz_as_bytes(&self->mpz, big_endian, len, buf);
}
diff --git a/tests/extmod/uctypes_32bit_intbig.py b/tests/extmod/uctypes_32bit_intbig.py
new file mode 100644
index 000000000..a082dc370
--- /dev/null
+++ b/tests/extmod/uctypes_32bit_intbig.py
@@ -0,0 +1,54 @@
+# This test checks previously known problem values for 32-bit ports.
+# It's less useful for 64-bit ports.
+try:
+ import uctypes
+except ImportError:
+ import sys
+ print("SKIP")
+ sys.exit()
+
+buf = b"12345678abcd"
+struct = uctypes.struct(
+ uctypes.addressof(buf),
+ {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4},
+ uctypes.LITTLE_ENDIAN
+)
+
+struct.f32 = 0x7fffffff
+print(buf)
+
+struct.f32 = 0x80000000
+print(buf)
+
+struct.f32 = 0xff010203
+print(buf)
+
+struct.f64 = 0x80000000
+print(buf)
+
+struct.f64 = 0x80000000 * 2
+print(buf)
+
+print("=")
+
+buf = b"12345678abcd"
+struct = uctypes.struct(
+ uctypes.addressof(buf),
+ {"f32": uctypes.UINT32 | 0, "f64": uctypes.UINT64 | 4},
+ uctypes.BIG_ENDIAN
+)
+
+struct.f32 = 0x7fffffff
+print(buf)
+
+struct.f32 = 0x80000000
+print(buf)
+
+struct.f32 = 0xff010203
+print(buf)
+
+struct.f64 = 0x80000000
+print(buf)
+
+struct.f64 = 0x80000000 * 2
+print(buf)
diff --git a/tests/extmod/uctypes_32bit_intbig.py.exp b/tests/extmod/uctypes_32bit_intbig.py.exp
new file mode 100644
index 000000000..d1fc1fe35
--- /dev/null
+++ b/tests/extmod/uctypes_32bit_intbig.py.exp
@@ -0,0 +1,11 @@
+b'\xff\xff\xff\x7f5678abcd'
+b'\x00\x00\x00\x805678abcd'
+b'\x03\x02\x01\xff5678abcd'
+b'\x03\x02\x01\xff\x00\x00\x00\x80\x00\x00\x00\x00'
+b'\x03\x02\x01\xff\x00\x00\x00\x00\x01\x00\x00\x00'
+=
+b'\x7f\xff\xff\xff5678abcd'
+b'\x80\x00\x00\x005678abcd'
+b'\xff\x01\x02\x035678abcd'
+b'\xff\x01\x02\x03\x00\x00\x00\x00\x80\x00\x00\x00'
+b'\xff\x01\x02\x03\x00\x00\x00\x01\x00\x00\x00\x00'
From 4df013c8ccf2e122a1bd3dd75d3937d46019409a Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 12:14:04 +1000
Subject: [PATCH 103/826] py/objtype: mp_obj_new_super doesn't need to be
public, so inline it.
Saves code size (20 bytes on bare-arm) and makes it a tiny bit more
efficient.
---
py/obj.h | 1 -
py/objtype.c | 10 +++-------
2 files changed, 3 insertions(+), 8 deletions(-)
diff --git a/py/obj.h b/py/obj.h
index b5a0c4190..a3c06a261 100644
--- a/py/obj.h
+++ b/py/obj.h
@@ -661,7 +661,6 @@ mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items);
mp_obj_t mp_obj_new_dict(size_t n_args);
mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items);
mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step);
-mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj);
mp_obj_t mp_obj_new_bound_meth(mp_obj_t meth, mp_obj_t self);
mp_obj_t mp_obj_new_getitem_iter(mp_obj_t *args, mp_obj_iter_buf_t *iter_buf);
mp_obj_t mp_obj_new_module(qstr module_name);
diff --git a/py/objtype.c b/py/objtype.c
index 5e522bed2..de1ee8c42 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -1013,7 +1013,9 @@ STATIC mp_obj_t super_make_new(const mp_obj_type_t *type_in, size_t n_args, size
// 0 arguments are turned into 2 in the compiler
// 1 argument is not yet implemented
mp_arg_check_num(n_args, n_kw, 2, 2, false);
- return mp_obj_new_super(args[0], args[1]);
+ mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
+ *o = (mp_obj_super_t){{type_in}, args[0], args[1]};
+ return MP_OBJ_FROM_PTR(o);
}
STATIC void super_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) {
@@ -1068,12 +1070,6 @@ const mp_obj_type_t mp_type_super = {
.attr = super_attr,
};
-mp_obj_t mp_obj_new_super(mp_obj_t type, mp_obj_t obj) {
- mp_obj_super_t *o = m_new_obj(mp_obj_super_t);
- *o = (mp_obj_super_t){{&mp_type_super}, type, obj};
- return MP_OBJ_FROM_PTR(o);
-}
-
/******************************************************************************/
// subclassing and built-ins specific to types
From fa03bbf0fd0a2f5a5c21472a56e39ba60f7f58dd Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 14:13:37 +1000
Subject: [PATCH 104/826] py/compile: Don't do unnecessary check if parse node
is a struct.
PN_atom_expr_normal parse nodes always have structs for their second
sub-node, so simplify the check for the sub-node kind to save code size.
---
py/compile.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/py/compile.c b/py/compile.c
index cf9e5079b..b114f8962 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -1422,7 +1422,7 @@ STATIC void compile_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
mp_parse_node_struct_t *pns_it = (mp_parse_node_struct_t*)pns->nodes[1];
if (MP_PARSE_NODE_IS_ID(pns_it->nodes[0])
&& MP_PARSE_NODE_LEAF_ARG(pns_it->nodes[0]) == MP_QSTR_range
- && MP_PARSE_NODE_IS_STRUCT_KIND(pns_it->nodes[1], PN_trailer_paren)) {
+ && MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pns_it->nodes[1]) == PN_trailer_paren) {
mp_parse_node_t pn_range_args = ((mp_parse_node_struct_t*)pns_it->nodes[1])->nodes[0];
mp_parse_node_t *args;
int n_args = mp_parse_node_extract_list(&pn_range_args, PN_arglist, &args);
From 40b40ffc98627b32adf83f3d657d237a9c59acca Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 14:23:47 +1000
Subject: [PATCH 105/826] py/compile: Extract parse-node kind at start of func
for efficiency.
Otherwise the type of parse-node and its kind has to be re-extracted
multiple times. This optimisation reduces code size by a bit (16 bytes on
bare-arm).
---
py/compile.c | 21 ++++++++++++++-------
1 file changed, 14 insertions(+), 7 deletions(-)
diff --git a/py/compile.c b/py/compile.c
index b114f8962..3aa70e8bf 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -586,8 +586,16 @@ STATIC void close_over_variables_etc(compiler_t *comp, scope_t *this_scope, int
}
STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn) {
- if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_star)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_star)) {
+ // For efficiency of the code below we extract the parse-node kind here
+ int pn_kind;
+ if (MP_PARSE_NODE_IS_ID(pn)) {
+ pn_kind = -1;
+ } else {
+ assert(MP_PARSE_NODE_IS_STRUCT(pn));
+ pn_kind = MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn);
+ }
+
+ if (pn_kind == PN_typedargslist_star || pn_kind == PN_varargslist_star) {
comp->have_star = true;
/* don't need to distinguish bare from named star
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@@ -598,8 +606,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
}
*/
- } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_dbl_star)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_dbl_star)) {
+ } else if (pn_kind == PN_typedargslist_dbl_star || pn_kind == PN_varargslist_dbl_star) {
// named double star
// TODO do we need to do anything with this?
@@ -607,14 +614,14 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
mp_parse_node_t pn_id;
mp_parse_node_t pn_colon;
mp_parse_node_t pn_equal;
- if (MP_PARSE_NODE_IS_ID(pn)) {
+ if (pn_kind == -1) {
// this parameter is just an id
pn_id = pn;
pn_colon = MP_PARSE_NODE_NULL;
pn_equal = MP_PARSE_NODE_NULL;
- } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_typedargslist_name)) {
+ } else if (pn_kind == PN_typedargslist_name) {
// this parameter has a colon and/or equal specifier
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
@@ -623,7 +630,7 @@ STATIC void compile_funcdef_lambdef_param(compiler_t *comp, mp_parse_node_t pn)
pn_equal = pns->nodes[2];
} else {
- assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn, PN_varargslist_name)); // should be
+ assert(pn_kind == PN_varargslist_name); // should be
// this parameter has an equal specifier
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
From ae54fbf1668959e50632034495631b0c5952ae9d Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 14:58:01 +1000
Subject: [PATCH 106/826] py/compile: Add COMP_RETURN_IF_EXPR option to enable
return-if-else opt.
With this optimisation enabled the compiler optimises the if-else
expression within a return statement. The optimisation reduces bytecode
size by 2 bytes for each use of such a return-if-else statement. Since
such a statement is not often used, and costs bytes for the code, the
feature is disabled by default.
For example the following code:
def f(x):
return 1 if x else 2
compiles to this bytecode with the optimisation disabled (left column is
bytecode offset in bytes):
00 LOAD_FAST 0
01 POP_JUMP_IF_FALSE 8
04 LOAD_CONST_SMALL_INT 1
05 JUMP 9
08 LOAD_CONST_SMALL_INT 2
09 RETURN_VALUE
and to this bytecode with the optimisation enabled:
00 LOAD_FAST 0
01 POP_JUMP_IF_FALSE 6
04 LOAD_CONST_SMALL_INT 1
05 RETURN_VALUE
06 LOAD_CONST_SMALL_INT 2
07 RETURN_VALUE
So the JUMP to RETURN_VALUE is optimised and replaced by RETURN_VALUE,
saving 2 bytes and making the code a bit faster.
---
py/compile.c | 3 ++-
py/mpconfig.h | 6 ++++++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/py/compile.c b/py/compile.c
index 3aa70e8bf..ae5c3b2dc 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -980,7 +980,8 @@ STATIC void compile_return_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
if (MP_PARSE_NODE_IS_NULL(pns->nodes[0])) {
// no argument to 'return', so return None
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE);
- } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
+ } else if (MICROPY_COMP_RETURN_IF_EXPR
+ && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_test_if_expr)) {
// special case when returning an if-expression; to match CPython optimisation
mp_parse_node_struct_t *pns_test_if_expr = (mp_parse_node_struct_t*)pns->nodes[0];
mp_parse_node_struct_t *pns_test_if_else = (mp_parse_node_struct_t*)pns_test_if_expr->nodes[1];
diff --git a/py/mpconfig.h b/py/mpconfig.h
index b6e24d205..9122c9916 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -353,6 +353,12 @@
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (0)
#endif
+// Whether to enable optimisation of: return a if b else c
+// Costs about 80 bytes (Thumb2) and saves 2 bytes of bytecode for each use
+#ifndef MICROPY_COMP_RETURN_IF_EXPR
+#define MICROPY_COMP_RETURN_IF_EXPR (0)
+#endif
+
/*****************************************************************************/
/* Internal debugging stuff */
From 03053f82db8fb79e8f62524948ebc2331c957af8 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 15:09:15 +1000
Subject: [PATCH 107/826] mpy-cross, unix, windows, stmhal: Enable
return-if-else optimisation.
Prior to making this a config option it was previously available on these
(and all other) ports, and it makes sense to keep it enabled for mpy-cross
as well as ports that have a decent amount of space for the code.
---
mpy-cross/mpconfigport.h | 1 +
stmhal/mpconfigport.h | 1 +
unix/mpconfigport.h | 1 +
windows/mpconfigport.h | 1 +
4 files changed, 4 insertions(+)
diff --git a/mpy-cross/mpconfigport.h b/mpy-cross/mpconfigport.h
index 383de1439..e227d1be5 100644
--- a/mpy-cross/mpconfigport.h
+++ b/mpy-cross/mpconfigport.h
@@ -44,6 +44,7 @@
#define MICROPY_COMP_CONST (1)
#define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
+#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_OPT_CACHE_MAP_LOOKUP_IN_BYTECODE (0)
diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h
index 2186e2ed6..444ce9303 100644
--- a/stmhal/mpconfigport.h
+++ b/stmhal/mpconfigport.h
@@ -45,6 +45,7 @@
// compiler configuration
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
+#define MICROPY_COMP_RETURN_IF_EXPR (1)
// optimisations
#define MICROPY_OPT_COMPUTED_GOTO (1)
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index 4067e1950..d197f4503 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -45,6 +45,7 @@
#endif
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
+#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_STACK_CHECK (1)
diff --git a/windows/mpconfigport.h b/windows/mpconfigport.h
index cad76e781..8cef50671 100644
--- a/windows/mpconfigport.h
+++ b/windows/mpconfigport.h
@@ -38,6 +38,7 @@
#define MICROPY_EMIT_INLINE_THUMB (0)
#define MICROPY_COMP_MODULE_CONST (1)
#define MICROPY_COMP_TRIPLE_TUPLE_ASSIGN (1)
+#define MICROPY_COMP_RETURN_IF_EXPR (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_ENABLE_FINALISER (1)
#define MICROPY_STACK_CHECK (1)
From 0dd6a59c895b6de4841b4e372069aa9392c24d5f Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 21:43:42 +1000
Subject: [PATCH 108/826] py/compile: Don't do unnecessary check if iter parse
node is a struct.
If we get to this point in the code then pn_iter is guaranteed to be a
struct.
---
py/compile.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/py/compile.c b/py/compile.c
index ae5c3b2dc..211086729 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -2833,14 +2833,14 @@ STATIC void compile_scope_comp_iter(compiler_t *comp, mp_parse_node_struct_t *pn
} else {
EMIT_ARG(store_comp, comp->scope_cur->kind, 4 * for_depth + 5);
}
- } else if (MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_if)) {
+ } else if (MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_if) {
// if condition
mp_parse_node_struct_t *pns_comp_if = (mp_parse_node_struct_t*)pn_iter;
c_if_cond(comp, pns_comp_if->nodes[0], false, l_top);
pn_iter = pns_comp_if->nodes[1];
goto tail_recursion;
} else {
- assert(MP_PARSE_NODE_IS_STRUCT_KIND(pn_iter, PN_comp_for)); // should be
+ assert(MP_PARSE_NODE_STRUCT_KIND((mp_parse_node_struct_t*)pn_iter) == PN_comp_for); // should be
// for loop
mp_parse_node_struct_t *pns_comp_for2 = (mp_parse_node_struct_t*)pn_iter;
compile_node(comp, pns_comp_for2->nodes[1]);
From 5335942b599d85263d3c18eb99ff5ebd04a8bc98 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 18 Apr 2017 22:52:18 +1000
Subject: [PATCH 109/826] py/compile: Refactor handling of special super()
call.
This patch refactors the handling of the special super() call within the
compiler. It removes the need for a global (to the compiler) state variable
which keeps track of whether the subject of an expression is super. The
handling of super() is now done entirely within one function, which makes
the compiler a bit cleaner and allows to easily add more optimisations to
super calls.
Changes to the code size are:
bare-arm: +12
minimal: +0
unix x64: +48
unix nanbox: -16
stmhal: +4
cc3200: +0
esp8266: -56
---
py/compile.c | 105 ++++++++++++++++++-----------
py/grammar.h | 2 +-
tests/cmdline/cmd_parsetree.py.exp | 2 +-
3 files changed, 68 insertions(+), 41 deletions(-)
diff --git a/py/compile.c b/py/compile.c
index 211086729..42c2cc3a2 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -115,7 +115,6 @@ typedef struct _compiler_t {
uint8_t is_repl;
uint8_t pass; // holds enum type pass_kind_t
- uint8_t func_arg_is_super; // used to compile special case of super() function call
uint8_t have_star;
// try to keep compiler clean from nlr
@@ -762,7 +761,6 @@ STATIC qstr compile_classdef_helper(compiler_t *comp, mp_parse_node_struct_t *pn
if (MP_PARSE_NODE_IS_STRUCT_KIND(parents, PN_classdef_2)) {
parents = MP_PARSE_NODE_NULL;
}
- comp->func_arg_is_super = false;
compile_trailer_paren_helper(comp, parents, false, 2);
// return its name (the 'C' in class C(...):")
@@ -836,7 +834,6 @@ STATIC void compile_decorated(compiler_t *comp, mp_parse_node_struct_t *pns) {
// nodes[1] contains arguments to the decorator function, if any
if (!MP_PARSE_NODE_IS_NULL(pns_decorator->nodes[1])) {
// call the decorator function with the arguments in nodes[1]
- comp->func_arg_is_super = false;
compile_node(comp, pns_decorator->nodes[1]);
}
}
@@ -2175,36 +2172,83 @@ STATIC void compile_factor_2(compiler_t *comp, mp_parse_node_struct_t *pns) {
}
STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *pns) {
- // this is to handle special super() call
- comp->func_arg_is_super = MP_PARSE_NODE_IS_ID(pns->nodes[0]) && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super;
+ // compile the subject of the expression
+ compile_node(comp, pns->nodes[0]);
- compile_generic_all_nodes(comp, pns);
-}
+ // compile_atom_expr_await may call us with a NULL node
+ if (MP_PARSE_NODE_IS_NULL(pns->nodes[1])) {
+ return;
+ }
-STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
- compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power
- EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
-}
+ // get the array of trailers (known to be an array of PARSE_NODE_STRUCT)
+ size_t num_trail = 1;
+ mp_parse_node_struct_t **pns_trail = (mp_parse_node_struct_t**)&pns->nodes[1];
+ if (MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_atom_expr_trailers) {
+ num_trail = MP_PARSE_NODE_STRUCT_NUM_NODES(pns_trail[0]);
+ pns_trail = (mp_parse_node_struct_t**)&pns_trail[0]->nodes[0];
+ }
-STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
- // function to call is on top of stack
+ // the current index into the array of trailers
+ size_t i = 0;
- // this is to handle special super() call
- if (MP_PARSE_NODE_IS_NULL(pn_arglist) && comp->func_arg_is_super && comp->scope_cur->kind == SCOPE_FUNCTION) {
+ // handle special super() call
+ if (comp->scope_cur->kind == SCOPE_FUNCTION
+ && MP_PARSE_NODE_IS_ID(pns->nodes[0])
+ && MP_PARSE_NODE_LEAF_ARG(pns->nodes[0]) == MP_QSTR_super
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[0]) == PN_trailer_paren
+ && MP_PARSE_NODE_IS_NULL(pns_trail[0]->nodes[0])) {
+ // at this point we have matched "super()" within a function
+
+ // load the class for super to search for a parent
compile_load_id(comp, MP_QSTR___class__);
+
// look for first argument to function (assumes it's "self")
- for (int i = 0; i < comp->scope_cur->id_info_len; i++) {
- id_info_t *id = &comp->scope_cur->id_info[i];
+ bool found = false;
+ id_info_t *id = &comp->scope_cur->id_info[0];
+ for (size_t n = comp->scope_cur->id_info_len; n > 0; --n, ++id) {
if (id->flags & ID_FLAG_IS_PARAM) {
- // first argument found; load it and call super
+ // first argument found; load it
compile_load_id(comp, id->qst);
- EMIT_ARG(call_function, 2, 0, 0);
- return;
+ found = true;
+ break;
}
}
- compile_syntax_error(comp, MP_PARSE_NODE_NULL, "super() call cannot find self"); // really a TypeError
- return;
+ if (!found) {
+ compile_syntax_error(comp, (mp_parse_node_t)pns_trail[0],
+ "super() can't find self"); // really a TypeError
+ return;
+ }
+
+ // a super() call
+ EMIT_ARG(call_function, 2, 0, 0);
+ i = 1;
+ }
+
+ // compile the remaining trailers
+ for (; i < num_trail; i++) {
+ if (i + 1 < num_trail
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i]) == PN_trailer_period
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[i + 1]) == PN_trailer_paren) {
+ // optimisation for method calls a.f(...), following PyPy
+ mp_parse_node_struct_t *pns_period = pns_trail[i];
+ mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
+ EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]));
+ compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
+ i += 1;
+ } else {
+ // node is one of: trailer_paren, trailer_bracket, trailer_period
+ compile_node(comp, (mp_parse_node_t)pns_trail[i]);
+ }
}
+}
+
+STATIC void compile_power(compiler_t *comp, mp_parse_node_struct_t *pns) {
+ compile_generic_all_nodes(comp, pns); // 2 nodes, arguments of power
+ EMIT_ARG(binary_op, MP_BINARY_OP_POWER);
+}
+
+STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_arglist, bool is_method_call, int n_positional_extra) {
+ // function to call is on top of stack
// get the list of arguments
mp_parse_node_t *args;
@@ -2285,23 +2329,6 @@ STATIC void compile_trailer_paren_helper(compiler_t *comp, mp_parse_node_t pn_ar
}
}
-STATIC void compile_atom_expr_trailers(compiler_t *comp, mp_parse_node_struct_t *pns) {
- int num_nodes = MP_PARSE_NODE_STRUCT_NUM_NODES(pns);
- for (int i = 0; i < num_nodes; i++) {
- if (i + 1 < num_nodes && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i], PN_trailer_period) && MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[i + 1], PN_trailer_paren)) {
- // optimisation for method calls a.f(...), following PyPy
- mp_parse_node_struct_t *pns_period = (mp_parse_node_struct_t*)pns->nodes[i];
- mp_parse_node_struct_t *pns_paren = (mp_parse_node_struct_t*)pns->nodes[i + 1];
- EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0])); // get the method
- compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
- i += 1;
- } else {
- compile_node(comp, pns->nodes[i]);
- }
- comp->func_arg_is_super = false;
- }
-}
-
// pns needs to have 2 nodes, first is lhs of comprehension, second is PN_comp_for node
STATIC void compile_comprehension(compiler_t *comp, mp_parse_node_struct_t *pns, scope_kind_t kind) {
assert(MP_PARSE_NODE_STRUCT_NUM_NODES(pns) == 2);
diff --git a/py/grammar.h b/py/grammar.h
index e8041c0e0..930d96dc1 100644
--- a/py/grammar.h
+++ b/py/grammar.h
@@ -261,7 +261,7 @@ DEF_RULE(atom_expr_await, c(atom_expr_await), and(3), tok(KW_AWAIT), rule(atom),
DEF_RULE_NC(atom_expr, or(1), rule(atom_expr_normal))
#endif
DEF_RULE(atom_expr_normal, c(atom_expr_normal), and_ident(2), rule(atom), opt_rule(atom_expr_trailers))
-DEF_RULE(atom_expr_trailers, c(atom_expr_trailers), one_or_more, rule(trailer))
+DEF_RULE_NC(atom_expr_trailers, one_or_more, rule(trailer))
DEF_RULE_NC(power_dbl_star, and_ident(2), tok(OP_DBL_STAR), rule(factor))
// atom: '(' [yield_expr|testlist_comp] ')' | '[' [testlist_comp] ']' | '{' [dictorsetmaker] '}' | NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False'
diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp
index 17fecaf96..d9f81d8d4 100644
--- a/tests/cmdline/cmd_parsetree.py.exp
+++ b/tests/cmdline/cmd_parsetree.py.exp
@@ -3,7 +3,7 @@
tok(4)
[ 4] rule(22) (n=4)
id(i)
-[ 4] rule(45) (n=1)
+[ 4] rule(44) (n=1)
NULL
[ 5] rule(8) (n=0)
NULL
From dd11af209d226b7d18d5148b239662e30ed60bad Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 19 Apr 2017 09:45:59 +1000
Subject: [PATCH 110/826] py: Add LOAD_SUPER_METHOD bytecode to allow heap-free
super meth calls.
This patch allows the following code to run without allocating on the heap:
super().foo(...)
Before this patch such a call would allocate a super object on the heap and
then load the foo method and call it right away. The super object is only
needed to perform the lookup of the method and not needed after that. This
patch makes an optimisation to allocate the super object on the C stack and
discard it right after use.
Changes in code size due to this patch are:
bare-arm: +128
minimal: +232
unix x64: +416
unix nanbox: +364
stmhal: +184
esp8266: +340
cc3200: +128
---
minimal/frozentest.mpy | Bin 255 -> 255 bytes
py/bc.c | 2 +-
py/bc0.h | 13 +++++++------
py/compile.c | 23 +++++++++++++++++------
py/emit.h | 4 ++--
py/emitbc.c | 6 +++---
py/emitnative.c | 19 +++++++++++++------
py/nativeglue.c | 1 +
py/objtype.c | 5 +++++
py/persistentcode.c | 2 +-
py/runtime.h | 1 +
py/runtime0.h | 1 +
py/showbc.c | 5 +++++
py/vm.c | 8 ++++++++
py/vmentrytable.h | 1 +
tools/mpy-tool.py | 4 ++--
16 files changed, 68 insertions(+), 27 deletions(-)
diff --git a/minimal/frozentest.mpy b/minimal/frozentest.mpy
index 5cb356d611968fc8169bb3758b365928ec5982f3..87f9581bfe7290b67f473a49441fd25db204f459 100644
GIT binary patch
delta 89
zcmey*_@6P*mx)O}hM55bc)1w9GiYgOXlQFNF#MN3&LH-KA%)Qh$PkCoj8HxkgcjNL
XewHYZ*= 3
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[1]) == PN_trailer_period
+ && MP_PARSE_NODE_STRUCT_KIND(pns_trail[2]) == PN_trailer_paren) {
+ // optimisation for method calls super().f(...), to eliminate heap allocation
+ mp_parse_node_struct_t *pns_period = pns_trail[1];
+ mp_parse_node_struct_t *pns_paren = pns_trail[2];
+ EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), true);
+ compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
+ i = 3;
+ } else {
+ // a super() call
+ EMIT_ARG(call_function, 2, 0, 0);
+ i = 1;
+ }
}
// compile the remaining trailers
@@ -2232,7 +2243,7 @@ STATIC void compile_atom_expr_normal(compiler_t *comp, mp_parse_node_struct_t *p
// optimisation for method calls a.f(...), following PyPy
mp_parse_node_struct_t *pns_period = pns_trail[i];
mp_parse_node_struct_t *pns_paren = pns_trail[i + 1];
- EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]));
+ EMIT_ARG(load_method, MP_PARSE_NODE_LEAF_ARG(pns_period->nodes[0]), false);
compile_trailer_paren_helper(comp, pns_paren->nodes[0], true, 0);
i += 1;
} else {
diff --git a/py/emit.h b/py/emit.h
index 64bb957f6..0236a9b8d 100644
--- a/py/emit.h
+++ b/py/emit.h
@@ -88,7 +88,7 @@ typedef struct _emit_method_table_t {
void (*load_const_obj)(emit_t *emit, mp_obj_t obj);
void (*load_null)(emit_t *emit);
void (*load_attr)(emit_t *emit, qstr qst);
- void (*load_method)(emit_t *emit, qstr qst);
+ void (*load_method)(emit_t *emit, qstr qst, bool is_super);
void (*load_build_class)(emit_t *emit);
void (*load_subscr)(emit_t *emit);
void (*store_attr)(emit_t *emit, qstr qst);
@@ -205,7 +205,7 @@ void mp_emit_bc_load_const_str(emit_t *emit, qstr qst);
void mp_emit_bc_load_const_obj(emit_t *emit, mp_obj_t obj);
void mp_emit_bc_load_null(emit_t *emit);
void mp_emit_bc_load_attr(emit_t *emit, qstr qst);
-void mp_emit_bc_load_method(emit_t *emit, qstr qst);
+void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super);
void mp_emit_bc_load_build_class(emit_t *emit);
void mp_emit_bc_load_subscr(emit_t *emit);
void mp_emit_bc_store_attr(emit_t *emit, qstr qst);
diff --git a/py/emitbc.c b/py/emitbc.c
index 673cd405f..6d8db81bc 100644
--- a/py/emitbc.c
+++ b/py/emitbc.c
@@ -594,9 +594,9 @@ void mp_emit_bc_load_attr(emit_t *emit, qstr qst) {
}
}
-void mp_emit_bc_load_method(emit_t *emit, qstr qst) {
- emit_bc_pre(emit, 1);
- emit_write_bytecode_byte_qstr(emit, MP_BC_LOAD_METHOD, qst);
+void mp_emit_bc_load_method(emit_t *emit, qstr qst, bool is_super) {
+ emit_bc_pre(emit, 1 - 2 * is_super);
+ emit_write_bytecode_byte_qstr(emit, is_super ? MP_BC_LOAD_SUPER_METHOD : MP_BC_LOAD_METHOD, qst);
}
void mp_emit_bc_load_build_class(emit_t *emit) {
diff --git a/py/emitnative.c b/py/emitnative.c
index 3ab001f8d..99adc809c 100644
--- a/py/emitnative.c
+++ b/py/emitnative.c
@@ -85,6 +85,7 @@ STATIC byte mp_f_n_args[MP_F_NUMBER_OF] = {
[MP_F_LOAD_BUILD_CLASS] = 0,
[MP_F_LOAD_ATTR] = 2,
[MP_F_LOAD_METHOD] = 3,
+ [MP_F_LOAD_SUPER_METHOD] = 2,
[MP_F_STORE_NAME] = 2,
[MP_F_STORE_GLOBAL] = 2,
[MP_F_STORE_ATTR] = 3,
@@ -1065,12 +1066,18 @@ STATIC void emit_native_load_attr(emit_t *emit, qstr qst) {
emit_post_push_reg(emit, VTYPE_PYOBJ, REG_RET);
}
-STATIC void emit_native_load_method(emit_t *emit, qstr qst) {
- vtype_kind_t vtype_base;
- emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
- assert(vtype_base == VTYPE_PYOBJ);
- emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
- emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name
+STATIC void emit_native_load_method(emit_t *emit, qstr qst, bool is_super) {
+ if (is_super) {
+ emit_get_stack_pointer_to_reg_for_pop(emit, REG_ARG_2, 3); // arg2 = dest ptr
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_2, 2); // arg2 = dest ptr
+ emit_call_with_imm_arg(emit, MP_F_LOAD_SUPER_METHOD, qst, REG_ARG_1); // arg1 = method name
+ } else {
+ vtype_kind_t vtype_base;
+ emit_pre_pop_reg(emit, &vtype_base, REG_ARG_1); // arg1 = base
+ assert(vtype_base == VTYPE_PYOBJ);
+ emit_get_stack_pointer_to_reg_for_push(emit, REG_ARG_3, 2); // arg3 = dest ptr
+ emit_call_with_imm_arg(emit, MP_F_LOAD_METHOD, qst, REG_ARG_2); // arg2 = method name
+ }
}
STATIC void emit_native_load_build_class(emit_t *emit) {
diff --git a/py/nativeglue.c b/py/nativeglue.c
index 694dfca74..c75e5ec04 100644
--- a/py/nativeglue.c
+++ b/py/nativeglue.c
@@ -133,6 +133,7 @@ void *const mp_fun_table[MP_F_NUMBER_OF] = {
mp_load_build_class,
mp_load_attr,
mp_load_method,
+ mp_load_super_method,
mp_store_name,
mp_store_global,
mp_store_attr,
diff --git a/py/objtype.c b/py/objtype.c
index de1ee8c42..2a119e40f 100644
--- a/py/objtype.c
+++ b/py/objtype.c
@@ -1070,6 +1070,11 @@ const mp_obj_type_t mp_type_super = {
.attr = super_attr,
};
+void mp_load_super_method(qstr attr, mp_obj_t *dest) {
+ mp_obj_super_t super = {{&mp_type_super}, dest[1], dest[2]};
+ mp_load_method(MP_OBJ_FROM_PTR(&super), attr, dest);
+}
+
/******************************************************************************/
// subclassing and built-ins specific to types
diff --git a/py/persistentcode.c b/py/persistentcode.c
index 2a9a5b7cc..a71045a29 100644
--- a/py/persistentcode.c
+++ b/py/persistentcode.c
@@ -39,7 +39,7 @@
#include "py/smallint.h"
// The current version of .mpy files
-#define MPY_VERSION (1)
+#define MPY_VERSION (2)
// The feature flags byte encodes the compile-time config options that
// affect the generate bytecode.
diff --git a/py/runtime.h b/py/runtime.h
index 177869145..d75d23ff1 100644
--- a/py/runtime.h
+++ b/py/runtime.h
@@ -131,6 +131,7 @@ mp_obj_t mp_load_attr(mp_obj_t base, qstr attr);
void mp_convert_member_lookup(mp_obj_t obj, const mp_obj_type_t *type, mp_obj_t member, mp_obj_t *dest);
void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest);
void mp_load_method_maybe(mp_obj_t base, qstr attr, mp_obj_t *dest);
+void mp_load_super_method(qstr attr, mp_obj_t *dest);
void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t val);
mp_obj_t mp_getiter(mp_obj_t o, mp_obj_iter_buf_t *iter_buf);
diff --git a/py/runtime0.h b/py/runtime0.h
index b1ed71026..720fe6a23 100644
--- a/py/runtime0.h
+++ b/py/runtime0.h
@@ -107,6 +107,7 @@ typedef enum {
MP_F_LOAD_BUILD_CLASS,
MP_F_LOAD_ATTR,
MP_F_LOAD_METHOD,
+ MP_F_LOAD_SUPER_METHOD,
MP_F_STORE_NAME,
MP_F_STORE_GLOBAL,
MP_F_STORE_ATTR,
diff --git a/py/showbc.c b/py/showbc.c
index b52905f67..0bccf8427 100644
--- a/py/showbc.c
+++ b/py/showbc.c
@@ -245,6 +245,11 @@ const byte *mp_bytecode_print_str(const byte *ip) {
printf("LOAD_METHOD %s", qstr_str(qst));
break;
+ case MP_BC_LOAD_SUPER_METHOD:
+ DECODE_QSTR;
+ printf("LOAD_SUPER_METHOD %s", qstr_str(qst));
+ break;
+
case MP_BC_LOAD_BUILD_CLASS:
printf("LOAD_BUILD_CLASS");
break;
diff --git a/py/vm.c b/py/vm.c
index 8ce635ca8..469528df4 100644
--- a/py/vm.c
+++ b/py/vm.c
@@ -376,6 +376,14 @@ run_code_state: ;
DISPATCH();
}
+ ENTRY(MP_BC_LOAD_SUPER_METHOD): {
+ MARK_EXC_IP_SELECTIVE();
+ DECODE_QSTR;
+ sp -= 1;
+ mp_load_super_method(qst, sp - 1);
+ DISPATCH();
+ }
+
ENTRY(MP_BC_LOAD_BUILD_CLASS):
MARK_EXC_IP_SELECTIVE();
PUSH(mp_load_build_class());
diff --git a/py/vmentrytable.h b/py/vmentrytable.h
index 8731c3d4c..dd9789e34 100644
--- a/py/vmentrytable.h
+++ b/py/vmentrytable.h
@@ -44,6 +44,7 @@ static const void *const entry_table[256] = {
[MP_BC_LOAD_GLOBAL] = &&entry_MP_BC_LOAD_GLOBAL,
[MP_BC_LOAD_ATTR] = &&entry_MP_BC_LOAD_ATTR,
[MP_BC_LOAD_METHOD] = &&entry_MP_BC_LOAD_METHOD,
+ [MP_BC_LOAD_SUPER_METHOD] = &&entry_MP_BC_LOAD_SUPER_METHOD,
[MP_BC_LOAD_BUILD_CLASS] = &&entry_MP_BC_LOAD_BUILD_CLASS,
[MP_BC_LOAD_SUBSCR] = &&entry_MP_BC_LOAD_SUBSCR,
[MP_BC_STORE_FAST_N] = &&entry_MP_BC_STORE_FAST_N,
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index d14e0f4ea..d2a1c67ad 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -57,7 +57,7 @@ def __str__(self):
return 'error while freezing %s: %s' % (self.rawcode.source_file, self.msg)
class Config:
- MPY_VERSION = 1
+ MPY_VERSION = 2
MICROPY_LONGINT_IMPL_NONE = 0
MICROPY_LONGINT_IMPL_LONGLONG = 1
MICROPY_LONGINT_IMPL_MPZ = 2
@@ -94,7 +94,7 @@ def OC4(a, b, c, d):
OC4(U, U, U, U), # 0x0c-0x0f
OC4(B, B, B, U), # 0x10-0x13
OC4(V, U, Q, V), # 0x14-0x17
- OC4(B, U, V, V), # 0x18-0x1b
+ OC4(B, V, V, Q), # 0x18-0x1b
OC4(Q, Q, Q, Q), # 0x1c-0x1f
OC4(B, B, V, V), # 0x20-0x23
OC4(Q, Q, Q, B), # 0x24-0x27
From 30badd1ce1fabd26e54fc445f07846306aa19cef Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 19 Apr 2017 09:49:48 +1000
Subject: [PATCH 111/826] tests: Add tests for calling super and loading a
method directly.
---
tests/basics/class_super.py | 14 ++++++++++++++
tests/cmdline/cmd_showbc.py | 4 ++++
tests/cmdline/cmd_showbc.py.exp | 21 ++++++++++++++++++++-
tests/micropython/heapalloc_super.py | 17 +++++++++++++++++
tests/micropython/heapalloc_super.py.exp | 3 +++
5 files changed, 58 insertions(+), 1 deletion(-)
create mode 100644 tests/micropython/heapalloc_super.py
create mode 100644 tests/micropython/heapalloc_super.py.exp
diff --git a/tests/basics/class_super.py b/tests/basics/class_super.py
index 4b052d8f3..1338ef452 100644
--- a/tests/basics/class_super.py
+++ b/tests/basics/class_super.py
@@ -20,3 +20,17 @@ class A:
def p(self):
print(str(super())[:18])
A().p()
+
+
+# test compiler's handling of long expressions with super
+class A:
+ bar = 123
+ def foo(self):
+ print('A foo')
+ return [1, 2, 3]
+class B(A):
+ def foo(self):
+ print('B foo')
+ print(super().bar) # accessing attribute after super()
+ return super().foo().count(2) # calling a subsequent method
+print(B().foo())
diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py
index 2f4e953bb..6e99fc418 100644
--- a/tests/cmdline/cmd_showbc.py
+++ b/tests/cmdline/cmd_showbc.py
@@ -150,3 +150,7 @@ class Class:
# delete name
del Class
+
+# load super method
+def f(self):
+ super().f()
diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp
index d0baee10f..1e015eb03 100644
--- a/tests/cmdline/cmd_showbc.py.exp
+++ b/tests/cmdline/cmd_showbc.py.exp
@@ -7,7 +7,7 @@ arg names:
(N_EXC_STACK 0)
bc=-1 line=1
########
- bc=\\d\+ line=152
+ bc=\\d\+ line=155
00 MAKE_FUNCTION \.\+
\\d\+ STORE_NAME f
\\d\+ MAKE_FUNCTION \.\+
@@ -25,6 +25,8 @@ arg names:
\\d\+ CALL_FUNCTION n=2 nkw=0
\\d\+ STORE_NAME Class
\\d\+ DELETE_NAME Class
+\\d\+ MAKE_FUNCTION \.\+
+\\d\+ STORE_NAME f
\\d\+ LOAD_CONST_NONE
\\d\+ RETURN_VALUE
File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
@@ -428,6 +430,23 @@ arg names:
10 STORE_NAME __qualname__
13 LOAD_CONST_NONE
14 RETURN_VALUE
+File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes)
+Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
+########
+\.\+5b
+arg names: self
+(N_STATE 4)
+(N_EXC_STACK 0)
+ bc=-1 line=1
+ bc=0 line=156
+00 LOAD_GLOBAL super (cache=0)
+\\d\+ LOAD_GLOBAL __class__ (cache=0)
+\\d\+ LOAD_FAST 0
+\\d\+ LOAD_SUPER_METHOD f
+\\d\+ CALL_METHOD n=0 nkw=0
+\\d\+ POP_TOP
+\\d\+ LOAD_CONST_NONE
+\\d\+ RETURN_VALUE
File cmdline/cmd_showbc.py, code block '' (descriptor: \.\+, bytecode @\.\+ bytes)
Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+):
########
diff --git a/tests/micropython/heapalloc_super.py b/tests/micropython/heapalloc_super.py
new file mode 100644
index 000000000..1cf5293d2
--- /dev/null
+++ b/tests/micropython/heapalloc_super.py
@@ -0,0 +1,17 @@
+# test super() operations which don't require allocation
+import micropython
+
+class A:
+ def foo(self):
+ print('A foo')
+ return 42
+class B(A):
+ def foo(self):
+ print('B foo')
+ print(super().foo())
+
+b = B()
+
+micropython.heap_lock()
+b.foo()
+micropython.heap_unlock()
diff --git a/tests/micropython/heapalloc_super.py.exp b/tests/micropython/heapalloc_super.py.exp
new file mode 100644
index 000000000..5dabd0c7c
--- /dev/null
+++ b/tests/micropython/heapalloc_super.py.exp
@@ -0,0 +1,3 @@
+B foo
+A foo
+42
From 5e66f2b751274d5fd95eff2510544e99a11e814c Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 22 Apr 2017 18:52:13 +0300
Subject: [PATCH 112/826] zephyr/main: Configure IPv4 netmask and gateway to
allow Internet access.
---
zephyr/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/zephyr/main.c b/zephyr/main.c
index 1f8589a6c..4c083e4c1 100644
--- a/zephyr/main.c
+++ b/zephyr/main.c
@@ -66,6 +66,10 @@ void init_zephyr(void) {
#ifdef CONFIG_NET_IPV4
static struct in_addr in4addr_my = {{{192, 0, 2, 1}}};
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0);
+ static struct in_addr in4netmask_my = {{{255, 255, 255, 0}}};
+ net_if_ipv4_set_netmask(net_if_get_default(), &in4netmask_my);
+ static struct in_addr in4gw_my = {{{192, 0, 2, 2}}};
+ net_if_ipv4_set_gw(net_if_get_default(), &in4gw_my);
#endif
#ifdef CONFIG_NET_IPV6
// 2001:db8::1
From c7aa86ce6f17f52aadff898b79c95d968da6bfa2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 25 Apr 2017 12:06:10 +1000
Subject: [PATCH 113/826] py/mpz: Strip trailing zeros from mpz value when set
from bytes.
---
py/mpz.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/py/mpz.c b/py/mpz.c
index 72d226cb3..c6832e389 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -938,6 +938,8 @@ void mpz_set_from_bytes(mpz_t *z, bool big_endian, size_t len, const byte *buf)
#endif
num_bits -= DIG_SIZE;
}
+
+ z->len = mpn_remove_trailing_zeros(z->dig, z->dig + z->len);
}
bool mpz_is_zero(const mpz_t *z) {
From 810133d97d4391151e86af90508222c480f362b7 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 25 Apr 2017 12:07:02 +1000
Subject: [PATCH 114/826] tests/basics: Add tests for int.from_bytes when src
has trailing zeros.
The trailing zeros should be truncated from the converted value.
---
tests/basics/int_bytes.py | 4 ++++
tests/basics/int_bytes_intbig.py | 3 +++
2 files changed, 7 insertions(+)
diff --git a/tests/basics/int_bytes.py b/tests/basics/int_bytes.py
index 45965ed46..93c00bba1 100644
--- a/tests/basics/int_bytes.py
+++ b/tests/basics/int_bytes.py
@@ -4,3 +4,7 @@
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))
print(int.from_bytes(b"\x01\0\0\0\0\0\0\0", "little"))
print(int.from_bytes(b"\x00\x01\0\0\0\0\0\0", "little"))
+
+# check that extra zero bytes don't change the internal int value
+print(int.from_bytes(bytes(20), "little") == 0)
+print(int.from_bytes(b"\x01" + bytes(20), "little") == 1)
diff --git a/tests/basics/int_bytes_intbig.py b/tests/basics/int_bytes_intbig.py
index 39cd67d26..0e0ad1cbb 100644
--- a/tests/basics/int_bytes_intbig.py
+++ b/tests/basics/int_bytes_intbig.py
@@ -7,3 +7,6 @@
print(il)
print(ib)
print(il.to_bytes(20, "little"))
+
+# check that extra zero bytes don't change the internal int value
+print(int.from_bytes(b + bytes(10), "little") == int.from_bytes(b, "little"))
From f85fd79c6c37cdbd32d9edc37efc985f1f4bc3bb Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 25 Apr 2017 12:22:04 +1000
Subject: [PATCH 115/826] py/mpz: In mpn_sub, use existing function to remove
trailing zeros.
---
py/mpz.c | 17 +++++++----------
1 file changed, 7 insertions(+), 10 deletions(-)
diff --git a/py/mpz.c b/py/mpz.c
index c6832e389..f5675a291 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -49,6 +49,12 @@
Definition of normalise: ?
*/
+STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {
+ for (--idig; idig >= oidig && *idig == 0; --idig) {
+ }
+ return idig + 1 - oidig;
+}
+
/* compares i with j
returns sign(i - j)
assumes i, j are normalised
@@ -190,16 +196,7 @@ STATIC size_t mpn_sub(mpz_dig_t *idig, const mpz_dig_t *jdig, size_t jlen, const
borrow >>= DIG_SIZE;
}
- for (--idig; idig >= oidig && *idig == 0; --idig) {
- }
-
- return idig + 1 - oidig;
-}
-
-STATIC size_t mpn_remove_trailing_zeros(mpz_dig_t *oidig, mpz_dig_t *idig) {
- for (--idig; idig >= oidig && *idig == 0; --idig) {
- }
- return idig + 1 - oidig;
+ return mpn_remove_trailing_zeros(oidig, idig);
}
#if MICROPY_OPT_MPZ_BITWISE
From 083cd21a741e4537f743db19871cc605e31aed96 Mon Sep 17 00:00:00 2001
From: Kushal Das
Date: Wed, 22 Mar 2017 19:06:34 +0530
Subject: [PATCH 116/826] zephyr: Add 96b_carbon configuration.
As there's no networking support in mainline yet, networking is disabled,
because otherwise the board hangs on startup.
---
zephyr/prj_96b_carbon.conf | 2 ++
1 file changed, 2 insertions(+)
create mode 100644 zephyr/prj_96b_carbon.conf
diff --git a/zephyr/prj_96b_carbon.conf b/zephyr/prj_96b_carbon.conf
new file mode 100644
index 000000000..3e41e2532
--- /dev/null
+++ b/zephyr/prj_96b_carbon.conf
@@ -0,0 +1,2 @@
+# TODO: Enable networking
+CONFIG_NETWORKING=n
From 0e177e06493368cbb5cfc5013804da247fb4c2e5 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 26 Apr 2017 01:05:54 +0300
Subject: [PATCH 117/826] zephyr/modusocket: Refactor send() into stream
write() method.
---
zephyr/modusocket.c | 44 +++++++++++++++++++++++++++++++++-----------
1 file changed, 33 insertions(+), 11 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 00e0bc789..bd51e6f5d 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -28,6 +28,7 @@
#ifdef MICROPY_PY_USOCKET
#include "py/runtime.h"
+#include "py/stream.h"
#include
#include
@@ -300,29 +301,44 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(socket_accept_obj, socket_accept);
-STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+STATIC mp_uint_t sock_write(mp_obj_t self_in, const void *buf, mp_uint_t size, int *errcode) {
socket_obj_t *socket = self_in;
- socket_check_closed(socket);
-
- mp_buffer_info_t bufinfo;
- mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ if (socket->ctx == NULL) {
+ // already closed
+ *errcode = EBADF;
+ return MP_STREAM_ERROR;
+ }
struct net_buf *send_buf = net_nbuf_get_tx(socket->ctx, K_FOREVER);
unsigned len = net_if_get_mtu(net_context_get_iface(socket->ctx));
// Arbitrary value to account for protocol headers
len -= 64;
- if (len > bufinfo.len) {
- len = bufinfo.len;
+ if (len > size) {
+ len = size;
}
- if (!net_nbuf_append(send_buf, len, bufinfo.buf, K_FOREVER)) {
+ if (!net_nbuf_append(send_buf, len, buf, K_FOREVER)) {
len = net_buf_frags_len(send_buf);
- //mp_raise_OSError(ENOSPC);
}
- RAISE_ERRNO(net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL));
+ int err = net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL);
+ if (err < 0) {
+ *errcode = -err;
+ return MP_STREAM_ERROR;
+ }
+ return len;
+}
+
+STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
+ mp_buffer_info_t bufinfo;
+ mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_READ);
+ int err = 0;
+ mp_uint_t len = sock_write(self_in, bufinfo.buf, bufinfo.len, &err);
+ if (len == MP_STREAM_ERROR) {
+ mp_raise_OSError(err);
+ }
return mp_obj_new_int_from_uint(len);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
@@ -436,12 +452,18 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
+STATIC const mp_stream_p_t socket_stream_p = {
+ //.read = sock_read,
+ .write = sock_write,
+ //.ioctl = sock_ioctl,
+};
+
STATIC const mp_obj_type_t socket_type = {
{ &mp_type_type },
.name = MP_QSTR_socket,
.print = socket_print,
.make_new = socket_make_new,
- //.protocol = &socket_stream_p,
+ .protocol = &socket_stream_p,
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
From 63068875c5b3bb754af4fd5f8006f6d9c0435f7d Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 26 Apr 2017 01:06:42 +0300
Subject: [PATCH 118/826] zephyr/modusocket: Enable stream write() method.
---
zephyr/modusocket.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index bd51e6f5d..e154fdfea 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -449,6 +449,8 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
From 7743b1523edee4cabffdfdc7d3d05fef24f38f8d Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 26 Apr 2017 11:16:52 +1000
Subject: [PATCH 119/826] unix: Remove obsolete MICROPY_FATFS macro.
It doesn't do anything. The VFS feature is controlled by MICROPY_VFS and
the FatFS driver, by MICROPY_VFS_FAT (which are set in mpconfigport.h).
---
unix/Makefile | 2 +-
unix/mpconfigport.mk | 3 ---
2 files changed, 1 insertion(+), 4 deletions(-)
diff --git a/unix/Makefile b/unix/Makefile
index 546985306..e08e817bc 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -213,7 +213,7 @@ minimal:
BUILD=build-minimal PROG=micropython_minimal FROZEN_DIR= \
MICROPY_PY_BTREE=0 MICROPY_PY_FFI=0 MICROPY_PY_SOCKET=0 MICROPY_PY_THREAD=0 \
MICROPY_PY_TERMIOS=0 MICROPY_PY_USSL=0 \
- MICROPY_USE_READLINE=0 MICROPY_FATFS=0
+ MICROPY_USE_READLINE=0
# build interpreter with nan-boxing as object model
nanbox:
diff --git a/unix/mpconfigport.mk b/unix/mpconfigport.mk
index 3b335ae78..8819546bf 100644
--- a/unix/mpconfigport.mk
+++ b/unix/mpconfigport.mk
@@ -8,9 +8,6 @@ MICROPY_FORCE_32BIT = 0
# 1 - use MicroPython version of readline
MICROPY_USE_READLINE = 1
-# Whether to enable FatFs VFS
-MICROPY_FATFS = 1
-
# btree module using Berkeley DB 1.xx
MICROPY_PY_BTREE = 1
From ef55be159c581e76bfc661fefd48f001b51a7007 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 26 Apr 2017 08:42:19 +0300
Subject: [PATCH 120/826] zephyr/modusocket: Refactor recv() into stream read()
method.
---
zephyr/modusocket.c | 47 +++++++++++++++++++++++++++++++--------------
1 file changed, 33 insertions(+), 14 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index e154fdfea..50a5c0314 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -343,14 +343,16 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_send_obj, socket_send);
-STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
+STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *errcode) {
socket_obj_t *socket = self_in;
- socket_check_closed(socket);
+ if (socket->ctx == NULL) {
+ // already closed
+ *errcode = EBADF;
+ return MP_STREAM_ERROR;
+ }
enum net_sock_type sock_type = net_context_get_type(socket->ctx);
- mp_int_t max_len = mp_obj_get_int(len_in);
unsigned recv_len;
- vstr_t vstr;
if (sock_type == SOCK_DGRAM) {
@@ -365,15 +367,14 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
recv_len = max_len;
}
- vstr_init_len(&vstr, recv_len);
- net_buf_gather(net_buf, vstr.buf, recv_len);
+ net_buf_gather(net_buf, buf, recv_len);
net_nbuf_unref(net_buf);
} else if (sock_type == SOCK_STREAM) {
do {
if (socket->state == STATE_PEER_CLOSED) {
- return mp_const_empty_bytes;
+ return 0;
}
if (socket->cur_buf == NULL) {
@@ -399,8 +400,7 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
DEBUG_printf("%d data bytes in head frag, going to read %d\n", frag_len, recv_len);
- vstr_init_len(&vstr, recv_len);
- memcpy(vstr.buf, frag->data, recv_len);
+ memcpy(buf, frag->data, recv_len);
if (recv_len != frag_len) {
net_buf_pull(frag, recv_len);
@@ -420,13 +420,32 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
// Zephyr IP stack appears to feed empty net_buf's with empty
// frags for various TCP control packets.
} while (recv_len == 0);
+ }
- } else {
- mp_not_implemented("");
+ return recv_len;
+}
+
+STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
+ mp_int_t max_len = mp_obj_get_int(len_in);
+ vstr_t vstr;
+ // +1 to accommodate for trailing \0
+ vstr_init_len(&vstr, max_len + 1);
+
+ int err;
+ mp_uint_t len = sock_read(self_in, vstr.buf, max_len, &err);
+
+ if (len == MP_STREAM_ERROR) {
+ vstr_clear(&vstr);
+ mp_raise_OSError(err);
+ }
+
+ if (len == 0) {
+ vstr_clear(&vstr);
+ return mp_const_empty_bytes;
}
- mp_obj_t ret = mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
- return ret;
+ vstr.len = len;
+ return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
@@ -455,7 +474,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
STATIC const mp_stream_p_t socket_stream_p = {
- //.read = sock_read,
+ .read = sock_read,
.write = sock_write,
//.ioctl = sock_ioctl,
};
From 1fe0f678f86507781989e8db5c005df602968e13 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 26 Apr 2017 08:42:48 +0300
Subject: [PATCH 121/826] zephyr/modusocket: Add read/readline/readinto stream
methods.
---
zephyr/modusocket.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 50a5c0314..2fa04a64a 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -469,6 +469,9 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
From 868453d3d83ea8d3ed161bd20f2f6cb59a396562 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 26 Apr 2017 09:06:58 +0300
Subject: [PATCH 122/826] zephyr/modusocket: sock_read: Check socket status
only at the start of packet.
Otherwise, if we already have a packet in progress, finish it first, before
check "peer closed" status.
---
zephyr/modusocket.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 2fa04a64a..5700cc4bd 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -373,11 +373,12 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
} else if (sock_type == SOCK_STREAM) {
do {
- if (socket->state == STATE_PEER_CLOSED) {
- return 0;
- }
if (socket->cur_buf == NULL) {
+ if (socket->state == STATE_PEER_CLOSED) {
+ return 0;
+ }
+
DEBUG_printf("TCP recv: no cur_buf, getting\n");
struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
// Restore ->frags overwritten by fifo
From 31bbcd448cb8fd61ee3fa23b93d03c5ae41427d8 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 27 Apr 2017 14:57:49 +0300
Subject: [PATCH 123/826] zephyr/modusocket: Add dummy makefile()
implementation.
---
zephyr/modusocket.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 5700cc4bd..92d45a0fe 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -450,6 +450,12 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
+STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
+ (void)n_args;
+ return args[0];
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_makefile_obj, 1, 3, socket_makefile);
+
STATIC mp_obj_t socket_close(mp_obj_t self_in) {
socket_obj_t *socket = self_in;
if (socket->ctx != NULL) {
@@ -474,6 +480,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
{ MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_makefile), (mp_obj_t)&socket_makefile_obj },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
From 8109cd5f23c530ef568c617c85193cfa9b836dbc Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 27 Apr 2017 15:00:23 +0300
Subject: [PATCH 124/826] extmod/crypto-algorithms/sha256: Remove non-standard
memory.h header.
---
extmod/crypto-algorithms/sha256.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/extmod/crypto-algorithms/sha256.c b/extmod/crypto-algorithms/sha256.c
index 82e5d9c7b..276611cfd 100644
--- a/extmod/crypto-algorithms/sha256.c
+++ b/extmod/crypto-algorithms/sha256.c
@@ -14,7 +14,6 @@
/*************************** HEADER FILES ***************************/
#include
-#include
#include "sha256.h"
/****************************** MACROS ******************************/
From 11a962099ea8735227623443c62c0248b98e4805 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 27 Apr 2017 18:08:05 +0300
Subject: [PATCH 125/826] examples/hwapi: Add config for Zephyr port of
96Boards Carbon.
---
examples/hwapi/hwconfig_z_96b_carbon.py | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 examples/hwapi/hwconfig_z_96b_carbon.py
diff --git a/examples/hwapi/hwconfig_z_96b_carbon.py b/examples/hwapi/hwconfig_z_96b_carbon.py
new file mode 100644
index 000000000..97fd57a07
--- /dev/null
+++ b/examples/hwapi/hwconfig_z_96b_carbon.py
@@ -0,0 +1,9 @@
+from machine import Signal
+
+# 96Boards Carbon board
+# USR1 - User controlled led, connected to PD2
+# USR2 - User controlled led, connected to PA15
+# BT - Bluetooth indicator, connected to PB5.
+# Note - 96b_carbon uses (at the time of writing) non-standard
+# for Zephyr port device naming convention.
+LED = Signal(("GPIOA", 15), Pin.OUT)
From 49de9b68d2fc15445f78afc6a3e12e1ab61918a5 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 28 Apr 2017 22:07:14 +1000
Subject: [PATCH 126/826] qemu-arm, stmhal: Remove dummy memory.h since it's no
longer needed.
extmod/crypto-algorithms/sha256.c was recently fixed so that it didn't
include this header.
---
qemu-arm/memory.h | 2 --
stmhal/memory.h | 2 --
2 files changed, 4 deletions(-)
delete mode 100644 qemu-arm/memory.h
delete mode 100644 stmhal/memory.h
diff --git a/qemu-arm/memory.h b/qemu-arm/memory.h
deleted file mode 100644
index f3777b0e3..000000000
--- a/qemu-arm/memory.h
+++ /dev/null
@@ -1,2 +0,0 @@
-// this is needed for extmod/crypto-algorithms/sha256.c
-#include
diff --git a/stmhal/memory.h b/stmhal/memory.h
deleted file mode 100644
index f3777b0e3..000000000
--- a/stmhal/memory.h
+++ /dev/null
@@ -1,2 +0,0 @@
-// this is needed for extmod/crypto-algorithms/sha256.c
-#include
From b08286948abc43eb48bf5964066164a6fa2ae95a Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 29 Apr 2017 11:03:46 +0300
Subject: [PATCH 127/826] extmod/moduselect: Convert to MP_ROM_QSTR and
friends.
---
extmod/moduselect.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 46dbe42e1..299654181 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -269,18 +269,18 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
-STATIC const mp_map_elem_t poll_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_register), (mp_obj_t)&poll_register_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_unregister), (mp_obj_t)&poll_unregister_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_modify), (mp_obj_t)&poll_modify_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_poll), (mp_obj_t)&poll_poll_obj },
+STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
+ { MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
+ { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
};
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
STATIC const mp_obj_type_t mp_type_poll = {
{ &mp_type_type },
.name = MP_QSTR_poll,
- .locals_dict = (mp_obj_t)&poll_locals_dict,
+ .locals_dict = (void*)&poll_locals_dict,
};
/// \function poll()
@@ -292,14 +292,14 @@ STATIC mp_obj_t select_poll(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
-STATIC const mp_map_elem_t mp_module_select_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uselect) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_select), (mp_obj_t)&mp_select_select_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_poll), (mp_obj_t)&mp_select_poll_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_POLLIN), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_RD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_POLLOUT), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_WR) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_POLLERR), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_ERR) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_POLLHUP), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_HUP) },
+STATIC const mp_rom_map_elem_t mp_module_select_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uselect) },
+ { MP_ROM_QSTR(MP_QSTR_select), MP_ROM_PTR(&mp_select_select_obj) },
+ { MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&mp_select_poll_obj) },
+ { MP_ROM_QSTR(MP_QSTR_POLLIN), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_RD) },
+ { MP_ROM_QSTR(MP_QSTR_POLLOUT), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_WR) },
+ { MP_ROM_QSTR(MP_QSTR_POLLERR), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_ERR) },
+ { MP_ROM_QSTR(MP_QSTR_POLLHUP), MP_OBJ_NEW_SMALL_INT(MP_STREAM_POLL_HUP) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_select_globals, mp_module_select_globals_table);
From edc0dcb55c127ff17d8f7e72b9ba5a9f9b77574b Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 29 Apr 2017 13:05:20 +0300
Subject: [PATCH 128/826] extmod/moduselect: Refactor towards introduction of
poll.ipoll().
This follows previous refactor made to unix/moduselect.
---
extmod/moduselect.c | 56 ++++++++++++++++++++++++++-------------------
1 file changed, 33 insertions(+), 23 deletions(-)
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 299654181..7e4148a6d 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -182,6 +182,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
typedef struct _mp_obj_poll_t {
mp_obj_base_t base;
mp_map_t poll_map;
+ int flags;
} mp_obj_poll_t;
/// \method register(obj[, eventmask])
@@ -219,9 +220,7 @@ STATIC mp_obj_t poll_modify(mp_obj_t self_in, mp_obj_t obj_in, mp_obj_t eventmas
}
MP_DEFINE_CONST_FUN_OBJ_3(poll_modify_obj, poll_modify);
-/// \method poll([timeout])
-/// Timeout is in milliseconds.
-STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
+STATIC mp_uint_t poll_poll_internal(uint n_args, const mp_obj_t *args) {
mp_obj_poll_t *self = args[0];
// work out timeout (its given already in ms)
@@ -239,33 +238,44 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
}
}
+ self->flags = flags;
+
mp_uint_t start_tick = mp_hal_ticks_ms();
+ mp_uint_t n_ready;
for (;;) {
// poll the objects
- mp_uint_t n_ready = poll_map_poll(&self->poll_map, NULL);
-
+ n_ready = poll_map_poll(&self->poll_map, NULL);
if (n_ready > 0 || (timeout != -1 && mp_hal_ticks_ms() - start_tick >= timeout)) {
- // one or more objects are ready, or we had a timeout
- mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL);
- n_ready = 0;
- for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
- if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
- continue;
- }
- poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value;
- if (poll_obj->flags_ret != 0) {
- mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
- ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
- if (flags & FLAG_ONESHOT) {
- // Don't poll next time, until new event flags will be set explicitly
- poll_obj->flags = 0;
- }
- }
- }
- return ret_list;
+ break;
}
MICROPY_EVENT_POLL_HOOK
}
+
+ return n_ready;
+}
+
+STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = args[0];
+ mp_uint_t n_ready = poll_poll_internal(n_args, args);
+
+ // one or more objects are ready, or we had a timeout
+ mp_obj_list_t *ret_list = mp_obj_new_list(n_ready, NULL);
+ n_ready = 0;
+ for (mp_uint_t i = 0; i < self->poll_map.alloc; ++i) {
+ if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
+ continue;
+ }
+ poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value;
+ if (poll_obj->flags_ret != 0) {
+ mp_obj_t tuple[2] = {poll_obj->obj, MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret)};
+ ret_list->items[n_ready++] = mp_obj_new_tuple(2, tuple);
+ if (self->flags & FLAG_ONESHOT) {
+ // Don't poll next time, until new event flags will be set explicitly
+ poll_obj->flags = 0;
+ }
+ }
+ }
+ return ret_list;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
From de3a96ba1734654c3e8c88a8010e145927286767 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 29 Apr 2017 13:05:44 +0300
Subject: [PATCH 129/826] extmod/moduselect: Implement ipoll() method for
alloc-free polling.
Similar to the implementation added to unix port module previously.
---
extmod/moduselect.c | 56 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/extmod/moduselect.c b/extmod/moduselect.c
index 7e4148a6d..88dd29a49 100644
--- a/extmod/moduselect.c
+++ b/extmod/moduselect.c
@@ -182,7 +182,11 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_select_select_obj, 3, 4, select_select);
typedef struct _mp_obj_poll_t {
mp_obj_base_t base;
mp_map_t poll_map;
+ short iter_cnt;
+ short iter_idx;
int flags;
+ // callee-owned tuple
+ mp_obj_t ret_tuple;
} mp_obj_poll_t;
/// \method register(obj[, eventmask])
@@ -279,17 +283,67 @@ STATIC mp_obj_t poll_poll(uint n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_poll_obj, 1, 3, poll_poll);
+STATIC mp_obj_t poll_ipoll(size_t n_args, const mp_obj_t *args) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(args[0]);
+
+ if (self->ret_tuple == MP_OBJ_NULL) {
+ self->ret_tuple = mp_obj_new_tuple(2, NULL);
+ }
+
+ int n_ready = poll_poll_internal(n_args, args);
+ self->iter_cnt = n_ready;
+ self->iter_idx = 0;
+
+ return args[0];
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(poll_ipoll_obj, 1, 3, poll_ipoll);
+
+STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
+ mp_obj_poll_t *self = MP_OBJ_TO_PTR(self_in);
+
+ if (self->iter_cnt == 0) {
+ return MP_OBJ_STOP_ITERATION;
+ }
+
+ self->iter_cnt--;
+
+ for (mp_uint_t i = self->iter_idx; i < self->poll_map.alloc; ++i) {
+ self->iter_idx++;
+ if (!MP_MAP_SLOT_IS_FILLED(&self->poll_map, i)) {
+ continue;
+ }
+ poll_obj_t *poll_obj = (poll_obj_t*)self->poll_map.table[i].value;
+ if (poll_obj->flags_ret != 0) {
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
+ t->items[0] = poll_obj->obj;
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(poll_obj->flags_ret);
+ if (self->flags & FLAG_ONESHOT) {
+ // Don't poll next time, until new event flags will be set explicitly
+ poll_obj->flags = 0;
+ }
+ return MP_OBJ_FROM_PTR(t);
+ }
+ }
+
+ assert(!"inconsistent number of poll active entries");
+ self->iter_cnt = 0;
+ return MP_OBJ_STOP_ITERATION;
+}
+
STATIC const mp_rom_map_elem_t poll_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_register), MP_ROM_PTR(&poll_register_obj) },
{ MP_ROM_QSTR(MP_QSTR_unregister), MP_ROM_PTR(&poll_unregister_obj) },
{ MP_ROM_QSTR(MP_QSTR_modify), MP_ROM_PTR(&poll_modify_obj) },
{ MP_ROM_QSTR(MP_QSTR_poll), MP_ROM_PTR(&poll_poll_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ipoll), MP_ROM_PTR(&poll_ipoll_obj) },
};
STATIC MP_DEFINE_CONST_DICT(poll_locals_dict, poll_locals_dict_table);
STATIC const mp_obj_type_t mp_type_poll = {
{ &mp_type_type },
.name = MP_QSTR_poll,
+ .getiter = mp_identity_getiter,
+ .iternext = poll_iternext,
.locals_dict = (void*)&poll_locals_dict,
};
@@ -298,6 +352,8 @@ STATIC mp_obj_t select_poll(void) {
mp_obj_poll_t *poll = m_new_obj(mp_obj_poll_t);
poll->base.type = &mp_type_poll;
mp_map_init(&poll->poll_map, 0);
+ poll->iter_cnt = 0;
+ poll->ret_tuple = MP_OBJ_NULL;
return poll;
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_select_poll_obj, select_poll);
From 4c2402e41e869772d3c9fa9b197040c5712624f6 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 29 Apr 2017 18:56:39 +0300
Subject: [PATCH 130/826] extmod/modlwip: getaddrinfo: Allow to accept all 6
standard params.
But warn if anything else but host/port is passed.
---
extmod/modlwip.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index fffabb98a..6a1dcaef5 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -1263,7 +1263,12 @@ 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) {
+STATIC mp_obj_t lwip_getaddrinfo(size_t n_args, const mp_obj_t *args) {
+ if (n_args > 2) {
+ mp_warning("getaddrinfo constraints not supported");
+ }
+
+ mp_obj_t host_in = args[0], port_in = args[1];
const char *host = mp_obj_str_get_str(host_in);
mp_int_t port = mp_obj_get_int(port_in);
@@ -1299,7 +1304,7 @@ STATIC mp_obj_t lwip_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
tuple->items[4] = netutils_format_inet_addr((uint8_t*)&state.ipaddr, port, NETUTILS_BIG);
return mp_obj_new_list(1, (mp_obj_t*)&tuple);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_2(lwip_getaddrinfo_obj, lwip_getaddrinfo);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(lwip_getaddrinfo_obj, 2, 6, lwip_getaddrinfo);
// Debug functions
From a7f502259131190195542abc71a3b6e3270d9062 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 30 Apr 2017 00:37:05 +0300
Subject: [PATCH 131/826] windows/README: Convert to Markdown.
---
windows/{README => README.md} | 45 ++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 19 deletions(-)
rename windows/{README => README.md} (54%)
diff --git a/windows/README b/windows/README.md
similarity index 54%
rename from windows/README
rename to windows/README.md
index 4b383eaed..b181908fe 100644
--- a/windows/README
+++ b/windows/README.md
@@ -4,53 +4,60 @@ The port requires additional testing, debugging, and patches. Please
consider to contribute.
-To cross-compile under Debian/Ubuntu Linux system:
+Building on Debian/Ubuntu Linux system
+---------------------------------------
-sudo apt-get install gcc-mingw-w64
-make CROSS_COMPILE=i686-w64-mingw32-
+ sudo apt-get install gcc-mingw-w64
+ make CROSS_COMPILE=i686-w64-mingw32-
If for some reason the mingw-w64 crosscompiler is not available, you can try
mingw32 instead, but it comes with a really old gcc which may produce some
spurious errors (you may need to disable -Werror):
-sudo apt-get install mingw32 mingw32-binutils mingw32-runtime
-make CROSS_COMPILE=i586-mingw32msvc-
+ sudo apt-get install mingw32 mingw32-binutils mingw32-runtime
+ make CROSS_COMPILE=i586-mingw32msvc-
-To compile under Cygwin:
+Bulding under Cygwin
+--------------------
Install following packages using cygwin's setup.exe:
-mingw64-i686-gcc-core, mingw64-x86_64-gcc-core, make
-Build using:
-make CROSS_COMPILE=i686-w64-mingw32-
+* mingw64-i686-gcc-core
+* mingw64-x86_64-gcc-core
+* make
+
+Build using:
-or for 64bit:
+ make CROSS_COMPILE=i686-w64-mingw32-
-make CROSS_COMPILE=x86_64-w64-mingw32-
+Or for 64bit:
+ make CROSS_COMPILE=x86_64-w64-mingw32-
-To compile using Visual Studio 2013 (or higher):
-Open micropython.vcxproj and build
+Building using MS Visual Studio 2013 (or higher)
+------------------------------------------------
+In IDE, open `micropython.vcxproj` and build.
-To compile using Visual Studio 2013 (or higher) commandline:
+To build from command line:
-msbuild micropython.vcxproj
+ msbuild micropython.vcxproj
-To run on Linux using Wine:
+Running on Linux using Wine
+---------------------------
The default build (MICROPY_USE_READLINE=1) uses extended Windows console
-functions and thus should be run using "wineconsole" tool. Depending
+functions and thus should be run using `wineconsole` tool. Depending
on the Wine build configuration, you may also want to select the curses
backend which has the look&feel of a standard Unix console:
wineconsole --backend=curses ./micropython.exe
-For more info, see https://www.winehq.org/docs/wineusr-guide/cui-programs
+For more info, see https://www.winehq.org/docs/wineusr-guide/cui-programs .
If built without line editing and history capabilities
(MICROPY_USE_READLINE=0), the resulting binary can be run using the standard
-"wine" tool.
+`wine` tool.
From 2f0ce2a6f50ba9472ce4bd8f9fe984d830e99ade Mon Sep 17 00:00:00 2001
From: stijn
Date: Wed, 26 Apr 2017 13:17:55 +0200
Subject: [PATCH 132/826] py: Cleanup use of global DEBUG preprocessor
definition
The standard preprocessor definition to differentiate debug and non-debug
builds is NDEBUG, not DEBUG, so don't rely on the latter:
- just delete the use of it in objint_longlong.c as it has been stale code
for years anyway (since commit [c4029e5]): SUFFIX isn't used anywhere.
- replace DEBUG with MICROPY_DEBUG_NLR in nlr.h: it is rarely used anymore
so can be off by default
---
py/nlr.h | 2 +-
py/objint_longlong.c | 8 --------
2 files changed, 1 insertion(+), 9 deletions(-)
diff --git a/py/nlr.h b/py/nlr.h
index 00c1072fe..7a71ef34b 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -85,7 +85,7 @@ NORETURN void nlr_jump(void *val);
NORETURN void nlr_jump_fail(void *val);
// use nlr_raise instead of nlr_jump so that debugging is easier
-#ifndef DEBUG
+#ifndef MICROPY_DEBUG_NLR
#define nlr_raise(val) nlr_jump(MP_OBJ_TO_PTR(val))
#else
#include "mpstate.h"
diff --git a/py/objint_longlong.c b/py/objint_longlong.c
index 540cfebd0..f638a5320 100644
--- a/py/objint_longlong.c
+++ b/py/objint_longlong.c
@@ -40,14 +40,6 @@
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_LONGLONG
-// Python3 no longer has "l" suffix for long ints. We allow to use it
-// for debugging purpose though.
-#ifdef DEBUG
-#define SUFFIX "l"
-#else
-#define SUFFIX ""
-#endif
-
#if MICROPY_PY_SYS_MAXSIZE
// Export value for sys.maxsize
const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX};
From 8d865fa7017481c3840e374d28b3a40fe0497253 Mon Sep 17 00:00:00 2001
From: stijn
Date: Wed, 26 Apr 2017 13:39:00 +0200
Subject: [PATCH 133/826] msvc: Do not define DEBUG for debug builds
It is not used anywhere and causes a warning about redefinition because
it is used in modutimeq.c
---
windows/msvc/debug.props | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/windows/msvc/debug.props b/windows/msvc/debug.props
index c0a22be85..fa1ca4fcb 100644
--- a/windows/msvc/debug.props
+++ b/windows/msvc/debug.props
@@ -4,10 +4,6 @@
-
-
- DEBUG;%(PreprocessorDefinitions)
-
-
+
-
+
\ No newline at end of file
From db9c2e310e0039c8280256c17ac338f31bcbd9cc Mon Sep 17 00:00:00 2001
From: stijn
Date: Mon, 3 Apr 2017 13:16:12 +0200
Subject: [PATCH 134/826] msvc: Rebuild all qstrs when mpconfig headers are
modified
Make qstr generation depend on modifications in mpconfigport.h, mpconfig.h
and makeqstrdata.py and if any of those change scan all source files for
qstrs again since they might have changed (for example typcially when
enabling new features in mpconfig.h).
This fixes #2982 for msvc builds.
---
windows/msvc/genhdr.targets | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/windows/msvc/genhdr.targets b/windows/msvc/genhdr.targets
index afe5f5d76..5792d878e 100644
--- a/windows/msvc/genhdr.targets
+++ b/windows/msvc/genhdr.targets
@@ -43,8 +43,13 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
+
+
+
+
+
-
+
@@ -56,15 +61,21 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
$([System.IO.Path]::GetDirectoryName('%(OutFile)'))
- $([System.DateTime]::Compare($([System.IO.File]::GetLastWriteTime('%(FullPath)')), $([System.IO.File]::GetLastWriteTime('%(OutFile)'))))
+ True
+
+ True
+
+
+ @(QstrDependencies->AnyHaveMetadataValue('Changed', 'True'))
+
+ Condition="'%(PyQstrSourceFiles.Changed)' == 'True' Or '$(ForceQstrRebuild)' == 'True'"/>
+ Condition="@(PyQstrSourceFiles->AnyHaveMetadataValue('Changed', 'True')) Or '$(ForceQstrRebuild)' == 'True'"/>
From 473e85e2da847ade98d728a17c339f5c75a19369 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 1 May 2017 00:01:30 +0300
Subject: [PATCH 135/826] tools/mpy-tool: Make work if run from another
directory.
By making sure we don't add relative paths to sys.path.
---
tools/mpy-tool.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index d2a1c67ad..aff4fd210 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -45,7 +45,7 @@
import struct
from collections import namedtuple
-sys.path.append('../py')
+sys.path.append(sys.path[0] + '/../py')
import makeqstrdata as qstrutil
class FreezeError(Exception):
From e81f46940e005e07502e3952f5b0feb23037235b Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 1 May 2017 00:03:45 +0300
Subject: [PATCH 136/826] tools/upip: Upgrade to 1.1.6, supports commented
lines in requirements.txt.
---
tools/upip.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/upip.py b/tools/upip.py
index 0070fd619..a156340b2 100644
--- a/tools/upip.py
+++ b/tools/upip.py
@@ -275,6 +275,8 @@ def main():
l = f.readline()
if not l:
break
+ if l[0] == "#":
+ continue
to_install.append(l.rstrip())
elif opt == "--debug":
debug = True
From fa823ea893e251214f1e8eea371c922ed6ba9a6d Mon Sep 17 00:00:00 2001
From: stijn
Date: Mon, 1 May 2017 11:39:39 +0200
Subject: [PATCH 137/826] windows/README: Fix some typos and grammar
---
windows/README.md | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/windows/README.md b/windows/README.md
index b181908fe..a263d8549 100644
--- a/windows/README.md
+++ b/windows/README.md
@@ -1,4 +1,4 @@
-This is experimental, community-supported Windows port of MicroPython.
+This is the experimental, community-supported Windows port of MicroPython.
It is based on Unix port, and expected to remain so.
The port requires additional testing, debugging, and patches. Please
consider to contribute.
@@ -18,8 +18,8 @@ spurious errors (you may need to disable -Werror):
make CROSS_COMPILE=i586-mingw32msvc-
-Bulding under Cygwin
---------------------
+Building under Cygwin
+---------------------
Install following packages using cygwin's setup.exe:
@@ -39,9 +39,9 @@ Or for 64bit:
Building using MS Visual Studio 2013 (or higher)
------------------------------------------------
-In IDE, open `micropython.vcxproj` and build.
+In the IDE, open `micropython.vcxproj` and build.
-To build from command line:
+To build from the command line:
msbuild micropython.vcxproj
@@ -50,7 +50,7 @@ Running on Linux using Wine
---------------------------
The default build (MICROPY_USE_READLINE=1) uses extended Windows console
-functions and thus should be run using `wineconsole` tool. Depending
+functions and thus should be ran using the `wineconsole` tool. Depending
on the Wine build configuration, you may also want to select the curses
backend which has the look&feel of a standard Unix console:
From c41fe70ef287882467fa0978ca0c678094c0bbec Mon Sep 17 00:00:00 2001
From: stijn
Date: Mon, 1 May 2017 11:59:39 +0200
Subject: [PATCH 138/826] windows/README: Add a note about stack usage for msvc
Add information as discussed in #2927 to the readme to make the easier
to discover.
---
windows/README.md | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/windows/README.md b/windows/README.md
index a263d8549..6d3249903 100644
--- a/windows/README.md
+++ b/windows/README.md
@@ -45,6 +45,17 @@ To build from the command line:
msbuild micropython.vcxproj
+__Stack usage__
+
+The msvc compiler is quite stack-hungry which might result in a "maximum recursion depth exceeded"
+RuntimeError for code with lots of nested function calls.
+There are several ways to deal with this:
+- increase the threshold used for detection by altering the argument to `mp_stack_set_limit` in `unix/main.c`
+- disable detection all together by setting `MICROPY_STACK_CHECK` to "0" in `windows/mpconfigport.h`
+- disable the /GL compiler flag by setting `WholeProgramOptimization` to "false"
+
+See [issue 2927](https://github.com/micropython/micropython/issues/2927) for more information.
+
Running on Linux using Wine
---------------------------
From 5db55e63f3e7a5beda732c241693e37e3a7b099f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 1 May 2017 18:20:09 +0300
Subject: [PATCH 139/826] extmod/modlwip: ioctl POLL: Fix handling of peer
closed socket.
Peer-closed socket is both readable and writable: read will return EOF,
write - error. Without this poll will hang on such socket.
Note that we don't return POLLHUP, based on argumentation in
http://www.greenend.org.uk/rjk/tech/poll.html that it should apply to
deeper disconnects, for example for networking, that would be link layer
disconnect (e.g. WiFi went down).
---
extmod/modlwip.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/extmod/modlwip.c b/extmod/modlwip.c
index 6a1dcaef5..c72849cf9 100644
--- a/extmod/modlwip.c
+++ b/extmod/modlwip.c
@@ -1143,8 +1143,11 @@ STATIC mp_uint_t lwip_socket_ioctl(mp_obj_t self_in, mp_uint_t request, uintptr_
ret |= MP_STREAM_POLL_WR;
}
- if (flags & MP_STREAM_POLL_HUP && socket->state == STATE_PEER_CLOSED) {
- ret |= MP_STREAM_POLL_HUP;
+ if (socket->state == STATE_PEER_CLOSED) {
+ // Peer-closed socket is both readable and writable: read will
+ // return EOF, write - error. Without this poll will hang on a
+ // socket which was closed by peer.
+ ret |= flags & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
}
} else {
From 11bc21dfa8f087ae2d95f378267ef270a85029ad Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 1 May 2017 18:47:26 +0300
Subject: [PATCH 140/826] unix/main: Ignore SIGPIPE signal, instead make EPIPE
arrive.
Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing
to peer-closed socket will lead to sudden termination of MicroPython
process. SIGPIPE is particularly nasty, because unix shell doesn't
print anything for it, so the above looks like completely sudden and
silent termination for unknown reason. Ignoring SIGPIPE is also what
CPython does. Note that this may lead to problems using MicroPython
scripts as pipe filters, but again, that's what CPython does. So,
scripts which want to follow unix shell pipe semantics (where SIGPIPE
means "pipe was requested to terminate, it's not an error"), should
catch EPIPE themselves.
---
unix/main.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/unix/main.c b/unix/main.c
index edea7900d..84570eb9f 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -35,6 +35,7 @@
#include
#include
#include
+#include
#include "py/mpstate.h"
#include "py/nlr.h"
@@ -414,6 +415,20 @@ int main(int argc, char **argv) {
}
MP_NOINLINE int main_(int argc, char **argv) {
+ #ifdef SIGPIPE
+ // Do not raise SIGPIPE, instead return EPIPE. Otherwise, e.g. writing
+ // to peer-closed socket will lead to sudden termination of MicroPython
+ // process. SIGPIPE is particularly nasty, because unix shell doesn't
+ // print anything for it, so the above looks like completely sudden and
+ // silent termination for unknown reason. Ignoring SIGPIPE is also what
+ // CPython does. Note that this may lead to problems using MicroPython
+ // scripts as pipe filters, but again, that's what CPython does. So,
+ // scripts which want to follow unix shell pipe semantics (where SIGPIPE
+ // means "pipe was requested to terminate, it's not an error"), should
+ // catch EPIPE themselves.
+ signal(SIGPIPE, SIG_IGN);
+ #endif
+
mp_stack_set_limit(40000 * (BYTES_PER_WORD / 4));
pre_process_options(argc, argv);
From 674da04e2e4aa54822652b8e3e24261d8d4cd95d Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 01:12:02 +0300
Subject: [PATCH 141/826] zephyr/Makefile: Add debugserver Zephyr target.
---
zephyr/Makefile | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zephyr/Makefile b/zephyr/Makefile
index 057a88862..9e8cb31d0 100644
--- a/zephyr/Makefile
+++ b/zephyr/Makefile
@@ -64,7 +64,7 @@ $(Z_EXPORTS): $(CONF_FILE)
# e.g. DTS-related.
$(MAKE) -f Makefile.zephyr BOARD=$(BOARD) CONF_FILE=$(CONF_FILE) initconfig outputexports lib
-GENERIC_TARGETS = all zephyr run qemu qemugdb flash debug
+GENERIC_TARGETS = all zephyr run qemu qemugdb flash debug debugserver
KCONFIG_TARGETS = \
initconfig config nconfig menuconfig xconfig gconfig \
oldconfig silentoldconfig defconfig savedefconfig \
From 58ecbc7752116be123598daec7c2be77d8681f8c Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 03:36:17 +0300
Subject: [PATCH 142/826] tests/cpydiff/core_arguments: Fill in
cause/workaround.
---
tests/cpydiff/core_arguments.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/cpydiff/core_arguments.py b/tests/cpydiff/core_arguments.py
index a0831ab40..4734a8062 100644
--- a/tests/cpydiff/core_arguments.py
+++ b/tests/cpydiff/core_arguments.py
@@ -1,8 +1,8 @@
"""
categories: Core
-description: Error messages may display incorrect argument counts
-cause: Unknown
-workaround: Unknown
+description: Error messages for methods may display unexpected argument counts
+cause: MicroPython counts "self" as an argument.
+workaround: Interpret error messages with the information above in mind.
"""
try:
[].append()
From 8bb84cc627b933ff3eb9931a97197e459811fe36 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 03:42:46 +0300
Subject: [PATCH 143/826] tests/cpydiff/core_function_userattr: Clarify, fill
in cause and workaround.
---
tests/cpydiff/core_function_instancevar.py | 11 -----------
tests/cpydiff/core_function_userattr.py | 11 +++++++++++
2 files changed, 11 insertions(+), 11 deletions(-)
delete mode 100644 tests/cpydiff/core_function_instancevar.py
create mode 100644 tests/cpydiff/core_function_userattr.py
diff --git a/tests/cpydiff/core_function_instancevar.py b/tests/cpydiff/core_function_instancevar.py
deleted file mode 100644
index ab027b166..000000000
--- a/tests/cpydiff/core_function_instancevar.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""
-categories: Core,Functions
-description: Assign instance variable to function
-cause: Unknown
-workaround: Unknown
-"""
-def f():
- pass
-
-f.x = 0
-print(f.x)
diff --git a/tests/cpydiff/core_function_userattr.py b/tests/cpydiff/core_function_userattr.py
new file mode 100644
index 000000000..297293908
--- /dev/null
+++ b/tests/cpydiff/core_function_userattr.py
@@ -0,0 +1,11 @@
+"""
+categories: Core,Functions
+description: User-defined attributes for functions are not supported
+cause: MicroPython is highly optimized for memory usage.
+workaround: Use external dictionary, e.g. ``FUNC_X[f] = 0``.
+"""
+def f():
+ pass
+
+f.x = 0
+print(f.x)
From c1b19115e584c5be21863a5e3d187356a28039b5 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 14:12:52 +0300
Subject: [PATCH 144/826] tests/cpydiff/core_import_prereg: Fill in cause and
workaround.
---
tests/cpydiff/core_import_prereg.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/cpydiff/core_import_prereg.py b/tests/cpydiff/core_import_prereg.py
index ab04cfc99..4a7121782 100644
--- a/tests/cpydiff/core_import_prereg.py
+++ b/tests/cpydiff/core_import_prereg.py
@@ -1,8 +1,8 @@
"""
categories: Core,import
description: Failed to load modules are still registered as loaded
-cause: Unknown
-workaround: Unknown
+cause: To make module handling more efficient, it's not wrapped with exception handling.
+workaround: Test modules before production use; during development, use ``del sys.modules["name"]``, or just soft or hard reset the board.
"""
import sys
From b5159a91498006c4ad8ff55465437a9fe18899a5 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 23:33:16 +0300
Subject: [PATCH 145/826] zephyr/mpconfigport.h: Enable line number information
for scripts.
---
zephyr/mpconfigport.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h
index 2c57ede4d..98a033be4 100644
--- a/zephyr/mpconfigport.h
+++ b/zephyr/mpconfigport.h
@@ -35,6 +35,7 @@
#define MICROPY_HEAP_SIZE (16 * 1024)
#endif
+#define MICROPY_ENABLE_SOURCE_LINE (1)
#define MICROPY_STACK_CHECK (1)
#define MICROPY_ENABLE_GC (1)
#define MICROPY_HELPER_REPL (1)
From 4c2fa83f2afa1dc9522755261c8a6969857a2031 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 2 May 2017 23:35:13 +0300
Subject: [PATCH 146/826] zephyr/main: Remove superfluous include.
---
zephyr/main.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/zephyr/main.c b/zephyr/main.c
index 4c083e4c1..a67ad3352 100644
--- a/zephyr/main.c
+++ b/zephyr/main.c
@@ -31,7 +31,6 @@
#include
#ifdef CONFIG_NETWORKING
#include
-#include
#endif
#include "py/nlr.h"
From d7da2dba07778fa3c0c7873b7c253bde48066e9c Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 3 May 2017 01:47:08 +0300
Subject: [PATCH 147/826] py/modio: Implement uio.resource_stream(package,
resource_path).
The with semantics of this function is close to
pkg_resources.resource_stream() function from setuptools, which
is the canonical way to access non-source files belonging to a package
(resources), regardless of what medium the package uses (e.g. individual
source files vs zip archive). In the case of MicroPython, this function
allows to access resources which are frozen into the executable, besides
accessing resources in the file system.
This is initial stage of the implementation, which actually doesn't
implement "package" part of the semantics, just accesses frozen resources
from "root", or filesystem resource - from current dir.
---
py/frozenmod.c | 25 +++++++++++++++++++------
py/frozenmod.h | 3 +++
py/modio.c | 29 +++++++++++++++++++++++++++++
py/mpconfig.h | 7 +++++++
unix/mpconfigport.h | 1 +
5 files changed, 59 insertions(+), 6 deletions(-)
diff --git a/py/frozenmod.c b/py/frozenmod.c
index 660167eed..1eaaf574a 100644
--- a/py/frozenmod.c
+++ b/py/frozenmod.c
@@ -43,16 +43,16 @@ extern const char mp_frozen_str_names[];
extern const uint32_t mp_frozen_str_sizes[];
extern const char mp_frozen_str_content[];
-STATIC mp_lexer_t *mp_find_frozen_str(const char *str, size_t len) {
+// On input, *len contains size of name, on output - size of content
+const char *mp_find_frozen_str(const char *str, size_t *len) {
const char *name = mp_frozen_str_names;
size_t offset = 0;
for (int i = 0; *name != 0; i++) {
size_t l = strlen(name);
- if (l == len && !memcmp(str, name, l)) {
- qstr source = qstr_from_strn(name, l);
- mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, mp_frozen_str_content + offset, mp_frozen_str_sizes[i], 0);
- return lex;
+ if (l == *len && !memcmp(str, name, l)) {
+ *len = mp_frozen_str_sizes[i];
+ return mp_frozen_str_content + offset;
}
name += l + 1;
offset += mp_frozen_str_sizes[i] + 1;
@@ -60,6 +60,19 @@ STATIC mp_lexer_t *mp_find_frozen_str(const char *str, size_t len) {
return NULL;
}
+STATIC mp_lexer_t *mp_lexer_frozen_str(const char *str, size_t len) {
+ size_t name_len = len;
+ const char *content = mp_find_frozen_str(str, &len);
+
+ if (content == NULL) {
+ return NULL;
+ }
+
+ qstr source = qstr_from_strn(str, name_len);
+ mp_lexer_t *lex = MICROPY_MODULE_FROZEN_LEXER(source, content, len, 0);
+ return lex;
+}
+
#endif
#if MICROPY_MODULE_FROZEN_MPY
@@ -124,7 +137,7 @@ mp_import_stat_t mp_frozen_stat(const char *str) {
int mp_find_frozen_module(const char *str, size_t len, void **data) {
#if MICROPY_MODULE_FROZEN_STR
- mp_lexer_t *lex = mp_find_frozen_str(str, len);
+ mp_lexer_t *lex = mp_lexer_frozen_str(str, len);
if (lex != NULL) {
*data = lex;
return MP_FROZEN_STR;
diff --git a/py/frozenmod.h b/py/frozenmod.h
index f08cb5e32..4b125ff24 100644
--- a/py/frozenmod.h
+++ b/py/frozenmod.h
@@ -24,6 +24,8 @@
* THE SOFTWARE.
*/
+#include "py/lexer.h"
+
enum {
MP_FROZEN_NONE,
MP_FROZEN_STR,
@@ -31,4 +33,5 @@ enum {
};
int mp_find_frozen_module(const char *str, size_t len, void **data);
+const char *mp_find_frozen_str(const char *str, size_t *len);
mp_import_stat_t mp_frozen_stat(const char *str);
diff --git a/py/modio.c b/py/modio.c
index d5da0b1db..6bf5129e6 100644
--- a/py/modio.c
+++ b/py/modio.c
@@ -30,6 +30,8 @@
#include "py/runtime.h"
#include "py/builtin.h"
#include "py/stream.h"
+#include "py/objstringio.h"
+#include "py/frozenmod.h"
#if MICROPY_PY_IO
@@ -129,11 +131,38 @@ STATIC const mp_obj_type_t bufwriter_type = {
};
#endif // MICROPY_PY_IO_BUFFEREDWRITER
+#if MICROPY_MODULE_FROZEN_STR
+STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {
+ if (package_in != mp_const_none) {
+ mp_not_implemented("");
+ }
+
+ size_t len;
+ const char *path = mp_obj_str_get_data(path_in, &len);
+ const char *data = mp_find_frozen_str(path, &len);
+ if (data != NULL) {
+ mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);
+ o->base.type = &mp_type_bytesio;
+ o->vstr = m_new_obj(vstr_t);
+ vstr_init_fixed_buf(o->vstr, len + 1, (char*)data);
+ o->vstr->len = len;
+ o->pos = 0;
+ return MP_OBJ_FROM_PTR(o);
+ }
+
+ return mp_builtin_open(1, &path_in, (mp_map_t*)&mp_const_empty_map);
+}
+MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream);
+#endif
+
STATIC const mp_rom_map_elem_t mp_module_io_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uio) },
// Note: mp_builtin_open_obj should be defined by port, it's not
// part of the core.
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&mp_builtin_open_obj) },
+ #if MICROPY_PY_IO_RESOURCE_STREAM
+ { MP_ROM_QSTR(MP_QSTR_resource_stream), MP_ROM_PTR(&resource_stream_obj) },
+ #endif
#if MICROPY_PY_IO_FILEIO
{ MP_ROM_QSTR(MP_QSTR_FileIO), MP_ROM_PTR(&mp_type_fileio) },
#if MICROPY_CPYTHON_COMPAT
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 9122c9916..a61d431e5 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -886,6 +886,13 @@ typedef double mp_float_t;
#define MICROPY_PY_IO (1)
#endif
+// Whether to provide "uio.resource_stream()" function with
+// the semantics of CPython's pkg_resources.resource_stream()
+// (allows to access resources in frozen packages).
+#ifndef MICROPY_PY_IO_RESOURCE_STREAM
+#define MICROPY_PY_IO_RESOURCE_STREAM (0)
+#endif
+
// Whether to provide "io.FileIO" class
#ifndef MICROPY_PY_IO_FILEIO
#define MICROPY_PY_IO_FILEIO (0)
diff --git a/unix/mpconfigport.h b/unix/mpconfigport.h
index d197f4503..d8b8e9d1e 100644
--- a/unix/mpconfigport.h
+++ b/unix/mpconfigport.h
@@ -101,6 +101,7 @@
#endif
#define MICROPY_PY_CMATH (1)
#define MICROPY_PY_IO_FILEIO (1)
+#define MICROPY_PY_IO_RESOURCE_STREAM (1)
#define MICROPY_PY_GC_COLLECT_RETVAL (1)
#define MICROPY_MODULE_FROZEN_STR (1)
From 7d4ba9d257865548e402e65033ac9c72307b6983 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 3 May 2017 01:47:14 +0300
Subject: [PATCH 148/826] tests/io/resource_stream: Add test for
uio.resource_stream().
---
tests/io/resource_stream.py | 17 +++++++++++++++++
tests/io/resource_stream.py.exp | 1 +
2 files changed, 18 insertions(+)
create mode 100644 tests/io/resource_stream.py
create mode 100644 tests/io/resource_stream.py.exp
diff --git a/tests/io/resource_stream.py b/tests/io/resource_stream.py
new file mode 100644
index 000000000..940ffaf2f
--- /dev/null
+++ b/tests/io/resource_stream.py
@@ -0,0 +1,17 @@
+import uio
+import sys
+
+try:
+ uio.resource_stream
+except AttributeError:
+ print('SKIP')
+ sys.exit()
+
+try:
+ buf = uio.resource_stream("data", "file2")
+except NotImplementedError:
+ pass
+
+# resource_stream(None, ...) look ups from current dir, hence sys.path[0] hack
+buf = uio.resource_stream(None, sys.path[0] + "/data/file2")
+print(buf.read())
diff --git a/tests/io/resource_stream.py.exp b/tests/io/resource_stream.py.exp
new file mode 100644
index 000000000..81c545efe
--- /dev/null
+++ b/tests/io/resource_stream.py.exp
@@ -0,0 +1 @@
+1234
From 5b57ae985ff7064dd7b09b0ce891697bfaa5dae2 Mon Sep 17 00:00:00 2001
From: stijn
Date: Wed, 10 Aug 2016 10:19:16 +0200
Subject: [PATCH 149/826] mpy-cross: Fix compiler detection for including
windows/fmode.c
fmode.c should only be included for builds targetting 'pure' windows, i.e.
msvc or mingw builds but not when using msys or cygwin's gcc (see #2298).
Just checking if the OS is windows and UNAME doesn't have msys stil leaves
the gate open for builds with cygwin's gcc since UNAME there is e.g.
CYGWIN_NT-6.1-WOW.
Fix this by checking for 'mingw' explicitly in the compiler version; both
gcc and clang have the -dumpmachine flag so the check should be ok for
all platforms.
---
mpy-cross/Makefile | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile
index 3d5e5da2f..6ed4e653f 100644
--- a/mpy-cross/Makefile
+++ b/mpy-cross/Makefile
@@ -49,10 +49,10 @@ SRC_C = \
main.c \
gccollect.c \
-ifeq ($(OS),Windows_NT)
- ifeq (,$(findstring MSYS,$(UNAME_S)))
- SRC_C += windows/fmode.c
- endif
+# Add fmode when compiling with mingw gcc
+COMPILER_TARGET := $(shell $(CC) -dumpmachine)
+ifneq (,$(findstring mingw,$(COMPILER_TARGET)))
+ SRC_C += windows/fmode.c
endif
OBJ = $(PY_O)
From ab4a8618cffc02d0838bd64372b066c99c2d2d7e Mon Sep 17 00:00:00 2001
From: stijn
Date: Mon, 1 May 2017 10:50:58 +0200
Subject: [PATCH 150/826] msvc: Workaround parser bug in older MSBuild versions
Versions prior to v14.0 have a bug in parsing item functions when used
within a condition: https://github.com/Microsoft/msbuild/issues/368.
Since commit [db9c2e3] this results in an error when building MicroPython
with for example VS2013.
Fix this by creating an intermediate property.
---
windows/msvc/genhdr.targets | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/windows/msvc/genhdr.targets b/windows/msvc/genhdr.targets
index 5792d878e..cac3e3ddc 100644
--- a/windows/msvc/genhdr.targets
+++ b/windows/msvc/genhdr.targets
@@ -69,13 +69,14 @@ using(var outFile = System.IO.File.CreateText(OutputFile)) {
@(QstrDependencies->AnyHaveMetadataValue('Changed', 'True'))
+ @(PyQstrSourceFiles->AnyHaveMetadataValue('Changed', 'True'))
+ Condition="'$(RunPreProcConcat)' == 'True' Or '$(ForceQstrRebuild)' == 'True'"/>
From 3923f96dc65bd37d16acec74f77546f048f9fa50 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 3 May 2017 12:22:53 +0300
Subject: [PATCH 151/826] tests/cpydiff/core_import_path: Test showing
difference in package.__path__.
---
tests/cpydiff/core_import_path.py | 9 +++++++++
1 file changed, 9 insertions(+)
create mode 100644 tests/cpydiff/core_import_path.py
diff --git a/tests/cpydiff/core_import_path.py b/tests/cpydiff/core_import_path.py
new file mode 100644
index 000000000..04fc4bd5b
--- /dev/null
+++ b/tests/cpydiff/core_import_path.py
@@ -0,0 +1,9 @@
+"""
+categories: Core,import
+description: __path__ attribute of a package has a different type (single string instead of list of strings) in MicroPython
+cause: MicroPython does't support namespace packages split across filesystem. Beyond that, MicroPython's import system is highly optimized for minimal memory usage.
+workaround: Details of import handling is inherently implementation dependent. Don't rely on such details in portable applications.
+"""
+import modules
+
+print(modules.__path__)
From 92657c671f85843ae5f0df85b954d844a5cdd9d1 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 3 May 2017 17:16:19 +0300
Subject: [PATCH 152/826] tests/cpydiff/core_import_split_ns_pkgs: Test for
split namespace packages.
---
tests/cpydiff/core_import_split_ns_pkgs.py | 14 ++++++++++++++
tests/cpydiff/modules/subpkg/foo.py | 0
tests/cpydiff/modules2/subpkg/bar.py | 0
3 files changed, 14 insertions(+)
create mode 100644 tests/cpydiff/core_import_split_ns_pkgs.py
create mode 100644 tests/cpydiff/modules/subpkg/foo.py
create mode 100644 tests/cpydiff/modules2/subpkg/bar.py
diff --git a/tests/cpydiff/core_import_split_ns_pkgs.py b/tests/cpydiff/core_import_split_ns_pkgs.py
new file mode 100644
index 000000000..700620c47
--- /dev/null
+++ b/tests/cpydiff/core_import_split_ns_pkgs.py
@@ -0,0 +1,14 @@
+"""
+categories: Core,import
+description: MicroPython does't support namespace packages split across filesystem.
+cause: MicroPython's import system is highly optimized for simplicity, minimal memory usage, and minimal filesystem search overhead.
+workaround: Don't install modules belonging to the same namespace package in different directories. For MicroPython, it's recommended to have at most 3-component module search paths: for your current application, per-user (writable), system-wide (non-writable).
+"""
+import sys
+sys.path.append(sys.path[1] + "/modules")
+sys.path.append(sys.path[1] + "/modules2")
+
+import subpkg.foo
+import subpkg.bar
+
+print("Two modules of a split namespace package imported")
diff --git a/tests/cpydiff/modules/subpkg/foo.py b/tests/cpydiff/modules/subpkg/foo.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/tests/cpydiff/modules2/subpkg/bar.py b/tests/cpydiff/modules2/subpkg/bar.py
new file mode 100644
index 000000000..e69de29bb
From 12ea06567c236f0c6e3aa6045ced9a9b1272ebc6 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 4 May 2017 00:48:48 +0300
Subject: [PATCH 153/826] tests/cpydiff/core_function_unpacking: Fill in
workaround.
---
tests/cpydiff/core_function_unpacking.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/cpydiff/core_function_unpacking.py b/tests/cpydiff/core_function_unpacking.py
index f0cc24055..01d25ee4d 100644
--- a/tests/cpydiff/core_function_unpacking.py
+++ b/tests/cpydiff/core_function_unpacking.py
@@ -1,7 +1,7 @@
"""
categories: Core,Functions
-description: Unpacking function arguments in non-last position gives incorrect result
+description: Unpacking function arguments in non-last position isn't detected as an error
cause: Unknown
-workaround: Unknown
+workaround: The syntax below is invalid, never use it in applications.
"""
print(*(1, 2), 3)
From d4c070415a3ec8ea06ab99b48ecf6976b7c93289 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 5 May 2017 13:12:19 +0300
Subject: [PATCH 154/826] tools/upip: Upgrade to 1.2.
Memory optimizations and error handling improvements.
---
tools/upip.py | 79 ++++++++++++++++++++++++++++-----------------------
1 file changed, 44 insertions(+), 35 deletions(-)
diff --git a/tools/upip.py b/tools/upip.py
index a156340b2..7b85c718f 100644
--- a/tools/upip.py
+++ b/tools/upip.py
@@ -104,6 +104,10 @@ def expandhome(s):
warn_ussl = True
def url_open(url):
global warn_ussl
+
+ if debug:
+ print(url)
+
proto, _, host, urlpath = url.split('/', 3)
try:
ai = usocket.getaddrinfo(host, 443)
@@ -113,41 +117,43 @@ def url_open(url):
addr = ai[0][4]
s = usocket.socket(ai[0][0])
- #print("Connect address:", addr)
- s.connect(addr)
-
- if proto == "https:":
- s = ussl.wrap_socket(s)
- if warn_ussl:
- print("Warning: %s SSL certificate is not validated" % host)
- warn_ussl = False
-
- # MicroPython rawsocket module supports file interface directly
- s.write("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (urlpath, host))
- l = s.readline()
- protover, status, msg = l.split(None, 2)
- if status != b"200":
- s.close()
- exc = ValueError(status)
- if status == b"404":
- fatal("Package not found", exc)
- fatal("Unexpected error querying for package", exc)
- while 1:
+ try:
+ #print("Connect address:", addr)
+ s.connect(addr)
+
+ if proto == "https:":
+ s = ussl.wrap_socket(s)
+ if warn_ussl:
+ print("Warning: %s SSL certificate is not validated" % host)
+ warn_ussl = False
+
+ # MicroPython rawsocket module supports file interface directly
+ s.write("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n" % (urlpath, host))
l = s.readline()
- if not l:
- s.close()
- fatal("Unexpected EOF in HTTP headers", ValueError())
- if l == b'\r\n':
- break
+ protover, status, msg = l.split(None, 2)
+ if status != b"200":
+ if status == b"404" or status == b"301":
+ raise NotFoundError("Package not found")
+ raise ValueError(status)
+ while 1:
+ l = s.readline()
+ if not l:
+ raise ValueError("Unexpected EOF in HTTP headers")
+ if l == b'\r\n':
+ break
+ except Exception as e:
+ s.close()
+ raise e
return s
def get_pkg_metadata(name):
f = url_open("https://pypi.python.org/pypi/%s/json" % name)
- s = f.read()
- f.close()
- return json.loads(s)
+ try:
+ return json.load(f)
+ finally:
+ f.close()
def fatal(msg, exc=None):
@@ -168,10 +174,12 @@ def install_pkg(pkg_spec, install_path):
print("Installing %s %s from %s" % (pkg_spec, latest_ver, package_url))
package_fname = op_basename(package_url)
f1 = url_open(package_url)
- f2 = uzlib.DecompIO(f1, gzdict_sz)
- f3 = tarfile.TarFile(fileobj=f2)
- meta = install_tar(f3, install_path)
- f1.close()
+ try:
+ f2 = uzlib.DecompIO(f1, gzdict_sz)
+ f3 = tarfile.TarFile(fileobj=f2)
+ meta = install_tar(f3, install_path)
+ finally:
+ f1.close()
del f3
del f2
gc.collect()
@@ -208,9 +216,10 @@ def install(to_install, install_path=None):
if deps:
deps = deps.decode("utf-8").split("\n")
to_install.extend(deps)
- except NotFoundError:
- print("Error: cannot find '%s' package (or server error), packages may be partially installed" \
- % pkg_spec, file=sys.stderr)
+ except Exception as e:
+ print("Error installing '{}': {}, packages may be partially installed".format(
+ pkg_spec, e),
+ file=sys.stderr)
def get_install_path():
global install_path
From c9a3a68a493426826841b4c0e22f8d688a12ad03 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 10 Mar 2017 17:13:29 +1100
Subject: [PATCH 155/826] extmod/vfs: Allow a VFS to be mounted at the root
dir.
This patch allows mounting of VFS objects right at the root directory, eg
os.mount(vfs, '/'). It still allows VFS's to be mounted at a path within
the root, eg os.mount(vfs, '/flash'), and such mount points will override
any paths within a VFS that is mounted at the root.
---
extmod/vfs.c | 61 +++++++++++++++++++++++++++++++++++++++++++---------
1 file changed, 51 insertions(+), 10 deletions(-)
diff --git a/extmod/vfs.c b/extmod/vfs.c
index e389ab324..84e9fe82d 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -27,6 +27,7 @@
#include
#include
+#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/objstr.h"
#include "py/mperrno.h"
@@ -50,8 +51,16 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) {
++path;
is_abs = 1;
}
+ if (*path == '\0') {
+ // path is "" or "/" so return virtual root
+ return MP_VFS_ROOT;
+ }
for (mp_vfs_mount_t *vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
size_t len = vfs->len - 1;
+ if (len == 0) {
+ *path_out = path - is_abs;
+ return vfs;
+ }
if (strncmp(path, vfs->str + 1, len) == 0) {
if (path[len] == '/') {
*path_out = path + len;
@@ -62,10 +71,9 @@ mp_vfs_mount_t *mp_vfs_lookup_path(const char *path, const char **path_out) {
}
}
}
- if (*path == '\0') {
- // path was "" or "/" so return virtual root
- return MP_VFS_ROOT;
- }
+
+ // if we get here then there's nothing mounted on /
+
if (is_abs) {
// path began with / and was not found
return MP_VFS_NONE;
@@ -162,13 +170,24 @@ mp_obj_t mp_vfs_mount(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
// check that the destination mount point is unused
const char *path_out;
- if (mp_vfs_lookup_path(mp_obj_str_get_str(pos_args[1]), &path_out) != MP_VFS_NONE) {
- mp_raise_OSError(MP_EPERM);
+ mp_vfs_mount_t *existing_mount = mp_vfs_lookup_path(mp_obj_str_get_str(pos_args[1]), &path_out);
+ if (existing_mount != MP_VFS_NONE && existing_mount != MP_VFS_ROOT) {
+ if (vfs->len != 1 && existing_mount->len == 1) {
+ // if root dir is mounted, still allow to mount something within a subdir of root
+ } else {
+ // mount point in use
+ mp_raise_OSError(MP_EPERM);
+ }
}
// insert the vfs into the mount table
mp_vfs_mount_t **vfsp = &MP_STATE_VM(vfs_mount_table);
while (*vfsp != NULL) {
+ if ((*vfsp)->len == 1) {
+ // make sure anything mounted at the root stays at the end of the list
+ vfs->next = *vfsp;
+ break;
+ }
vfsp = &(*vfsp)->next;
}
*vfsp = vfs;
@@ -228,10 +247,21 @@ MP_DEFINE_CONST_FUN_OBJ_KW(mp_vfs_open_obj, 0, mp_vfs_open);
mp_obj_t mp_vfs_chdir(mp_obj_t path_in) {
mp_obj_t path_out;
mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out);
- if (vfs != MP_VFS_ROOT) {
+ MP_STATE_VM(vfs_cur) = vfs;
+ if (vfs == MP_VFS_ROOT) {
+ // If we change to the root dir and a VFS is mounted at the root then
+ // we must change that VFS's current dir to the root dir so that any
+ // subsequent relative paths begin at the root of that VFS.
+ for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
+ if (vfs->len == 1) {
+ mp_obj_t root = mp_obj_new_str("/", 1, false);
+ mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &root);
+ break;
+ }
+ }
+ } else {
mp_vfs_proxy_call(vfs, MP_QSTR_chdir, 1, &path_out);
}
- MP_STATE_VM(vfs_cur) = vfs;
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj, mp_vfs_chdir);
@@ -241,6 +271,10 @@ mp_obj_t mp_vfs_getcwd(void) {
return MP_OBJ_NEW_QSTR(MP_QSTR__slash_);
}
mp_obj_t cwd_o = mp_vfs_proxy_call(MP_STATE_VM(vfs_cur), MP_QSTR_getcwd, 0, NULL);
+ if (MP_STATE_VM(vfs_cur)->len == 1) {
+ // don't prepend "/" for vfs mounted at root
+ return cwd_o;
+ }
const char *cwd = mp_obj_str_get_str(cwd_o);
vstr_t vstr;
vstr_init(&vstr, MP_STATE_VM(vfs_cur)->len + strlen(cwd) + 1);
@@ -267,8 +301,15 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
// list the root directory
mp_obj_t dir_list = mp_obj_new_list(0, NULL);
for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
- mp_obj_list_append(dir_list, mp_obj_new_str_of_type(mp_obj_get_type(path_in),
- (const byte*)vfs->str + 1, vfs->len - 1));
+ if (vfs->len == 1) {
+ // vfs is mounted at root dir, delegate to it
+ mp_obj_t root = mp_obj_new_str("/", 1, false);
+ mp_obj_t dir_list2 = mp_vfs_proxy_call(vfs, MP_QSTR_listdir, 1, &root);
+ dir_list = mp_binary_op(MP_BINARY_OP_ADD, dir_list, dir_list2);
+ } else {
+ mp_obj_list_append(dir_list, mp_obj_new_str_of_type(mp_obj_get_type(path_in),
+ (const byte*)vfs->str + 1, vfs->len - 1));
+ }
}
return dir_list;
}
From 6c8b57a90212c63441f8e5165b4781409648e519 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 10 Mar 2017 17:13:58 +1100
Subject: [PATCH 156/826] tests/extmod: Add more tests for VFS FAT.
---
tests/extmod/vfs_fat_more.py | 104 +++++++++++++++++++++++++++++++
tests/extmod/vfs_fat_more.py.exp | 28 +++++++++
2 files changed, 132 insertions(+)
create mode 100644 tests/extmod/vfs_fat_more.py
create mode 100644 tests/extmod/vfs_fat_more.py.exp
diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py
new file mode 100644
index 000000000..217d63995
--- /dev/null
+++ b/tests/extmod/vfs_fat_more.py
@@ -0,0 +1,104 @@
+import sys
+import uerrno
+try:
+ import uos_vfs as uos
+ open = uos.vfs_open
+except ImportError:
+ import uos
+try:
+ uos.VfsFat
+except AttributeError:
+ print("SKIP")
+ sys.exit()
+
+
+class RAMFS:
+
+ SEC_SIZE = 512
+
+ def __init__(self, blocks):
+ self.data = bytearray(blocks * self.SEC_SIZE)
+
+ def readblocks(self, n, buf):
+ #print("readblocks(%s, %x(%d))" % (n, id(buf), len(buf)))
+ for i in range(len(buf)):
+ buf[i] = self.data[n * self.SEC_SIZE + i]
+
+ def writeblocks(self, n, buf):
+ #print("writeblocks(%s, %x)" % (n, id(buf)))
+ for i in range(len(buf)):
+ self.data[n * self.SEC_SIZE + i] = buf[i]
+
+ def ioctl(self, op, arg):
+ #print("ioctl(%d, %r)" % (op, arg))
+ if op == 4: # BP_IOCTL_SEC_COUNT
+ return len(self.data) // self.SEC_SIZE
+ if op == 5: # BP_IOCTL_SEC_SIZE
+ return self.SEC_SIZE
+
+
+try:
+ bdev = RAMFS(50)
+ bdev2 = RAMFS(50)
+except MemoryError:
+ print("SKIP")
+ sys.exit()
+
+uos.VfsFat.mkfs(bdev)
+uos.mount(bdev, '/')
+
+print(uos.getcwd())
+
+f = open('test.txt', 'w')
+f.write('hello')
+f.close()
+
+print(uos.listdir())
+print(uos.listdir('/'))
+print(uos.stat('')[:-3])
+print(uos.stat('/')[:-3])
+print(uos.stat('test.txt')[:-3])
+print(uos.stat('/test.txt')[:-3])
+
+f = open('/test.txt')
+print(f.read())
+f.close()
+
+uos.rename('test.txt', 'test2.txt')
+print(uos.listdir())
+uos.rename('test2.txt', '/test3.txt')
+print(uos.listdir())
+uos.rename('/test3.txt', 'test4.txt')
+print(uos.listdir())
+uos.rename('/test4.txt', '/test5.txt')
+print(uos.listdir())
+
+uos.mkdir('dir')
+print(uos.listdir())
+uos.mkdir('/dir2')
+print(uos.listdir())
+uos.mkdir('dir/subdir')
+print(uos.listdir('dir'))
+for exist in ('', '/', 'dir', '/dir', 'dir/subdir'):
+ try:
+ uos.mkdir(exist)
+ except OSError as er:
+ print('mkdir OSError', er.args[0] == 17) # EEXIST
+
+uos.chdir('/')
+print(uos.stat('test5.txt')[:-3])
+
+uos.VfsFat.mkfs(bdev2)
+uos.mount(bdev2, '/sys')
+print(uos.listdir())
+print(uos.listdir('sys'))
+print(uos.listdir('/sys'))
+
+uos.rmdir('dir2')
+uos.remove('test5.txt')
+print(uos.listdir())
+
+uos.umount('/')
+print(uos.getcwd())
+print(uos.listdir())
+print(uos.listdir('sys'))
diff --git a/tests/extmod/vfs_fat_more.py.exp b/tests/extmod/vfs_fat_more.py.exp
new file mode 100644
index 000000000..aaca3cc75
--- /dev/null
+++ b/tests/extmod/vfs_fat_more.py.exp
@@ -0,0 +1,28 @@
+/
+['test.txt']
+['test.txt']
+(16384, 0, 0, 0, 0, 0, 0)
+(16384, 0, 0, 0, 0, 0, 0)
+(32768, 0, 0, 0, 0, 0, 5)
+(32768, 0, 0, 0, 0, 0, 5)
+hello
+['test2.txt']
+['test3.txt']
+['test4.txt']
+['test5.txt']
+['test5.txt', 'dir']
+['test5.txt', 'dir', 'dir2']
+['subdir']
+mkdir OSError True
+mkdir OSError True
+mkdir OSError True
+mkdir OSError True
+mkdir OSError True
+(32768, 0, 0, 0, 0, 0, 5)
+['sys', 'test5.txt', 'dir', 'dir2']
+[]
+[]
+['sys', 'dir']
+/
+['sys']
+[]
From 1b3e3724188af762ccab80cafc959a0e766983bc Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 10 Mar 2017 17:43:49 +1100
Subject: [PATCH 157/826] tests/extmod: Add some more VFS tests.
---
tests/extmod/vfs_basic.py | 20 ++++++++++++++++++++
tests/extmod/vfs_basic.py.exp | 19 +++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/tests/extmod/vfs_basic.py b/tests/extmod/vfs_basic.py
index 83c83fd22..1821a277d 100644
--- a/tests/extmod/vfs_basic.py
+++ b/tests/extmod/vfs_basic.py
@@ -109,3 +109,23 @@ def open(self, file, mode):
uos.umount('/test_mnt')
except OSError:
print('OSError')
+
+# root dir
+uos.mount(Filesystem(3), '/')
+print(uos.listdir())
+open('test')
+
+uos.mount(Filesystem(4), '/mnt')
+print(uos.listdir())
+print(uos.listdir('/mnt'))
+uos.chdir('/mnt')
+print(uos.listdir())
+
+# chdir to a subdir within root-mounted vfs, and then listdir
+uos.chdir('/subdir')
+print(uos.listdir())
+uos.chdir('/')
+
+uos.umount('/')
+print(uos.listdir('/'))
+uos.umount('/mnt')
diff --git a/tests/extmod/vfs_basic.py.exp b/tests/extmod/vfs_basic.py.exp
index 5104a16a6..416d45961 100644
--- a/tests/extmod/vfs_basic.py.exp
+++ b/tests/extmod/vfs_basic.py.exp
@@ -32,3 +32,22 @@ OSError
1 umount
2 umount
OSError
+3 mount False False
+3 listdir /
+['a3']
+3 open test r
+4 mount False False
+3 listdir /
+['mnt', 'a3']
+4 listdir /
+['a4']
+4 chdir /
+4 listdir
+['a4']
+3 chdir /subdir
+3 listdir
+['a3']
+3 chdir /
+3 umount
+['mnt']
+4 umount
From e62235f8c755b270e478f403d8ac75c5192847ba Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 10 Mar 2017 17:14:21 +1100
Subject: [PATCH 158/826] esp8266: Change default settings to mount flash at
root dir.
---
esp8266/main.c | 4 ++--
esp8266/modules/_boot.py | 4 +---
esp8266/qstrdefsport.h | 4 ++--
3 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/esp8266/main.c b/esp8266/main.c
index 888e58970..e3188dfe4 100644
--- a/esp8266/main.c
+++ b/esp8266/main.c
@@ -50,8 +50,8 @@ STATIC void mp_reset(void) {
mp_init();
mp_obj_list_init(mp_sys_path, 0);
mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_)); // current dir (or base dir of the script)
- mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash_slash_lib));
- mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_flash));
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_lib));
+ mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR__slash_));
mp_obj_list_init(mp_sys_argv, 0);
MP_STATE_PORT(term_obj) = MP_OBJ_NULL;
MP_STATE_PORT(dupterm_arr_obj) = MP_OBJ_NULL;
diff --git a/esp8266/modules/_boot.py b/esp8266/modules/_boot.py
index 954a9ee28..52683693d 100644
--- a/esp8266/modules/_boot.py
+++ b/esp8266/modules/_boot.py
@@ -5,9 +5,7 @@
try:
if bdev:
- vfs = uos.VfsFat(bdev)
- uos.mount(vfs, '/flash')
- uos.chdir('/flash')
+ uos.mount(bdev, '/')
except OSError:
import inisetup
vfs = inisetup.setup()
diff --git a/esp8266/qstrdefsport.h b/esp8266/qstrdefsport.h
index 676b3bae7..7610eb33d 100644
--- a/esp8266/qstrdefsport.h
+++ b/esp8266/qstrdefsport.h
@@ -27,5 +27,5 @@
// qstrs specific to this port, only needed if they aren't auto-generated
// Entries for sys.path
-Q(/flash)
-Q(/flash/lib)
+Q(/)
+Q(/lib)
From 288ea06e7ce80c24c242ebd065be39ab3ab64c12 Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Tue, 4 Apr 2017 15:56:40 -0700
Subject: [PATCH 159/826] lib/utils/pyexec: Update event-driven REPL to match
non-event REPL.
Don't print dupe ">>> " prompt when starting event-driven REPL. Clear
incomplete line in transition from raw to friendly REPL.
---
lib/utils/pyexec.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c
index 112cfe592..7d0d1cc38 100644
--- a/lib/utils/pyexec.c
+++ b/lib/utils/pyexec.c
@@ -171,7 +171,8 @@ STATIC int pyexec_friendly_repl_process_char(int c);
void pyexec_event_repl_init(void) {
MP_STATE_VM(repl_line) = vstr_new(32);
repl.cont_line = false;
- readline_init(MP_STATE_VM(repl_line), ">>> ");
+ // no prompt before printing friendly REPL banner or entering raw REPL
+ readline_init(MP_STATE_VM(repl_line), "");
if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
pyexec_raw_repl_process_char(CHAR_CTRL_A);
} else {
@@ -187,6 +188,7 @@ STATIC int pyexec_raw_repl_process_char(int c) {
} else if (c == CHAR_CTRL_B) {
// change to friendly REPL
pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL;
+ vstr_reset(MP_STATE_VM(repl_line));
repl.cont_line = false;
pyexec_friendly_repl_process_char(CHAR_CTRL_B);
return 0;
From 58bb73e010301235b32c3b81575af21cca55f2a7 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 21:42:39 +1000
Subject: [PATCH 160/826] py/objint: In int.from_bytes, only create big-int if
really needed.
This patch ensures that int.from_bytes only creates a big-int if necessary,
by checking the value for a small-int overflow as it's being parsed.
---
py/objint.c | 33 ++++++++++++++++-----------------
1 file changed, 16 insertions(+), 17 deletions(-)
diff --git a/py/objint.c b/py/objint.c
index 99c54a310..bda9c46cf 100644
--- a/py/objint.c
+++ b/py/objint.c
@@ -407,26 +407,25 @@ STATIC mp_obj_t int_from_bytes(size_t n_args, const mp_obj_t *args) {
mp_buffer_info_t bufinfo;
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ);
- #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
- // If result guaranteedly fits in small int, use that
- if (bufinfo.len >= sizeof(mp_uint_t) || !MP_SMALL_INT_FITS(1 << (bufinfo.len * 8 - 1))) {
- return mp_obj_int_from_bytes_impl(args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little), bufinfo.len, bufinfo.buf);
- } else
- #endif
- {
- const byte* buf = (const byte*)bufinfo.buf;
- int delta = 1;
- if (args[2] == MP_OBJ_NEW_QSTR(MP_QSTR_little)) {
- buf += bufinfo.len - 1;
- delta = -1;
- }
+ const byte* buf = (const byte*)bufinfo.buf;
+ int delta = 1;
+ if (args[2] == MP_OBJ_NEW_QSTR(MP_QSTR_little)) {
+ buf += bufinfo.len - 1;
+ delta = -1;
+ }
- mp_uint_t value = 0;
- for (; bufinfo.len--; buf += delta) {
- value = (value << 8) | *buf;
+ mp_uint_t value = 0;
+ size_t len = bufinfo.len;
+ for (; len--; buf += delta) {
+ #if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
+ if (value > (MP_SMALL_INT_MAX >> 8)) {
+ // Result will overflow a small-int so construct a big-int
+ return mp_obj_int_from_bytes_impl(args[2] != MP_OBJ_NEW_QSTR(MP_QSTR_little), bufinfo.len, bufinfo.buf);
}
- return mp_obj_new_int_from_uint(value);
+ #endif
+ value = (value << 8) | *buf;
}
+ return mp_obj_new_int_from_uint(value);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(int_from_bytes_fun_obj, 3, 4, int_from_bytes);
From dce7dd425977320b822f8bb529d123eafebe6e55 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 21:44:12 +1000
Subject: [PATCH 161/826] tests/micropython: Add test for int.from_bytes with
many zero bytes.
---
tests/micropython/heapalloc_int_from_bytes.py | 1 +
tests/micropython/heapalloc_int_from_bytes.py.exp | 1 +
2 files changed, 2 insertions(+)
diff --git a/tests/micropython/heapalloc_int_from_bytes.py b/tests/micropython/heapalloc_int_from_bytes.py
index f8afd2280..5fe50443a 100644
--- a/tests/micropython/heapalloc_int_from_bytes.py
+++ b/tests/micropython/heapalloc_int_from_bytes.py
@@ -5,4 +5,5 @@
micropython.heap_lock()
print(int.from_bytes(b"1", "little"))
print(int.from_bytes(b"12", "little"))
+print(int.from_bytes(b"2\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", "little"))
micropython.heap_unlock()
diff --git a/tests/micropython/heapalloc_int_from_bytes.py.exp b/tests/micropython/heapalloc_int_from_bytes.py.exp
index 7ceb19a38..5ac6a573f 100644
--- a/tests/micropython/heapalloc_int_from_bytes.py.exp
+++ b/tests/micropython/heapalloc_int_from_bytes.py.exp
@@ -1,2 +1,3 @@
49
12849
+50
From 084824f866af4cda42a41a16d844fa47ba3b8938 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 6 May 2017 11:01:57 +1000
Subject: [PATCH 162/826] tests: Move super-as-local test from cpydiff to basic
tests.
It's now possible to use the name "super" as a local variable.
---
tests/basics/class_super_aslocal.py | 9 +++++++++
tests/cpydiff/core_class_superaslocal.py | 13 -------------
2 files changed, 9 insertions(+), 13 deletions(-)
create mode 100644 tests/basics/class_super_aslocal.py
delete mode 100644 tests/cpydiff/core_class_superaslocal.py
diff --git a/tests/basics/class_super_aslocal.py b/tests/basics/class_super_aslocal.py
new file mode 100644
index 000000000..c9259110a
--- /dev/null
+++ b/tests/basics/class_super_aslocal.py
@@ -0,0 +1,9 @@
+# test using the name "super" as a local variable
+
+class A:
+ def foo(self):
+ super = [1, 2]
+ super.pop()
+ print(super)
+
+A().foo()
diff --git a/tests/cpydiff/core_class_superaslocal.py b/tests/cpydiff/core_class_superaslocal.py
deleted file mode 100644
index fc07ccb38..000000000
--- a/tests/cpydiff/core_class_superaslocal.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""
-categories: Core,Classes
-description: Bug when using "super" as a local
-cause: Unknown
-workaround: Unknown
-"""
-class A:
- def foo(self):
- super = [1]
- super.pop()
- print(super)
-
-A().foo()
From 0986675451edbdcbe31d90ddacf8f6dc3327a4ae Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 6 May 2017 17:03:40 +1000
Subject: [PATCH 163/826] stmhal: Convert all module and method tables to use
MP_ROM macros.
---
stmhal/accel.c | 18 +++----
stmhal/adc.c | 22 ++++----
stmhal/boards/make-pins.py | 4 +-
stmhal/can.c | 36 ++++++-------
stmhal/dac.c | 20 +++----
stmhal/extint.c | 26 ++++-----
stmhal/i2c.c | 24 ++++-----
stmhal/lcd.c | 22 ++++----
stmhal/led.c | 12 ++---
stmhal/make-stmconst.py | 6 +--
stmhal/modmachine.c | 84 ++++++++++++++---------------
stmhal/modnetwork.c | 10 ++--
stmhal/modnwcc3k.c | 22 ++++----
stmhal/modnwwiznet5k.c | 8 +--
stmhal/modpyb.c | 108 ++++++++++++++++++-------------------
stmhal/modstm.c | 10 ++--
stmhal/moduos.c | 40 +++++++-------
stmhal/modusocket.c | 62 ++++++++++-----------
stmhal/pin.c | 76 +++++++++++++-------------
stmhal/pybstdio.c | 24 ++++-----
stmhal/rtc.c | 14 ++---
stmhal/sdcard.c | 20 +++----
stmhal/servo.c | 12 ++---
stmhal/spi.c | 42 +++++++--------
stmhal/storage.c | 10 ++--
stmhal/timer.c | 76 +++++++++++++-------------
stmhal/uart.c | 28 +++++-----
stmhal/usb.c | 40 +++++++-------
stmhal/usrsw.c | 6 +--
stmhal/wdt.c | 6 +--
30 files changed, 444 insertions(+), 444 deletions(-)
diff --git a/stmhal/accel.c b/stmhal/accel.c
index 2e3504b06..d0d4148ab 100644
--- a/stmhal/accel.c
+++ b/stmhal/accel.c
@@ -211,15 +211,15 @@ STATIC mp_obj_t pyb_accel_write(mp_obj_t self_in, mp_obj_t reg, mp_obj_t val) {
}
MP_DEFINE_CONST_FUN_OBJ_3(pyb_accel_write_obj, pyb_accel_write);
-STATIC const mp_map_elem_t pyb_accel_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_accel_locals_dict_table[] = {
// TODO add init, deinit, and perhaps reset methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_x), (mp_obj_t)&pyb_accel_x_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_y), (mp_obj_t)&pyb_accel_y_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_z), (mp_obj_t)&pyb_accel_z_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_tilt), (mp_obj_t)&pyb_accel_tilt_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_filtered_xyz), (mp_obj_t)&pyb_accel_filtered_xyz_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_accel_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_accel_write_obj },
+ { MP_ROM_QSTR(MP_QSTR_x), MP_ROM_PTR(&pyb_accel_x_obj) },
+ { MP_ROM_QSTR(MP_QSTR_y), MP_ROM_PTR(&pyb_accel_y_obj) },
+ { MP_ROM_QSTR(MP_QSTR_z), MP_ROM_PTR(&pyb_accel_z_obj) },
+ { MP_ROM_QSTR(MP_QSTR_tilt), MP_ROM_PTR(&pyb_accel_tilt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_filtered_xyz), MP_ROM_PTR(&pyb_accel_filtered_xyz_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&pyb_accel_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_accel_write_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_accel_locals_dict, pyb_accel_locals_dict_table);
@@ -228,7 +228,7 @@ const mp_obj_type_t pyb_accel_type = {
{ &mp_type_type },
.name = MP_QSTR_Accel,
.make_new = pyb_accel_make_new,
- .locals_dict = (mp_obj_t)&pyb_accel_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_accel_locals_dict,
};
#endif // MICROPY_HW_HAS_MMA7660
diff --git a/stmhal/adc.c b/stmhal/adc.c
index 11259546b..9ab725fe2 100644
--- a/stmhal/adc.c
+++ b/stmhal/adc.c
@@ -439,9 +439,9 @@ STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_obj, adc_read_timed);
-STATIC const mp_map_elem_t adc_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_timed), (mp_obj_t)&adc_read_timed_obj},
+STATIC const mp_rom_map_elem_t adc_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&adc_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read_timed), MP_ROM_PTR(&adc_read_timed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table);
@@ -451,7 +451,7 @@ const mp_obj_type_t pyb_adc_type = {
.name = MP_QSTR_ADC,
.print = adc_print,
.make_new = adc_make_new,
- .locals_dict = (mp_obj_t)&adc_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&adc_locals_dict,
};
/******************************************************************************/
@@ -658,13 +658,13 @@ STATIC mp_obj_t adc_all_read_vref(mp_obj_t self_in) {
STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_all_read_vref_obj, adc_all_read_vref);
#endif
-STATIC const mp_map_elem_t adc_all_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_channel), (mp_obj_t)&adc_all_read_channel_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_core_temp), (mp_obj_t)&adc_all_read_core_temp_obj},
+STATIC const mp_rom_map_elem_t adc_all_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_read_channel), MP_ROM_PTR(&adc_all_read_channel_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read_core_temp), MP_ROM_PTR(&adc_all_read_core_temp_obj) },
#if MICROPY_PY_BUILTINS_FLOAT
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_core_vbat), (mp_obj_t)&adc_all_read_core_vbat_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_core_vref), (mp_obj_t)&adc_all_read_core_vref_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_read_vref), (mp_obj_t)&adc_all_read_vref_obj},
+ { MP_ROM_QSTR(MP_QSTR_read_core_vbat), MP_ROM_PTR(&adc_all_read_core_vbat_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read_core_vref), MP_ROM_PTR(&adc_all_read_core_vref_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read_vref), MP_ROM_PTR(&adc_all_read_vref_obj) },
#endif
};
@@ -674,5 +674,5 @@ const mp_obj_type_t pyb_adc_all_type = {
{ &mp_type_type },
.name = MP_QSTR_ADCAll,
.make_new = adc_all_make_new,
- .locals_dict = (mp_obj_t)&adc_all_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&adc_all_locals_dict,
};
diff --git a/stmhal/boards/make-pins.py b/stmhal/boards/make-pins.py
index 371ac77dd..51619ffa2 100755
--- a/stmhal/boards/make-pins.py
+++ b/stmhal/boards/make-pins.py
@@ -283,11 +283,11 @@ def parse_board_file(self, filename):
self.board_pins.append(NamedPin(row[0], pin))
def print_named(self, label, named_pins):
- print('STATIC const mp_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label))
+ print('STATIC const mp_rom_map_elem_t pin_{:s}_pins_locals_dict_table[] = {{'.format(label))
for named_pin in named_pins:
pin = named_pin.pin()
if pin.is_board_pin():
- print(' {{ MP_OBJ_NEW_QSTR(MP_QSTR_{:s}), (mp_obj_t)&pin_{:s} }},'.format(named_pin.name(), pin.cpu_pin_name()))
+ print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},'.format(named_pin.name(), pin.cpu_pin_name()))
print('};')
print('MP_DEFINE_CONST_DICT(pin_{:s}_pins_locals_dict, pin_{:s}_pins_locals_dict_table);'.format(label, label));
diff --git a/stmhal/can.c b/stmhal/can.c
index 09861ec73..fe52d8678 100644
--- a/stmhal/can.c
+++ b/stmhal/can.c
@@ -777,29 +777,29 @@ STATIC mp_obj_t pyb_can_rxcallback(mp_obj_t self_in, mp_obj_t fifo_in, mp_obj_t
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_can_rxcallback_obj, pyb_can_rxcallback);
-STATIC const mp_map_elem_t pyb_can_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_can_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_can_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_can_deinit_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_can_any_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_can_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_can_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_initfilterbanks), (mp_obj_t)&pyb_can_initfilterbanks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_setfilter), (mp_obj_t)&pyb_can_setfilter_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_clearfilter), (mp_obj_t)&pyb_can_clearfilter_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_rxcallback), (mp_obj_t)&pyb_can_rxcallback_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_can_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_can_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_can_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_can_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_can_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_initfilterbanks), MP_ROM_PTR(&pyb_can_initfilterbanks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setfilter), MP_ROM_PTR(&pyb_can_setfilter_obj) },
+ { MP_ROM_QSTR(MP_QSTR_clearfilter), MP_ROM_PTR(&pyb_can_clearfilter_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rxcallback), MP_ROM_PTR(&pyb_can_rxcallback_obj) },
// class constants
// Note: we use the ST constants >> 4 so they fit in a small-int. The
// right-shift is undone when the constants are used in the init function.
- { MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL), MP_OBJ_NEW_SMALL_INT(CAN_MODE_NORMAL >> 4) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_LOOPBACK >> 4) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SILENT), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT >> 4) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_OBJ_NEW_SMALL_INT(CAN_MODE_SILENT_LOOPBACK >> 4) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_MASK16), MP_OBJ_NEW_SMALL_INT(MASK16) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LIST16), MP_OBJ_NEW_SMALL_INT(LIST16) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_MASK32), MP_OBJ_NEW_SMALL_INT(MASK32) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LIST32), MP_OBJ_NEW_SMALL_INT(LIST32) },
+ { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(CAN_MODE_NORMAL >> 4) },
+ { MP_ROM_QSTR(MP_QSTR_LOOPBACK), MP_ROM_INT(CAN_MODE_LOOPBACK >> 4) },
+ { MP_ROM_QSTR(MP_QSTR_SILENT), MP_ROM_INT(CAN_MODE_SILENT >> 4) },
+ { MP_ROM_QSTR(MP_QSTR_SILENT_LOOPBACK), MP_ROM_INT(CAN_MODE_SILENT_LOOPBACK >> 4) },
+ { MP_ROM_QSTR(MP_QSTR_MASK16), MP_ROM_INT(MASK16) },
+ { MP_ROM_QSTR(MP_QSTR_LIST16), MP_ROM_INT(LIST16) },
+ { MP_ROM_QSTR(MP_QSTR_MASK32), MP_ROM_INT(MASK32) },
+ { MP_ROM_QSTR(MP_QSTR_LIST32), MP_ROM_INT(LIST32) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_can_locals_dict, pyb_can_locals_dict_table);
diff --git a/stmhal/dac.c b/stmhal/dac.c
index 48c0ce8bd..6524c6840 100644
--- a/stmhal/dac.c
+++ b/stmhal/dac.c
@@ -481,20 +481,20 @@ mp_obj_t pyb_dac_write_timed(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_dac_write_timed_obj, 1, pyb_dac_write_timed);
#endif
-STATIC const mp_map_elem_t pyb_dac_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_dac_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_dac_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_dac_deinit_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_dac_write_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_dac_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_dac_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_dac_write_obj) },
#if defined(TIM6)
- { MP_OBJ_NEW_QSTR(MP_QSTR_noise), (mp_obj_t)&pyb_dac_noise_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_triangle), (mp_obj_t)&pyb_dac_triangle_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write_timed), (mp_obj_t)&pyb_dac_write_timed_obj },
+ { MP_ROM_QSTR(MP_QSTR_noise), MP_ROM_PTR(&pyb_dac_noise_obj) },
+ { MP_ROM_QSTR(MP_QSTR_triangle), MP_ROM_PTR(&pyb_dac_triangle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write_timed), MP_ROM_PTR(&pyb_dac_write_timed_obj) },
#endif
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_NORMAL), MP_OBJ_NEW_SMALL_INT(DMA_NORMAL) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_CIRCULAR), MP_OBJ_NEW_SMALL_INT(DMA_CIRCULAR) },
+ { MP_ROM_QSTR(MP_QSTR_NORMAL), MP_ROM_INT(DMA_NORMAL) },
+ { MP_ROM_QSTR(MP_QSTR_CIRCULAR), MP_ROM_INT(DMA_CIRCULAR) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_dac_locals_dict, pyb_dac_locals_dict_table);
@@ -503,7 +503,7 @@ const mp_obj_type_t pyb_dac_type = {
{ &mp_type_type },
.name = MP_QSTR_DAC,
.make_new = pyb_dac_make_new,
- .locals_dict = (mp_obj_t)&pyb_dac_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_dac_locals_dict,
};
#endif // MICROPY_HW_ENABLE_DAC
diff --git a/stmhal/extint.c b/stmhal/extint.c
index 59b00cb73..642ecfd85 100644
--- a/stmhal/extint.c
+++ b/stmhal/extint.c
@@ -368,23 +368,23 @@ STATIC void extint_obj_print(const mp_print_t *print, mp_obj_t self_in, mp_print
mp_printf(print, "", self->line);
}
-STATIC const mp_map_elem_t extint_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_line), (mp_obj_t)&extint_obj_line_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_enable), (mp_obj_t)&extint_obj_enable_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_disable), (mp_obj_t)&extint_obj_disable_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_swint), (mp_obj_t)&extint_obj_swint_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_regs), (mp_obj_t)&extint_regs_obj },
+STATIC const mp_rom_map_elem_t extint_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_line), MP_ROM_PTR(&extint_obj_line_obj) },
+ { MP_ROM_QSTR(MP_QSTR_enable), MP_ROM_PTR(&extint_obj_enable_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disable), MP_ROM_PTR(&extint_obj_disable_obj) },
+ { MP_ROM_QSTR(MP_QSTR_swint), MP_ROM_PTR(&extint_obj_swint_obj) },
+ { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&extint_regs_obj) },
// class constants
/// \constant IRQ_RISING - interrupt on a rising edge
/// \constant IRQ_FALLING - interrupt on a falling edge
/// \constant IRQ_RISING_FALLING - interrupt on a rising or falling edge
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_RISING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_FALLING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_IT_RISING_FALLING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_EVT_RISING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_EVT_RISING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_EVT_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_EVT_FALLING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_EVT_RISING_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING), MP_ROM_INT(GPIO_MODE_IT_RISING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_FALLING), MP_ROM_INT(GPIO_MODE_IT_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_IRQ_RISING_FALLING), MP_ROM_INT(GPIO_MODE_IT_RISING_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_EVT_RISING), MP_ROM_INT(GPIO_MODE_EVT_RISING) },
+ { MP_ROM_QSTR(MP_QSTR_EVT_FALLING), MP_ROM_INT(GPIO_MODE_EVT_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_EVT_RISING_FALLING), MP_ROM_INT(GPIO_MODE_EVT_RISING_FALLING) },
};
STATIC MP_DEFINE_CONST_DICT(extint_locals_dict, extint_locals_dict_table);
@@ -394,7 +394,7 @@ const mp_obj_type_t extint_type = {
.name = MP_QSTR_ExtInt,
.print = extint_obj_print,
.make_new = extint_make_new,
- .locals_dict = (mp_obj_t)&extint_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&extint_locals_dict,
};
void extint_init0(void) {
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index a3ded36ec..4a792d163 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -1010,22 +1010,22 @@ STATIC mp_obj_t pyb_i2c_mem_write(mp_uint_t n_args, const mp_obj_t *pos_args, mp
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_mem_write_obj, 1, pyb_i2c_mem_write);
-STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_i2c_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_i2c_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_i2c_deinit_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_is_ready), (mp_obj_t)&pyb_i2c_is_ready_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_i2c_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_i2c_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_i2c_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_i2c_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_is_ready), MP_ROM_PTR(&pyb_i2c_is_ready_obj) },
+ { MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&pyb_i2c_scan_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_i2c_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_i2c_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem_read), MP_ROM_PTR(&pyb_i2c_mem_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem_write), MP_ROM_PTR(&pyb_i2c_mem_write_obj) },
// class constants
/// \constant MASTER - for initialising the bus to master mode
/// \constant SLAVE - for initialising the bus to slave mode
- { MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(PYB_I2C_MASTER) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE), MP_OBJ_NEW_SMALL_INT(PYB_I2C_SLAVE) },
+ { MP_ROM_QSTR(MP_QSTR_MASTER), MP_ROM_INT(PYB_I2C_MASTER) },
+ { MP_ROM_QSTR(MP_QSTR_SLAVE), MP_ROM_INT(PYB_I2C_SLAVE) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_i2c_locals_dict, pyb_i2c_locals_dict_table);
@@ -1035,5 +1035,5 @@ const mp_obj_type_t pyb_i2c_type = {
.name = MP_QSTR_I2C,
.print = pyb_i2c_print,
.make_new = pyb_i2c_make_new,
- .locals_dict = (mp_obj_t)&pyb_i2c_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_i2c_locals_dict,
};
diff --git a/stmhal/lcd.c b/stmhal/lcd.c
index ae453f0fc..da0974460 100644
--- a/stmhal/lcd.c
+++ b/stmhal/lcd.c
@@ -504,17 +504,17 @@ STATIC mp_obj_t pyb_lcd_show(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_lcd_show_obj, pyb_lcd_show);
-STATIC const mp_map_elem_t pyb_lcd_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_lcd_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_command), (mp_obj_t)&pyb_lcd_command_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_contrast), (mp_obj_t)&pyb_lcd_contrast_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_light), (mp_obj_t)&pyb_lcd_light_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_lcd_write_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_fill), (mp_obj_t)&pyb_lcd_fill_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_get), (mp_obj_t)&pyb_lcd_get_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pixel), (mp_obj_t)&pyb_lcd_pixel_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_text), (mp_obj_t)&pyb_lcd_text_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_show), (mp_obj_t)&pyb_lcd_show_obj },
+ { MP_ROM_QSTR(MP_QSTR_command), MP_ROM_PTR(&pyb_lcd_command_obj) },
+ { MP_ROM_QSTR(MP_QSTR_contrast), MP_ROM_PTR(&pyb_lcd_contrast_obj) },
+ { MP_ROM_QSTR(MP_QSTR_light), MP_ROM_PTR(&pyb_lcd_light_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&pyb_lcd_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_fill), MP_ROM_PTR(&pyb_lcd_fill_obj) },
+ { MP_ROM_QSTR(MP_QSTR_get), MP_ROM_PTR(&pyb_lcd_get_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pixel), MP_ROM_PTR(&pyb_lcd_pixel_obj) },
+ { MP_ROM_QSTR(MP_QSTR_text), MP_ROM_PTR(&pyb_lcd_text_obj) },
+ { MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&pyb_lcd_show_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_lcd_locals_dict, pyb_lcd_locals_dict_table);
@@ -523,7 +523,7 @@ const mp_obj_type_t pyb_lcd_type = {
{ &mp_type_type },
.name = MP_QSTR_LCD,
.make_new = pyb_lcd_make_new,
- .locals_dict = (mp_obj_t)&pyb_lcd_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_lcd_locals_dict,
};
#endif // MICROPY_HW_HAS_LCD
diff --git a/stmhal/led.c b/stmhal/led.c
index be98aa4a4..466514684 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -349,11 +349,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_off_obj, led_obj_off);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(led_obj_toggle_obj, led_obj_toggle);
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(led_obj_intensity_obj, 1, 2, led_obj_intensity);
-STATIC const mp_map_elem_t led_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_on), (mp_obj_t)&led_obj_on_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_off), (mp_obj_t)&led_obj_off_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_toggle), (mp_obj_t)&led_obj_toggle_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_intensity), (mp_obj_t)&led_obj_intensity_obj },
+STATIC const mp_rom_map_elem_t led_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_on), MP_ROM_PTR(&led_obj_on_obj) },
+ { MP_ROM_QSTR(MP_QSTR_off), MP_ROM_PTR(&led_obj_off_obj) },
+ { MP_ROM_QSTR(MP_QSTR_toggle), MP_ROM_PTR(&led_obj_toggle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_intensity), MP_ROM_PTR(&led_obj_intensity_obj) },
};
STATIC MP_DEFINE_CONST_DICT(led_locals_dict, led_locals_dict_table);
@@ -363,7 +363,7 @@ const mp_obj_type_t pyb_led_type = {
.name = MP_QSTR_LED,
.print = led_obj_print,
.make_new = led_obj_make_new,
- .locals_dict = (mp_obj_t)&led_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&led_locals_dict,
};
#else
diff --git a/stmhal/make-stmconst.py b/stmhal/make-stmconst.py
index c9eb42a40..9bb7a0569 100644
--- a/stmhal/make-stmconst.py
+++ b/stmhal/make-stmconst.py
@@ -162,13 +162,13 @@ def print_regs_as_submodules(reg_name, reg_defs, modules, needed_qstrs):
modules.append((mod_name_lower, mod_name_upper))
print("""
-STATIC const mp_map_elem_t stm_%s_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_%s) },
+STATIC const mp_rom_map_elem_t stm_%s_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_%s) },
""" % (mod_name_lower, mod_name_upper))
needed_qstrs.add(mod_name_upper)
for r in reg_defs:
- print(' { MP_OBJ_NEW_QSTR(MP_QSTR_%s), MP_OBJ_NEW_SMALL_INT(%#x) }, // %s-bits, %s' % (r[0], r[1], r[2], r[3]))
+ print(' { MP_ROM_QSTR(MP_QSTR_%s), MP_ROM_INT(%#x) }, // %s-bits, %s' % (r[0], r[1], r[2], r[3]))
needed_qstrs.add(r[0])
print("""};
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index d615a0f2b..98d5c2da9 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -518,66 +518,66 @@ STATIC mp_obj_t machine_reset_cause(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_cause_obj, machine_reset_cause);
-STATIC const mp_map_elem_t machine_module_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_umachine) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&machine_unique_id_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&machine_reset_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_soft_reset), (mp_obj_t)&machine_soft_reset_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&machine_freq_obj },
+STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
+ { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset), MP_ROM_PTR(&machine_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_soft_reset), MP_ROM_PTR(&machine_soft_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
+ { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
#if MICROPY_HW_ENABLE_RNG
- { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
+ { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_idle), (mp_obj_t)&pyb_wfi_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&machine_sleep_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deepsleep), (mp_obj_t)&machine_deepsleep_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_reset_cause), (mp_obj_t)&machine_reset_cause_obj },
+ { MP_ROM_QSTR(MP_QSTR_idle), MP_ROM_PTR(&pyb_wfi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sleep), MP_ROM_PTR(&machine_sleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deepsleep), MP_ROM_PTR(&machine_deepsleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reset_cause), MP_ROM_PTR(&machine_reset_cause_obj) },
#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_wake_reason), (mp_obj_t)&machine_wake_reason_obj },
+ { MP_ROM_QSTR(MP_QSTR_wake_reason), MP_ROM_PTR(&machine_wake_reason_obj) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
+ { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_time_pulse_us), (mp_obj_t)&machine_time_pulse_us_obj },
+ { MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
- { MP_ROM_QSTR(MP_QSTR_mem8), (mp_obj_t)&machine_mem8_obj },
- { MP_ROM_QSTR(MP_QSTR_mem16), (mp_obj_t)&machine_mem16_obj },
- { MP_ROM_QSTR(MP_QSTR_mem32), (mp_obj_t)&machine_mem32_obj },
+ { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Signal), (mp_obj_t)&machine_signal_type },
+ { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
+ { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
+ { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
#endif
// TODO: Per new API, I2C types below, if called with 1 arg (ID), should still
// initialize master mode on the peripheral.
- { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&machine_i2c_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&machine_hard_spi_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WDT), (mp_obj_t)&pyb_wdt_type },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) },
#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_HeartBeat), (mp_obj_t)&pyb_heartbeat_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sd_type },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
+ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
+ { MP_ROM_QSTR(MP_QSTR_HeartBeat), MP_ROM_PTR(&pyb_heartbeat_type) },
+ { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_IDLE), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_ACTIVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_LPDS) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP), MP_OBJ_NEW_SMALL_INT(PYB_PWR_MODE_HIBERNATE) },
+ { MP_ROM_QSTR(MP_QSTR_IDLE), MP_ROM_INT(PYB_PWR_MODE_ACTIVE) },
+ { MP_ROM_QSTR(MP_QSTR_SLEEP), MP_ROM_INT(PYB_PWR_MODE_LPDS) },
+ { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP), MP_ROM_INT(PYB_PWR_MODE_HIBERNATE) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_PWRON_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_POWER_ON) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_HARD_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_HARD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WDT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_WDT) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_DEEPSLEEP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SOFT_RESET), MP_OBJ_NEW_SMALL_INT(PYB_RESET_SOFT) },
+ { MP_ROM_QSTR(MP_QSTR_PWRON_RESET), MP_ROM_INT(PYB_RESET_POWER_ON) },
+ { MP_ROM_QSTR(MP_QSTR_HARD_RESET), MP_ROM_INT(PYB_RESET_HARD) },
+ { MP_ROM_QSTR(MP_QSTR_WDT_RESET), MP_ROM_INT(PYB_RESET_WDT) },
+ { MP_ROM_QSTR(MP_QSTR_DEEPSLEEP_RESET), MP_ROM_INT(PYB_RESET_DEEPSLEEP) },
+ { MP_ROM_QSTR(MP_QSTR_SOFT_RESET), MP_ROM_INT(PYB_RESET_SOFT) },
#if 0
- { MP_OBJ_NEW_QSTR(MP_QSTR_WLAN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_WLAN) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PIN_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_GPIO) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_RTC_WAKE), MP_OBJ_NEW_SMALL_INT(PYB_SLP_WAKED_BY_RTC) },
+ { MP_ROM_QSTR(MP_QSTR_WLAN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_WLAN) },
+ { MP_ROM_QSTR(MP_QSTR_PIN_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_GPIO) },
+ { MP_ROM_QSTR(MP_QSTR_RTC_WAKE), MP_ROM_INT(PYB_SLP_WAKED_BY_RTC) },
#endif
};
diff --git a/stmhal/modnetwork.c b/stmhal/modnetwork.c
index c15bfc7b2..09a80ef3c 100644
--- a/stmhal/modnetwork.c
+++ b/stmhal/modnetwork.c
@@ -71,17 +71,17 @@ STATIC mp_obj_t network_route(void) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(network_route_obj, network_route);
-STATIC const mp_map_elem_t mp_module_network_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_network) },
+STATIC const mp_rom_map_elem_t mp_module_network_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_network) },
#if MICROPY_PY_WIZNET5K
- { MP_OBJ_NEW_QSTR(MP_QSTR_WIZNET5K), (mp_obj_t)&mod_network_nic_type_wiznet5k },
+ { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
#endif
#if MICROPY_PY_CC3K
- { MP_OBJ_NEW_QSTR(MP_QSTR_CC3K), (mp_obj_t)&mod_network_nic_type_cc3k },
+ { MP_ROM_QSTR(MP_QSTR_CC3K), MP_ROM_PTR(&mod_network_nic_type_cc3k) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_route), (mp_obj_t)&network_route_obj },
+ { MP_ROM_QSTR(MP_QSTR_route), MP_ROM_PTR(&network_route_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_network_globals, mp_module_network_globals_table);
diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c
index 26c6cd48c..957d74e6e 100644
--- a/stmhal/modnwcc3k.c
+++ b/stmhal/modnwcc3k.c
@@ -562,18 +562,18 @@ STATIC mp_obj_t cc3k_patch_program(mp_obj_t self_in, mp_obj_t key_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(cc3k_patch_program_obj, cc3k_patch_program);
-STATIC const mp_map_elem_t cc3k_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&cc3k_connect_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_disconnect), (mp_obj_t)&cc3k_disconnect_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&cc3k_isconnected_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&cc3k_ifconfig_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_patch_version), (mp_obj_t)&cc3k_patch_version_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_patch_program), (mp_obj_t)&cc3k_patch_program_obj },
+STATIC const mp_rom_map_elem_t cc3k_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&cc3k_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&cc3k_disconnect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&cc3k_isconnected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&cc3k_ifconfig_obj) },
+ { MP_ROM_QSTR(MP_QSTR_patch_version), MP_ROM_PTR(&cc3k_patch_version_obj) },
+ { MP_ROM_QSTR(MP_QSTR_patch_program), MP_ROM_PTR(&cc3k_patch_program_obj) },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WEP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(WLAN_SEC_WPA2) },
+ { MP_ROM_QSTR(MP_QSTR_WEP), MP_ROM_INT(WLAN_SEC_WEP) },
+ { MP_ROM_QSTR(MP_QSTR_WPA), MP_ROM_INT(WLAN_SEC_WPA) },
+ { MP_ROM_QSTR(MP_QSTR_WPA2), MP_ROM_INT(WLAN_SEC_WPA2) },
};
STATIC MP_DEFINE_CONST_DICT(cc3k_locals_dict, cc3k_locals_dict_table);
@@ -583,7 +583,7 @@ const mod_network_nic_type_t mod_network_nic_type_cc3k = {
{ &mp_type_type },
.name = MP_QSTR_CC3K,
.make_new = cc3k_make_new,
- .locals_dict = (mp_obj_t)&cc3k_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&cc3k_locals_dict,
},
.gethostbyname = cc3k_gethostbyname,
.socket = cc3k_socket_socket,
diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c
index b32f16913..4752cdc0b 100644
--- a/stmhal/modnwwiznet5k.c
+++ b/stmhal/modnwwiznet5k.c
@@ -433,9 +433,9 @@ STATIC mp_obj_t wiznet5k_ifconfig(mp_uint_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(wiznet5k_ifconfig_obj, 1, 2, wiznet5k_ifconfig);
-STATIC const mp_map_elem_t wiznet5k_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_regs), (mp_obj_t)&wiznet5k_regs_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ifconfig), (mp_obj_t)&wiznet5k_ifconfig_obj },
+STATIC const mp_rom_map_elem_t wiznet5k_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_regs), MP_ROM_PTR(&wiznet5k_regs_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ifconfig), MP_ROM_PTR(&wiznet5k_ifconfig_obj) },
};
STATIC MP_DEFINE_CONST_DICT(wiznet5k_locals_dict, wiznet5k_locals_dict_table);
@@ -445,7 +445,7 @@ const mod_network_nic_type_t mod_network_nic_type_wiznet5k = {
{ &mp_type_type },
.name = MP_QSTR_WIZNET5K,
.make_new = wiznet5k_make_new,
- .locals_dict = (mp_obj_t)&wiznet5k_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&wiznet5k_locals_dict,
},
.gethostbyname = wiznet5k_gethostbyname,
.socket = wiznet5k_socket_socket,
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 296bcbae0..b8da948ab 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -108,103 +108,103 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
MP_DECLARE_CONST_FUN_OBJ_KW(pyb_main_obj); // defined in main.c
-STATIC const mp_map_elem_t pyb_module_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
+STATIC const mp_rom_map_elem_t pyb_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_pyb) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_fault_debug), (mp_obj_t)&pyb_fault_debug_obj },
+ { MP_ROM_QSTR(MP_QSTR_fault_debug), MP_ROM_PTR(&pyb_fault_debug_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_hard_reset), (mp_obj_t)&machine_reset_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&machine_unique_id_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&machine_freq_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_repl_info), (mp_obj_t)&pyb_set_repl_info_obj },
+ { MP_ROM_QSTR(MP_QSTR_bootloader), MP_ROM_PTR(&machine_bootloader_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hard_reset), MP_ROM_PTR(&machine_reset_obj) },
+ { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&machine_info_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unique_id), MP_ROM_PTR(&machine_unique_id_obj) },
+ { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&machine_freq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_repl_info), MP_ROM_PTR(&pyb_set_repl_info_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_wfi), (mp_obj_t)&pyb_wfi_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_disable_irq), (mp_obj_t)&pyb_disable_irq_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_enable_irq), (mp_obj_t)&pyb_enable_irq_obj },
+ { MP_ROM_QSTR(MP_QSTR_wfi), MP_ROM_PTR(&pyb_wfi_obj) },
+ { MP_ROM_QSTR(MP_QSTR_disable_irq), MP_ROM_PTR(&pyb_disable_irq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_enable_irq), MP_ROM_PTR(&pyb_enable_irq_obj) },
#if IRQ_ENABLE_STATS
- { MP_OBJ_NEW_QSTR(MP_QSTR_irq_stats), (mp_obj_t)&pyb_irq_stats_obj },
+ { MP_ROM_QSTR(MP_QSTR_irq_stats), MP_ROM_PTR(&pyb_irq_stats_obj) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_stop), (mp_obj_t)&machine_sleep_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&machine_deepsleep_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_repl_uart), (mp_obj_t)&mod_os_dupterm_obj },
+ { MP_ROM_QSTR(MP_QSTR_stop), MP_ROM_PTR(&machine_sleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_standby), MP_ROM_PTR(&machine_deepsleep_obj) },
+ { MP_ROM_QSTR(MP_QSTR_main), MP_ROM_PTR(&pyb_main_obj) },
+ { MP_ROM_QSTR(MP_QSTR_repl_uart), MP_ROM_PTR(&mod_os_dupterm_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_hid_mouse), (mp_obj_t)&pyb_usb_hid_mouse_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_hid_keyboard), (mp_obj_t)&pyb_usb_hid_keyboard_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_USB_VCP), (mp_obj_t)&pyb_usb_vcp_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_USB_HID), (mp_obj_t)&pyb_usb_hid_type },
+ { MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hid_mouse), MP_ROM_PTR(&pyb_usb_hid_mouse_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hid_keyboard), MP_ROM_PTR(&pyb_usb_hid_keyboard_obj) },
+ { MP_ROM_QSTR(MP_QSTR_USB_VCP), MP_ROM_PTR(&pyb_usb_vcp_type) },
+ { MP_ROM_QSTR(MP_QSTR_USB_HID), MP_ROM_PTR(&pyb_usb_hid_type) },
// these 2 are deprecated; use USB_VCP.isconnected and USB_HID.send instead
- { MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
+ { MP_ROM_QSTR(MP_QSTR_have_cdc), MP_ROM_PTR(&pyb_have_cdc_obj) },
+ { MP_ROM_QSTR(MP_QSTR_hid), MP_ROM_PTR(&pyb_hid_send_report_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&mp_utime_ticks_ms_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&mp_utime_ticks_us_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&mp_utime_sleep_ms_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&mp_utime_sleep_us_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&mp_vfs_mount_obj },
+ { MP_ROM_QSTR(MP_QSTR_millis), MP_ROM_PTR(&mp_utime_ticks_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_elapsed_millis), MP_ROM_PTR(&pyb_elapsed_millis_obj) },
+ { MP_ROM_QSTR(MP_QSTR_micros), MP_ROM_PTR(&mp_utime_ticks_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_elapsed_micros), MP_ROM_PTR(&pyb_elapsed_micros_obj) },
+ { MP_ROM_QSTR(MP_QSTR_delay), MP_ROM_PTR(&mp_utime_sleep_ms_obj) },
+ { MP_ROM_QSTR(MP_QSTR_udelay), MP_ROM_PTR(&mp_utime_sleep_us_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Timer), (mp_obj_t)&pyb_timer_type },
+ { MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
#if MICROPY_HW_ENABLE_RNG
- { MP_OBJ_NEW_QSTR(MP_QSTR_rng), (mp_obj_t)&pyb_rng_get_obj },
+ { MP_ROM_QSTR(MP_QSTR_rng), MP_ROM_PTR(&pyb_rng_get_obj) },
#endif
#if MICROPY_HW_ENABLE_RTC
- { MP_OBJ_NEW_QSTR(MP_QSTR_RTC), (mp_obj_t)&pyb_rtc_type },
+ { MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_Pin), (mp_obj_t)&pin_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ExtInt), (mp_obj_t)&extint_type },
+ { MP_ROM_QSTR(MP_QSTR_Pin), MP_ROM_PTR(&pin_type) },
+ { MP_ROM_QSTR(MP_QSTR_ExtInt), MP_ROM_PTR(&extint_type) },
#if MICROPY_HW_ENABLE_SERVO
- { MP_OBJ_NEW_QSTR(MP_QSTR_pwm), (mp_obj_t)&pyb_pwm_set_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_servo), (mp_obj_t)&pyb_servo_set_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_Servo), (mp_obj_t)&pyb_servo_type },
+ { MP_ROM_QSTR(MP_QSTR_pwm), MP_ROM_PTR(&pyb_pwm_set_obj) },
+ { MP_ROM_QSTR(MP_QSTR_servo), MP_ROM_PTR(&pyb_servo_set_obj) },
+ { MP_ROM_QSTR(MP_QSTR_Servo), MP_ROM_PTR(&pyb_servo_type) },
#endif
#if MICROPY_HW_HAS_SWITCH
- { MP_OBJ_NEW_QSTR(MP_QSTR_Switch), (mp_obj_t)&pyb_switch_type },
+ { MP_ROM_QSTR(MP_QSTR_Switch), MP_ROM_PTR(&pyb_switch_type) },
#endif
#if MICROPY_HW_HAS_FLASH
- { MP_OBJ_NEW_QSTR(MP_QSTR_Flash), (mp_obj_t)&pyb_flash_type },
+ { MP_ROM_QSTR(MP_QSTR_Flash), MP_ROM_PTR(&pyb_flash_type) },
#endif
#if MICROPY_HW_HAS_SDCARD
- { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj }, // now obsolete
- { MP_OBJ_NEW_QSTR(MP_QSTR_SDCard), (mp_obj_t)&pyb_sdcard_type },
+ { MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sdcard_obj) }, // now obsolete
+ { MP_ROM_QSTR(MP_QSTR_SDCard), MP_ROM_PTR(&pyb_sdcard_type) },
#endif
#if defined(MICROPY_HW_LED1)
- { MP_OBJ_NEW_QSTR(MP_QSTR_LED), (mp_obj_t)&pyb_led_type },
+ { MP_ROM_QSTR(MP_QSTR_LED), MP_ROM_PTR(&pyb_led_type) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_I2C), (mp_obj_t)&pyb_i2c_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SPI), (mp_obj_t)&pyb_spi_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_UART), (mp_obj_t)&pyb_uart_type },
+ { MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&pyb_i2c_type) },
+ { MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&pyb_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
#if MICROPY_HW_ENABLE_CAN
- { MP_OBJ_NEW_QSTR(MP_QSTR_CAN), (mp_obj_t)&pyb_can_type },
+ { MP_ROM_QSTR(MP_QSTR_CAN), MP_ROM_PTR(&pyb_can_type) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_ADC), (mp_obj_t)&pyb_adc_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ADCAll), (mp_obj_t)&pyb_adc_all_type },
+ { MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
+ { MP_ROM_QSTR(MP_QSTR_ADCAll), MP_ROM_PTR(&pyb_adc_all_type) },
#if MICROPY_HW_ENABLE_DAC
- { MP_OBJ_NEW_QSTR(MP_QSTR_DAC), (mp_obj_t)&pyb_dac_type },
+ { MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&pyb_dac_type) },
#endif
#if MICROPY_HW_HAS_MMA7660
- { MP_OBJ_NEW_QSTR(MP_QSTR_Accel), (mp_obj_t)&pyb_accel_type },
+ { MP_ROM_QSTR(MP_QSTR_Accel), MP_ROM_PTR(&pyb_accel_type) },
#endif
#if MICROPY_HW_HAS_LCD
- { MP_OBJ_NEW_QSTR(MP_QSTR_LCD), (mp_obj_t)&pyb_lcd_type },
+ { MP_ROM_QSTR(MP_QSTR_LCD), MP_ROM_PTR(&pyb_lcd_type) },
#endif
};
diff --git a/stmhal/modstm.c b/stmhal/modstm.c
index 76c8eb155..18882fa47 100644
--- a/stmhal/modstm.c
+++ b/stmhal/modstm.c
@@ -37,12 +37,12 @@
#include "py/objint.h"
#include "genhdr/modstm_mpz.h"
-STATIC const mp_map_elem_t stm_module_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_stm) },
+STATIC const mp_rom_map_elem_t stm_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_stm) },
- { MP_ROM_QSTR(MP_QSTR_mem8), (mp_obj_t)&machine_mem8_obj },
- { MP_ROM_QSTR(MP_QSTR_mem16), (mp_obj_t)&machine_mem16_obj },
- { MP_ROM_QSTR(MP_QSTR_mem32), (mp_obj_t)&machine_mem32_obj },
+ { MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
#include "genhdr/modstm_const.h"
};
diff --git a/stmhal/moduos.c b/stmhal/moduos.c
index 745c0d5d7..2d648cb91 100644
--- a/stmhal/moduos.c
+++ b/stmhal/moduos.c
@@ -128,36 +128,36 @@ STATIC mp_obj_t os_dupterm(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_os_dupterm_obj, 0, 1, os_dupterm);
-STATIC const mp_map_elem_t os_module_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_uos) },
+STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uos) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_uname), (mp_obj_t)&os_uname_obj },
+ { MP_ROM_QSTR(MP_QSTR_uname), MP_ROM_PTR(&os_uname_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&mp_vfs_chdir_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&mp_vfs_getcwd_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&mp_vfs_listdir_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&mp_vfs_mkdir_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_remove), (mp_obj_t)&mp_vfs_remove_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_rename),(mp_obj_t)&mp_vfs_rename_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_rmdir), (mp_obj_t)&mp_vfs_rmdir_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_stat), (mp_obj_t)&mp_vfs_stat_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_statvfs), (mp_obj_t)&mp_vfs_statvfs_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_unlink), (mp_obj_t)&mp_vfs_remove_obj }, // unlink aliases to remove
+ { MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
+ { MP_ROM_QSTR(MP_QSTR_rename),MP_ROM_PTR(&mp_vfs_rename_obj)},
+ { MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_stat), MP_ROM_PTR(&mp_vfs_stat_obj) },
+ { MP_ROM_QSTR(MP_QSTR_statvfs), MP_ROM_PTR(&mp_vfs_statvfs_obj) },
+ { MP_ROM_QSTR(MP_QSTR_unlink), MP_ROM_PTR(&mp_vfs_remove_obj) }, // unlink aliases to remove
- { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj },
+ { MP_ROM_QSTR(MP_QSTR_sync), MP_ROM_PTR(&mod_os_sync_obj) },
/// \constant sep - separation character used in paths
- { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
+ { MP_ROM_QSTR(MP_QSTR_sep), MP_ROM_QSTR(MP_QSTR__slash_) },
#if MICROPY_HW_ENABLE_RNG
- { MP_OBJ_NEW_QSTR(MP_QSTR_urandom), (mp_obj_t)&os_urandom_obj },
+ { MP_ROM_QSTR(MP_QSTR_urandom), MP_ROM_PTR(&os_urandom_obj) },
#endif
// these are MicroPython extensions
- { MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&mod_os_dupterm_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&mp_vfs_mount_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&mp_vfs_umount_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_VfsFat), (mp_obj_t)&mp_fat_vfs_type },
+ { MP_ROM_QSTR(MP_QSTR_dupterm), MP_ROM_PTR(&mod_os_dupterm_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mount), MP_ROM_PTR(&mp_vfs_mount_obj) },
+ { MP_ROM_QSTR(MP_QSTR_umount), MP_ROM_PTR(&mp_vfs_umount_obj) },
+ { MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
diff --git a/stmhal/modusocket.c b/stmhal/modusocket.c
index fd60c5ad4..081a322ae 100644
--- a/stmhal/modusocket.c
+++ b/stmhal/modusocket.c
@@ -347,20 +347,20 @@ STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t blocking) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking);
-STATIC const mp_map_elem_t socket_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&socket_close_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&socket_close_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_bind), (mp_obj_t)&socket_bind_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_listen), (mp_obj_t)&socket_listen_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_connect), (mp_obj_t)&socket_connect_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sendto), (mp_obj_t)&socket_sendto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recvfrom), (mp_obj_t)&socket_recvfrom_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_settimeout), (mp_obj_t)&socket_settimeout_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_setblocking), (mp_obj_t)&socket_setblocking_obj },
+STATIC const mp_rom_map_elem_t socket_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&socket_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) },
+ { MP_ROM_QSTR(MP_QSTR_bind), MP_ROM_PTR(&socket_bind_obj) },
+ { MP_ROM_QSTR(MP_QSTR_listen), MP_ROM_PTR(&socket_listen_obj) },
+ { MP_ROM_QSTR(MP_QSTR_accept), MP_ROM_PTR(&socket_accept_obj) },
+ { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&socket_connect_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&socket_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&socket_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendto), MP_ROM_PTR(&socket_sendto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recvfrom), MP_ROM_PTR(&socket_recvfrom_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setsockopt), MP_ROM_PTR(&socket_setsockopt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_settimeout), MP_ROM_PTR(&socket_settimeout_obj) },
+ { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) },
};
STATIC MP_DEFINE_CONST_DICT(socket_locals_dict, socket_locals_dict_table);
@@ -380,7 +380,7 @@ STATIC const mp_obj_type_t socket_type = {
.name = MP_QSTR_socket,
.make_new = socket_make_new,
.protocol = &socket_stream_p,
- .locals_dict = (mp_obj_t)&socket_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&socket_locals_dict,
};
/******************************************************************************/
@@ -417,28 +417,28 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_usocket_getaddrinfo_obj, mod_usocket_getaddrinfo);
-STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
+STATIC const mp_rom_map_elem_t mp_module_usocket_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_usocket) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj },
+ { MP_ROM_QSTR(MP_QSTR_socket), MP_ROM_PTR(&socket_type) },
+ { MP_ROM_QSTR(MP_QSTR_getaddrinfo), MP_ROM_PTR(&mod_usocket_getaddrinfo_obj) },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_AF_INET6) },
+ { MP_ROM_QSTR(MP_QSTR_AF_INET), MP_ROM_INT(MOD_NETWORK_AF_INET) },
+ { MP_ROM_QSTR(MP_QSTR_AF_INET6), MP_ROM_INT(MOD_NETWORK_AF_INET6) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_STREAM) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_DGRAM) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_SOCK_RAW) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_STREAM), MP_ROM_INT(MOD_NETWORK_SOCK_STREAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_DGRAM), MP_ROM_INT(MOD_NETWORK_SOCK_DGRAM) },
+ { MP_ROM_QSTR(MP_QSTR_SOCK_RAW), MP_ROM_INT(MOD_NETWORK_SOCK_RAW) },
/*
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_ICMP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_ICMP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV4), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV4) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_TCP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_UDP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_IPV6), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_IPV6) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_RAW), MP_OBJ_NEW_SMALL_INT(MOD_NETWORK_IPPROTO_RAW) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IP), MP_ROM_INT(MOD_NETWORK_IPPROTO_IP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_ICMP), MP_ROM_INT(MOD_NETWORK_IPPROTO_ICMP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV4), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV4) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_TCP), MP_ROM_INT(MOD_NETWORK_IPPROTO_TCP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_UDP), MP_ROM_INT(MOD_NETWORK_IPPROTO_UDP) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_IPV6), MP_ROM_INT(MOD_NETWORK_IPPROTO_IPV6) },
+ { MP_ROM_QSTR(MP_QSTR_IPPROTO_RAW), MP_ROM_INT(MOD_NETWORK_IPPROTO_RAW) },
*/
};
diff --git a/stmhal/pin.c b/stmhal/pin.c
index 845126e28..b8702dae2 100644
--- a/stmhal/pin.c
+++ b/stmhal/pin.c
@@ -496,47 +496,47 @@ STATIC mp_obj_t pin_af(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_obj, pin_af);
-STATIC const mp_map_elem_t pin_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pin_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pin_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_value), (mp_obj_t)&pin_value_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_low), (mp_obj_t)&pin_low_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_high), (mp_obj_t)&pin_high_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_name_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_names), (mp_obj_t)&pin_names_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_af_list), (mp_obj_t)&pin_af_list_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_port), (mp_obj_t)&pin_port_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pin), (mp_obj_t)&pin_pin_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_gpio), (mp_obj_t)&pin_gpio_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_mode), (mp_obj_t)&pin_mode_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pull), (mp_obj_t)&pin_pull_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_af), (mp_obj_t)&pin_af_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pin_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&pin_value_obj) },
+ { MP_ROM_QSTR(MP_QSTR_low), MP_ROM_PTR(&pin_low_obj) },
+ { MP_ROM_QSTR(MP_QSTR_high), MP_ROM_PTR(&pin_high_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_names), MP_ROM_PTR(&pin_names_obj) },
+ { MP_ROM_QSTR(MP_QSTR_af_list), MP_ROM_PTR(&pin_af_list_obj) },
+ { MP_ROM_QSTR(MP_QSTR_port), MP_ROM_PTR(&pin_port_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pin), MP_ROM_PTR(&pin_pin_obj) },
+ { MP_ROM_QSTR(MP_QSTR_gpio), MP_ROM_PTR(&pin_gpio_obj) },
+ { MP_ROM_QSTR(MP_QSTR_mode), MP_ROM_PTR(&pin_mode_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pull), MP_ROM_PTR(&pin_pull_obj) },
+ { MP_ROM_QSTR(MP_QSTR_af), MP_ROM_PTR(&pin_af_obj) },
// class methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_mapper), (mp_obj_t)&pin_mapper_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_dict), (mp_obj_t)&pin_map_dict_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_debug), (mp_obj_t)&pin_debug_obj },
+ { MP_ROM_QSTR(MP_QSTR_mapper), MP_ROM_PTR(&pin_mapper_obj) },
+ { MP_ROM_QSTR(MP_QSTR_dict), MP_ROM_PTR(&pin_map_dict_obj) },
+ { MP_ROM_QSTR(MP_QSTR_debug), MP_ROM_PTR(&pin_debug_obj) },
// class attributes
- { MP_OBJ_NEW_QSTR(MP_QSTR_board), (mp_obj_t)&pin_board_pins_obj_type },
- { MP_OBJ_NEW_QSTR(MP_QSTR_cpu), (mp_obj_t)&pin_cpu_pins_obj_type },
+ { MP_ROM_QSTR(MP_QSTR_board), MP_ROM_PTR(&pin_board_pins_obj_type) },
+ { MP_ROM_QSTR(MP_QSTR_cpu), MP_ROM_PTR(&pin_cpu_pins_obj_type) },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_IN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_INPUT) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OUT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ALT), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ANALOG), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_ANALOG) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_UP), MP_OBJ_NEW_SMALL_INT(GPIO_PULLUP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_DOWN), MP_OBJ_NEW_SMALL_INT(GPIO_PULLDOWN) },
+ { MP_ROM_QSTR(MP_QSTR_IN), MP_ROM_INT(GPIO_MODE_INPUT) },
+ { MP_ROM_QSTR(MP_QSTR_OUT), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) },
+ { MP_ROM_QSTR(MP_QSTR_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) },
+ { MP_ROM_QSTR(MP_QSTR_ALT), MP_ROM_INT(GPIO_MODE_AF_PP) },
+ { MP_ROM_QSTR(MP_QSTR_ALT_OPEN_DRAIN), MP_ROM_INT(GPIO_MODE_AF_OD) },
+ { MP_ROM_QSTR(MP_QSTR_ANALOG), MP_ROM_INT(GPIO_MODE_ANALOG) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_UP), MP_ROM_INT(GPIO_PULLUP) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_DOWN), MP_ROM_INT(GPIO_PULLDOWN) },
// legacy class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_PP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OUT_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_OUTPUT_OD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_AF_PP), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_PP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_AF_OD), MP_OBJ_NEW_SMALL_INT(GPIO_MODE_AF_OD) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PULL_NONE), MP_OBJ_NEW_SMALL_INT(GPIO_NOPULL) },
+ { MP_ROM_QSTR(MP_QSTR_OUT_PP), MP_ROM_INT(GPIO_MODE_OUTPUT_PP) },
+ { MP_ROM_QSTR(MP_QSTR_OUT_OD), MP_ROM_INT(GPIO_MODE_OUTPUT_OD) },
+ { MP_ROM_QSTR(MP_QSTR_AF_PP), MP_ROM_INT(GPIO_MODE_AF_PP) },
+ { MP_ROM_QSTR(MP_QSTR_AF_OD), MP_ROM_INT(GPIO_MODE_AF_OD) },
+ { MP_ROM_QSTR(MP_QSTR_PULL_NONE), MP_ROM_INT(GPIO_NOPULL) },
#include "genhdr/pins_af_const.h"
};
@@ -570,7 +570,7 @@ const mp_obj_type_t pin_type = {
.make_new = mp_pin_make_new,
.call = pin_call,
.protocol = &pin_pin_p,
- .locals_dict = (mp_obj_t)&pin_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pin_locals_dict,
};
/// \moduleref pyb
@@ -633,10 +633,10 @@ STATIC mp_obj_t pin_af_reg(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_af_reg_obj, pin_af_reg);
-STATIC const mp_map_elem_t pin_af_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_index), (mp_obj_t)&pin_af_index_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_name), (mp_obj_t)&pin_af_name_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_reg), (mp_obj_t)&pin_af_reg_obj },
+STATIC const mp_rom_map_elem_t pin_af_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_index), MP_ROM_PTR(&pin_af_index_obj) },
+ { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&pin_af_name_obj) },
+ { MP_ROM_QSTR(MP_QSTR_reg), MP_ROM_PTR(&pin_af_reg_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pin_af_locals_dict, pin_af_locals_dict_table);
@@ -644,5 +644,5 @@ const mp_obj_type_t pin_af_type = {
{ &mp_type_type },
.name = MP_QSTR_PinAF,
.print = pin_af_obj_print,
- .locals_dict = (mp_obj_t)&pin_af_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pin_af_locals_dict,
};
diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c
index 9b1bfff90..bd15c583d 100644
--- a/stmhal/pybstdio.c
+++ b/stmhal/pybstdio.c
@@ -92,19 +92,19 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stdio_obj___exit___obj, 4, 4, stdio_o
// TODO gc hook to close the file if not already closed
-STATIC const mp_map_elem_t stdio_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t stdio_locals_dict_table[] = {
#if MICROPY_PY_SYS_STDIO_BUFFER
- { MP_OBJ_NEW_QSTR(MP_QSTR_buffer), (mp_obj_t)&stdio_buffer_obj },
+ { MP_ROM_QSTR(MP_QSTR_buffer), MP_ROM_PTR(&stdio_buffer_obj) },
#endif
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_readlines), (mp_obj_t)&mp_stream_unbuffered_readlines_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&stdio_obj___exit___obj },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
+ { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)},
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&stdio_obj___exit___obj) },
};
STATIC MP_DEFINE_CONST_DICT(stdio_locals_dict, stdio_locals_dict_table);
@@ -123,7 +123,7 @@ STATIC const mp_obj_type_t stdio_obj_type = {
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &stdio_obj_stream_p,
- .locals_dict = (mp_obj_t)&stdio_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&stdio_locals_dict,
};
const pyb_stdio_obj_t mp_sys_stdin_obj = {{&stdio_obj_type}, .fd = STDIO_FD_IN};
diff --git a/stmhal/rtc.c b/stmhal/rtc.c
index 4fa26d25b..bc9c889c2 100644
--- a/stmhal/rtc.c
+++ b/stmhal/rtc.c
@@ -718,12 +718,12 @@ mp_obj_t pyb_rtc_calibration(mp_uint_t n_args, const mp_obj_t *args) {
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_calibration_obj, 1, 2, pyb_rtc_calibration);
-STATIC const mp_map_elem_t pyb_rtc_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_rtc_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&pyb_rtc_info_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_datetime), (mp_obj_t)&pyb_rtc_datetime_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_wakeup), (mp_obj_t)&pyb_rtc_wakeup_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_calibration), (mp_obj_t)&pyb_rtc_calibration_obj },
+STATIC const mp_rom_map_elem_t pyb_rtc_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_rtc_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&pyb_rtc_info_obj) },
+ { MP_ROM_QSTR(MP_QSTR_datetime), MP_ROM_PTR(&pyb_rtc_datetime_obj) },
+ { MP_ROM_QSTR(MP_QSTR_wakeup), MP_ROM_PTR(&pyb_rtc_wakeup_obj) },
+ { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&pyb_rtc_calibration_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_rtc_locals_dict, pyb_rtc_locals_dict_table);
@@ -731,5 +731,5 @@ const mp_obj_type_t pyb_rtc_type = {
{ &mp_type_type },
.name = MP_QSTR_RTC,
.make_new = pyb_rtc_make_new,
- .locals_dict = (mp_obj_t)&pyb_rtc_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_rtc_locals_dict,
};
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index 5abffa730..5a4b3b0e4 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -469,16 +469,16 @@ STATIC mp_obj_t pyb_sdcard_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_sdcard_ioctl_obj, pyb_sdcard_ioctl);
-STATIC const mp_map_elem_t pyb_sdcard_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_present), (mp_obj_t)&sd_present_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_power), (mp_obj_t)&sd_power_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&sd_info_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&sd_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&sd_write_obj },
+STATIC const mp_rom_map_elem_t pyb_sdcard_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_present), MP_ROM_PTR(&sd_present_obj) },
+ { MP_ROM_QSTR(MP_QSTR_power), MP_ROM_PTR(&sd_power_obj) },
+ { MP_ROM_QSTR(MP_QSTR_info), MP_ROM_PTR(&sd_info_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&sd_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&sd_write_obj) },
// block device protocol
- { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&pyb_sdcard_readblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&pyb_sdcard_writeblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&pyb_sdcard_ioctl_obj },
+ { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_sdcard_readblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_sdcard_writeblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_sdcard_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_sdcard_locals_dict, pyb_sdcard_locals_dict_table);
@@ -487,7 +487,7 @@ const mp_obj_type_t pyb_sdcard_type = {
{ &mp_type_type },
.name = MP_QSTR_SDCard,
.make_new = pyb_sdcard_make_new,
- .locals_dict = (mp_obj_t)&pyb_sdcard_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_sdcard_locals_dict,
};
void sdcard_init_vfs(fs_user_mount_t *vfs, int part) {
diff --git a/stmhal/servo.c b/stmhal/servo.c
index dff549582..4c62044dd 100644
--- a/stmhal/servo.c
+++ b/stmhal/servo.c
@@ -317,11 +317,11 @@ STATIC mp_obj_t pyb_servo_speed(mp_uint_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_servo_speed_obj, 1, 3, pyb_servo_speed);
-STATIC const mp_map_elem_t pyb_servo_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_pulse_width), (mp_obj_t)&pyb_servo_pulse_width_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_calibration), (mp_obj_t)&pyb_servo_calibration_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_angle), (mp_obj_t)&pyb_servo_angle_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_speed), (mp_obj_t)&pyb_servo_speed_obj },
+STATIC const mp_rom_map_elem_t pyb_servo_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&pyb_servo_pulse_width_obj) },
+ { MP_ROM_QSTR(MP_QSTR_calibration), MP_ROM_PTR(&pyb_servo_calibration_obj) },
+ { MP_ROM_QSTR(MP_QSTR_angle), MP_ROM_PTR(&pyb_servo_angle_obj) },
+ { MP_ROM_QSTR(MP_QSTR_speed), MP_ROM_PTR(&pyb_servo_speed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_servo_locals_dict, pyb_servo_locals_dict_table);
@@ -331,5 +331,5 @@ const mp_obj_type_t pyb_servo_type = {
.name = MP_QSTR_Servo,
.print = pyb_servo_print,
.make_new = pyb_servo_make_new,
- .locals_dict = (mp_obj_t)&pyb_servo_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_servo_locals_dict,
};
diff --git a/stmhal/spi.c b/stmhal/spi.c
index d7c9b04cc..eb7edbea0 100644
--- a/stmhal/spi.c
+++ b/stmhal/spi.c
@@ -783,37 +783,37 @@ STATIC mp_obj_t pyb_spi_send_recv(mp_uint_t n_args, const mp_obj_t *pos_args, mp
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_send_recv_obj, 1, pyb_spi_send_recv);
-STATIC const mp_map_elem_t pyb_spi_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_spi_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_spi_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_spi_deinit_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_spi_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_spi_deinit_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_machine_spi_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_machine_spi_readinto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_machine_spi_write_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_write_readinto), (mp_obj_t)&mp_machine_spi_write_readinto_obj },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_machine_spi_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_machine_spi_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_machine_spi_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_write_readinto), MP_ROM_PTR(&mp_machine_spi_write_readinto_obj) },
// legacy methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_spi_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_spi_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send_recv), (mp_obj_t)&pyb_spi_send_recv_obj },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_spi_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_spi_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send_recv), MP_ROM_PTR(&pyb_spi_send_recv_obj) },
// class constants
/// \constant MASTER - for initialising the bus to master mode
/// \constant SLAVE - for initialising the bus to slave mode
/// \constant MSB - set the first bit to MSB
/// \constant LSB - set the first bit to LSB
- { MP_OBJ_NEW_QSTR(MP_QSTR_MASTER), MP_OBJ_NEW_SMALL_INT(SPI_MODE_MASTER) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_SLAVE), MP_OBJ_NEW_SMALL_INT(SPI_MODE_SLAVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_MSB), MP_OBJ_NEW_SMALL_INT(SPI_FIRSTBIT_MSB) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LSB), MP_OBJ_NEW_SMALL_INT(SPI_FIRSTBIT_LSB) },
+ { MP_ROM_QSTR(MP_QSTR_MASTER), MP_ROM_INT(SPI_MODE_MASTER) },
+ { MP_ROM_QSTR(MP_QSTR_SLAVE), MP_ROM_INT(SPI_MODE_SLAVE) },
+ { MP_ROM_QSTR(MP_QSTR_MSB), MP_ROM_INT(SPI_FIRSTBIT_MSB) },
+ { MP_ROM_QSTR(MP_QSTR_LSB), MP_ROM_INT(SPI_FIRSTBIT_LSB) },
/* TODO
- { MP_OBJ_NEW_QSTR(MP_QSTR_DIRECTION_2LINES ((uint32_t)0x00000000)
- { MP_OBJ_NEW_QSTR(MP_QSTR_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY
- { MP_OBJ_NEW_QSTR(MP_QSTR_DIRECTION_1LINE SPI_CR1_BIDIMODE
- { MP_OBJ_NEW_QSTR(MP_QSTR_NSS_SOFT SPI_CR1_SSM
- { MP_OBJ_NEW_QSTR(MP_QSTR_NSS_HARD_INPUT ((uint32_t)0x00000000)
- { MP_OBJ_NEW_QSTR(MP_QSTR_NSS_HARD_OUTPUT ((uint32_t)0x00040000)
+ { MP_ROM_QSTR(MP_QSTR_DIRECTION_2LINES ((uint32_t)0x00000000)
+ { MP_ROM_QSTR(MP_QSTR_DIRECTION_2LINES_RXONLY SPI_CR1_RXONLY
+ { MP_ROM_QSTR(MP_QSTR_DIRECTION_1LINE SPI_CR1_BIDIMODE
+ { MP_ROM_QSTR(MP_QSTR_NSS_SOFT SPI_CR1_SSM
+ { MP_ROM_QSTR(MP_QSTR_NSS_HARD_INPUT ((uint32_t)0x00000000)
+ { MP_ROM_QSTR(MP_QSTR_NSS_HARD_OUTPUT ((uint32_t)0x00040000)
*/
};
@@ -833,7 +833,7 @@ const mp_obj_type_t pyb_spi_type = {
.print = pyb_spi_print,
.make_new = pyb_spi_make_new,
.protocol = &pyb_spi_p,
- .locals_dict = (mp_obj_t)&pyb_spi_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_spi_locals_dict,
};
/******************************************************************************/
diff --git a/stmhal/storage.c b/stmhal/storage.c
index ed8b4e87a..d0f278285 100644
--- a/stmhal/storage.c
+++ b/stmhal/storage.c
@@ -488,10 +488,10 @@ STATIC mp_obj_t pyb_flash_ioctl(mp_obj_t self, mp_obj_t cmd_in, mp_obj_t arg_in)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_flash_ioctl_obj, pyb_flash_ioctl);
-STATIC const mp_map_elem_t pyb_flash_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_readblocks), (mp_obj_t)&pyb_flash_readblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_writeblocks), (mp_obj_t)&pyb_flash_writeblocks_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ioctl), (mp_obj_t)&pyb_flash_ioctl_obj },
+STATIC const mp_rom_map_elem_t pyb_flash_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_readblocks), MP_ROM_PTR(&pyb_flash_readblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_writeblocks), MP_ROM_PTR(&pyb_flash_writeblocks_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ioctl), MP_ROM_PTR(&pyb_flash_ioctl_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_flash_locals_dict, pyb_flash_locals_dict_table);
@@ -500,7 +500,7 @@ const mp_obj_type_t pyb_flash_type = {
{ &mp_type_type },
.name = MP_QSTR_Flash,
.make_new = pyb_flash_make_new,
- .locals_dict = (mp_obj_t)&pyb_flash_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_flash_locals_dict,
};
void pyb_flash_init_vfs(fs_user_mount_t *vfs) {
diff --git a/stmhal/timer.c b/stmhal/timer.c
index 5a574867b..fd0695bdd 100644
--- a/stmhal/timer.c
+++ b/stmhal/timer.c
@@ -1180,37 +1180,37 @@ STATIC mp_obj_t pyb_timer_callback(mp_obj_t self_in, mp_obj_t callback) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_callback_obj, pyb_timer_callback);
-STATIC const mp_map_elem_t pyb_timer_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_timer_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_timer_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_timer_deinit_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_channel), (mp_obj_t)&pyb_timer_channel_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_counter), (mp_obj_t)&pyb_timer_counter_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_source_freq), (mp_obj_t)&pyb_timer_source_freq_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&pyb_timer_freq_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_prescaler), (mp_obj_t)&pyb_timer_prescaler_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_period), (mp_obj_t)&pyb_timer_period_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_timer_callback_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_UP), MP_OBJ_NEW_SMALL_INT(TIM_COUNTERMODE_UP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_DOWN), MP_OBJ_NEW_SMALL_INT(TIM_COUNTERMODE_DOWN) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_CENTER), MP_OBJ_NEW_SMALL_INT(TIM_COUNTERMODE_CENTERALIGNED1) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PWM), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_PWM_NORMAL) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_PWM_INVERTED), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_PWM_INVERTED) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_TIMING), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_TIMING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_ACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_ACTIVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_INACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_INACTIVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_TOGGLE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_TOGGLE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_FORCED_ACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_FORCED_ACTIVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_OC_FORCED_INACTIVE), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_OC_FORCED_INACTIVE) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IC), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_IC) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ENC_A), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_A) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ENC_B), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_B) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_ENC_AB), MP_OBJ_NEW_SMALL_INT(CHANNEL_MODE_ENC_AB) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_HIGH), MP_OBJ_NEW_SMALL_INT(TIM_OCPOLARITY_HIGH) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_LOW), MP_OBJ_NEW_SMALL_INT(TIM_OCPOLARITY_LOW) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_RISING), MP_OBJ_NEW_SMALL_INT(TIM_ICPOLARITY_RISING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_FALLING), MP_OBJ_NEW_SMALL_INT(TIM_ICPOLARITY_FALLING) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_BOTH), MP_OBJ_NEW_SMALL_INT(TIM_ICPOLARITY_BOTHEDGE) },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_timer_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_timer_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_channel), MP_ROM_PTR(&pyb_timer_channel_obj) },
+ { MP_ROM_QSTR(MP_QSTR_counter), MP_ROM_PTR(&pyb_timer_counter_obj) },
+ { MP_ROM_QSTR(MP_QSTR_source_freq), MP_ROM_PTR(&pyb_timer_source_freq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_freq), MP_ROM_PTR(&pyb_timer_freq_obj) },
+ { MP_ROM_QSTR(MP_QSTR_prescaler), MP_ROM_PTR(&pyb_timer_prescaler_obj) },
+ { MP_ROM_QSTR(MP_QSTR_period), MP_ROM_PTR(&pyb_timer_period_obj) },
+ { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_callback_obj) },
+ { MP_ROM_QSTR(MP_QSTR_UP), MP_ROM_INT(TIM_COUNTERMODE_UP) },
+ { MP_ROM_QSTR(MP_QSTR_DOWN), MP_ROM_INT(TIM_COUNTERMODE_DOWN) },
+ { MP_ROM_QSTR(MP_QSTR_CENTER), MP_ROM_INT(TIM_COUNTERMODE_CENTERALIGNED1) },
+ { MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_INT(CHANNEL_MODE_PWM_NORMAL) },
+ { MP_ROM_QSTR(MP_QSTR_PWM_INVERTED), MP_ROM_INT(CHANNEL_MODE_PWM_INVERTED) },
+ { MP_ROM_QSTR(MP_QSTR_OC_TIMING), MP_ROM_INT(CHANNEL_MODE_OC_TIMING) },
+ { MP_ROM_QSTR(MP_QSTR_OC_ACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_ACTIVE) },
+ { MP_ROM_QSTR(MP_QSTR_OC_INACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_INACTIVE) },
+ { MP_ROM_QSTR(MP_QSTR_OC_TOGGLE), MP_ROM_INT(CHANNEL_MODE_OC_TOGGLE) },
+ { MP_ROM_QSTR(MP_QSTR_OC_FORCED_ACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_FORCED_ACTIVE) },
+ { MP_ROM_QSTR(MP_QSTR_OC_FORCED_INACTIVE), MP_ROM_INT(CHANNEL_MODE_OC_FORCED_INACTIVE) },
+ { MP_ROM_QSTR(MP_QSTR_IC), MP_ROM_INT(CHANNEL_MODE_IC) },
+ { MP_ROM_QSTR(MP_QSTR_ENC_A), MP_ROM_INT(CHANNEL_MODE_ENC_A) },
+ { MP_ROM_QSTR(MP_QSTR_ENC_B), MP_ROM_INT(CHANNEL_MODE_ENC_B) },
+ { MP_ROM_QSTR(MP_QSTR_ENC_AB), MP_ROM_INT(CHANNEL_MODE_ENC_AB) },
+ { MP_ROM_QSTR(MP_QSTR_HIGH), MP_ROM_INT(TIM_OCPOLARITY_HIGH) },
+ { MP_ROM_QSTR(MP_QSTR_LOW), MP_ROM_INT(TIM_OCPOLARITY_LOW) },
+ { MP_ROM_QSTR(MP_QSTR_RISING), MP_ROM_INT(TIM_ICPOLARITY_RISING) },
+ { MP_ROM_QSTR(MP_QSTR_FALLING), MP_ROM_INT(TIM_ICPOLARITY_FALLING) },
+ { MP_ROM_QSTR(MP_QSTR_BOTH), MP_ROM_INT(TIM_ICPOLARITY_BOTHEDGE) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_locals_dict, pyb_timer_locals_dict_table);
@@ -1219,7 +1219,7 @@ const mp_obj_type_t pyb_timer_type = {
.name = MP_QSTR_Timer,
.print = pyb_timer_print,
.make_new = pyb_timer_make_new,
- .locals_dict = (mp_obj_t)&pyb_timer_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_timer_locals_dict,
};
/// \moduleref pyb
@@ -1337,13 +1337,13 @@ STATIC mp_obj_t pyb_timer_channel_callback(mp_obj_t self_in, mp_obj_t callback)
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_timer_channel_callback_obj, pyb_timer_channel_callback);
-STATIC const mp_map_elem_t pyb_timer_channel_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_timer_channel_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_timer_channel_callback_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pulse_width), (mp_obj_t)&pyb_timer_channel_capture_compare_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_pulse_width_percent), (mp_obj_t)&pyb_timer_channel_pulse_width_percent_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_capture), (mp_obj_t)&pyb_timer_channel_capture_compare_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_compare), (mp_obj_t)&pyb_timer_channel_capture_compare_obj },
+ { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_timer_channel_callback_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pulse_width), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) },
+ { MP_ROM_QSTR(MP_QSTR_pulse_width_percent), MP_ROM_PTR(&pyb_timer_channel_pulse_width_percent_obj) },
+ { MP_ROM_QSTR(MP_QSTR_capture), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) },
+ { MP_ROM_QSTR(MP_QSTR_compare), MP_ROM_PTR(&pyb_timer_channel_capture_compare_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_timer_channel_locals_dict, pyb_timer_channel_locals_dict_table);
@@ -1351,7 +1351,7 @@ STATIC const mp_obj_type_t pyb_timer_channel_type = {
{ &mp_type_type },
.name = MP_QSTR_TimerChannel,
.print = pyb_timer_channel_print,
- .locals_dict = (mp_obj_t)&pyb_timer_channel_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_timer_channel_locals_dict,
};
STATIC void timer_handle_irq_channel(pyb_timer_obj_t *tim, uint8_t channel, mp_obj_t callback) {
diff --git a/stmhal/uart.c b/stmhal/uart.c
index 4fae3a80c..b24813804 100644
--- a/stmhal/uart.c
+++ b/stmhal/uart.c
@@ -910,29 +910,29 @@ STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_sendbreak_obj, pyb_uart_sendbreak);
-STATIC const mp_map_elem_t pyb_uart_locals_dict_table[] = {
+STATIC const mp_rom_map_elem_t pyb_uart_locals_dict_table[] = {
// instance methods
- { MP_OBJ_NEW_QSTR(MP_QSTR_init), (mp_obj_t)&pyb_uart_init_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_deinit), (mp_obj_t)&pyb_uart_deinit_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_uart_any_obj },
+ { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&pyb_uart_init_obj) },
+ { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&pyb_uart_deinit_obj) },
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_uart_any_obj) },
/// \method read([nbytes])
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
/// \method readline()
- { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
/// \method readinto(buf[, nbytes])
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
/// \method write(buf)
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_writechar), (mp_obj_t)&pyb_uart_writechar_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readchar), (mp_obj_t)&pyb_uart_readchar_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_sendbreak), (mp_obj_t)&pyb_uart_sendbreak_obj },
+ { MP_ROM_QSTR(MP_QSTR_writechar), MP_ROM_PTR(&pyb_uart_writechar_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readchar), MP_ROM_PTR(&pyb_uart_readchar_obj) },
+ { MP_ROM_QSTR(MP_QSTR_sendbreak), MP_ROM_PTR(&pyb_uart_sendbreak_obj) },
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_RTS), MP_OBJ_NEW_SMALL_INT(UART_HWCONTROL_RTS) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_CTS), MP_OBJ_NEW_SMALL_INT(UART_HWCONTROL_CTS) },
+ { MP_ROM_QSTR(MP_QSTR_RTS), MP_ROM_INT(UART_HWCONTROL_RTS) },
+ { MP_ROM_QSTR(MP_QSTR_CTS), MP_ROM_INT(UART_HWCONTROL_CTS) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_uart_locals_dict, pyb_uart_locals_dict_table);
@@ -1040,5 +1040,5 @@ const mp_obj_type_t pyb_uart_type = {
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &uart_stream_p,
- .locals_dict = (mp_obj_t)&pyb_uart_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_uart_locals_dict,
};
diff --git a/stmhal/usb.c b/stmhal/usb.c
index f71c70665..9428cf7db 100644
--- a/stmhal/usb.c
+++ b/stmhal/usb.c
@@ -450,21 +450,21 @@ mp_obj_t pyb_usb_vcp___exit__(mp_uint_t n_args, const mp_obj_t *args) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_usb_vcp___exit___obj, 4, 4, pyb_usb_vcp___exit__);
-STATIC const mp_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_setinterrupt), (mp_obj_t)&pyb_usb_vcp_setinterrupt_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_isconnected), (mp_obj_t)&pyb_usb_vcp_isconnected_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&pyb_usb_vcp_any_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_usb_vcp_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_usb_vcp_recv_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_readline), (mp_obj_t)&mp_stream_unbuffered_readline_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_readlines), (mp_obj_t)&mp_stream_unbuffered_readlines_obj},
- { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&mp_stream_write_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_close), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___del__), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___enter__), (mp_obj_t)&mp_identity_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR___exit__), (mp_obj_t)&pyb_usb_vcp___exit___obj },
+STATIC const mp_rom_map_elem_t pyb_usb_vcp_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_setinterrupt), MP_ROM_PTR(&pyb_usb_vcp_setinterrupt_obj) },
+ { MP_ROM_QSTR(MP_QSTR_isconnected), MP_ROM_PTR(&pyb_usb_vcp_isconnected_obj) },
+ { MP_ROM_QSTR(MP_QSTR_any), MP_ROM_PTR(&pyb_usb_vcp_any_obj) },
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_usb_vcp_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_usb_vcp_recv_obj) },
+ { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&mp_stream_read_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) },
+ { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj)},
+ { MP_ROM_QSTR(MP_QSTR_readlines), MP_ROM_PTR(&mp_stream_unbuffered_readlines_obj)},
+ { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) },
+ { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___enter__), MP_ROM_PTR(&mp_identity_obj) },
+ { MP_ROM_QSTR(MP_QSTR___exit__), MP_ROM_PTR(&pyb_usb_vcp___exit___obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_usb_vcp_locals_dict, pyb_usb_vcp_locals_dict_table);
@@ -521,7 +521,7 @@ const mp_obj_type_t pyb_usb_vcp_type = {
.getiter = mp_identity_getiter,
.iternext = mp_stream_unbuffered_iter,
.protocol = &pyb_usb_vcp_stream_p,
- .locals_dict = (mp_obj_t)&pyb_usb_vcp_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_usb_vcp_locals_dict,
};
/******************************************************************************/
@@ -616,9 +616,9 @@ STATIC mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_hid_send_report_obj, pyb_hid_send_report);
-STATIC const mp_map_elem_t pyb_usb_hid_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&pyb_usb_hid_send_obj },
- { MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&pyb_usb_hid_recv_obj },
+STATIC const mp_rom_map_elem_t pyb_usb_hid_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_send), MP_ROM_PTR(&pyb_usb_hid_send_obj) },
+ { MP_ROM_QSTR(MP_QSTR_recv), MP_ROM_PTR(&pyb_usb_hid_recv_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_usb_hid_locals_dict, pyb_usb_hid_locals_dict_table);
@@ -650,7 +650,7 @@ const mp_obj_type_t pyb_usb_hid_type = {
.name = MP_QSTR_USB_HID,
.make_new = pyb_usb_hid_make_new,
.protocol = &pyb_usb_hid_stream_p,
- .locals_dict = (mp_obj_t)&pyb_usb_hid_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_usb_hid_locals_dict,
};
/******************************************************************************/
diff --git a/stmhal/usrsw.c b/stmhal/usrsw.c
index 5bf4cc767..d4f0c6939 100644
--- a/stmhal/usrsw.c
+++ b/stmhal/usrsw.c
@@ -122,8 +122,8 @@ mp_obj_t pyb_switch_callback(mp_obj_t self_in, mp_obj_t callback) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_switch_callback_obj, pyb_switch_callback);
-STATIC const mp_map_elem_t pyb_switch_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_callback), (mp_obj_t)&pyb_switch_callback_obj },
+STATIC const mp_rom_map_elem_t pyb_switch_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_callback), MP_ROM_PTR(&pyb_switch_callback_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_switch_locals_dict, pyb_switch_locals_dict_table);
@@ -134,7 +134,7 @@ const mp_obj_type_t pyb_switch_type = {
.print = pyb_switch_print,
.make_new = pyb_switch_make_new,
.call = pyb_switch_call,
- .locals_dict = (mp_obj_t)&pyb_switch_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_switch_locals_dict,
};
#endif // MICROPY_HW_HAS_SWITCH
diff --git a/stmhal/wdt.c b/stmhal/wdt.c
index d9a089d01..af2481e92 100644
--- a/stmhal/wdt.c
+++ b/stmhal/wdt.c
@@ -94,8 +94,8 @@ STATIC mp_obj_t pyb_wdt_feed(mp_obj_t self_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_wdt_feed_obj, pyb_wdt_feed);
-STATIC const mp_map_elem_t pyb_wdt_locals_dict_table[] = {
- { MP_OBJ_NEW_QSTR(MP_QSTR_feed), (mp_obj_t)&pyb_wdt_feed_obj },
+STATIC const mp_rom_map_elem_t pyb_wdt_locals_dict_table[] = {
+ { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&pyb_wdt_feed_obj) },
};
STATIC MP_DEFINE_CONST_DICT(pyb_wdt_locals_dict, pyb_wdt_locals_dict_table);
@@ -104,5 +104,5 @@ const mp_obj_type_t pyb_wdt_type = {
{ &mp_type_type },
.name = MP_QSTR_WDT,
.make_new = pyb_wdt_make_new,
- .locals_dict = (mp_obj_t)&pyb_wdt_locals_dict,
+ .locals_dict = (mp_obj_dict_t*)&pyb_wdt_locals_dict,
};
From c1e0eb7afe2109a81f6e3ec28f9d01705010500c Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 6 May 2017 11:40:20 +0300
Subject: [PATCH 164/826] unix/main: Don't allow to specify too small heap
size.
This will lead to crash like:
FATAL: uncaught NLR 80a5420
On x86_32, the minimum heap size is smaller, but not 2 times, so just
use value which works for x86_64.
---
unix/main.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/unix/main.c b/unix/main.c
index 84570eb9f..93156d66e 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -375,6 +375,10 @@ STATIC void pre_process_options(int argc, char **argv) {
if (word_adjust) {
heap_size = heap_size * BYTES_PER_WORD / 4;
}
+ // If requested size too small, we'll crash anyway
+ if (heap_size < 700) {
+ goto invalid_arg;
+ }
#endif
} else {
invalid_arg:
From 4a4490ffcc906fe88e157dc926be54030c6fbf72 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 6 May 2017 18:42:35 +0300
Subject: [PATCH 165/826] py/modio: resource_stream: Implement "package" param
handling.
---
py/modio.c | 35 +++++++++++++++++++++++++++++----
tests/io/resource_stream.py | 6 ++----
tests/io/resource_stream.py.exp | 1 +
3 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/py/modio.c b/py/modio.c
index 6bf5129e6..2d317d022 100644
--- a/py/modio.c
+++ b/py/modio.c
@@ -133,13 +133,39 @@ STATIC const mp_obj_type_t bufwriter_type = {
#if MICROPY_MODULE_FROZEN_STR
STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {
+ VSTR_FIXED(path_buf, MICROPY_ALLOC_PATH_MAX);
+ size_t len;
+
+ // As an extension to pkg_resources.resource_stream(), we support
+ // package parameter being None, the path_in is interpreted as a
+ // raw path.
if (package_in != mp_const_none) {
- mp_not_implemented("");
+ mp_obj_t args[5];
+ args[0] = package_in;
+ args[1] = mp_const_none; // TODO should be globals
+ args[2] = mp_const_none; // TODO should be locals
+ args[3] = mp_const_true; // Pass sentinel "non empty" value to force returning of leaf module
+ args[4] = MP_OBJ_NEW_SMALL_INT(0);
+
+ // TODO lookup __import__ and call that instead of going straight to builtin implementation
+ mp_obj_t pkg = mp_builtin___import__(5, args);
+
+ mp_obj_t dest[2];
+ mp_load_method_maybe(pkg, MP_QSTR___path__, dest);
+ if (dest[0] == MP_OBJ_NULL) {
+ mp_raise_TypeError(NULL);
+ }
+
+ const char *path = mp_obj_str_get_data(dest[0], &len);
+ vstr_add_strn(&path_buf, path, len);
+ vstr_add_byte(&path_buf, '/');
}
- size_t len;
const char *path = mp_obj_str_get_data(path_in, &len);
- const char *data = mp_find_frozen_str(path, &len);
+ vstr_add_strn(&path_buf, path, len);
+
+ len = path_buf.len;
+ const char *data = mp_find_frozen_str(path_buf.buf, &len);
if (data != NULL) {
mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t);
o->base.type = &mp_type_bytesio;
@@ -150,7 +176,8 @@ STATIC mp_obj_t resource_stream(mp_obj_t package_in, mp_obj_t path_in) {
return MP_OBJ_FROM_PTR(o);
}
- return mp_builtin_open(1, &path_in, (mp_map_t*)&mp_const_empty_map);
+ mp_obj_t path_out = mp_obj_new_str(path_buf.buf, path_buf.len, false);
+ return mp_builtin_open(1, &path_out, (mp_map_t*)&mp_const_empty_map);
}
MP_DEFINE_CONST_FUN_OBJ_2(resource_stream_obj, resource_stream);
#endif
diff --git a/tests/io/resource_stream.py b/tests/io/resource_stream.py
index 940ffaf2f..86975f118 100644
--- a/tests/io/resource_stream.py
+++ b/tests/io/resource_stream.py
@@ -7,10 +7,8 @@
print('SKIP')
sys.exit()
-try:
- buf = uio.resource_stream("data", "file2")
-except NotImplementedError:
- pass
+buf = uio.resource_stream("data", "file2")
+print(buf.read())
# resource_stream(None, ...) look ups from current dir, hence sys.path[0] hack
buf = uio.resource_stream(None, sys.path[0] + "/data/file2")
diff --git a/tests/io/resource_stream.py.exp b/tests/io/resource_stream.py.exp
index 81c545efe..75404a347 100644
--- a/tests/io/resource_stream.py.exp
+++ b/tests/io/resource_stream.py.exp
@@ -1 +1,2 @@
1234
+1234
From 6cfa61a4cc60a877836537092d763bce3444588a Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 9 May 2017 10:41:00 +1000
Subject: [PATCH 166/826] py/binary: Handle storing big-ints to all arrays
types.
Prior to this patch only 'q' and 'Q' type arrays could store big-int
values. With this patch any big int that is stored to an array is handled
by the big-int implementation, regardless of the typecode of the array.
This allows arrays to work with all type sizes on all architectures.
---
py/binary.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/py/binary.c b/py/binary.c
index 6450478cc..34feb384e 100644
--- a/py/binary.c
+++ b/py/binary.c
@@ -327,9 +327,10 @@ void mp_binary_set_val_array(char typecode, void *p, mp_uint_t index, mp_obj_t v
break;
default:
#if MICROPY_LONGINT_IMPL != MICROPY_LONGINT_IMPL_NONE
- if ((typecode | 0x20) == 'q' && MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
+ if (MP_OBJ_IS_TYPE(val_in, &mp_type_int)) {
+ size_t size = mp_binary_get_size('@', typecode, NULL);
mp_obj_int_to_bytes_impl(val_in, MP_ENDIANNESS_BIG,
- sizeof(long long), (byte*)&((long long*)p)[index]);
+ size, (uint8_t*)p + index * size);
return;
}
#endif
From 2e9e14980d87239f861377d1dac45bb04d3f9712 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 9 May 2017 10:46:43 +1000
Subject: [PATCH 167/826] tests/basics: Update array test for big-int with lL
typecodes.
---
tests/basics/array_intbig.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/tests/basics/array_intbig.py b/tests/basics/array_intbig.py
index 2975cd385..4a3b2a0d4 100644
--- a/tests/basics/array_intbig.py
+++ b/tests/basics/array_intbig.py
@@ -1,4 +1,4 @@
-# test array('q') and array('Q')
+# test array types QqLl that require big-ints
try:
from array import array
@@ -7,6 +7,9 @@
print("SKIP")
sys.exit()
+print(array('L', [0, 2**32-1]))
+print(array('l', [-2**31, 0, 2**31-1]))
+
print(array('q'))
print(array('Q'))
From e711e2d44a24024fcd7d7f5b39f285f979b66a77 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 9 May 2017 10:49:19 +1000
Subject: [PATCH 168/826] tests/basics: Add memoryview test for big ints.
---
tests/basics/memoryview2.py | 4 ----
tests/basics/memoryview_intbig.py | 11 +++++++++++
2 files changed, 11 insertions(+), 4 deletions(-)
create mode 100644 tests/basics/memoryview_intbig.py
diff --git a/tests/basics/memoryview2.py b/tests/basics/memoryview2.py
index edb7c9e64..4b5af852b 100644
--- a/tests/basics/memoryview2.py
+++ b/tests/basics/memoryview2.py
@@ -12,7 +12,3 @@
print(list(memoryview(array('B', [0x7f, 0x80, 0x81, 0xff]))))
print(list(memoryview(array('h', [0x7f00, -0x8000]))))
print(list(memoryview(array('H', [0x7f00, 0x8000, 0x8100, 0xffff]))))
-
-# these constructors give an internal overflow in uPy
-#print(list(memoryview(array('i', [0x7f000000, -0x80000000]))))
-#print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff]))))
diff --git a/tests/basics/memoryview_intbig.py b/tests/basics/memoryview_intbig.py
new file mode 100644
index 000000000..180f15d18
--- /dev/null
+++ b/tests/basics/memoryview_intbig.py
@@ -0,0 +1,11 @@
+# test memoryview accessing maximum values for signed/unsigned elements
+try:
+ from array import array
+ memoryview
+except:
+ import sys
+ print("SKIP")
+ sys.exit()
+
+print(list(memoryview(array('i', [0x7f000000, -0x80000000]))))
+print(list(memoryview(array('I', [0x7f000000, 0x80000000, 0x81000000, 0xffffffff]))))
From 2998647c4e2c765cba72e390d467e4ba9dcf3262 Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Thu, 4 May 2017 16:31:08 -0700
Subject: [PATCH 169/826] py/lexer: Simplify lexer startup by using dummy bytes
and next_char().
Now consistently uses the EOL processing ("\r" and "\r\n" convert to "\n")
and EOF processing (ensure "\n" before EOF) provided by next_char().
In particular the lexer can now correctly handle input that starts with CR.
---
py/lexer.c | 29 +++++++----------------------
1 file changed, 7 insertions(+), 22 deletions(-)
diff --git a/py/lexer.c b/py/lexer.c
index 05651abec..4cbf31d90 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -677,7 +677,7 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
lex->source_name = src_name;
lex->reader = reader;
lex->line = 1;
- lex->column = 1;
+ lex->column = -2; // account for 3 dummy bytes
lex->emit_dent = 0;
lex->nested_bracket_level = 0;
lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT;
@@ -688,27 +688,12 @@ mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
// store sentinel for first indentation level
lex->indent_level[0] = 0;
- // preload characters
- lex->chr0 = reader.readbyte(reader.data);
- lex->chr1 = reader.readbyte(reader.data);
- lex->chr2 = reader.readbyte(reader.data);
-
- // if input stream is 0, 1 or 2 characters long and doesn't end in a newline, then insert a newline at the end
- if (lex->chr0 == MP_LEXER_EOF) {
- lex->chr0 = '\n';
- } else if (lex->chr1 == MP_LEXER_EOF) {
- if (lex->chr0 == '\r') {
- lex->chr0 = '\n';
- } else if (lex->chr0 != '\n') {
- lex->chr1 = '\n';
- }
- } else if (lex->chr2 == MP_LEXER_EOF) {
- if (lex->chr1 == '\r') {
- lex->chr1 = '\n';
- } else if (lex->chr1 != '\n') {
- lex->chr2 = '\n';
- }
- }
+ // load lexer with start of file, advancing lex->column to 1
+ // start with dummy bytes and use next_char() for proper EOL/EOF handling
+ lex->chr0 = lex->chr1 = lex->chr2 = 0;
+ next_char(lex);
+ next_char(lex);
+ next_char(lex);
// preload first token
mp_lexer_to_next(lex);
From d00d062af2743832c22e3fdff7c88db894cf59d8 Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Mon, 8 May 2017 17:24:29 -0700
Subject: [PATCH 170/826] tests/basics/lexer: Add lexer tests for input
starting with newlines.
---
tests/basics/lexer.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tests/basics/lexer.py b/tests/basics/lexer.py
index 5f12afa70..f1602f5de 100644
--- a/tests/basics/lexer.py
+++ b/tests/basics/lexer.py
@@ -9,6 +9,14 @@
exec("\n\n")
exec("\r")
exec("\r\r")
+exec("\t")
+exec("\r\n")
+exec("\nprint(1)")
+exec("\rprint(2)")
+exec("\r\nprint(3)")
+exec("\n5")
+exec("\r6")
+exec("\r\n7")
print(eval("1"))
print(eval("12"))
print(eval("123"))
From 9bd67d9fbc09823e33642e7ec709afbf88d11d0a Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 9 May 2017 15:50:40 +1000
Subject: [PATCH 171/826] tests/extmod: Make some vfs tests fully unmount FSs
before running.
Otherwise the existing FSs can interfere with the tests, and in some
cases the tests can write to the real FS on the device.
---
tests/extmod/vfs_basic.py | 4 ++++
tests/extmod/vfs_fat_more.py | 8 ++++++++
2 files changed, 12 insertions(+)
diff --git a/tests/extmod/vfs_basic.py b/tests/extmod/vfs_basic.py
index 1821a277d..32bfe8ab4 100644
--- a/tests/extmod/vfs_basic.py
+++ b/tests/extmod/vfs_basic.py
@@ -47,6 +47,10 @@ def open(self, file, mode):
# first we umount any existing mount points the target may have
+try:
+ uos.umount('/')
+except OSError:
+ pass
for path in uos.listdir('/'):
uos.umount('/' + path)
diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py
index 217d63995..6c2df528f 100644
--- a/tests/extmod/vfs_fat_more.py
+++ b/tests/extmod/vfs_fat_more.py
@@ -44,6 +44,14 @@ def ioctl(self, op, arg):
print("SKIP")
sys.exit()
+# first we umount any existing mount points the target may have
+try:
+ uos.umount('/')
+except OSError:
+ pass
+for path in uos.listdir('/'):
+ uos.umount('/' + path)
+
uos.VfsFat.mkfs(bdev)
uos.mount(bdev, '/')
From edc02bd952ed4a2042f81b0eaa41f0168ed3d98d Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 9 May 2017 14:22:21 +0300
Subject: [PATCH 172/826] unix/main: Implement -m option for packages.
---
py/builtinimport.c | 9 +++++++--
unix/main.c | 17 +++++++++++++----
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/py/builtinimport.c b/py/builtinimport.c
index cf17d5305..d01ebbe73 100644
--- a/py/builtinimport.c
+++ b/py/builtinimport.c
@@ -429,8 +429,13 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) {
// if args[3] (fromtuple) has magic value False, set up
// this module for command-line "-m" option (set module's
- // name to __main__ instead of real name).
- if (i == mod_len && fromtuple == mp_const_false) {
+ // name to __main__ instead of real name). Do this only
+ // for *modules* however - packages never have their names
+ // replaced, instead they're -m'ed using a special __main__
+ // submodule in them. (This all apparently is done to not
+ // touch package name itself, which is important for future
+ // imports).
+ if (i == mod_len && fromtuple == mp_const_false && stat != MP_IMPORT_STAT_DIR) {
mp_obj_module_t *o = MP_OBJ_TO_PTR(module_obj);
mp_obj_dict_store(MP_OBJ_FROM_PTR(o->globals), MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR___main__));
#if MICROPY_CPYTHON_COMPAT
diff --git a/unix/main.c b/unix/main.c
index 93156d66e..633144c86 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -553,6 +553,9 @@ MP_NOINLINE int main_(int argc, char **argv) {
mp_obj_t mod;
nlr_buf_t nlr;
+ bool subpkg_tried = false;
+
+ reimport:
if (nlr_push(&nlr) == 0) {
mod = mp_builtin___import__(MP_ARRAY_SIZE(import_args), import_args);
nlr_pop();
@@ -561,11 +564,17 @@ MP_NOINLINE int main_(int argc, char **argv) {
return handle_uncaught_exception(nlr.ret_val) & 0xff;
}
- if (mp_obj_is_package(mod)) {
- // TODO
- mp_printf(&mp_stderr_print, "%s: -m for packages not yet implemented\n", argv[0]);
- exit(1);
+ if (mp_obj_is_package(mod) && !subpkg_tried) {
+ subpkg_tried = true;
+ vstr_t vstr;
+ int len = strlen(argv[a + 1]);
+ vstr_init(&vstr, len + sizeof(".__main__"));
+ vstr_add_strn(&vstr, argv[a + 1], len);
+ vstr_add_strn(&vstr, ".__main__", sizeof(".__main__") - 1);
+ import_args[0] = mp_obj_new_str_from_vstr(&mp_type_str, &vstr);
+ goto reimport;
}
+
ret = 0;
break;
} else if (strcmp(argv[a], "-X") == 0) {
From 1365f7f293bc133385b34e5a05ac043df5bba8a1 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 10 May 2017 11:10:52 +1000
Subject: [PATCH 173/826] esp32/modsocket: When resolving IP addr handle the
case of host=''.
---
esp32/modsocket.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/esp32/modsocket.c b/esp32/modsocket.c
index 5d554b764..4fe5e0ddf 100644
--- a/esp32/modsocket.c
+++ b/esp32/modsocket.c
@@ -108,9 +108,13 @@ static int _socket_getaddrinfo2(const mp_obj_t host, const mp_obj_t portx, struc
port = mp_obj_str_binary_op(MP_BINARY_OP_MODULO, mp_obj_new_str("%s", 2, true), port);
}
- mp_uint_t host_len, port_len;
- const char *host_str = mp_obj_str_get_data(host, &host_len);
- const char *port_str = mp_obj_str_get_data(port, &port_len);
+ const char *host_str = mp_obj_str_get_str(host);
+ const char *port_str = mp_obj_str_get_str(port);
+
+ if (host_str[0] == '\0') {
+ // a host of "" is equivalent to the default/all-local IP address
+ host_str = "0.0.0.0";
+ }
MP_THREAD_GIL_EXIT();
int res = lwip_getaddrinfo(host_str, port_str, &hints, resp);
From 87283c1974188707b436eebf2a04d4555a26dcca Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 23:31:51 +1000
Subject: [PATCH 174/826] extmod/vfs: Implement mp_vfs_ilistdir().
uos.ilistdir() is the core function, returning an iterator that yields
3-tuples. uos.listdir() is implemented in terms of ilistdir().
---
extmod/vfs.c | 79 ++++++++++++++++++++++++++++++++++++++++++----------
extmod/vfs.h | 6 ++++
2 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 84e9fe82d..8db7d5e44 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -286,7 +286,49 @@ mp_obj_t mp_vfs_getcwd(void) {
}
MP_DEFINE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj, mp_vfs_getcwd);
-mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
+typedef struct _mp_vfs_ilistdir_it_t {
+ mp_obj_base_t base;
+ mp_fun_1_t iternext;
+ union {
+ mp_vfs_mount_t *vfs;
+ mp_obj_t iter;
+ } cur;
+ bool is_str;
+ bool is_iter;
+} mp_vfs_ilistdir_it_t;
+
+STATIC mp_obj_t mp_vfs_ilistdir_it_iternext(mp_obj_t self_in) {
+ mp_vfs_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
+ if (self->is_iter) {
+ // continue delegating to root dir
+ return mp_iternext(self->cur.iter);
+ } else if (self->cur.vfs == NULL) {
+ // finished iterating mount points and no root dir is mounted
+ return MP_OBJ_STOP_ITERATION;
+ } else {
+ // continue iterating mount points
+ mp_vfs_mount_t *vfs = self->cur.vfs;
+ self->cur.vfs = vfs->next;
+ if (vfs->len == 1) {
+ // vfs is mounted at root dir, delegate to it
+ mp_obj_t root = mp_obj_new_str("/", 1, false);
+ self->is_iter = true;
+ self->cur.iter = mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &root);
+ return mp_iternext(self->cur.iter);
+ } else {
+ // a mounted directory
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
+ t->items[0] = mp_obj_new_str_of_type(
+ self->is_str ? &mp_type_str : &mp_type_bytes,
+ (const byte*)vfs->str + 1, vfs->len - 1);
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
+ return MP_OBJ_FROM_PTR(t);
+ }
+ }
+}
+
+mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args) {
mp_obj_t path_in;
if (n_args == 1) {
path_in = args[0];
@@ -299,22 +341,29 @@ mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
if (vfs == MP_VFS_ROOT) {
// list the root directory
- mp_obj_t dir_list = mp_obj_new_list(0, NULL);
- for (vfs = MP_STATE_VM(vfs_mount_table); vfs != NULL; vfs = vfs->next) {
- if (vfs->len == 1) {
- // vfs is mounted at root dir, delegate to it
- mp_obj_t root = mp_obj_new_str("/", 1, false);
- mp_obj_t dir_list2 = mp_vfs_proxy_call(vfs, MP_QSTR_listdir, 1, &root);
- dir_list = mp_binary_op(MP_BINARY_OP_ADD, dir_list, dir_list2);
- } else {
- mp_obj_list_append(dir_list, mp_obj_new_str_of_type(mp_obj_get_type(path_in),
- (const byte*)vfs->str + 1, vfs->len - 1));
- }
- }
- return dir_list;
+ mp_vfs_ilistdir_it_t *iter = m_new_obj(mp_vfs_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter;
+ iter->iternext = mp_vfs_ilistdir_it_iternext;
+ iter->cur.vfs = MP_STATE_VM(vfs_mount_table);
+ iter->is_str = mp_obj_get_type(path_in) == &mp_type_str;
+ iter->is_iter = false;
+ return MP_OBJ_FROM_PTR(iter);
}
- return mp_vfs_proxy_call(vfs, MP_QSTR_listdir, 1, &path_out);
+ return mp_vfs_proxy_call(vfs, MP_QSTR_ilistdir, 1, &path_out);
+}
+MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj, 0, 1, mp_vfs_ilistdir);
+
+mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t iter = mp_vfs_ilistdir(n_args, args);
+ mp_obj_t dir_list = mp_obj_new_list(0, NULL);
+ mp_obj_t next;
+ while ((next = mp_iternext(iter)) != MP_OBJ_STOP_ITERATION) {
+ mp_obj_t *items;
+ mp_obj_get_array_fixed_n(next, 3, &items);
+ mp_obj_list_append(dir_list, items[0]);
+ }
+ return dir_list;
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj, 0, 1, mp_vfs_listdir);
diff --git a/extmod/vfs.h b/extmod/vfs.h
index 4a1c225a0..edaeb5349 100644
--- a/extmod/vfs.h
+++ b/extmod/vfs.h
@@ -35,6 +35,10 @@
#define MP_VFS_NONE ((mp_vfs_mount_t*)1)
#define MP_VFS_ROOT ((mp_vfs_mount_t*)0)
+// MicroPython's port-standardized versions of stat constants
+#define MP_S_IFDIR (0x4000)
+#define MP_S_IFREG (0x8000)
+
// constants for block protocol ioctl
#define BP_IOCTL_INIT (1)
#define BP_IOCTL_DEINIT (2)
@@ -56,6 +60,7 @@ mp_obj_t mp_vfs_umount(mp_obj_t mnt_in);
mp_obj_t mp_vfs_open(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args);
mp_obj_t mp_vfs_chdir(mp_obj_t path_in);
mp_obj_t mp_vfs_getcwd(void);
+mp_obj_t mp_vfs_ilistdir(size_t n_args, const mp_obj_t *args);
mp_obj_t mp_vfs_listdir(size_t n_args, const mp_obj_t *args);
mp_obj_t mp_vfs_mkdir(mp_obj_t path_in);
mp_obj_t mp_vfs_remove(mp_obj_t path_in);
@@ -69,6 +74,7 @@ MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_umount_obj);
MP_DECLARE_CONST_FUN_OBJ_KW(mp_vfs_open_obj);
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_chdir_obj);
MP_DECLARE_CONST_FUN_OBJ_0(mp_vfs_getcwd_obj);
+MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_ilistdir_obj);
MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(mp_vfs_listdir_obj);
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_mkdir_obj);
MP_DECLARE_CONST_FUN_OBJ_1(mp_vfs_remove_obj);
From d4cd4831b01ff87b4a9f84bb88b165e3b156b3b4 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 23:32:44 +1000
Subject: [PATCH 175/826] extmod/vfs_fat: Replace listdir() with implementation
of ilistdir().
VfsFat no longer has the listdir() method. Rather, if listdir()
functionality is needed then one should use uos.listdir() which will call
VfsFat.ilistdir().
---
extmod/vfs_fat.c | 8 ++---
extmod/vfs_fat.h | 2 +-
extmod/vfs_fat_misc.c | 73 +++++++++++++++++++++++++------------------
3 files changed, 48 insertions(+), 35 deletions(-)
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index dee4f9298..41c32c6b6 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -91,7 +91,7 @@ STATIC MP_DEFINE_CONST_STATICMETHOD_OBJ(fat_vfs_mkfs_obj, MP_ROM_PTR(&fat_vfs_mk
STATIC MP_DEFINE_CONST_FUN_OBJ_3(fat_vfs_open_obj, fatfs_builtin_open_self);
-STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) {
+STATIC mp_obj_t fat_vfs_ilistdir_func(size_t n_args, const mp_obj_t *args) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(args[0]);
bool is_str_type = true;
const char *path;
@@ -104,9 +104,9 @@ STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) {
path = "";
}
- return fat_vfs_listdir2(self, path, is_str_type);
+ return fat_vfs_ilistdir2(self, path, is_str_type);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func);
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_ilistdir_obj, 1, 2, fat_vfs_ilistdir_func);
STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t vfs_in, mp_obj_t path_in, mp_int_t attr) {
mp_obj_fat_vfs_t *self = MP_OBJ_TO_PTR(vfs_in);
@@ -321,7 +321,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(fat_vfs_umount_obj, vfs_fat_umount);
STATIC const mp_rom_map_elem_t fat_vfs_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mkfs), MP_ROM_PTR(&fat_vfs_mkfs_obj) },
{ MP_ROM_QSTR(MP_QSTR_open), MP_ROM_PTR(&fat_vfs_open_obj) },
- { MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&fat_vfs_listdir_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&fat_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&fat_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&fat_vfs_rmdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&fat_vfs_chdir_obj) },
diff --git a/extmod/vfs_fat.h b/extmod/vfs_fat.h
index 7eb865254..6c7c05a9a 100644
--- a/extmod/vfs_fat.h
+++ b/extmod/vfs_fat.h
@@ -57,4 +57,4 @@ mp_import_stat_t fat_vfs_import_stat(struct _fs_user_mount_t *vfs, const char *p
mp_obj_t fatfs_builtin_open_self(mp_obj_t self_in, mp_obj_t path, mp_obj_t mode);
MP_DECLARE_CONST_FUN_OBJ_KW(mp_builtin_open_obj);
-mp_obj_t fat_vfs_listdir2(struct _fs_user_mount_t *vfs, const char *path, bool is_str_type);
+mp_obj_t fat_vfs_ilistdir2(struct _fs_user_mount_t *vfs, const char *path, bool is_str_type);
diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c
index 19db99c7f..5b906189f 100644
--- a/extmod/vfs_fat_misc.c
+++ b/extmod/vfs_fat_misc.c
@@ -34,51 +34,64 @@
#include "extmod/vfs_fat.h"
#include "py/lexer.h"
-// TODO: actually, the core function should be ilistdir()
-
-mp_obj_t fat_vfs_listdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) {
- FRESULT res;
- FILINFO fno;
+typedef struct _mp_vfs_fat_ilistdir_it_t {
+ mp_obj_base_t base;
+ mp_fun_1_t iternext;
+ bool is_str;
FF_DIR dir;
+} mp_vfs_fat_ilistdir_it_t;
- res = f_opendir(&vfs->fatfs, &dir, path);
- if (res != FR_OK) {
- mp_raise_OSError(fresult_to_errno_table[res]);
- }
-
- mp_obj_t dir_list = mp_obj_new_list(0, NULL);
+STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
+ mp_vfs_fat_ilistdir_it_t *self = MP_OBJ_TO_PTR(self_in);
for (;;) {
- res = f_readdir(&dir, &fno); /* Read a directory item */
- if (res != FR_OK || fno.fname[0] == 0) break; /* Break on error or end of dir */
- if (fno.fname[0] == '.' && fno.fname[1] == 0) continue; /* Ignore . entry */
- if (fno.fname[0] == '.' && fno.fname[1] == '.' && fno.fname[2] == 0) continue; /* Ignore .. entry */
-
+ FILINFO fno;
+ FRESULT res = f_readdir(&self->dir, &fno);
char *fn = fno.fname;
+ if (res != FR_OK || fn[0] == 0) {
+ // stop on error or end of dir
+ break;
+ }
+ if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) {
+ // skip . and ..
+ continue;
+ }
- /*
+ // make 3-tuple with info about this entry
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
+ if (self->is_str) {
+ t->items[0] = mp_obj_new_str(fn, strlen(fn), false);
+ } else {
+ t->items[0] = mp_obj_new_bytes((const byte*)fn, strlen(fn));
+ }
if (fno.fattrib & AM_DIR) {
// dir
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR);
} else {
// file
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(MP_S_IFREG);
}
- */
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(0); // no inode number
- // make a string object for this entry
- mp_obj_t entry_o;
- if (is_str_type) {
- entry_o = mp_obj_new_str(fn, strlen(fn), false);
- } else {
- entry_o = mp_obj_new_bytes((const byte*)fn, strlen(fn));
- }
-
- // add the entry to the list
- mp_obj_list_append(dir_list, entry_o);
+ return MP_OBJ_FROM_PTR(t);
}
- f_closedir(&dir);
+ // ignore error because we may be closing a second time
+ f_closedir(&self->dir);
- return dir_list;
+ return MP_OBJ_STOP_ITERATION;
+}
+
+mp_obj_t fat_vfs_ilistdir2(fs_user_mount_t *vfs, const char *path, bool is_str_type) {
+ mp_vfs_fat_ilistdir_it_t *iter = m_new_obj(mp_vfs_fat_ilistdir_it_t);
+ iter->base.type = &mp_type_polymorph_iter;
+ iter->iternext = mp_vfs_fat_ilistdir_it_iternext;
+ iter->is_str = is_str_type;
+ FRESULT res = f_opendir(&vfs->fatfs, &iter->dir, path);
+ if (res != FR_OK) {
+ mp_raise_OSError(fresult_to_errno_table[res]);
+ }
+ return MP_OBJ_FROM_PTR(iter);
}
mp_import_stat_t fat_vfs_import_stat(fs_user_mount_t *vfs, const char *path) {
From 852c215d76de082adf57d3724907ab2c8d790e78 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 23:35:49 +1000
Subject: [PATCH 176/826] tests/extmod/vfs: Update tests to reflect new
ilistdir() method.
---
tests/extmod/vfs_basic.py | 18 +++++++++++++++---
tests/extmod/vfs_basic.py.exp | 21 ++++++++++++---------
tests/extmod/vfs_fat_fileio1.py | 2 +-
tests/extmod/vfs_fat_fileio1.py.exp | 2 +-
tests/extmod/vfs_fat_fileio2.py | 8 ++++----
tests/extmod/vfs_fat_fileio2.py.exp | 8 ++++----
tests/extmod/vfs_fat_oldproto.py | 4 ++--
tests/extmod/vfs_fat_oldproto.py.exp | 2 +-
tests/extmod/vfs_fat_ramdisk.py | 6 +++---
tests/extmod/vfs_fat_ramdisk.py.exp | 4 ++--
10 files changed, 45 insertions(+), 30 deletions(-)
diff --git a/tests/extmod/vfs_basic.py b/tests/extmod/vfs_basic.py
index 32bfe8ab4..a3b2f3c29 100644
--- a/tests/extmod/vfs_basic.py
+++ b/tests/extmod/vfs_basic.py
@@ -20,9 +20,9 @@ def mount(self, readonly, mkfs):
print(self.id, 'mount', readonly, mkfs)
def umount(self):
print(self.id, 'umount')
- def listdir(self, dir):
- print(self.id, 'listdir', dir)
- return ['a%d' % self.id]
+ def ilistdir(self, dir):
+ print(self.id, 'ilistdir', dir)
+ return iter([('a%d' % self.id, 0, 0)])
def chdir(self, dir):
print(self.id, 'chdir', dir)
def getcwd(self):
@@ -64,6 +64,18 @@ def open(self, file, mode):
uos.mount(Filesystem(1), '/test_mnt')
print(uos.listdir())
+# ilistdir
+i = uos.ilistdir()
+print(next(i))
+try:
+ next(i)
+except StopIteration:
+ print('StopIteration')
+try:
+ next(i)
+except StopIteration:
+ print('StopIteration')
+
# referencing the mount point in different ways
print(uos.listdir('test_mnt'))
print(uos.listdir('/test_mnt'))
diff --git a/tests/extmod/vfs_basic.py.exp b/tests/extmod/vfs_basic.py.exp
index 416d45961..8a23aa8ae 100644
--- a/tests/extmod/vfs_basic.py.exp
+++ b/tests/extmod/vfs_basic.py.exp
@@ -2,20 +2,23 @@
/
1 mount False False
['test_mnt']
-1 listdir /
+('test_mnt', 16384, 0)
+StopIteration
+StopIteration
+1 ilistdir /
['a1']
-1 listdir /
+1 ilistdir /
['a1']
2 mount True False
['test_mnt', 'test_mnt2']
-2 listdir /
+2 ilistdir /
['a2']
3 mount False False
OSError
OSError
OSError
1 chdir /
-1 listdir
+1 ilistdir
['a1']
1 getcwd
/test_mntdir1
@@ -33,19 +36,19 @@ OSError
2 umount
OSError
3 mount False False
-3 listdir /
+3 ilistdir /
['a3']
3 open test r
4 mount False False
-3 listdir /
+3 ilistdir /
['mnt', 'a3']
-4 listdir /
+4 ilistdir /
['a4']
4 chdir /
-4 listdir
+4 ilistdir
['a4']
3 chdir /subdir
-3 listdir
+3 ilistdir
['a3']
3 chdir /
3 umount
diff --git a/tests/extmod/vfs_fat_fileio1.py b/tests/extmod/vfs_fat_fileio1.py
index 526b3f5c1..9036df7a5 100644
--- a/tests/extmod/vfs_fat_fileio1.py
+++ b/tests/extmod/vfs_fat_fileio1.py
@@ -115,4 +115,4 @@ def ioctl(self, op, arg):
print(e.args[0] == 20) # uerrno.ENOTDIR
vfs.remove("foo_file.txt")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
diff --git a/tests/extmod/vfs_fat_fileio1.py.exp b/tests/extmod/vfs_fat_fileio1.py.exp
index 7959a70ee..d777585cf 100644
--- a/tests/extmod/vfs_fat_fileio1.py.exp
+++ b/tests/extmod/vfs_fat_fileio1.py.exp
@@ -10,4 +10,4 @@ e
True
d
True
-['foo_dir']
+[('foo_dir', 16384, 0)]
diff --git a/tests/extmod/vfs_fat_fileio2.py b/tests/extmod/vfs_fat_fileio2.py
index 111abfa7e..b2a0ba70f 100644
--- a/tests/extmod/vfs_fat_fileio2.py
+++ b/tests/extmod/vfs_fat_fileio2.py
@@ -91,23 +91,23 @@ def ioctl(self, op, arg):
# trim full path
vfs.rename("foo_dir/file-in-dir.txt", "foo_dir/file.txt")
-print(vfs.listdir("foo_dir"))
+print(list(vfs.ilistdir("foo_dir")))
vfs.rename("foo_dir/file.txt", "moved-to-root.txt")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
# check that renaming to existing file will overwrite it
with open("temp", "w") as f:
f.write("new text")
vfs.rename("temp", "moved-to-root.txt")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
with open("moved-to-root.txt") as f:
print(f.read())
# valid removes
vfs.remove("foo_dir/sub_file.txt")
vfs.rmdir("foo_dir")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
# disk full
try:
diff --git a/tests/extmod/vfs_fat_fileio2.py.exp b/tests/extmod/vfs_fat_fileio2.py.exp
index 38ec5c9b9..118dee26b 100644
--- a/tests/extmod/vfs_fat_fileio2.py.exp
+++ b/tests/extmod/vfs_fat_fileio2.py.exp
@@ -3,9 +3,9 @@ True
True
b'data in file'
True
-['sub_file.txt', 'file.txt']
-['foo_dir', 'moved-to-root.txt']
-['foo_dir', 'moved-to-root.txt']
+[('sub_file.txt', 32768, 0), ('file.txt', 32768, 0)]
+[('foo_dir', 16384, 0), ('moved-to-root.txt', 32768, 0)]
+[('foo_dir', 16384, 0), ('moved-to-root.txt', 32768, 0)]
new text
-['moved-to-root.txt']
+[('moved-to-root.txt', 32768, 0)]
ENOSPC: True
diff --git a/tests/extmod/vfs_fat_oldproto.py b/tests/extmod/vfs_fat_oldproto.py
index 77d349212..3e66758c3 100644
--- a/tests/extmod/vfs_fat_oldproto.py
+++ b/tests/extmod/vfs_fat_oldproto.py
@@ -53,10 +53,10 @@ def count(self):
with vfs.open("file.txt", "w") as f:
f.write("hello!")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
with vfs.open("file.txt", "r") as f:
print(f.read())
vfs.remove("file.txt")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
diff --git a/tests/extmod/vfs_fat_oldproto.py.exp b/tests/extmod/vfs_fat_oldproto.py.exp
index a389a5217..ab8338cbb 100644
--- a/tests/extmod/vfs_fat_oldproto.py.exp
+++ b/tests/extmod/vfs_fat_oldproto.py.exp
@@ -1,3 +1,3 @@
-['file.txt']
+[('file.txt', 32768, 0)]
hello!
[]
diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py
index 81f9418b2..89b40e3a2 100644
--- a/tests/extmod/vfs_fat_ramdisk.py
+++ b/tests/extmod/vfs_fat_ramdisk.py
@@ -65,7 +65,7 @@ def ioctl(self, op, arg):
with vfs.open("foo_file.txt", "w") as f:
f.write("hello!")
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
print("stat root:", vfs.stat("/"))
print("stat file:", vfs.stat("foo_file.txt")[:-3]) # timestamps differ across runs
@@ -76,7 +76,7 @@ def ioctl(self, op, arg):
vfs.mkdir("foo_dir")
vfs.chdir("foo_dir")
print("getcwd:", vfs.getcwd())
-print(vfs.listdir())
+print(list(vfs.ilistdir()))
with vfs.open("sub_file.txt", "w") as f:
f.write("subdir file")
@@ -92,4 +92,4 @@ def ioctl(self, op, arg):
uos.umount(vfs)
vfs = uos.VfsFat(bdev)
-print(vfs.listdir(b""))
+print(list(vfs.ilistdir(b"")))
diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp
index 137db5841..6298a7efd 100644
--- a/tests/extmod/vfs_fat_ramdisk.py.exp
+++ b/tests/extmod/vfs_fat_ramdisk.py.exp
@@ -3,7 +3,7 @@ True
statvfs: (512, 512, 16, 16, 16, 0, 0, 0, 0, 255)
getcwd: /
True
-['foo_file.txt']
+[('foo_file.txt', 32768, 0)]
stat root: (16384, 0, 0, 0, 0, 0, 0, 0, 0, 0)
stat file: (32768, 0, 0, 0, 0, 0, 6)
True
@@ -12,4 +12,4 @@ getcwd: /foo_dir
[]
True
getcwd: /
-[b'foo_file.txt', b'foo_dir']
+[(b'foo_file.txt', 32768, 0), (b'foo_dir', 16384, 0)]
From f1609bc843f1c30117cf9dfae8fb22ee36512446 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Fri, 5 May 2017 23:36:17 +1000
Subject: [PATCH 177/826] ports: Add ilistdir in uos module.
---
cc3200/mods/moduos.c | 1 +
esp8266/moduos.c | 1 +
qemu-arm/moduos.c | 1 +
stmhal/moduos.c | 1 +
unix/moduos_vfs.c | 1 +
5 files changed, 5 insertions(+)
diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c
index add10ec6c..ed8879bf3 100644
--- a/cc3200/mods/moduos.c
+++ b/cc3200/mods/moduos.c
@@ -155,6 +155,7 @@ STATIC const mp_map_elem_t os_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_chdir), (mp_obj_t)&mp_vfs_chdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_getcwd), (mp_obj_t)&mp_vfs_getcwd_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_ilistdir), (mp_obj_t)&mp_vfs_ilistdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_listdir), (mp_obj_t)&mp_vfs_listdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_mkdir), (mp_obj_t)&mp_vfs_mkdir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_rename), (mp_obj_t)&mp_vfs_rename_obj},
diff --git a/esp8266/moduos.c b/esp8266/moduos.c
index a22fbd4df..807d2e18a 100644
--- a/esp8266/moduos.c
+++ b/esp8266/moduos.c
@@ -93,6 +93,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
#endif
#if MICROPY_VFS_FAT
{ MP_ROM_QSTR(MP_QSTR_VfsFat), MP_ROM_PTR(&mp_fat_vfs_type) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_rmdir), MP_ROM_PTR(&mp_vfs_rmdir_obj) },
diff --git a/qemu-arm/moduos.c b/qemu-arm/moduos.c
index dcb67396b..a48b51db0 100644
--- a/qemu-arm/moduos.c
+++ b/qemu-arm/moduos.c
@@ -31,6 +31,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
diff --git a/stmhal/moduos.c b/stmhal/moduos.c
index 2d648cb91..ece6019fb 100644
--- a/stmhal/moduos.c
+++ b/stmhal/moduos.c
@@ -135,6 +135,7 @@ STATIC const mp_rom_map_elem_t os_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
diff --git a/unix/moduos_vfs.c b/unix/moduos_vfs.c
index 58990b028..96defa554 100644
--- a/unix/moduos_vfs.c
+++ b/unix/moduos_vfs.c
@@ -42,6 +42,7 @@ STATIC const mp_rom_map_elem_t uos_vfs_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_chdir), MP_ROM_PTR(&mp_vfs_chdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_getcwd), MP_ROM_PTR(&mp_vfs_getcwd_obj) },
+ { MP_ROM_QSTR(MP_QSTR_ilistdir), MP_ROM_PTR(&mp_vfs_ilistdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_listdir), MP_ROM_PTR(&mp_vfs_listdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_mkdir), MP_ROM_PTR(&mp_vfs_mkdir_obj) },
{ MP_ROM_QSTR(MP_QSTR_remove), MP_ROM_PTR(&mp_vfs_remove_obj) },
From d70f688f25a76e1e6a251a4ffc5144539c1a4e64 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 10 May 2017 12:30:34 +1000
Subject: [PATCH 178/826] extmod/vfs: Use MP_S_IFDIR, MP_S_IFREG consts instead
of magic numbers.
---
extmod/vfs.c | 2 +-
extmod/vfs_fat.c | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/extmod/vfs.c b/extmod/vfs.c
index 8db7d5e44..f158bd387 100644
--- a/extmod/vfs.c
+++ b/extmod/vfs.c
@@ -408,7 +408,7 @@ mp_obj_t mp_vfs_stat(mp_obj_t path_in) {
mp_vfs_mount_t *vfs = lookup_path(path_in, &path_out);
if (vfs == MP_VFS_ROOT) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
- t->items[0] = MP_OBJ_NEW_SMALL_INT(0x4000); // st_mode = stat.S_IFDIR
+ t->items[0] = MP_OBJ_NEW_SMALL_INT(MP_S_IFDIR); // st_mode
for (int i = 1; i <= 9; ++i) {
t->items[i] = MP_OBJ_NEW_SMALL_INT(0); // dev, nlink, uid, gid, size, atime, mtime, ctime
}
diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c
index 41c32c6b6..0ec3fe6d2 100644
--- a/extmod/vfs_fat.c
+++ b/extmod/vfs_fat.c
@@ -225,9 +225,9 @@ STATIC mp_obj_t fat_vfs_stat(mp_obj_t vfs_in, mp_obj_t path_in) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
mp_int_t mode = 0;
if (fno.fattrib & AM_DIR) {
- mode |= 0x4000; // stat.S_IFDIR
+ mode |= MP_S_IFDIR;
} else {
- mode |= 0x8000; // stat.S_IFREG
+ mode |= MP_S_IFREG;
}
mp_int_t seconds = timeutils_seconds_since_2000(
1980 + ((fno.fdate >> 9) & 0x7f),
From 6d221fe284f977dbf55fd4668efae281b045c237 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 10 May 2017 12:44:21 +1000
Subject: [PATCH 179/826] docs/library/uos: Add description of uos.ilistdir()
function.
---
docs/library/uos.rst | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/docs/library/uos.rst b/docs/library/uos.rst
index e1ea72967..d1f83d2cc 100644
--- a/docs/library/uos.rst
+++ b/docs/library/uos.rst
@@ -37,6 +37,21 @@ Functions
Get the current directory.
+.. function:: ilistdir([dir])
+
+ This function returns an iterator which then yields 3-tuples corresponding to
+ the entries in the directory that it is listing. With no argument it lists the
+ current directory, otherwise it lists the directory given by `dir`.
+
+ The 3-tuples have the form `(name, type, inode)`:
+
+ - `name` is a string (or bytes if `dir` is a bytes object) and is the name of
+ the entry;
+ - `type` is an integer that specifies the type of the entry, with 0x4000 for
+ directories and 0x8000 for regular files;
+ - `inode` is an integer corresponding to the inode of the file, and may be 0
+ for filesystems that don't have such a notion.
+
.. function:: listdir([dir])
With no argument, list the current directory. Otherwise list the given directory.
From a1f254028d0ca19f5d2ea1a7f1bbe42cd52533e2 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 22 Apr 2017 18:10:13 +1000
Subject: [PATCH 180/826] py/mkrules.mk: Add dependency of .mpy files upon
mpy-cross.
This ensures that mpy-cross is automatically built (and is up-to-date) for
ports that use frozen bytecode. It also makes sure that .mpy files are
re-built if mpy-cross is changed.
---
py/mkrules.mk | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/py/mkrules.mk b/py/mkrules.mk
index 2ba57e0ee..b37415e05 100644
--- a/py/mkrules.mk
+++ b/py/mkrules.mk
@@ -102,15 +102,19 @@ $(BUILD)/frozen.c: $(wildcard $(FROZEN_DIR)/*) $(HEADER_BUILD) $(FROZEN_EXTRA_DE
endif
ifneq ($(FROZEN_MPY_DIR),)
+# to build the MicroPython cross compiler
+$(TOP)/mpy-cross/mpy-cross: $(TOP)/py/*.[ch] $(TOP)/mpy-cross/*.[ch] $(TOP)/windows/fmode.c
+ $(Q)$(MAKE) -C $(TOP)/mpy-cross
+
# make a list of all the .py files that need compiling and freezing
FROZEN_MPY_PY_FILES := $(shell find -L $(FROZEN_MPY_DIR) -type f -name '*.py' | $(SED) -e 's=^$(FROZEN_MPY_DIR)/==')
FROZEN_MPY_MPY_FILES := $(addprefix $(BUILD)/frozen_mpy/,$(FROZEN_MPY_PY_FILES:.py=.mpy))
# to build .mpy files from .py files
-$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py
+$(BUILD)/frozen_mpy/%.mpy: $(FROZEN_MPY_DIR)/%.py $(TOP)/mpy-cross/mpy-cross
@$(ECHO) "MPY $<"
$(Q)$(MKDIR) -p $(dir $@)
- $(Q)$(MPY_CROSS) -o $@ -s $(^:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $^
+ $(Q)$(MPY_CROSS) -o $@ -s $(<:$(FROZEN_MPY_DIR)/%=%) $(MPY_CROSS_FLAGS) $<
# to build frozen_mpy.c from all .mpy files
$(BUILD)/frozen_mpy.c: $(FROZEN_MPY_MPY_FILES) $(BUILD)/genhdr/qstrdefs.generated.h
From 1d8c3f4cff19e8128757a7c24ca98d6ea5e95c0d Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 26 Apr 2017 11:34:22 +1000
Subject: [PATCH 181/826] mpy-cross/Makefile: Override undefine any inherited
variables.
This is a temporary hack to allow othe Makefiles to build mpy-cross
recursively.
---
mpy-cross/Makefile | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/mpy-cross/Makefile b/mpy-cross/Makefile
index 6ed4e653f..de07d2f6d 100644
--- a/mpy-cross/Makefile
+++ b/mpy-cross/Makefile
@@ -1,3 +1,14 @@
+# The following is a temporary hack to forefully undefine vars that might have
+# be defined by a calling Makefile (from recursive make).
+# TODO: Find a better way to be able to call this Makefile recursively.
+override undefine COPT
+override undefine CFLAGS_EXTRA
+override undefine LDFLAGS_EXTRA
+override undefine FROZEN_DIR
+override undefine FROZEN_MPY_DIR
+override undefine BUILD
+override undefine PROG
+
include ../py/mkenv.mk
# define main target
From 5feeba889799834af0d504dcb5993be5905a9d63 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 01:19:13 +0300
Subject: [PATCH 182/826] examples/hwapi/hwconfig*: Use inline Signal() args
where possible.
---
examples/hwapi/hwconfig_esp8266_esp12.py | 2 +-
examples/hwapi/hwconfig_pyboard.py | 8 ++++----
examples/hwapi/hwconfig_z_frdm_k64f.py | 2 +-
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/examples/hwapi/hwconfig_esp8266_esp12.py b/examples/hwapi/hwconfig_esp8266_esp12.py
index 198a652d0..2e855ee3d 100644
--- a/examples/hwapi/hwconfig_esp8266_esp12.py
+++ b/examples/hwapi/hwconfig_esp8266_esp12.py
@@ -2,4 +2,4 @@
# ESP12 module as used by many boards
# Blue LED on pin 2, active low (inverted)
-LED = Signal(Pin(2, Pin.OUT), invert=True)
+LED = Signal(2, Pin.OUT, invert=True)
diff --git a/examples/hwapi/hwconfig_pyboard.py b/examples/hwapi/hwconfig_pyboard.py
index 4db432491..fb260033e 100644
--- a/examples/hwapi/hwconfig_pyboard.py
+++ b/examples/hwapi/hwconfig_pyboard.py
@@ -1,13 +1,13 @@
from machine import Pin, Signal
# Red LED on pin LED_RED also kown as A13
-LED = Signal(Pin('LED_RED', Pin.OUT))
+LED = Signal('LED_RED', Pin.OUT)
# Green LED on pin LED_GREEN also known as A14
-LED2 = Signal(Pin('LED_GREEN', Pin.OUT))
+LED2 = Signal('LED_GREEN', Pin.OUT)
# Yellow LED on pin LED_YELLOW also known as A15
-LED3 = Signal(Pin('LED_YELLOW', Pin.OUT))
+LED3 = Signal('LED_YELLOW', Pin.OUT)
# Blue LED on pin LED_BLUE also known as B4
-LED4 = Signal(Pin('LED_BLUE', Pin.OUT))
+LED4 = Signal('LED_BLUE', Pin.OUT)
diff --git a/examples/hwapi/hwconfig_z_frdm_k64f.py b/examples/hwapi/hwconfig_z_frdm_k64f.py
index 6313e2ddb..377c63878 100644
--- a/examples/hwapi/hwconfig_z_frdm_k64f.py
+++ b/examples/hwapi/hwconfig_z_frdm_k64f.py
@@ -2,4 +2,4 @@
# Freescale/NXP FRDM-K64F board
# Blue LED on port B, pin 21
-LED = Signal(Pin(("GPIO_1", 21), Pin.OUT))
+LED = Signal(("GPIO_1", 21), Pin.OUT)
From 6f56412ec3b93bb93b109f0a01512ecaeebf4f79 Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Tue, 9 May 2017 13:19:46 -0700
Subject: [PATCH 183/826] py/lexer: Process CR earlier to allow newlines checks
on chr1.
Resolves an issue where lexer failed to accept CR after line continuation
character. It also simplifies the code.
---
py/lexer.c | 19 +++++++------------
1 file changed, 7 insertions(+), 12 deletions(-)
diff --git a/py/lexer.c b/py/lexer.c
index 4cbf31d90..abc1f3ebb 100644
--- a/py/lexer.c
+++ b/py/lexer.c
@@ -137,23 +137,18 @@ STATIC void next_char(mp_lexer_t *lex) {
lex->chr1 = lex->chr2;
lex->chr2 = lex->reader.readbyte(lex->reader.data);
- if (lex->chr0 == '\r') {
+ if (lex->chr1 == '\r') {
// CR is a new line, converted to LF
- lex->chr0 = '\n';
- if (lex->chr1 == '\n') {
- // CR LF is a single new line
- lex->chr1 = lex->chr2;
+ lex->chr1 = '\n';
+ if (lex->chr2 == '\n') {
+ // CR LF is a single new line, throw out the extra LF
lex->chr2 = lex->reader.readbyte(lex->reader.data);
}
}
- if (lex->chr2 == MP_LEXER_EOF) {
- // EOF, check if we need to insert a newline at end of file
- if (lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') {
- // if lex->chr1 == '\r' then this makes a CR LF which will be converted to LF above
- // otherwise it just inserts a LF
- lex->chr2 = '\n';
- }
+ // check if we need to insert a newline at end of file
+ if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') {
+ lex->chr2 = '\n';
}
}
From 760aa0996f29ae33a36c48128dd8f74597b877ad Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Tue, 9 May 2017 13:17:04 -0700
Subject: [PATCH 184/826] tests/basics/lexer: Add line continuation tests for
lexer.
Tests for an issue with line continuation failing in paste mode due to the
lexer only checking for \n in the "following" character position, before
next_char() has had a chance to convert \r and \r\n to \n.
---
tests/basics/lexer.py | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tests/basics/lexer.py b/tests/basics/lexer.py
index f1602f5de..244de8cb9 100644
--- a/tests/basics/lexer.py
+++ b/tests/basics/lexer.py
@@ -27,6 +27,14 @@
print(eval("12\r"))
print(eval("123\r"))
+# line continuation
+print(eval("'123' \\\r '456'"))
+print(eval("'123' \\\n '456'"))
+print(eval("'123' \\\r\n '456'"))
+print(eval("'123'\\\r'456'"))
+print(eval("'123'\\\n'456'"))
+print(eval("'123'\\\r\n'456'"))
+
# backslash used to escape a line-break in a string
print('a\
b')
From 0987ad5e30239c642fb6f16508bac6b6b9a4a46b Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Thu, 11 May 2017 23:39:34 +0300
Subject: [PATCH 185/826] esp8266/esp8266.ld, esp8266_ota.ld: Grow main
firmware size by 32KB.
To accommodate both system and user frozen modules.
---
esp8266/esp8266.ld | 2 +-
esp8266/esp8266_ota.ld | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld
index 960c75179..deeb82b45 100644
--- a/esp8266/esp8266.ld
+++ b/esp8266/esp8266.ld
@@ -5,7 +5,7 @@ MEMORY
dport0_0_seg : org = 0x3ff00000, len = 0x10
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
- irom0_0_seg : org = 0x40209000, len = 0x87000
+ irom0_0_seg : org = 0x40209000, len = 0x8f000
}
/* define common sections and symbols */
diff --git a/esp8266/esp8266_ota.ld b/esp8266/esp8266_ota.ld
index d9afaa8f2..604480a0a 100644
--- a/esp8266/esp8266_ota.ld
+++ b/esp8266/esp8266_ota.ld
@@ -6,7 +6,7 @@ MEMORY
dram0_0_seg : org = 0x3ffe8000, len = 0x14000
iram1_0_seg : org = 0x40100000, len = 0x8000
/* 0x3c000 is size of bootloader, 0x9000 is size of packed RAM segments */
- irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x87000
+ irom0_0_seg : org = 0x40200000 + 0x3c000 + 0x9000, len = 0x8f000
}
/* define common sections and symbols */
From 3e05df7fd1038d1e733559a7c180ac7da20b2aa6 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 15:58:19 +0300
Subject: [PATCH 186/826] esp8266/modesp: flash_user_start: Use value from
linker script.
Make esp8266_common.ld export size reserved to all code segments, and use
that in esp.flash_user_start() implementation.
---
esp8266/esp8266_common.ld | 2 ++
esp8266/modesp.c | 8 +++-----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/esp8266/esp8266_common.ld b/esp8266/esp8266_common.ld
index 1da835681..bc983df70 100644
--- a/esp8266/esp8266_common.ld
+++ b/esp8266/esp8266_common.ld
@@ -19,6 +19,8 @@ EXTERN(_KernelExceptionVector)
EXTERN(_NMIExceptionVector)
EXTERN(_UserExceptionVector)
+_firmware_size = ORIGIN(irom0_0_seg) + LENGTH(irom0_0_seg) - 0x40200000;
+
PROVIDE(_memmap_vecbase_reset = 0x40000000);
/* Various memory-map dependent cache attribute settings: */
diff --git a/esp8266/modesp.c b/esp8266/modesp.c
index 432fd5ac3..5eaae27d6 100644
--- a/esp8266/modesp.c
+++ b/esp8266/modesp.c
@@ -159,12 +159,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_size_obj, esp_flash_size);
// we assume there's a yaota8266 bootloader.
#define IS_OTA_FIRMWARE() ((*(uint32_t*)0x40200000 & 0xff00) == 0x100)
+extern byte _firmware_size[];
+
STATIC mp_obj_t esp_flash_user_start(void) {
- if (IS_OTA_FIRMWARE()) {
- return MP_OBJ_NEW_SMALL_INT(0x3c000 + 0x90000);
- } else {
- return MP_OBJ_NEW_SMALL_INT(0x90000);
- }
+ return MP_OBJ_NEW_SMALL_INT((uint32_t)_firmware_size);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(esp_flash_user_start_obj, esp_flash_user_start);
From 5f7ce2a1ca65840ef95d0c044088bc38453b7471 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 16:08:54 +0300
Subject: [PATCH 187/826] esp8266/modules/flashbdev: Reserve one sector for
native code storage.
---
esp8266/modules/flashbdev.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/esp8266/modules/flashbdev.py b/esp8266/modules/flashbdev.py
index 8f8df0b64..40ba655c6 100644
--- a/esp8266/modules/flashbdev.py
+++ b/esp8266/modules/flashbdev.py
@@ -3,7 +3,7 @@
class FlashBdev:
SEC_SIZE = 4096
- RESERVED_SECS = 0
+ RESERVED_SECS = 1
START_SEC = esp.flash_user_start() // SEC_SIZE + RESERVED_SECS
NUM_BLK = 0x6b - RESERVED_SECS
From e9308c189af388525becbcd42b81ea6d37738135 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 17:57:23 +0300
Subject: [PATCH 188/826] esp8266/scripts: Move drivers/modules to modules/
(frozen bytecode).
---
esp8266/{scripts => modules}/apa102.py | 0
esp8266/{scripts => modules}/dht.py | 0
esp8266/{scripts => modules}/neopixel.py | 0
esp8266/{scripts => modules}/ntptime.py | 0
4 files changed, 0 insertions(+), 0 deletions(-)
rename esp8266/{scripts => modules}/apa102.py (100%)
rename esp8266/{scripts => modules}/dht.py (100%)
rename esp8266/{scripts => modules}/neopixel.py (100%)
rename esp8266/{scripts => modules}/ntptime.py (100%)
diff --git a/esp8266/scripts/apa102.py b/esp8266/modules/apa102.py
similarity index 100%
rename from esp8266/scripts/apa102.py
rename to esp8266/modules/apa102.py
diff --git a/esp8266/scripts/dht.py b/esp8266/modules/dht.py
similarity index 100%
rename from esp8266/scripts/dht.py
rename to esp8266/modules/dht.py
diff --git a/esp8266/scripts/neopixel.py b/esp8266/modules/neopixel.py
similarity index 100%
rename from esp8266/scripts/neopixel.py
rename to esp8266/modules/neopixel.py
diff --git a/esp8266/scripts/ntptime.py b/esp8266/modules/ntptime.py
similarity index 100%
rename from esp8266/scripts/ntptime.py
rename to esp8266/modules/ntptime.py
From ddf0b7dbc3843f2025da5a4cc1b588340c4aad13 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 17:58:50 +0300
Subject: [PATCH 189/826] esp8266/scripts: Move initsetup & port_diag tools to
modules/.
---
esp8266/{scripts => modules}/inisetup.py | 0
esp8266/{scripts => modules}/port_diag.py | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename esp8266/{scripts => modules}/inisetup.py (100%)
rename esp8266/{scripts => modules}/port_diag.py (100%)
diff --git a/esp8266/scripts/inisetup.py b/esp8266/modules/inisetup.py
similarity index 100%
rename from esp8266/scripts/inisetup.py
rename to esp8266/modules/inisetup.py
diff --git a/esp8266/scripts/port_diag.py b/esp8266/modules/port_diag.py
similarity index 100%
rename from esp8266/scripts/port_diag.py
rename to esp8266/modules/port_diag.py
From 5c312861a611df156f2fb2b0811f3713df2edb14 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 18:31:22 +0300
Subject: [PATCH 190/826] unix/Makefile: Enable frozen bytecode modules dir.
---
unix/Makefile | 1 +
1 file changed, 1 insertion(+)
diff --git a/unix/Makefile b/unix/Makefile
index e08e817bc..830f30742 100644
--- a/unix/Makefile
+++ b/unix/Makefile
@@ -2,6 +2,7 @@
include ../py/mkenv.mk
FROZEN_DIR = scripts
+FROZEN_MPY_DIR = modules
# define main target
PROG = micropython
From a4e38db30dacf6bd2d0b5c9221ca6efef7202a92 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 18:32:25 +0300
Subject: [PATCH 191/826] unix: Move upip to frozen bytecode dir.
For x86_64 build, this saves only 128 bytes on the final executable
size, but still an improvement.
---
unix/{scripts => modules}/upip.py | 0
unix/{scripts => modules}/upip_utarfile.py | 0
2 files changed, 0 insertions(+), 0 deletions(-)
rename unix/{scripts => modules}/upip.py (100%)
rename unix/{scripts => modules}/upip_utarfile.py (100%)
diff --git a/unix/scripts/upip.py b/unix/modules/upip.py
similarity index 100%
rename from unix/scripts/upip.py
rename to unix/modules/upip.py
diff --git a/unix/scripts/upip_utarfile.py b/unix/modules/upip_utarfile.py
similarity index 100%
rename from unix/scripts/upip_utarfile.py
rename to unix/modules/upip_utarfile.py
From 1659c0645d27bba297813889fc7d2c118706c74f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 21:54:32 +0300
Subject: [PATCH 192/826] zephyr/modusocket: Add dummy setsockopt()
implementation.
---
zephyr/modusocket.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 92d45a0fe..ad3a7e23b 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -450,6 +450,13 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_recv_obj, socket_recv);
+STATIC mp_obj_t socket_setsockopt(size_t n_args, const mp_obj_t *args) {
+ (void)n_args; // always 4
+ mp_warning("setsockopt() not implemented");
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(socket_setsockopt_obj, 4, 4, socket_setsockopt);
+
STATIC mp_obj_t socket_makefile(size_t n_args, const mp_obj_t *args) {
(void)n_args;
return args[0];
@@ -475,6 +482,7 @@ STATIC const mp_map_elem_t socket_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_accept), (mp_obj_t)&socket_accept_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_send), (mp_obj_t)&socket_send_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_recv), (mp_obj_t)&socket_recv_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_setsockopt), (mp_obj_t)&socket_setsockopt_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&mp_stream_read_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_readinto), (mp_obj_t)&mp_stream_readinto_obj },
From 50d7ed325af28317c4ee8d771f93e8602fac1e19 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 21:55:42 +0300
Subject: [PATCH 193/826] zephyr/modusocket: Add SOL_SOCKET and SO_REUSEADDR
constants.
---
zephyr/modusocket.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index ad3a7e23b..0cacd7179 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -517,6 +517,9 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
From d57c6564dc270f52e131162f682c706f44696a16 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 21:58:51 +0300
Subject: [PATCH 194/826] zephyr/prj_qemu_x86.conf: Bump RAM size to 320K.
---
zephyr/prj_qemu_x86.conf | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/zephyr/prj_qemu_x86.conf b/zephyr/prj_qemu_x86.conf
index cb90834ac..ef60cfec9 100644
--- a/zephyr/prj_qemu_x86.conf
+++ b/zephyr/prj_qemu_x86.conf
@@ -3,4 +3,4 @@
CONFIG_NET_SLIP_TAP=y
# Default RAM easily overflows with uPy and networking
-CONFIG_RAM_SIZE=256
+CONFIG_RAM_SIZE=320
From 5383a50072dcd9827e601add56d20b86b9dd9e27 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Fri, 12 May 2017 22:05:07 +0300
Subject: [PATCH 195/826] zephyr/README: Update to require Zephyr 1.8.
There're a lot of changes and fixes in 1.8 regarding IP stack,
incompatible with previous Zephyr versions, so supporting them
doesn't make sense.
This is the last commit which should build with Zephyr 1.7.
---
zephyr/README.md | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/zephyr/README.md b/zephyr/README.md
index 4fbf3d401..018b4ce71 100644
--- a/zephyr/README.md
+++ b/zephyr/README.md
@@ -1,20 +1,19 @@
MicroPython port to Zephyr RTOS
===============================
-This is an initial port of MicroPython to Zephyr RTOS
+This is an work-in-progress port of MicroPython to Zephyr RTOS
(http://zephyrproject.org).
-The port integrates well with Zephyr build system, using the latest
-features which will be available in 1.6.0, and thus requires Zephyr
-master to build against. All boards supported by Zephyr (with standard
-level of feature support, like UART console) should work with
-MicroPython (but not all were tested).
+This port requires Zephyr version 1.8 or higher. All boards supported
+by Zephyr (with standard level of features support, like UART console)
+should work with MicroPython (but not all were tested).
Features supported at this time:
* REPL (interactive prompt) over Zephyr UART console.
* `utime` module for time measurements and delays.
* `machine.Pin` class for GPIO control.
+* `usocket` module for networking (IPv4/IPv6).
* "Frozen modules" support to allow to bundle Python modules together
with firmware. Including complete applications, including with
run-on-boot capability.
@@ -97,10 +96,10 @@ MicroPython is committed to maintain minimal binary size for Zephyr port
below 128KB, as long as Zephyr project is committed to maintain stable
minimal size of their kernel (which they appear to be). Note that at such
size, there is no support for any Zephyr features beyond REPL over UART,
-and only very minimal set of builtin Python modules. Thus, this build
-is more suitable for code size control and quick demonstrations on
-smaller systems. It's also suitable for careful enabling of features one
-by one to achieve needed functionality and code size. This is in a
+and only very minimal set of builtin Python modules is available. Thus,
+this build is more suitable for code size control and quick demonstrations
+on smaller systems. It's also suitable for careful enabling of features
+one by one to achieve needed functionality and code size. This is in the
contrast to the "default" build, which may get more and more features
enabled over time.
From ec534609f665cb791b8fc1eae1a44e514c297659 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 13 May 2017 10:08:13 +1000
Subject: [PATCH 196/826] tools/mpy-tool.py: Use MP_ROM_xxx macros to support
nanbox builds.
---
tools/mpy-tool.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index aff4fd210..483a992db 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -332,25 +332,25 @@ def freeze(self, parent_name):
raise FreezeError(self, 'freezing of object %r is not implemented' % (obj,))
# generate constant table
- print('STATIC const mp_uint_t const_table_data_%s[%u] = {'
+ print('STATIC const mp_rom_obj_t const_table_data_%s[%u] = {'
% (self.escaped_name, len(self.qstrs) + len(self.objs) + len(self.raw_codes)))
for qst in self.qstrs:
- print(' (mp_uint_t)MP_OBJ_NEW_QSTR(%s),' % global_qstrs[qst].qstr_id)
+ print(' MP_ROM_QSTR(%s),' % global_qstrs[qst].qstr_id)
for i in range(len(self.objs)):
if type(self.objs[i]) is float:
print('#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_A || MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_B')
- print(' (mp_uint_t)&const_obj_%s_%u,' % (self.escaped_name, i))
+ print(' MP_ROM_PTR(&const_obj_%s_%u),' % (self.escaped_name, i))
print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
n = struct.unpack('
Date: Fri, 12 May 2017 20:37:49 +0200
Subject: [PATCH 197/826] esp8266/ets_alt_task.c: Prevent spurious large
increment of ticks_ms()
This happened when the overflow counter for ticks_ms() was interrupted
by an external hard interrupt (issue #3076).
---
esp8266/ets_alt_task.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/esp8266/ets_alt_task.c b/esp8266/ets_alt_task.c
index 6434f2366..ff7dba186 100644
--- a/esp8266/ets_alt_task.c
+++ b/esp8266/ets_alt_task.c
@@ -120,11 +120,13 @@ bool ets_loop_iter(void) {
}
// handle overflow of system microsecond counter
+ ets_intr_lock();
uint32_t system_time_cur = system_get_time();
if (system_time_cur < system_time_prev) {
system_time_high_word += 1; // record overflow of low 32-bits
}
system_time_prev = system_time_cur;
+ ets_intr_unlock();
//static unsigned cnt;
bool progress = false;
From f95e4e77823919dfe82b6711f1d25d2d8c5008fc Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 13 May 2017 18:58:46 +1000
Subject: [PATCH 198/826] extmod/vfs_fat_misc: Remove dot-dirs filter since
FatFS already does it.
---
extmod/vfs_fat_misc.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/extmod/vfs_fat_misc.c b/extmod/vfs_fat_misc.c
index 5b906189f..7c16db7e5 100644
--- a/extmod/vfs_fat_misc.c
+++ b/extmod/vfs_fat_misc.c
@@ -52,10 +52,8 @@ STATIC mp_obj_t mp_vfs_fat_ilistdir_it_iternext(mp_obj_t self_in) {
// stop on error or end of dir
break;
}
- if (fn[0] == '.' && (fn[1] == 0 || (fn[1] == '.' && fn[2] == 0))) {
- // skip . and ..
- continue;
- }
+
+ // Note that FatFS already filters . and .., so we don't need to
// make 3-tuple with info about this entry
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(3, NULL));
From cda09727b451b6b928cc0129c4be7d3127f1aaad Mon Sep 17 00:00:00 2001
From: Damien George
Date: Sat, 13 May 2017 19:10:15 +1000
Subject: [PATCH 199/826] tests/extmod/vfs_fat: Add test for ilistdir of a
non-existent directory.
---
tests/extmod/vfs_fat_ramdisk.py | 6 ++++++
tests/extmod/vfs_fat_ramdisk.py.exp | 1 +
2 files changed, 7 insertions(+)
diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py
index 89b40e3a2..fe72a8bef 100644
--- a/tests/extmod/vfs_fat_ramdisk.py
+++ b/tests/extmod/vfs_fat_ramdisk.py
@@ -93,3 +93,9 @@ def ioctl(self, op, arg):
vfs = uos.VfsFat(bdev)
print(list(vfs.ilistdir(b"")))
+
+# list a non-existent directory
+try:
+ vfs.ilistdir(b"no_exist")
+except OSError as e:
+ print('ENOENT:', e.args[0] == uerrno.ENOENT)
diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp
index 6298a7efd..ccd0f7134 100644
--- a/tests/extmod/vfs_fat_ramdisk.py.exp
+++ b/tests/extmod/vfs_fat_ramdisk.py.exp
@@ -13,3 +13,4 @@ getcwd: /foo_dir
True
getcwd: /
[(b'foo_file.txt', 32768, 0), (b'foo_dir', 16384, 0)]
+ENOENT: True
From 054a381d7c9f3f5b706475a934299c541efdd746 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 14:13:24 +0300
Subject: [PATCH 200/826] tests/extmod/vfs_fat_more: Make skippable is uos is
not available.
Fixes Zephyr tests.
---
tests/extmod/vfs_fat_more.py | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/tests/extmod/vfs_fat_more.py b/tests/extmod/vfs_fat_more.py
index 6c2df528f..dacb21553 100644
--- a/tests/extmod/vfs_fat_more.py
+++ b/tests/extmod/vfs_fat_more.py
@@ -1,10 +1,15 @@
import sys
import uerrno
try:
- import uos_vfs as uos
- open = uos.vfs_open
+ try:
+ import uos_vfs as uos
+ open = uos.vfs_open
+ except ImportError:
+ import uos
except ImportError:
- import uos
+ print("SKIP")
+ sys.exit()
+
try:
uos.VfsFat
except AttributeError:
From c022c9a2f0ea3a707b6993daaffe2bcddd520da2 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 15:22:22 +0300
Subject: [PATCH 201/826] zephyr/modusocket: Wrap pkt_get_info() call.
The most important info it returns are numbers of free buffers
in different pools (rx/tx packet headers, data fragments).
---
zephyr/modusocket.c | 14 ++++++++++++++
zephyr/prj_base.conf | 3 +++
2 files changed, 17 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 0cacd7179..c48606b76 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -507,6 +507,18 @@ STATIC const mp_obj_type_t socket_type = {
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
+STATIC mp_obj_t nbuf_get_info(void) {
+ struct net_buf_pool *rx, *tx, *rx_data, *tx_data;
+ net_nbuf_get_info(&rx, &tx, &rx_data, &tx_data);
+ mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
+ t->items[0] = MP_OBJ_NEW_SMALL_INT(rx->avail_count);
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(tx->avail_count);
+ t->items[2] = MP_OBJ_NEW_SMALL_INT(rx_data->avail_count);
+ t->items[3] = MP_OBJ_NEW_SMALL_INT(tx_data->avail_count);
+ return MP_OBJ_FROM_PTR(t);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(nbuf_get_info_obj, nbuf_get_info);
+
STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
// objects
@@ -520,6 +532,8 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
+
+ { MP_OBJ_NEW_QSTR(MP_QSTR_nbuf_get_info), (mp_obj_t)&nbuf_get_info_obj },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
diff --git a/zephyr/prj_base.conf b/zephyr/prj_base.conf
index 1a0b40711..97a78fa77 100644
--- a/zephyr/prj_base.conf
+++ b/zephyr/prj_base.conf
@@ -17,6 +17,9 @@ CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_NBUF_RX_COUNT=5
+# Required for usocket.pkt_get_info()
+CONFIG_NET_BUF_POOL_USAGE=y
+
# Uncomment to enable "INFO" level net_buf logging
#CONFIG_NET_LOG=y
#CONFIG_NET_DEBUG_NET_BUF=y
From 39d3335606e912dee16ee29cd481427f884dbf18 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 15:47:47 +0300
Subject: [PATCH 202/826] zephyr/modusocket: Update for net_pkt refactor.
---
zephyr/modusocket.c | 113 +++++++++++++++++++++-----------------------
1 file changed, 54 insertions(+), 59 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index c48606b76..eec4fa219 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -35,7 +35,7 @@
// Zephyr's generated version header
#include
#include
-#include
+#include
#define DEBUG 0
#if DEBUG // print debugging info
@@ -51,7 +51,7 @@ typedef struct _socket_obj_t {
struct k_fifo recv_q;
struct k_fifo accept_q;
};
- struct net_buf *cur_buf;
+ struct net_pkt *cur_pkt;
#define STATE_NEW 0
#define STATE_CONNECTING 1
@@ -115,12 +115,12 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
}
// Copy data from Zephyr net_buf chain into linear buffer.
-// We don't use net_nbuf_read(), because it's weird (e.g., we'd like to
-// free processed data fragment ASAP, while net_nbuf_read() holds onto
+// We don't use net_pkt_read(), because it's weird (e.g., we'd like to
+// free processed data fragment ASAP, while net_pkt_read() holds onto
// the whole fragment chain to do its deeds, and that's minor comparing
// to the fact that it copies data byte by byte).
-static char *net_buf_gather(struct net_buf *buf, char *to, unsigned max_len) {
- struct net_buf *tmp = buf->frags;
+static char *net_pkt_gather(struct net_pkt *pkt, char *to, unsigned max_len) {
+ struct net_buf *tmp = pkt->frags;
while (tmp && max_len) {
unsigned len = tmp->len;
@@ -130,48 +130,46 @@ static char *net_buf_gather(struct net_buf *buf, char *to, unsigned max_len) {
memcpy(to, tmp->data, len);
to += len;
max_len -= len;
- tmp = net_buf_frag_del(buf, tmp);
+ tmp = net_pkt_frag_del(pkt, NULL, tmp);
}
return to;
}
// Callback for incoming packets.
-static void sock_received_cb(struct net_context *context, struct net_buf *net_buf, int status, void *user_data) {
+static void sock_received_cb(struct net_context *context, struct net_pkt *pkt, int status, void *user_data) {
socket_obj_t *socket = (socket_obj_t*)user_data;
- DEBUG_printf("recv cb: context: %p, status: %d, buf: %p", context, status, net_buf);
- if (net_buf) {
- DEBUG_printf(" (sz=%d, l=%d), token: %p", net_buf->size, net_buf->len, net_nbuf_token(net_buf));
+ DEBUG_printf("recv cb: context: %p, status: %d, pkt: %p", context, status, pkt);
+ if (pkt) {
+ DEBUG_printf(" (appdatalen=%d), token: %p", pkt->appdatalen, net_pkt_token(pkt));
}
DEBUG_printf("\n");
#if DEBUG > 1
- net_nbuf_print_frags(net_buf);
+ net_pkt_print_frags(pkt);
#endif
// if net_buf == NULL, EOF
- if (net_buf == NULL) {
- struct net_buf *last_buf = _k_fifo_peek_tail(&socket->recv_q);
- if (last_buf == NULL) {
+ if (pkt == NULL) {
+ struct net_pkt *last_pkt = _k_fifo_peek_tail(&socket->recv_q);
+ if (last_pkt == NULL) {
socket->state = STATE_PEER_CLOSED;
DEBUG_printf("Marked socket %p as peer-closed\n", socket);
} else {
// We abuse "buf_sent" flag to store EOF flag
- net_nbuf_set_buf_sent(last_buf, true);
- DEBUG_printf("Set EOF flag on %p\n", last_buf);
+ net_pkt_set_sent(last_pkt, true);
+ DEBUG_printf("Set EOF flag on %p\n", last_pkt);
}
return;
}
// Make sure that "EOF flag" is not set
- net_nbuf_set_buf_sent(net_buf, false);
+ net_pkt_set_sent(pkt, false);
// We don't care about packet header, so get rid of it asap
- unsigned header_len = net_nbuf_appdata(net_buf) - net_buf->frags->data;
- net_buf_pull(net_buf->frags, header_len);
+ unsigned header_len = net_pkt_appdata(pkt) - pkt->frags->data;
+ net_buf_pull(pkt->frags, header_len);
- // net_buf->frags will be overwritten by fifo, so save it
- net_nbuf_set_token(net_buf, net_buf->frags);
- k_fifo_put(&socket->recv_q, net_buf);
+ k_fifo_put(&socket->recv_q, pkt);
}
// Callback for incoming connections.
@@ -187,7 +185,7 @@ socket_obj_t *socket_new(void) {
socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
socket->base.type = (mp_obj_t)&socket_type;
k_fifo_init(&socket->recv_q);
- socket->cur_buf = NULL;
+ socket->cur_pkt = NULL;
socket->state = STATE_NEW;
return socket;
}
@@ -309,7 +307,7 @@ STATIC mp_uint_t sock_write(mp_obj_t self_in, const void *buf, mp_uint_t size, i
return MP_STREAM_ERROR;
}
- struct net_buf *send_buf = net_nbuf_get_tx(socket->ctx, K_FOREVER);
+ struct net_pkt *send_pkt = net_pkt_get_tx(socket->ctx, K_FOREVER);
unsigned len = net_if_get_mtu(net_context_get_iface(socket->ctx));
// Arbitrary value to account for protocol headers
@@ -318,11 +316,11 @@ STATIC mp_uint_t sock_write(mp_obj_t self_in, const void *buf, mp_uint_t size, i
len = size;
}
- if (!net_nbuf_append(send_buf, len, buf, K_FOREVER)) {
- len = net_buf_frags_len(send_buf);
+ if (!net_pkt_append(send_pkt, len, buf, K_FOREVER)) {
+ len = net_pkt_get_len(send_pkt);
}
- int err = net_context_send(send_buf, /*cb*/NULL, K_FOREVER, NULL, NULL);
+ int err = net_context_send(send_pkt, /*cb*/NULL, K_FOREVER, NULL, NULL);
if (err < 0) {
*errcode = -err;
return MP_STREAM_ERROR;
@@ -356,41 +354,37 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
if (sock_type == SOCK_DGRAM) {
- struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
- // Restore ->frags overwritten by fifo
- net_buf->frags = net_nbuf_token(net_buf);
+ struct net_pkt *pkt = k_fifo_get(&socket->recv_q, K_FOREVER);
- recv_len = net_nbuf_appdatalen(net_buf);
- DEBUG_printf("recv: net_buf=%p, appdatalen: %d\n", net_buf, recv_len);
+ recv_len = net_pkt_appdatalen(pkt);
+ DEBUG_printf("recv: pkt=%p, appdatalen: %d\n", pkt, recv_len);
if (recv_len > max_len) {
recv_len = max_len;
}
- net_buf_gather(net_buf, buf, recv_len);
- net_nbuf_unref(net_buf);
+ net_pkt_gather(pkt, buf, recv_len);
+ net_pkt_unref(pkt);
} else if (sock_type == SOCK_STREAM) {
do {
- if (socket->cur_buf == NULL) {
+ if (socket->cur_pkt == NULL) {
if (socket->state == STATE_PEER_CLOSED) {
return 0;
}
- DEBUG_printf("TCP recv: no cur_buf, getting\n");
- struct net_buf *net_buf = k_fifo_get(&socket->recv_q, K_FOREVER);
- // Restore ->frags overwritten by fifo
- net_buf->frags = net_nbuf_token(net_buf);
+ DEBUG_printf("TCP recv: no cur_pkt, getting\n");
+ struct net_pkt *pkt = k_fifo_get(&socket->recv_q, K_FOREVER);
- DEBUG_printf("TCP recv: new cur_buf: %p\n", net_buf);
- socket->cur_buf = net_buf;
+ DEBUG_printf("TCP recv: new cur_pkt: %p\n", pkt);
+ socket->cur_pkt = pkt;
}
- struct net_buf *frag = socket->cur_buf->frags;
+ struct net_buf *frag = socket->cur_pkt->frags;
if (frag == NULL) {
- printf("net_buf has empty fragments on start!\n");
+ printf("net_pkt has empty fragments on start!\n");
assert(0);
}
@@ -406,20 +400,20 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
if (recv_len != frag_len) {
net_buf_pull(frag, recv_len);
} else {
- frag = net_buf_frag_del(socket->cur_buf, frag);
+ frag = net_pkt_frag_del(socket->cur_pkt, NULL, frag);
if (frag == NULL) {
- DEBUG_printf("Finished processing net_buf %p\n", socket->cur_buf);
- // If "buf_sent" flag was set, it's last packet and we reached EOF
- if (net_nbuf_buf_sent(socket->cur_buf)) {
+ DEBUG_printf("Finished processing pkt %p\n", socket->cur_pkt);
+ // If "sent" flag was set, it's last packet and we reached EOF
+ if (net_pkt_sent(socket->cur_pkt)) {
socket->state = STATE_PEER_CLOSED;
}
- net_nbuf_unref(socket->cur_buf);
- socket->cur_buf = NULL;
+ net_pkt_unref(socket->cur_pkt);
+ socket->cur_pkt = NULL;
}
}
// Keep repeating while we're getting empty fragments
- // Zephyr IP stack appears to feed empty net_buf's with empty
- // frags for various TCP control packets.
+ // Zephyr IP stack appears to have fed empty net_buf's with empty
+ // frags for various TCP control packets - in previous versions.
} while (recv_len == 0);
}
@@ -507,17 +501,18 @@ STATIC const mp_obj_type_t socket_type = {
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
-STATIC mp_obj_t nbuf_get_info(void) {
- struct net_buf_pool *rx, *tx, *rx_data, *tx_data;
- net_nbuf_get_info(&rx, &tx, &rx_data, &tx_data);
+STATIC mp_obj_t pkt_get_info(void) {
+ struct k_mem_slab *rx, *tx;
+ struct net_buf_pool *rx_data, *tx_data;
+ net_pkt_get_info(&rx, &tx, &rx_data, &tx_data);
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(4, NULL));
- t->items[0] = MP_OBJ_NEW_SMALL_INT(rx->avail_count);
- t->items[1] = MP_OBJ_NEW_SMALL_INT(tx->avail_count);
+ t->items[0] = MP_OBJ_NEW_SMALL_INT(k_mem_slab_num_free_get(rx));
+ t->items[1] = MP_OBJ_NEW_SMALL_INT(k_mem_slab_num_free_get(tx));
t->items[2] = MP_OBJ_NEW_SMALL_INT(rx_data->avail_count);
t->items[3] = MP_OBJ_NEW_SMALL_INT(tx_data->avail_count);
return MP_OBJ_FROM_PTR(t);
}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(nbuf_get_info_obj, nbuf_get_info);
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(pkt_get_info_obj, pkt_get_info);
STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_usocket) },
@@ -533,7 +528,7 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_nbuf_get_info), (mp_obj_t)&nbuf_get_info_obj },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_pkt_get_info), (mp_obj_t)&pkt_get_info_obj },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
From 69f0b4ad5bac70d3be5cc674d6e0a5f188c353bb Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 16:05:10 +0300
Subject: [PATCH 203/826] zephyr/modusocket: Switch to net_pkt_append()
returning length.
Requires patch in review.
---
zephyr/modusocket.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index eec4fa219..d40b4887c 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -316,9 +316,9 @@ STATIC mp_uint_t sock_write(mp_obj_t self_in, const void *buf, mp_uint_t size, i
len = size;
}
- if (!net_pkt_append(send_pkt, len, buf, K_FOREVER)) {
- len = net_pkt_get_len(send_pkt);
- }
+ // TODO: Return value of 0 is a hard case (as we wait forever, should
+ // not happen).
+ len = net_pkt_append(send_pkt, len, buf, K_FOREVER);
int err = net_context_send(send_pkt, /*cb*/NULL, K_FOREVER, NULL, NULL);
if (err < 0) {
From 86c4544ef9af169d590048d499edfd3e255e16d6 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 16:22:14 +0300
Subject: [PATCH 204/826] zephyr/modusocket: If there're no packets in recv_q,
cancel waiter.
This solves a case when socker_read() has blocked on fifo, and then peer
closed event arrives.
---
zephyr/modusocket.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index d40b4887c..daaa15748 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -153,6 +153,7 @@ static void sock_received_cb(struct net_context *context, struct net_pkt *pkt, i
struct net_pkt *last_pkt = _k_fifo_peek_tail(&socket->recv_q);
if (last_pkt == NULL) {
socket->state = STATE_PEER_CLOSED;
+ k_fifo_cancel_wait(&socket->recv_q);
DEBUG_printf("Marked socket %p as peer-closed\n", socket);
} else {
// We abuse "buf_sent" flag to store EOF flag
@@ -378,6 +379,11 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
DEBUG_printf("TCP recv: no cur_pkt, getting\n");
struct net_pkt *pkt = k_fifo_get(&socket->recv_q, K_FOREVER);
+ if (pkt == NULL) {
+ DEBUG_printf("TCP recv: NULL return from fifo\n");
+ continue;
+ }
+
DEBUG_printf("TCP recv: new cur_pkt: %p\n", pkt);
socket->cur_pkt = pkt;
}
From 0c57979ce28712422d996fb5291de85e8f7f3be8 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sat, 13 May 2017 16:42:35 +0300
Subject: [PATCH 205/826] zephyr/modusocket: Implement getaddrinfo().
---
zephyr/modusocket.c | 86 ++++++++++++++++++++++++++++++++++++++++++++
zephyr/prj_base.conf | 6 ++++
2 files changed, 92 insertions(+)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index daaa15748..aa638d413 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#define DEBUG 0
#if DEBUG // print debugging info
@@ -114,6 +115,27 @@ STATIC void parse_inet_addr(socket_obj_t *socket, mp_obj_t addr_in, struct socka
sockaddr_in->sin_port = htons(mp_obj_get_int(addr_items[1]));
}
+STATIC mp_obj_t format_inet_addr(struct sockaddr *addr, mp_obj_t port) {
+ // We employ the fact that port and address offsets are the same for IPv4 & IPv6
+ struct sockaddr_in6 *sockaddr_in6 = (struct sockaddr_in6*)addr;
+ char buf[40];
+ net_addr_ntop(addr->family, &sockaddr_in6->sin6_addr, buf, sizeof(buf));
+ mp_obj_tuple_t *tuple = mp_obj_new_tuple(addr->family == AF_INET ? 2 : 4, NULL);
+
+ tuple->items[0] = mp_obj_new_str(buf, strlen(buf), false);
+ // We employ the fact that port offset is the same for IPv4 & IPv6
+ // not filled in
+ //tuple->items[1] = mp_obj_new_int(ntohs(((struct sockaddr_in*)addr)->sin_port));
+ tuple->items[1] = port;
+
+ if (addr->family == AF_INET6) {
+ tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0); // flow_info
+ tuple->items[3] = MP_OBJ_NEW_SMALL_INT(sockaddr_in6->sin6_scope_id);
+ }
+
+ return MP_OBJ_FROM_PTR(tuple);
+}
+
// Copy data from Zephyr net_buf chain into linear buffer.
// We don't use net_pkt_read(), because it's weird (e.g., we'd like to
// free processed data fragment ASAP, while net_pkt_read() holds onto
@@ -507,6 +529,69 @@ STATIC const mp_obj_type_t socket_type = {
.locals_dict = (mp_obj_t)&socket_locals_dict,
};
+//
+// getaddrinfo() implementation
+//
+
+typedef struct _getaddrinfo_state_t {
+ mp_obj_t result;
+ struct k_sem sem;
+ mp_obj_t port;
+} getaddrinfo_state_t;
+
+void dns_resolve_cb(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data) {
+ getaddrinfo_state_t *state = user_data;
+
+ if (info == NULL) {
+ k_sem_give(&state->sem);
+ return;
+ }
+
+ mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(info->ai_family);
+ // info->ai_socktype not filled
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM);
+ // info->ai_protocol not filled
+ tuple->items[2] = MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP);
+ tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
+ tuple->items[4] = format_inet_addr(&info->ai_addr, state->port);
+ mp_obj_list_append(state->result, MP_OBJ_FROM_PTR(tuple));
+}
+
+STATIC mp_obj_t mod_getaddrinfo(size_t n_args, const mp_obj_t *args) {
+ mp_obj_t host_in = args[0], port_in = args[1];
+ const char *host = mp_obj_str_get_str(host_in);
+ mp_int_t family = 0;
+ if (n_args > 2) {
+ family = mp_obj_get_int(args[2]);
+ }
+
+ getaddrinfo_state_t state;
+ // Just validate that it's int
+ (void)mp_obj_get_int(port_in);
+ state.port = port_in;
+ state.result = mp_obj_new_list(0, NULL);
+ k_sem_init(&state.sem, 0, UINT_MAX);
+
+ int status;
+ for (int i = 2; i--;) {
+ int type = (family != AF_INET6 ? DNS_QUERY_TYPE_A : DNS_QUERY_TYPE_AAAA);
+ status = dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000);
+ if (status < 0) {
+ mp_raise_OSError(status);
+ }
+ k_sem_take(&state.sem, K_FOREVER);
+ if (family != 0) {
+ break;
+ }
+ family = AF_INET6;
+ }
+
+ return state.result;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_getaddrinfo_obj, 2, 3, mod_getaddrinfo);
+
+
STATIC mp_obj_t pkt_get_info(void) {
struct k_mem_slab *rx, *tx;
struct net_buf_pool *rx_data, *tx_data;
@@ -534,6 +619,7 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOL_SOCKET), MP_OBJ_NEW_SMALL_INT(1) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_SO_REUSEADDR), MP_OBJ_NEW_SMALL_INT(2) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_getaddrinfo_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_pkt_get_info), (mp_obj_t)&pkt_get_info_obj },
};
diff --git a/zephyr/prj_base.conf b/zephyr/prj_base.conf
index 97a78fa77..4346f20bf 100644
--- a/zephyr/prj_base.conf
+++ b/zephyr/prj_base.conf
@@ -17,6 +17,12 @@ CONFIG_NET_TCP=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NET_NBUF_RX_COUNT=5
+# DNS
+CONFIG_DNS_RESOLVER=y
+CONFIG_DNS_RESOLVER_ADDITIONAL_QUERIES=2
+CONFIG_DNS_SERVER_IP_ADDRESSES=y
+CONFIG_DNS_SERVER1="192.0.2.2"
+
# Required for usocket.pkt_get_info()
CONFIG_NET_BUF_POOL_USAGE=y
From 55491031be1f267e07b2495916d4f5ba2735cc00 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 14 May 2017 17:51:12 +0300
Subject: [PATCH 206/826] tools/mpy_cross_all.py: Helper tool to run mpy-cross
on the entire project.
---
tools/mpy_cross_all.py | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100755 tools/mpy_cross_all.py
diff --git a/tools/mpy_cross_all.py b/tools/mpy_cross_all.py
new file mode 100755
index 000000000..2bda71e9b
--- /dev/null
+++ b/tools/mpy_cross_all.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python3
+import argparse
+import os
+import os.path
+
+argparser = argparse.ArgumentParser(description="Compile all .py files to .mpy recursively")
+argparser.add_argument("-o", "--out", help="output directory (default: input dir)")
+argparser.add_argument("--target", help="select MicroPython target config")
+argparser.add_argument("-mcache-lookup-bc", action="store_true", help="cache map lookups in the bytecode")
+argparser.add_argument("dir", help="input directory")
+args = argparser.parse_args()
+
+TARGET_OPTS = {
+ "unix": "-mcache-lookup-bc",
+ "baremetal": "",
+}
+
+args.dir = args.dir.rstrip("/")
+
+if not args.out:
+ args.out = args.dir
+
+path_prefix_len = len(args.dir) + 1
+
+for path, subdirs, files in os.walk(args.dir):
+ for f in files:
+ if f.endswith(".py"):
+ fpath = path + "/" + f
+ #print(fpath)
+ out_fpath = args.out + "/" + fpath[path_prefix_len:-3] + ".mpy"
+ out_dir = os.path.dirname(out_fpath)
+ if not os.path.isdir(out_dir):
+ os.makedirs(out_dir)
+ cmd = "mpy-cross -v -v %s -s %s %s -o %s" % (TARGET_OPTS.get(args.target, ""),
+ fpath[path_prefix_len:], fpath, out_fpath)
+ #print(cmd)
+ res = os.system(cmd)
+ assert res == 0
From f06d0839bdaff783d8902bcedb572cbaabb6447a Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Thu, 12 Jan 2017 16:08:51 -0800
Subject: [PATCH 207/826] py/modsys: update conditionals for code referencing
sys.stdout
Working on a build with PY_IO enabled (for PY_UJSON support) but PY_SYS_STDFILES disabled (no filesystem). There are multiple references to mp_sys_stdout_obj that should only be enabled if both PY_IO and PY_SYS_STDFILES are enabled.
---
py/modbuiltins.c | 8 ++++----
py/modsys.c | 4 ++--
py/mpprint.h | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/py/modbuiltins.c b/py/modbuiltins.c
index e8119456d..17bd30c52 100644
--- a/py/modbuiltins.c
+++ b/py/modbuiltins.c
@@ -406,7 +406,7 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *
if (end_elem != NULL && end_elem->value != mp_const_none) {
end_data = mp_obj_str_get_data(end_elem->value, &end_len);
}
- #if MICROPY_PY_IO
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
void *stream_obj = &mp_sys_stdout_obj;
mp_map_elem_t *file_elem = mp_map_lookup(kwargs, MP_OBJ_NEW_QSTR(MP_QSTR_file), MP_MAP_LOOKUP);
if (file_elem != NULL && file_elem->value != mp_const_none) {
@@ -417,19 +417,19 @@ STATIC mp_obj_t mp_builtin_print(size_t n_args, const mp_obj_t *args, mp_map_t *
#endif
for (mp_uint_t i = 0; i < n_args; i++) {
if (i > 0) {
- #if MICROPY_PY_IO
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_stream_write_adaptor(stream_obj, sep_data, sep_len);
#else
mp_print_strn(&mp_plat_print, sep_data, sep_len, 0, 0, 0);
#endif
}
- #if MICROPY_PY_IO
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_obj_print_helper(&print, args[i], PRINT_STR);
#else
mp_obj_print_helper(&mp_plat_print, args[i], PRINT_STR);
#endif
}
- #if MICROPY_PY_IO
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
mp_stream_write_adaptor(stream_obj, end_data, end_len);
#else
mp_print_strn(&mp_plat_print, end_data, end_len, 0, 0, 0);
diff --git a/py/modsys.c b/py/modsys.c
index b208c88bd..5fbcb944c 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -45,7 +45,7 @@ extern struct _mp_dummy_t mp_sys_stdin_obj;
extern struct _mp_dummy_t mp_sys_stdout_obj;
extern struct _mp_dummy_t mp_sys_stderr_obj;
-#if MICROPY_PY_IO
+#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
const mp_print_t mp_sys_stdout_print = {&mp_sys_stdout_obj, mp_stream_write_adaptor};
#endif
@@ -106,7 +106,7 @@ STATIC mp_obj_t mp_sys_exit(size_t n_args, const mp_obj_t *args) {
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);
STATIC mp_obj_t mp_sys_print_exception(size_t n_args, const mp_obj_t *args) {
- #if MICROPY_PY_IO
+ #if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
void *stream_obj = &mp_sys_stdout_obj;
if (n_args > 1) {
stream_obj = MP_OBJ_TO_PTR(args[1]); // XXX may fail
diff --git a/py/mpprint.h b/py/mpprint.h
index f9204e322..4fc904a20 100644
--- a/py/mpprint.h
+++ b/py/mpprint.h
@@ -39,7 +39,7 @@
#define PF_FLAG_ADD_PERCENT (0x100)
#define PF_FLAG_SHOW_OCTAL_LETTER (0x200)
-#if MICROPY_PY_IO
+#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
# define MP_PYTHON_PRINTER &mp_sys_stdout_print
#else
# define MP_PYTHON_PRINTER &mp_plat_print
@@ -55,7 +55,7 @@ typedef struct _mp_print_t {
// All (non-debug) prints go through one of the two interfaces below.
// 1) Wrapper for platform print function, which wraps MP_PLAT_PRINT_STRN.
extern const mp_print_t mp_plat_print;
-#if MICROPY_PY_IO
+#if MICROPY_PY_IO && MICROPY_PY_SYS_STDFILES
// 2) Wrapper for printing to sys.stdout.
extern const mp_print_t mp_sys_stdout_print;
#endif
From c19f07bd52aeb59ac8bdfa1e575e2323f6a14c6e Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 14 May 2017 22:52:16 +0300
Subject: [PATCH 208/826] docs/machine.Pin: There's no toggle() method in
MicroPython hardware API.
May be a port-specific method, not portable, not part of the official
specification.
---
docs/library/machine.Pin.rst | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/docs/library/machine.Pin.rst b/docs/library/machine.Pin.rst
index 369c08f44..6d6ba7bfd 100644
--- a/docs/library/machine.Pin.rst
+++ b/docs/library/machine.Pin.rst
@@ -158,15 +158,6 @@ Methods
and get the value of the pin. It is equivalent to Pin.value([x]).
See :meth:`Pin.value` for more details.
-.. method:: Pin.toggle()
-
- Toggle the output value of the pin. Equivalent to ``pin.value(not pin.out_value())``.
- Returns ``None``.
-
- Not all ports implement this method.
-
- Availability: WiPy.
-
.. method:: Pin.id()
Get the pin identifier. This may return the ``id`` as specified in the
From 0ba136fbe9bf2f20555480ef4de1778e48ea3105 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Sun, 14 May 2017 23:12:06 +0300
Subject: [PATCH 209/826] docs/machine.Signal: Add initial draft description of
Signal class.
---
docs/library/machine.Signal.rst | 96 +++++++++++++++++++++++++++++++++
docs/library/machine.rst | 1 +
2 files changed, 97 insertions(+)
create mode 100644 docs/library/machine.Signal.rst
diff --git a/docs/library/machine.Signal.rst b/docs/library/machine.Signal.rst
new file mode 100644
index 000000000..486908627
--- /dev/null
+++ b/docs/library/machine.Signal.rst
@@ -0,0 +1,96 @@
+.. currentmodule:: machine
+.. _machine.Signal:
+
+class Signal -- control and sense external I/O devices
+======================================================
+
+The Signal class is a simple extension of Pin class. Unlike Pin, which
+can be only in "absolute" 0 and 1 states, a Signal can be in "asserted"
+(on) or "deasserted" (off) states, while being inverted (active-low) or
+not. Summing up, it adds logical inversion support to Pin functionality.
+While this may seem a simple addition, it is exactly what is needed to
+support wide array of simple digital devices in a way portable across
+different boards, which is one of the major MicroPython goals. Regardless
+whether different users have an active-high or active-low LED, a normally
+open or normally closed relay - you can develop single, nicely looking
+application which works with each of them, and capture hardware
+configuration differences in few lines on the config file of your app.
+
+Following is the guide when Signal vs Pin should be used:
+
+* Use Signal: If you want to control a simple on/off (including software
+ PWM!) devices like LEDs, multi-segment indicators, relays, buzzers, or
+ read simple binary sensors, like normally open or normally closed buttons,
+ pulled high or low, Reed switches, moisture/flame detectors, etc. etc.
+ Summing up, if you have a real physical device/sensor requiring GPIO
+ access, you likely should use a Signal.
+
+* Use Pin: If you implement a higher-level protocol or bus to communicate
+ with more complex devices.
+
+The split between Pin and Signal come from the usecases above and the
+architecture of MicroPython: Pin offers the lowest overhead, which may
+be important when bit-banging protocols. But Signal adds additional
+flexibility on top of Pin, at the cost of minor overhead (much smaller
+than if you implemented active-high vs active-low device differences in
+Python manually!). Also, Pin is low-level object which needs to be
+implemented for each support board, while Signal is a high-level object
+which comes for free once Pin is implemented.
+
+If in doubt, give the Signal a try! Once again, it is developed to save
+developers from the need to handle unexciting differences like active-low
+vs active-high signals, and allow other users to share and enjoy your
+application, instead of being frustrated by the fact that it doesn't
+work for them simply because their LEDs or relays are wired in a slightly
+different way.
+
+Constructors
+------------
+
+.. class:: Signal(pin_obj, invert=False)
+ Signal(pin_arguments..., \*, invert=False)
+
+ Create a Signal object. There're two ways to create it:
+
+ * By wrapping existing Pin object - universal method which works for
+ any board.
+ * By passing required Pin parameters directly to Signal constructor,
+ skipping the need to create intermediate Pin object. Available on
+ many, but not all boards.
+
+ The arguments are:
+
+ - ``pin_obj`` is existing Pin object.
+
+ - ``pin_arguments`` are the same arguments as can be passed to Pin constructor.
+
+ - ``invert`` - if True, the signal will be inverted (active low).
+
+Methods
+-------
+
+.. method:: Signal.value([x])
+
+ This method allows to set and get the value of the signal, depending on whether
+ the argument ``x`` is supplied or not.
+
+ If the argument is omitted then this method gets the signal level, 1 meaning
+ signal is asserted (active) and 0 - signal inactive.
+
+ If the argument is supplied then this method sets the signal level. The
+ argument ``x`` can be anything that converts to a boolean. If it converts
+ to ``True``, the signal is active, otherwise it is inactive.
+
+ Correspondence between signal being active and actual logic level on the
+ underlying pin depends on whether signal is inverted (active-low) or not.
+ For non-inverted signal, active status corresponds to logical 1, inactive -
+ to logical 0. For inverted/active-low signal, active status corresponds
+ to logical 0, while inactive - to logical 1.
+
+.. method:: Signal.on()
+
+ Activate signal.
+
+.. method:: Signal.off()
+
+ Deactivate signal.
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index ea11a1ff4..c2c6b83fd 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -147,6 +147,7 @@ Classes
machine.I2C.rst
machine.Pin.rst
+ machine.Signal.rst
machine.RTC.rst
machine.SPI.rst
machine.Timer.rst
From d5713c8618e8d809f354b6be72b7410dc5ac840a Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Mon, 15 May 2017 00:26:44 +0300
Subject: [PATCH 210/826] docs/library/index: Add important summary of the
intro section as warning.
To make them harder to miss.
---
docs/library/index.rst | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/docs/library/index.rst b/docs/library/index.rst
index 1a61f6882..770920a1f 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -1,6 +1,17 @@
MicroPython libraries
=====================
+.. warning::
+
+ Important summary of this section
+
+ * MicroPython implements a subset of Python functionality for each module.
+ * To ease extensibility, MicroPython versions of standard Python modules
+ usually have ``u`` (micro) prefix.
+ * Any particular MicroPython variant or port may miss any feature/function
+ described in this general documentation, due to resource constraints.
+
+
This chapter describes modules (function and class libraries) which are built
into MicroPython. There are a few categories of modules:
From 53461deb04ecddf3be8b8b03024bb8bbc08b9d6b Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Fri, 12 May 2017 13:30:12 -0700
Subject: [PATCH 211/826] py/objstringio: Fix StringIO reads at or beyond EOF.
Existing code failed if seek() went past EOF (which is acceptable when writing).
---
py/objstringio.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/py/objstringio.c b/py/objstringio.c
index 88659deb8..f4e796780 100644
--- a/py/objstringio.c
+++ b/py/objstringio.c
@@ -56,6 +56,9 @@ STATIC mp_uint_t stringio_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *er
(void)errcode;
mp_obj_stringio_t *o = MP_OBJ_TO_PTR(o_in);
check_stringio_is_open(o);
+ if (o->vstr->len <= o->pos) { // read to EOF, or seeked to EOF or beyond
+ return 0;
+ }
mp_uint_t remaining = o->vstr->len - o->pos;
if (size > remaining) {
size = remaining;
From 162a0f942b8c049ef3b7a4c6ad7f28f8a46667dd Mon Sep 17 00:00:00 2001
From: Tom Collins
Date: Fri, 12 May 2017 13:28:07 -0700
Subject: [PATCH 212/826] tests/io/bytesio_ext: Test read() after seek() past
end of BytesIO object.
---
tests/io/bytesio_ext.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/tests/io/bytesio_ext.py b/tests/io/bytesio_ext.py
index e827d1409..e454b2fd9 100644
--- a/tests/io/bytesio_ext.py
+++ b/tests/io/bytesio_ext.py
@@ -4,6 +4,10 @@
except ImportError:
import io
+a = io.BytesIO(b"foobar")
+a.seek(10)
+print(a.read(10))
+
a = io.BytesIO()
print(a.seek(8))
a.write(b"123")
From 4b235800a4ebba19a98bba50a5a98d2c407d99a7 Mon Sep 17 00:00:00 2001
From: puuu
Date: Thu, 11 May 2017 11:50:01 +0900
Subject: [PATCH 213/826] esp8266/modnetwork: In connect, fix potential buffer
overflows.
---
esp8266/modnetwork.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/esp8266/modnetwork.c b/esp8266/modnetwork.c
index 627655b36..eb9d75e28 100644
--- a/esp8266/modnetwork.c
+++ b/esp8266/modnetwork.c
@@ -102,13 +102,13 @@ STATIC mp_obj_t esp_connect(mp_uint_t n_args, const mp_obj_t *args) {
if (n_args > 1) {
p = mp_obj_str_get_data(args[1], &len);
+ len = MIN(len, sizeof(config.ssid));
memcpy(config.ssid, p, len);
if (n_args > 2) {
p = mp_obj_str_get_data(args[2], &len);
- } else {
- p = "";
+ len = MIN(len, sizeof(config.password));
+ memcpy(config.password, p, len);
}
- memcpy(config.password, p, len);
error_check(wifi_station_set_config(&config), "Cannot set STA config");
}
From 37bd3b4f4cbbfabc86b03f8df8a3047fa2b65dd1 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 16 May 2017 17:40:22 +1000
Subject: [PATCH 214/826] stmhal/modmachine: Add machine.UART class, linking to
pyb.UART.
pyb.UART has a superset of machine.UART functionality so can be used to
provide compatibility with other ports that also implement machine.UART.
---
stmhal/modmachine.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 98d5c2da9..40b5b7bf3 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -50,6 +50,7 @@
#include "rtc.h"
#include "i2c.h"
#include "spi.h"
+#include "uart.h"
#include "wdt.h"
#if defined(MCU_SERIES_F4)
@@ -557,9 +558,9 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
// initialize master mode on the peripheral.
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
+ { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_WDT), MP_ROM_PTR(&pyb_wdt_type) },
#if 0
- { MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
{ MP_ROM_QSTR(MP_QSTR_Timer), MP_ROM_PTR(&pyb_timer_type) },
{ MP_ROM_QSTR(MP_QSTR_HeartBeat), MP_ROM_PTR(&pyb_heartbeat_type) },
{ MP_ROM_QSTR(MP_QSTR_SD), MP_ROM_PTR(&pyb_sd_type) },
From a004554dc168049f3656480c7b34608741f76765 Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 16 May 2017 17:44:14 +1000
Subject: [PATCH 215/826] stmhal/modmachine: Remove TODO comment that is now
implemented.
---
stmhal/modmachine.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 40b5b7bf3..c5444ec98 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -554,8 +554,6 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_RTC), MP_ROM_PTR(&pyb_rtc_type) },
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&pyb_adc_type) },
#endif
- // TODO: Per new API, I2C types below, if called with 1 arg (ID), should still
- // initialize master mode on the peripheral.
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_i2c_type) },
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hard_spi_type) },
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&pyb_uart_type) },
From 88c51c3592edc6c29fb0aad57c91e535793aa31b Mon Sep 17 00:00:00 2001
From: Damien George
Date: Tue, 16 May 2017 18:53:02 +1000
Subject: [PATCH 216/826] tools/mpy-tool.py: Fix regression with freezing
floats in obj repr C.
Regression was introduced by ec534609f665cb791b8fc1eae1a44e514c297659
---
tools/mpy-tool.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/mpy-tool.py b/tools/mpy-tool.py
index 483a992db..544f90cc8 100755
--- a/tools/mpy-tool.py
+++ b/tools/mpy-tool.py
@@ -343,7 +343,7 @@ def freeze(self, parent_name):
print('#elif MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_C')
n = struct.unpack('
Date: Tue, 16 May 2017 13:43:06 +0300
Subject: [PATCH 217/826] zephyr/modusocket: First step to switch to
alternative FIFO processing.
Here we wait for non-empty FIFO, and then directly access/drop its head
element.
---
zephyr/modusocket.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index aa638d413..37dfab638 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -399,12 +399,14 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
}
DEBUG_printf("TCP recv: no cur_pkt, getting\n");
- struct net_pkt *pkt = k_fifo_get(&socket->recv_q, K_FOREVER);
-
+ _k_fifo_wait_non_empty(&socket->recv_q, K_FOREVER);
+ struct net_pkt *pkt = _k_fifo_peek_head(&socket->recv_q);
if (pkt == NULL) {
DEBUG_printf("TCP recv: NULL return from fifo\n");
continue;
}
+ // Drop head packet from queue
+ k_fifo_get(&socket->recv_q, K_NO_WAIT);
DEBUG_printf("TCP recv: new cur_pkt: %p\n", pkt);
socket->cur_pkt = pkt;
From aa9ce283c2b1877a73e20dace4062484d3d5f7fa Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Tue, 16 May 2017 13:46:54 +0300
Subject: [PATCH 218/826] zephyr/modusocket: Get rid of cur_pkt object member.
Instead, just peek a packet at the head of the queue and work with it.
---
zephyr/modusocket.c | 42 ++++++++++++++++++------------------------
1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index 37dfab638..c4e6529b8 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -52,7 +52,6 @@ typedef struct _socket_obj_t {
struct k_fifo recv_q;
struct k_fifo accept_q;
};
- struct net_pkt *cur_pkt;
#define STATE_NEW 0
#define STATE_CONNECTING 1
@@ -208,7 +207,6 @@ socket_obj_t *socket_new(void) {
socket_obj_t *socket = m_new_obj_with_finaliser(socket_obj_t);
socket->base.type = (mp_obj_t)&socket_type;
k_fifo_init(&socket->recv_q);
- socket->cur_pkt = NULL;
socket->state = STATE_NEW;
return socket;
}
@@ -393,26 +391,20 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
do {
- if (socket->cur_pkt == NULL) {
- if (socket->state == STATE_PEER_CLOSED) {
- return 0;
- }
-
- DEBUG_printf("TCP recv: no cur_pkt, getting\n");
- _k_fifo_wait_non_empty(&socket->recv_q, K_FOREVER);
- struct net_pkt *pkt = _k_fifo_peek_head(&socket->recv_q);
- if (pkt == NULL) {
- DEBUG_printf("TCP recv: NULL return from fifo\n");
- continue;
- }
- // Drop head packet from queue
- k_fifo_get(&socket->recv_q, K_NO_WAIT);
+ if (socket->state == STATE_PEER_CLOSED) {
+ return 0;
+ }
- DEBUG_printf("TCP recv: new cur_pkt: %p\n", pkt);
- socket->cur_pkt = pkt;
+ _k_fifo_wait_non_empty(&socket->recv_q, K_FOREVER);
+ struct net_pkt *pkt = _k_fifo_peek_head(&socket->recv_q);
+ if (pkt == NULL) {
+ DEBUG_printf("TCP recv: NULL return from fifo\n");
+ continue;
}
- struct net_buf *frag = socket->cur_pkt->frags;
+ DEBUG_printf("TCP recv: cur_pkt: %p\n", pkt);
+
+ struct net_buf *frag = pkt->frags;
if (frag == NULL) {
printf("net_pkt has empty fragments on start!\n");
assert(0);
@@ -430,15 +422,17 @@ STATIC mp_uint_t sock_read(mp_obj_t self_in, void *buf, mp_uint_t max_len, int *
if (recv_len != frag_len) {
net_buf_pull(frag, recv_len);
} else {
- frag = net_pkt_frag_del(socket->cur_pkt, NULL, frag);
+ frag = net_pkt_frag_del(pkt, NULL, frag);
if (frag == NULL) {
- DEBUG_printf("Finished processing pkt %p\n", socket->cur_pkt);
+ DEBUG_printf("Finished processing pkt %p\n", pkt);
+ // Drop head packet from queue
+ k_fifo_get(&socket->recv_q, K_NO_WAIT);
+
// If "sent" flag was set, it's last packet and we reached EOF
- if (net_pkt_sent(socket->cur_pkt)) {
+ if (net_pkt_sent(pkt)) {
socket->state = STATE_PEER_CLOSED;
}
- net_pkt_unref(socket->cur_pkt);
- socket->cur_pkt = NULL;
+ net_pkt_unref(pkt);
}
}
// Keep repeating while we're getting empty fragments
From 5f648ff60e0e7ff4eaa1add0091962f02256235f Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 17 May 2017 00:17:53 +0300
Subject: [PATCH 219/826] zephyr/main: Check default netif before applying
operations to it.
If no network driver is enabled (e.g., it doesn't exist for a particular
board), it will be NULL.
---
zephyr/main.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/zephyr/main.c b/zephyr/main.c
index a67ad3352..a4301629f 100644
--- a/zephyr/main.c
+++ b/zephyr/main.c
@@ -62,6 +62,13 @@ static char heap[MICROPY_HEAP_SIZE];
void init_zephyr(void) {
// TODO: Make addresses configurable
+ #ifdef CONFIG_NETWORKING
+ if (net_if_get_default() == NULL) {
+ // If there's no default networking interface,
+ // there's nothing to configure.
+ return;
+ }
+ #endif
#ifdef CONFIG_NET_IPV4
static struct in_addr in4addr_my = {{{192, 0, 2, 1}}};
net_if_ipv4_addr_add(net_if_get_default(), &in4addr_my, NET_ADDR_MANUAL, 0);
From 0912334f54f5cdf1d7784032e64e23495d854bed Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 17 May 2017 00:21:22 +0300
Subject: [PATCH 220/826] zephyr/modusocket: getaddrinfo: Use RAISE_ERRNO for
proper error decoding.
---
zephyr/modusocket.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/zephyr/modusocket.c b/zephyr/modusocket.c
index c4e6529b8..fbc630136 100644
--- a/zephyr/modusocket.c
+++ b/zephyr/modusocket.c
@@ -572,10 +572,7 @@ STATIC mp_obj_t mod_getaddrinfo(size_t n_args, const mp_obj_t *args) {
int status;
for (int i = 2; i--;) {
int type = (family != AF_INET6 ? DNS_QUERY_TYPE_A : DNS_QUERY_TYPE_AAAA);
- status = dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000);
- if (status < 0) {
- mp_raise_OSError(status);
- }
+ RAISE_ERRNO(dns_get_addr_info(host, type, NULL, dns_resolve_cb, &state, 3000));
k_sem_take(&state.sem, K_FOREVER);
if (family != 0) {
break;
From 0af974b77754ea8bcdaab07527fe685b3fc11631 Mon Sep 17 00:00:00 2001
From: Paul Sokolovsky
Date: Wed, 17 May 2017 00:42:26 +0300
Subject: [PATCH 221/826] examples/hwapi/soft_pwm2_uasyncio: Update for
call_later_ms().
Following finalized naming in uasyncio.
---
examples/hwapi/soft_pwm2_uasyncio.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/examples/hwapi/soft_pwm2_uasyncio.py b/examples/hwapi/soft_pwm2_uasyncio.py
index abeb4b1bf..908ef2d8a 100644
--- a/examples/hwapi/soft_pwm2_uasyncio.py
+++ b/examples/hwapi/soft_pwm2_uasyncio.py
@@ -27,5 +27,5 @@ async def fade_in_out(LED):
loop = uasyncio.get_event_loop()
loop.create_task(fade_in_out(LED))
-loop.call_later_ms_(800, fade_in_out(LED2))
+loop.call_later_ms(800, fade_in_out(LED2))
loop.run_forever()
From e4a53570d08643d62ba8e2b72919ae1693162e9a Mon Sep 17 00:00:00 2001
From: Damien George
Date: Wed, 17 May 2017 12:38:33 +1000
Subject: [PATCH 222/826] docs: Change single occurrence of "Micropython" to
"MicroPython".
---
docs/topindex.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/topindex.html b/docs/topindex.html
index 3cbf21615..f32f3cea6 100644
--- a/docs/topindex.html
+++ b/docs/topindex.html
@@ -48,7 +48,7 @@