summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Ruben Bakke <glennbakke@gmail.com>2017-03-07 17:46:34 +0100
committerGlenn Ruben Bakke <glennbakke@gmail.com>2017-03-07 17:46:34 +0100
commitfd8f2c36f539a386192d106ef5ca0ce6a3926aec (patch)
tree7b0bf8cb7a0677c1987b2d3e725f57cffc2e8633
parent5f705adae06d4925351fe716f956d0fc922e53cf (diff)
parentfd49ff991769a29b2dcc0f8ed88143487f2bd131 (diff)
Merge branch 'master' into nrf5_no_sdk
-rw-r--r--.gitignore4
-rw-r--r--bare-arm/main.c1
-rw-r--r--cc3200/bootmgr/main.c3
-rw-r--r--cc3200/fatfs/src/drivers/sflash_diskio.c2
-rw-r--r--cc3200/ftp/ftp.c24
-rw-r--r--cc3200/main.c7
-rw-r--r--cc3200/misc/mpexception.c3
-rw-r--r--cc3200/misc/mpexception.h3
-rw-r--r--cc3200/misc/mpirq.c2
-rw-r--r--cc3200/mods/modmachine.c1
-rw-r--r--cc3200/mods/modnetwork.c5
-rw-r--r--cc3200/mods/moduhashlib.c4
-rw-r--r--cc3200/mods/moduos.c3
-rw-r--r--cc3200/mods/modusocket.c293
-rw-r--r--cc3200/mods/modussl.c1
-rw-r--r--cc3200/mods/modwlan.c288
-rw-r--r--cc3200/mods/modwlan.h15
-rw-r--r--cc3200/mods/pybadc.c9
-rw-r--r--cc3200/mods/pybi2c.c13
-rw-r--r--cc3200/mods/pybrtc.c11
-rw-r--r--cc3200/mods/pybsd.c5
-rw-r--r--cc3200/mods/pybspi.c5
-rw-r--r--cc3200/mods/pybtimer.c5
-rw-r--r--cc3200/mods/pybuart.c12
-rw-r--r--cc3200/mods/pybwdt.c5
-rw-r--r--cc3200/mpconfigport.h13
-rw-r--r--cc3200/simplelink/user.h2
-rw-r--r--cc3200/telnet/telnet.c14
-rw-r--r--docs/Makefile19
-rw-r--r--docs/differences/index_template.txt8
-rw-r--r--docs/esp8266/tutorial/intro.rst24
-rw-r--r--docs/esp8266_contents.rst1
-rw-r--r--docs/esp8266_index.rst1
-rw-r--r--docs/library/framebuf.rst129
-rw-r--r--docs/library/index.rst1
-rw-r--r--docs/library/lcd160cr.rst8
-rw-r--r--docs/library/machine.rst22
-rw-r--r--docs/library/uhashlib.rst52
-rw-r--r--docs/pyboard_contents.rst1
-rw-r--r--docs/pyboard_index.rst1
-rw-r--r--docs/topindex.html4
-rw-r--r--docs/unix_contents.rst1
-rw-r--r--docs/unix_index.rst1
-rw-r--r--docs/wipy_contents.rst1
-rw-r--r--docs/wipy_index.rst1
-rw-r--r--drivers/display/lcd160cr.py8
-rw-r--r--esp8266/mpconfigport.h1
-rw-r--r--extmod/modurandom.c15
-rw-r--r--extmod/modutimeq.c10
-rw-r--r--lib/utils/pyexec.c6
-rw-r--r--minimal/README.md12
-rw-r--r--minimal/main.c7
-rw-r--r--minimal/mpconfigport.h5
-rw-r--r--py/compile.c37
-rw-r--r--py/emitinlinethumb.c2
-rw-r--r--py/map.c11
-rw-r--r--py/modsys.c13
-rw-r--r--py/modthread.c11
-rw-r--r--py/moduerrno.c28
-rw-r--r--py/mpconfig.h5
-rw-r--r--py/mpstate.h14
-rw-r--r--py/nlr.h2
-rw-r--r--py/nlrx64.S262
-rw-r--r--py/nlrx64.c129
-rw-r--r--py/nlrx86.S195
-rw-r--r--py/nlrx86.c114
-rw-r--r--py/nlrxtensa.S119
-rw-r--r--py/nlrxtensa.c103
-rw-r--r--py/objarray.c4
-rw-r--r--py/objfun.c10
-rw-r--r--py/objlist.c10
-rw-r--r--py/objstr.c15
-rw-r--r--py/parse.c178
-rw-r--r--py/py.mk4
-rw-r--r--py/runtime.c23
-rw-r--r--qemu-arm/Makefile2
-rw-r--r--qemu-arm/main.c3
-rw-r--r--qemu-arm/modmachine.c (renamed from cc3200/util/std.h)29
-rw-r--r--qemu-arm/mpconfigport.h4
-rw-r--r--qemu-arm/test_main.c3
-rw-r--r--stmhal/accel.c6
-rw-r--r--stmhal/gccollect.c4
-rw-r--r--stmhal/i2c.c2
-rw-r--r--stmhal/lcd.c6
-rw-r--r--stmhal/led.c2
-rw-r--r--stmhal/main.c24
-rw-r--r--stmhal/modmachine.c2
-rw-r--r--stmhal/modnwcc3k.c3
-rw-r--r--stmhal/modnwwiznet5k.c8
-rw-r--r--stmhal/modpyb.c37
-rw-r--r--stmhal/mphalport.h8
-rw-r--r--stmhal/sdcard.c4
-rw-r--r--stmhal/stm32_it.c2
-rw-r--r--stmhal/systick.c42
-rw-r--r--stmhal/systick.h2
-rw-r--r--tests/basics/array_intbig.py (renamed from tests/basics/array_q.py)0
-rw-r--r--tests/basics/builtin_abs.py8
-rw-r--r--tests/basics/builtin_abs_intbig.py9
-rw-r--r--tests/basics/builtin_bin.py1
-rw-r--r--tests/basics/builtin_bin_intbig.py3
-rw-r--r--tests/basics/builtin_divmod.py12
-rw-r--r--tests/basics/builtin_divmod_intbig.py13
-rw-r--r--tests/basics/builtin_hash.py8
-rw-r--r--tests/basics/builtin_hash_intbig.py10
-rw-r--r--tests/basics/builtin_hex.py3
-rw-r--r--tests/basics/builtin_hex_intbig.py4
-rw-r--r--tests/basics/builtin_oct.py3
-rw-r--r--tests/basics/builtin_oct_intbig.py4
-rw-r--r--tests/basics/builtin_pow3.py14
-rw-r--r--tests/basics/builtin_pow3_intbig.py23
-rw-r--r--tests/basics/bytearray_intbig.py (renamed from tests/basics/bytearray_longint.py)0
-rw-r--r--tests/basics/bytes_construct.py3
-rw-r--r--tests/basics/bytes_construct_intbig.py4
-rw-r--r--tests/basics/floordivide.py15
-rw-r--r--tests/basics/floordivide_intbig.py15
-rw-r--r--tests/basics/int_big1.py (renamed from tests/basics/int_mpz.py)0
-rw-r--r--tests/basics/int_bytes.py1
-rw-r--r--tests/basics/int_bytes_intbig.py (renamed from tests/basics/int_bytes_long.py)2
-rw-r--r--tests/basics/int_constfolding.py14
-rw-r--r--tests/basics/int_constfolding_intbig.py19
-rw-r--r--tests/basics/int_divmod.py8
-rw-r--r--tests/basics/int_divmod_intbig.py9
-rw-r--r--tests/basics/int_intbig.py (renamed from tests/basics/int_long.py)0
-rw-r--r--tests/basics/list_slice_assign.py11
-rw-r--r--tests/basics/memoryview1.py4
-rw-r--r--tests/basics/op_error.py1
-rw-r--r--tests/basics/op_error_intbig.py13
-rw-r--r--tests/basics/ordereddict1.py11
-rw-r--r--tests/basics/slice_intbig.py (renamed from tests/basics/slice_bignum.py)0
-rw-r--r--tests/basics/string_join.py5
-rw-r--r--tests/basics/struct1.py28
-rw-r--r--tests/basics/struct1_intbig.py37
-rw-r--r--tests/basics/unpack1.py2
-rw-r--r--tests/cmdline/cmd_parsetree.py.exp4
-rw-r--r--tests/cpydiff/core_arguments.py10
-rw-r--r--tests/cpydiff/core_class_delnotimpl.py16
-rw-r--r--tests/cpydiff/core_class_superaslocal.py13
-rw-r--r--tests/cpydiff/core_class_supermultiple.py27
-rw-r--r--tests/cpydiff/core_class_superproperty.py18
-rw-r--r--tests/cpydiff/core_function_instancevar.py11
-rw-r--r--tests/cpydiff/core_function_unpacking.py7
-rw-r--r--tests/cpydiff/core_generator_noexit.py24
-rw-r--r--tests/cpydiff/core_import_prereg.py17
-rw-r--r--tests/cpydiff/core_mro.py15
-rw-r--r--tests/cpydiff/modules/__init__.py0
-rw-r--r--tests/cpydiff/modules/foo.py2
-rw-r--r--tests/cpydiff/modules_array_containment.py8
-rw-r--r--tests/cpydiff/modules_array_deletion.py10
-rw-r--r--tests/cpydiff/modules_array_subscrstep.py9
-rw-r--r--tests/cpydiff/modules_deque.py9
-rw-r--r--tests/cpydiff/modules_json_nonserializable.py14
-rw-r--r--tests/cpydiff/modules_struct_fewargs.py12
-rw-r--r--tests/cpydiff/modules_struct_manyargs.py12
-rw-r--r--tests/cpydiff/modules_sys_stdassign.py9
-rw-r--r--tests/cpydiff/syntax_spaces.py18
-rw-r--r--tests/cpydiff/syntax_unicode_nameesc.py7
-rw-r--r--tests/cpydiff/types_bytearray_sliceassign.py9
-rw-r--r--tests/cpydiff/types_bytes_keywords.py7
-rw-r--r--tests/cpydiff/types_bytes_subscrstep.py7
-rw-r--r--tests/cpydiff/types_exception_chaining.py10
-rw-r--r--tests/cpydiff/types_exception_instancevar.py9
-rw-r--r--tests/cpydiff/types_exception_loops.py12
-rw-r--r--tests/cpydiff/types_exception_subclassinit.py11
-rw-r--r--tests/cpydiff/types_float_rounding.py9
-rw-r--r--tests/cpydiff/types_int_subclassconv.py11
-rw-r--r--tests/cpydiff/types_int_tobytesfloat.py10
-rw-r--r--tests/cpydiff/types_list_delete_subscrstep.py9
-rw-r--r--tests/cpydiff/types_list_store_noniter.py9
-rw-r--r--tests/cpydiff/types_list_store_subscrstep.py9
-rw-r--r--tests/cpydiff/types_str_decodeerror.py11
-rw-r--r--tests/cpydiff/types_str_endswith.py7
-rw-r--r--tests/cpydiff/types_str_formatsubscr.py7
-rw-r--r--tests/cpydiff/types_str_keywords.py7
-rw-r--r--tests/cpydiff/types_str_rsplitnone.py7
-rw-r--r--tests/cpydiff/types_str_subclassequality.py11
-rw-r--r--tests/cpydiff/types_str_subscrstep.py7
-rw-r--r--tests/cpydiff/types_tuple_subscrstep.py7
-rw-r--r--tests/extmod/machine_signal.py40
-rw-r--r--tests/extmod/machine_signal.py.exp4
-rw-r--r--tests/extmod/uctypes_array_assign_native_le.py10
-rw-r--r--tests/extmod/uctypes_array_assign_native_le.py.exp2
-rw-r--r--tests/extmod/uctypes_array_assign_native_le_intbig.py43
-rw-r--r--tests/extmod/uctypes_array_assign_native_le_intbig.py.exp2
-rw-r--r--tests/feature_check/int_big.py2
-rw-r--r--tests/feature_check/int_big.py.exp0
-rw-r--r--tests/float/complex1.py3
-rw-r--r--tests/float/complex1_intbig.py4
-rw-r--r--tests/float/float2int_doubleprec_intbig.py (renamed from tests/float/float2int_doubleprec.py)32
-rw-r--r--tests/float/float2int_fp30_intbig.py (renamed from tests/float/float2int_fp30.py)32
-rw-r--r--tests/float/float2int_intbig.py (renamed from tests/float/float2int.py)34
-rw-r--r--tests/float/string_format_modulo2.py4
-rw-r--r--tests/float/string_format_modulo2_intbig.py21
-rw-r--r--tests/micropython/const_intbig.py13
-rw-r--r--tests/micropython/const_intbig.py.exp2
-rw-r--r--tests/micropython/heapalloc_exc_raise.py23
-rw-r--r--tests/micropython/heapalloc_exc_raise.py.exp2
-rw-r--r--tests/micropython/native_const_intbig.py (renamed from tests/micropython/native_const.py)0
-rw-r--r--tests/micropython/native_const_intbig.py.exp (renamed from tests/micropython/native_const.py.exp)0
-rw-r--r--tests/micropython/viper_misc.py7
-rw-r--r--tests/micropython/viper_misc.py.exp1
-rw-r--r--tests/micropython/viper_misc_intbig.py8
-rw-r--r--tests/micropython/viper_misc_intbig.py.exp1
-rwxr-xr-xtests/run-tests8
-rw-r--r--tools/gen-cpydiff.py224
-rwxr-xr-xtools/tinytest-codegen.py3
-rw-r--r--unix/input.c14
-rw-r--r--unix/main.c2
-rw-r--r--unix/modmachine.c2
-rw-r--r--unix/moduselect.c3
-rw-r--r--windows/msvc/sources.props2
210 files changed, 2370 insertions, 1527 deletions
diff --git a/.gitignore b/.gitignore
index a6295928d..280db388f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,7 @@ __pycache__/
######################
GNUmakefile
user.props
+
+# Generated rst files
+######################
+genrst/
diff --git a/bare-arm/main.c b/bare-arm/main.c
index e6ce06398..99a7f926e 100644
--- a/bare-arm/main.c
+++ b/bare-arm/main.c
@@ -48,6 +48,7 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void nlr_jump_fail(void *val) {
+ while (1);
}
void NORETURN __fatal_error(const char *msg) {
diff --git a/cc3200/bootmgr/main.c b/cc3200/bootmgr/main.c
index 97c8b36af..0d9ab35f8 100644
--- a/cc3200/bootmgr/main.c
+++ b/cc3200/bootmgr/main.c
@@ -26,8 +26,7 @@
#include <stdint.h>
#include <stdbool.h>
-
-#include "std.h"
+#include <stdio.h>
#include "py/mpconfig.h"
#include "hw_ints.h"
diff --git a/cc3200/fatfs/src/drivers/sflash_diskio.c b/cc3200/fatfs/src/drivers/sflash_diskio.c
index 1cfd41fb7..6a1fc4068 100644
--- a/cc3200/fatfs/src/drivers/sflash_diskio.c
+++ b/cc3200/fatfs/src/drivers/sflash_diskio.c
@@ -1,6 +1,6 @@
#include <stdint.h>
#include <stdbool.h>
-#include "std.h"
+#include <stdio.h>
#include "py/mpconfig.h"
#include "py/obj.h"
diff --git a/cc3200/ftp/ftp.c b/cc3200/ftp/ftp.c
index 679c32561..22035d6b3 100644
--- a/cc3200/ftp/ftp.c
+++ b/cc3200/ftp/ftp.c
@@ -25,8 +25,7 @@
*/
#include <stdint.h>
-#include <ctype.h>
-#include "std.h"
+#include <stdio.h>
#include "py/mpstate.h"
#include "py/obj.h"
@@ -500,12 +499,12 @@ static void ftp_wait_for_enabled (void) {
static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
SlSockNonblocking_t nonBlockingOption;
- sockaddr_in sServerAddress;
+ SlSockAddrIn_t sServerAddress;
_i16 _sd;
_i16 result;
// Open a socket for ftp data listen
- ASSERT ((*sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) > 0);
+ ASSERT ((*sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_IP)) > 0);
_sd = *sd;
if (_sd > 0) {
@@ -514,12 +513,12 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
// Enable non-blocking mode
nonBlockingOption.NonblockingEnabled = 1;
- ASSERT ((result = sl_SetSockOpt(_sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
+ ASSERT ((result = sl_SetSockOpt(_sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
// Bind the socket to a port number
- sServerAddress.sin_family = AF_INET;
- sServerAddress.sin_addr.s_addr = INADDR_ANY;
- sServerAddress.sin_port = htons(port);
+ sServerAddress.sin_family = SL_AF_INET;
+ sServerAddress.sin_addr.s_addr = SL_INADDR_ANY;
+ sServerAddress.sin_port = sl_Htons(port);
ASSERT ((result |= sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
@@ -535,7 +534,7 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
}
static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) {
- sockaddr_in sClientAddress;
+ SlSockAddrIn_t sClientAddress;
SlSocklen_t in_addrSize;
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
@@ -932,6 +931,13 @@ static void ftp_close_cmd_data (void) {
ftp_close_filesystem_on_error ();
}
+static void stoupper (char *str) {
+ while (str && *str != '\0') {
+ *str = (char)unichar_toupper((int)(*str));
+ str++;
+ }
+}
+
static ftp_cmd_index_t ftp_pop_command (char **str) {
char _cmd[FTP_CMD_SIZE_MAX];
ftp_pop_param (str, _cmd);
diff --git a/cc3200/main.c b/cc3200/main.c
index 06b3604b6..7c6c4b545 100644
--- a/cc3200/main.c
+++ b/cc3200/main.c
@@ -98,13 +98,6 @@ int main (void) {
for ( ; ; );
}
-void stoupper (char *str) {
- while (str && *str != '\0') {
- *str = (char)toupper((int)(*str));
- str++;
- }
-}
-
// We need this when configSUPPORT_STATIC_ALLOCATION is enabled
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
diff --git a/cc3200/misc/mpexception.c b/cc3200/misc/mpexception.c
index c45f0244b..068adb70b 100644
--- a/cc3200/misc/mpexception.c
+++ b/cc3200/misc/mpexception.c
@@ -40,9 +40,6 @@ STATIC void mpexception_set_user_interrupt (int chr, void *data);
/******************************************************************************
DECLARE EXPORTED DATA
******************************************************************************/
-const char mpexception_os_resource_not_avaliable[] = "resource not available";
-const char mpexception_os_operation_failed[] = "the requested operation failed";
-const char mpexception_os_request_not_possible[] = "the requested operation is not possible";
const char mpexception_value_invalid_arguments[] = "invalid argument(s) value";
const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type";
const char mpexception_uncaught[] = "uncaught exception";
diff --git a/cc3200/misc/mpexception.h b/cc3200/misc/mpexception.h
index f55aa739e..2f9d1877c 100644
--- a/cc3200/misc/mpexception.h
+++ b/cc3200/misc/mpexception.h
@@ -28,9 +28,6 @@
#ifndef MPEXCEPTION_H_
#define MPEXCEPTION_H_
-extern const char mpexception_os_resource_not_avaliable[];
-extern const char mpexception_os_operation_failed[];
-extern const char mpexception_os_request_not_possible[];
extern const char mpexception_value_invalid_arguments[];
extern const char mpexception_num_type_invalid_arguments[];
extern const char mpexception_uncaught[];
diff --git a/cc3200/misc/mpirq.c b/cc3200/misc/mpirq.c
index be5746759..37149089f 100644
--- a/cc3200/misc/mpirq.c
+++ b/cc3200/misc/mpirq.c
@@ -24,7 +24,7 @@
* THE SOFTWARE.
*/
-#include "std.h"
+#include <stdio.h>
#include "py/mpconfig.h"
#include "py/obj.h"
diff --git a/cc3200/mods/modmachine.c b/cc3200/mods/modmachine.c
index 8a57c2eb4..3c4e5a116 100644
--- a/cc3200/mods/modmachine.c
+++ b/cc3200/mods/modmachine.c
@@ -26,7 +26,6 @@
*/
#include <stdint.h>
-#include "std.h"
#include "py/mpstate.h"
#include "py/runtime.h"
diff --git a/cc3200/mods/modnetwork.c b/cc3200/mods/modnetwork.c
index 89d61e939..d44f75aca 100644
--- a/cc3200/mods/modnetwork.c
+++ b/cc3200/mods/modnetwork.c
@@ -25,12 +25,11 @@
* THE SOFTWARE.
*/
-#include <std.h>
-
#include "py/mpstate.h"
#include "py/obj.h"
#include "py/nlr.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "modnetwork.h"
#include "mpexception.h"
@@ -101,7 +100,7 @@ STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args
// check the server id
if (args[0].u_obj != MP_OBJ_NULL) {
if (mp_obj_get_int(args[0].u_obj) != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
}
diff --git a/cc3200/mods/moduhashlib.c b/cc3200/mods/moduhashlib.c
index c22cc8a06..e1145e4d8 100644
--- a/cc3200/mods/moduhashlib.c
+++ b/cc3200/mods/moduhashlib.c
@@ -93,7 +93,7 @@ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
self->digested = false;
}
} else {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
}
@@ -106,7 +106,7 @@ STATIC mp_obj_t hash_read (mp_obj_t self_in) {
}
} else if (self->c_size < self->b_size) {
// it's a fixed len block which is still incomplete
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
if (!self->digested) {
diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c
index 0adc75503..5523c887f 100644
--- a/cc3200/mods/moduos.c
+++ b/cc3200/mods/moduos.c
@@ -173,9 +173,6 @@ STATIC const mp_map_elem_t os_module_globals_table[] = {
{ 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_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&os_dupterm_obj },
-
- /// \constant sep - separation character used in paths
- { MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
};
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c
index 45f1f2d47..02ce3e279 100644
--- a/cc3200/mods/modusocket.c
+++ b/cc3200/mods/modusocket.c
@@ -36,10 +36,252 @@
#include "py/stream.h"
#include "netutils.h"
#include "modnetwork.h"
-#include "modwlan.h"
#include "modusocket.h"
#include "mpexception.h"
+/******************************************************************************/
+// The following set of macros and functions provide a glue between the CC3100
+// simplelink layer and the functions/methods provided by the usocket module.
+// They were historically in a separate file because usocket was designed to
+// work with multiple NICs, and the wlan_XXX functions just provided one
+// particular NIC implementation (that of the CC3100). But the CC3200 port only
+// supports a single NIC (being the CC3100) so it's unnecessary and inefficient
+// to provide an intermediate wrapper layer. Hence the wlan_XXX functions
+// are provided below as static functions so they can be inlined directly by
+// the corresponding usocket calls.
+
+#define WLAN_MAX_RX_SIZE 16000
+#define WLAN_MAX_TX_SIZE 1476
+
+#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \
+ addr.sa_family = SL_AF_INET; \
+ addr.sa_data[0] = port >> 8; \
+ addr.sa_data[1] = port; \
+ addr.sa_data[2] = ip[3]; \
+ addr.sa_data[3] = ip[2]; \
+ addr.sa_data[4] = ip[1]; \
+ addr.sa_data[5] = ip[0];
+
+#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
+ ip[0] = addr.sa_data[5]; \
+ ip[1] = addr.sa_data[4]; \
+ ip[2] = addr.sa_data[3]; \
+ ip[3] = addr.sa_data[2];
+
+STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
+ uint32_t ip;
+ int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
+ out_ip[0] = ip;
+ out_ip[1] = ip >> 8;
+ out_ip[2] = ip >> 16;
+ out_ip[3] = ip >> 24;
+ return result;
+}
+
+STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
+ int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto);
+ if (sd < 0) {
+ *_errno = sd;
+ return -1;
+ }
+ s->sock_base.sd = sd;
+ return 0;
+}
+
+STATIC void wlan_socket_close(mod_network_socket_obj_t *s) {
+ // this is to prevent the finalizer to close a socket that failed when being created
+ if (s->sock_base.sd >= 0) {
+ modusocket_socket_delete(s->sock_base.sd);
+ sl_Close(s->sock_base.sd);
+ s->sock_base.sd = -1;
+ }
+}
+
+STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr));
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
+ int ret = sl_Listen(s->sock_base.sd, backlog);
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
+ // accept incoming connection
+ int16_t sd;
+ SlSockAddr_t addr;
+ SlSocklen_t addr_len = sizeof(addr);
+
+ sd = sl_Accept(s->sock_base.sd, &addr, &addr_len);
+ // save the socket descriptor
+ s2->sock_base.sd = sd;
+ if (sd < 0) {
+ *_errno = sd;
+ return -1;
+ }
+
+ // return ip and port
+ UNPACK_SOCKADDR(addr, ip, *port);
+ return 0;
+}
+
+STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr));
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
+ mp_int_t bytes = 0;
+ if (len > 0) {
+ bytes = sl_Send(s->sock_base.sd, (const void *)buf, len, 0);
+ }
+ if (bytes <= 0) {
+ *_errno = bytes;
+ return -1;
+ }
+ return bytes;
+}
+
+STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
+ int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return ret;
+}
+
+STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
+ MAKE_SOCKADDR(addr, ip, port)
+ int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr));
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return ret;
+}
+
+STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
+ SlSockAddr_t addr;
+ SlSocklen_t addr_len = sizeof(addr);
+ mp_int_t ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ UNPACK_SOCKADDR(addr, ip, *port);
+ return ret;
+}
+
+STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
+ int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen);
+ if (ret < 0) {
+ *_errno = ret;
+ return -1;
+ }
+ return 0;
+}
+
+STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) {
+ int ret;
+ bool has_timeout;
+ if (timeout_s == 0 || timeout_s == -1) {
+ SlSockNonblocking_t option;
+ if (timeout_s == 0) {
+ // set non-blocking mode
+ option.NonblockingEnabled = 1;
+ } else {
+ // set blocking mode
+ option.NonblockingEnabled = 0;
+ }
+ ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option));
+ has_timeout = false;
+ } else {
+ // set timeout
+ struct SlTimeval_t timeVal;
+ timeVal.tv_sec = timeout_s; // seconds
+ timeVal.tv_usec = 0; // microseconds. 10000 microseconds resolution
+ ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_RCVTIMEO, &timeVal, sizeof(timeVal));
+ has_timeout = true;
+ }
+
+ if (ret != 0) {
+ *_errno = ret;
+ return -1;
+ }
+
+ s->sock_base.has_timeout = has_timeout;
+ return 0;
+}
+
+STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
+ mp_int_t ret;
+ if (request == MP_STREAM_POLL) {
+ mp_uint_t flags = arg;
+ ret = 0;
+ int32_t sd = s->sock_base.sd;
+
+ // init fds
+ SlFdSet_t rfds, wfds, xfds;
+ SL_FD_ZERO(&rfds);
+ SL_FD_ZERO(&wfds);
+ SL_FD_ZERO(&xfds);
+
+ // set fds if needed
+ if (flags & MP_STREAM_POLL_RD) {
+ SL_FD_SET(sd, &rfds);
+ }
+ if (flags & MP_STREAM_POLL_WR) {
+ SL_FD_SET(sd, &wfds);
+ }
+ if (flags & MP_STREAM_POLL_HUP) {
+ SL_FD_SET(sd, &xfds);
+ }
+
+ // call simplelink's select with minimum timeout
+ SlTimeval_t tv;
+ tv.tv_sec = 0;
+ tv.tv_usec = 1;
+ int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
+
+ // check for errors
+ if (nfds == -1) {
+ *_errno = nfds;
+ return -1;
+ }
+
+ // check return of select
+ if (SL_FD_ISSET(sd, &rfds)) {
+ ret |= MP_STREAM_POLL_RD;
+ }
+ if (SL_FD_ISSET(sd, &wfds)) {
+ ret |= MP_STREAM_POLL_WR;
+ }
+ if (SL_FD_ISSET(sd, &xfds)) {
+ ret |= MP_STREAM_POLL_HUP;
+ }
+ } else {
+ *_errno = MP_EINVAL;
+ ret = MP_STREAM_ERROR;
+ }
+ return ret;
+}
+
/******************************************************************************
DEFINE PRIVATE CONSTANTS
******************************************************************************/
@@ -95,13 +337,13 @@ void modusocket_socket_delete (int16_t sd) {
}
void modusocket_enter_sleep (void) {
- fd_set socketset;
+ SlFdSet_t socketset;
int16_t maxfd = 0;
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
int16_t sd;
if ((sd = modusocket_sockets[i].sd) >= 0) {
- FD_SET(sd, &socketset);
+ SL_FD_SET(sd, &socketset);
maxfd = (maxfd > sd) ? maxfd : sd;
}
}
@@ -133,9 +375,9 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
// create socket object
mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
s->base.type = (mp_obj_t)&socket_type;
- s->sock_base.u_param.domain = AF_INET;
- s->sock_base.u_param.type = SOCK_STREAM;
- s->sock_base.u_param.proto = IPPROTO_TCP;
+ s->sock_base.u_param.domain = SL_AF_INET;
+ s->sock_base.u_param.type = SL_SOCK_STREAM;
+ s->sock_base.u_param.proto = SL_IPPROTO_TCP;
s->sock_base.u_param.fileno = -1;
s->sock_base.has_timeout = false;
s->sock_base.cert_req = false;
@@ -180,7 +422,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// call the NIC to bind the socket
- int _errno;
+ int _errno = 0;
if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
mp_raise_OSError(-_errno);
}
@@ -217,8 +459,8 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
// accept the incoming connection
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
- mp_uint_t port;
- int _errno;
+ mp_uint_t port = 0;
+ int _errno = 0;
if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
mp_raise_OSError(-_errno);
}
@@ -277,8 +519,8 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
int _errno;
mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
if (ret < 0) {
- if (_errno == EAGAIN && self->sock_base.has_timeout) {
- mp_raise_msg(&mp_type_TimeoutError, "timed out");
+ if (_errno == MP_EAGAIN && self->sock_base.has_timeout) {
+ mp_raise_OSError(MP_ETIMEDOUT);
}
mp_raise_OSError(-_errno);
}
@@ -304,7 +546,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
// call the nic to sendto
- int _errno;
+ int _errno = 0;
mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
if (ret < 0) {
mp_raise_OSError(-_errno);
@@ -319,12 +561,12 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
vstr_t vstr;
vstr_init_len(&vstr, mp_obj_get_int(len_in));
byte ip[4];
- mp_uint_t port;
- int _errno;
+ mp_uint_t port = 0;
+ int _errno = 0;
mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
if (ret < 0) {
- if (_errno == EAGAIN && self->sock_base.has_timeout) {
- mp_raise_msg(&mp_type_TimeoutError, "timed out");
+ if (_errno == MP_EAGAIN && self->sock_base.has_timeout) {
+ mp_raise_OSError(MP_ETIMEDOUT);
}
mp_raise_OSError(-_errno);
}
@@ -501,13 +743,13 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
// ipv4 only
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
- int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET);
+ int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET);
if (result < 0) {
mp_raise_OSError(-result);
}
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
- tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
- tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM);
+ tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET);
+ tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM);
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
@@ -521,18 +763,15 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
{ 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 },
- // class exceptions
- { MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_type_TimeoutError },
-
// class constants
- { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(SL_AF_INET) },
- { 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_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SL_SOCK_DGRAM) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_SEC), MP_OBJ_NEW_SMALL_INT(SL_SEC_SOCKET) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
- { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(SL_IPPROTO_TCP) },
+ { MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(SL_IPPROTO_UDP) },
};
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
diff --git a/cc3200/mods/modussl.c b/cc3200/mods/modussl.c
index 7a4787b6b..95ecdbce7 100644
--- a/cc3200/mods/modussl.c
+++ b/cc3200/mods/modussl.c
@@ -25,7 +25,6 @@
*/
#include <stdint.h>
-#include <std.h>
#include "simplelink.h"
#include "py/mpconfig.h"
diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c
index d9b018350..2a0d3bf63 100644
--- a/cc3200/mods/modwlan.c
+++ b/cc3200/mods/modwlan.c
@@ -26,7 +26,7 @@
#include <stdint.h>
#include <stdbool.h>
-#include "std.h"
+#include <stdio.h>
#include "simplelink.h"
#include "py/mpconfig.h"
@@ -35,13 +35,8 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "py/mphal.h"
-#include "inc/hw_types.h"
-#include "inc/hw_ints.h"
-#include "inc/hw_memmap.h"
-#include "rom_map.h"
-#include "prcm.h"
-#include "timeutils.h"
-#include "netutils.h"
+#include "lib/timeutils/timeutils.h"
+#include "lib/netutils/netutils.h"
#include "modnetwork.h"
#include "modusocket.h"
#include "modwlan.h"
@@ -117,26 +112,6 @@ typedef enum{
#define ASSERT_ON_ERROR(x) ASSERT((x) >= 0)
-#define IPV4_ADDR_STR_LEN_MAX (16)
-
-#define WLAN_MAX_RX_SIZE 16000
-#define WLAN_MAX_TX_SIZE 1476
-
-#define MAKE_SOCKADDR(addr, ip, port) sockaddr addr; \
- addr.sa_family = AF_INET; \
- addr.sa_data[0] = port >> 8; \
- addr.sa_data[1] = port; \
- addr.sa_data[2] = ip[3]; \
- addr.sa_data[3] = ip[2]; \
- addr.sa_data[4] = ip[1]; \
- addr.sa_data[5] = ip[0];
-
-#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
- ip[0] = addr.sa_data[5]; \
- ip[1] = addr.sa_data[4]; \
- ip[2] = addr.sa_data[3]; \
- ip[3] = addr.sa_data[2];
-
/******************************************************************************
DECLARE PRIVATE DATA
******************************************************************************/
@@ -161,7 +136,9 @@ STATIC const mp_irq_methods_t wlan_irq_methods;
/******************************************************************************
DECLARE PUBLIC DATA
******************************************************************************/
+#ifdef SL_PLATFORM_MULTI_THREADED
OsiLockObj_t wlan_LockObj;
+#endif
/******************************************************************************
DECLARE PRIVATE FUNCTIONS
@@ -396,14 +373,18 @@ void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) {
__attribute__ ((section (".boot")))
void wlan_pre_init (void) {
// create the wlan lock
+ #ifdef SL_PLATFORM_MULTI_THREADED
ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock"));
+ #endif
}
void wlan_first_start (void) {
if (wlan_obj.mode < 0) {
CLR_STATUS_BIT_ALL(wlan_obj.status);
wlan_obj.mode = sl_Start(0, 0, 0);
+ #ifdef SL_PLATFORM_MULTI_THREADED
sl_LockObjUnlock (&wlan_LockObj);
+ #endif
}
// get the mac address
@@ -512,7 +493,9 @@ void wlan_update(void) {
void wlan_stop (uint32_t timeout) {
wlan_servers_stop();
+ #ifdef SL_PLATFORM_MULTI_THREADED
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
+ #endif
sl_Stop(timeout);
wlan_clear_data();
wlan_obj.mode = -1;
@@ -568,11 +551,15 @@ STATIC void wlan_clear_data (void) {
STATIC void wlan_reenable (SlWlanMode_t mode) {
// stop and start again
+ #ifdef SL_PLATFORM_MULTI_THREADED
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
+ #endif
sl_Stop(SL_STOP_TIMEOUT);
wlan_clear_data();
wlan_obj.mode = sl_Start(0, 0, 0);
+ #ifdef SL_PLATFORM_MULTI_THREADED
sl_LockObjUnlock (&wlan_LockObj);
+ #endif
ASSERT (wlan_obj.mode == mode);
}
@@ -810,8 +797,9 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
wlan_validate_channel(channel);
// get the antenna type
- uint8_t antenna = args[4].u_int;
+ uint8_t antenna = 0;
#if MICROPY_HW_ANTENNA_DIVERSITY
+ antenna = args[4].u_int;
wlan_validate_antenna(antenna);
#endif
@@ -827,7 +815,9 @@ STATIC const mp_arg_t wlan_init_args[] = {
{ MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
{ MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
+ #if MICROPY_HW_ANTENNA_DIVERSITY
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
+ #endif
};
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
// parse args
@@ -846,7 +836,7 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
if (n_args > 1 || n_kw > 0) {
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// start the peripheral
wlan_init_helper(self, &args[1]);
@@ -870,7 +860,7 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
// check for correct wlan mode
if (wlan_obj.mode == ROLE_AP) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
Sl_WlanNetworkEntry_t wlanEntry;
@@ -924,7 +914,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
// check for the correct wlan mode
if (wlan_obj.mode == ROLE_AP) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
// parse args
@@ -972,7 +962,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
modwlan_Status_t status;
status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout);
if (status == MODWLAN_ERROR_TIMEOUT) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_ETIMEDOUT);
} else if (status == MODWLAN_ERROR_INVALID_PARAMS) {
mp_raise_ValueError(mpexception_value_invalid_arguments);
}
@@ -1003,7 +993,7 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
// check the interface id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_EPERM);
}
// get the configuration
@@ -1234,13 +1224,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
// strcpy(urn, p);
//
// if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) {
-// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+// mp_raise_OSError(MP_EIO);
// }
// }
// else {
// // get the URN
// if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) {
-// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+// mp_raise_OSError(MP_EIO);
// }
// return mp_obj_new_str(urn, (len - 1), false);
// }
@@ -1254,9 +1244,9 @@ STATIC mp_obj_t wlan_print_ver(void) {
byte config_opt = SL_DEVICE_GENERAL_VERSION;
byte config_len = sizeof(ver);
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver);
- printf("NWP: %d.%d.%d.%d\n", ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2], ver.NwpVersion[3]);
- printf("MAC: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.FwVersion[0], ver.ChipFwAndPhyVersion.FwVersion[1],
- ver.ChipFwAndPhyVersion.FwVersion[2], ver.ChipFwAndPhyVersion.FwVersion[3]);
+ printf("NWP: %d.%d.%d.%d\n", (int)ver.NwpVersion[0], (int)ver.NwpVersion[1], (int)ver.NwpVersion[2], (int)ver.NwpVersion[3]);
+ printf("MAC: %d.%d.%d.%d\n", (int)ver.ChipFwAndPhyVersion.FwVersion[0], (int)ver.ChipFwAndPhyVersion.FwVersion[1],
+ (int)ver.ChipFwAndPhyVersion.FwVersion[2], (int)ver.ChipFwAndPhyVersion.FwVersion[3]);
printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1],
ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]);
return mp_const_none;
@@ -1288,8 +1278,10 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WEP) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
+ #if MICROPY_HW_ANTENNA_DIVERSITY
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_INTERNAL) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_EXT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_EXTERNAL) },
+ #endif
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANY_EVENT), MP_OBJ_NEW_SMALL_INT(MODWLAN_WIFI_EVENT_ANY) },
};
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
@@ -1309,221 +1301,3 @@ STATIC const mp_irq_methods_t wlan_irq_methods = {
.disable = wlan_lpds_irq_disable,
.flags = wlan_irq_flags,
};
-
-/******************************************************************************/
-// Micro Python bindings; WLAN socket
-
-int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
- uint32_t ip;
- int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
- out_ip[0] = ip;
- out_ip[1] = ip >> 8;
- out_ip[2] = ip >> 16;
- out_ip[3] = ip >> 24;
- return result;
-}
-
-int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
- int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto);
- if (sd < 0) {
- *_errno = sd;
- return -1;
- }
- s->sock_base.sd = sd;
- return 0;
-}
-
-void wlan_socket_close(mod_network_socket_obj_t *s) {
- // this is to prevent the finalizer to close a socket that failed when being created
- if (s->sock_base.sd >= 0) {
- modusocket_socket_delete(s->sock_base.sd);
- sl_Close(s->sock_base.sd);
- s->sock_base.sd = -1;
- }
-}
-
-int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr));
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
- int ret = sl_Listen(s->sock_base.sd, backlog);
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
- // accept incoming connection
- int16_t sd;
- sockaddr addr;
- socklen_t addr_len = sizeof(addr);
-
- sd = sl_Accept(s->sock_base.sd, &addr, &addr_len);
- // save the socket descriptor
- s2->sock_base.sd = sd;
- if (sd < 0) {
- *_errno = sd;
- return -1;
- }
-
- // return ip and port
- UNPACK_SOCKADDR(addr, ip, *port);
- return 0;
-}
-
-int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr));
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
- mp_int_t bytes = 0;
- if (len > 0) {
- bytes = sl_Send(s->sock_base.sd, (const void *)buf, len, 0);
- }
- if (bytes <= 0) {
- *_errno = bytes;
- return -1;
- }
- return bytes;
-}
-
-int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
- int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
- if (ret < 0) {
- *_errno = ret;
- return -1;
- }
- return ret;
-}
-
-int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
- MAKE_SOCKADDR(addr, ip, port)
- int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr));
- if (ret < 0) {
- *_errno = ret;
- return -1;
- }
- return ret;
-}
-
-int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
- sockaddr addr;
- socklen_t addr_len = sizeof(addr);
- mp_int_t ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
- if (ret < 0) {
- *_errno = ret;
- return -1;
- }
- UNPACK_SOCKADDR(addr, ip, *port);
- return ret;
-}
-
-int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
- int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen);
- if (ret < 0) {
- *_errno = ret;
- return -1;
- }
- return 0;
-}
-
-int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) {
- int ret;
- bool has_timeout;
- if (timeout_s == 0 || timeout_s == -1) {
- SlSockNonblocking_t option;
- if (timeout_s == 0) {
- // set non-blocking mode
- option.NonblockingEnabled = 1;
- } else {
- // set blocking mode
- option.NonblockingEnabled = 0;
- }
- ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_NONBLOCKING, &option, sizeof(option));
- has_timeout = false;
- } else {
- // set timeout
- struct SlTimeval_t timeVal;
- timeVal.tv_sec = timeout_s; // seconds
- timeVal.tv_usec = 0; // microseconds. 10000 microseconds resolution
- ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_RCVTIMEO, &timeVal, sizeof(timeVal));
- has_timeout = true;
- }
-
- if (ret != 0) {
- *_errno = ret;
- return -1;
- }
-
- s->sock_base.has_timeout = has_timeout;
- return 0;
-}
-
-int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
- mp_int_t ret;
- if (request == MP_STREAM_POLL) {
- mp_uint_t flags = arg;
- ret = 0;
- int32_t sd = s->sock_base.sd;
-
- // init fds
- fd_set rfds, wfds, xfds;
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&xfds);
-
- // set fds if needed
- if (flags & MP_STREAM_POLL_RD) {
- FD_SET(sd, &rfds);
- }
- if (flags & MP_STREAM_POLL_WR) {
- FD_SET(sd, &wfds);
- }
- if (flags & MP_STREAM_POLL_HUP) {
- FD_SET(sd, &xfds);
- }
-
- // call simplelink's select with minimum timeout
- SlTimeval_t tv;
- tv.tv_sec = 0;
- tv.tv_usec = 1;
- int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
-
- // check for errors
- if (nfds == -1) {
- *_errno = nfds;
- return -1;
- }
-
- // check return of select
- if (FD_ISSET(sd, &rfds)) {
- ret |= MP_STREAM_POLL_RD;
- }
- if (FD_ISSET(sd, &wfds)) {
- ret |= MP_STREAM_POLL_WR;
- }
- if (FD_ISSET(sd, &xfds)) {
- ret |= MP_STREAM_POLL_HUP;
- }
- } else {
- *_errno = EINVAL;
- ret = MP_STREAM_ERROR;
- }
- return ret;
-}
-
diff --git a/cc3200/mods/modwlan.h b/cc3200/mods/modwlan.h
index 5899f87b2..3bfd1fbbf 100644
--- a/cc3200/mods/modwlan.h
+++ b/cc3200/mods/modwlan.h
@@ -97,19 +97,4 @@ extern bool wlan_is_connected (void);
extern void wlan_set_current_time (uint32_t seconds_since_2000);
extern void wlan_off_on (void);
-extern int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family);
-extern int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno);
-extern void wlan_socket_close(mod_network_socket_obj_t *s);
-extern int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
-extern int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno);
-extern int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno);
-extern int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
-extern int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno);
-extern int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno);
-extern int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
-extern int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
-extern int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
-extern int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno);
-extern int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno);
-
#endif /* MODWLAN_H_ */
diff --git a/cc3200/mods/pybadc.c b/cc3200/mods/pybadc.c
index e63bebbd0..696e7650b 100644
--- a/cc3200/mods/pybadc.c
+++ b/cc3200/mods/pybadc.c
@@ -33,6 +33,7 @@
#include "py/runtime.h"
#include "py/binary.h"
#include "py/gc.h"
+#include "py/mperrno.h"
#include "bufhelper.h"
#include "inc/hw_types.h"
#include "inc/hw_adc.h"
@@ -104,7 +105,7 @@ STATIC void pyb_adc_init (pyb_adc_obj_t *self) {
STATIC void pyb_adc_check_init(void) {
// not initialized
if (!pyb_adc_obj.enabled) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
}
@@ -149,7 +150,7 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// check the number of bits
@@ -206,7 +207,7 @@ STATIC mp_obj_t adc_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
if (args[0].u_obj != MP_OBJ_NULL) {
ch_id = mp_obj_get_int(args[0].u_obj);
if (ch_id >= PYB_ADC_NUM_CHANNELS) {
- mp_raise_ValueError(mpexception_os_resource_not_avaliable);
+ mp_raise_ValueError(mpexception_value_invalid_arguments);
} else if (args[1].u_obj != mp_const_none) {
uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
if (ch_id != pin_ch_id) {
@@ -277,7 +278,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
// the channel must be enabled
if (!self->enabled) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
// wait until a new value is available
diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c
index 32451802d..658b2bfcd 100644
--- a/cc3200/mods/pybi2c.c
+++ b/cc3200/mods/pybi2c.c
@@ -30,6 +30,7 @@
#include "py/mpstate.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "bufhelper.h"
#include "inc/hw_types.h"
@@ -144,7 +145,7 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
// not initialized
if (!self->baudrate) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
}
@@ -256,7 +257,7 @@ STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) {
// receive the data
if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
}
@@ -275,7 +276,7 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
// Read the specified length of data
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
}
}
@@ -341,7 +342,7 @@ STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// setup the object
@@ -445,7 +446,7 @@ STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m
// send the data
if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
// return the number of bytes written
@@ -514,7 +515,7 @@ STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args,
return mp_obj_new_int(bufinfo.len);
}
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c
index db00f4939..ddc26faf9 100644
--- a/cc3200/mods/pybrtc.c
+++ b/cc3200/mods/pybrtc.c
@@ -25,11 +25,10 @@
* THE SOFTWARE.
*/
-#include <std.h>
-
#include "py/mpconfig.h"
#include "py/obj.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
@@ -294,7 +293,7 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// setup the object
@@ -362,7 +361,7 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
// check the alarm id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
uint32_t f_seconds;
@@ -397,7 +396,7 @@ STATIC mp_obj_t pyb_rtc_alarm_left (mp_uint_t n_args, const mp_obj_t *args) {
// only alarm id 0 is available
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// get the current time
@@ -415,7 +414,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc
STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
// only alarm id 0 is available
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// disable the alarm
pyb_rtc_disable_alarm();
diff --git a/cc3200/mods/pybsd.c b/cc3200/mods/pybsd.c
index 937b8599d..306baea8b 100644
--- a/cc3200/mods/pybsd.c
+++ b/cc3200/mods/pybsd.c
@@ -27,6 +27,7 @@
#include "py/mpconfig.h"
#include "py/obj.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
#include "extmod/vfs_fat.h"
@@ -108,7 +109,7 @@ STATIC mp_obj_t pyb_sd_init_helper (pybsd_obj_t *self, const mp_arg_val_t *args)
pyb_sd_hw_init (self);
if (sd_disk_init() != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
// register it with the sleep module
@@ -133,7 +134,7 @@ STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// setup and initialize the object
diff --git a/cc3200/mods/pybspi.c b/cc3200/mods/pybspi.c
index 6fc7ee62d..3cd384266 100644
--- a/cc3200/mods/pybspi.c
+++ b/cc3200/mods/pybspi.c
@@ -30,6 +30,7 @@
#include "py/mpstate.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "bufhelper.h"
#include "inc/hw_types.h"
#include "inc/hw_mcspi.h"
@@ -131,7 +132,7 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
if (!self->baudrate) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
// send and receive the data
MAP_SPICSEnable(GSPI_BASE);
@@ -234,7 +235,7 @@ STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
// check the peripheral id
if (args[0].u_int != 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// setup the object
diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c
index 0eeb6eefd..d25ac6c2b 100644
--- a/cc3200/mods/pybtimer.c
+++ b/cc3200/mods/pybtimer.c
@@ -34,6 +34,7 @@
#include "py/nlr.h"
#include "py/runtime.h"
#include "py/gc.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "inc/hw_types.h"
#include "inc/hw_ints.h"
@@ -329,7 +330,7 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
// create a new Timer object
int32_t timer_idx = mp_obj_get_int(args[0]);
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
@@ -370,7 +371,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
// verify that the timer has been already initialized
if (!tim->config) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
// invalid channel
diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c
index dceb842d5..bab2b3d22 100644
--- a/cc3200/mods/pybuart.c
+++ b/cc3200/mods/pybuart.c
@@ -279,7 +279,7 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
STATIC void uart_check_init(pyb_uart_obj_t *self) {
// not initialized
if (!self->baudrate) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
}
@@ -471,7 +471,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
}
if (uart_id > PYB_UART_1) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
// get the correct uart instance
@@ -596,8 +596,8 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
// wait for first char to become available
if (!uart_rx_wait(self)) {
- // return EAGAIN error to indicate non-blocking (then read() method returns None)
- *errcode = EAGAIN;
+ // return MP_EAGAIN error to indicate non-blocking (then read() method returns None)
+ *errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@@ -619,7 +619,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
// write the data
if (!uart_tx_strn(self, buf, size)) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
+ mp_raise_OSError(MP_EIO);
}
return size;
}
@@ -639,7 +639,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
ret |= MP_STREAM_POLL_WR;
}
} else {
- *errcode = EINVAL;
+ *errcode = MP_EINVAL;
ret = MP_STREAM_ERROR;
}
return ret;
diff --git a/cc3200/mods/pybwdt.c b/cc3200/mods/pybwdt.c
index b4c847268..76c701ca0 100644
--- a/cc3200/mods/pybwdt.c
+++ b/cc3200/mods/pybwdt.c
@@ -29,6 +29,7 @@
#include "py/mpconfig.h"
#include "py/obj.h"
#include "py/runtime.h"
+#include "py/mperrno.h"
#include "py/mphal.h"
#include "inc/hw_types.h"
#include "inc/hw_gpio.h"
@@ -100,14 +101,14 @@ STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_wdt_init_args, args);
if (args[0].u_obj != mp_const_none && mp_obj_get_int(args[0].u_obj) > 0) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
+ mp_raise_OSError(MP_ENODEV);
}
uint timeout_ms = args[1].u_int;
if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) {
mp_raise_ValueError(mpexception_value_invalid_arguments);
}
if (pyb_wdt_obj.running) {
- mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
+ mp_raise_OSError(MP_EPERM);
}
// Enable the WDT peripheral clock
diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h
index 944a6c071..a8dc0cfeb 100644
--- a/cc3200/mpconfigport.h
+++ b/cc3200/mpconfigport.h
@@ -75,10 +75,10 @@
#define MICROPY_STREAMS_NON_BLOCK (1)
#define MICROPY_MODULE_WEAK_LINKS (1)
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
+#define MICROPY_USE_INTERNAL_ERRNO (1)
#define MICROPY_VFS (1)
#define MICROPY_VFS_FAT (1)
#define MICROPY_PY_ASYNC_AWAIT (0)
-#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
@@ -106,6 +106,8 @@
#define MICROPY_PY_CMATH (0)
#define MICROPY_PY_IO (1)
#define MICROPY_PY_IO_FILEIO (1)
+#define MICROPY_PY_UERRNO (1)
+#define MICROPY_PY_UERRNO_ERRORCODE (0)
#define MICROPY_PY_THREAD (1)
#define MICROPY_PY_THREAD_GIL (1)
#define MICROPY_PY_UBINASCII (0)
@@ -121,6 +123,14 @@
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
+// We define our own list of errno constants to include in uerrno module
+#define MICROPY_PY_UERRNO_LIST \
+ X(EPERM) \
+ X(EIO) \
+ X(ENODEV) \
+ X(EINVAL) \
+ X(ETIMEDOUT) \
+
// TODO these should be generic, not bound to fatfs
#define mp_type_fileio fatfs_type_fileio
#define mp_type_textio fatfs_type_textio
@@ -160,6 +170,7 @@ extern const struct _mp_obj_module_t mp_module_ussl;
{ MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
+ { MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
diff --git a/cc3200/simplelink/user.h b/cc3200/simplelink/user.h
index af3f14e34..d3f6d4adf 100644
--- a/cc3200/simplelink/user.h
+++ b/cc3200/simplelink/user.h
@@ -163,7 +163,7 @@ extern "C" {
\warning
*/
-#define SL_INC_STD_BSD_API_NAMING
+/* #define SL_INC_STD_BSD_API_NAMING */
/*!
diff --git a/cc3200/telnet/telnet.c b/cc3200/telnet/telnet.c
index e90bf928f..26e45a75f 100644
--- a/cc3200/telnet/telnet.c
+++ b/cc3200/telnet/telnet.c
@@ -296,23 +296,23 @@ static void telnet_wait_for_enabled (void) {
static bool telnet_create_socket (void) {
SlSockNonblocking_t nonBlockingOption;
- sockaddr_in sServerAddress;
+ SlSockAddrIn_t sServerAddress;
_i16 result;
// Open a socket for telnet
- ASSERT ((telnet_data.sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0);
+ ASSERT ((telnet_data.sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP)) > 0);
if (telnet_data.sd > 0) {
// add the socket to the network administration
modusocket_socket_add(telnet_data.sd, false);
// Enable non-blocking mode
nonBlockingOption.NonblockingEnabled = 1;
- ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
+ ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
// Bind the socket to a port number
- sServerAddress.sin_family = AF_INET;
- sServerAddress.sin_addr.s_addr = INADDR_ANY;
- sServerAddress.sin_port = htons(TELNET_PORT);
+ sServerAddress.sin_family = SL_AF_INET;
+ sServerAddress.sin_addr.s_addr = SL_INADDR_ANY;
+ sServerAddress.sin_port = sl_Htons(TELNET_PORT);
ASSERT ((result |= sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
@@ -330,7 +330,7 @@ static bool telnet_create_socket (void) {
static void telnet_wait_for_connection (void) {
SlSocklen_t in_addrSize;
- sockaddr_in sClientAddress;
+ SlSockAddrIn_t sClientAddress;
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
telnet_data.n_sd = sl_Accept(telnet_data.sd, (SlSockAddr_t *)&sClientAddress, (SlSocklen_t *)&in_addrSize);
diff --git a/docs/Makefile b/docs/Makefile
index d81d11eeb..e9c128e90 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -2,10 +2,14 @@
#
# You can set these variables from the command line.
+PYTHON = python3
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build/$(MICROPY_PORT)
+CPYDIFFDIR = ../tools
+CPYDIFF = gen-cpydiff.py
+GENRSTDIR = genrst
# Run "make FORCE= ..." to avoid rebuilding from scratch (and risk
# producing incorrect docs).
FORCE = -E
@@ -48,11 +52,18 @@ help:
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
+ @echo " cpydiff to generate the MicroPython differences from CPython"
clean:
rm -rf $(BUILDDIR)/*
+ rm -f $(GENRSTDIR)/*
-html:
+cpydiff:
+ @echo "Generating MicroPython Differences."
+ rm -f $(GENRSTDIR)/*
+ cd $(CPYDIFFDIR) && $(PYTHON) $(CPYDIFF)
+
+html: cpydiff
$(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
@@ -106,20 +117,20 @@ epub:
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-latex:
+latex: cpydiff
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
-latexpdf:
+latexpdf: cpydiff
$(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-latexpdfja:
+latexpdfja: cpydiff
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
diff --git a/docs/differences/index_template.txt b/docs/differences/index_template.txt
new file mode 100644
index 000000000..6ade2c2da
--- /dev/null
+++ b/docs/differences/index_template.txt
@@ -0,0 +1,8 @@
+MicroPython Differences from CPython
+====================================
+
+The operations listed in this section produce conflicting results in MicroPython when compared to standard Python.
+
+.. toctree::
+ :maxdepth: 2
+
diff --git a/docs/esp8266/tutorial/intro.rst b/docs/esp8266/tutorial/intro.rst
index fe824cfff..e7a38d3e5 100644
--- a/docs/esp8266/tutorial/intro.rst
+++ b/docs/esp8266/tutorial/intro.rst
@@ -72,15 +72,17 @@ For best results it is recommended to first erase the entire flash of your
device before putting on new MicroPython firmware.
Currently we only support esptool.py to copy across the firmware. You can find
-this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
-using pip (at least version 1.2.1 is required)::
+this tool here: `<https://github.com/espressif/esptool/>`__, or install it
+using pip::
pip install esptool
-It requires Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in
-the command above. Any other
-flashing program should work, so feel free to try them out, or refer to the
-documentation for your board to see its recommendations.
+Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer).
+An older version (at least 1.2.1 is needed) works fine but will require Python
+2.7.
+
+Any other flashing program should work, so feel free to try them out or refer
+to the documentation for your board to see its recommendations.
Using esptool.py you can erase the flash with the command::
@@ -88,7 +90,7 @@ Using esptool.py you can erase the flash with the command::
And then deploy the new firmware using::
- esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-2016-05-03-v1.8.bin
+ esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin
You might need to change the "port" setting to something else relevant for your
PC. You may also need to reduce the baudrate if you get errors when flashing
@@ -99,7 +101,7 @@ For some boards with a particular FlashROM configuration (e.g. some variants of
a NodeMCU board) you may need to use the following command to deploy
the firmware (note the ``-fm dio`` option)::
- esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-2016-05-03-v1.8.bin
+ esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin
If the above commands run without error then MicroPython should be installed on
your board!
@@ -158,7 +160,9 @@ after it, here are troubleshooting recommendations:
esptool.py, which had a different programming algorithm::
pip install esptool==1.0.1
This version doesn't support ``--flash_size=detect`` option, so you will
- need to specify FlashROM size explicitly (in megabits).
+ need to specify FlashROM size explicitly (in megabits). It also requires
+ Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in the
+ command above.
* The ``--flash_size`` option in the commands above is mandatory. Omitting
it will lead to a corrupted firmware.
@@ -179,7 +183,7 @@ after it, here are troubleshooting recommendations:
application in the ESP8266 community.
* If you still experience problems with even flashing the firmware, please
- refer to esptool.py project page, https://github.com/themadinventor/esptool
+ refer to esptool.py project page, https://github.com/espressif/esptool
for additional documentation and bug tracker where you can report problems.
* If you are able to flash firmware, but ``--verify`` option or
diff --git a/docs/esp8266_contents.rst b/docs/esp8266_contents.rst
index 30def3df2..7c35460bd 100644
--- a/docs/esp8266_contents.rst
+++ b/docs/esp8266_contents.rst
@@ -8,4 +8,5 @@ MicroPython documentation contents
esp8266/tutorial/index.rst
library/index.rst
reference/index.rst
+ genrst/index.rst
license.rst
diff --git a/docs/esp8266_index.rst b/docs/esp8266_index.rst
index 82de9d6df..8654c43aa 100644
--- a/docs/esp8266_index.rst
+++ b/docs/esp8266_index.rst
@@ -5,6 +5,7 @@ MicroPython documentation and references
esp8266/quickref.rst
library/index.rst
+ genrst/index.rst
license.rst
esp8266_contents.rst
diff --git a/docs/library/framebuf.rst b/docs/library/framebuf.rst
new file mode 100644
index 000000000..657ad461b
--- /dev/null
+++ b/docs/library/framebuf.rst
@@ -0,0 +1,129 @@
+:mod:`framebuf` --- Frame buffer manipulation
+=============================================
+
+.. module:: framebuf
+ :synopsis: Frame buffer manipulation
+
+This module provides a general frame buffer which can be used to create
+bitmap images, which can then be sent to a display.
+
+class FrameBuffer
+-----------------
+
+The FrameBuffer class provides a pixel buffer which can be drawn upon with
+pixels, lines, rectangles, text and even other FrameBuffer's. It is useful
+when generating output for displays.
+
+For example::
+
+ import framebuf
+
+ # FrameBuffer needs 2 bytes for every RGB565 pixel
+ fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
+
+ fbuf.fill(0)
+ fbuf.text('MicroPython!', 0, 0, 0xffff)
+ fbuf.hline(0, 10, 96, 0xffff)
+
+Constructors
+------------
+
+.. class:: FrameBuffer(buffer, width, height, format, stride=width)
+
+ Construct a FrameBuffer object. The parameters are:
+
+ - `buffer` is an object with a buffer protocol which must be large
+ enough to contain every pixel defined by the width, height and
+ format of the FrameBuffer.
+ - `width` is the width of the FrameBuffer in pixels
+ - `height` is the height of the FrameBuffer in pixels
+ - `format` specifies the type of pixel used in the FrameBuffer;
+ valid values are ``framebuf.MVLSB``, ``framebuf.RGB565``
+ and ``framebuf.GS4_HMSB``. MVLSB is monochrome 8-bit color,
+ RGB565 is RGB 16-bit color, and GS4_HMSB is grayscale 4-bit color.
+ Where a color value c is passed to a method, c is a small integer
+ with an encoding that is dependent on the format of the FrameBuffer.
+ - `stride` is the number of pixels between each horizontal line
+ of pixels in the FrameBuffer. This defaults to `width` but may
+ need adjustments when implementing a FrameBuffer within another
+ larger FrameBuffer or screen. The `buffer` size must accommodate
+ an increased step size.
+
+ One must specify valid `buffer`, `width`, `height`, `format` and
+ optionally `stride`. Invalid `buffer` size or dimensions may lead to
+ unexpected errors.
+
+Drawing primitive shapes
+------------------------
+
+The following methods draw shapes onto the FrameBuffer.
+
+.. method:: FrameBuffer.fill(c)
+
+ Fill the entire FrameBuffer with the specified color.
+
+.. method:: FrameBuffer.pixel(x, y[, c])
+
+ If `c` is not given, get the color value of the specified pixel.
+ If `c` is given, set the specified pixel to the given color.
+
+.. method:: FrameBuffer.hline(x, y, w, c)
+.. method:: FrameBuffer.vline(x, y, h, c)
+.. method:: FrameBuffer.line(x1, y1, x2, y2, c)
+
+ Draw a line from a set of coordinates using the given color and
+ a thickness of 1 pixel. The `line` method draws the line up to
+ a second set of coordinates whereas the `hline` and `vline`
+ methods draw horizontal and vertical lines respectively up to
+ a given length.
+
+.. method:: FrameBuffer.rect(x, y, w, h, c)
+.. method:: FrameBuffer.fill_rect(x, y, w, h, c)
+
+ Draw a rectangle at the given location, size and color. The `rect`
+ method draws only a 1 pixel outline whereas the `fill_rect` method
+ draws both the outline and interior.
+
+Drawing text
+------------
+
+.. method:: FrameBuffer.text(s, x, y[, c])
+
+ Write text to the FrameBuffer using the the coordinates as the upper-left
+ corner of the text. The color of the text can be defined by the optional
+ argument but is otherwise a default value of 1. All characters have
+ dimensions of 8x8 pixels and there is currently no way to change the font.
+
+
+Other methods
+-------------
+
+.. method:: FrameBuffer.scroll(xstep, ystep)
+
+ Shift the contents of the FrameBuffer by the given vector. This may
+ leave a footprint of the previous colors in the FrameBuffer.
+
+.. method:: FrameBuffer.blit(fbuf, x, y[, key])
+
+ Draw another FrameBuffer on top of the current one at the given coordinates.
+ If `key` is specified then it should be a color integer and the
+ corresponding color will be considered transparent: all pixels with that
+ color value will not be drawn.
+
+ This method works between FrameBuffer's utilising different formats, but the
+ resulting colors may be unexpected due to the mismatch in color formats.
+
+Constants
+---------
+
+.. data:: framebuf.MVLSB
+
+ Monochrome (1-bit) color format
+
+.. data:: framebuf.RGB565
+
+ Red Green Blue (16-bit, 5+6+5) color format
+
+.. data:: framebuf.GS4_HMSB
+
+ Grayscale (4-bit) color format
diff --git a/docs/library/index.rst b/docs/library/index.rst
index a110ef0d2..5d64d01f7 100644
--- a/docs/library/index.rst
+++ b/docs/library/index.rst
@@ -153,6 +153,7 @@ the following libraries.
.. toctree::
:maxdepth: 1
+ framebuf.rst
machine.rst
micropython.rst
network.rst
diff --git a/docs/library/lcd160cr.rst b/docs/library/lcd160cr.rst
index 56af097a1..76828d32d 100644
--- a/docs/library/lcd160cr.rst
+++ b/docs/library/lcd160cr.rst
@@ -304,6 +304,10 @@ Advanced commands
the 16-bit RGB values for the pixels, and they will be written to the area
specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner.
+ The `framebuf <framebuf.html>`_ module can be used to construct frame buffers
+ and provides drawing primitives. Using a frame buffer will improve
+ performance of animations when compared to drawing directly to the screen.
+
.. method:: LCD160CR.set_scroll(on)
Turn scrolling on or off. This controls globally whether any window regions will
@@ -341,7 +345,9 @@ Advanced commands
.. method:: LCD160CR.jpeg(buf)
- Display a JPEG. `buf` should contain the entire JPEG data.
+ Display a JPEG. `buf` should contain the entire JPEG data. JPEG data should
+ not include EXIF information. The following encodings are supported: Baseline
+ DCT, Huffman coding, 8 bits per sample, 3 color components, YCbCr4:2:2.
The origin of the JPEG is set by :meth:`LCD160CR.set_pos`.
.. method:: LCD160CR.jpeg_start(total_len)
diff --git a/docs/library/machine.rst b/docs/library/machine.rst
index 50884e7be..c677bcbf0 100644
--- a/docs/library/machine.rst
+++ b/docs/library/machine.rst
@@ -134,24 +134,24 @@ Constants
---------
.. data:: machine.IDLE
-.. data:: machine.SLEEP
-.. data:: machine.DEEPSLEEP
+ machine.SLEEP
+ machine.DEEPSLEEP
- irq wake values
+ IRQ wake values.
.. data:: machine.PWRON_RESET
-.. data:: machine.HARD_RESET
-.. data:: machine.WDT_RESET
-.. data:: machine.DEEPSLEEP_RESET
-.. data:: machine.SOFT_RESET
+ machine.HARD_RESET
+ machine.WDT_RESET
+ machine.DEEPSLEEP_RESET
+ machine.SOFT_RESET
- reset causes
+ Reset causes.
.. data:: machine.WLAN_WAKE
-.. data:: machine.PIN_WAKE
-.. data:: machine.RTC_WAKE
+ machine.PIN_WAKE
+ machine.RTC_WAKE
- wake reasons
+ Wake-up reasons.
Classes
-------
diff --git a/docs/library/uhashlib.rst b/docs/library/uhashlib.rst
index 223c72dfe..2c340e40b 100644
--- a/docs/library/uhashlib.rst
+++ b/docs/library/uhashlib.rst
@@ -1,33 +1,41 @@
-:mod:`uhashlib` -- hashing algorithm
-====================================
+:mod:`uhashlib` -- hashing algorithms
+=====================================
.. module:: uhashlib
- :synopsis: hashing algorithm
+ :synopsis: hashing algorithms
-.. only:: port_pyboard
+This module implements binary data hashing algorithms. The exact inventory
+of available algorithms depends on a board. Among the algorithms which may
+be implemented:
- This module implements binary data hashing algorithms. Currently, it
- implements SHA256 algorithm. Choosing SHA256 was a deliberate choice,
- as a modern, cryptographically secure algorithm. This means that a
- single algorithm can cover both use cases of "any hash algorithm" and
- security-related usage, and thus save space omitting legacy algorithms
- like MD5 or SHA1.
+* SHA256 - The current generation, modern hashing algorithm (of SHA2 series).
+ It is suitable for cryptographically-secure purposes. Included in the
+ MicroPython core and any board is recommended to provide this, unless
+ it has particular code size constraints.
-.. only:: port_wipy
-
- This module implements binary data hashing algorithms. Currently, it
- implements SHA1 and SHA256 algorithms only. These two algorithms are
- more than enough for today's web applications.
+* SHA1 - A previous generation algorithm. Not recommended for new usages,
+ but SHA1 is a part of number of Internet standards and existing
+ applications, so boards targetting network connectivity and
+ interoperatiability will try to provide this.
+* MD5 - A legacy algorithm, not considered cryptographically secure. Only
+ selected boards, targetting interoperatibility with legacy applications,
+ will offer this.
Constructors
------------
-.. only:: port_pyboard
+.. class:: uhashlib.sha256([data])
- .. class:: uhashlib.sha256([data])
-
- Create a hasher object and optionally feed ``data`` into it.
+ Create an SHA256 hasher object and optionally feed ``data`` into it.
+
+.. class:: uhashlib.sha1([data])
+
+ Create an SHA1 hasher object and optionally feed ``data`` into it.
+
+.. class:: uhashlib.md5([data])
+
+ Create an MD5 hasher object and optionally feed ``data`` into it.
.. only:: port_wipy
@@ -69,11 +77,7 @@ Methods
.. method:: hash.digest()
Return hash for all data passed through hash, as a bytes object. After this
- method is called, more data cannot be fed into hash any longer.
-
- .. only:: port_wipy
-
- SHA1 hashes are 20-byte long. SHA256 hashes are 32-byte long.
+ method is called, more data cannot be fed into the hash any longer.
.. method:: hash.hexdigest()
diff --git a/docs/pyboard_contents.rst b/docs/pyboard_contents.rst
index 5ced479ef..658dd366f 100644
--- a/docs/pyboard_contents.rst
+++ b/docs/pyboard_contents.rst
@@ -9,5 +9,6 @@ MicroPython documentation contents
library/index.rst
reference/index.rst
pyboard/hardware/index.rst
+ genrst/index.rst
license.rst
diff --git a/docs/pyboard_index.rst b/docs/pyboard_index.rst
index 38ccb1ac9..4caa4cc88 100644
--- a/docs/pyboard_index.rst
+++ b/docs/pyboard_index.rst
@@ -8,6 +8,7 @@ MicroPython documentation and references
pyboard/tutorial/index.rst
library/index.rst
pyboard/hardware/index.rst
+ genrst/index.rst
license.rst
pyboard_contents.rst
diff --git a/docs/topindex.html b/docs/topindex.html
index 75039233e..3cbf21615 100644
--- a/docs/topindex.html
+++ b/docs/topindex.html
@@ -47,6 +47,10 @@
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
{% endif %}
</p>
+ <p class="biglink">
+ <a class="biglink" href="{{ pathto("genrst/index") }}">Micropython Differences</a><br/>
+ <span class="linkdescr">MicroPython operations which differ from CPython</span>
+ </p>
</td>
<td width="40%" style="padding-left:2em;">
<p class="biglink">
diff --git a/docs/unix_contents.rst b/docs/unix_contents.rst
index ec0a6f0e8..8c5a586b2 100644
--- a/docs/unix_contents.rst
+++ b/docs/unix_contents.rst
@@ -5,4 +5,5 @@ MicroPython documentation contents
library/index.rst
reference/index.rst
+ genrst/index.rst
license.rst
diff --git a/docs/unix_index.rst b/docs/unix_index.rst
index 027f24c2e..7fa1753c2 100644
--- a/docs/unix_index.rst
+++ b/docs/unix_index.rst
@@ -4,6 +4,7 @@ MicroPython documentation and references
.. toctree::
library/index.rst
+ genrst/index.rst
license.rst
unix_contents.rst
diff --git a/docs/wipy_contents.rst b/docs/wipy_contents.rst
index 2beffa236..0e50a7c6e 100644
--- a/docs/wipy_contents.rst
+++ b/docs/wipy_contents.rst
@@ -8,4 +8,5 @@ MicroPython documentation contents
wipy/tutorial/index.rst
library/index.rst
reference/index.rst
+ genrst/index.rst
license.rst
diff --git a/docs/wipy_index.rst b/docs/wipy_index.rst
index 9fe3dce89..a390aecb1 100644
--- a/docs/wipy_index.rst
+++ b/docs/wipy_index.rst
@@ -7,6 +7,7 @@ MicroPython documentation and references
wipy/general.rst
wipy/tutorial/index.rst
library/index.rst
+ genrst/index.rst
license.rst
wipy_contents.rst
diff --git a/drivers/display/lcd160cr.py b/drivers/display/lcd160cr.py
index a5da64348..0cf52f2ef 100644
--- a/drivers/display/lcd160cr.py
+++ b/drivers/display/lcd160cr.py
@@ -235,7 +235,7 @@ class LCD160CR:
self._fcmd2('<BBB', 0x19, value)
def save_to_flash(self):
- self._fcmd2('<BBB', 0x66, 'n')
+ self._send(b'\x02fn')
#### PIXEL ACCESS ####
@@ -243,13 +243,13 @@ class LCD160CR:
self._fcmd2b('<BBBBH', 0x41, x, y, c)
def get_pixel(self, x, y):
- self._fcmd2b('<BBBB', 0x61, x, y)
+ self._fcmd2('<BBBB', 0x61, x, y)
t = 1000
while t:
self.i2c.readfrom_into(self.i2c_addr, self.buf1)
if self.buf1[0] >= 2:
self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
- return self.buf[3][1] + self.buf[3][2] << 8
+ return self.buf[3][1] | self.buf[3][2] << 8
t -= 1
sleep_ms(1)
raise OSError(uerrno.ETIMEDOUT)
@@ -446,6 +446,8 @@ class LCD160CR:
self._send(s)
def jpeg_start(self, l):
+ if l > 0xffff:
+ raise ValueError('length must be 65535 or less')
self.oflush()
self._fcmd2('<BBH', 0x6a, l)
diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h
index 04b9792eb..cf4cbecd4 100644
--- a/esp8266/mpconfigport.h
+++ b/esp8266/mpconfigport.h
@@ -40,6 +40,7 @@
#define MICROPY_PY_BUILTINS_PROPERTY (1)
#define MICROPY_PY_BUILTINS_HELP (1)
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
+#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
#define MICROPY_PY___FILE__ (0)
#define MICROPY_PY_GC (1)
#define MICROPY_PY_ARRAY (1)
diff --git a/extmod/modurandom.c b/extmod/modurandom.c
index 12e56741e..4b63dace4 100644
--- a/extmod/modurandom.c
+++ b/extmod/modurandom.c
@@ -74,7 +74,7 @@ STATIC uint32_t yasmarang_randbelow(uint32_t n) {
STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
int n = mp_obj_get_int(num_in);
if (n > 32 || n == 0) {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ mp_raise_ValueError(NULL);
}
uint32_t mask = ~0;
// Beware of C undefined behavior when shifting by >= than bit size
@@ -102,7 +102,7 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
if (start > 0) {
return mp_obj_new_int(yasmarang_randbelow(start));
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ goto error;
}
} else {
mp_int_t stop = mp_obj_get_int(args[1]);
@@ -111,7 +111,7 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
if (start < stop) {
return mp_obj_new_int(start + yasmarang_randbelow(stop - start));
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ goto error;
}
} else {
// range(start, stop, step)
@@ -122,15 +122,18 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
} else if (step < 0) {
n = (stop - start + step + 1) / step;
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ goto error;
}
if (n > 0) {
return mp_obj_new_int(start + step * yasmarang_randbelow(n));
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ goto error;
}
}
}
+
+error:
+ mp_raise_ValueError(NULL);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange);
@@ -140,7 +143,7 @@ STATIC mp_obj_t mod_urandom_randint(mp_obj_t a_in, mp_obj_t b_in) {
if (a <= b) {
return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
} else {
- nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
+ mp_raise_ValueError(NULL);
}
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint);
diff --git a/extmod/modutimeq.c b/extmod/modutimeq.c
index f73b39103..1d7425bd7 100644
--- a/extmod/modutimeq.c
+++ b/extmod/modutimeq.c
@@ -4,7 +4,7 @@
* The MIT License (MIT)
*
* Copyright (c) 2014 Damien P. George
- * Copyright (c) 2016 Paul Sokolovsky
+ * Copyright (c) 2016-2017 Paul Sokolovsky
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -43,6 +43,7 @@
struct qentry {
mp_uint_t time;
+ mp_uint_t id;
mp_obj_t callback;
mp_obj_t args;
};
@@ -54,6 +55,7 @@ typedef struct _mp_obj_utimeq_t {
struct qentry items[];
} mp_obj_utimeq_t;
+STATIC mp_uint_t utimeq_id;
STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) {
return MP_OBJ_TO_PTR(heap_in);
@@ -63,6 +65,11 @@ STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
mp_uint_t item_tm = item->time;
mp_uint_t parent_tm = parent->time;
mp_uint_t res = parent_tm - item_tm;
+ if (res == 0) {
+ // TODO: This actually should use the same "ring" logic
+ // as for time, to avoid artifacts when id's overflow.
+ return item->id < parent->id;
+ }
if ((mp_int_t)res < 0) {
res += MODULO;
}
@@ -125,6 +132,7 @@ STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) {
}
mp_uint_t l = heap->len;
heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
+ heap->items[l].id = utimeq_id++;
heap->items[l].callback = args[2];
heap->items[l].args = args[3];
heap_siftdown(heap, 0, heap->len);
diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c
index 5e2f24298..0d20c1917 100644
--- a/lib/utils/pyexec.c
+++ b/lib/utils/pyexec.c
@@ -75,11 +75,15 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
} else
#endif
{
+ #if MICROPY_ENABLE_COMPILER
// source is a lexer, parse and compile the script
mp_lexer_t *lex = source;
qstr source_name = lex->source_name;
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);
+ #else
+ mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported");
+ #endif
}
// execute code
@@ -137,6 +141,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
return ret;
}
+#if MICROPY_ENABLE_COMPILER
#if MICROPY_REPL_EVENT_DRIVEN
typedef struct _repl_t {
@@ -497,6 +502,7 @@ friendly_repl_reset:
}
#endif // MICROPY_REPL_EVENT_DRIVEN
+#endif // MICROPY_ENABLE_COMPILER
int pyexec_file(const char *filename) {
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
diff --git a/minimal/README.md b/minimal/README.md
index 7c42e082e..14b8c00a3 100644
--- a/minimal/README.md
+++ b/minimal/README.md
@@ -33,3 +33,15 @@ This version of the build will work out-of-the-box on a pyboard (and
anything similar), and will give you a MicroPython REPL on UART1 at 9600
baud. Pin PA13 will also be driven high, and this turns on the red LED on
the pyboard.
+
+## Building without the built-in MicroPython compiler
+
+This minimal port can be built with the built-in MicroPython compiler
+disabled. This will reduce the firmware by about 20k on a Thumb2 machine,
+and by about 40k on 32-bit x86. Without the compiler the REPL will be
+disabled, but pre-compiled scripts can still be executed.
+
+To test out this feature, change the `MICROPY_ENABLE_COMPILER` config
+option to "0" in the mpconfigport.h file in this directory. Then
+recompile and run the firmware and it will execute the frozentest.py
+file.
diff --git a/minimal/main.c b/minimal/main.c
index 5e104e7e8..766ad6c1b 100644
--- a/minimal/main.c
+++ b/minimal/main.c
@@ -9,6 +9,7 @@
#include "py/gc.h"
#include "lib/utils/pyexec.h"
+#if MICROPY_ENABLE_COMPILER
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
if (lex == NULL) {
@@ -28,6 +29,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
}
}
+#endif
static char *stack_top;
static char heap[2048];
@@ -40,6 +42,7 @@ int main(int argc, char **argv) {
gc_init(heap, heap + sizeof(heap));
#endif
mp_init();
+ #if MICROPY_ENABLE_COMPILER
#if MICROPY_REPL_EVENT_DRIVEN
pyexec_event_repl_init();
for (;;) {
@@ -53,6 +56,9 @@ int main(int argc, char **argv) {
#endif
//do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
//do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
+ #else
+ pyexec_frozen_module("frozentest.py");
+ #endif
mp_deinit();
return 0;
}
@@ -81,6 +87,7 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void nlr_jump_fail(void *val) {
+ while (1);
}
void NORETURN __fatal_error(const char *msg) {
diff --git a/minimal/mpconfigport.h b/minimal/mpconfigport.h
index 5236babf6..e08943860 100644
--- a/minimal/mpconfigport.h
+++ b/minimal/mpconfigport.h
@@ -2,6 +2,11 @@
// options to control how Micro Python is built
+// You can disable the built-in MicroPython compiler by setting the following
+// config option to 0. If you do this then you won't get a REPL prompt, but you
+// will still be able to execute pre-compiled scripts, compiled with mpy-cross.
+#define MICROPY_ENABLE_COMPILER (1)
+
#define MICROPY_QSTR_BYTES_IN_HASH (1)
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
#define MICROPY_ALLOC_PATH_MAX (256)
diff --git a/py/compile.c b/py/compile.c
index 15e757d46..ca21d8294 100644
--- a/py/compile.c
+++ b/py/compile.c
@@ -47,8 +47,6 @@ typedef enum {
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
- PN_string, // special node for non-interned string
- PN_bytes, // special node for non-interned bytes
PN_const_object, // special node for a constant, generic Python object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
@@ -1880,8 +1878,6 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
} else {
// for non-REPL, evaluate then discard the expression
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
// do nothing with a lonely constant
} else {
@@ -2600,33 +2596,19 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn
}
#endif
-STATIC void compile_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
- // only create and load the actual str object on the last pass
- if (comp->pass != MP_PASS_EMIT) {
- EMIT_ARG(load_const_obj, mp_const_none);
- } else {
- EMIT_ARG(load_const_obj, mp_obj_new_str((const char*)pns->nodes[0], pns->nodes[1], false));
- }
-}
-
-STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
- // only create and load the actual bytes object on the last pass
- if (comp->pass != MP_PASS_EMIT) {
- EMIT_ARG(load_const_obj, mp_const_none);
- } else {
- EMIT_ARG(load_const_obj, mp_obj_new_bytes((const byte*)pns->nodes[0], pns->nodes[1]));
- }
-}
-
-STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
+STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
// nodes are 32-bit pointers, but need to extract 64-bit object
- EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
+ return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
#else
- EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
+ return (mp_obj_t)pns->nodes[0];
#endif
}
+STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
+ EMIT_ARG(load_const_obj, get_const_object(pns));
+}
+
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
STATIC const compile_function_t compile_function[] = {
// only define rules with a compile function
@@ -2637,8 +2619,6 @@ STATIC const compile_function_t compile_function[] = {
#undef c
#undef DEF_RULE
#undef DEF_RULE_NC
- compile_string,
- compile_bytes,
compile_const_object,
};
@@ -2891,7 +2871,8 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
&& MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
- || MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) {
+ || (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)
+ && MP_OBJ_IS_STR(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) {
// compile the doc string
compile_node(comp, pns->nodes[0]);
// store the doc string
diff --git a/py/emitinlinethumb.c b/py/emitinlinethumb.c
index 89bcebfea..c1a4eac5d 100644
--- a/py/emitinlinethumb.c
+++ b/py/emitinlinethumb.c
@@ -42,8 +42,6 @@ typedef enum {
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
- PN_string, // special node for non-interned string
- PN_bytes, // special node for non-interned bytes
PN_const_object, // special node for a constant, generic Python object
// define rules without a compile function
#define DEF_RULE(rule, comp, kind, ...)
diff --git a/py/map.c b/py/map.c
index c45f71e17..50d74f38f 100644
--- a/py/map.c
+++ b/py/map.c
@@ -178,8 +178,14 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) {
if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) {
if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) {
- elem->key = MP_OBJ_SENTINEL;
- // keep elem->value so that caller can access it if needed
+ // remove the found element by moving the rest of the array down
+ mp_obj_t value = elem->value;
+ --map->used;
+ memmove(elem, elem + 1, (top - elem - 1) * sizeof(*elem));
+ // put the found element after the end so the caller can access it if needed
+ elem = &map->table[map->used];
+ elem->key = MP_OBJ_NULL;
+ elem->value = value;
}
return elem;
}
@@ -187,7 +193,6 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) {
return NULL;
}
- // TODO shrink array down over any previously-freed slots
if (map->used == map->alloc) {
// TODO: Alloc policy
map->alloc += 4;
diff --git a/py/modsys.c b/py/modsys.c
index 8c368ac35..b208c88bd 100644
--- a/py/modsys.c
+++ b/py/modsys.c
@@ -32,6 +32,7 @@
#include "py/objstr.h"
#include "py/objint.h"
#include "py/stream.h"
+#include "py/smallint.h"
#if MICROPY_PY_SYS
@@ -162,12 +163,12 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
#if MICROPY_PY_SYS_MAXSIZE
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
- // INT_MAX is not representable as small int, as we know that small int
- // takes one bit for tag. So, we have little choice but to provide this
- // value. Apps also should be careful to not try to compare sys.maxsize
- // with some number (which may not fit in available int size), but instead
- // count number of significant bits in sys.maxsize.
- { MP_ROM_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(INT_MAX >> 1) },
+ // Maximum mp_int_t value is not representable as small int, so we have
+ // little choice but to use MP_SMALL_INT_MAX. Apps also should be careful
+ // to not try to compare sys.maxsize to some literal number (as this
+ // number might not fit in available int size), but instead count number
+ // of "one" bits in sys.maxsize.
+ { MP_ROM_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(MP_SMALL_INT_MAX) },
#else
{ MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) },
#endif
diff --git a/py/modthread.c b/py/modthread.c
index 975e7d1f6..dda9e9348 100644
--- a/py/modthread.c
+++ b/py/modthread.c
@@ -143,6 +143,8 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) {
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size);
typedef struct _thread_entry_args_t {
+ mp_obj_dict_t *dict_locals;
+ mp_obj_dict_t *dict_globals;
size_t stack_size;
mp_obj_t fun;
size_t n_args;
@@ -161,6 +163,10 @@ STATIC void *thread_entry(void *args_in) {
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
mp_stack_set_limit(args->stack_size);
+ // set locals and globals from the calling context
+ mp_locals_set(args->dict_locals);
+ mp_globals_set(args->dict_globals);
+
MP_THREAD_GIL_ENTER();
// signal that we are set up and running
@@ -169,7 +175,6 @@ STATIC void *thread_entry(void *args_in) {
// TODO set more thread-specific state here:
// mp_pending_exception? (root pointer)
// cur_exception (root pointer)
- // dict_locals? (root pointer) uPy doesn't make a new locals dict for functions, just for classes, so it's different to CPy
DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top));
@@ -240,6 +245,10 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
th_args->n_args = pos_args_len;
memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
+ // pass our locals and globals into the new thread
+ th_args->dict_locals = mp_locals_get();
+ th_args->dict_globals = mp_globals_get();
+
// set the stack size to use
th_args->stack_size = thread_stack_size;
diff --git a/py/moduerrno.c b/py/moduerrno.c
index 4a5e87419..de66c941b 100644
--- a/py/moduerrno.c
+++ b/py/moduerrno.c
@@ -32,9 +32,10 @@
#if MICROPY_PY_UERRNO
-// This list could be defined per port in mpconfigport.h to tailor it to a
-// specific port's needs. But for now we have a common list.
-#define ERRNO_LIST \
+// This list can be defined per port in mpconfigport.h to tailor it to a
+// specific port's needs. If it's not defined then we provide a default.
+#ifndef MICROPY_PY_UERRNO_LIST
+#define MICROPY_PY_UERRNO_LIST \
X(EPERM) \
X(ENOENT) \
X(EIO) \
@@ -58,9 +59,12 @@
X(EALREADY) \
X(EINPROGRESS) \
+#endif
+
+#if MICROPY_PY_UERRNO_ERRORCODE
STATIC const mp_rom_map_elem_t errorcode_table[] = {
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
- ERRNO_LIST
+ MICROPY_PY_UERRNO_LIST
#undef X
};
@@ -75,13 +79,16 @@ STATIC const mp_obj_dict_t errorcode_dict = {
.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,
},
};
+#endif
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
+ #if MICROPY_PY_UERRNO_ERRORCODE
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
+ #endif
#define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },
- ERRNO_LIST
+ MICROPY_PY_UERRNO_LIST
#undef X
};
@@ -93,12 +100,23 @@ const mp_obj_module_t mp_module_uerrno = {
};
qstr mp_errno_to_str(mp_obj_t errno_val) {
+ #if MICROPY_PY_UERRNO_ERRORCODE
+ // We have the errorcode dict so can do a lookup using the hash map
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
if (elem == NULL) {
return MP_QSTR_NULL;
} else {
return MP_OBJ_QSTR_VALUE(elem->value);
}
+ #else
+ // We don't have the errorcode dict so do a simple search in the modules dict
+ for (size_t i = 0; i < MP_ARRAY_SIZE(mp_module_uerrno_globals_table); ++i) {
+ if (errno_val == mp_module_uerrno_globals_table[i].value) {
+ return MP_OBJ_QSTR_VALUE(mp_module_uerrno_globals_table[i].key);
+ }
+ }
+ return MP_QSTR_NULL;
+ #endif
}
#endif //MICROPY_PY_UERRNO
diff --git a/py/mpconfig.h b/py/mpconfig.h
index 1b47d822f..7e3bd8bdb 100644
--- a/py/mpconfig.h
+++ b/py/mpconfig.h
@@ -917,6 +917,11 @@ typedef double mp_float_t;
#define MICROPY_PY_UERRNO (0)
#endif
+// Whether to provide the uerrno.errorcode dict
+#ifndef MICROPY_PY_UERRNO_ERRORCODE
+#define MICROPY_PY_UERRNO_ERRORCODE (1)
+#endif
+
// Whether to provide "uselect" module (baremetal implementation)
#ifndef MICROPY_PY_USELECT
#define MICROPY_PY_USELECT (0)
diff --git a/py/mpstate.h b/py/mpstate.h
index 54392a994..9e4f54ae5 100644
--- a/py/mpstate.h
+++ b/py/mpstate.h
@@ -196,11 +196,13 @@ typedef struct _mp_state_vm_t {
// This structure holds state that is specific to a given thread.
// Everything in this structure is scanned for root pointers.
typedef struct _mp_state_thread_t {
+ mp_obj_dict_t *dict_locals;
+ mp_obj_dict_t *dict_globals;
+
// Note: nlr asm code has the offset of this hard-coded
nlr_buf_t *nlr_top; // ROOT POINTER
// Stack top at the start of program
- // Note: this entry is used to locate the end of the root pointer section.
char *stack_top;
#if MICROPY_STACK_CHECK
@@ -208,15 +210,11 @@ typedef struct _mp_state_thread_t {
#endif
} mp_state_thread_t;
-// This structure combines the above 3 structures, and adds the local
-// and global dicts.
+// This structure combines the above 3 structures.
+// The order of the entries are important for root pointer scanning in the GC to work.
// Note: if this structure changes then revisit all nlr asm code since they
// have the offset of nlr_top hard-coded.
typedef struct _mp_state_ctx_t {
- // these must come first for root pointer scanning in GC to work
- mp_obj_dict_t *dict_locals;
- mp_obj_dict_t *dict_globals;
- // these must come next in this order for root pointer scanning in GC to work
mp_state_thread_t thread;
mp_state_vm_t vm;
mp_state_mem_t mem;
@@ -224,7 +222,7 @@ typedef struct _mp_state_ctx_t {
extern mp_state_ctx_t mp_state_ctx;
-#define MP_STATE_CTX(x) (mp_state_ctx.x)
+#define MP_STATE_CTX(x) MP_STATE_THREAD(x)
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
diff --git a/py/nlr.h b/py/nlr.h
index 6c86fc26c..00c1072fe 100644
--- a/py/nlr.h
+++ b/py/nlr.h
@@ -82,7 +82,7 @@ NORETURN void nlr_jump(void *val);
// This must be implemented by a port. It's called by nlr_jump
// if no nlr buf has been pushed. It must not return, but rather
// should bail out with a fatal error.
-void nlr_jump_fail(void *val);
+NORETURN void nlr_jump_fail(void *val);
// use nlr_raise instead of nlr_jump so that debugging is easier
#ifndef DEBUG
diff --git a/py/nlrx64.S b/py/nlrx64.S
deleted file mode 100644
index 78d654558..000000000
--- a/py/nlrx64.S
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * This file is part of the Micro Python project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013, 2014 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if defined(__x86_64__) && !MICROPY_NLR_SETJMP
-
-// We only need the functions here if we are on x86-64, and we are not
-// using setjmp/longjmp.
-//
-// For reference, x86-64 callee save regs are:
-// rbx, rbp, rsp, r12, r13, r14, r15
-
-// the offset of nlr_top within mp_state_ctx_t
-#define NLR_TOP_OFFSET (2 * 8)
-
-#if defined(__APPLE__) && defined(__MACH__)
-#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
-#define MP_THREAD_GET_STATE _mp_thread_get_state
-#else
-#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
-#define MP_THREAD_GET_STATE mp_thread_get_state
-#endif
-
-// offset of nlr_top within mp_state_thread_t structure
-#define NLR_TOP_TH_OFF (0)
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define NLR_OS_WINDOWS
-#endif
-
- .file "nlr.s"
- .text
-
-#if !defined(NLR_OS_WINDOWS)
-
-/******************************************************************************/
-//
-// Functions for *nix and OSX.
-// OSX needs _ prefix for binding to C, and doesn't support some directives.
-//
-/******************************************************************************/
-
-/**************************************/
-// mp_uint_t nlr_push(rdi=nlr_buf_t *nlr)
-
-#if !(defined(__APPLE__) && defined(__MACH__))
- .globl nlr_push
- .type nlr_push, @function
-nlr_push:
-#else
- .globl _nlr_push
-_nlr_push:
-#endif
- movq (%rsp), %rax # load return %rip
- movq %rax, 16(%rdi) # store %rip into nlr_buf
- movq %rbp, 24(%rdi) # store %rbp into nlr_buf
- movq %rsp, 32(%rdi) # store %rsp into nlr_buf
- movq %rbx, 40(%rdi) # store %rbx into nlr_buf
- movq %r12, 48(%rdi) # store %r12 into nlr_buf
- movq %r13, 56(%rdi) # store %r13 into nlr_buf
- movq %r14, 64(%rdi) # store %r14 into nlr_buf
- movq %r15, 72(%rdi) # store %r15 into nlr_buf
-
-#if !MICROPY_PY_THREAD
- movq NLR_TOP(%rip), %rax # get last nlr_buf
- movq %rax, (%rdi) # store it
- movq %rdi, NLR_TOP(%rip) # stor new nlr_buf (to make linked list)
-#else
- movq %rdi, %rbp # since we make a call, must save rdi in rbp
- callq MP_THREAD_GET_STATE # get mp_state_thread ptr into rax
- movq NLR_TOP_TH_OFF(%rax), %rsi # get thread.nlr_top (last nlr_buf)
- movq %rsi, (%rbp) # store it
- movq %rbp, NLR_TOP_TH_OFF(%rax) # store new nlr_buf (to make linked list)
- movq 24(%rbp), %rbp # restore rbp
-#endif
-
- xorq %rax, %rax # return 0, normal return
- ret # return
-#if !(defined(__APPLE__) && defined(__MACH__))
- .size nlr_push, .-nlr_push
-#endif
-
-/**************************************/
-// void nlr_pop()
-
-#if !(defined(__APPLE__) && defined(__MACH__))
- .globl nlr_pop
- .type nlr_pop, @function
-nlr_pop:
-#else
- .globl _nlr_pop
-_nlr_pop:
-#endif
-
-#if !MICROPY_PY_THREAD
- movq NLR_TOP(%rip), %rax # get nlr_top into %rax
- movq (%rax), %rax # load prev nlr_buf
- movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
-#else
- callq MP_THREAD_GET_STATE # get mp_state_thread ptr into rax
- movq NLR_TOP_TH_OFF(%rax), %rdi # get thread.nlr_top (last nlr_buf)
- movq (%rdi), %rdi # load prev nlr_buf
- movq %rdi, NLR_TOP_TH_OFF(%rax) # store prev nlr_buf (to unlink list)
-#endif
-
- ret # return
-#if !(defined(__APPLE__) && defined(__MACH__))
- .size nlr_pop, .-nlr_pop
-#endif
-
-/**************************************/
-// void nlr_jump(rdi=mp_uint_t val)
-
-#if !(defined(__APPLE__) && defined(__MACH__))
- .globl nlr_jump
- .type nlr_jump, @function
-nlr_jump:
-#else
- .globl _nlr_jump
- _nlr_jump:
-#endif
-
-#if !MICROPY_PY_THREAD
- movq %rdi, %rax # put return value in %rax
- movq NLR_TOP(%rip), %rdi # get nlr_top into %rdi
- test %rdi, %rdi # check for nlr_top being NULL
- je .fail # fail if nlr_top is NULL
- movq %rax, 8(%rdi) # store return value
- movq (%rdi), %rax # load prev nlr_buf
- movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
-#else
- movq %rdi, %rbp # put return value in rbp
- callq MP_THREAD_GET_STATE # get thread ptr in rax
- movq %rax, %rsi # put thread ptr in rsi
- movq %rbp, %rax # put return value to rax (for je .fail)
- movq NLR_TOP_TH_OFF(%rsi), %rdi # get thread.nlr_top in rdi
- test %rdi, %rdi # check for nlr_top being NULL
- je .fail # fail if nlr_top is NULL
- movq %rax, 8(%rdi) # store return value
- movq (%rdi), %rax # load prev nlr_buf
- movq %rax, NLR_TOP_TH_OFF(%rsi) # store prev nlr_buf (to unlink list)
-#endif
-
- movq 72(%rdi), %r15 # load saved %r15
- movq 64(%rdi), %r14 # load saved %r14
- movq 56(%rdi), %r13 # load saved %r13
- movq 48(%rdi), %r12 # load saved %r12
- movq 40(%rdi), %rbx # load saved %rbx
- movq 32(%rdi), %rsp # load saved %rsp
- movq 24(%rdi), %rbp # load saved %rbp
- movq 16(%rdi), %rax # load saved %rip
- movq %rax, (%rsp) # store saved %rip to stack
- xorq %rax, %rax # clear return register
- inc %al # increase to make 1, non-local return
- ret # return
-.fail:
- movq %rax, %rdi # put argument back in first-arg register
-#if !(defined(__APPLE__) && defined(__MACH__))
- je nlr_jump_fail # transfer control to nlr_jump_fail
- .size nlr_jump, .-nlr_jump
-#else
- je _nlr_jump_fail # transfer control to nlr_jump_fail
-#endif
-
-#else // !defined(NLR_OS_WINDOWS)
-
-/******************************************************************************/
-//
-// Functions for Windows
-//
-/******************************************************************************/
-
-/**************************************/
-// mp_uint_t nlr_push(rcx=nlr_buf_t *nlr)
-
- .globl nlr_push
-nlr_push:
- movq (%rsp), %rax # load return %rip
- movq %rax, 16(%rcx) # store %rip into nlr_buf
- movq %rbp, 24(%rcx) # store %rbp into nlr_buf
- movq %rsp, 32(%rcx) # store %rsp into nlr_buf
- movq %rbx, 40(%rcx) # store %rbx into nlr_buf
- movq %r12, 48(%rcx) # store %r12 into nlr_buf
- movq %r13, 56(%rcx) # store %r13 into nlr_buf
- movq %r14, 64(%rcx) # store %r14 into nlr_buf
- movq %r15, 72(%rcx) # store %r15 into
- movq %rdi, 80(%rcx) # store %rdr into
- movq %rsi, 88(%rcx) # store %rsi into
- movq NLR_TOP(%rip), %rax # get last nlr_buf
- movq %rax, (%rcx) # store it
- movq %rcx, NLR_TOP(%rip) # stor new nlr_buf (to make linked list)
- xorq %rax, %rax # return 0, normal return
- ret # return
-
-/**************************************/
-// void nlr_pop()
-
- .globl nlr_pop
-nlr_pop:
- movq NLR_TOP(%rip), %rax # get nlr_top into %rax
- movq (%rax), %rax # load prev nlr_buf
- movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
- ret # return
-
-/**************************************/
-// void nlr_jump(rcx=mp_uint_t val)
-
- .globl nlr_jump
-nlr_jump:
- movq %rcx, %rax # put return value in %rax
- movq NLR_TOP(%rip), %rcx # get nlr_top into %rcx
- test %rcx, %rcx # check for nlr_top being NULL
- je .fail # fail if nlr_top is NULL
- movq %rax, 8(%rcx) # store return value
- movq (%rcx), %rax # load prev nlr_buf
- movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
- movq 72(%rcx), %r15 # load saved %r15
- movq 64(%rcx), %r14 # load saved %r14
- movq 56(%rcx), %r13 # load saved %r13
- movq 48(%rcx), %r12 # load saved %r12
- movq 40(%rcx), %rbx # load saved %rbx
- movq 32(%rcx), %rsp # load saved %rsp
- movq 24(%rcx), %rbp # load saved %rbp
- movq 16(%rcx), %rax # load saved %rip
- movq 80(%rcx), %rdi # store %rdr into
- movq 88(%rcx), %rsi # store %rsi into
- movq %rax, (%rsp) # store saved %rip to stack
- xorq %rax, %rax # clear return register
- inc %al # increase to make 1, non-local return
- ret # return
-.fail:
- movq %rax, %rcx # put argument back in first-arg register
- je nlr_jump_fail # transfer control to nlr_jump_fail
-
-#endif // !defined(NLR_OS_WINDOWS)
-
-#endif // defined(__x86_64__) && !MICROPY_NLR_SETJMP
-#if defined(linux)
- .section .note.GNU-stack,"",%progbits
-#endif
diff --git a/py/nlrx64.c b/py/nlrx64.c
new file mode 100644
index 000000000..845aac67a
--- /dev/null
+++ b/py/nlrx64.c
@@ -0,0 +1,129 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * 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 "py/mpstate.h"
+#include "py/nlr.h"
+
+#if !MICROPY_NLR_SETJMP && defined(__x86_64__)
+
+#undef nlr_push
+
+// x86-64 callee-save registers are:
+// rbx, rbp, rsp, r12, r13, r14, r15
+
+#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
+
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
+
+unsigned int nlr_push(nlr_buf_t *nlr) {
+ (void)nlr;
+
+ #if NLR_OS_WINDOWS
+
+ __asm volatile (
+ "movq (%rsp), %rax \n" // load return %rip
+ "movq %rax, 16(%rcx) \n" // store %rip into nlr_buf
+ "movq %rbp, 24(%rcx) \n" // store %rbp into nlr_buf
+ "movq %rsp, 32(%rcx) \n" // store %rsp into nlr_buf
+ "movq %rbx, 40(%rcx) \n" // store %rbx into nlr_buf
+ "movq %r12, 48(%rcx) \n" // store %r12 into nlr_buf
+ "movq %r13, 56(%rcx) \n" // store %r13 into nlr_buf
+ "movq %r14, 64(%rcx) \n" // store %r14 into nlr_buf
+ "movq %r15, 72(%rcx) \n" // store %r15 into nlr_buf
+ "movq %rdi, 80(%rcx) \n" // store %rdr into nlr_buf
+ "movq %rsi, 88(%rcx) \n" // store %rsi into nlr_buf
+ "jmp nlr_push_tail \n" // do the rest in C
+ );
+
+ #else
+
+ __asm volatile (
+ "movq (%rsp), %rax \n" // load return %rip
+ "movq %rax, 16(%rdi) \n" // store %rip into nlr_buf
+ "movq %rbp, 24(%rdi) \n" // store %rbp into nlr_buf
+ "movq %rsp, 32(%rdi) \n" // store %rsp into nlr_buf
+ "movq %rbx, 40(%rdi) \n" // store %rbx into nlr_buf
+ "movq %r12, 48(%rdi) \n" // store %r12 into nlr_buf
+ "movq %r13, 56(%rdi) \n" // store %r13 into nlr_buf
+ "movq %r14, 64(%rdi) \n" // store %r14 into nlr_buf
+ "movq %r15, 72(%rdi) \n" // store %r15 into nlr_buf
+ "jmp nlr_push_tail \n" // do the rest in C
+ );
+
+ #endif
+
+ return 0; // needed to silence compiler warning
+}
+
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ nlr->prev = *top;
+ *top = nlr;
+ return 0; // normal return
+}
+
+void nlr_pop(void) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ *top = (*top)->prev;
+}
+
+NORETURN void nlr_jump(void *val) {
+ 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;
+
+ __asm volatile (
+ "movq %0, %%rcx \n" // %rcx points to nlr_buf
+ #if NLR_OS_WINDOWS
+ "movq 88(%%rcx), %%rsi \n" // load saved %rsi
+ "movq 80(%%rcx), %%rdi \n" // load saved %rdr
+ #endif
+ "movq 72(%%rcx), %%r15 \n" // load saved %r15
+ "movq 64(%%rcx), %%r14 \n" // load saved %r14
+ "movq 56(%%rcx), %%r13 \n" // load saved %r13
+ "movq 48(%%rcx), %%r12 \n" // load saved %r12
+ "movq 40(%%rcx), %%rbx \n" // load saved %rbx
+ "movq 32(%%rcx), %%rsp \n" // load saved %rsp
+ "movq 24(%%rcx), %%rbp \n" // load saved %rbp
+ "movq 16(%%rcx), %%rax \n" // load saved %rip
+ "movq %%rax, (%%rsp) \n" // store saved %rip to stack
+ "xorq %%rax, %%rax \n" // clear return register
+ "inc %%al \n" // increase to make 1, non-local return
+ "ret \n" // return
+ : // output operands
+ : "r"(top) // input operands
+ : // clobbered registers
+ );
+
+ for (;;); // needed to silence compiler warning
+}
+
+#endif // !MICROPY_NLR_SETJMP && defined(__x86_64__)
diff --git a/py/nlrx86.S b/py/nlrx86.S
deleted file mode 100644
index ff0cc2130..000000000
--- a/py/nlrx86.S
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * This file is part of the Micro Python project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2013, 2014 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if defined(__i386__) && !MICROPY_NLR_SETJMP
-
-// We only need the functions here if we are on x86, and we are not
-// using setjmp/longjmp.
-//
-// For reference, x86 callee save regs are:
-// ebx, esi, edi, ebp, esp, eip
-
-// the offset of nlr_top within mp_state_ctx_t
-#define NLR_TOP_OFFSET (2 * 4)
-
-#if defined(_WIN32) || defined(__CYGWIN__)
-#define NLR_OS_WINDOWS
-#endif
-
-#if defined(__APPLE__) && defined(__MACH__)
-#define NLR_OS_MAC
-#endif
-
-#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
-#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
-#define MP_THREAD_GET_STATE _mp_thread_get_state
-#else
-#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
-#define MP_THREAD_GET_STATE mp_thread_get_state
-#endif
-
-// offset of nlr_top within mp_state_thread_t structure
-#define NLR_TOP_TH_OFF (0)
-
- .file "nlr.s"
- .text
-
-/**************************************/
-// mp_uint_t nlr_push(4(%esp)=nlr_buf_t *nlr)
-
-#if defined(NLR_OS_WINDOWS)
- .globl _nlr_push
- .def _nlr_push; .scl 2; .type 32; .endef
-_nlr_push:
-#elif defined(NLR_OS_MAC)
- .globl _nlr_push
-_nlr_push:
-#else
- .globl nlr_push
- .type nlr_push, @function
-nlr_push:
-#endif
- mov 4(%esp), %edx # load nlr_buf
- mov (%esp), %eax # load return %ip
- mov %eax, 8(%edx) # store %ip into nlr_buf+8
- mov %ebp, 12(%edx) # store %bp into nlr_buf+12
- mov %esp, 16(%edx) # store %sp into nlr_buf+16
- mov %ebx, 20(%edx) # store %bx into nlr_buf+20
- mov %edi, 24(%edx) # store %di into nlr_buf
- mov %esi, 28(%edx) # store %si into nlr_buf
-
-#if !MICROPY_PY_THREAD
- mov NLR_TOP, %eax # load nlr_top
- mov %eax, (%edx) # store it
- mov %edx, NLR_TOP # stor new nlr_buf (to make linked list)
-#else
- // to check: stack is aligned to 16-byte boundary before this call
- call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
- mov 4(%esp), %edx # load nlr_buf argument into edx (edx clobbered by call)
- mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
- mov %ecx, (%edx) # store it
- mov %edx, NLR_TOP_TH_OFF(%eax) # store new nlr_buf (to make linked list)
-#endif
-
- xor %eax, %eax # return 0, normal return
- ret # return
-#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
- .size nlr_push, .-nlr_push
-#endif
-
-/**************************************/
-// void nlr_pop()
-
-#if defined(NLR_OS_WINDOWS)
- .globl _nlr_pop
- .def _nlr_pop; .scl 2; .type 32; .endef
-_nlr_pop:
-#elif defined(NLR_OS_MAC)
- .globl _nlr_pop
-_nlr_pop:
-#else
- .globl nlr_pop
- .type nlr_pop, @function
-nlr_pop:
-#endif
-
-#if !MICROPY_PY_THREAD
- mov NLR_TOP, %eax # load nlr_top
- mov (%eax), %eax # load prev nlr_buf
- mov %eax, NLR_TOP # store nlr_top (to unlink list)
-#else
- call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
- mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
- mov (%ecx), %ecx # load prev nlr_buf
- mov %ecx, NLR_TOP_TH_OFF(%eax) # store prev nlr_buf (to unlink list)
-#endif
-
- ret # return
-#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
- .size nlr_pop, .-nlr_pop
-#endif
-
-/**************************************/
-// void nlr_jump(4(%esp)=mp_uint_t val)
-
-#if defined(NLR_OS_WINDOWS)
- .globl _nlr_jump
- .def _nlr_jump; .scl 2; .type 32; .endef
-_nlr_jump:
-#elif defined(NLR_OS_MAC)
- .globl _nlr_jump
-_nlr_jump:
-#else
- .globl nlr_jump
- .type nlr_jump, @function
-nlr_jump:
-#endif
-
-#if !MICROPY_PY_THREAD
- mov NLR_TOP, %edx # load nlr_top
- test %edx, %edx # check for nlr_top being NULL
-#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
- je _nlr_jump_fail # fail if nlr_top is NULL
-#else
- je nlr_jump_fail # fail if nlr_top is NULL
-#endif
- mov 4(%esp), %eax # load return value
- mov %eax, 4(%edx) # store return value
- mov (%edx), %eax # load prev nlr_top
- mov %eax, NLR_TOP # store nlr_top (to unlink list)
-#else
- call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
- mov NLR_TOP_TH_OFF(%eax), %edx # get thread.nlr_top (last nlr_buf)
- test %edx, %edx # check for nlr_top being NULL
-#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
- je _nlr_jump_fail # fail if nlr_top is NULL
-#else
- je nlr_jump_fail # fail if nlr_top is NULL
-#endif
- mov 4(%esp), %ecx # load return value
- mov %ecx, 4(%edx) # store return value
- mov (%edx), %ecx # load prev nlr_top
- mov %ecx, NLR_TOP_TH_OFF(%eax) # store nlr_top (to unlink list)
-#endif
-
- mov 28(%edx), %esi # load saved %si
- mov 24(%edx), %edi # load saved %di
- mov 20(%edx), %ebx # load saved %bx
- mov 16(%edx), %esp # load saved %sp
- mov 12(%edx), %ebp # load saved %bp
- mov 8(%edx), %eax # load saved %ip
- mov %eax, (%esp) # store saved %ip to stack
- xor %eax, %eax # clear return register
- inc %al # increase to make 1, non-local return
- ret # return
-#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
- .size nlr_jump, .-nlr_jump
-#endif
-
-#endif // defined(__i386__) && !MICROPY_NLR_SETJMP
-#if defined(linux)
- .section .note.GNU-stack,"",%progbits
-#endif
diff --git a/py/nlrx86.c b/py/nlrx86.c
new file mode 100644
index 000000000..07ba72628
--- /dev/null
+++ b/py/nlrx86.c
@@ -0,0 +1,114 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * 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 "py/mpconfig.h"
+#include "py/mpstate.h"
+#include "py/nlr.h"
+
+#if !MICROPY_NLR_SETJMP && defined(__i386__)
+
+#undef nlr_push
+
+// For reference, x86 callee save regs are:
+// ebx, esi, edi, ebp, esp, eip
+
+#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
+
+#if NLR_OS_WINDOWS
+unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
+#else
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
+#endif
+
+unsigned int nlr_push(nlr_buf_t *nlr) {
+ (void)nlr;
+
+ __asm volatile (
+ // Check for Zephyr, which uses a different calling convention
+ // by default.
+ // TODO: Better check for Zephyr.
+ // TODE: Better support for various x86 calling conventions
+ // (unfortunately, __attribute__((naked)) is not supported on x86).
+ #ifndef CONFIG_SOC_IA32
+ "pop %ebp \n" // undo function's prelude
+ #endif
+ "mov 4(%esp), %edx \n" // load nlr_buf
+ "mov (%esp), %eax \n" // load return %eip
+ "mov %eax, 8(%edx) \n" // store %eip into nlr_buf
+ "mov %ebp, 12(%edx) \n" // store %ebp into nlr_buf
+ "mov %esp, 16(%edx) \n" // store %esp into nlr_buf
+ "mov %ebx, 20(%edx) \n" // store %ebx into nlr_buf
+ "mov %edi, 24(%edx) \n" // store %edi into nlr_buf
+ "mov %esi, 28(%edx) \n" // store %esi into nlr_buf
+ "jmp nlr_push_tail \n" // do the rest in C
+ );
+
+ return 0; // needed to silence compiler warning
+}
+
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ nlr->prev = *top;
+ *top = nlr;
+ return 0; // normal return
+}
+
+void nlr_pop(void) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ *top = (*top)->prev;
+}
+
+NORETURN void nlr_jump(void *val) {
+ 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;
+
+ __asm volatile (
+ "mov %0, %%edx \n" // %edx points to nlr_buf
+ "mov 28(%%edx), %%esi \n" // load saved %esi
+ "mov 24(%%edx), %%edi \n" // load saved %edi
+ "mov 20(%%edx), %%ebx \n" // load saved %ebx
+ "mov 16(%%edx), %%esp \n" // load saved %esp
+ "mov 12(%%edx), %%ebp \n" // load saved %ebp
+ "mov 8(%%edx), %%eax \n" // load saved %eip
+ "mov %%eax, (%%esp) \n" // store saved %eip to stack
+ "xor %%eax, %%eax \n" // clear return register
+ "inc %%al \n" // increase to make 1, non-local return
+ "ret \n" // return
+ : // output operands
+ : "r"(top) // input operands
+ : // clobbered registers
+ );
+
+ for (;;); // needed to silence compiler warning
+}
+
+#endif // !MICROPY_NLR_SETJMP && defined(__i386__)
diff --git a/py/nlrxtensa.S b/py/nlrxtensa.S
deleted file mode 100644
index 6d87e305d..000000000
--- a/py/nlrxtensa.S
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * This file is part of the Micro Python project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2014 Damien P. George
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#if defined(__xtensa__)
-
-/*
- calling conventions:
- a0 = return address
- a1 = stack pointer
- a2 = first arg, return value
- a3-a7 = rest of args
-*/
-
-// the offset of nlr_top within mp_state_ctx_t
-#define NLR_TOP_OFFSET (2 * 4)
-
-#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
-
- .file "nlr.s"
- .text
-
- .literal_position
- .literal .LC0, NLR_TOP
- .align 4
- .global nlr_push
- .type nlr_push, @function
-nlr_push:
- // save regs
- s32i.n a0, a2, 8
- s32i.n a1, a2, 12
- s32i.n a8, a2, 16
- s32i.n a9, a2, 20
- s32i.n a10, a2, 24
- s32i.n a11, a2, 28
- s32i.n a12, a2, 32
- s32i.n a13, a2, 36
- s32i.n a14, a2, 40
- s32i.n a15, a2, 44
-
- l32r a3, .LC0
- l32i.n a4, a3, 0
- s32i.n a2, a3, 0
- s32i.n a4, a2, 0
- movi.n a2, 0
- ret.n
- .size nlr_push, .-nlr_push
-
- .literal_position
- .literal .LC1, NLR_TOP
- .align 4
- .global nlr_pop
- .type nlr_pop, @function
-nlr_pop:
- l32r a2, .LC1
- l32i.n a3, a2, 0
- l32i.n a3, a3, 0
- s32i.n a3, a2, 0
- ret.n
- .size nlr_pop, .-nlr_pop
-
- .literal_position
- .literal .LC2, NLR_TOP
- .align 4
- .global nlr_jump
- .type nlr_jump, @function
-nlr_jump:
- l32r a3, .LC2
- l32i.n a3, a3, 0 // a3 = nlr_top
- bnez.n a3, .L4
- call0 nlr_jump_fail
-.L4:
- s32i.n a2, a3, 4 // nlr_top->ret_val = val
-
- // restore regs
- l32i.n a0, a3, 8
- l32i.n a1, a3, 12
- l32i.n a8, a3, 16
- l32i.n a9, a3, 20
- l32i.n a10, a3, 24
- l32i.n a11, a3, 28
- l32i.n a12, a3, 32
- l32i.n a13, a3, 36
- l32i.n a14, a3, 40
- l32i.n a15, a3, 44
-
- l32i.n a3, a3, 0 // a3 = nlr_top->prev
- l32r a2, .LC2
- s32i.n a3, a2, 0 // nlr_top = a3
- movi.n a2, 1 // return 1
- ret.n
- .size nlr_jump, .-nlr_jump
-
-#endif // defined(__xtensa__)
-#if defined(linux)
- .section .note.GNU-stack,"",%progbits
-#endif
diff --git a/py/nlrxtensa.c b/py/nlrxtensa.c
new file mode 100644
index 000000000..ccac3597b
--- /dev/null
+++ b/py/nlrxtensa.c
@@ -0,0 +1,103 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2014-2017 Damien P. George
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * 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 "py/mpstate.h"
+#include "py/nlr.h"
+
+#if !MICROPY_NLR_SETJMP && defined(__xtensa__)
+
+#undef nlr_push
+
+// Xtensa calling conventions:
+// a0 = return address
+// a1 = stack pointer
+// a2 = first arg, return value
+// a3-a7 = rest of args
+
+unsigned int nlr_push(nlr_buf_t *nlr) {
+
+ __asm volatile (
+ "s32i.n a0, a2, 8 \n" // save regs...
+ "s32i.n a1, a2, 12 \n"
+ "s32i.n a8, a2, 16 \n"
+ "s32i.n a9, a2, 20 \n"
+ "s32i.n a10, a2, 24 \n"
+ "s32i.n a11, a2, 28 \n"
+ "s32i.n a12, a2, 32 \n"
+ "s32i.n a13, a2, 36 \n"
+ "s32i.n a14, a2, 40 \n"
+ "s32i.n a15, a2, 44 \n"
+ "j nlr_push_tail \n" // do the rest in C
+ );
+
+ return 0; // needed to silence compiler warning
+}
+
+__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ nlr->prev = *top;
+ *top = nlr;
+ return 0; // normal return
+}
+
+void nlr_pop(void) {
+ nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
+ *top = (*top)->prev;
+}
+
+NORETURN void nlr_jump(void *val) {
+ 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;
+
+ __asm volatile (
+ "mov.n a2, %0 \n" // a2 points to nlr_buf
+ "l32i.n a0, a2, 8 \n" // restore regs...
+ "l32i.n a1, a2, 12 \n"
+ "l32i.n a8, a2, 16 \n"
+ "l32i.n a9, a2, 20 \n"
+ "l32i.n a10, a2, 24 \n"
+ "l32i.n a11, a2, 28 \n"
+ "l32i.n a12, a2, 32 \n"
+ "l32i.n a13, a2, 36 \n"
+ "l32i.n a14, a2, 40 \n"
+ "l32i.n a15, a2, 44 \n"
+ "movi.n a2, 1 \n" // return 1, non-local return
+ "ret.n \n" // return
+ : // output operands
+ : "r"(top) // input operands
+ : // clobbered registers
+ );
+
+ for (;;); // needed to silence compiler warning
+}
+
+#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__)
diff --git a/py/objarray.c b/py/objarray.c
index 1b590f3c0..a84a63151 100644
--- a/py/objarray.c
+++ b/py/objarray.c
@@ -418,6 +418,10 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
uint8_t* dest_items = o->items;
#if MICROPY_PY_BUILTINS_MEMORYVIEW
if (o->base.type == &mp_type_memoryview) {
+ if ((o->typecode & 0x80) == 0) {
+ // store to read-only memoryview not allowed
+ return MP_OBJ_NULL;
+ }
if (len_adj != 0) {
goto compat_error;
}
diff --git a/py/objfun.c b/py/objfun.c
index e5f6009dc..a823f49e5 100644
--- a/py/objfun.c
+++ b/py/objfun.c
@@ -511,17 +511,11 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
// convert float to int (could also pass in float registers)
return (mp_int_t)mp_obj_float_get(obj);
#endif
- } else if (type == &mp_type_tuple) {
+ } else if (type == &mp_type_tuple || type == &mp_type_list) {
// pointer to start of tuple (could pass length, but then could use len(x) for that)
mp_uint_t len;
mp_obj_t *items;
- mp_obj_tuple_get(obj, &len, &items);
- return (mp_uint_t)items;
- } else if (type == &mp_type_list) {
- // pointer to start of list (could pass length, but then could use len(x) for that)
- mp_uint_t len;
- mp_obj_t *items;
- mp_obj_list_get(obj, &len, &items);
+ mp_obj_get_array(obj, &len, &items);
return (mp_uint_t)items;
} else {
mp_buffer_info_t bufinfo;
diff --git a/py/objlist.c b/py/objlist.c
index 55ee19120..ba7898415 100644
--- a/py/objlist.c
+++ b/py/objlist.c
@@ -192,13 +192,13 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
#if MICROPY_PY_BUILTINS_SLICE
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
- mp_check_self(MP_OBJ_IS_TYPE(value, &mp_type_list));
- mp_obj_list_t *slice = MP_OBJ_TO_PTR(value);
+ mp_uint_t value_len; mp_obj_t *value_items;
+ mp_obj_get_array(value, &value_len, &value_items);
mp_bound_slice_t slice_out;
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
mp_not_implemented("");
}
- mp_int_t len_adj = slice->len - (slice_out.stop - slice_out.start);
+ mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
//printf("Len adj: %d\n", len_adj);
if (len_adj > 0) {
if (self->len + len_adj > self->alloc) {
@@ -208,10 +208,10 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
self->alloc = self->len + len_adj;
}
mp_seq_replace_slice_grow_inplace(self->items, self->len,
- slice_out.start, slice_out.stop, slice->items, slice->len, len_adj, sizeof(*self->items));
+ slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items));
} else {
mp_seq_replace_slice_no_grow(self->items, self->len,
- slice_out.start, slice_out.stop, slice->items, slice->len, sizeof(*self->items));
+ slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));
// Clear "freed" elements at the end of list
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
// TODO: apply allocation policy re: alloc_size
diff --git a/py/objstr.c b/py/objstr.c
index c137afe67..17d06f88e 100644
--- a/py/objstr.c
+++ b/py/objstr.c
@@ -430,16 +430,13 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
// process args
mp_uint_t seq_len;
mp_obj_t *seq_items;
- if (MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {
- mp_obj_tuple_get(arg, &seq_len, &seq_items);
- } else {
- if (!MP_OBJ_IS_TYPE(arg, &mp_type_list)) {
- // arg is not a list, try to convert it to one
- // TODO: Try to optimize?
- arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg);
- }
- mp_obj_list_get(arg, &seq_len, &seq_items);
+
+ if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {
+ // arg is not a list nor a tuple, try to convert it to a list
+ // TODO: Try to optimize?
+ arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg);
}
+ mp_obj_get_array(arg, &seq_len, &seq_items);
// count required length
size_t required_len = 0;
diff --git a/py/parse.c b/py/parse.c
index d15af4158..2f16748a6 100644
--- a/py/parse.c
+++ b/py/parse.c
@@ -38,6 +38,7 @@
#include "py/runtime0.h"
#include "py/runtime.h"
#include "py/objint.h"
+#include "py/objstr.h"
#include "py/builtin.h"
#if MICROPY_ENABLE_COMPILER
@@ -75,8 +76,6 @@ enum {
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
- RULE_string, // special node for non-interned string
- RULE_bytes, // special node for non-interned bytes
RULE_const_object, // special node for a constant, generic Python object
// define rules without a compile function
@@ -123,8 +122,6 @@ STATIC const rule_t *const rules[] = {
#include "py/grammar.h"
#undef DEF_RULE
#undef DEF_RULE_NC
- NULL, // RULE_string
- NULL, // RULE_bytes
NULL, // RULE_const_object
// define rules without a compile function
@@ -150,15 +147,7 @@ typedef struct _mp_parse_chunk_t {
byte data[];
} mp_parse_chunk_t;
-typedef enum {
- PARSE_ERROR_NONE = 0,
- PARSE_ERROR_MEMORY,
- PARSE_ERROR_CONST,
-} parse_error_t;
-
typedef struct _parser_t {
- parse_error_t parse_error;
-
size_t rule_stack_alloc;
size_t rule_stack_top;
rule_stack_t *rule_stack;
@@ -219,15 +208,8 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
}
STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
- if (parser->parse_error) {
- return;
- }
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
- rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC, true);
- if (rs == NULL) {
- parser->parse_error = PARSE_ERROR_MEMORY;
- return;
- }
+ rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC);
parser->rule_stack = rs;
parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;
}
@@ -244,7 +226,6 @@ STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
}
STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
- assert(!parser->parse_error);
parser->rule_stack_top -= 1;
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
@@ -326,11 +307,7 @@ void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
} else {
// node must be a mp_parse_node_struct_t
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
- if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
- printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
- } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
- printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
- } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
+ if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
#else
@@ -361,58 +338,26 @@ STATIC void result_stack_show(parser_t *parser) {
*/
STATIC mp_parse_node_t pop_result(parser_t *parser) {
- if (parser->parse_error) {
- return MP_PARSE_NODE_NULL;
- }
assert(parser->result_stack_top > 0);
return parser->result_stack[--parser->result_stack_top];
}
STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {
- if (parser->parse_error) {
- return MP_PARSE_NODE_NULL;
- }
assert(parser->result_stack_top > pos);
return parser->result_stack[parser->result_stack_top - 1 - pos];
}
STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
- if (parser->parse_error) {
- return;
- }
if (parser->result_stack_top >= parser->result_stack_alloc) {
- mp_parse_node_t *stack = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC, true);
- if (stack == NULL) {
- parser->parse_error = PARSE_ERROR_MEMORY;
- return;
- }
+ mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC);
parser->result_stack = stack;
parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;
}
parser->result_stack[parser->result_stack_top++] = pn;
}
-STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, size_t src_line, size_t rule_kind, const char *str, size_t len) {
- mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * 2);
- if (pn == NULL) {
- parser->parse_error = PARSE_ERROR_MEMORY;
- return MP_PARSE_NODE_NULL;
- }
- pn->source_line = src_line;
- pn->kind_num_nodes = rule_kind | (2 << 8);
- char *p = m_new(char, len);
- memcpy(p, str, len);
- pn->nodes[0] = (uintptr_t)p;
- pn->nodes[1] = len;
- return (mp_parse_node_t)pn;
-}
-
STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
- if (pn == NULL) {
- parser->parse_error = PARSE_ERROR_MEMORY;
- return MP_PARSE_NODE_NULL;
- }
pn->source_line = src_line;
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
// nodes are 32-bit pointers, but need to store 64-bit object
@@ -436,7 +381,11 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
mp_map_elem_t *elem;
if (rule->rule_id == RULE_atom
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
- pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
+ if (MP_OBJ_IS_SMALL_INT(elem->value)) {
+ pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
+ } else {
+ pn = make_node_const_object(parser, lex->tok_line, elem->value);
+ }
} else {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
}
@@ -469,8 +418,11 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
// qstr exists, make a leaf node
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
} else {
- // not interned, make a node holding a pointer to the string/bytes data
- pn = make_node_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
+ // not interned, make a node holding a pointer to the string/bytes object
+ mp_obj_t o = mp_obj_new_str_of_type(
+ lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes,
+ (const byte*)lex->vstr.buf, lex->vstr.len);
+ pn = make_node_const_object(parser, lex->tok_line, o);
}
} else {
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
@@ -666,16 +618,19 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
// get the value
mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];
- if (!MP_PARSE_NODE_IS_SMALL_INT(pn_value)) {
- parser->parse_error = PARSE_ERROR_CONST;
- return false;
+ mp_obj_t value;
+ if (!mp_parse_node_get_int_maybe(pn_value, &value)) {
+ mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
+ "constant must be an integer");
+ mp_obj_exception_add_traceback(exc, parser->lexer->source_name,
+ ((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTR_NULL);
+ nlr_raise(exc);
}
- mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
// store the value in the table of dynamic constants
mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
assert(elem->value == MP_OBJ_NULL);
- elem->value = MP_OBJ_NEW_SMALL_INT(value);
+ elem->value = value;
// If the constant starts with an underscore then treat it as a private
// variable and don't emit any code to store the value to the id.
@@ -770,10 +725,6 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
#endif
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
- if (pn == NULL) {
- parser->parse_error = PARSE_ERROR_MEMORY;
- return;
- }
pn->source_line = src_line;
pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
for (size_t i = num_args; i > 0; i--) {
@@ -788,15 +739,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser_t parser;
- parser.parse_error = PARSE_ERROR_NONE;
-
parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;
parser.rule_stack_top = 0;
- parser.rule_stack = m_new_maybe(rule_stack_t, parser.rule_stack_alloc);
+ parser.rule_stack = m_new(rule_stack_t, parser.rule_stack_alloc);
parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;
parser.result_stack_top = 0;
- parser.result_stack = m_new_maybe(mp_parse_node_t, parser.result_stack_alloc);
+ parser.result_stack = m_new(mp_parse_node_t, parser.result_stack_alloc);
parser.lexer = lex;
@@ -807,11 +756,6 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
mp_map_init(&parser.consts, 0);
#endif
- // check if we could allocate the stacks
- if (parser.rule_stack == NULL || parser.result_stack == NULL) {
- goto memory_error;
- }
-
// work out the top-level rule to use, and push it on the stack
size_t top_level_rule;
switch (input_kind) {
@@ -830,7 +774,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
for (;;) {
next_rule:
- if (parser.rule_stack_top == 0 || parser.parse_error) {
+ if (parser.rule_stack_top == 0) {
break;
}
@@ -930,15 +874,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
// this code discards lonely statements, such as doc strings
if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
mp_parse_node_t p = peek_result(&parser, 1);
- if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_string)) {
+ if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p))
+ || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) {
pop_result(&parser); // MP_PARSE_NODE_NULL
- mp_parse_node_t pn = pop_result(&parser); // possibly RULE_string
- if (MP_PARSE_NODE_IS_STRUCT(pn)) {
- mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
- if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
- m_del(char, (char*)pns->nodes[0], (size_t)pns->nodes[1]);
- }
- }
+ pop_result(&parser); // const expression (leaf or RULE_const_object)
+ // Pushing the "pass" rule here will overwrite any RULE_const_object
+ // entry that was on the result stack, allowing the GC to reclaim
+ // the memory from the const object when needed.
push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
break;
}
@@ -1094,27 +1036,12 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
parser.tree.chunk = parser.cur_chunk;
}
- mp_obj_t exc;
-
- if (parser.parse_error) {
- #if MICROPY_COMP_CONST
- if (parser.parse_error == PARSE_ERROR_CONST) {
- exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
- "constant must be an integer");
- } else
- #endif
- {
- assert(parser.parse_error == PARSE_ERROR_MEMORY);
- memory_error:
- exc = mp_obj_new_exception_msg(&mp_type_MemoryError,
- "parser could not allocate enough memory");
- }
- parser.tree.root = MP_PARSE_NODE_NULL;
- } else if (
+ if (
lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream
|| parser.result_stack_top == 0 // check that we got a node (can fail on empty input)
) {
- syntax_error:
+ syntax_error:;
+ mp_obj_t exc;
if (lex->tok_kind == MP_TOKEN_INDENT) {
exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
"unexpected indent");
@@ -1125,37 +1052,24 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
"invalid syntax");
}
- parser.tree.root = MP_PARSE_NODE_NULL;
- } else {
- // no errors
-
- //result_stack_show(parser);
- //printf("rule stack alloc: %d\n", parser.rule_stack_alloc);
- //printf("result stack alloc: %d\n", parser.result_stack_alloc);
- //printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
-
- // get the root parse node that we created
- assert(parser.result_stack_top == 1);
- exc = MP_OBJ_NULL;
- parser.tree.root = parser.result_stack[0];
+ // add traceback to give info about file name and location
+ // we don't have a 'block' name, so just pass the NULL qstr to indicate this
+ mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
+ nlr_raise(exc);
}
+ // get the root parse node that we created
+ assert(parser.result_stack_top == 1);
+ parser.tree.root = parser.result_stack[0];
+
// free the memory that we don't need anymore
m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);
m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);
- // we also free the lexer on behalf of the caller (see below)
- if (exc != MP_OBJ_NULL) {
- // had an error so raise the exception
- // add traceback to give info about file name and location
- // we don't have a 'block' name, so just pass the NULL qstr to indicate this
- mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
- mp_lexer_free(lex);
- nlr_raise(exc);
- } else {
- mp_lexer_free(lex);
- return parser.tree;
- }
+ // we also free the lexer on behalf of the caller
+ mp_lexer_free(lex);
+
+ return parser.tree;
}
void mp_parse_tree_clear(mp_parse_tree_t *tree) {
diff --git a/py/py.mk b/py/py.mk
index 01a802674..c4e2a79e6 100644
--- a/py/py.mk
+++ b/py/py.mk
@@ -282,6 +282,10 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_C
$(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@
+# Force nlr code to always be compiled with space-saving optimisation so
+# that the function preludes are of a minimal and predictable form.
+$(PY_BUILD)/nlr%.o: CFLAGS += -Os
+
# emitters
$(PY_BUILD)/emitnx64.o: CFLAGS += -DN_X64
diff --git a/py/runtime.c b/py/runtime.c
index db6a6f18f..1f69290ba 100644
--- a/py/runtime.c
+++ b/py/runtime.c
@@ -797,11 +797,7 @@ void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
mp_uint_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
mp_obj_t *seq_items;
- if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
- mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
- } else {
- mp_obj_list_get(seq_in, &seq_len, &seq_items);
- }
+ mp_obj_get_array(seq_in, &seq_len, &seq_items);
if (seq_len < num) {
goto too_short;
} else if (seq_len > num) {
@@ -851,16 +847,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
mp_uint_t seq_len;
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
mp_obj_t *seq_items;
- if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
- mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
- } else {
- if (num_left == 0 && num_right == 0) {
- // *a, = b # sets a to b if b is a list
- items[0] = seq_in;
- return;
- }
- mp_obj_list_get(seq_in, &seq_len, &seq_items);
- }
+ mp_obj_get_array(seq_in, &seq_len, &seq_items);
if (seq_len < num_left + num_right) {
goto too_short;
}
@@ -1431,7 +1418,11 @@ void *m_malloc_fail(size_t num_bytes) {
}
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) {
- nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
+ if (msg == NULL) {
+ nlr_raise(mp_obj_new_exception(exc_type));
+ } else {
+ nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
+ }
}
NORETURN void mp_raise_ValueError(const char *msg) {
diff --git a/qemu-arm/Makefile b/qemu-arm/Makefile
index 0af2fc901..dce739fc9 100644
--- a/qemu-arm/Makefile
+++ b/qemu-arm/Makefile
@@ -36,9 +36,11 @@ LDFLAGS= --specs=nano.specs --specs=rdimon.specs -Wl,--gc-sections -Wl,-Map=$(@:
SRC_C = \
main.c \
+ modmachine.c \
SRC_TEST_C = \
test_main.c \
+ modmachine.c \
LIB_SRC_C = $(addprefix lib/,\
libm/math.c \
diff --git a/qemu-arm/main.c b/qemu-arm/main.c
index b6ff73980..aa7247b44 100644
--- a/qemu-arm/main.c
+++ b/qemu-arm/main.c
@@ -1,4 +1,5 @@
#include <stdint.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
@@ -59,4 +60,6 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void nlr_jump_fail(void *val) {
+ printf("uncaught NLR\n");
+ exit(1);
}
diff --git a/cc3200/util/std.h b/qemu-arm/modmachine.c
index a74c90e25..0f66349a8 100644
--- a/cc3200/util/std.h
+++ b/qemu-arm/modmachine.c
@@ -1,9 +1,9 @@
/*
- * This file is part of the Micro Python project, http://micropython.org/
+ * This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
- * Copyright (c) 2013, 2014 Damien P. George
+ * Copyright (c) 2017 Damien P. George
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,13 +24,24 @@
* THE SOFTWARE.
*/
-// This file is needed because in some cases we can't include stdio.h,
-// because the CC3100 socket driver has name clashes with it.
+#include "extmod/machine_mem.h"
+#include "extmod/machine_pinbase.h"
+#include "extmod/machine_signal.h"
-typedef unsigned int size_t;
+STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
+ { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
-int printf(const char *fmt, ...);
-int snprintf(char *str, size_t size, const char *fmt, ...);
+ { 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) },
-// Convenience function, defined in main.c.
-void stoupper (char *str);
+ { MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
+};
+
+STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
+
+const mp_obj_module_t mp_module_machine = {
+ .base = { &mp_type_module },
+ .globals = (mp_obj_dict_t*)&machine_module_globals,
+};
diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h
index 853385d6a..3452266f4 100644
--- a/qemu-arm/mpconfigport.h
+++ b/qemu-arm/mpconfigport.h
@@ -33,6 +33,7 @@
#define MICROPY_PY_URE (1)
#define MICROPY_PY_UHEAPQ (1)
#define MICROPY_PY_UHASHLIB (1)
+#define MICROPY_PY_MACHINE (1)
#define MICROPY_USE_INTERNAL_PRINTF (0)
// type definitions for the specific machine
@@ -57,5 +58,8 @@ typedef long mp_off_t;
#define MICROPY_PORT_BUILTINS \
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
+#define MICROPY_PORT_BUILTIN_MODULES \
+ { MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
+
// We need to provide a declaration/definition of alloca()
#include <alloca.h>
diff --git a/qemu-arm/test_main.c b/qemu-arm/test_main.c
index 5c0c915c4..4d8993090 100644
--- a/qemu-arm/test_main.c
+++ b/qemu-arm/test_main.c
@@ -1,4 +1,5 @@
#include <stdint.h>
+#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <malloc.h>
@@ -92,4 +93,6 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
void nlr_jump_fail(void *val) {
+ printf("uncaught NLR\n");
+ exit(1);
}
diff --git a/stmhal/accel.c b/stmhal/accel.c
index 827e9177a..2e3504b06 100644
--- a/stmhal/accel.c
+++ b/stmhal/accel.c
@@ -76,9 +76,9 @@ STATIC void accel_start(void) {
// turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again
mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off
- HAL_Delay(30);
+ mp_hal_delay_ms(30);
mp_hal_pin_high(&MICROPY_HW_MMA_AVDD_PIN); // turn on
- HAL_Delay(30);
+ mp_hal_delay_ms(30);
HAL_StatusTypeDef status;
@@ -98,7 +98,7 @@ STATIC void accel_start(void) {
status = HAL_I2C_Mem_Write(&I2CHandle1, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
// wait for MMA to become active
- HAL_Delay(30);
+ mp_hal_delay_ms(30);
}
/******************************************************************************/
diff --git a/stmhal/gccollect.c b/stmhal/gccollect.c
index 8a7bbf27f..d7223dedc 100644
--- a/stmhal/gccollect.c
+++ b/stmhal/gccollect.c
@@ -39,7 +39,7 @@ mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs);
void gc_collect(void) {
// get current time, in case we want to time the GC
#if 0
- uint32_t start = sys_tick_get_microseconds();
+ uint32_t start = mp_hal_ticks_us();
#endif
// start the GC
@@ -66,7 +66,7 @@ void gc_collect(void) {
#if 0
// print GC info
- uint32_t ticks = sys_tick_get_microseconds() - start;
+ uint32_t ticks = mp_hal_ticks_us() - start;
gc_info_t info;
gc_info(&info);
printf("GC@%lu %lums\n", start, ticks);
diff --git a/stmhal/i2c.c b/stmhal/i2c.c
index 29c350d22..412a8e363 100644
--- a/stmhal/i2c.c
+++ b/stmhal/i2c.c
@@ -346,7 +346,7 @@ STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) {
// stop bit was generated and bus is back to normal
return;
}
- HAL_Delay(1);
+ mp_hal_delay_ms(1);
}
// bus was/is busy, need to reset the peripheral to get it to work again
i2c_deinit(i2c);
diff --git a/stmhal/lcd.c b/stmhal/lcd.c
index e73b6e16d..cde6c36f6 100644
--- a/stmhal/lcd.c
+++ b/stmhal/lcd.c
@@ -274,11 +274,11 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_
mp_hal_pin_output(lcd->pin_bl);
// init the LCD
- HAL_Delay(1); // wait a bit
+ mp_hal_delay_ms(1); // wait a bit
mp_hal_pin_low(lcd->pin_rst); // RST=0; reset
- HAL_Delay(1); // wait for reset; 2us min
+ mp_hal_delay_ms(1); // wait for reset; 2us min
mp_hal_pin_high(lcd->pin_rst); // RST=1; enable
- HAL_Delay(1); // wait for reset; 2us min
+ mp_hal_delay_ms(1); // wait for reset; 2us min
lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal
lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display)
lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias
diff --git a/stmhal/led.c b/stmhal/led.c
index 357aed407..be98aa4a4 100644
--- a/stmhal/led.c
+++ b/stmhal/led.c
@@ -275,7 +275,7 @@ void led_debug(int n, int delay) {
led_state(2, n & 2);
led_state(3, n & 4);
led_state(4, n & 8);
- HAL_Delay(delay);
+ mp_hal_delay_ms(delay);
}
/******************************************************************************/
diff --git a/stmhal/main.c b/stmhal/main.c
index c6d482f3c..e07f6cf8c 100644
--- a/stmhal/main.c
+++ b/stmhal/main.c
@@ -71,10 +71,10 @@ void flash_error(int n) {
for (int i = 0; i < n; i++) {
led_state(PYB_LED_RED, 1);
led_state(PYB_LED_GREEN, 0);
- HAL_Delay(250);
+ mp_hal_delay_ms(250);
led_state(PYB_LED_RED, 0);
led_state(PYB_LED_GREEN, 1);
- HAL_Delay(250);
+ mp_hal_delay_ms(250);
}
led_state(PYB_LED_GREEN, 0);
}
@@ -349,7 +349,7 @@ STATIC uint update_reset_mode(uint reset_mode) {
if (!switch_get()) {
break;
}
- HAL_Delay(20);
+ mp_hal_delay_ms(20);
if (i % 30 == 29) {
if (++reset_mode > 3) {
reset_mode = 1;
@@ -364,13 +364,13 @@ STATIC uint update_reset_mode(uint reset_mode) {
led_state(2, 0);
led_state(3, 0);
led_state(4, 0);
- HAL_Delay(50);
+ mp_hal_delay_ms(50);
led_state(2, reset_mode & 1);
led_state(3, reset_mode & 2);
led_state(4, reset_mode & 4);
- HAL_Delay(50);
+ mp_hal_delay_ms(50);
}
- HAL_Delay(400);
+ mp_hal_delay_ms(400);
#elif defined(MICROPY_HW_LED1)
@@ -383,11 +383,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
break;
}
led_state(1, 1);
- HAL_Delay(100);
+ mp_hal_delay_ms(100);
led_state(1, 0);
- HAL_Delay(200);
+ mp_hal_delay_ms(200);
}
- HAL_Delay(400);
+ mp_hal_delay_ms(400);
if (!switch_get()) {
break;
}
@@ -399,11 +399,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
for (uint i = 0; i < 2; i++) {
for (uint j = 0; j < reset_mode; j++) {
led_state(1, 1);
- HAL_Delay(100);
+ mp_hal_delay_ms(100);
led_state(1, 0);
- HAL_Delay(200);
+ mp_hal_delay_ms(200);
}
- HAL_Delay(400);
+ mp_hal_delay_ms(400);
}
#else
#error Need a reset mode update method
diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c
index 16c50079d..d615a0f2b 100644
--- a/stmhal/modmachine.c
+++ b/stmhal/modmachine.c
@@ -324,7 +324,7 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
//printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q);
// let the USB CDC have a chance to process before we change the clock
- HAL_Delay(5);
+ mp_hal_delay_ms(5);
// desired system clock source is in sysclk_source
RCC_ClkInitTypeDef RCC_ClkInitStruct;
diff --git a/stmhal/modnwcc3k.c b/stmhal/modnwcc3k.c
index 19aeabf5c..e1426c055 100644
--- a/stmhal/modnwcc3k.c
+++ b/stmhal/modnwcc3k.c
@@ -36,6 +36,7 @@
#include "py/stream.h"
#include "py/runtime.h"
#include "py/mperrno.h"
+#include "py/mphal.h"
#include "netutils.h"
#include "modnetwork.h"
#include "pin.h"
@@ -120,7 +121,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
if (retry == 0 || CC3000_EXPORT(errno) != -95) {
return CC3000_EXPORT(errno);
}
- HAL_Delay(50);
+ mp_hal_delay_ms(50);
}
if (ip == 0) {
diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c
index 04d37ccee..e3d5c6370 100644
--- a/stmhal/modnwwiznet5k.c
+++ b/stmhal/modnwwiznet5k.c
@@ -202,7 +202,7 @@ STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_
*_errno = MP_ENOTCONN; // ??
return -1;
}
- HAL_Delay(1);
+ mp_hal_delay_ms(1);
}
}
@@ -348,9 +348,9 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
mp_hal_pin_output(wiznet5k_obj.rst);
mp_hal_pin_low(wiznet5k_obj.rst);
- HAL_Delay(1); // datasheet says 2us
+ mp_hal_delay_ms(1); // datasheet says 2us
mp_hal_pin_high(wiznet5k_obj.rst);
- HAL_Delay(160); // datasheet says 150ms
+ mp_hal_delay_ms(160); // datasheet says 150ms
reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
@@ -371,7 +371,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
ctlnetwork(CN_SET_NETINFO, (void*)&netinfo);
// seems we need a small delay after init
- HAL_Delay(250);
+ mp_hal_delay_ms(250);
// register with network module
mod_network_register_nic(&wiznet5k_obj);
diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c
index 93ae5d40b..296bcbae0 100644
--- a/stmhal/modpyb.c
+++ b/stmhal/modpyb.c
@@ -34,6 +34,7 @@
#include "py/obj.h"
#include "py/gc.h"
#include "py/builtin.h"
+#include "py/mphal.h"
#include "lib/utils/pyexec.h"
#include "lib/oofatfs/ff.h"
#include "lib/oofatfs/diskio.h"
@@ -71,20 +72,6 @@ STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) {
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug);
-/// \function millis()
-/// Returns the number of milliseconds since the board was last reset.
-///
-/// The result is always a micropython smallint (31-bit signed number), so
-/// after 2^30 milliseconds (about 12.4 days) this will start to return
-/// negative numbers.
-STATIC mp_obj_t pyb_millis(void) {
- // We want to "cast" the 32 bit unsigned into a small-int. This means
- // copying the MSB down 1 bit (extending the sign down), which is
- // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
- return MP_OBJ_NEW_SMALL_INT(HAL_GetTick());
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
-
/// \function elapsed_millis(start)
/// Returns the number of milliseconds which have elapsed since `start`.
///
@@ -97,25 +84,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
/// # Perform some operation
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
uint32_t startMillis = mp_obj_get_int(start);
- uint32_t currMillis = HAL_GetTick();
+ uint32_t currMillis = mp_hal_ticks_ms();
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
-/// \function micros()
-/// Returns the number of microseconds since the board was last reset.
-///
-/// The result is always a micropython smallint (31-bit signed number), so
-/// after 2^30 microseconds (about 17.8 minutes) this will start to return
-/// negative numbers.
-STATIC mp_obj_t pyb_micros(void) {
- // We want to "cast" the 32 bit unsigned into a small-int. This means
- // copying the MSB down 1 bit (extending the sign down), which is
- // equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
- return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds());
-}
-STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
-
/// \function elapsed_micros(start)
/// Returns the number of microseconds which have elapsed since `start`.
///
@@ -128,7 +101,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
/// # Perform some operation
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
uint32_t startMicros = mp_obj_get_int(start);
- uint32_t currMicros = sys_tick_get_microseconds();
+ uint32_t currMicros = mp_hal_ticks_us();
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
@@ -168,9 +141,9 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ 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_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_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)&pyb_micros_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 },
diff --git a/stmhal/mphalport.h b/stmhal/mphalport.h
index 7204d4bd3..752102402 100644
--- a/stmhal/mphalport.h
+++ b/stmhal/mphalport.h
@@ -27,13 +27,7 @@ void mp_hal_set_interrupt_char(int c); // -1 to disable
// timing functions
-#include "stmhal/systick.h"
-
-#define mp_hal_delay_ms HAL_Delay
-#define mp_hal_delay_us(us) sys_tick_udelay(us)
-#define mp_hal_delay_us_fast(us) sys_tick_udelay(us)
-#define mp_hal_ticks_ms HAL_GetTick
-#define mp_hal_ticks_us() sys_tick_get_microseconds()
+#define mp_hal_delay_us_fast(us) mp_hal_delay_us(us)
extern bool mp_hal_ticks_cpu_enabled;
void mp_hal_ticks_cpu_enable(void);
diff --git a/stmhal/sdcard.c b/stmhal/sdcard.c
index 6e9c46df5..73206f431 100644
--- a/stmhal/sdcard.c
+++ b/stmhal/sdcard.c
@@ -28,9 +28,9 @@
#include "py/nlr.h"
#include "py/runtime.h"
+#include "py/mphal.h"
#include "lib/oofatfs/ff.h"
#include "extmod/vfs_fat.h"
-#include "mphalport.h"
#include "sdcard.h"
#include "pin.h"
@@ -145,7 +145,7 @@ bool sdcard_power_on(void) {
if (retry == 0) {
goto error;
}
- HAL_Delay(50);
+ mp_hal_delay_ms(50);
}
// configure the SD bus width for wide operation
diff --git a/stmhal/stm32_it.c b/stmhal/stm32_it.c
index d8fcc59ce..913f1c931 100644
--- a/stmhal/stm32_it.c
+++ b/stmhal/stm32_it.c
@@ -298,7 +298,7 @@ void SysTick_Handler(void) {
uwTick += 1;
// Read the systick control regster. This has the side effect of clearing
- // the COUNTFLAG bit, which makes the logic in sys_tick_get_microseconds
+ // the COUNTFLAG bit, which makes the logic in mp_hal_ticks_us
// work properly.
SysTick->CTRL;
diff --git a/stmhal/systick.c b/stmhal/systick.c
index ade05d74d..eb11de9b7 100644
--- a/stmhal/systick.c
+++ b/stmhal/systick.c
@@ -24,20 +24,36 @@
* THE SOFTWARE.
*/
-#include STM32_HAL_H
-
-#include "py/obj.h"
+#include "py/mphal.h"
#include "irq.h"
#include "systick.h"
#include "pybthread.h"
-// We provide our own version of HAL_Delay that calls __WFI while waiting, in
-// order to reduce power consumption.
-// Note: Upon entering this function we may or may not have the GIL.
+extern __IO uint32_t uwTick;
+
+// We provide our own version of HAL_Delay that calls __WFI while waiting,
+// and works when interrupts are disabled. This function is intended to be
+// used only by the ST HAL functions.
void HAL_Delay(uint32_t Delay) {
if (query_irq() == IRQ_STATE_ENABLED) {
// IRQs enabled, so can use systick counter to do the delay
- extern __IO uint32_t uwTick;
+ uint32_t start = uwTick;
+ // Wraparound of tick is taken care of by 2's complement arithmetic.
+ while (uwTick - start < Delay) {
+ // Enter sleep mode, waiting for (at least) the SysTick interrupt.
+ __WFI();
+ }
+ } else {
+ // IRQs disabled, use mp_hal_delay_ms routine.
+ mp_hal_delay_ms(Delay);
+ }
+}
+
+// Core delay function that does an efficient sleep and may switch thread context.
+// Note: Upon entering this function we may or may not have the GIL.
+void mp_hal_delay_ms(mp_uint_t Delay) {
+ if (query_irq() == IRQ_STATE_ENABLED) {
+ // IRQs enabled, so can use systick counter to do the delay
uint32_t start = uwTick;
// Wraparound of tick is taken care of by 2's complement arithmetic.
while (uwTick - start < Delay) {
@@ -64,11 +80,11 @@ void HAL_Delay(uint32_t Delay) {
}
// delay for given number of microseconds
-void sys_tick_udelay(uint32_t usec) {
+void mp_hal_delay_us(mp_uint_t usec) {
if (query_irq() == IRQ_STATE_ENABLED) {
// IRQs enabled, so can use systick counter to do the delay
- uint32_t start = sys_tick_get_microseconds();
- while (sys_tick_get_microseconds() - start < usec) {
+ uint32_t start = mp_hal_ticks_us();
+ while (mp_hal_ticks_us() - start < usec) {
}
} else {
// IRQs disabled, so need to use a busy loop for the delay
@@ -92,11 +108,15 @@ void sys_tick_wait_at_least(uint32_t start_tick, uint32_t delay_ms) {
}
}
+mp_uint_t mp_hal_ticks_ms(void) {
+ return uwTick;
+}
+
// The SysTick timer counts down at 168 MHz, so we can use that knowledge
// to grab a microsecond counter.
//
// We assume that HAL_GetTickis returns milliseconds.
-uint32_t sys_tick_get_microseconds(void) {
+mp_uint_t mp_hal_ticks_us(void) {
mp_uint_t irq_state = disable_irq();
uint32_t counter = SysTick->VAL;
uint32_t milliseconds = HAL_GetTick();
diff --git a/stmhal/systick.h b/stmhal/systick.h
index 5a4dfb3ed..1e7f62335 100644
--- a/stmhal/systick.h
+++ b/stmhal/systick.h
@@ -24,7 +24,5 @@
* THE SOFTWARE.
*/
-void sys_tick_udelay(uint32_t usec);
void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
-uint32_t sys_tick_get_microseconds(void);
diff --git a/tests/basics/array_q.py b/tests/basics/array_intbig.py
index 2975cd385..2975cd385 100644
--- a/tests/basics/array_q.py
+++ b/tests/basics/array_intbig.py
diff --git a/tests/basics/builtin_abs.py b/tests/basics/builtin_abs.py
index 788bc450f..142344e22 100644
--- a/tests/basics/builtin_abs.py
+++ b/tests/basics/builtin_abs.py
@@ -4,11 +4,3 @@ print(abs(False))
print(abs(True))
print(abs(1))
print(abs(-1))
-
-# bignum
-print(abs(123456789012345678901234567890))
-print(abs(-123456789012345678901234567890))
-
-# edge cases for 32 and 64 bit archs (small int overflow when negating)
-print(abs(-0x3fffffff - 1))
-print(abs(-0x3fffffffffffffff - 1))
diff --git a/tests/basics/builtin_abs_intbig.py b/tests/basics/builtin_abs_intbig.py
new file mode 100644
index 000000000..3dd5ea89f
--- /dev/null
+++ b/tests/basics/builtin_abs_intbig.py
@@ -0,0 +1,9 @@
+# test builtin abs
+
+# bignum
+print(abs(123456789012345678901234567890))
+print(abs(-123456789012345678901234567890))
+
+# edge cases for 32 and 64 bit archs (small int overflow when negating)
+print(abs(-0x3fffffff - 1))
+print(abs(-0x3fffffffffffffff - 1))
diff --git a/tests/basics/builtin_bin.py b/tests/basics/builtin_bin.py
index f6b6079de..85af406ce 100644
--- a/tests/basics/builtin_bin.py
+++ b/tests/basics/builtin_bin.py
@@ -8,5 +8,4 @@ print(bin(-15))
print(bin(12345))
print(bin(0b10101))
-print(bin(12345678901234567890))
print(bin(0b10101010101010101010))
diff --git a/tests/basics/builtin_bin_intbig.py b/tests/basics/builtin_bin_intbig.py
new file mode 100644
index 000000000..345e1f687
--- /dev/null
+++ b/tests/basics/builtin_bin_intbig.py
@@ -0,0 +1,3 @@
+# test builtin bin function
+
+print(bin(12345678901234567890))
diff --git a/tests/basics/builtin_divmod.py b/tests/basics/builtin_divmod.py
index c3b865819..26b3ae382 100644
--- a/tests/basics/builtin_divmod.py
+++ b/tests/basics/builtin_divmod.py
@@ -10,18 +10,6 @@ except ZeroDivisionError:
print("ZeroDivisionError")
try:
- divmod(1 << 65, 0)
-except ZeroDivisionError:
- print("ZeroDivisionError")
-
-try:
divmod('a', 'b')
except TypeError:
print("TypeError")
-
-# bignum
-l = (1 << 65) + 123
-print(divmod(3, l))
-print(divmod(l, 5))
-print(divmod(l + 3, l))
-print(divmod(l * 20, l + 2))
diff --git a/tests/basics/builtin_divmod_intbig.py b/tests/basics/builtin_divmod_intbig.py
new file mode 100644
index 000000000..758e83415
--- /dev/null
+++ b/tests/basics/builtin_divmod_intbig.py
@@ -0,0 +1,13 @@
+# test builtin divmod
+
+try:
+ divmod(1 << 65, 0)
+except ZeroDivisionError:
+ print("ZeroDivisionError")
+
+# bignum
+l = (1 << 65) + 123
+print(divmod(3, l))
+print(divmod(l, 5))
+print(divmod(l + 3, l))
+print(divmod(l * 20, l + 2))
diff --git a/tests/basics/builtin_hash.py b/tests/basics/builtin_hash.py
index ffea08e57..704895fbb 100644
--- a/tests/basics/builtin_hash.py
+++ b/tests/basics/builtin_hash.py
@@ -4,8 +4,6 @@ print(hash(False))
print(hash(True))
print({():1}) # hash tuple
print({(1,):1}) # hash non-empty tuple
-print({1 << 66:1}) # hash big int
-print({-(1 << 66):2}) # hash negative big int
print(hash in {hash:1}) # hash function
try:
@@ -50,9 +48,3 @@ class E:
def __hash__(self):
return True
print(hash(E()))
-
-# __hash__ returning a large number should be truncated
-class F:
- def __hash__(self):
- return 1 << 70 | 1
-print(hash(F()) != 0)
diff --git a/tests/basics/builtin_hash_intbig.py b/tests/basics/builtin_hash_intbig.py
new file mode 100644
index 000000000..0092c0f3a
--- /dev/null
+++ b/tests/basics/builtin_hash_intbig.py
@@ -0,0 +1,10 @@
+# test builtin hash function
+
+print({1 << 66:1}) # hash big int
+print({-(1 << 66):2}) # hash negative big int
+
+# __hash__ returning a large number should be truncated
+class F:
+ def __hash__(self):
+ return 1 << 70 | 1
+print(hash(F()) != 0)
diff --git a/tests/basics/builtin_hex.py b/tests/basics/builtin_hex.py
index 7d1c98a7a..95d74257e 100644
--- a/tests/basics/builtin_hex.py
+++ b/tests/basics/builtin_hex.py
@@ -7,6 +7,3 @@ print(hex(-15))
print(hex(12345))
print(hex(0x12345))
-
-print(hex(12345678901234567890))
-print(hex(0x12345678901234567890))
diff --git a/tests/basics/builtin_hex_intbig.py b/tests/basics/builtin_hex_intbig.py
new file mode 100644
index 000000000..7049ca3f5
--- /dev/null
+++ b/tests/basics/builtin_hex_intbig.py
@@ -0,0 +1,4 @@
+# test builtin hex function
+
+print(hex(12345678901234567890))
+print(hex(0x12345678901234567890))
diff --git a/tests/basics/builtin_oct.py b/tests/basics/builtin_oct.py
index d8ba8e434..6dc48a6fa 100644
--- a/tests/basics/builtin_oct.py
+++ b/tests/basics/builtin_oct.py
@@ -7,6 +7,3 @@ print(oct(-15))
print(oct(12345))
print(oct(0o12345))
-
-print(oct(12345678901234567890))
-print(oct(0o12345670123456701234))
diff --git a/tests/basics/builtin_oct_intbig.py b/tests/basics/builtin_oct_intbig.py
new file mode 100644
index 000000000..4dc28ab46
--- /dev/null
+++ b/tests/basics/builtin_oct_intbig.py
@@ -0,0 +1,4 @@
+# test builtin oct function
+
+print(oct(12345678901234567890))
+print(oct(0o12345670123456701234))
diff --git a/tests/basics/builtin_pow3.py b/tests/basics/builtin_pow3.py
index 35e143a38..dec7253bb 100644
--- a/tests/basics/builtin_pow3.py
+++ b/tests/basics/builtin_pow3.py
@@ -8,8 +8,6 @@ except NotImplementedError:
print("SKIP")
sys.exit()
-print(pow(555557, 1000002, 1000003))
-
# 3 arg pow is defined to only work on integers
try:
print(pow("x", 5, 6))
@@ -25,15 +23,3 @@ try:
print(pow(4, 5, "z"))
except TypeError:
print("TypeError expected")
-
-# Tests for 3 arg pow with large values
-
-# This value happens to be prime
-x = 0xd48a1e2a099b1395895527112937a391d02d4a208bce5d74b281cf35a57362502726f79a632f063a83c0eba66196712d963aa7279ab8a504110a668c0fc38a7983c51e6ee7a85cae87097686ccdc359ee4bbf2c583bce524e3f7836bded1c771a4efcb25c09460a862fc98e18f7303df46aaeb34da46b0c4d61d5cd78350f3edb60e6bc4befa712a849
-y = 0x3accf60bb1a5365e4250d1588eb0fe6cd81ad495e9063f90880229f2a625e98c59387238670936afb2cafc5b79448e4414d6cd5e9901aa845aa122db58ddd7b9f2b17414600a18c47494ed1f3d49d005a5
-
-print(hex(pow(2, 200, x))) # Should not overflow, just 1 << 200
-print(hex(pow(2, x-1, x))) # Should be 1, since x is prime
-print(hex(pow(y, x-1, x))) # Should be 1, since x is prime
-print(hex(pow(y, y-1, x))) # Should be a 'big value'
-print(hex(pow(y, y-1, y))) # Should be a 'big value'
diff --git a/tests/basics/builtin_pow3_intbig.py b/tests/basics/builtin_pow3_intbig.py
new file mode 100644
index 000000000..9f482cbde
--- /dev/null
+++ b/tests/basics/builtin_pow3_intbig.py
@@ -0,0 +1,23 @@
+# test builtin pow() with integral values
+# 3 arg version
+
+try:
+ print(pow(3, 4, 7))
+except NotImplementedError:
+ import sys
+ print("SKIP")
+ sys.exit()
+
+print(pow(555557, 1000002, 1000003))
+
+# Tests for 3 arg pow with large values
+
+# This value happens to be prime
+x = 0xd48a1e2a099b1395895527112937a391d02d4a208bce5d74b281cf35a57362502726f79a632f063a83c0eba66196712d963aa7279ab8a504110a668c0fc38a7983c51e6ee7a85cae87097686ccdc359ee4bbf2c583bce524e3f7836bded1c771a4efcb25c09460a862fc98e18f7303df46aaeb34da46b0c4d61d5cd78350f3edb60e6bc4befa712a849
+y = 0x3accf60bb1a5365e4250d1588eb0fe6cd81ad495e9063f90880229f2a625e98c59387238670936afb2cafc5b79448e4414d6cd5e9901aa845aa122db58ddd7b9f2b17414600a18c47494ed1f3d49d005a5
+
+print(hex(pow(2, 200, x))) # Should not overflow, just 1 << 200
+print(hex(pow(2, x-1, x))) # Should be 1, since x is prime
+print(hex(pow(y, x-1, x))) # Should be 1, since x is prime
+print(hex(pow(y, y-1, x))) # Should be a 'big value'
+print(hex(pow(y, y-1, y))) # Should be a 'big value'
diff --git a/tests/basics/bytearray_longint.py b/tests/basics/bytearray_intbig.py
index 334eabe12..334eabe12 100644
--- a/tests/basics/bytearray_longint.py
+++ b/tests/basics/bytearray_intbig.py
diff --git a/tests/basics/bytes_construct.py b/tests/basics/bytes_construct.py
index 59e02f063..164738767 100644
--- a/tests/basics/bytes_construct.py
+++ b/tests/basics/bytes_construct.py
@@ -11,9 +11,6 @@ print(bytes(bytearray(4)))
print(bytes(array('b', [1, 2])))
print(bytes(array('h', [0x101, 0x202])))
-# long ints
-print(ord(bytes([14953042807679334000 & 0xff])))
-
# constructor value out of range
try:
bytes([-1])
diff --git a/tests/basics/bytes_construct_intbig.py b/tests/basics/bytes_construct_intbig.py
new file mode 100644
index 000000000..c32de185f
--- /dev/null
+++ b/tests/basics/bytes_construct_intbig.py
@@ -0,0 +1,4 @@
+# test construction of bytes from different objects
+
+# long ints
+print(ord(bytes([14953042807679334000 & 0xff])))
diff --git a/tests/basics/floordivide.py b/tests/basics/floordivide.py
index 930313d6c..60e7634b1 100644
--- a/tests/basics/floordivide.py
+++ b/tests/basics/floordivide.py
@@ -12,18 +12,3 @@ print(a // b)
print(a // -b)
print(-a // b)
print(-a // -b)
-
-if True:
- a = 987654321987987987987987987987
- b = 19
-
- print(a // b)
- print(a // -b)
- print(-a // b)
- print(-a // -b)
- a = 10000000000000000000000000000000000000000000
- b = 100
- print(a // b)
- print(a // -b)
- print(-a // b)
- print(-a // -b)
diff --git a/tests/basics/floordivide_intbig.py b/tests/basics/floordivide_intbig.py
new file mode 100644
index 000000000..422329fcd
--- /dev/null
+++ b/tests/basics/floordivide_intbig.py
@@ -0,0 +1,15 @@
+# check modulo matches python definition
+
+a = 987654321987987987987987987987
+b = 19
+
+print(a // b)
+print(a // -b)
+print(-a // b)
+print(-a // -b)
+a = 10000000000000000000000000000000000000000000
+b = 100
+print(a // b)
+print(a // -b)
+print(-a // b)
+print(-a // -b)
diff --git a/tests/basics/int_mpz.py b/tests/basics/int_big1.py
index 425bc21b6..425bc21b6 100644
--- a/tests/basics/int_mpz.py
+++ b/tests/basics/int_big1.py
diff --git a/tests/basics/int_bytes.py b/tests/basics/int_bytes.py
index 2f468da44..45965ed46 100644
--- a/tests/basics/int_bytes.py
+++ b/tests/basics/int_bytes.py
@@ -1,7 +1,6 @@
print((10).to_bytes(1, "little"))
print((111111).to_bytes(4, "little"))
print((100).to_bytes(10, "little"))
-print((2**64).to_bytes(9, "little"))
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"))
diff --git a/tests/basics/int_bytes_long.py b/tests/basics/int_bytes_intbig.py
index 81ebc6cdc..39cd67d26 100644
--- a/tests/basics/int_bytes_long.py
+++ b/tests/basics/int_bytes_intbig.py
@@ -1,3 +1,5 @@
+print((2**64).to_bytes(9, "little"))
+
b = bytes(range(20))
il = int.from_bytes(b, "little")
diff --git a/tests/basics/int_constfolding.py b/tests/basics/int_constfolding.py
index aa38fa6b8..7bb538378 100644
--- a/tests/basics/int_constfolding.py
+++ b/tests/basics/int_constfolding.py
@@ -7,19 +7,11 @@ print(+100)
# negation
print(-1)
print(-(-1))
-print(-0x3fffffff) # 32-bit edge case
-print(-0x3fffffffffffffff) # 64-bit edge case
-print(-(-0x3fffffff - 1)) # 32-bit edge case
-print(-(-0x3fffffffffffffff - 1)) # 64-bit edge case
# 1's complement
print(~0)
print(~1)
print(~-1)
-print(~0x3fffffff) # 32-bit edge case
-print(~0x3fffffffffffffff) # 64-bit edge case
-print(~(-0x3fffffff - 1)) # 32-bit edge case
-print(~(-0x3fffffffffffffff - 1)) # 64-bit edge case
# addition
print(1 + 2)
@@ -37,9 +29,3 @@ print(123 // 7, 123 % 7)
print(-123 // 7, -123 % 7)
print(123 // -7, 123 % -7)
print(-123 // -7, -123 % -7)
-
-# zero big-num on rhs
-print(1 + ((1 << 65) - (1 << 65)))
-
-# negative big-num on rhs
-print(1 + (-(1 << 65)))
diff --git a/tests/basics/int_constfolding_intbig.py b/tests/basics/int_constfolding_intbig.py
new file mode 100644
index 000000000..714f1559a
--- /dev/null
+++ b/tests/basics/int_constfolding_intbig.py
@@ -0,0 +1,19 @@
+# tests int constant folding in compiler
+
+# negation
+print(-0x3fffffff) # 32-bit edge case
+print(-0x3fffffffffffffff) # 64-bit edge case
+print(-(-0x3fffffff - 1)) # 32-bit edge case
+print(-(-0x3fffffffffffffff - 1)) # 64-bit edge case
+
+# 1's complement
+print(~0x3fffffff) # 32-bit edge case
+print(~0x3fffffffffffffff) # 64-bit edge case
+print(~(-0x3fffffff - 1)) # 32-bit edge case
+print(~(-0x3fffffffffffffff - 1)) # 64-bit edge case
+
+# zero big-num on rhs
+print(1 + ((1 << 65) - (1 << 65)))
+
+# negative big-num on rhs
+print(1 + (-(1 << 65)))
diff --git a/tests/basics/int_divmod.py b/tests/basics/int_divmod.py
index 3c76cd958..2e878135f 100644
--- a/tests/basics/int_divmod.py
+++ b/tests/basics/int_divmod.py
@@ -5,11 +5,3 @@ for i in range(-2, 3):
for j in range(-4, 5):
if j != 0:
print(i, j, i // j, i % j, divmod(i, j))
-
-# this tests bignum modulo
-a = 987654321987987987987987987987
-b = 19
-print(a % b)
-print(a % -b)
-print(-a % b)
-print(-a % -b)
diff --git a/tests/basics/int_divmod_intbig.py b/tests/basics/int_divmod_intbig.py
new file mode 100644
index 000000000..ea8de07f2
--- /dev/null
+++ b/tests/basics/int_divmod_intbig.py
@@ -0,0 +1,9 @@
+# test integer floor division and modulo
+
+# this tests bignum modulo
+a = 987654321987987987987987987987
+b = 19
+print(a % b)
+print(a % -b)
+print(-a % b)
+print(-a % -b)
diff --git a/tests/basics/int_long.py b/tests/basics/int_intbig.py
index a22075d1f..a22075d1f 100644
--- a/tests/basics/int_long.py
+++ b/tests/basics/int_intbig.py
diff --git a/tests/basics/list_slice_assign.py b/tests/basics/list_slice_assign.py
index baa9a0081..1ad1ef27c 100644
--- a/tests/basics/list_slice_assign.py
+++ b/tests/basics/list_slice_assign.py
@@ -34,3 +34,14 @@ print(l)
l = list(x)
del l[:-3]
print(l)
+
+# assign a tuple
+l = [1, 2, 3]
+l[0:1] = (10, 11, 12)
+print(l)
+
+# RHS of slice must be an iterable
+try:
+ [][0:1] = 123
+except TypeError:
+ print('TypeError')
diff --git a/tests/basics/memoryview1.py b/tests/basics/memoryview1.py
index 019a1179f..a771acdda 100644
--- a/tests/basics/memoryview1.py
+++ b/tests/basics/memoryview1.py
@@ -18,6 +18,10 @@ try:
m[0] = 1
except TypeError:
print("TypeError")
+try:
+ m[0:2] = b'00'
+except TypeError:
+ print("TypeError")
# test writing to bytearray
b = bytearray(b)
diff --git a/tests/basics/op_error.py b/tests/basics/op_error.py
index 5ba6a80e2..b30b5f0a3 100644
--- a/tests/basics/op_error.py
+++ b/tests/basics/op_error.py
@@ -23,7 +23,6 @@ test_exc("bytearray() // 2", TypeError)
# object with buffer protocol needed on rhs
test_exc("bytearray(1) + 1", TypeError)
-test_exc("(1 << 70) in 1", TypeError)
# unsupported subscription
test_exc("1[0]", TypeError)
diff --git a/tests/basics/op_error_intbig.py b/tests/basics/op_error_intbig.py
new file mode 100644
index 000000000..432c05a9f
--- /dev/null
+++ b/tests/basics/op_error_intbig.py
@@ -0,0 +1,13 @@
+# test errors from bad operations (unary, binary, etc)
+
+def test_exc(code, exc):
+ try:
+ exec(code)
+ print("no exception")
+ except exc:
+ print("right exception")
+ except:
+ print("wrong exception")
+
+# object with buffer protocol needed on rhs
+test_exc("(1 << 70) in 1", TypeError)
diff --git a/tests/basics/ordereddict1.py b/tests/basics/ordereddict1.py
index 5e8b2413b..7147968c5 100644
--- a/tests/basics/ordereddict1.py
+++ b/tests/basics/ordereddict1.py
@@ -9,8 +9,19 @@ except ImportError:
sys.exit()
d = OrderedDict([(10, 20), ("b", 100), (1, 2)])
+print(len(d))
print(list(d.keys()))
print(list(d.values()))
del d["b"]
+print(len(d))
+print(list(d.keys()))
+print(list(d.values()))
+
+# access remaining elements after deleting
+print(d[10], d[1])
+
+# add an element after deleting
+d["abc"] = 123
+print(len(d))
print(list(d.keys()))
print(list(d.values()))
diff --git a/tests/basics/slice_bignum.py b/tests/basics/slice_intbig.py
index cc820522b..cc820522b 100644
--- a/tests/basics/slice_bignum.py
+++ b/tests/basics/slice_intbig.py
diff --git a/tests/basics/string_join.py b/tests/basics/string_join.py
index 4a2e9aa91..82f1b799a 100644
--- a/tests/basics/string_join.py
+++ b/tests/basics/string_join.py
@@ -14,6 +14,11 @@ print(','.join('abc' for i in range(5)))
print(b','.join([b'abc', b'123']))
try:
+ ''.join(None)
+except TypeError:
+ print("TypeError")
+
+try:
print(b','.join(['abc', b'123']))
except TypeError:
print("TypeError")
diff --git a/tests/basics/struct1.py b/tests/basics/struct1.py
index d89519a2f..bb6877c78 100644
--- a/tests/basics/struct1.py
+++ b/tests/basics/struct1.py
@@ -37,34 +37,6 @@ s = struct.pack("BHBI", 10, 100, 200, 300)
v = struct.unpack("BHBI", s)
print(v == (10, 100, 200, 300))
-# check maximum pack on 32-bit machine
-print(struct.pack("<I", 2**32 - 1))
-print(struct.pack("<I", 0xffffffff))
-
-# long long ints
-print(struct.pack("<Q", 2**64 - 1))
-print(struct.pack(">Q", 2**64 - 1))
-print(struct.pack("<Q", 0xffffffffffffffff))
-print(struct.pack(">Q", 0xffffffffffffffff))
-print(struct.pack("<q", -1))
-print(struct.pack(">q", -1))
-print(struct.pack("<Q", 1234567890123456789))
-print(struct.pack("<q", -1234567890123456789))
-print(struct.pack(">Q", 1234567890123456789))
-print(struct.pack(">q", -1234567890123456789))
-print(struct.unpack("<Q", b"\x12\x34\x56\x78\x90\x12\x34\x56"))
-print(struct.unpack(">Q", b"\x12\x34\x56\x78\x90\x12\x34\x56"))
-print(struct.unpack("<q", b"\x12\x34\x56\x78\x90\x12\x34\xf6"))
-print(struct.unpack(">q", b"\xf2\x34\x56\x78\x90\x12\x34\x56"))
-
-# check maximum unpack
-print(struct.unpack("<I", b"\xff\xff\xff\xff"))
-print(struct.unpack("<Q", b"\xff\xff\xff\xff\xff\xff\xff\xff"))
-
-# check small int overflow
-print(struct.unpack("<i", b'\xff\xff\xff\x7f'))
-print(struct.unpack("<q", b'\xff\xff\xff\xff\xff\xff\xff\x7f'))
-
# network byte order
print(struct.pack('!i', 123))
diff --git a/tests/basics/struct1_intbig.py b/tests/basics/struct1_intbig.py
new file mode 100644
index 000000000..7f4c3ce12
--- /dev/null
+++ b/tests/basics/struct1_intbig.py
@@ -0,0 +1,37 @@
+try:
+ import ustruct as struct
+except:
+ try:
+ import struct
+ except ImportError:
+ import sys
+ print("SKIP")
+ sys.exit()
+
+# check maximum pack on 32-bit machine
+print(struct.pack("<I", 2**32 - 1))
+print(struct.pack("<I", 0xffffffff))
+
+# long long ints
+print(struct.pack("<Q", 2**64 - 1))
+print(struct.pack(">Q", 2**64 - 1))
+print(struct.pack("<Q", 0xffffffffffffffff))
+print(struct.pack(">Q", 0xffffffffffffffff))
+print(struct.pack("<q", -1))
+print(struct.pack(">q", -1))
+print(struct.pack("<Q", 1234567890123456789))
+print(struct.pack("<q", -1234567890123456789))
+print(struct.pack(">Q", 1234567890123456789))
+print(struct.pack(">q", -1234567890123456789))
+print(struct.unpack("<Q", b"\x12\x34\x56\x78\x90\x12\x34\x56"))
+print(struct.unpack(">Q", b"\x12\x34\x56\x78\x90\x12\x34\x56"))
+print(struct.unpack("<q", b"\x12\x34\x56\x78\x90\x12\x34\xf6"))
+print(struct.unpack(">q", b"\xf2\x34\x56\x78\x90\x12\x34\x56"))
+
+# check maximum unpack
+print(struct.unpack("<I", b"\xff\xff\xff\xff"))
+print(struct.unpack("<Q", b"\xff\xff\xff\xff\xff\xff\xff\xff"))
+
+# check small int overflow
+print(struct.unpack("<i", b'\xff\xff\xff\x7f'))
+print(struct.unpack("<q", b'\xff\xff\xff\xff\xff\xff\xff\x7f'))
diff --git a/tests/basics/unpack1.py b/tests/basics/unpack1.py
index 0e8ec592c..1e8b53aa1 100644
--- a/tests/basics/unpack1.py
+++ b/tests/basics/unpack1.py
@@ -41,7 +41,7 @@ a, *b, c = 24, 25, 26, 27 ; print(a, b)
a = [28, 29]
*b, = a
-print(a, b, a == b)
+print(a, b, a == b, a is b)
[*a] = [1, 2, 3]
print(a)
diff --git a/tests/cmdline/cmd_parsetree.py.exp b/tests/cmdline/cmd_parsetree.py.exp
index 36f1f1b27..17fecaf96 100644
--- a/tests/cmdline/cmd_parsetree.py.exp
+++ b/tests/cmdline/cmd_parsetree.py.exp
@@ -15,13 +15,13 @@
str(str)
[ 8] rule(5) (n=2)
id(c)
-[ 8] literal str(a very long str that will not be interned)
+[ 8] literal \.\+
[ 9] rule(5) (n=2)
id(d)
bytes(bytes)
[ 10] rule(5) (n=2)
id(e)
-[ 10] literal bytes(a very long bytes that will not be interned)
+[ 10] literal \.\+
[ 11] rule(5) (n=2)
id(f)
[ 11] literal \.\+
diff --git a/tests/cpydiff/core_arguments.py b/tests/cpydiff/core_arguments.py
new file mode 100644
index 000000000..a0831ab40
--- /dev/null
+++ b/tests/cpydiff/core_arguments.py
@@ -0,0 +1,10 @@
+"""
+categories: Core
+description: Error messages may display incorrect argument counts
+cause: Unknown
+workaround: Unknown
+"""
+try:
+ [].append()
+except Exception as e:
+ print(e)
diff --git a/tests/cpydiff/core_class_delnotimpl.py b/tests/cpydiff/core_class_delnotimpl.py
new file mode 100644
index 000000000..c51c3d536
--- /dev/null
+++ b/tests/cpydiff/core_class_delnotimpl.py
@@ -0,0 +1,16 @@
+"""
+categories: Core,Classes
+description: Special method __del__ not implemented for user-defined classes
+cause: Unknown
+workaround: Unknown
+"""
+import gc
+
+class Foo():
+ def __del__(self):
+ print('__del__')
+
+f = Foo()
+del f
+
+gc.collect()
diff --git a/tests/cpydiff/core_class_superaslocal.py b/tests/cpydiff/core_class_superaslocal.py
new file mode 100644
index 000000000..fc07ccb38
--- /dev/null
+++ b/tests/cpydiff/core_class_superaslocal.py
@@ -0,0 +1,13 @@
+"""
+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()
diff --git a/tests/cpydiff/core_class_supermultiple.py b/tests/cpydiff/core_class_supermultiple.py
new file mode 100644
index 000000000..adf4a17a8
--- /dev/null
+++ b/tests/cpydiff/core_class_supermultiple.py
@@ -0,0 +1,27 @@
+"""
+categories: Core,Classes
+description: When inheriting from multiple classes super() only calls one class
+cause: Depth first non-exhaustive method resolution order
+workaround: Unknown
+"""
+class A:
+ def __init__(self):
+ print("A.__init__")
+
+class B(A):
+ def __init__(self):
+ print("B.__init__")
+ super().__init__()
+
+class C(A):
+ def __init__(self):
+ print("C.__init__")
+ super().__init__()
+
+
+class D(B,C):
+ def __init__(self):
+ print("D.__init__")
+ super().__init__()
+
+D()
diff --git a/tests/cpydiff/core_class_superproperty.py b/tests/cpydiff/core_class_superproperty.py
new file mode 100644
index 000000000..1ec210550
--- /dev/null
+++ b/tests/cpydiff/core_class_superproperty.py
@@ -0,0 +1,18 @@
+"""
+categories: Core,Classes
+description: Calling super() getter property in subclass will return a property object, not the value
+cause: Unknown
+workaround: Unknown
+"""
+class A:
+ @property
+ def p(self):
+ return {"a":10}
+
+class AA(A):
+ @property
+ def p(self):
+ return super().p
+
+a = AA()
+print(a.p)
diff --git a/tests/cpydiff/core_function_instancevar.py b/tests/cpydiff/core_function_instancevar.py
new file mode 100644
index 000000000..ab027b166
--- /dev/null
+++ b/tests/cpydiff/core_function_instancevar.py
@@ -0,0 +1,11 @@
+"""
+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_unpacking.py b/tests/cpydiff/core_function_unpacking.py
new file mode 100644
index 000000000..f0cc24055
--- /dev/null
+++ b/tests/cpydiff/core_function_unpacking.py
@@ -0,0 +1,7 @@
+"""
+categories: Core,Functions
+description: Unpacking function arguments in non-last position gives incorrect result
+cause: Unknown
+workaround: Unknown
+"""
+print(*(1, 2), 3)
diff --git a/tests/cpydiff/core_generator_noexit.py b/tests/cpydiff/core_generator_noexit.py
new file mode 100644
index 000000000..c25fbe75a
--- /dev/null
+++ b/tests/cpydiff/core_generator_noexit.py
@@ -0,0 +1,24 @@
+"""
+categories: Core,Generator
+description: Context manager __exit__() not called in a generator which does not run to completion
+cause: Unknown
+workaround: Unknown
+"""
+class foo(object):
+ def __enter__(self):
+ print('Enter')
+ def __exit__(self, *args):
+ print('Exit')
+
+def bar(x):
+ with foo():
+ while True:
+ x += 1
+ yield x
+
+def func():
+ g = bar(0)
+ for _ in range(3):
+ print(next(g))
+
+func()
diff --git a/tests/cpydiff/core_import_prereg.py b/tests/cpydiff/core_import_prereg.py
new file mode 100644
index 000000000..ab04cfc99
--- /dev/null
+++ b/tests/cpydiff/core_import_prereg.py
@@ -0,0 +1,17 @@
+"""
+categories: Core,import
+description: Failed to load modules are still registered as loaded
+cause: Unknown
+workaround: Unknown
+"""
+import sys
+
+try:
+ from modules import foo
+except NameError as e:
+ print(e)
+try:
+ from modules import foo
+ print('Should not get here')
+except NameError as e:
+ print(e)
diff --git a/tests/cpydiff/core_mro.py b/tests/cpydiff/core_mro.py
new file mode 100644
index 000000000..35b898b30
--- /dev/null
+++ b/tests/cpydiff/core_mro.py
@@ -0,0 +1,15 @@
+"""
+categories: Core
+description: Method Resolution Order (MRO) is not compliant with CPython
+cause: Unknown
+workaround: Unknown
+"""
+class Foo:
+ def __str__(self):
+ return "Foo"
+
+class C(tuple, Foo):
+ pass
+
+t = C((1, 2, 3))
+print(t)
diff --git a/tests/cpydiff/modules/__init__.py b/tests/cpydiff/modules/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/cpydiff/modules/__init__.py
diff --git a/tests/cpydiff/modules/foo.py b/tests/cpydiff/modules/foo.py
new file mode 100644
index 000000000..e6e33a7b4
--- /dev/null
+++ b/tests/cpydiff/modules/foo.py
@@ -0,0 +1,2 @@
+print('foo')
+xxx
diff --git a/tests/cpydiff/modules_array_containment.py b/tests/cpydiff/modules_array_containment.py
new file mode 100644
index 000000000..190a3c276
--- /dev/null
+++ b/tests/cpydiff/modules_array_containment.py
@@ -0,0 +1,8 @@
+"""
+categories: Modules,array
+description: Looking for integer not implemented
+cause: Unknown
+workaround: Unknown
+"""
+import array
+print(1 in array.array('B', b'12'))
diff --git a/tests/cpydiff/modules_array_deletion.py b/tests/cpydiff/modules_array_deletion.py
new file mode 100644
index 000000000..97f988da2
--- /dev/null
+++ b/tests/cpydiff/modules_array_deletion.py
@@ -0,0 +1,10 @@
+"""
+categories: Modules,array
+description: Array deletion not implemented
+cause: Unknown
+workaround: Unknown
+"""
+import array
+a = array.array('b', (1, 2, 3))
+del a[1]
+print(a)
diff --git a/tests/cpydiff/modules_array_subscrstep.py b/tests/cpydiff/modules_array_subscrstep.py
new file mode 100644
index 000000000..1103f1826
--- /dev/null
+++ b/tests/cpydiff/modules_array_subscrstep.py
@@ -0,0 +1,9 @@
+"""
+categories: Modules,array
+description: Subscript with step != 1 is not yet implemented
+cause: Unknown
+workaround: Unknown
+"""
+import array
+a = array.array('b', (1, 2, 3))
+print(a[3:2:2])
diff --git a/tests/cpydiff/modules_deque.py b/tests/cpydiff/modules_deque.py
new file mode 100644
index 000000000..dc9369d02
--- /dev/null
+++ b/tests/cpydiff/modules_deque.py
@@ -0,0 +1,9 @@
+"""
+categories: Modules,deque
+description: Deque not implemented
+cause: Unknown
+workaround: Use regular queues or lists creatively
+"""
+import collections
+D = collections.deque()
+print(D)
diff --git a/tests/cpydiff/modules_json_nonserializable.py b/tests/cpydiff/modules_json_nonserializable.py
new file mode 100644
index 000000000..913b734e8
--- /dev/null
+++ b/tests/cpydiff/modules_json_nonserializable.py
@@ -0,0 +1,14 @@
+"""
+categories: Modules,json
+description: JSON module does not throw exception when object is not serialisable
+cause: Unknown
+workaround: Unknown
+"""
+import json
+a = bytes(x for x in range(256))
+try:
+ z = json.dumps(a)
+ x = json.loads(z)
+ print('Should not get here')
+except TypeError:
+ print('TypeError')
diff --git a/tests/cpydiff/modules_struct_fewargs.py b/tests/cpydiff/modules_struct_fewargs.py
new file mode 100644
index 000000000..08d32ca67
--- /dev/null
+++ b/tests/cpydiff/modules_struct_fewargs.py
@@ -0,0 +1,12 @@
+"""
+categories: Modules,struct
+description: Struct pack with too few args, not checked by uPy
+cause: Unknown
+workaround: Unknown
+"""
+import struct
+try:
+ print(struct.pack('bb', 1))
+ print('Should not get here')
+except:
+ print('struct.error')
diff --git a/tests/cpydiff/modules_struct_manyargs.py b/tests/cpydiff/modules_struct_manyargs.py
new file mode 100644
index 000000000..cdbb5c672
--- /dev/null
+++ b/tests/cpydiff/modules_struct_manyargs.py
@@ -0,0 +1,12 @@
+"""
+categories: Modules,struct
+description: Struct pack with too many args, not checked by uPy
+cause: Unknown
+workaround: Unknown
+"""
+import struct
+try:
+ print(struct.pack('bb', 1, 2, 3))
+ print('Should not get here')
+except:
+ print('struct.error')
diff --git a/tests/cpydiff/modules_sys_stdassign.py b/tests/cpydiff/modules_sys_stdassign.py
new file mode 100644
index 000000000..096af430e
--- /dev/null
+++ b/tests/cpydiff/modules_sys_stdassign.py
@@ -0,0 +1,9 @@
+"""
+categories: Modules,sys
+description: Override sys.stdin, sys.stdout and sys.stderr. Impossible as they are stored in read-only memory.
+cause: Unknown
+workaround: Unknown
+"""
+import sys
+sys.stdin = None
+print(sys.stdin)
diff --git a/tests/cpydiff/syntax_spaces.py b/tests/cpydiff/syntax_spaces.py
new file mode 100644
index 000000000..8578a51e2
--- /dev/null
+++ b/tests/cpydiff/syntax_spaces.py
@@ -0,0 +1,18 @@
+"""
+categories: Syntax,Spaces
+description: uPy requires spaces between literal numbers and keywords, CPy doesn't
+cause: Unknown
+workaround: Unknown
+"""
+try:
+ print(eval('1and 0'))
+except SyntaxError:
+ print('Should have worked')
+try:
+ print(eval('1or 0'))
+except SyntaxError:
+ print('Should have worked')
+try:
+ print(eval('1if 1else 0'))
+except SyntaxError:
+ print('Should have worked')
diff --git a/tests/cpydiff/syntax_unicode_nameesc.py b/tests/cpydiff/syntax_unicode_nameesc.py
new file mode 100644
index 000000000..21628c974
--- /dev/null
+++ b/tests/cpydiff/syntax_unicode_nameesc.py
@@ -0,0 +1,7 @@
+"""
+categories: Syntax,Unicode
+description: Unicode name escapes are not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print("\N{LATIN SMALL LETTER A}")
diff --git a/tests/cpydiff/types_bytearray_sliceassign.py b/tests/cpydiff/types_bytearray_sliceassign.py
new file mode 100644
index 000000000..e4068b04b
--- /dev/null
+++ b/tests/cpydiff/types_bytearray_sliceassign.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,bytearray
+description: Array slice assignment with unsupported RHS
+cause: Unknown
+workaround: Unknown
+"""
+b = bytearray(4)
+b[0:1] = [1, 2]
+print(b)
diff --git a/tests/cpydiff/types_bytes_keywords.py b/tests/cpydiff/types_bytes_keywords.py
new file mode 100644
index 000000000..35119e28f
--- /dev/null
+++ b/tests/cpydiff/types_bytes_keywords.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,bytes
+description: bytes(...) with keywords not implemented
+cause: Unknown
+workaround: Input the encoding format directly. eg. ``print(bytes('abc', 'utf-8'))``
+"""
+print(bytes('abc', encoding='utf8'))
diff --git a/tests/cpydiff/types_bytes_subscrstep.py b/tests/cpydiff/types_bytes_subscrstep.py
new file mode 100644
index 000000000..fd1602d65
--- /dev/null
+++ b/tests/cpydiff/types_bytes_subscrstep.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,bytes
+description: Bytes subscr with step != 1 not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print(b'123'[0:3:2])
diff --git a/tests/cpydiff/types_exception_chaining.py b/tests/cpydiff/types_exception_chaining.py
new file mode 100644
index 000000000..836c4eb3e
--- /dev/null
+++ b/tests/cpydiff/types_exception_chaining.py
@@ -0,0 +1,10 @@
+"""
+categories: Types,Exception
+description: Exception chaining not implemented
+cause: Unknown
+workaround: Unknown
+"""
+try:
+ raise TypeError
+except TypeError:
+ raise ValueError
diff --git a/tests/cpydiff/types_exception_instancevar.py b/tests/cpydiff/types_exception_instancevar.py
new file mode 100644
index 000000000..d1015e96c
--- /dev/null
+++ b/tests/cpydiff/types_exception_instancevar.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,Exception
+description: Assign instance variable to exception
+cause: Unknown
+workaround: Unknown
+"""
+e = Exception()
+e.x = 0
+print(e.x)
diff --git a/tests/cpydiff/types_exception_loops.py b/tests/cpydiff/types_exception_loops.py
new file mode 100644
index 000000000..a142e4757
--- /dev/null
+++ b/tests/cpydiff/types_exception_loops.py
@@ -0,0 +1,12 @@
+"""
+categories: Types,Exception
+description: While loop guards will obscure exception line number reporting due to being optimised onto the end of the code block
+cause: Unknown
+workaround: Unknown
+"""
+l = ["-foo", "-bar"]
+
+i = 0
+while l[i][0] == "-":
+ print("iter")
+ i += 1
diff --git a/tests/cpydiff/types_exception_subclassinit.py b/tests/cpydiff/types_exception_subclassinit.py
new file mode 100644
index 000000000..177094646
--- /dev/null
+++ b/tests/cpydiff/types_exception_subclassinit.py
@@ -0,0 +1,11 @@
+"""
+categories: Types,Exception
+description: Exception.__init__ raises TypeError if overridden and called by subclass
+cause: Unknown
+workaround: Unknown
+"""
+class A(Exception):
+ def __init__(self):
+ Exception.__init__(self)
+
+a = A()
diff --git a/tests/cpydiff/types_float_rounding.py b/tests/cpydiff/types_float_rounding.py
new file mode 100644
index 000000000..647f61ba2
--- /dev/null
+++ b/tests/cpydiff/types_float_rounding.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,float
+description: uPy and CPython outputs formats differ
+cause: Unknown
+workaround: Unknown
+"""
+print('%.1g' % -9.9)
+print('%.1e' % 9.99)
+print('%.1e' % 0.999)
diff --git a/tests/cpydiff/types_int_subclassconv.py b/tests/cpydiff/types_int_subclassconv.py
new file mode 100644
index 000000000..565fbad4b
--- /dev/null
+++ b/tests/cpydiff/types_int_subclassconv.py
@@ -0,0 +1,11 @@
+"""
+categories: Types,int
+description: No int conversion for int-derived types available
+cause: Unknown
+workaround: Unknown
+"""
+class A(int):
+ __add__ = lambda self, other: A(int(self) + other)
+
+a = A(42)
+print(a+a)
diff --git a/tests/cpydiff/types_int_tobytesfloat.py b/tests/cpydiff/types_int_tobytesfloat.py
new file mode 100644
index 000000000..5d5b980fa
--- /dev/null
+++ b/tests/cpydiff/types_int_tobytesfloat.py
@@ -0,0 +1,10 @@
+"""
+categories: Types,int
+description: Incorrect error message when passing float into to_bytes
+cause: Unknown
+workaround: Unknown
+"""
+try:
+ int('1').to_bytes(1.0)
+except TypeError as e:
+ print(e)
diff --git a/tests/cpydiff/types_list_delete_subscrstep.py b/tests/cpydiff/types_list_delete_subscrstep.py
new file mode 100644
index 000000000..f524fa8dc
--- /dev/null
+++ b/tests/cpydiff/types_list_delete_subscrstep.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,list
+description: List delete with step != 1 not implemented
+cause: Unknown
+workaround: Unknown
+"""
+l = [1, 2, 3, 4]
+del l[0:4:2]
+print(l)
diff --git a/tests/cpydiff/types_list_store_noniter.py b/tests/cpydiff/types_list_store_noniter.py
new file mode 100644
index 000000000..1d69b4a82
--- /dev/null
+++ b/tests/cpydiff/types_list_store_noniter.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,list
+description: List slice-store with non-iterable on RHS is not implemented
+cause: RHS is restricted to be a tuple or list
+workaround: Use ``list(<iter>)`` on RHS to convert the iterable to a list
+"""
+l = [10, 20]
+l[0:1] = range(4)
+print(l)
diff --git a/tests/cpydiff/types_list_store_subscrstep.py b/tests/cpydiff/types_list_store_subscrstep.py
new file mode 100644
index 000000000..2de2e1a3c
--- /dev/null
+++ b/tests/cpydiff/types_list_store_subscrstep.py
@@ -0,0 +1,9 @@
+"""
+categories: Types,list
+description: List store with step != 1 not implemented
+cause: Unknown
+workaround: Unknown
+"""
+l = [1, 2, 3, 4]
+l[0:4:2] = [5, 6]
+print(l)
diff --git a/tests/cpydiff/types_str_decodeerror.py b/tests/cpydiff/types_str_decodeerror.py
new file mode 100644
index 000000000..944db98fe
--- /dev/null
+++ b/tests/cpydiff/types_str_decodeerror.py
@@ -0,0 +1,11 @@
+"""
+categories: Types,str
+description: UnicodeDecodeError not raised when expected
+cause: Unknown
+workaround: Unknown
+"""
+try:
+ print(repr(str(b"\xa1\x80", 'utf8')))
+ print('Should not get here')
+except UnicodeDecodeError:
+ print('UnicodeDecodeError')
diff --git a/tests/cpydiff/types_str_endswith.py b/tests/cpydiff/types_str_endswith.py
new file mode 100644
index 000000000..ac2600bd2
--- /dev/null
+++ b/tests/cpydiff/types_str_endswith.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,str
+description: Start/end indices such as str.endswith(s, start) not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print('abc'.endswith('c', 1))
diff --git a/tests/cpydiff/types_str_formatsubscr.py b/tests/cpydiff/types_str_formatsubscr.py
new file mode 100644
index 000000000..dd1d8d33d
--- /dev/null
+++ b/tests/cpydiff/types_str_formatsubscr.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,str
+description: Attributes/subscr not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print('{a[0]}'.format(a=[1, 2]))
diff --git a/tests/cpydiff/types_str_keywords.py b/tests/cpydiff/types_str_keywords.py
new file mode 100644
index 000000000..b336b1a73
--- /dev/null
+++ b/tests/cpydiff/types_str_keywords.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,str
+description: str(...) with keywords not implemented
+cause: Unknown
+workaround: Input the encoding format directly. eg ``print(bytes('abc', 'utf-8'))``
+"""
+print(str(b'abc', encoding='utf8'))
diff --git a/tests/cpydiff/types_str_rsplitnone.py b/tests/cpydiff/types_str_rsplitnone.py
new file mode 100644
index 000000000..cadf86987
--- /dev/null
+++ b/tests/cpydiff/types_str_rsplitnone.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,str
+description: None as first argument for rsplit such as str.rsplit(None, n) not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print('a a a'.rsplit(None, 1))
diff --git a/tests/cpydiff/types_str_subclassequality.py b/tests/cpydiff/types_str_subclassequality.py
new file mode 100644
index 000000000..8aec1ea78
--- /dev/null
+++ b/tests/cpydiff/types_str_subclassequality.py
@@ -0,0 +1,11 @@
+"""
+categories: Types,str
+description: Instance of a subclass of str cannot be compared for equality with an instance of a str
+cause: Unknown
+workaround: Unknown
+"""
+class S(str):
+ pass
+
+s = S('hello')
+print(s == 'hello')
diff --git a/tests/cpydiff/types_str_subscrstep.py b/tests/cpydiff/types_str_subscrstep.py
new file mode 100644
index 000000000..0c2fce1b1
--- /dev/null
+++ b/tests/cpydiff/types_str_subscrstep.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,str
+description: Subscript with step != 1 is not yet implemented
+cause: Unknown
+workaround: Unknown
+"""
+print('abcdefghi'[0:9:2])
diff --git a/tests/cpydiff/types_tuple_subscrstep.py b/tests/cpydiff/types_tuple_subscrstep.py
new file mode 100644
index 000000000..f90f3c5bf
--- /dev/null
+++ b/tests/cpydiff/types_tuple_subscrstep.py
@@ -0,0 +1,7 @@
+"""
+categories: Types,tuple
+description: Tuple load with step != 1 not implemented
+cause: Unknown
+workaround: Unknown
+"""
+print((1, 2, 3, 4)[0:4:2])
diff --git a/tests/extmod/machine_signal.py b/tests/extmod/machine_signal.py
new file mode 100644
index 000000000..401533f23
--- /dev/null
+++ b/tests/extmod/machine_signal.py
@@ -0,0 +1,40 @@
+# test machine.Signal class
+
+try:
+ import umachine as machine
+except ImportError:
+ import machine
+try:
+ machine.PinBase
+ machine.Signal
+except AttributeError:
+ print("SKIP")
+ import sys
+ sys.exit()
+
+class Pin(machine.PinBase):
+ def __init__(self):
+ self.v = 0
+
+ def value(self, v=None):
+ if v is None:
+ return self.v
+ else:
+ self.v = int(v)
+
+
+# test non-inverted
+p = Pin()
+s = machine.Signal(p)
+s.value(0)
+print(p.value(), s.value())
+s.value(1)
+print(p.value(), s.value())
+
+# test inverted, and using on/off methods
+p = Pin()
+s = machine.Signal(p, inverted=True)
+s.off()
+print(p.value(), s.value())
+s.on()
+print(p.value(), s.value())
diff --git a/tests/extmod/machine_signal.py.exp b/tests/extmod/machine_signal.py.exp
new file mode 100644
index 000000000..7e9dd6796
--- /dev/null
+++ b/tests/extmod/machine_signal.py.exp
@@ -0,0 +1,4 @@
+0 0
+1 1
+1 0
+0 1
diff --git a/tests/extmod/uctypes_array_assign_native_le.py b/tests/extmod/uctypes_array_assign_native_le.py
index 474b7e0f2..f0ecc0dad 100644
--- a/tests/extmod/uctypes_array_assign_native_le.py
+++ b/tests/extmod/uctypes_array_assign_native_le.py
@@ -70,16 +70,6 @@ S.arr10[0] = 0x11223344
print(hex(S.arr10[0]))
assert hex(S.arr10[0]) == "0x11223344"
-# assign int64
-S.arr11[0] = 0x11223344
-print(hex(S.arr11[0]))
-assert hex(S.arr11[0]) == "0x11223344"
-
-# assign uint64
-S.arr12[0] = 0x11223344
-print(hex(S.arr12[0]))
-assert hex(S.arr12[0]) == "0x11223344"
-
# index out of range
try:
print(S.arr8[2])
diff --git a/tests/extmod/uctypes_array_assign_native_le.py.exp b/tests/extmod/uctypes_array_assign_native_le.py.exp
index 4efcdec66..9d67b1c77 100644
--- a/tests/extmod/uctypes_array_assign_native_le.py.exp
+++ b/tests/extmod/uctypes_array_assign_native_le.py.exp
@@ -6,8 +6,6 @@ True
0x11
0x1122
0x11223344
-0x11223344
-0x11223344
IndexError
TypeError
TypeError
diff --git a/tests/extmod/uctypes_array_assign_native_le_intbig.py b/tests/extmod/uctypes_array_assign_native_le_intbig.py
new file mode 100644
index 000000000..f29a3b66e
--- /dev/null
+++ b/tests/extmod/uctypes_array_assign_native_le_intbig.py
@@ -0,0 +1,43 @@
+import sys
+try:
+ import uctypes
+except ImportError:
+ print("SKIP")
+ sys.exit()
+
+if sys.byteorder != "little":
+ print("SKIP")
+ sys.exit()
+
+desc = {
+ # arr is array at offset 0, of UINT8 elements, array size is 2
+ "arr": (uctypes.ARRAY | 0, uctypes.UINT8 | 2),
+ # arr2 is array at offset 0, size 2, of structures defined recursively
+ "arr2": (uctypes.ARRAY | 0, 2, {"b": uctypes.UINT8 | 0}),
+ "arr3": (uctypes.ARRAY | 2, uctypes.UINT16 | 2),
+
+ # aligned
+ "arr5": (uctypes.ARRAY | 0, uctypes.UINT32 | 1),
+ "arr7": (uctypes.ARRAY | 0, 1, {"l": uctypes.UINT32 | 0}),
+
+ "arr8": (uctypes.ARRAY | 0, uctypes.INT8 | 1),
+ "arr9": (uctypes.ARRAY | 0, uctypes.INT16 | 1),
+ "arr10": (uctypes.ARRAY | 0, uctypes.INT32 | 1),
+ "arr11": (uctypes.ARRAY | 0, uctypes.INT64 | 1),
+ "arr12": (uctypes.ARRAY | 0, uctypes.UINT64| 1),
+ "arr13": (uctypes.ARRAY | 1, 1, {"l": {}}),
+}
+
+data = bytearray(8)
+
+S = uctypes.struct(uctypes.addressof(data), desc)
+
+# assign int64
+S.arr11[0] = 0x11223344
+print(hex(S.arr11[0]))
+assert hex(S.arr11[0]) == "0x11223344"
+
+# assign uint64
+S.arr12[0] = 0x11223344
+print(hex(S.arr12[0]))
+assert hex(S.arr12[0]) == "0x11223344"
diff --git a/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp b/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp
new file mode 100644
index 000000000..0394e9ae1
--- /dev/null
+++ b/tests/extmod/uctypes_array_assign_native_le_intbig.py.exp
@@ -0,0 +1,2 @@
+0x11223344
+0x11223344
diff --git a/tests/feature_check/int_big.py b/tests/feature_check/int_big.py
new file mode 100644
index 000000000..8b82814ae
--- /dev/null
+++ b/tests/feature_check/int_big.py
@@ -0,0 +1,2 @@
+# Check whether arbitrary-precision integers (MPZ) are supported
+1000000000000000000000000000000000000000000000
diff --git a/tests/feature_check/int_big.py.exp b/tests/feature_check/int_big.py.exp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/tests/feature_check/int_big.py.exp
diff --git a/tests/float/complex1.py b/tests/float/complex1.py
index 1031111f3..8c8d285e1 100644
--- a/tests/float/complex1.py
+++ b/tests/float/complex1.py
@@ -49,9 +49,6 @@ print(float('nan') * 1j)
print(float('inf') * (1 + 1j))
print(float('-inf') * (1 + 1j))
-# convert bignum to complex on rhs
-ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag))
-
# can't assign to attributes
try:
(1j).imag = 0
diff --git a/tests/float/complex1_intbig.py b/tests/float/complex1_intbig.py
new file mode 100644
index 000000000..ed2390bba
--- /dev/null
+++ b/tests/float/complex1_intbig.py
@@ -0,0 +1,4 @@
+# test basic complex number functionality
+
+# convert bignum to complex on rhs
+ans = 1j + (1 << 70); print("%.5g %.5g" % (ans.real, ans.imag))
diff --git a/tests/float/float2int_doubleprec.py b/tests/float/float2int_doubleprec_intbig.py
index acdc8c69c..de2137d66 100644
--- a/tests/float/float2int_doubleprec.py
+++ b/tests/float/float2int_doubleprec_intbig.py
@@ -5,21 +5,29 @@ try:
except:
import struct
+import sys
+maxsize_bits = 0
+maxsize = sys.maxsize
+while maxsize:
+ maxsize >>= 1
+ maxsize_bits += 1
+
# work out configuration values
-is_64bit = struct.calcsize("P") == 8
+is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
-try:
- dummy = 0x7fffffffffffffff
- try:
- if (0xffffffffffffffff + 1) > 0:
- ll_type = 2
- else:
- ll_type = 1
- except:
- # in case the sum in the if statement above changes to raising an exception on overflow
+ll_type = None
+if is_64bit:
+ if maxsize_bits < 63:
+ ll_type = 0
+else:
+ if maxsize_bits < 31:
+ ll_type = 0
+if ll_type is None:
+ one = 1
+ if one << 65 < one << 62:
ll_type = 1
-except:
- ll_type = 0
+ else:
+ ll_type = 2
# This case occurs with time.time() values
if ll_type != 0:
diff --git a/tests/float/float2int_fp30.py b/tests/float/float2int_fp30_intbig.py
index bad9c31e9..fbb94a4cc 100644
--- a/tests/float/float2int_fp30.py
+++ b/tests/float/float2int_fp30_intbig.py
@@ -5,21 +5,29 @@ try:
except:
import struct
+import sys
+maxsize_bits = 0
+maxsize = sys.maxsize
+while maxsize:
+ maxsize >>= 1
+ maxsize_bits += 1
+
# work out configuration values
-is_64bit = struct.calcsize("P") == 8
+is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
-try:
- dummy = 0x7fffffffffffffff
- try:
- if (0xffffffffffffffff + 1) > 0:
- ll_type = 2
- else:
- ll_type = 1
- except:
- # in case the sum in the if statement above changes to raising an exception on overflow
+ll_type = None
+if is_64bit:
+ if maxsize_bits < 63:
+ ll_type = 0
+else:
+ if maxsize_bits < 31:
+ ll_type = 0
+if ll_type is None:
+ one = 1
+ if one << 65 < one << 62:
ll_type = 1
-except:
- ll_type = 0
+ else:
+ ll_type = 2
# basic conversion
print(int(14187744.))
diff --git a/tests/float/float2int.py b/tests/float/float2int_intbig.py
index da530cee6..3596d2f73 100644
--- a/tests/float/float2int.py
+++ b/tests/float/float2int_intbig.py
@@ -5,21 +5,31 @@ try:
except:
import struct
+import sys
+
+maxsize_bits = 0
+maxsize = sys.maxsize
+while maxsize:
+ maxsize >>= 1
+ maxsize_bits += 1
+
# work out configuration values
-is_64bit = struct.calcsize("P") == 8
+is_64bit = maxsize_bits > 32
# 0 = none, 1 = long long, 2 = mpz
-try:
- dummy = 0x7fffffffffffffff
- try:
- if (0xffffffffffffffff + 1) > 0:
- ll_type = 2
- else:
- ll_type = 1
- except:
- # in case the sum in the if statement above changes to raising an exception on overflow
+ll_type = None
+if is_64bit:
+ if maxsize_bits < 63:
+ ll_type = 0
+else:
+ if maxsize_bits < 31:
+ ll_type = 0
+if ll_type is None:
+ one = 1
+ if one << 65 < one << 62:
ll_type = 1
-except:
- ll_type = 0
+ else:
+ ll_type = 2
+
# basic conversion
print(int(14187745.))
diff --git a/tests/float/string_format_modulo2.py b/tests/float/string_format_modulo2.py
index d35f2a2c0..f6b1ae537 100644
--- a/tests/float/string_format_modulo2.py
+++ b/tests/float/string_format_modulo2.py
@@ -18,7 +18,7 @@ def test(num, num_str):
# check pure zero
test(0.0, '0.0')
-# check most powers of 10, making sure to include exponents with 3 digits
-for e in range(-101, 102):
+# check some powers of 10, making sure to include exponents with 3 digits
+for e in range(-8, 8):
num = pow(10, e)
test(num, '1e%d' % e)
diff --git a/tests/float/string_format_modulo2_intbig.py b/tests/float/string_format_modulo2_intbig.py
new file mode 100644
index 000000000..9992ba65d
--- /dev/null
+++ b/tests/float/string_format_modulo2_intbig.py
@@ -0,0 +1,21 @@
+# test formatting floats with large precision, that it doesn't overflow the buffer
+
+def test(num, num_str):
+ if num == float('inf') or num == 0.0 and num_str != '0.0':
+ # skip numbers that overflow or underflow the FP precision
+ return
+ for kind in ('e', 'f', 'g'):
+ # check precision either side of the size of the buffer (32 bytes)
+ for prec in range(23, 36, 2):
+ fmt = '%.' + '%d' % prec + kind
+ s = fmt % num
+ check = abs(float(s) - num)
+ if num > 1:
+ check /= num
+ if check > 1e-6:
+ print('FAIL', num_str, fmt, s, len(s), check)
+
+# check most powers of 10, making sure to include exponents with 3 digits
+for e in range(-101, 102):
+ num = pow(10, e)
+ test(num, '1e%d' % e)
diff --git a/tests/micropython/const_intbig.py b/tests/micropython/const_intbig.py
new file mode 100644
index 000000000..e74902652
--- /dev/null
+++ b/tests/micropython/const_intbig.py
@@ -0,0 +1,13 @@
+# test constant optimisation, with consts that are bignums
+
+from micropython import const
+
+# check we can make consts from bignums
+Z1 = const(0xffffffff)
+Z2 = const(0xffffffffffffffff)
+print(hex(Z1), hex(Z2))
+
+# check arithmetic with bignum
+Z3 = const(Z1 + Z2)
+Z4 = const((1 << 100) + Z1)
+print(hex(Z3), hex(Z4))
diff --git a/tests/micropython/const_intbig.py.exp b/tests/micropython/const_intbig.py.exp
new file mode 100644
index 000000000..137f86cf8
--- /dev/null
+++ b/tests/micropython/const_intbig.py.exp
@@ -0,0 +1,2 @@
+0xffffffff 0xffffffffffffffff
+0x100000000fffffffe 0x100000000000000000ffffffff
diff --git a/tests/micropython/heapalloc_exc_raise.py b/tests/micropython/heapalloc_exc_raise.py
new file mode 100644
index 000000000..d60e14ce5
--- /dev/null
+++ b/tests/micropython/heapalloc_exc_raise.py
@@ -0,0 +1,23 @@
+# Test that we can raise and catch (preallocated) exception
+# without memory allocation.
+import micropython
+
+e = ValueError("error")
+
+def func():
+ try:
+ # This works as is because traceback is not allocated
+ # if not possible (heap is locked, no memory). If heap
+ # is not locked, this would allocate a traceback entry.
+ # To avoid that, traceback should be warmed up (by raising
+ # it once after creation) and then cleared before each
+ # raise with:
+ # e.__traceback__ = None
+ raise e
+ except Exception as e2:
+ print(e2)
+
+micropython.heap_lock()
+func()
+print("ok")
+micropython.heap_unlock()
diff --git a/tests/micropython/heapalloc_exc_raise.py.exp b/tests/micropython/heapalloc_exc_raise.py.exp
new file mode 100644
index 000000000..1e9edc75d
--- /dev/null
+++ b/tests/micropython/heapalloc_exc_raise.py.exp
@@ -0,0 +1,2 @@
+error
+ok
diff --git a/tests/micropython/native_const.py b/tests/micropython/native_const_intbig.py
index 611b39d8f..611b39d8f 100644
--- a/tests/micropython/native_const.py
+++ b/tests/micropython/native_const_intbig.py
diff --git a/tests/micropython/native_const.py.exp b/tests/micropython/native_const_intbig.py.exp
index 1d52d220f..1d52d220f 100644
--- a/tests/micropython/native_const.py.exp
+++ b/tests/micropython/native_const_intbig.py.exp
diff --git a/tests/micropython/viper_misc.py b/tests/micropython/viper_misc.py
index 8bf6cc638..021e03f2c 100644
--- a/tests/micropython/viper_misc.py
+++ b/tests/micropython/viper_misc.py
@@ -50,13 +50,6 @@ def viper_no_annotation(x, y):
return x * y
print(viper_no_annotation(4, 5))
-# unsigned ints
-@micropython.viper
-def viper_uint() -> uint:
- return uint(-1)
-import sys
-print(viper_uint() == (sys.maxsize << 1 | 1))
-
# a for loop
@micropython.viper
def viper_for(a:int, b:int) -> int:
diff --git a/tests/micropython/viper_misc.py.exp b/tests/micropython/viper_misc.py.exp
index 4800050d1..e4462771b 100644
--- a/tests/micropython/viper_misc.py.exp
+++ b/tests/micropython/viper_misc.py.exp
@@ -5,7 +5,6 @@ Ellipsis
6
7
20
-True
49994955
1 1
1 3
diff --git a/tests/micropython/viper_misc_intbig.py b/tests/micropython/viper_misc_intbig.py
new file mode 100644
index 000000000..e036435c7
--- /dev/null
+++ b/tests/micropython/viper_misc_intbig.py
@@ -0,0 +1,8 @@
+import micropython
+
+# unsigned ints
+@micropython.viper
+def viper_uint() -> uint:
+ return uint(-1)
+import sys
+print(viper_uint() == (sys.maxsize << 1 | 1))
diff --git a/tests/micropython/viper_misc_intbig.py.exp b/tests/micropython/viper_misc_intbig.py.exp
new file mode 100644
index 000000000..0ca95142b
--- /dev/null
+++ b/tests/micropython/viper_misc_intbig.py.exp
@@ -0,0 +1 @@
+True
diff --git a/tests/run-tests b/tests/run-tests
index 6cca829b6..bacaebea8 100755
--- a/tests/run-tests
+++ b/tests/run-tests
@@ -198,6 +198,7 @@ def run_tests(pyb, tests, args):
skip_tests = set()
skip_native = False
+ skip_int_big = False
skip_set_type = False
skip_async = False
@@ -206,6 +207,11 @@ def run_tests(pyb, tests, args):
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')
+ if native == b'CRASH':
+ 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')
if native == b'CRASH':
@@ -320,12 +326,14 @@ def run_tests(pyb, tests, args):
test_name = os.path.splitext(test_basename)[0]
is_native = test_name.startswith("native_") or test_name.startswith("viper_")
is_endian = test_name.endswith("_endian")
+ is_int_big = test_name.startswith("int_big") or test_name.endswith("_intbig")
is_set_type = test_name.startswith("set_") or test_name.startswith("frozenset")
is_async = test_name.startswith("async_")
skip_it = test_file in skip_tests
skip_it |= skip_native and is_native
skip_it |= skip_endian and is_endian
+ skip_it |= skip_int_big and is_int_big
skip_it |= skip_set_type and is_set_type
skip_it |= skip_async and is_async
diff --git a/tools/gen-cpydiff.py b/tools/gen-cpydiff.py
new file mode 100644
index 000000000..4b273d97f
--- /dev/null
+++ b/tools/gen-cpydiff.py
@@ -0,0 +1,224 @@
+# This file is part of the MicroPython project, http://micropython.org/
+#
+# The MIT License (MIT)
+#
+# Copyright (c) 2016 Rami Ali
+#
+# 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.
+
+""" gen-cpydiff generates documentation which outlines operations that differ between MicroPython
+ and CPython. This script is called by the docs Makefile for html and Latex and may be run
+ manually using the command make gen-cpydiff. """
+
+import os
+import errno
+import subprocess
+import time
+import re
+from collections import namedtuple
+
+# Micropython supports syntax of CPython 3.4 with some features from 3.5, and
+# such version should be used to test for differences. If your default python3
+# executable is of lower version, you can point MICROPY_CPYTHON3 environment var
+# to the correct executable.
+if os.name == 'nt':
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3.exe')
+ MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../windows/micropython.exe')
+else:
+ CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3')
+ MICROPYTHON = os.getenv('MICROPY_MICROPYTHON', '../unix/micropython')
+
+TESTPATH = '../tests/cpydiff/'
+DOCPATH = '../docs/genrst/'
+INDEXTEMPLATE = '../docs/differences/index_template.txt'
+INDEX = 'index.rst'
+
+HEADER = '.. This document was generated by tools/gen-cpydiff.py\n\n'
+UIMPORTLIST = {'struct', 'collections', 'json'}
+CLASSMAP = {'Core': 'Core Language', 'Types': 'Builtin Types'}
+INDEXPRIORITY = ['syntax', 'core_language', 'builtin_types', 'modules']
+RSTCHARS = ['=', '-', '~', '`', ':']
+SPLIT = '"""\n|categories: |description: |cause: |workaround: '
+TAB = ' '
+
+Output = namedtuple('output', ['name', 'class_', 'desc', 'cause', 'workaround', 'code',
+ 'output_cpy', 'output_upy', 'status'])
+
+def readfiles():
+ """ Reads test files """
+ tests = list(filter(lambda x: x.endswith('.py'), os.listdir(TESTPATH)))
+ tests.sort()
+ files = []
+
+ for test in tests:
+ text = open(TESTPATH + test, 'r').read()
+
+ try:
+ class_, desc, cause, workaround, code = [x.rstrip() for x in \
+ list(filter(None, re.split(SPLIT, text)))]
+ output = Output(test, class_, desc, cause, workaround, code, '', '', '')
+ files.append(output)
+ except IndexError:
+ print('Incorrect format in file ' + TESTPATH + test)
+
+ return files
+
+def uimports(code):
+ """ converts CPython module names into MicroPython equivalents """
+ for uimport in UIMPORTLIST:
+ uimport = bytes(uimport, 'utf8')
+ code = code.replace(uimport, b'u' + uimport)
+ return code
+
+def run_tests(tests):
+ """ executes all tests """
+ results = []
+ for test in tests:
+ with open(TESTPATH + test.name, 'rb') as f:
+ input_cpy = f.read()
+ input_upy = uimports(input_cpy)
+
+ process = subprocess.Popen(CPYTHON3, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
+ output_cpy = [com.decode('utf8') for com in process.communicate(input_cpy)]
+
+ process = subprocess.Popen(MICROPYTHON, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
+ output_upy = [com.decode('utf8') for com in process.communicate(input_upy)]
+
+ if output_cpy[0] == output_upy[0] and output_cpy[1] == output_upy[1]:
+ status = 'Supported'
+ print('Supported operation!\nFile: ' + TESTPATH + test.name)
+ else:
+ status = 'Unsupported'
+
+ output = Output(test.name, test.class_, test.desc, test.cause,
+ test.workaround, test.code, output_cpy, output_upy, status)
+ results.append(output)
+
+ results.sort(key=lambda x: x.class_)
+ return results
+
+def indent(block, spaces):
+ """ indents paragraphs of text for rst formatting """
+ new_block = ''
+ for line in block.split('\n'):
+ new_block += spaces + line + '\n'
+ return new_block
+
+def gen_table(contents):
+ """ creates a table given any set of columns """
+ xlengths = []
+ ylengths = []
+ for column in contents:
+ col_len = 0
+ for entry in column:
+ lines = entry.split('\n')
+ for line in lines:
+ col_len = max(len(line) + 2, col_len)
+ xlengths.append(col_len)
+ for i in range(len(contents[0])):
+ ymax = 0
+ for j in range(len(contents)):
+ ymax = max(ymax, len(contents[j][i].split('\n')))
+ ylengths.append(ymax)
+
+ table_divider = '+' + ''.join(['-' * i + '+' for i in xlengths]) + '\n'
+ table = table_divider
+ for i in range(len(ylengths)):
+ row = [column[i] for column in contents]
+ row = [entry + '\n' * (ylengths[i]-len(entry.split('\n'))) for entry in row]
+ row = [entry.split('\n') for entry in row]
+ for j in range(ylengths[i]):
+ k = 0
+ for entry in row:
+ width = xlengths[k]
+ table += ''.join(['| {:{}}'.format(entry[j], width - 1)])
+ k += 1
+ table += '|\n'
+ table += table_divider
+ return table + '\n'
+
+def gen_rst(results):
+ """ creates restructured text documents to display tests """
+
+ # make sure the destination directory exists
+ try:
+ os.mkdir(DOCPATH)
+ except OSError as e:
+ if e.args[0] != errno.EEXIST and e.args[0] != errno.EISDIR:
+ raise
+
+ toctree = []
+ class_ = []
+ for output in results:
+ section = output.class_.split(',')
+ for i in range(len(section)):
+ section[i] = section[i].rstrip()
+ if section[i] in CLASSMAP:
+ section[i] = CLASSMAP[section[i]]
+ if i >= len(class_) or section[i] != class_[i]:
+ if i == 0:
+ filename = section[i].replace(' ', '_').lower()
+ rst = open(DOCPATH + filename + '.rst', 'w')
+ rst.write(HEADER)
+ rst.write(section[i] + '\n')
+ rst.write(RSTCHARS[0] * len(section[i]))
+ rst.write(time.strftime("\nGenerated %a %d %b %Y %X UTC\n\n", time.gmtime()))
+ toctree.append(filename)
+ else:
+ rst.write(section[i] + '\n')
+ rst.write(RSTCHARS[min(i, len(RSTCHARS)-1)] * len(section[i]))
+ rst.write('\n\n')
+ class_ = section
+ rst.write('**' + output.desc + '**\n\n')
+ if output.cause != 'Unknown':
+ rst.write('**Cause:** ' + output.cause + '\n\n')
+ if output.workaround != 'Unknown':
+ rst.write('**Workaround:** ' + output.workaround + '\n\n')
+
+ rst.write('Sample code::\n\n' + indent(output.code, TAB) + '\n')
+ output_cpy = indent(''.join(output.output_cpy[0:2]), TAB).rstrip()
+ output_cpy = ('::\n\n' if output_cpy != '' else '') + output_cpy
+ output_upy = indent(''.join(output.output_upy[0:2]), TAB).rstrip()
+ output_upy = ('::\n\n' if output_upy != '' else '') + output_upy
+ table = gen_table([['CPy output:', output_cpy], ['uPy output:', output_upy]])
+ rst.write(table)
+
+ template = open(INDEXTEMPLATE, 'r')
+ index = open(DOCPATH + INDEX, 'w')
+ index.write(HEADER)
+ index.write(template.read())
+ for section in INDEXPRIORITY:
+ if section in toctree:
+ index.write(indent(section + '.rst', TAB))
+ toctree.remove(section)
+ for section in toctree:
+ index.write(indent(section + '.rst', TAB))
+
+def main():
+ """ Main function """
+
+ # set search path so that test scripts find the test modules (and no other ones)
+ os.environ['PYTHONPATH'] = TESTPATH
+ os.environ['MICROPYPATH'] = TESTPATH
+
+ files = readfiles()
+ results = run_tests(files)
+ gen_rst(results)
+
+main()
diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py
index 3436d0f45..dadfea1cc 100755
--- a/tools/tinytest-codegen.py
+++ b/tools/tinytest-codegen.py
@@ -48,10 +48,9 @@ testgroup_member = (
# currently these tests are selected because they pass on qemu-arm
test_dirs = ('basics', 'micropython', 'float', 'extmod', 'inlineasm') # 'import', 'io', 'misc')
exclude_tests = (
- 'float/float2int_doubleprec.py', # requires double precision floating point to work
+ 'float/float2int_doubleprec_intbig.py', # requires double precision floating point to work
'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py', 'inlineasm/asmfpsqrt.py',
'extmod/ticks_diff.py', 'extmod/time_ms_us.py', 'extmod/uheapq_timeq.py',
- 'extmod/machine_pinbase.py', 'extmod/machine_pulse.py',
'extmod/vfs_fat_ramdisk.py', 'extmod/vfs_fat_fileio.py', 'extmod/vfs_fat_fsusermount.py', 'extmod/vfs_fat_oldproto.py',
)
diff --git a/unix/input.c b/unix/input.c
index 15ee60e75..7cd527fed 100644
--- a/unix/input.c
+++ b/unix/input.c
@@ -35,10 +35,6 @@
#if MICROPY_USE_READLINE == 1
#include "lib/mp-readline/readline.h"
-#elif MICROPY_USE_READLINE == 2
-#include <readline/readline.h>
-#include <readline/history.h>
-#include <readline/tilde.h>
#endif
char *prompt(char *p) {
@@ -66,12 +62,6 @@ char *prompt(char *p) {
char *line = malloc(vstr.len + 1);
memcpy(line, vstr.buf, vstr.len + 1);
vstr_clear(&vstr);
-#elif MICROPY_USE_READLINE == 2
- // GNU readline
- char *line = readline(p);
- if (line) {
- add_history(line);
- }
#else
// simple read string
static char buf[256];
@@ -124,8 +114,6 @@ void prompt_read_history(void) {
}
vstr_clear(&vstr);
}
- #elif MICROPY_USE_READLINE == 2
- read_history(tilde_expand("~/.micropython.history"));
#endif
#endif
}
@@ -152,8 +140,6 @@ void prompt_write_history(void) {
close(fd);
}
}
- #elif MICROPY_USE_READLINE == 2
- write_history(tilde_expand("~/.micropython.history"));
#endif
#endif
}
diff --git a/unix/main.c b/unix/main.c
index ad654780d..d916cdeb8 100644
--- a/unix/main.c
+++ b/unix/main.c
@@ -249,7 +249,7 @@ STATIC int do_repl(void) {
#else
- // use GNU or simple readline
+ // use simple readline
for (;;) {
char *line = prompt(">>> ");
diff --git a/unix/modmachine.c b/unix/modmachine.c
index e5f9ec8d7..33a3b098e 100644
--- a/unix/modmachine.c
+++ b/unix/modmachine.c
@@ -32,6 +32,7 @@
#include "extmod/machine_mem.h"
#include "extmod/machine_pinbase.h"
+#include "extmod/machine_signal.h"
#include "extmod/machine_pulse.h"
#if MICROPY_PLAT_DEV_MEM
@@ -82,6 +83,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
{ MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) },
+ { MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
#if MICROPY_PY_MACHINE_PULSE
{ MP_ROM_QSTR(MP_QSTR_time_pulse_us), MP_ROM_PTR(&machine_time_pulse_us_obj) },
#endif
diff --git a/unix/moduselect.c b/unix/moduselect.c
index 76938329f..37a3a33b2 100644
--- a/unix/moduselect.c
+++ b/unix/moduselect.c
@@ -253,8 +253,9 @@ STATIC mp_obj_t poll_iternext(mp_obj_t self_in) {
self->iter_cnt--;
- struct pollfd *entries = self->entries;
+ struct pollfd *entries = self->entries + self->iter_idx;
for (int i = self->iter_idx; i < self->len; i++, entries++) {
+ self->iter_idx++;
if (entries->revents != 0) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(self->ret_tuple);
// If there's an object stored, return it, otherwise raw fd
diff --git a/windows/msvc/sources.props b/windows/msvc/sources.props
index 4ea917552..e35df8352 100644
--- a/windows/msvc/sources.props
+++ b/windows/msvc/sources.props
@@ -15,6 +15,7 @@
<ClCompile Include="$(PyBaseDir)unix\modmachine.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_mem.c" />
<ClCompile Include="$(PyBaseDir)extmod\machine_pinbase.c" />
+ <ClCompile Include="$(PyBaseDir)extmod\machine_signal.c" />
<ClCompile Include="$(PyBaseDir)extmod\modubinascii.c" />
<ClCompile Include="$(PyBaseDir)extmod\moductypes.c" />
<ClCompile Include="$(PyBaseDir)extmod\moduhashlib.c" />
@@ -24,6 +25,7 @@
<ClCompile Include="$(PyBaseDir)extmod\modure.c" />
<ClCompile Include="$(PyBaseDir)extmod\moduzlib.c" />
<ClCompile Include="$(PyBaseDir)extmod\utime_mphal.c" />
+ <ClCompile Include="$(PyBaseDir)extmod\virtpin.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(PyBaseDir)py\*.h" />