diff --git a/cc3200/hal/cc3200_hal.c b/cc3200/hal/cc3200_hal.c index f4d38d120e..37026db14e 100644 --- a/cc3200/hal/cc3200_hal.c +++ b/cc3200/hal/cc3200_hal.c @@ -130,10 +130,6 @@ void mp_hal_delay_ms(mp_uint_t delay) { } } -NORETURN void mp_hal_raise(int errno) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, mp_obj_new_int(errno))); -} - void mp_hal_set_interrupt_char (int c) { mpexception_set_interrupt_char (c); } diff --git a/cc3200/hal/cc3200_hal.h b/cc3200/hal/cc3200_hal.h index 054d5035a2..9715096b61 100644 --- a/cc3200/hal/cc3200_hal.h +++ b/cc3200/hal/cc3200_hal.h @@ -62,7 +62,6 @@ extern void HAL_SystemInit (void); extern void HAL_SystemDeInit (void); extern void HAL_IncrementTick(void); -extern NORETURN void mp_hal_raise(int errno); extern void mp_hal_set_interrupt_char (int c); #endif /* CC3200_LAUNCHXL_HAL_CC3200_HAL_H_ */ diff --git a/cc3200/misc/mpirq.c b/cc3200/misc/mpirq.c index 29cc4a7bdb..4389ab0c3c 100644 --- a/cc3200/misc/mpirq.c +++ b/cc3200/misc/mpirq.c @@ -112,7 +112,7 @@ void mp_irq_remove (const mp_obj_t parent) { uint mp_irq_translate_priority (uint priority) { if (priority < 1 || priority > MP_ARRAY_SIZE(mp_irq_priorities)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_irq_priorities[priority - 1]; } diff --git a/cc3200/mods/modmachine.c b/cc3200/mods/modmachine.c index f82decda2c..8a57c2eb45 100644 --- a/cc3200/mods/modmachine.c +++ b/cc3200/mods/modmachine.c @@ -130,7 +130,7 @@ STATIC mp_obj_t machine_main(mp_obj_t main) { if (MP_OBJ_IS_STR(main)) { MP_STATE_PORT(machine_config_main) = main; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_const_none; } diff --git a/cc3200/mods/modnetwork.c b/cc3200/mods/modnetwork.c index 8e086b1d29..f98d9a88ad 100644 --- a/cc3200/mods/modnetwork.c +++ b/cc3200/mods/modnetwork.c @@ -101,7 +101,7 @@ STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, mp_uint_t n_a // check the server id if (args[0].u_obj != MP_OBJ_NULL) { if (mp_obj_get_int(args[0].u_obj) != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } } diff --git a/cc3200/mods/moduhashlib.c b/cc3200/mods/moduhashlib.c index 93f15540c9..46f30be21d 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 { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } } @@ -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 - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } if (!self->digested) { diff --git a/cc3200/mods/moduos.c b/cc3200/mods/moduos.c index 8e3e0135ec..d5b29336af 100644 --- a/cc3200/mods/moduos.c +++ b/cc3200/mods/moduos.c @@ -158,7 +158,7 @@ STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonl #endif // cannot mount twice or on existing paths if (f_stat(path, &fno) == FR_OK || osmount_find_by_device(device)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // create a new object @@ -196,7 +196,7 @@ STATIC void mount (mp_obj_t device, const char *path, uint pathlen, bool readonl if (f_mount(&self->fatfs, self->path, 1) != FR_OK) { // remove it and raise mp_obj_list_remove(&MP_STATE_PORT(mount_obj_list), self); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } // mount succeeded, increment the count @@ -252,7 +252,7 @@ STATIC mp_obj_t os_chdir(mp_obj_t path_in) { } if (res != FR_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } return mp_const_none; @@ -263,7 +263,7 @@ STATIC mp_obj_t os_getcwd(void) { char buf[MICROPY_ALLOC_PATH_MAX + 1]; FRESULT res = f_getcwd(buf, sizeof buf); if (res != FR_OK) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + mp_raise_OSError(fresult_to_errno_table[res]); } return mp_obj_new_str(buf, strlen(buf), false); } @@ -303,7 +303,7 @@ STATIC mp_obj_t os_listdir(mp_uint_t n_args, const mp_obj_t *args) { res = f_opendir(&dir, path); /* Open the directory */ if (res != FR_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } for ( ; ; ) { @@ -335,10 +335,10 @@ STATIC mp_obj_t os_mkdir(mp_obj_t path_o) { case FR_OK: return mp_const_none; case FR_EXIST: - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_mkdir_obj, os_mkdir); @@ -351,7 +351,7 @@ STATIC mp_obj_t os_rename(mp_obj_t path_in, mp_obj_t path_out) { case FR_OK: return mp_const_none; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } } STATIC MP_DEFINE_CONST_FUN_OBJ_2(os_rename_obj, os_rename); @@ -363,7 +363,7 @@ STATIC mp_obj_t os_remove(mp_obj_t path_o) { case FR_OK: return mp_const_none; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } } STATIC MP_DEFINE_CONST_FUN_OBJ_1(os_remove_obj, os_remove); @@ -394,7 +394,7 @@ STATIC mp_obj_t os_stat(mp_obj_t path_in) { fno.ftime = 0; fno.fattrib = AM_DIR; } else if ((res = f_stat(path, &fno)) != FR_OK) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(fresult_to_errno_table[res]))); + mp_raise_OSError(fresult_to_errno_table[res]); } mp_obj_tuple_t *t = mp_obj_new_tuple(10, NULL); @@ -481,7 +481,7 @@ STATIC mp_obj_t os_mount(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k return mp_const_none; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments)); + mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments); } MP_DEFINE_CONST_FUN_OBJ_KW(os_mount_obj, 2, os_mount); @@ -490,7 +490,7 @@ STATIC mp_obj_t os_unmount(mp_obj_t path_o) { // '/flash' cannot be unmounted, also not the current working directory if (path_equal(path, "/flash")) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // now unmount it @@ -498,7 +498,7 @@ STATIC mp_obj_t os_unmount(mp_obj_t path_o) { if ((mount_obj = osmount_find_by_path(path))) { unmount (mount_obj); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_msg(&mp_type_ValueError, mpexception_value_invalid_arguments); } return mp_const_none; @@ -515,7 +515,7 @@ STATIC mp_obj_t os_mkfs(mp_obj_t device) { path = mp_obj_str_get_str(device); // otherwise the relative path check will pass... if (path[0] != '/') { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_value_invalid_arguments)); + mp_raise_msg(&mp_type_OSError, mpexception_value_invalid_arguments); } } else { // mount it briefly @@ -541,7 +541,7 @@ STATIC mp_obj_t os_mkfs(mp_obj_t device) { } if (res != FR_OK) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } return mp_const_none; } diff --git a/cc3200/mods/modusocket.c b/cc3200/mods/modusocket.c index c7b3fb2035..81a4c2e198 100644 --- a/cc3200/mods/modusocket.c +++ b/cc3200/mods/modusocket.c @@ -156,7 +156,7 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_ // create the socket int _errno; if (wlan_socket_socket(s, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } // add the socket to the list modusocket_socket_add(s->sock_base.sd, true); @@ -182,7 +182,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) { // call the NIC to bind the socket int _errno; if (wlan_socket_bind(self, ip, port, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_const_none; } @@ -200,7 +200,7 @@ STATIC mp_obj_t socket_listen(mp_uint_t n_args, const mp_obj_t *args) { int _errno; if (wlan_socket_listen(self, backlog, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_const_none; } @@ -220,7 +220,7 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) { mp_uint_t port; int _errno; if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } // add the socket to the list @@ -248,7 +248,7 @@ STATIC mp_obj_t socket_connect(mp_obj_t self_in, mp_obj_t addr_in) { if (!self->sock_base.cert_req && _errno == SL_ESECSNOVERIFY) { return mp_const_none; } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_const_none; } @@ -262,7 +262,7 @@ STATIC mp_obj_t socket_send(mp_obj_t self_in, mp_obj_t buf_in) { int _errno; mp_int_t ret = wlan_socket_send(self, bufinfo.buf, bufinfo.len, &_errno); if (ret < 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_obj_new_int_from_uint(ret); } @@ -278,9 +278,9 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno); if (ret < 0) { if (_errno == EAGAIN && self->sock_base.has_timeout) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); + mp_raise_msg(&mp_type_TimeoutError, "timed out"); } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } if (ret == 0) { return mp_const_empty_bytes; @@ -307,7 +307,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_ int _errno; mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno); if (ret < 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_obj_new_int(ret); } @@ -324,9 +324,9 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) { 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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TimeoutError, "timed out")); + mp_raise_msg(&mp_type_TimeoutError, "timed out"); } - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } mp_obj_t tuple[2]; if (ret == 0) { @@ -364,7 +364,7 @@ STATIC mp_obj_t socket_setsockopt(mp_uint_t n_args, const mp_obj_t *args) { int _errno; if (wlan_socket_setsockopt(self, level, opt, optval, optlen, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_const_none; } @@ -384,7 +384,7 @@ STATIC mp_obj_t socket_settimeout(mp_obj_t self_in, mp_obj_t timeout_in) { } int _errno; if (wlan_socket_settimeout(self, timeout, &_errno) != 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-_errno))); + mp_raise_OSError(-_errno); } return mp_const_none; } @@ -408,7 +408,7 @@ STATIC mp_obj_t socket_makefile(mp_uint_t n_args, const mp_obj_t *args) { if (n_args > 1) { const char *mode = mp_obj_str_get_str(args[1]); if (strcmp(mode, "rb") && strcmp(mode, "wb")) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } return self; @@ -504,7 +504,7 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) { uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE]; int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET); if (result < 0) { - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(-result))); + 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); diff --git a/cc3200/mods/modussl.c b/cc3200/mods/modussl.c index 1f27bdd21f..7a4787b6b3 100644 --- a/cc3200/mods/modussl.c +++ b/cc3200/mods/modussl.c @@ -131,10 +131,10 @@ STATIC mp_obj_t mod_ssl_wrap_socket(mp_uint_t n_args, const mp_obj_t *pos_args, return ssl_sock; socket_error: - nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(_errno))); + mp_raise_OSError(_errno); arg_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(mod_ssl_wrap_socket_obj, 0, mod_ssl_wrap_socket); diff --git a/cc3200/mods/modutime.c b/cc3200/mods/modutime.c index bef8b667f3..7ea8df1eff 100644 --- a/cc3200/mods/modutime.c +++ b/cc3200/mods/modutime.c @@ -29,7 +29,7 @@ #include #include "py/mpconfig.h" -#include "py/nlr.h" +#include "py/runtime.h" #include "py/obj.h" #include "py/smallint.h" #include "py/mphal.h" @@ -109,7 +109,7 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) { // localtime generates a tuple of len 8. CPython uses 9, so we accept both. if (len < 8 || len > 9) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, mpexception_num_type_invalid_arguments)); + mp_raise_TypeError(mpexception_num_type_invalid_arguments); } return mp_obj_new_int_from_uint(timeutils_mktime(mp_obj_get_int(elem[0]), mp_obj_get_int(elem[1]), mp_obj_get_int(elem[2]), diff --git a/cc3200/mods/modwlan.c b/cc3200/mods/modwlan.c index 2fb7ed377d..4b3dd4ec38 100644 --- a/cc3200/mods/modwlan.c +++ b/cc3200/mods/modwlan.c @@ -603,7 +603,7 @@ STATIC void wlan_reset (void) { STATIC void wlan_validate_mode (uint mode) { if (mode != ROLE_STA && mode != ROLE_AP) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } @@ -614,7 +614,7 @@ STATIC void wlan_set_mode (uint mode) { STATIC void wlan_validate_ssid_len (uint32_t len) { if (len > MODWLAN_SSID_LEN_MAX) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } @@ -647,7 +647,7 @@ STATIC void wlan_validate_security (uint8_t auth, const char *key, uint8_t len) return; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { @@ -670,7 +670,7 @@ STATIC void wlan_set_security (uint8_t auth, const char *key, uint8_t len) { STATIC void wlan_validate_channel (uint8_t channel) { if (channel < 1 || channel > 11) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } @@ -682,7 +682,7 @@ STATIC void wlan_set_channel (uint8_t channel) { #if MICROPY_HW_ANTENNA_DIVERSITY STATIC void wlan_validate_antenna (uint8_t antenna) { if (antenna != ANTENNA_TYPE_INTERNAL && antenna != ANTENNA_TYPE_EXTERNAL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } @@ -847,7 +847,7 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_ui if (n_args > 1 || n_kw > 0) { // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // start the peripheral wlan_init_helper(self, &args[1]); @@ -871,7 +871,7 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) { // check for correct wlan mode if (wlan_obj.mode == ROLE_AP) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } Sl_WlanNetworkEntry_t wlanEntry; @@ -925,7 +925,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // parse args @@ -973,9 +973,9 @@ 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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } else if (status == MODWLAN_ERROR_INVALID_PARAMS) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } return mp_const_none; } @@ -1004,7 +1004,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // get the configuration @@ -1051,7 +1051,7 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma // check for the correct string const char *mode = mp_obj_str_get_str(args[1].u_obj); if (strcmp("dhcp", mode)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } // only if we are not in AP mode @@ -1165,7 +1165,7 @@ STATIC mp_obj_t wlan_mac (mp_uint_t n_args, const mp_obj_t *args) { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_READ); if (bufinfo.len != 6) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } memcpy(self->mac, bufinfo.buf, SL_MAC_ADDR_LEN); sl_NetCfgSet(SL_MAC_ADDRESS_SET, 1, SL_MAC_ADDR_LEN, (_u8 *)self->mac); @@ -1201,7 +1201,7 @@ STATIC mp_obj_t wlan_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t * return _irq; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); @@ -1230,18 +1230,18 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq); // // // the call to sl_NetAppSet corrupts the input string URN=args[1], so we copy into a local buffer // if (len > MAX_DEVICE_URN_LEN) { -// nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); +// mp_raise_ValueError(mpexception_value_invalid_arguments); // } // 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) { -// nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); +// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); // } // } // 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) { -// nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); +// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); // } // return mp_obj_new_str(urn, (len - 1), false); // } diff --git a/cc3200/mods/pybadc.c b/cc3200/mods/pybadc.c index 22a90edb0a..f8c9b3da54 100644 --- a/cc3200/mods/pybadc.c +++ b/cc3200/mods/pybadc.c @@ -104,7 +104,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } } @@ -149,12 +149,12 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uin // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // check the number of bits if (args[1].u_int != 12) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } // setup the object @@ -173,7 +173,7 @@ STATIC mp_obj_t adc_init(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(args), &pyb_adc_init_args[1], args); // check the number of bits if (args[0].u_int != 12) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } pyb_adc_init(pos_args[0]); return mp_const_none; @@ -206,11 +206,11 @@ 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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_os_resource_not_avaliable)); + mp_raise_ValueError(mpexception_os_resource_not_avaliable); } 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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } } else { @@ -277,7 +277,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) { // the channel must be enabled if (!self->enabled) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // wait until a new value is available diff --git a/cc3200/mods/pybi2c.c b/cc3200/mods/pybi2c.c index 5022e614f6..d92782d8ae 100644 --- a/cc3200/mods/pybi2c.c +++ b/cc3200/mods/pybi2c.c @@ -144,7 +144,7 @@ STATIC bool pyb_i2c_transaction(uint cmd) { STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) { // not initialized if (!self->baudrate) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } } @@ -256,7 +256,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)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } } @@ -275,7 +275,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)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } } } @@ -323,7 +323,7 @@ STATIC mp_obj_t pyb_i2c_init_helper(pyb_i2c_obj_t *self, const mp_arg_val_t *arg return mp_const_none; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC const mp_arg_t pyb_i2c_init_args[] = { @@ -341,7 +341,7 @@ STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // setup the object @@ -445,7 +445,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)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } // return the number of bytes written @@ -514,7 +514,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); } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem); diff --git a/cc3200/mods/pybpin.c b/cc3200/mods/pybpin.c index ce304404b5..f59e65fc26 100644 --- a/cc3200/mods/pybpin.c +++ b/cc3200/mods/pybpin.c @@ -145,7 +145,7 @@ pin_obj_t *pin_find(mp_obj_t user_obj) { return pin_obj; } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } void pin_config (pin_obj_t *self, int af, uint mode, uint pull, int value, uint strength) { @@ -185,7 +185,7 @@ uint8_t pin_find_peripheral_unit (const mp_obj_t pin, uint8_t fn, uint8_t type) return pin_o->af_list[i].unit; } } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit) { @@ -195,13 +195,13 @@ uint8_t pin_find_peripheral_type (const mp_obj_t pin, uint8_t fn, uint8_t unit) return pin_o->af_list[i].type; } } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } int8_t pin_find_af_index (const pin_obj_t* pin, uint8_t fn, uint8_t unit, uint8_t type) { int8_t af = pin_obj_find_af(pin, fn, unit, type); if (af < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } return af; } @@ -426,18 +426,18 @@ STATIC void pin_extint_register(pin_obj_t *self, uint32_t intmode, uint32_t prio STATIC void pin_validate_mode (uint mode) { if (mode != GPIO_DIR_MODE_IN && mode != GPIO_DIR_MODE_OUT && mode != PIN_TYPE_OD && mode != GPIO_DIR_MODE_ALT && mode != GPIO_DIR_MODE_ALT_OD) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void pin_validate_pull (uint pull) { if (pull != PIN_TYPE_STD && pull != PIN_TYPE_STD_PU && pull != PIN_TYPE_STD_PD) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } STATIC void pin_validate_drive(uint strength) { if (strength != PIN_STRENGTH_2MA && strength != PIN_STRENGTH_4MA && strength != PIN_STRENGTH_6MA) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } @@ -450,7 +450,7 @@ STATIC void pin_validate_af(const pin_obj_t* pin, int8_t idx, uint8_t *fn, uint8 return; } } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC uint8_t pin_get_value (const pin_obj_t* self) { @@ -591,7 +591,7 @@ STATIC mp_obj_t pin_obj_init_helper(pin_obj_t *self, mp_uint_t n_args, const mp_ return mp_const_none; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void pin_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { @@ -905,7 +905,7 @@ STATIC mp_obj_t pin_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *k return _irq; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pin_irq_obj, 1, pin_irq); diff --git a/cc3200/mods/pybrtc.c b/cc3200/mods/pybrtc.c index ea99411052..4662edbe7e 100644 --- a/cc3200/mods/pybrtc.c +++ b/cc3200/mods/pybrtc.c @@ -202,7 +202,7 @@ STATIC uint pyb_rtc_datetime_s_us(const mp_obj_t datetime, uint32_t *seconds) { // verify the tuple if (len < 3 || len > 8) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } tm.tm_year = mp_obj_get_int(items[0]); @@ -294,7 +294,7 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // setup the object @@ -362,7 +362,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } uint32_t f_seconds; @@ -371,7 +371,7 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma if (MP_OBJ_IS_TYPE(args[1].u_obj, &mp_type_tuple)) { // datetime tuple given // repeat cannot be used with a datetime tuple if (repeat) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } f_mseconds = pyb_rtc_datetime_s_us (args[1].u_obj, &f_seconds) / 1000; } else { // then it must be an integer @@ -397,7 +397,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // get the current time @@ -415,7 +415,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // disable the alarm pyb_rtc_disable_alarm(); @@ -453,7 +453,7 @@ STATIC mp_obj_t pyb_rtc_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_ return _irq; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_rtc_irq_obj, 1, pyb_rtc_irq); diff --git a/cc3200/mods/pybsd.c b/cc3200/mods/pybsd.c index 55b797dc78..d7efbe872c 100644 --- a/cc3200/mods/pybsd.c +++ b/cc3200/mods/pybsd.c @@ -107,7 +107,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } // register it with the sleep module @@ -132,7 +132,7 @@ STATIC mp_obj_t pyb_sd_make_new (const mp_obj_type_t *type, mp_uint_t n_args, mp // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // setup and initialize the object diff --git a/cc3200/mods/pybspi.c b/cc3200/mods/pybspi.c index d4fcbe94b4..5a040e3f59 100644 --- a/cc3200/mods/pybspi.c +++ b/cc3200/mods/pybspi.c @@ -131,7 +131,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // send and receive the data MAP_SPICSEnable(GSPI_BASE); @@ -218,7 +218,7 @@ STATIC mp_obj_t pyb_spi_init_helper(pyb_spi_obj_t *self, const mp_arg_val_t *arg return mp_const_none; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } static const mp_arg_t pyb_spi_init_args[] = { @@ -240,7 +240,7 @@ STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp // check the peripheral id if (args[0].u_int != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // setup the object @@ -295,7 +295,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_spi_write_obj, pyb_spi_write); STATIC mp_obj_t pyb_spi_read(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_nbytes, MP_ARG_REQUIRED | MP_ARG_OBJ, }, - { MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} }, + { MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} }, }; // parse args @@ -319,7 +319,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_spi_read_obj, 1, pyb_spi_read); STATIC mp_obj_t pyb_spi_readinto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { static const mp_arg_t allowed_args[] = { { MP_QSTR_buf, MP_ARG_REQUIRED | MP_ARG_OBJ, }, - { MP_QSTR_write, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 0x00} }, + { MP_QSTR_write, MP_ARG_INT, {.u_int = 0x00} }, }; // parse args @@ -357,7 +357,7 @@ STATIC mp_obj_t pyb_spi_write_readinto (mp_obj_t self, mp_obj_t writebuf, mp_obj // get the read buffer mp_get_buffer_raise(readbuf, &bufinfo_read, MP_BUFFER_WRITE); if (bufinfo_read.len != bufinfo_write.len) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } } diff --git a/cc3200/mods/pybtimer.c b/cc3200/mods/pybtimer.c index 65fc7195e6..2ac71cccb7 100644 --- a/cc3200/mods/pybtimer.c +++ b/cc3200/mods/pybtimer.c @@ -223,7 +223,7 @@ STATIC uint32_t compute_prescaler_period_and_match_value(pyb_timer_channel_obj_t return prescaler; error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC void timer_init (pyb_timer_obj_t *tim) { @@ -319,7 +319,7 @@ STATIC mp_obj_t pyb_timer_init_helper(pyb_timer_obj_t *tim, mp_uint_t n_args, co return mp_const_none; error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { @@ -329,7 +329,7 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, mp_uint_t n_args, // 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)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx]; @@ -370,7 +370,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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) { // invalid channel @@ -440,7 +440,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp return ch; error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_obj, 2, pyb_timer_channel); @@ -560,7 +560,7 @@ STATIC mp_obj_t pyb_timer_channel_freq(mp_uint_t n_args, const mp_obj_t *args) { // set int32_t _frequency = mp_obj_get_int(args[1]); if (_frequency <= 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } ch->frequency = _frequency; ch->period = 1000000 / _frequency; @@ -579,7 +579,7 @@ STATIC mp_obj_t pyb_timer_channel_period(mp_uint_t n_args, const mp_obj_t *args) // set int32_t _period = mp_obj_get_int(args[1]); if (_period <= 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } ch->period = _period; ch->frequency = 1000000 / _period; @@ -712,7 +712,7 @@ STATIC mp_obj_t pyb_timer_channel_irq (mp_uint_t n_args, const mp_obj_t *pos_arg return _irq; invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_timer_channel_irq_obj, 1, pyb_timer_channel_irq); diff --git a/cc3200/mods/pybuart.c b/cc3200/mods/pybuart.c index e7b5255bdf..493522f835 100644 --- a/cc3200/mods/pybuart.c +++ b/cc3200/mods/pybuart.c @@ -280,7 +280,7 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) { STATIC void uart_check_init(pyb_uart_obj_t *self) { // not initialized if (!self->baudrate) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } } @@ -432,7 +432,7 @@ STATIC mp_obj_t pyb_uart_init_helper(pyb_uart_obj_t *self, const mp_arg_val_t *a return mp_const_none; error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC const mp_arg_t pyb_uart_init_args[] = { @@ -472,7 +472,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, mp_uint_t n_args, m } if (uart_id > PYB_UART_1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } // get the correct uart instance @@ -556,7 +556,7 @@ STATIC mp_obj_t pyb_uart_irq (mp_uint_t n_args, const mp_obj_t *pos_args, mp_map return uart_irq_new (self, trigger, priority, args[2].u_obj); invalid_args: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_uart_irq_obj, 1, pyb_uart_irq); @@ -622,7 +622,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)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_operation_failed)); + mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed); } return size; } diff --git a/cc3200/mods/pybwdt.c b/cc3200/mods/pybwdt.c index 6e5fe4714a..30478c83ce 100644 --- a/cc3200/mods/pybwdt.c +++ b/cc3200/mods/pybwdt.c @@ -100,14 +100,14 @@ STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp 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) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable)); + mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable); } uint timeout_ms = args[1].u_int; if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } if (pyb_wdt_obj.running) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, mpexception_os_request_not_possible)); + mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible); } // Enable the WDT peripheral clock diff --git a/cc3200/mpconfigport.h b/cc3200/mpconfigport.h index 0b16d730d0..bf3e691bd8 100644 --- a/cc3200/mpconfigport.h +++ b/cc3200/mpconfigport.h @@ -38,6 +38,7 @@ // options to control how Micro Python is built #define MICROPY_ALLOC_PATH_MAX (128) +#define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) #define MICROPY_COMP_MODULE_CONST (1) diff --git a/cc3200/mpthreadport.c b/cc3200/mpthreadport.c index 064aa6ba10..e77ac4ae53 100644 --- a/cc3200/mpthreadport.c +++ b/cc3200/mpthreadport.c @@ -28,10 +28,13 @@ #include "py/mpconfig.h" #include "py/mpstate.h" +#include "py/runtime.h" #include "py/gc.h" #include "py/mpthread.h" +#include "py/mphal.h" #include "mptask.h" #include "task.h" +#include "irq.h" #if MICROPY_PY_THREAD @@ -131,7 +134,7 @@ void mp_thread_create(void *(*entry)(void*), void *arg, size_t *stack_size) { TaskHandle_t id = xTaskCreateStatic(freertos_entry, "Thread", *stack_size / sizeof(void*), arg, 2, stack, tcb); if (id == NULL) { mp_thread_mutex_unlock(&thread_mutex); - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "can't create thread")); + mp_raise_msg(&mp_type_OSError, "can't create thread"); } // add thread to linked list of all threads @@ -165,14 +168,23 @@ void mp_thread_mutex_init(mp_thread_mutex_t *mutex) { mutex->handle = xSemaphoreCreateMutexStatic(&mutex->buffer); } +// To allow hard interrupts to work with threading we only take/give the semaphore +// if we are not within an interrupt context and interrupts are enabled. + int mp_thread_mutex_lock(mp_thread_mutex_t *mutex, int wait) { - int ret = xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0); - return ret == pdTRUE; + if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { + int ret = xSemaphoreTake(mutex->handle, wait ? portMAX_DELAY : 0); + return ret == pdTRUE; + } else { + return 1; + } } void mp_thread_mutex_unlock(mp_thread_mutex_t *mutex) { - xSemaphoreGive(mutex->handle); - // TODO check return value + if ((HAL_NVIC_INT_CTRL_REG & HAL_VECTACTIVE_MASK) == 0 && query_irq() == IRQ_STATE_ENABLED) { + xSemaphoreGive(mutex->handle); + // TODO check return value + } } #endif // MICROPY_PY_THREAD diff --git a/cc3200/serverstask.c b/cc3200/serverstask.c index 1305afda0b..6b5899e186 100644 --- a/cc3200/serverstask.c +++ b/cc3200/serverstask.c @@ -29,7 +29,7 @@ #include "py/mpconfig.h" #include "py/misc.h" -#include "py/nlr.h" +#include "py/runtime.h" #include "py/mphal.h" #include "serverstask.h" #include "simplelink.h" @@ -187,7 +187,7 @@ void servers_close_socket (int16_t *sd) { void servers_set_login (char *user, char *pass) { if (strlen(user) > SERVERS_USER_PASS_LEN_MAX || strlen(pass) > SERVERS_USER_PASS_LEN_MAX) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } memcpy(servers_user, user, SERVERS_USER_PASS_LEN_MAX); memcpy(servers_pass, pass, SERVERS_USER_PASS_LEN_MAX); @@ -196,7 +196,7 @@ void servers_set_login (char *user, char *pass) { void servers_set_timeout (uint32_t timeout) { if (timeout < SERVERS_MIN_TIMEOUT_MS) { // timeout is too low - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, mpexception_value_invalid_arguments)); + mp_raise_ValueError(mpexception_value_invalid_arguments); } servers_data.timeout = timeout; } diff --git a/conf.py b/conf.py index 47dc20f59f..bb2a2d897b 100644 --- a/conf.py +++ b/conf.py @@ -69,7 +69,7 @@ copyright = '2014-2016, Damien P. George, Scott Shawcroft, Tony DiCola and other # The short X.Y version. version = '1.8' # The full version, including alpha/beta/rc tags. -release = '1.8.4' +release = '1.8.5' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/docs/library/machine.SPI.rst b/docs/library/machine.SPI.rst index 73b3a3996d..9b4d62e011 100644 --- a/docs/library/machine.SPI.rst +++ b/docs/library/machine.SPI.rst @@ -1,10 +1,13 @@ .. currentmodule:: machine -class SPI -- a master-driven serial protocol -============================================ +class SPI -- a Serial Peripheral Interface bus protocol +======================================================= -SPI is a serial protocol that is driven by a master. At the physical level -there are 3 lines: SCK, MOSI, MISO. +SPI is a serial protocol that is driven by a master. At the physical level, +bus consistens of 3 lines: SCK, MOSI, MISO. Multiple devices can share the +same bus. Each device should have a separate, 4th signal, SS (Slave Select), +to select a particualr device on a bus with which communication takes place. +Management of an SS signal should happen in user code (via machine.Pin class). .. only:: port_wipy @@ -21,65 +24,83 @@ there are 3 lines: SCK, MOSI, MISO. Constructors ------------ -.. only:: port_wipy +.. class:: SPI(id, ...) - .. class:: SPI(id, ...) + Construct an SPI object on the given bus, ``id``. Values of ``id`` depend + on a particular port and its hardware. Values 0, 1, etc. are commonly used + to select hardware SPI block #0, #1, etc. Value -1 can be used for + bitbanging (software) implementation of SPI (if supported by a port). - Construct an SPI object on the given bus. ``id`` can be only 0. - With no additional parameters, the SPI object is created but not - initialised (it has the settings from the last initialisation of - the bus, if any). If extra arguments are given, the bus is initialised. - See ``init`` for parameters of initialisation. + With no additional parameters, the SPI object is created but not + initialised (it has the settings from the last initialisation of + the bus, if any). If extra arguments are given, the bus is initialised. + See ``init`` for parameters of initialisation. Methods ------- -.. method:: SPI.init(mode, baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO)) +.. method:: SPI.init(baudrate=1000000, \*, polarity=0, phase=0, bits=8, firstbit=SPI.MSB, pins=(CLK, MOSI, MISO), sck=None, mosi=None, miso=None) Initialise the SPI bus with the given parameters: - - ``mode`` must be ``SPI.MASTER``. - ``baudrate`` is the SCK clock rate. - ``polarity`` can be 0 or 1, and is the level the idle clock line sits at. - ``phase`` can be 0 or 1 to sample data on the first or second clock edge respectively. - - ``bits`` is the width of each transfer, accepted values are 8, 16 and 32. - - ``firstbit`` can be ``SPI.MSB`` only. - - ``pins`` is an optional tuple with the pins to assign to the SPI bus. + - ``bits`` is the width in bits of each transfer. Only 8 of is guaranteed to be supported by all hardware. + - ``firstbit`` can be ``SPI.MSB`` or ``SPI.LSB``. + - ``pins`` is an optional tuple with the pins to assign to the SPI bus (deprecated, only for WiPy). + - ``sck``, ``mosi``, ``miso`` are pins (machine.Pin) objects to use for bus signals. For most + hardware SPI blocks (as selected by ``id`` parameter to the constructore), pins are fixed + and cannot be changed. In some cases, hardware blocks allow 2-3 alternative pin sets for + a hardware SPI block. Arbitrary pin assignments are possible only for a bitbanging SPI driver + (``id``=-1). .. method:: SPI.deinit() Turn off the SPI bus. +.. method:: SPI.read(nbytes, write=0x00) + + Read a number of bytes specified by ``nbytes`` while continuously writing + the single byte given by ``write``. + Returns a ``bytes`` object with the data that was read. + +.. method:: SPI.readinto(buf, write=0x00) + + Read into the buffer specified by ``buf`` while continuously writing the + single byte given by ``write``. + Returns ``None``. + + Note: on WiPy this function returns the number of bytes read. + .. method:: SPI.write(buf) - Write the data contained in ``buf``. - Returns the number of bytes written. + Write the bytes contained in ``buf``. + Returns ``None``. -.. method:: SPI.read(nbytes, *, write=0x00) - - Read the ``nbytes`` while writing the data specified by ``write``. - Return the number of bytes read. - -.. method:: SPI.readinto(buf, *, write=0x00) - - Read into the buffer specified by ``buf`` while writing the data specified by - ``write``. - Return the number of bytes read. + Note: on WiPy this function returns the number of bytes written. .. method:: SPI.write_readinto(write_buf, read_buf) - Write from ``write_buf`` and read into ``read_buf``. Both buffers must have the + Write the bytes from ``write_buf`` while reading into ``read_buf``. The + buffers can be the same or different, but both buffers must have the same length. - Returns the number of bytes written + Returns ``None``. + + Note: on WiPy this function returns the number of bytes written. Constants --------- .. data:: SPI.MASTER - for initialising the SPI bus to master + for initialising the SPI bus to master; this is only used for the WiPy .. data:: SPI.MSB set the first bit to be the most significant bit + +.. data:: SPI.LSB + + set the first bit to be the least significant bit diff --git a/docs/reference/constrained.rst b/docs/reference/constrained.rst new file mode 100644 index 0000000000..7c1b6a3eb2 --- /dev/null +++ b/docs/reference/constrained.rst @@ -0,0 +1,456 @@ +.. _constrained: + +MicroPython on Microcontrollers +=============================== + +MicroPython is designed to be capable of running on microcontrollers. These +have hardware limitations which may be unfamiliar to programmers more familiar +with conventional computers. In particular the amount of RAM and nonvolatile +"disk" (flash memory) storage is limited. This tutorial offers ways to make +the most of the limited resources. Because MicroPython runs on controllers +based on a variety of architectures, the methods presented are generic: in some +cases it will be necessary to obtain detailed information from platform specific +documentation. + +Flash Memory +------------ + +On the Pyboard the simple way to address the limited capacity is to fit a micro +SD card. In some cases this is impractical, either because the device does not +have an SD card slot or for reasons of cost or power consumption; hence the +on-chip flash must be used. The firmware including the MicroPython subsystem is +stored in the onboard flash. The remaining capacity is available for use. For +reasons connected with the physical architecture of the flash memory part of +this capacity may be inaccessible as a filesystem. In such cases this space may +be employed by incorporating user modules into a firmware build which is then +flashed to the device. + +There are two ways to achieve this: frozen modules and frozen bytecode. Frozen +modules store the Python source with the firmware. Frozen bytecode uses the +cross compiler to convert the source to bytecode which is then stored with the +firmware. In either case the module may be accessed with an import statement: + +.. code:: + + import mymodule + +The procedure for producing frozen modules and bytecode is platform dependent; +instructions for building the firmware can be found in the README files in the +relevant part of the source tree. + +In general terms the steps are as follows: + +* Clone the MicroPython `repository `_. +* Acquire the (platform specific) toolchain to build the firmware. +* Build the cross compiler. +* Place the modules to be frozen in a specified directory (dependent on whether + the module is to be frozen as source or as bytecode). +* Build the firmware. A specific command may be required to build frozen + code of either type - see the platform documentation. +* Flash the firmware to the device. + +RAM +--- + +When reducing RAM usage there are two phases to consider: compilation and +execution. In addition to memory consumption, there is also an issue known as +heap fragmentation. In general terms it is best to minimise the repeated +creation and destruction of objects. The reason for this is covered in the +section covering the `heap`_. + +Compilation Phase +~~~~~~~~~~~~~~~~~ + +When a module is imported, MicroPython compiles the code to bytecode which is +then executed by the MicroPython virtual machine (VM). The bytecode is stored +in RAM. The compiler itself requires RAM, but this becomes available for use +when the compilation has completed. + +If a number of modules have already been imported the situation can arise where +there is insufficient RAM to run the compiler. In this case the import +statement will produce a memory exception. + +If a module instantiates global objects on import it will consume RAM at the +time of import, which is then unavailable for the compiler to use on subsequent +imports. In general it is best to avoid code which runs on import; a better +approach is to have initialisation code which is run by the application after +all modules have been imported. This maximises the RAM available to the +compiler. + +If RAM is still insufficient to compile all modules one solution is to +precompile modules. MicroPython has a cross compiler capable of compiling Python +modules to bytecode (see the README in the mpy-cross directory). The resulting +bytecode file has a .mpy extension; it may be copied to the filesystem and +imported in the usual way. Alternatively some or all modules may be implemented +as frozen bytecode: on most platforms this saves even more RAM as the bytecode +is run directly from flash rather than being stored in RAM. + +Execution Phase +~~~~~~~~~~~~~~~ + +There are a number of coding techniques for reducing RAM usage. + +**Constants** + +MicroPython provides a ``const`` keyword which may be used as follows: + +.. code:: + + from micropython import const + ROWS = const(33) + _COLS = const(0x10) + a = ROWS + b = _COLS + +In both instances where the constant is assigned to a variable the compiler +will avoid coding a lookup to the name of the constant by substituting its +literal value. This saves bytecode and hence RAM. However the ``ROWS`` value +will occupy at least two machine words, one each for the key and value in the +globals dictionary. The presence in the dictionary is necessary because another +module might import or use it. This RAM can be saved by prepending the name +with an underscore as in ``_COLS``: this symbol is not visible outside the +module so will not occupy RAM. + +The argument to ``const()`` may be anything which, at compile time, evaluates +to an integer e.g. ``0x100`` or ``1 << 8``. It can even include other const +symbols that have already been defined, e.g. ``1 << BIT``. + +**Constant data structures** + +Where there is a substantial volume of constant data and the platform supports +execution from Flash, RAM may be saved as follows. The data should be located in +Python modules and frozen as bytecode. The data must be defined as ``bytes`` +objects. The compiler 'knows' that ``bytes`` objects are immutable and ensures +that the objects remain in flash memory rather than being copied to RAM. The +``ustruct`` module can assist in converting between ``bytes`` types and other +Python built-in types. + +When considering the implications of frozen bytecode, note that in Python +strings, floats, bytes, integers and complex numbers are immutable. Accordingly +these will be frozen into flash. Thus, in the line + +.. code:: + + mystring = "The quick brown fox" + +the actual string "The quick brown fox" will reside in flash. At runtime a +reference to the string is assigned to the *variable* ``mystring``. The reference +occupies a single machine word. In principle a long integer could be used to +store constant data: + +.. code:: + + bar = 0xDEADBEEF0000DEADBEEF + +As in the string example, at runtime a reference to the arbitrarily large +integer is assigned to the variable ``bar``. That reference occupies a +single machine word. + +It might be expected that tuples of integers could be employed for the purpose +of storing constant data with minimal RAM use. With the current compiler this +is ineffective (the code works, but RAM is not saved). + +.. code:: + + foo = (1, 2, 3, 4, 5, 6, 100000) + +At runtime the tuple will be located in RAM. This may be subject to future +improvement. + +**Needless object creation** + +There are a number of situations where objects may unwittingly be created and +destroyed. This can reduce the usability of RAM through fragmentation. The +following sections discuss instances of this. + +**String concatenation** + +Consider the following code fragments which aim to produce constant strings: + +.. code:: + + var = "foo" + "bar" + var1 = "foo" "bar" + var2 = """\ + foo\ + bar""" + +Each produces the same outcome, however the first needlessly creates two string +objects at runtime, allocates more RAM for concatenation before producing the +third. The others perform the concatenation at compile time which is more +efficient, reducing fragmentation. + +Where strings must be dynamically created before being fed to a stream such as +a file it will save RAM if this is done in a piecemeal fashion. Rather than +creating a large string object, create a substring and feed it to the stream +before dealing with the next. + +The best way to create dynamic strings is by means of the string ``format`` +method: + +.. code:: + + var = "Temperature {:5.2f} Pressure {:06d}\n".format(temp, press) + +**Buffers** + +When accessing devices such as instances of UART, I2C and SPI interfaces, using +pre-allocated buffers avoids the creation of needless objects. Consider these +two loops: + +.. code:: + + while True: + var = spi.read(100) + # process data + + buf = bytearray(100) + while True: + spi.readinto(buf) + # process data in buf + +The first creates a buffer on each pass whereas the second re-uses a pre-allocated +buffer; this is both faster and more efficient in terms of memory fragmentation. + +**Bytes are smaller than ints** + +On most platforms an integer consumes four bytes. Consider the two calls to the +function ``foo()``: + +.. code:: + + def foo(bar): + for x in bar: + print(x) + foo((1, 2, 0xff)) + foo(b'\1\2\xff') + +In the first call a tuple of integers is created in RAM. The second efficiently +creates a ``bytes`` object consuming the minimum amount of RAM. If the module +were frozen as bytecode, the ``bytes`` object would reside in flash. + +**Strings Versus Bytes** + +Python3 introduced Unicode support. This introduced a distinction between a +string and an array of bytes. MicroPython ensures that Unicode strings take no +additional space so long as all characters in the string are ASCII (i.e. have +a value < 126). If values in the full 8-bit range are required ``bytes`` and +``bytearray`` objects can be used to ensure that no additional space will be +required. Note that most string methods (e.g. ``strip()``) apply also to ``bytes`` +instances so the process of eliminating Unicode can be painless. + +.. code:: + + s = 'the quick brown fox' # A string instance + b = b'the quick brown fox' # a bytes instance + +Where it is necessary to convert between strings and bytes the string ``encode`` +and the bytes ``decode`` methods can be used. Note that both strings and bytes +are immutable. Any operation which takes as input such an object and produces +another implies at least one RAM allocation to produce the result. In the +second line below a new bytes object is allocated. This would also occur if ``foo`` +were a string. + +.. code:: + + foo = b' empty whitespace' + foo = foo.lstrip() + +**Runtime compiler execution** + +The Python keywords ``eval`` and ``exec`` invoke the compiler at runtime, which +requires significant amounts of RAM. Note that the ``pickle`` library employs +``exec``. It may be more RAM efficient to use the ``json`` library for object +serialisation. + +**Storing strings in flash** + +Python strings are immutable hence have the potential to be stored in read only +memory. The compiler can place in flash strings defined in Python code. As with +frozen modules it is necessary to have a copy of the source tree on the PC and +the toolchain to build the firmware. The procedure will work even if the +modules have not been fully debugged, so long as they can be imported and run. + +After importing the modules, execute: + +.. code:: + + micropython.qstr_info(1) + +Then copy and paste all the Q(xxx) lines into a text editor. Check for and +remove lines which are obviously invalid. Open the file qstrdefsport.h which +will be found in stmhal (or the equivalent directory for the architecture in +use). Copy and paste the corrected lines at the end of the file. Save the file, +rebuild and flash the firmware. The outcome can be checked by importing the +modules and again issuing: + +.. code:: + + micropython.qstr_info(1) + +The Q(xxx) lines should be gone. + +.. _heap: + +The Heap +-------- + +When a running program instantiates an object the necessary RAM is allocated +from a fixed size pool known as the heap. When the object goes out of scope (in +other words becomes inaccessible to code) the redundant object is known as +"garbage". A process known as "garbage collection" (GC) reclaims that memory, +returning it to the free heap. This process runs automatically, however it can +be invoked directly by issuing ``gc.collect()``. + +The discourse on this is somewhat involved. For a 'quick fix' issue the +following periodically: + +.. code:: + + gc.collect() + gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) + +Fragmentation +~~~~~~~~~~~~~ + +Say a program creates an object ``foo``, then an object ``bar``. Subsequently +``foo`` goes out of scope but ``bar`` remains. The RAM used by ``foo`` will be +reclaimed by GC. However if ``bar`` was allocated to a higher address, the +RAM reclaimed from ``foo`` will only be of use for objects no bigger than +``foo``. In a complex or long running program the heap can become fragmented: +despite there being a substantial amount of RAM available, there is insufficient +contiguous space to allocate a particular object, and the program fails with a +memory error. + +The techniques outlined above aim to minimise this. Where large permanent buffers +or other objects are required it is best to instantiate these early in the +process of program execution before fragmentation can occur. Further improvements +may be made by monitoring the state of the heap and by controlling GC; these are +outlined below. + +Reporting +~~~~~~~~~ + +A number of library functions are available to report on memory allocation and +to control GC. These are to be found in the ``gc`` and ``micropython`` modules. +The following example may be pasted at the REPL (``ctrl e`` to enter paste mode, +``ctrl d`` to run it). + +.. code:: + + import gc + import micropython + gc.collect() + micropython.mem_info() + print('-----------------------------') + print('Initial free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) + def func(): + a = bytearray(10000) + gc.collect() + print('Func definition: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) + func() + print('Func run free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) + gc.collect() + print('Garbage collect free: {} allocated: {}'.format(gc.mem_free(), gc.mem_alloc())) + print('-----------------------------') + micropython.mem_info(1) + +Methods employed above: + +* ``gc.collect()`` Force a garbage collection. See footnote. +* ``micropython.mem_info()`` Print a summary of RAM utilisation. +* ``gc.mem_free()`` Return the free heap size in bytes. +* ``gc.mem_alloc()`` Return the number of bytes currently allocated. +* ``micropython.mem_info(1)`` Print a table of heap utilisation (detailed below). + +The numbers produced are dependent on the platform, but it can be seen that +declaring the function uses a small amount of RAM in the form of bytecode +emitted by the compiler (the RAM used by the compiler has been reclaimed). +Running the function uses over 10KiB, but on return ``a`` is garbage because it +is out of scope and cannot be referenced. The final ``gc.collect()`` recovers +that memory. + +The final output produced by ``micropython.mem_info(1)`` will vary in detail but +may be interpreted as follows: + +====== ================= +Symbol Meaning +====== ================= + . free block + h head block + = tail block + m marked head block + T tuple + L list + D dict + F float + B byte code + M module +====== ================= + +Each letter represents a single block of memory, a block being 16 bytes. So each +line of the heap dump represents 0x400 bytes or 1KiB of RAM. + +Control of Garbage Collection +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A GC can be demanded at any time by issuing ``gc.collect()``. It is advantageous +to do this at intervals, firstly to pre-empt fragmentation and secondly for +performance. A GC can take several milliseconds but is quicker when there is +little work to do (about 1ms on the Pyboard). An explicit call can minimise that +delay while ensuring it occurs at points in the program when it is acceptable. + +Automatic GC is provoked under the following circumstances. When an attempt at +allocation fails, a GC is performed and the allocation re-tried. Only if this +fails is an exception raised. Secondly an automatic GC will be triggered if the +amount of free RAM falls below a threshold. This threshold can be adapted as +execution progresses: + +.. code:: + + gc.collect() + gc.threshold(gc.mem_free() // 4 + gc.mem_alloc()) + +This will provoke a GC when more than 25% of the currently free heap becomes +occupied. + +In general modules should instantiate data objects at runtime using constructors +or other initialisation functions. The reason is that if this occurs on +initialisation the compiler may be starved of RAM when subsequent modules are +imported. If modules do instantiate data on import then ``gc.collect()`` issued +after the import will ameliorate the problem. + +String Operations +----------------- + +MicroPython handles strings in an efficient manner and understanding this can +help in designing applications to run on microcontrollers. When a module +is compiled, strings which occur multiple times are stored once only, a process +known as string interning. In MicroPython an interned string is known as a ``qstr``. +In a module imported normally that single instance will be located in RAM, but +as described above, in modules frozen as bytecode it will be located in flash. + +String comparisons are also performed efficiently using hashing rather than +character by character. The penalty for using strings rather than integers may +hence be small both in terms of performance and RAM usage - a fact which may +come as a surprise to C programmers. + +Postscript +---------- + +MicroPython passes, returns and (by default) copies objects by reference. A +reference occupies a single machine word so these processes are efficient in +RAM usage and speed. + +Where variables are required whose size is neither a byte nor a machine word +there are standard libraries which can assist in storing these efficiently and +in performing conversions. See the ``array``, ``ustruct`` and ``uctypes`` +modules. + +Footnote: gc.collect() return value +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +On Unix and Windows platforms the ``gc.collect()`` method returns an integer +which signifies the number of distinct memory regions that were reclaimed in the +collection (more precisely, the number of heads that were turned into frees). For +efficiency reasons bare metal ports do not return this value. diff --git a/docs/reference/index.rst b/docs/reference/index.rst index ae8d6530af..7a85fc5cf3 100644 --- a/docs/reference/index.rst +++ b/docs/reference/index.rst @@ -15,6 +15,7 @@ MicroPython are described in the sections here. repl.rst isr_rules.rst speed_python.rst + constrained.rst .. only:: port_pyboard diff --git a/esp8266/Makefile b/esp8266/Makefile index d86fec1808..5f0044df05 100644 --- a/esp8266/Makefile +++ b/esp8266/Makefile @@ -7,19 +7,19 @@ MICROPY_PY_USSL = 1 MICROPY_SSL_AXTLS = 1 MICROPY_PY_BTREE = 1 +FROZEN_DIR = scripts +FROZEN_MPY_DIR = modules + # include py core make definitions include ../py/py.mk MPY_CROSS = ../mpy-cross/mpy-cross MPY_TOOL = ../tools/mpy-tool.py -MAKE_FROZEN = ../tools/make-frozen.py -FROZEN_DIR = scripts -FROZEN_MPY_DIR = modules PORT ?= /dev/ttyACM0 BAUD ?= 115200 FLASH_MODE ?= qio -FLASH_SIZE ?= 8m +FLASH_SIZE ?= detect CROSS_COMPILE = xtensa-lx106-elf- ESP_SDK = $(shell $(CC) -print-sysroot)/usr @@ -66,6 +66,7 @@ SRC_C = \ main.c \ help.c \ esp_mphal.c \ + esp_init_data.c \ gccollect.c \ lexerstr32.c \ uart.c \ @@ -90,7 +91,6 @@ SRC_C = \ modmachine.c \ modonewire.c \ ets_alt_task.c \ - $(BUILD)/frozen.c \ fatfs_port.c \ axtls_helpers.c \ hspi.c \ diff --git a/esp8266/esp8266.ld b/esp8266/esp8266.ld index c726790d38..5fb6f13796 100644 --- a/esp8266/esp8266.ld +++ b/esp8266/esp8266.ld @@ -20,7 +20,7 @@ PHDRS irom0_0_phdr PT_LOAD; } -ENTRY(call_user_start) +ENTRY(firmware_start) EXTERN(_DebugExceptionVector) EXTERN(_DoubleExceptionVector) EXTERN(_KernelExceptionVector) @@ -130,8 +130,10 @@ SECTIONS *stmhal/pybstdio.o(.literal*, .text*) + build/main.o(.literal* .text*) *gccollect.o(.literal* .text*) *gchelper.o(.literal* .text*) + *help.o(.literal* .text*) *lexerstr32.o(.literal* .text*) *utils.o(.literal* .text*) *modpyb.o(.literal*, .text*) @@ -141,6 +143,7 @@ SECTIONS *modpybadc.o(.literal*, .text*) *modpybuart.o(.literal*, .text*) *modpybi2c.o(.literal*, .text*) + *modmachine.o(.literal*, .text*) *modmachinewdt.o(.literal*, .text*) *modpybspi.o(.literal*, .text*) *modpybhspi.o(.literal*, .text*) @@ -199,7 +202,8 @@ SECTIONS *(.entry.text) *(.init.literal) *(.init) - *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.literal .text .literal.* .text.* .iram0.literal .iram0.text .iram0.text.*.literal .iram0.text.*) + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.fini.literal) *(.fini) *(.gnu.version) diff --git a/esp8266/esp_init_data.c b/esp8266/esp_init_data.c new file mode 100644 index 0000000000..b229f751da --- /dev/null +++ b/esp8266/esp_init_data.c @@ -0,0 +1,80 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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 + * 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 +#include "ets_sys.h" +#include "etshal.h" +#include "esp_mphal.h" +#include "user_interface.h" +#include "extmod/misc.h" + +uint32_t SPIRead(uint32_t offset, void *buf, uint32_t len); +uint32_t SPIWrite(uint32_t offset, const void *buf, uint32_t len); +uint32_t SPIEraseSector(int sector); +NORETURN void call_user_start(void); +void ets_printf(const char *fmt, ...); +extern char flashchip; + +static const uint8_t default_init_data[] __attribute__((aligned(4))) = { +0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05, +0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00, +0xf8, 0xf8, 0x52, 0x4e, 0x4a, 0x44, 0x40, 0x38, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, +0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +void firmware_start(void) { + // For SDK 1.5.2, either address has shifted and not mirrored in + // eagle.rom.addr.v6.ld, or extra initial member was added. + SpiFlashChip *flash = (SpiFlashChip*)(&flashchip + 4); + + char buf[128]; + SPIRead(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); + /*for (int i = 0; i < sizeof(buf); i++) { + static char hexf[] = "%x "; + ets_printf(hexf, buf[i]); + }*/ + + bool inited = false; + for (int i = 0; i < sizeof(buf); i++) { + if (buf[i] != 0xff) { + inited = true; + break; + } + } + + if (!inited) { + static char msg[] = "Writing init data\n"; + ets_printf(msg); + SPIRead((uint32_t)&default_init_data - 0x40200000, buf, sizeof(buf)); + SPIWrite(flash->chip_size - 4 * 0x1000, buf, sizeof(buf)); + } + + asm("j call_user_start"); +} diff --git a/esp8266/main.c b/esp8266/main.c index c938dcb30b..033ab7afed 100644 --- a/esp8266/main.c +++ b/esp8266/main.c @@ -141,7 +141,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) { +void MP_FASTCODE(nlr_jump_fail)(void *val) { printf("NLR jump failed\n"); for (;;) { } diff --git a/esp8266/modules/webrepl.py b/esp8266/modules/webrepl.py index da3e70c595..b200f4fc81 100644 --- a/esp8266/modules/webrepl.py +++ b/esp8266/modules/webrepl.py @@ -31,6 +31,10 @@ def setup_conn(port, accept_handler): def accept_conn(listen_sock): global client_s cl, remote_addr = listen_sock.accept() + if uos.dupterm(): + print("\nConcurrent WebREPL connection from", remote_addr, "rejected") + cl.close() + return print("\nWebREPL connection from:", remote_addr) client_s = cl websocket_helper.server_handshake(cl) diff --git a/esp8266/modutime.c b/esp8266/modutime.c index 4b94ace74c..abfe069cc3 100644 --- a/esp8266/modutime.c +++ b/esp8266/modutime.c @@ -38,6 +38,7 @@ #include "modpybrtc.h" #include "timeutils.h" #include "user_interface.h" +#include "extmod/utime_mphal.h" /// \module time - time related functions /// @@ -99,53 +100,6 @@ STATIC mp_obj_t time_mktime(mp_obj_t tuple) { } MP_DEFINE_CONST_FUN_OBJ_1(time_mktime_obj, time_mktime); -/// \function sleep(seconds) -/// Sleep for the given number of seconds. -STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { - #if MICROPY_PY_BUILTINS_FLOAT - mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o)); - #else - mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o)); - #endif - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); - -STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { - mp_hal_delay_ms(mp_obj_get_int(arg)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms); - -STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { - mp_hal_delay_us(mp_obj_get_int(arg)); - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us); - -STATIC mp_obj_t time_ticks_ms(void) { - return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms); - -STATIC mp_obj_t time_ticks_us(void) { - return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_us_obj, time_ticks_us); - -STATIC mp_obj_t time_ticks_cpu(void) { - return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_cpu_obj, time_ticks_cpu); - -STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) { - // we assume that the arguments come from ticks_xx so are small ints - uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in); - uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in); - return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff); - /// \function time() /// Returns the number of seconds, as an integer, since 1/1/2000. STATIC mp_obj_t time_time(void) { @@ -159,13 +113,13 @@ STATIC const mp_map_elem_t time_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&time_ticks_us_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&time_ticks_cpu_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&mp_utime_sleep_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&mp_utime_ticks_diff_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj }, }; diff --git a/esp8266/mpconfigport.h b/esp8266/mpconfigport.h index 19cf9a6792..602b3e9c81 100644 --- a/esp8266/mpconfigport.h +++ b/esp8266/mpconfigport.h @@ -9,6 +9,7 @@ #define MICROPY_ALLOC_PARSE_RULE_INC (8) #define MICROPY_ALLOC_PARSE_RESULT_INC (8) #define MICROPY_ALLOC_PARSE_CHUNK_INIT (64) +#define MICROPY_PERSISTENT_CODE_LOAD (1) #define MICROPY_EMIT_X64 (0) #define MICROPY_EMIT_THUMB (0) #define MICROPY_EMIT_INLINE_THUMB (0) @@ -17,6 +18,7 @@ #define MICROPY_DEBUG_PRINTER_DEST mp_debug_print #define MICROPY_ENABLE_GC (1) #define MICROPY_STACK_CHECK (1) +#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1) #define MICROPY_REPL_EVENT_DRIVEN (0) #define MICROPY_REPL_AUTO_INDENT (1) #define MICROPY_HELPER_REPL (1) @@ -33,6 +35,7 @@ #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_SET (1) #define MICROPY_PY_BUILTINS_SLICE (1) +#define MICROPY_PY_BUILTINS_SLICE_ATTRS (1) #define MICROPY_PY_BUILTINS_PROPERTY (1) #define MICROPY_PY___FILE__ (0) #define MICROPY_PY_GC (1) @@ -49,6 +52,7 @@ #define MICROPY_PY_SYS_MAXSIZE (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_STDFILES (1) +#define MICROPY_PY_SYS_STDIO_BUFFER (1) #define MICROPY_PY_UERRNO (1) #define MICROPY_PY_UBINASCII (1) #define MICROPY_PY_UCTYPES (1) @@ -58,6 +62,7 @@ #define MICROPY_PY_UJSON (1) #define MICROPY_PY_URANDOM (1) #define MICROPY_PY_URE (1) +#define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_UZLIB (1) #define MICROPY_PY_LWIP (1) #define MICROPY_PY_MACHINE (1) @@ -177,4 +182,6 @@ extern const struct _mp_obj_module_t onewire_module; #define MICROPY_HW_MCU_NAME "ESP8266" #define MICROPY_PY_SYS_PLATFORM "esp8266" +#define MP_FASTCODE(n) __attribute__((section(".iram0.text." #n))) n + #define _assert(expr) ((expr) ? (void)0 : __assert_func(__FILE__, __LINE__, __func__, #expr)) diff --git a/extmod/machine_i2c.c b/extmod/machine_i2c.c index d76e5eedd1..e201b23990 100644 --- a/extmod/machine_i2c.c +++ b/extmod/machine_i2c.c @@ -272,7 +272,7 @@ STATIC mp_obj_t machine_i2c_scan(mp_obj_t self_in) { // 7-bit addresses 0b0000xxx and 0b1111xxx are reserved for (int addr = 0x08; addr < 0x78; ++addr) { mp_hal_i2c_start(self); - int ack = mp_hal_i2c_write_byte(self, (addr << 1) | 1); + int ack = mp_hal_i2c_write_byte(self, (addr << 1)); if (ack) { mp_obj_list_append(list, MP_OBJ_NEW_SMALL_INT(addr)); } diff --git a/extmod/modujson.c b/extmod/modujson.c index 0d0781e063..ca4e6df104 100644 --- a/extmod/modujson.c +++ b/extmod/modujson.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) 2014 Damien P. George + * Copyright (c) 2014-2016 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 @@ -28,8 +28,10 @@ #include "py/nlr.h" #include "py/objlist.h" +#include "py/objstringio.h" #include "py/parsenum.h" #include "py/runtime.h" +#include "py/stream.h" #if MICROPY_PY_UJSON @@ -42,7 +44,7 @@ STATIC mp_obj_t mod_ujson_dumps(mp_obj_t obj) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); -// This function implements a simple non-recursive JSON parser. +// The function below implements a simple non-recursive JSON parser. // // The JSON specification is at http://www.ietf.org/rfc/rfc4627.txt // The parser here will parse any valid JSON and return the correct @@ -52,13 +54,35 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_dumps_obj, mod_ujson_dumps); // input is outside it's specs. // // Most of the work is parsing the primitives (null, false, true, numbers, -// strings). It does 1 pass over the input string and so is easily extended to -// being able to parse from a non-seekable stream. It tries to be fast and +// strings). It does 1 pass over the input stream. It tries to be fast and // small in code size, while not using more RAM than necessary. -STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { - mp_uint_t len; - const char *s = mp_obj_str_get_data(obj, &len); - const char *top = s + len; + +typedef struct _ujson_stream_t { + mp_obj_t stream_obj; + mp_uint_t (*read)(mp_obj_t obj, void *buf, mp_uint_t size, int *errcode); + int errcode; + byte cur; +} ujson_stream_t; + +#define S_EOF (0) // null is not allowed in json stream so is ok as EOF marker +#define S_END(s) ((s).cur == S_EOF) +#define S_CUR(s) ((s).cur) +#define S_NEXT(s) (ujson_stream_next(&(s))) + +STATIC byte ujson_stream_next(ujson_stream_t *s) { + mp_uint_t ret = s->read(s->stream_obj, &s->cur, 1, &s->errcode); + if (s->errcode != 0) { + mp_raise_OSError(s->errcode); + } + if (ret == 0) { + s->cur = S_EOF; + } + return s->cur; +} + +STATIC mp_obj_t mod_ujson_load(mp_obj_t stream_obj) { + const mp_stream_p_t *stream_p = mp_get_stream_raise(stream_obj, MP_STREAM_OP_READ); + ujson_stream_t s = {stream_obj, stream_p->read, 0, 0}; vstr_t vstr; vstr_init(&vstr, 8); mp_obj_list_t stack; // we use a list as a simple stack for nested JSON @@ -67,41 +91,43 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { mp_obj_t stack_top = MP_OBJ_NULL; mp_obj_type_t *stack_top_type = NULL; mp_obj_t stack_key = MP_OBJ_NULL; + S_NEXT(s); for (;;) { cont: - if (s == top) { + if (S_END(s)) { break; } mp_obj_t next = MP_OBJ_NULL; bool enter = false; - switch (*s) { + byte cur = S_CUR(s); + S_NEXT(s); + switch (cur) { case ',': case ':': case ' ': case '\t': case '\n': case '\r': - s += 1; goto cont; case 'n': - if (s + 3 < top && s[1] == 'u' && s[2] == 'l' && s[3] == 'l') { - s += 4; + if (S_CUR(s) == 'u' && S_NEXT(s) == 'l' && S_NEXT(s) == 'l') { + S_NEXT(s); next = mp_const_none; } else { goto fail; } break; case 'f': - if (s + 4 < top && s[1] == 'a' && s[2] == 'l' && s[3] == 's' && s[4] == 'e') { - s += 5; + if (S_CUR(s) == 'a' && S_NEXT(s) == 'l' && S_NEXT(s) == 's' && S_NEXT(s) == 'e') { + S_NEXT(s); next = mp_const_false; } else { goto fail; } break; case 't': - if (s + 3 < top && s[1] == 'r' && s[2] == 'u' && s[3] == 'e') { - s += 4; + if (S_CUR(s) == 'r' && S_NEXT(s) == 'u' && S_NEXT(s) == 'e') { + S_NEXT(s); next = mp_const_true; } else { goto fail; @@ -109,11 +135,10 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { break; case '"': vstr_reset(&vstr); - for (s++; s < top && *s != '"';) { - byte c = *s; + for (; !S_END(s) && S_CUR(s) != '"';) { + byte c = S_CUR(s); if (c == '\\') { - s++; - c = *s; + c = S_NEXT(s); switch (c) { case 'b': c = 0x08; break; case 'f': c = 0x0c; break; @@ -121,10 +146,9 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { case 'r': c = 0x0d; break; case 't': c = 0x09; break; case 'u': { - if (s + 4 >= top) { goto fail; } mp_uint_t num = 0; for (int i = 0; i < 4; i++) { - c = (*++s | 0x20) - '0'; + c = (S_NEXT(s) | 0x20) - '0'; if (c > 9) { c -= ('a' - ('9' + 1)); } @@ -137,27 +161,29 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { } vstr_add_byte(&vstr, c); str_cont: - s++; + S_NEXT(s); } - if (s == top) { + if (S_END(s)) { goto fail; } - s++; + S_NEXT(s); next = mp_obj_new_str(vstr.buf, vstr.len, false); break; case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { bool flt = false; vstr_reset(&vstr); - for (; s < top; s++) { - if (*s == '.' || *s == 'E' || *s == 'e') { + for (;;) { + vstr_add_byte(&vstr, cur); + cur = S_CUR(s); + if (cur == '.' || cur == 'E' || cur == 'e') { flt = true; - } else if (*s == '-' || unichar_isdigit(*s)) { + } else if (cur == '-' || unichar_isdigit(cur)) { // pass } else { break; } - vstr_add_byte(&vstr, *s); + S_NEXT(s); } if (flt) { next = mp_parse_num_decimal(vstr.buf, vstr.len, false, false, NULL); @@ -169,16 +195,13 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { case '[': next = mp_obj_new_list(0, NULL); enter = true; - s += 1; break; case '{': next = mp_obj_new_dict(0); enter = true; - s += 1; break; case '}': case ']': { - s += 1; if (stack_top == MP_OBJ_NULL) { // no object at all goto fail; @@ -231,10 +254,10 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { } success: // eat trailing whitespace - while (s < top && unichar_isspace(*s)) { - s++; + while (unichar_isspace(S_CUR(s))) { + S_NEXT(s); } - if (s < top) { + if (!S_END(s)) { // unexpected chars goto fail; } @@ -248,11 +271,21 @@ STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { fail: nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "syntax error in JSON")); } +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_load_obj, mod_ujson_load); + +STATIC mp_obj_t mod_ujson_loads(mp_obj_t obj) { + mp_uint_t len; + const char *buf = mp_obj_str_get_data(obj, &len); + vstr_t vstr = {len, len, (char*)buf, true}; + mp_obj_stringio_t sio = {{&mp_type_stringio}, &vstr, 0}; + return mod_ujson_load(MP_OBJ_FROM_PTR(&sio)); +} STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_ujson_loads_obj, mod_ujson_loads); STATIC const mp_rom_map_elem_t mp_module_ujson_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ujson) }, { MP_ROM_QSTR(MP_QSTR_dumps), MP_ROM_PTR(&mod_ujson_dumps_obj) }, + { MP_ROM_QSTR(MP_QSTR_load), MP_ROM_PTR(&mod_ujson_load_obj) }, { MP_ROM_QSTR(MP_QSTR_loads), MP_ROM_PTR(&mod_ujson_loads_obj) }, }; diff --git a/extmod/modussl_mbedtls.c b/extmod/modussl_mbedtls.c index ddb7ba0fe7..5a7a745d82 100644 --- a/extmod/modussl_mbedtls.c +++ b/extmod/modussl_mbedtls.c @@ -215,6 +215,16 @@ STATIC mp_uint_t socket_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in return MP_STREAM_ERROR; } +STATIC mp_obj_t socket_setblocking(mp_obj_t self_in, mp_obj_t flag_in) { + // Currently supports only blocking mode + (void)self_in; + if (!mp_obj_is_true(flag_in)) { + mp_not_implemented(""); + } + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(socket_setblocking_obj, socket_setblocking); + STATIC mp_obj_t socket_close(mp_obj_t self_in) { mp_obj_ssl_socket_t *self = MP_OBJ_TO_PTR(self_in); @@ -236,6 +246,7 @@ STATIC const mp_rom_map_elem_t ussl_socket_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_readinto), MP_ROM_PTR(&mp_stream_readinto_obj) }, { MP_ROM_QSTR(MP_QSTR_readline), MP_ROM_PTR(&mp_stream_unbuffered_readline_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&mp_stream_write_obj) }, + { MP_ROM_QSTR(MP_QSTR_setblocking), MP_ROM_PTR(&socket_setblocking_obj) }, { MP_ROM_QSTR(MP_QSTR_close), MP_ROM_PTR(&socket_close_obj) }, }; diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c new file mode 100644 index 0000000000..3ecdc94469 --- /dev/null +++ b/extmod/utime_mphal.c @@ -0,0 +1,89 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * Copyright (c) 2016 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 + * 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" +#if MICROPY_PY_UTIME_MP_HAL + +#include + +#include "py/obj.h" +#include "py/mphal.h" +#include "py/smallint.h" +#include "extmod/utime_mphal.h" + +STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { + #if MICROPY_PY_BUILTINS_FLOAT + mp_hal_delay_ms(1000 * mp_obj_get_float(seconds_o)); + #else + mp_hal_delay_ms(1000 * mp_obj_get_int(seconds_o)); + #endif + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_obj, time_sleep); + +STATIC mp_obj_t time_sleep_ms(mp_obj_t arg) { + mp_int_t ms = mp_obj_get_int(arg); + if (ms > 0) { + mp_hal_delay_ms(ms); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_ms_obj, time_sleep_ms); + +STATIC mp_obj_t time_sleep_us(mp_obj_t arg) { + mp_int_t us = mp_obj_get_int(arg); + if (us > 0) { + mp_hal_delay_us(us); + } + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_1(mp_utime_sleep_us_obj, time_sleep_us); + +STATIC mp_obj_t time_ticks_ms(void) { + return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_ms() & MP_SMALL_INT_POSITIVE_MASK); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_ms_obj, time_ticks_ms); + +STATIC mp_obj_t time_ticks_us(void) { + return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_us() & MP_SMALL_INT_POSITIVE_MASK); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj, time_ticks_us); + +STATIC mp_obj_t time_ticks_cpu(void) { + return MP_OBJ_NEW_SMALL_INT(mp_hal_ticks_cpu() & MP_SMALL_INT_POSITIVE_MASK); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj, time_ticks_cpu); + +STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) { + // we assume that the arguments come from ticks_xx so are small ints + uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in); + uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in); + return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK); +} +MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj, time_ticks_diff); + +#endif // MICROPY_PY_UTIME_MP_HAL diff --git a/extmod/utime_mphal.h b/extmod/utime_mphal.h new file mode 100644 index 0000000000..4f2395a090 --- /dev/null +++ b/extmod/utime_mphal.h @@ -0,0 +1,36 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 Damien P. George + * Copyright (c) 2016 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 + * 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/obj.h" + +MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_ms_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_sleep_us_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_ms_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_us_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_cpu_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_utime_ticks_diff_obj); diff --git a/extmod/uzlib/tinf.h b/extmod/uzlib/tinf.h index 3545bbd883..106203a099 100644 --- a/extmod/uzlib/tinf.h +++ b/extmod/uzlib/tinf.h @@ -32,6 +32,7 @@ extern "C" { #define TINF_DONE 1 #define TINF_DATA_ERROR (-3) #define TINF_CHKSUM_ERROR (-4) +#define TINF_DICT_ERROR (-5) /* checksum types */ #define TINF_CHKSUM_NONE 0 diff --git a/extmod/uzlib/tinflate.c b/extmod/uzlib/tinflate.c index 0e53f7f072..58850eb4a2 100644 --- a/extmod/uzlib/tinflate.c +++ b/extmod/uzlib/tinflate.c @@ -361,6 +361,9 @@ static int tinf_inflate_block_data(TINF_DATA *d, TINF_TREE *lt, TINF_TREE *dt) /* possibly get more bits from distance code */ offs = tinf_read_bits(d, dist_bits[dist], dist_base[dist]); if (d->dict_ring) { + if (offs > d->dict_size) { + return TINF_DICT_ERROR; + } d->lzOff = d->dict_idx - offs; if (d->lzOff < 0) { d->lzOff += d->dict_size; diff --git a/extmod/vfs_fat.c b/extmod/vfs_fat.c index 3a17533e43..6e827fc664 100644 --- a/extmod/vfs_fat.c +++ b/extmod/vfs_fat.c @@ -31,6 +31,7 @@ #include #include "py/nlr.h" #include "py/runtime.h" +#include "py/mperrno.h" #include "lib/fatfs/ff.h" #include "lib/fatfs/diskio.h" #include "extmod/vfs_fat_file.h" @@ -76,24 +77,42 @@ STATIC mp_obj_t fat_vfs_listdir_func(size_t n_args, const mp_obj_t *args) { } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(fat_vfs_listdir_obj, 1, 2, fat_vfs_listdir_func); -STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { - (void)vfs_in; +STATIC mp_obj_t fat_vfs_remove_internal(mp_obj_t path_in, mp_int_t attr) { const char *path = mp_obj_str_get_str(path_in); - // TODO check that path is actually a file before trying to unlink it - FRESULT res = f_unlink(path); - if (res == FR_OK) { - return mp_const_none; - } else { + + FILINFO fno; +#if _USE_LFN + fno.lfname = NULL; + fno.lfsize = 0; +#endif + FRESULT res = f_stat(path, &fno); + + if (res != FR_OK) { mp_raise_OSError(fresult_to_errno_table[res]); } + + // check if path is a file or directory + if ((fno.fattrib & AM_DIR) == attr) { + res = f_unlink(path); + + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } + return mp_const_none; + } else { + mp_raise_OSError(attr ? MP_ENOTDIR : MP_EISDIR); + } +} + +STATIC mp_obj_t fat_vfs_remove(mp_obj_t vfs_in, mp_obj_t path_in) { + (void)vfs_in; + return fat_vfs_remove_internal(path_in, 0); // 0 == file attribute } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_remove_obj, fat_vfs_remove); STATIC mp_obj_t fat_vfs_rmdir(mp_obj_t vfs_in, mp_obj_t path_in) { - // TODO: Currently just redirects to fat_vfs_remove(), which are - // backed by the same underlying FatFs function. Should at least - // check that path is actually a dir. - return fat_vfs_remove(vfs_in, path_in); + (void) vfs_in; + return fat_vfs_remove_internal(path_in, AM_DIR); } STATIC MP_DEFINE_CONST_FUN_OBJ_2(fat_vfs_rmdir_obj, fat_vfs_rmdir); diff --git a/extmod/vfs_fat_file.c b/extmod/vfs_fat_file.c index ecc9ed70f9..e269ef593c 100644 --- a/extmod/vfs_fat_file.c +++ b/extmod/vfs_fat_file.c @@ -110,14 +110,20 @@ STATIC mp_uint_t file_obj_write(mp_obj_t self_in, const void *buf, mp_uint_t siz STATIC mp_obj_t file_obj_flush(mp_obj_t self_in) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); - f_sync(&self->fp); + FRESULT res = f_sync(&self->fp); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(file_obj_flush_obj, file_obj_flush); STATIC mp_obj_t file_obj_close(mp_obj_t self_in) { pyb_file_obj_t *self = MP_OBJ_TO_PTR(self_in); - f_close(&self->fp); + FRESULT res = f_close(&self->fp); + if (res != FR_OK) { + mp_raise_OSError(fresult_to_errno_table[res]); + } return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close); diff --git a/lib/utils/pyexec.c b/lib/utils/pyexec.c index bc540199d9..f9bbf68a16 100644 --- a/lib/utils/pyexec.c +++ b/lib/utils/pyexec.c @@ -45,6 +45,7 @@ #include "genhdr/mpversion.h" pyexec_mode_kind_t pyexec_mode_kind = PYEXEC_MODE_FRIENDLY_REPL; +int pyexec_system_exit = 0; STATIC bool repl_display_debugging_info = 0; #define EXEC_FLAG_PRINT_EOF (1) @@ -61,6 +62,9 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind, int ret = 0; uint32_t start = 0; + // by default a SystemExit exception returns 0 + pyexec_system_exit = 0; + nlr_buf_t nlr; if (nlr_push(&nlr) == 0) { mp_obj_t module_fun; @@ -99,7 +103,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind, // check for SystemExit if (mp_obj_is_subclass_fast(mp_obj_get_type((mp_obj_t)nlr.ret_val), &mp_type_SystemExit)) { // at the moment, the value of SystemExit is unused - ret = PYEXEC_FORCED_EXIT; + ret = pyexec_system_exit; } else { mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val); ret = 0; @@ -148,7 +152,7 @@ STATIC int pyexec_raw_repl_process_char(int c); STATIC int pyexec_friendly_repl_process_char(int c); void pyexec_event_repl_init(void) { - MP_STATE_VM(repl_line) = vstr_new_size(32); + MP_STATE_VM(repl_line) = vstr_new(32); repl.cont_line = false; readline_init(MP_STATE_VM(repl_line), ">>> "); if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { diff --git a/lib/utils/pyexec.h b/lib/utils/pyexec.h index e0f62440e0..ae69a195e7 100644 --- a/lib/utils/pyexec.h +++ b/lib/utils/pyexec.h @@ -33,6 +33,11 @@ typedef enum { extern pyexec_mode_kind_t pyexec_mode_kind; +// Set this to the value (eg PYEXEC_FORCED_EXIT) that will be propagated through +// the pyexec functions if a SystemExit exception is raised by the running code. +// It will reset to 0 at the start of each execution (eg each REPL entry). +extern int pyexec_system_exit; + #define PYEXEC_FORCED_EXIT (0x100) #define PYEXEC_SWITCH_MODE (0x200) diff --git a/py/argcheck.c b/py/argcheck.c index a6c769ee82..8cef10b165 100644 --- a/py/argcheck.c +++ b/py/argcheck.c @@ -37,8 +37,7 @@ void mp_arg_check_num(size_t n_args, size_t n_kw, size_t n_args_min, size_t n_ar if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { mp_arg_error_terse_mismatch(); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "function does not take keyword arguments")); + mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments"); } } @@ -116,8 +115,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n mp_arg_error_terse_mismatch(); } else { // TODO better error message - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "extra positional arguments given")); + mp_raise_msg(&mp_type_TypeError, "extra positional arguments given"); } } if (kws_found < kws->used) { @@ -125,8 +123,7 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n mp_arg_error_terse_mismatch(); } else { // TODO better error message - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "extra keyword arguments given")); + mp_raise_msg(&mp_type_TypeError, "extra keyword arguments given"); } } } @@ -139,7 +136,7 @@ void mp_arg_parse_all_kw_array(size_t n_pos, size_t n_kw, const mp_obj_t *args, #if MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE || _MSC_VER NORETURN void mp_arg_error_terse_mismatch(void) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "argument num/types mismatch")); + mp_raise_msg(&mp_type_TypeError, "argument num/types mismatch"); } #endif diff --git a/py/bc.c b/py/bc.c index e5abea2440..07de08fc36 100644 --- a/py/bc.c +++ b/py/bc.c @@ -185,7 +185,7 @@ void mp_setup_code_state(mp_code_state_t *code_state, mp_obj_fun_bc_t *self, siz } // Didn't find name match with positional args if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "function does not take keyword arguments")); + mp_raise_msg(&mp_type_TypeError, "function does not take keyword arguments"); } mp_obj_dict_store(dict, kwargs[2 * i], kwargs[2 * i + 1]); continue2:; @@ -234,8 +234,7 @@ continue2:; } else { // no keyword arguments given if (n_kwonly_args != 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "function missing keyword-only argument")); + mp_raise_msg(&mp_type_TypeError, "function missing keyword-only argument"); } if ((scope_flags & MP_SCOPE_FLAG_VARKEYWORDS) != 0) { *var_pos_kw_args = mp_obj_new_dict(0); diff --git a/py/builtinevex.c b/py/builtinevex.c index 74c43b1768..636f869300 100644 --- a/py/builtinevex.c +++ b/py/builtinevex.c @@ -95,7 +95,7 @@ STATIC mp_obj_t mp_builtin_compile(size_t n_args, const mp_obj_t *args) { case MP_QSTR_exec: parse_input_kind = MP_PARSE_FILE_INPUT; break; case MP_QSTR_eval: parse_input_kind = MP_PARSE_EVAL_INPUT; break; default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad compile mode")); + mp_raise_msg(&mp_type_ValueError, "bad compile mode"); } mp_obj_code_t *code = m_new_obj(mp_obj_code_t); diff --git a/py/builtinimport.c b/py/builtinimport.c index e4199f25d7..e72eaf4724 100644 --- a/py/builtinimport.c +++ b/py/builtinimport.c @@ -138,7 +138,7 @@ STATIC void do_load_from_lexer(mp_obj_t module_obj, mp_lexer_t *lex, const char if (lex == NULL) { // we verified the file exists using stat, but lexer could still fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found")); + mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%s'", fname)); @@ -340,7 +340,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("Warning: no dots in current module name and level>0\n"); p = this_name + this_name_l; } else if (level != -1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "Invalid relative import")); + mp_raise_msg(&mp_type_ImportError, "invalid relative import"); } uint new_mod_l = (mod_len == 0 ? (size_t)(p - this_name) : (size_t)(p - this_name) + 1 + mod_len); @@ -355,7 +355,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { DEBUG_printf("Resolved base name for relative import: '%s'\n", qstr_str(new_mod_q)); if (new_mod_q == MP_QSTR_) { // CPython raises SystemError - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "cannot perform relative import")); + mp_raise_msg(&mp_type_ImportError, "cannot perform relative import"); } module_name = MP_OBJ_NEW_QSTR(new_mod_q); mod_str = new_mod; @@ -425,7 +425,7 @@ mp_obj_t mp_builtin___import__(size_t n_args, const mp_obj_t *args) { #endif // couldn't find the file, so fail if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ImportError, "module not found")); + mp_raise_msg(&mp_type_ImportError, "module not found"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ImportError, "no module named '%q'", mod_name)); diff --git a/py/compile.c b/py/compile.c index 0ea8a3c150..f84d5e2145 100644 --- a/py/compile.c +++ b/py/compile.c @@ -2723,15 +2723,8 @@ STATIC void compile_node(compiler_t *comp, mp_parse_node_t pn) { mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn; EMIT_ARG(set_source_line, pns->source_line); compile_function_t f = compile_function[MP_PARSE_NODE_STRUCT_KIND(pns)]; - if (f == NULL) { -#if MICROPY_DEBUG_PRINTERS - printf("node %u cannot be compiled\n", (uint)MP_PARSE_NODE_STRUCT_KIND(pns)); - mp_parse_node_print(pn, 0); -#endif - compile_syntax_error(comp, pn, "internal compiler error"); - } else { - f(comp, pns); - } + assert(f != NULL); + f(comp, pns); } } @@ -2836,12 +2829,10 @@ STATIC void compile_scope_func_annotations(compiler_t *comp, mp_parse_node_t pn) // no annotation return; } - } else if (MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star) { + } else { + assert(MP_PARSE_NODE_STRUCT_KIND(pns) == PN_typedargslist_dbl_star); // double star with possible annotation // fallthrough - } else { - // no annotation - return; } mp_parse_node_t pn_annotation = pns->nodes[1]; diff --git a/py/emitglue.c b/py/emitglue.c index 2bfc4ad82b..c81387fd4d 100644 --- a/py/emitglue.c +++ b/py/emitglue.c @@ -425,7 +425,7 @@ mp_raw_code_t *mp_raw_code_load_file(const char *filename) { return rc; } -#elif defined(__thumb2__) || defined(__thumb__) +#elif defined(__thumb2__) || defined(__thumb__) || defined(__xtensa__) // fatfs file reader (assume thumb2 arch uses fatfs...) #include "lib/fatfs/ff.h" diff --git a/py/lexer.c b/py/lexer.c index b2c9c5ff78..4a7c8f580a 100644 --- a/py/lexer.c +++ b/py/lexer.c @@ -343,7 +343,6 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) { lex->tok_kind = MP_TOKEN_NEWLINE; mp_uint_t num_spaces = lex->column - 1; - lex->emit_dent = 0; if (num_spaces == indent_top(lex)) { } else if (num_spaces > indent_top(lex)) { indent_push(lex, num_spaces); @@ -359,16 +358,7 @@ STATIC void mp_lexer_next_token_into(mp_lexer_t *lex, bool first_token) { } } else if (is_end(lex)) { - if (indent_top(lex) > 0) { - lex->tok_kind = MP_TOKEN_NEWLINE; - lex->emit_dent = 0; - while (indent_top(lex) > 0) { - indent_pop(lex); - lex->emit_dent -= 1; - } - } else { - lex->tok_kind = MP_TOKEN_END; - } + lex->tok_kind = MP_TOKEN_END; } else if (is_char_or(lex, '\'', '\"') || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"')) diff --git a/py/misc.h b/py/misc.h index 3ed227a352..e60665e591 100644 --- a/py/misc.h +++ b/py/misc.h @@ -151,8 +151,7 @@ void vstr_init_fixed_buf(vstr_t *vstr, size_t alloc, char *buf); struct _mp_print_t; void vstr_init_print(vstr_t *vstr, size_t alloc, struct _mp_print_t *print); void vstr_clear(vstr_t *vstr); -vstr_t *vstr_new(void); -vstr_t *vstr_new_size(size_t alloc); +vstr_t *vstr_new(size_t alloc); void vstr_free(vstr_t *vstr); static inline void vstr_reset(vstr_t *vstr) { vstr->len = 0; } static inline char *vstr_str(vstr_t *vstr) { return vstr->buf; } diff --git a/py/modbuiltins.c b/py/modbuiltins.c index 29f84d6c25..57e52efa52 100644 --- a/py/modbuiltins.c +++ b/py/modbuiltins.c @@ -178,7 +178,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { str[3] = (c & 0x3F) | 0x80; len = 4; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)")); + mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(0x110000)"); } return mp_obj_new_str(str, len, true); #else @@ -187,7 +187,7 @@ STATIC mp_obj_t mp_builtin_chr(mp_obj_t o_in) { char str[1] = {ord}; return mp_obj_new_str(str, 1, true); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "chr() arg not in range(256)")); + mp_raise_msg(&mp_type_ValueError, "chr() arg not in range(256)"); } #endif } @@ -286,7 +286,7 @@ STATIC mp_obj_t mp_builtin_min_max(size_t n_args, const mp_obj_t *args, mp_map_t if (default_elem != NULL) { best_obj = default_elem->value; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "arg is an empty sequence")); + mp_raise_msg(&mp_type_ValueError, "arg is an empty sequence"); } } return best_obj; @@ -507,8 +507,7 @@ MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_sum_obj, 1, 2, mp_builtin_sum); STATIC mp_obj_t mp_builtin_sorted(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs) { if (n_args > 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "must use keyword argument for key function")); + mp_raise_msg(&mp_type_TypeError, "must use keyword argument for key function"); } mp_obj_t self = mp_type_list.make_new(&mp_type_list, 1, 0, args); mp_obj_list_sort(1, &self, kwargs); diff --git a/py/modmicropython.c b/py/modmicropython.c index f7d74db2e0..675d169cc4 100644 --- a/py/modmicropython.c +++ b/py/modmicropython.c @@ -34,6 +34,16 @@ // Various builtins specific to MicroPython runtime, // living in micropython module +STATIC mp_obj_t mp_micropython_opt_level(size_t n_args, const mp_obj_t *args) { + if (n_args == 0) { + return MP_OBJ_NEW_SMALL_INT(MP_STATE_VM(mp_optimise_value)); + } else { + MP_STATE_VM(mp_optimise_value) = mp_obj_get_int(args[0]); + return mp_const_none; + } +} +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_micropython_opt_level_obj, 0, 1, mp_micropython_opt_level); + #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS @@ -121,6 +131,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_alloc_emergency_exception_buf_obj, mp_alloc_ STATIC const mp_rom_map_elem_t mp_module_micropython_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_micropython) }, { MP_ROM_QSTR(MP_QSTR_const), MP_ROM_PTR(&mp_identity_obj) }, + { MP_ROM_QSTR(MP_QSTR_opt_level), MP_ROM_PTR(&mp_micropython_opt_level_obj) }, #if MICROPY_PY_MICROPYTHON_MEM_INFO #if MICROPY_MEM_STATS { MP_ROM_QSTR(MP_QSTR_mem_total), MP_ROM_PTR(&mp_micropython_mem_total_obj) }, diff --git a/py/modthread.c b/py/modthread.c index c358cdf9ed..6f55281adc 100644 --- a/py/modthread.c +++ b/py/modthread.c @@ -239,7 +239,7 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args) } else { // positional and keyword arguments if (mp_obj_get_type(args[2]) != &mp_type_dict) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "expecting a dict for keyword args")); + mp_raise_msg(&mp_type_TypeError, "expecting a dict for keyword args"); } mp_map_t *map = &((mp_obj_dict_t*)MP_OBJ_TO_PTR(args[2]))->map; th_args = m_new_obj_var(thread_entry_args_t, mp_obj_t, pos_args_len + 2 * map->used); diff --git a/py/mpconfig.h b/py/mpconfig.h index e33a41f7a0..dcdaffe0f4 100644 --- a/py/mpconfig.h +++ b/py/mpconfig.h @@ -860,6 +860,12 @@ typedef double mp_float_t; #define MICROPY_PY_UERRNO (0) #endif +// Whether to provide "utime" module functions implementation +// in terms of mp_hal_* functions. +#ifndef MICROPY_PY_UTIME_MP_HAL +#define MICROPY_PY_UTIME_MP_HAL (0) +#endif + // Whether to provide "_thread" module #ifndef MICROPY_PY_THREAD #define MICROPY_PY_THREAD (0) diff --git a/py/mphal.h b/py/mphal.h index 54a45b0240..8d5654f9e3 100644 --- a/py/mphal.h +++ b/py/mphal.h @@ -66,6 +66,10 @@ mp_uint_t mp_hal_ticks_ms(void); mp_uint_t mp_hal_ticks_us(void); #endif +#ifndef mp_hal_ticks_cpu +mp_uint_t mp_hal_ticks_cpu(void); +#endif + // If port HAL didn't define its own pin API, use generic // "virtual pin" API from the core. #ifndef mp_hal_pin_obj_t diff --git a/py/mpprint.c b/py/mpprint.c index 97ea33ad2a..9ad0f3f9a0 100644 --- a/py/mpprint.c +++ b/py/mpprint.c @@ -252,8 +252,8 @@ int mp_print_mp_int(const mp_print_t *print, mp_obj_t x, int base, int base_char // enough, a dynamic one will be allocated. char stack_buf[sizeof(mp_int_t) * 4]; char *buf = stack_buf; - mp_uint_t buf_size = sizeof(stack_buf); - mp_uint_t fmt_size = 0; + size_t buf_size = sizeof(stack_buf); + size_t fmt_size = 0; char *str; if (prec > 1) { diff --git a/py/mpz.c b/py/mpz.c index bb76479569..cceb079cd3 100644 --- a/py/mpz.c +++ b/py/mpz.c @@ -645,18 +645,6 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, const mpz_dig_t *den #define MIN_ALLOC (2) -STATIC const uint8_t log_base2_floor[] = { - 0, - 0, 1, 1, 2, - 2, 2, 2, 3, - 3, 3, 3, 3, - 3, 3, 3, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 4, - 4, 4, 4, 5 -}; - void mpz_init_zero(mpz_t *z) { z->neg = 0; z->fixed_dig = 0; @@ -734,11 +722,9 @@ STATIC void mpz_need_dig(mpz_t *z, mp_uint_t need) { } if (z->dig == NULL || z->alloc < need) { - if (z->fixed_dig) { - // cannot reallocate fixed buffers - assert(0); - return; - } + // if z has fixed digit buffer there's not much we can do as the caller will + // be expecting a buffer with at least "need" bytes (but it shouldn't happen) + assert(!z->fixed_dig); z->dig = m_renew(mpz_dig_t, z->dig, z->alloc, need); z->alloc = need; } @@ -1497,13 +1483,10 @@ mpz_t *mpz_lcm(const mpz_t *z1, const mpz_t *z2) { quo * rhs + rem = lhs 0 <= rem < rhs can have lhs, rhs the same + assumes rhs != 0 (undefined behaviour if it is) */ void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs) { - if (rhs->len == 0) { - mpz_set_from_int(dest_quo, 0); - mpz_set_from_int(dest_rem, 0); - return; - } + assert(!mpz_is_zero(rhs)); mpz_need_dig(dest_quo, lhs->len + 1); // +1 necessary? memset(dest_quo->dig, 0, (lhs->len + 1) * sizeof(mpz_dig_t)); @@ -1657,18 +1640,6 @@ mp_float_t mpz_as_float(const mpz_t *i) { } #endif -mp_uint_t mpz_as_str_size(const mpz_t *i, mp_uint_t base, const char *prefix, char comma) { - if (base < 2 || base > 32) { - return 0; - } - - mp_uint_t num_digits = i->len * DIG_SIZE / log_base2_floor[base] + 1; - mp_uint_t num_commas = comma ? num_digits / 3: 0; - mp_uint_t prefix_len = prefix ? strlen(prefix) : 0; - - return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte -} - #if 0 this function is unused char *mpz_as_str(const mpz_t *i, mp_uint_t base) { @@ -1678,7 +1649,7 @@ char *mpz_as_str(const mpz_t *i, mp_uint_t base) { } #endif -// assumes enough space as calculated by mpz_as_str_size +// assumes enough space as calculated by mp_int_format_size // returns length of string, not including null byte mp_uint_t mpz_as_str_inpl(const mpz_t *i, mp_uint_t base, const char *prefix, char base_char, char comma, char *str) { if (str == NULL || base < 2 || base > 32) { diff --git a/py/mpz.h b/py/mpz.h index 63ac772ffd..55ef3e15ff 100644 --- a/py/mpz.h +++ b/py/mpz.h @@ -127,6 +127,7 @@ void mpz_or_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_xor_inpl(mpz_t *dest, const mpz_t *lhs, const mpz_t *rhs); void mpz_divmod_inpl(mpz_t *dest_quo, mpz_t *dest_rem, const mpz_t *lhs, const mpz_t *rhs); +static inline size_t mpz_max_num_bits(const mpz_t *z) { return z->len * MPZ_DIG_SIZE; } mp_int_t mpz_hash(const mpz_t *z); bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value); bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value); diff --git a/py/obj.c b/py/obj.c index d6ce3dae6a..72b7a216bc 100644 --- a/py/obj.c +++ b/py/obj.c @@ -233,8 +233,7 @@ mp_int_t mp_obj_get_int(mp_const_obj_t arg) { return mp_obj_int_get_checked(arg); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to int")); + mp_raise_msg(&mp_type_TypeError, "can't convert to int"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to int", mp_obj_get_type_str(arg))); @@ -282,8 +281,7 @@ mp_float_t mp_obj_get_float(mp_obj_t arg) { return mp_obj_float_get(arg); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to float")); + mp_raise_msg(&mp_type_TypeError, "can't convert to float"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to float", mp_obj_get_type_str(arg))); @@ -312,8 +310,7 @@ void mp_obj_get_complex(mp_obj_t arg, mp_float_t *real, mp_float_t *imag) { mp_obj_complex_get(arg, real, imag); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "can't convert to complex")); + mp_raise_msg(&mp_type_TypeError, "can't convert to complex"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "can't convert %s to complex", mp_obj_get_type_str(arg))); @@ -331,8 +328,7 @@ void mp_obj_get_array(mp_obj_t o, mp_uint_t *len, mp_obj_t **items) { mp_obj_list_get(o, len, items); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "expected tuple/list")); + mp_raise_msg(&mp_type_TypeError, "expected tuple/list"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object '%s' is not a tuple or list", mp_obj_get_type_str(o))); @@ -346,8 +342,7 @@ void mp_obj_get_array_fixed_n(mp_obj_t o, mp_uint_t len, mp_obj_t **items) { mp_obj_get_array(o, &seq_len, items); if (seq_len != len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "tuple/list has wrong length")); + mp_raise_msg(&mp_type_ValueError, "tuple/list has wrong length"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "requested length %d but object has length %d", (int)len, (int)seq_len)); @@ -362,8 +357,7 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, i = MP_OBJ_SMALL_INT_VALUE(index); } else if (!mp_obj_get_int_maybe(index, &i)) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "indices must be integers")); + mp_raise_msg(&mp_type_TypeError, "indices must be integers"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "%q indices must be integers, not %s", @@ -383,7 +377,7 @@ mp_uint_t mp_get_index(const mp_obj_type_t *type, mp_uint_t len, mp_obj_t index, } else { if (i < 0 || (mp_uint_t)i >= len) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "index out of range")); + mp_raise_msg(&mp_type_IndexError, "index out of range"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_IndexError, "%q index out of range", type->name)); @@ -416,8 +410,7 @@ mp_obj_t mp_obj_len(mp_obj_t o_in) { mp_obj_t len = mp_obj_len_maybe(o_in); if (len == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object has no len")); + mp_raise_msg(&mp_type_TypeError, "object has no len"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "object of type '%s' has no len()", mp_obj_get_type_str(o_in))); @@ -458,8 +451,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { } if (value == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object does not support item deletion")); + mp_raise_msg(&mp_type_TypeError, "object does not support item deletion"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item deletion", mp_obj_get_type_str(base))); @@ -474,8 +466,7 @@ mp_obj_t mp_obj_subscr(mp_obj_t base, mp_obj_t index, mp_obj_t value) { } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object does not support item assignment")); + mp_raise_msg(&mp_type_TypeError, "object does not support item assignment"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object does not support item assignment", mp_obj_get_type_str(base))); @@ -504,7 +495,7 @@ bool mp_get_buffer(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { void mp_get_buffer_raise(mp_obj_t obj, mp_buffer_info_t *bufinfo, mp_uint_t flags) { if (!mp_get_buffer(obj, bufinfo, flags)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "object with buffer protocol required")); + mp_raise_msg(&mp_type_TypeError, "object with buffer protocol required"); } } diff --git a/py/objarray.c b/py/objarray.c index 2cd0fef6b6..8e1d32f0f4 100644 --- a/py/objarray.c +++ b/py/objarray.c @@ -95,7 +95,7 @@ STATIC void array_print(const mp_print_t *print, mp_obj_t o_in, mp_print_kind_t STATIC mp_obj_array_t *array_new(char typecode, mp_uint_t n) { int typecode_size = mp_binary_get_size('@', typecode, NULL); if (typecode_size == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "bad typecode")); + mp_raise_msg(&mp_type_ValueError, "bad typecode"); } mp_obj_array_t *o = m_new_obj(mp_obj_array_t); #if MICROPY_PY_BUILTINS_BYTEARRAY && MICROPY_PY_ARRAY @@ -395,7 +395,7 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value mp_obj_array_t *src_slice = MP_OBJ_TO_PTR(value); if (item_sz != mp_binary_get_size('@', src_slice->typecode & TYPECODE_MASK, NULL)) { compat_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "lhs and rhs should be compatible")); + mp_raise_msg(&mp_type_ValueError, "lhs and rhs should be compatible"); } src_len = src_slice->len; src_items = src_slice->items; diff --git a/py/objcomplex.c b/py/objcomplex.c index 5da655eb3c..96be25255c 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -197,7 +197,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t case MP_BINARY_OP_INPLACE_TRUE_DIVIDE: if (rhs_imag == 0) { if (rhs_real == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "complex division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "complex division by zero"); } lhs_real /= rhs_real; lhs_imag /= rhs_real; @@ -226,7 +226,7 @@ mp_obj_t mp_obj_complex_binary_op(mp_uint_t op, mp_float_t lhs_real, mp_float_t lhs_real = 1; rhs_real = 0; } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power")); + mp_raise_msg(&mp_type_ZeroDivisionError, "0.0 to a complex power"); } } else { mp_float_t ln1 = MICROPY_FLOAT_C_FUN(log)(abs1); diff --git a/py/objdict.c b/py/objdict.c index 7a74557dc1..4942d37791 100644 --- a/py/objdict.c +++ b/py/objdict.c @@ -162,7 +162,7 @@ mp_obj_t mp_obj_dict_get(mp_obj_t self_in, mp_obj_t index) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } @@ -178,7 +178,7 @@ STATIC mp_obj_t dict_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) { mp_obj_dict_t *self = MP_OBJ_TO_PTR(self_in); mp_map_elem_t *elem = mp_map_lookup(&self->map, index, MP_MAP_LOOKUP); if (elem == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, index)); } else { return elem->value; } @@ -250,15 +250,16 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(dict_copy_obj, dict_copy); // this is a classmethod STATIC mp_obj_t dict_fromkeys(size_t n_args, const mp_obj_t *args) { mp_obj_t iter = mp_getiter(args[1]); - mp_obj_t len = mp_obj_len_maybe(iter); mp_obj_t value = mp_const_none; mp_obj_t next = MP_OBJ_NULL; - mp_obj_t self_out; if (n_args > 2) { value = args[2]; } + // optimisation to allocate result based on len of argument + mp_obj_t self_out; + mp_obj_t len = mp_obj_len_maybe(args[1]); if (len == MP_OBJ_NULL) { /* object's type doesn't have a __len__ slot */ self_out = mp_obj_new_dict(0); @@ -282,7 +283,7 @@ STATIC mp_obj_t dict_get_helper(mp_map_t *self, mp_obj_t key, mp_obj_t deflt, mp if (elem == NULL || elem->value == MP_OBJ_NULL) { if (deflt == MP_OBJ_NULL) { if (lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "")); + nlr_raise(mp_obj_new_exception_arg1(&mp_type_KeyError, key)); } else { value = mp_const_none; } @@ -342,7 +343,7 @@ STATIC mp_obj_t dict_popitem(mp_obj_t self_in) { mp_uint_t cur = 0; mp_map_elem_t *next = dict_iter_next(self, &cur); if (next == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "popitem(): dictionary is empty")); + mp_raise_msg(&mp_type_KeyError, "popitem(): dictionary is empty"); } self->map.used--; mp_obj_t items[] = {next->key, next->value}; @@ -384,9 +385,7 @@ STATIC mp_obj_t dict_update(size_t n_args, const mp_obj_t *args, mp_map_t *kwarg if (key == MP_OBJ_STOP_ITERATION || value == MP_OBJ_STOP_ITERATION || stop != MP_OBJ_STOP_ITERATION) { - nlr_raise(mp_obj_new_exception_msg( - &mp_type_ValueError, - "dictionary update sequence has the wrong length")); + mp_raise_msg(&mp_type_ValueError, "dictionary update sequence has the wrong length"); } else { mp_map_lookup(&self->map, key, MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)->value = value; } diff --git a/py/objfloat.c b/py/objfloat.c index 85b8b13861..73d07feac8 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -198,7 +198,7 @@ mp_obj_t mp_obj_float_binary_op(mp_uint_t op, mp_float_t lhs_val, mp_obj_t rhs_i case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: if (rhs_val == 0) { zero_division_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } // Python specs require that x == (x//y)*y + (x%y) so we must // call divmod to compute the correct floor division, which diff --git a/py/objgenerator.c b/py/objgenerator.c index 8c32a36496..cbef9fea3d 100644 --- a/py/objgenerator.c +++ b/py/objgenerator.c @@ -105,7 +105,7 @@ mp_vm_return_kind_t mp_obj_gen_resume(mp_obj_t self_in, mp_obj_t send_value, mp_ } if (self->code_state.sp == self->code_state.state - 1) { if (send_value != mp_const_none) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator")); + mp_raise_msg(&mp_type_TypeError, "can't send non-None value to a just-started generator"); } } else { *self->code_state.sp = send_value; @@ -157,7 +157,7 @@ STATIC mp_obj_t gen_resume_and_raise(mp_obj_t self_in, mp_obj_t send_value, mp_o case MP_VM_RETURN_YIELD: if (throw_value != MP_OBJ_NULL && mp_obj_is_subclass_fast(MP_OBJ_FROM_PTR(mp_obj_get_type(throw_value)), MP_OBJ_FROM_PTR(&mp_type_GeneratorExit))) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); + mp_raise_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"); } return ret; @@ -209,7 +209,7 @@ STATIC mp_obj_t gen_instance_close(mp_obj_t self_in) { mp_obj_t ret; switch (mp_obj_gen_resume(self_in, mp_const_none, MP_OBJ_FROM_PTR(&mp_const_GeneratorExit_obj), &ret)) { case MP_VM_RETURN_YIELD: - nlr_raise(mp_obj_new_exception_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit")); + mp_raise_msg(&mp_type_RuntimeError, "generator ignored GeneratorExit"); // Swallow StopIteration & GeneratorExit (== successful close), and re-raise any other case MP_VM_RETURN_EXCEPTION: diff --git a/py/objint.c b/py/objint.c index 9f948a1455..f8988d6c94 100644 --- a/py/objint.c +++ b/py/objint.c @@ -133,8 +133,8 @@ void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t // enough, a dynamic one will be allocated. char stack_buf[sizeof(mp_int_t) * 4]; char *buf = stack_buf; - mp_uint_t buf_size = sizeof(stack_buf); - mp_uint_t fmt_size; + size_t buf_size = sizeof(stack_buf); + size_t fmt_size; char *str = mp_obj_int_formatted(&buf, &buf_size, &fmt_size, self_in, 10, NULL, '\0', '\0'); mp_print_str(print, str); @@ -162,14 +162,14 @@ STATIC const uint8_t log_base2_floor[] = { 4, 4, 4, 5 }; -STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) { +size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma) { if (base < 2 || base > 32) { return 0; } - uint num_digits = sizeof(fmt_int_t) * 8 / log_base2_floor[base] + 1; - uint num_commas = comma ? num_digits / 3: 0; - uint prefix_len = prefix ? strlen(prefix) : 0; + size_t num_digits = num_bits / log_base2_floor[base] + 1; + size_t num_commas = comma ? num_digits / 3 : 0; + size_t prefix_len = prefix ? strlen(prefix) : 0; return num_digits + num_commas + prefix_len + 2; // +1 for sign, +1 for null byte } @@ -180,7 +180,7 @@ STATIC uint int_as_str_size_formatted(uint base, const char *prefix, char comma) // // The resulting formatted string will be returned from this function and the // formatted size will be in *fmt_size. -char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { fmt_int_t num; if (MP_OBJ_IS_SMALL_INT(self_in)) { @@ -211,7 +211,7 @@ char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, sign = '-'; } - uint needed_size = int_as_str_size_formatted(base, prefix, comma); + size_t needed_size = mp_int_format_size(sizeof(fmt_int_t) * 8, base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; @@ -294,19 +294,19 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { // This is called only with strings whose value doesn't fit in SMALL_INT mp_obj_t mp_obj_new_int_from_str_len(const char **str, mp_uint_t len, bool neg, mp_uint_t base) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "long int not supported in this build")); + mp_raise_msg(&mp_type_OverflowError, "long int not supported in this build"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ll(long long val) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } // This is called when an integer larger than a SMALL_INT is needed (although val might still fit in a SMALL_INT) mp_obj_t mp_obj_new_int_from_ull(unsigned long long val) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } @@ -316,7 +316,7 @@ mp_obj_t mp_obj_new_int_from_uint(mp_uint_t value) { if ((value & ~MP_SMALL_INT_POSITIVE_MASK) == 0) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } @@ -342,7 +342,7 @@ mp_obj_t mp_obj_new_int(mp_int_t value) { if (MP_SMALL_INT_FITS(value)) { return MP_OBJ_NEW_SMALL_INT(value); } - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "small int overflow")); + mp_raise_msg(&mp_type_OverflowError, "small int overflow"); return mp_const_none; } diff --git a/py/objint.h b/py/objint.h index c79eb874a9..6e627f1bd7 100644 --- a/py/objint.h +++ b/py/objint.h @@ -50,13 +50,15 @@ typedef enum { mp_fp_as_int_class_t mp_classify_fp_as_int(mp_float_t val); #endif // MICROPY_PY_BUILTINS_FLOAT +size_t mp_int_format_size(size_t num_bits, int base, const char *prefix, char comma); + void mp_obj_int_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind); -char *mp_obj_int_formatted(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); -char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma); mp_int_t mp_obj_int_hash(mp_obj_t self_in); -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf); +void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf); int mp_obj_int_sign(mp_obj_t self_in); mp_obj_t mp_obj_int_abs(mp_obj_t self_in); mp_obj_t mp_obj_int_unary_op(mp_uint_t op, mp_obj_t o_in); diff --git a/py/objint_longlong.c b/py/objint_longlong.c index f10e46447b..b051cfbe64 100644 --- a/py/objint_longlong.c +++ b/py/objint_longlong.c @@ -53,7 +53,7 @@ const mp_obj_int_t mp_maxsize_obj = {{&mp_type_int}, MP_SSIZE_MAX}; #endif -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf) { +void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); mp_obj_int_t *self = self_in; long long val = self->val; diff --git a/py/objint_mpz.c b/py/objint_mpz.c index 3a30eb9d9b..0a1d68598d 100644 --- a/py/objint_mpz.c +++ b/py/objint_mpz.c @@ -90,12 +90,12 @@ STATIC mp_obj_int_t *mp_obj_int_new_mpz(void) { // formatted size will be in *fmt_size. // // This particular routine should only be called for the mpz representation of the int. -char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_size, mp_const_obj_t self_in, +char *mp_obj_int_formatted_impl(char **buf, size_t *buf_size, size_t *fmt_size, mp_const_obj_t self_in, int base, const char *prefix, char base_char, char comma) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); const mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); - mp_uint_t needed_size = mpz_as_str_size(&self->mpz, base, prefix, comma); + size_t needed_size = mp_int_format_size(mpz_max_num_bits(&self->mpz), base, prefix, comma); if (needed_size > *buf_size) { *buf = m_new(char, needed_size); *buf_size = needed_size; @@ -107,7 +107,7 @@ char *mp_obj_int_formatted_impl(char **buf, mp_uint_t *buf_size, mp_uint_t *fmt_ return str; } -void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, mp_uint_t len, byte *buf) { +void mp_obj_int_to_bytes_impl(mp_obj_t self_in, bool big_endian, size_t len, byte *buf) { assert(MP_OBJ_IS_TYPE(self_in, &mp_type_int)); mp_obj_int_t *self = MP_OBJ_TO_PTR(self_in); mpz_as_bytes(&self->mpz, big_endian, len, buf); @@ -234,8 +234,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_INPLACE_FLOOR_DIVIDE: { if (mpz_is_zero(zrhs)) { zero_division_error: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, - "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } mpz_t rem; mpz_init_zero(&rem); mpz_divmod_inpl(&res->mpz, &rem, zlhs, zrhs); @@ -272,7 +271,7 @@ mp_obj_t mp_obj_int_binary_op(mp_uint_t op, mp_obj_t lhs_in, mp_obj_t rhs_in) { case MP_BINARY_OP_INPLACE_RSHIFT: { mp_int_t irhs = mp_obj_int_get_checked(rhs_in); if (irhs < 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } if (op == MP_BINARY_OP_LSHIFT || op == MP_BINARY_OP_INPLACE_LSHIFT) { mpz_shl_inpl(&res->mpz, zlhs, irhs); @@ -398,7 +397,7 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) { return value; } else { // overflow - nlr_raise(mp_obj_new_exception_msg(&mp_type_OverflowError, "overflow converting long int to machine word")); + mp_raise_msg(&mp_type_OverflowError, "overflow converting long int to machine word"); } } } diff --git a/py/objlist.c b/py/objlist.c index b5e8b99651..6d4a20a507 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -266,7 +266,7 @@ STATIC mp_obj_t list_pop(size_t n_args, const mp_obj_t *args) { mp_check_self(MP_OBJ_IS_TYPE(args[0], &mp_type_list)); mp_obj_list_t *self = MP_OBJ_TO_PTR(args[0]); if (self->len == 0) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_IndexError, "pop from empty list")); + mp_raise_msg(&mp_type_IndexError, "pop from empty list"); } mp_uint_t index = mp_get_index(self->base.type, self->len, n_args == 1 ? MP_OBJ_NEW_SMALL_INT(-1) : args[1], false); mp_obj_t ret = self->items[index]; diff --git a/py/objnamedtuple.c b/py/objnamedtuple.c index 38cda1ad75..18931a16c2 100644 --- a/py/objnamedtuple.c +++ b/py/objnamedtuple.c @@ -73,7 +73,7 @@ STATIC void namedtuple_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest) { } else { // delete/store attribute // provide more detailed error message than we'd get by just returning - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "can't set attribute")); + mp_raise_msg(&mp_type_AttributeError, "can't set attribute"); } } diff --git a/py/objobject.c b/py/objobject.c index bba6f053e6..b33dc491c4 100644 --- a/py/objobject.c +++ b/py/objobject.c @@ -50,8 +50,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(object___init___obj, object___init__); STATIC mp_obj_t object___new__(mp_obj_t cls) { if (!MP_OBJ_IS_TYPE(cls, &mp_type_type) || !mp_obj_is_instance_type((mp_obj_type_t*)MP_OBJ_TO_PTR(cls))) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "__new__ arg must be a user-type")); + mp_raise_msg(&mp_type_TypeError, "__new__ arg must be a user-type"); } mp_obj_t o = MP_OBJ_SENTINEL; mp_obj_t res = mp_obj_instance_make_new(MP_OBJ_TO_PTR(cls), 1, 0, &o); diff --git a/py/objset.c b/py/objset.c index 6b6f95f9b2..fc124fcd8c 100644 --- a/py/objset.c +++ b/py/objset.c @@ -68,7 +68,7 @@ STATIC void check_set(mp_obj_t o) { if (MP_OBJ_IS_TYPE(o, &mp_type_frozenset)) { // Mutable method called on frozenset; emulate CPython behavior, eg: // AttributeError: 'frozenset' object has no attribute 'add' - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "'frozenset' has no such attribute")); + mp_raise_msg(&mp_type_AttributeError, "'frozenset' has no such attribute"); } #endif mp_check_self(MP_OBJ_IS_TYPE(o, &mp_type_set)); @@ -389,7 +389,7 @@ STATIC mp_obj_t set_pop(mp_obj_t self_in) { mp_obj_set_t *self = MP_OBJ_TO_PTR(self_in); mp_obj_t obj = mp_set_remove_first(&self->set); if (obj == MP_OBJ_NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_KeyError, "pop from an empty set")); + mp_raise_msg(&mp_type_KeyError, "pop from an empty set"); } return obj; } diff --git a/py/objstringio.c b/py/objstringio.c index eb0cc4eb36..a430fca3b7 100644 --- a/py/objstringio.c +++ b/py/objstringio.c @@ -30,22 +30,16 @@ #include "py/nlr.h" #include "py/objstr.h" +#include "py/objstringio.h" #include "py/runtime.h" #include "py/stream.h" #if MICROPY_PY_IO -typedef struct _mp_obj_stringio_t { - mp_obj_base_t base; - vstr_t *vstr; - // StringIO has single pointer used for both reading and writing - mp_uint_t pos; -} mp_obj_stringio_t; - #if MICROPY_CPYTHON_COMPAT STATIC void check_stringio_is_open(const mp_obj_stringio_t *o) { if (o->vstr == NULL) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "I/O operation on closed file")); + mp_raise_msg(&mp_type_ValueError, "I/O operation on closed file"); } } #else @@ -156,7 +150,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stringio___exit___obj, 4, 4, stringio STATIC mp_obj_stringio_t *stringio_new(const mp_obj_type_t *type) { mp_obj_stringio_t *o = m_new_obj(mp_obj_stringio_t); o->base.type = type; - o->vstr = vstr_new(); + o->vstr = vstr_new(16); o->pos = 0; return o; } diff --git a/py/objstringio.h b/py/objstringio.h new file mode 100644 index 0000000000..853bfb11b7 --- /dev/null +++ b/py/objstringio.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 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. + */ +#ifndef MICROPY_INCLUDED_PY_OBJSTRINGIO_H +#define MICROPY_INCLUDED_PY_OBJSTRINGIO_H + +#include "py/obj.h" + +typedef struct _mp_obj_stringio_t { + mp_obj_base_t base; + vstr_t *vstr; + // StringIO has single pointer used for both reading and writing + mp_uint_t pos; +} mp_obj_stringio_t; + +#endif // MICROPY_INCLUDED_PY_OBJSTRINGIO_H diff --git a/py/objtype.c b/py/objtype.c index 907308a757..8b46c54001 100644 --- a/py/objtype.c +++ b/py/objtype.c @@ -311,8 +311,7 @@ mp_obj_t mp_obj_instance_make_new(const mp_obj_type_t *self, size_t n_args, size } if (init_ret != mp_const_none) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "__init__() should return None")); + mp_raise_msg(&mp_type_TypeError, "__init__() should return None"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "__init__() should return None, not '%s'", mp_obj_get_type_str(init_ret))); @@ -508,7 +507,7 @@ STATIC void mp_obj_instance_load_attr(mp_obj_t self_in, qstr attr, mp_obj_t *des // the code. const mp_obj_t *proxy = mp_obj_property_get(member); if (proxy[0] == mp_const_none) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, "unreadable attribute")); + mp_raise_msg(&mp_type_AttributeError, "unreadable attribute"); } else { dest[0] = mp_call_function_n_kw(proxy[0], 1, 0, &self_in); } @@ -710,8 +709,7 @@ mp_obj_t mp_obj_instance_call(mp_obj_t self_in, size_t n_args, size_t n_kw, cons mp_obj_t call = mp_obj_instance_get_call(self_in); if (call == MP_OBJ_NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not callable")); + mp_raise_msg(&mp_type_TypeError, "object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(self_in))); @@ -793,7 +791,7 @@ STATIC mp_obj_t type_make_new(const mp_obj_type_t *type_in, size_t n_args, size_ return mp_obj_new_type(mp_obj_str_get_qstr(args[0]), args[1], args[2]); default: - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "type takes 1 or 3 arguments")); + mp_raise_msg(&mp_type_TypeError, "type takes 1 or 3 arguments"); } } @@ -804,7 +802,7 @@ STATIC mp_obj_t type_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp if (self->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "cannot create instance")); + mp_raise_msg(&mp_type_TypeError, "cannot create instance"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "cannot create '%q' instances", self->name)); @@ -892,8 +890,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) // TODO: Verify with CPy, tested on function type if (t->make_new == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "type is not an acceptable base type")); + mp_raise_msg(&mp_type_TypeError, "type is not an acceptable base type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "type '%q' is not an acceptable base type", t->name)); @@ -927,7 +924,7 @@ mp_obj_t mp_obj_new_type(qstr name, mp_obj_t bases_tuple, mp_obj_t locals_dict) const mp_obj_type_t *native_base; uint num_native_bases = instance_count_native_bases(o, &native_base); if (num_native_bases > 1) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict")); + mp_raise_msg(&mp_type_TypeError, "multiple bases have instance lay-out conflict"); } mp_map_t *locals_map = &o->locals_dict->map; @@ -1074,7 +1071,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { } else if (MP_OBJ_IS_TYPE(classinfo, &mp_type_tuple)) { mp_obj_tuple_get(classinfo, &len, &items); } else { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes")); + mp_raise_msg(&mp_type_TypeError, "issubclass() arg 2 must be a class or a tuple of classes"); } for (uint i = 0; i < len; i++) { @@ -1088,7 +1085,7 @@ STATIC mp_obj_t mp_obj_is_subclass(mp_obj_t object, mp_obj_t classinfo) { STATIC mp_obj_t mp_builtin_issubclass(mp_obj_t object, mp_obj_t classinfo) { if (!MP_OBJ_IS_TYPE(object, &mp_type_type)) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class")); + mp_raise_msg(&mp_type_TypeError, "issubclass() arg 1 must be a class"); } return mp_obj_is_subclass(object, classinfo); } diff --git a/py/parsenum.c b/py/parsenum.c index 83a6abd202..1010ad3055 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -27,7 +27,7 @@ #include #include -#include "py/nlr.h" +#include "py/runtime.h" #include "py/parsenumbase.h" #include "py/parsenum.h" #include "py/smallint.h" @@ -55,7 +55,7 @@ mp_obj_t mp_parse_num_integer(const char *restrict str_, size_t len, int base, m // check radix base if ((base != 0 && base < 2) || base > 36) { // this won't be reached if lex!=NULL - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36")); + mp_raise_msg(&mp_type_ValueError, "int() arg 2 must be >= 2 and <= 36"); } // skip leading space diff --git a/py/py.mk b/py/py.mk index 741ad52f98..ab07bbbdec 100644 --- a/py/py.mk +++ b/py/py.mk @@ -229,6 +229,7 @@ PY_O_BASENAME = \ ../extmod/vfs_fat_file.o \ ../extmod/vfs_fat_lexer.o \ ../extmod/vfs_fat_misc.o \ + ../extmod/utime_mphal.o \ ../extmod/moduos_dupterm.o \ ../lib/embed/abort_.o \ ../lib/utils/printf.o \ @@ -236,6 +237,10 @@ PY_O_BASENAME = \ # prepend the build destination prefix to the py object files PY_O = $(addprefix $(PY_BUILD)/, $(PY_O_BASENAME)) +ifneq ($(FROZEN_DIR),) +PY_O += $(BUILD)/$(BUILD)/frozen.o +endif + # Sources that may contain qstrings SRC_QSTR_IGNORE = nlr% emitnx% emitnthumb% emitnarm% SRC_QSTR = $(SRC_MOD) $(addprefix py/,$(filter-out $(SRC_QSTR_IGNORE),$(PY_O_BASENAME:.o=.c)) emitnative.c) diff --git a/py/runtime.c b/py/runtime.c index 003c9f8b44..6eda77ee9c 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -138,8 +138,7 @@ mp_obj_t mp_load_global(qstr qst) { elem = mp_map_lookup((mp_map_t*)&mp_module_builtins_globals.map, MP_OBJ_NEW_QSTR(qst), MP_MAP_LOOKUP); if (elem == NULL) { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_NameError, - "name not defined")); + mp_raise_msg(&mp_type_NameError, "name not defined"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_NameError, "name '%q' is not defined", qst)); @@ -230,8 +229,7 @@ mp_obj_t mp_unary_op(mp_uint_t op, mp_obj_t arg) { } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "unsupported type for operator")); + mp_raise_msg(&mp_type_TypeError, "unsupported type for operator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported type for %q: '%s'", @@ -323,7 +321,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_INPLACE_LSHIFT: { if (rhs_val < 0) { // negative shift not allowed - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } else if (rhs_val >= (mp_int_t)BITS_PER_WORD || lhs_val > (MP_SMALL_INT_MAX >> rhs_val) || lhs_val < (MP_SMALL_INT_MIN >> rhs_val)) { // left-shift will overflow, so use higher precision integer lhs = mp_obj_new_int_from_ll(lhs_val); @@ -338,7 +336,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { case MP_BINARY_OP_INPLACE_RSHIFT: if (rhs_val < 0) { // negative shift not allowed - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); + mp_raise_msg(&mp_type_ValueError, "negative shift count"); } else { // standard precision is enough for right-shift if (rhs_val >= (mp_int_t)BITS_PER_WORD) { @@ -414,7 +412,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { lhs = mp_obj_new_float(lhs_val); goto generic_binary_op; #else - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative power with no float support")); + mp_raise_msg(&mp_type_ValueError, "negative power with no float support"); #endif } else { mp_int_t ans = 1; @@ -515,8 +513,7 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) { } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not iterable")); + mp_raise_msg(&mp_type_TypeError, "object not iterable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(rhs))); @@ -538,8 +535,7 @@ generic_binary_op: unsupported_op: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "unsupported type for operator")); + mp_raise_msg(&mp_type_TypeError, "unsupported type for operator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "unsupported types for %q: '%s', '%s'", @@ -547,7 +543,7 @@ unsupported_op: } zero_division: - nlr_raise(mp_obj_new_exception_msg(&mp_type_ZeroDivisionError, "division by zero")); + mp_raise_msg(&mp_type_ZeroDivisionError, "division by zero"); } mp_obj_t mp_call_function_0(mp_obj_t fun) { @@ -581,8 +577,7 @@ mp_obj_t mp_call_function_n_kw(mp_obj_t fun_in, mp_uint_t n_args, mp_uint_t n_kw } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not callable")); + mp_raise_msg(&mp_type_TypeError, "object not callable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not callable", mp_obj_get_type_str(fun_in))); @@ -813,16 +808,14 @@ void mp_unpack_sequence(mp_obj_t seq_in, mp_uint_t num, mp_obj_t *items) { too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); } too_long: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "too many values to unpack (expected %d)", (int)num)); @@ -888,8 +881,7 @@ void mp_unpack_ex(mp_obj_t seq_in, mp_uint_t num_in, mp_obj_t *items) { too_short: if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, - "wrong number of values to unpack")); + mp_raise_msg(&mp_type_ValueError, "wrong number of values to unpack"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "need more than %d values to unpack", (int)seq_len)); @@ -928,8 +920,7 @@ STATIC mp_obj_t checked_fun_call(mp_obj_t self_in, size_t n_args, size_t n_kw, c const mp_obj_type_t *arg0_type = mp_obj_get_type(args[0]); if (arg0_type != self->type) { if (MICROPY_ERROR_REPORTING != MICROPY_ERROR_REPORTING_DETAILED) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "argument has wrong type")); + mp_raise_msg(&mp_type_TypeError, "argument has wrong type"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "argument should be a '%q' not a '%q'", self->type->name, arg0_type->name)); @@ -1045,8 +1036,7 @@ void mp_load_method(mp_obj_t base, qstr attr, mp_obj_t *dest) { if (dest[0] == MP_OBJ_NULL) { // no attribute/method called attr if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, - "no such attribute")); + mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { // following CPython, we give a more detailed error message for type objects if (MP_OBJ_IS_TYPE(base, &mp_type_type)) { @@ -1074,8 +1064,7 @@ void mp_store_attr(mp_obj_t base, qstr attr, mp_obj_t value) { } } if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_AttributeError, - "no such attribute")); + mp_raise_msg(&mp_type_AttributeError, "no such attribute"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AttributeError, "'%s' object has no attribute '%q'", @@ -1105,8 +1094,7 @@ mp_obj_t mp_getiter(mp_obj_t o_in) { // object not iterable if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not iterable")); + mp_raise_msg(&mp_type_TypeError, "object not iterable"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not iterable", mp_obj_get_type_str(o_in))); @@ -1128,8 +1116,7 @@ mp_obj_t mp_iternext_allow_raise(mp_obj_t o_in) { return mp_call_method_n_kw(0, 0, dest); } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not an iterator")); + mp_raise_msg(&mp_type_TypeError, "object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in))); @@ -1165,8 +1152,7 @@ mp_obj_t mp_iternext(mp_obj_t o_in) { } } else { if (MICROPY_ERROR_REPORTING == MICROPY_ERROR_REPORTING_TERSE) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, - "object not an iterator")); + mp_raise_msg(&mp_type_TypeError, "object not an iterator"); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_TypeError, "'%s' object is not an iterator", mp_obj_get_type_str(o_in))); @@ -1384,8 +1370,7 @@ void *m_malloc_fail(size_t num_bytes) { // dummy #if MICROPY_ENABLE_GC } else if (gc_is_locked()) { - nlr_raise(mp_obj_new_exception_msg(&mp_type_MemoryError, - "memory allocation failed, heap is locked")); + mp_raise_msg(&mp_type_MemoryError, "memory allocation failed, heap is locked"); #endif } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, diff --git a/py/sequence.c b/py/sequence.c index 239f1b2cc5..0acdd25be0 100644 --- a/py/sequence.c +++ b/py/sequence.c @@ -235,7 +235,7 @@ mp_obj_t mp_seq_index_obj(const mp_obj_t *items, mp_uint_t len, mp_uint_t n_args } } - nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "object not in sequence")); + mp_raise_msg(&mp_type_ValueError, "object not in sequence"); } mp_obj_t mp_seq_count_obj(const mp_obj_t *items, mp_uint_t len, mp_obj_t value) { diff --git a/py/stream.c b/py/stream.c index 5610faf748..cc8a63ac2e 100644 --- a/py/stream.c +++ b/py/stream.c @@ -101,7 +101,7 @@ const mp_stream_p_t *mp_get_stream_raise(mp_obj_t self_in, int flags) { || ((flags & MP_STREAM_OP_WRITE) && stream_p->write == NULL) || ((flags & MP_STREAM_OP_IOCTL) && stream_p->ioctl == NULL)) { // CPython: io.UnsupportedOperation, OSError subclass - nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "stream operation not supported")); + mp_raise_msg(&mp_type_OSError, "stream operation not supported"); } return stream_p; } diff --git a/py/vstr.c b/py/vstr.c index 5096475f10..6a91552b5a 100644 --- a/py/vstr.c +++ b/py/vstr.c @@ -74,20 +74,8 @@ void vstr_clear(vstr_t *vstr) { vstr->buf = NULL; } -vstr_t *vstr_new(void) { +vstr_t *vstr_new(size_t alloc) { vstr_t *vstr = m_new_obj(vstr_t); - if (vstr == NULL) { - return NULL; - } - vstr_init(vstr, 16); - return vstr; -} - -vstr_t *vstr_new_size(size_t alloc) { - vstr_t *vstr = m_new_obj(vstr_t); - if (vstr == NULL) { - return NULL; - } vstr_init(vstr, alloc); return vstr; } diff --git a/qemu-arm/Makefile b/qemu-arm/Makefile index 31ba6baa26..9159f97e54 100644 --- a/qemu-arm/Makefile +++ b/qemu-arm/Makefile @@ -40,19 +40,28 @@ SRC_C = \ SRC_TEST_C = \ test_main.c \ +STM_SRC_C = $(addprefix stmhal/,\ + pybstdio.c \ + ) + SRC_S = \ OBJ = OBJ += $(PY_O) OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) OBJ += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ_TEST = OBJ_TEST += $(PY_O) OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_TEST_C:.c=.o)) OBJ_TEST += $(addprefix $(BUILD)/, $(SRC_S:.s=.o)) +OBJ_TEST += $(addprefix $(BUILD)/, $(STM_SRC_C:.c=.o)) OBJ_TEST += $(BUILD)/tinytest.o +# List of sources for qstr extraction +SRC_QSTR += $(SRC_C) $(STM_SRC_C) + all: run run: $(BUILD)/firmware.elf diff --git a/qemu-arm/memory.h b/qemu-arm/memory.h new file mode 100644 index 0000000000..f3777b0e39 --- /dev/null +++ b/qemu-arm/memory.h @@ -0,0 +1,2 @@ +// this is needed for extmod/crypto-algorithms/sha256.c +#include diff --git a/qemu-arm/mpconfigport.h b/qemu-arm/mpconfigport.h index 1f23148c2a..b8806405bc 100644 --- a/qemu-arm/mpconfigport.h +++ b/qemu-arm/mpconfigport.h @@ -20,9 +20,18 @@ #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) -#define MICROPY_PY_IO (0) +#define MICROPY_PY_IO (1) #define MICROPY_PY_SYS_EXIT (1) #define MICROPY_PY_SYS_MAXSIZE (1) +#define MICROPY_PY_UERRNO (1) +#define MICROPY_PY_UBINASCII (1) +#define MICROPY_PY_URANDOM (1) +#define MICROPY_PY_UCTYPES (1) +#define MICROPY_PY_UZLIB (1) +#define MICROPY_PY_UJSON (1) +#define MICROPY_PY_URE (1) +#define MICROPY_PY_UHEAPQ (1) +#define MICROPY_PY_UHASHLIB (1) #define MICROPY_USE_INTERNAL_PRINTF (0) // type definitions for the specific machine diff --git a/qemu-arm/mphalport.h b/qemu-arm/mphalport.h index 4bd8276f34..d996402ae4 100644 --- a/qemu-arm/mphalport.h +++ b/qemu-arm/mphalport.h @@ -1 +1,2 @@ -// empty file +#define mp_hal_stdin_rx_chr() (0) +#define mp_hal_stdout_tx_strn_cooked(s, l) write(1, (s), (l)) diff --git a/stmhal/Makefile b/stmhal/Makefile index 7be0f28fe1..e2e1dc6a15 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -274,16 +274,9 @@ $(PY_BUILD)/mpprint.o: COPT += -Os all: $(BUILD)/firmware.dfu $(BUILD)/firmware.hex ifneq ($(FROZEN_DIR),) +# To use frozen source modules, put your .py files in a subdirectory (eg scripts/) +# and then invoke make with FROZEN_DIR=scripts (be sure to build from scratch). CFLAGS += -DMICROPY_MODULE_FROZEN_STR -OBJ += $(BUILD)/frozen-files.o -MAKE_FROZEN = ../tools/make-frozen.py - -$(BUILD)/frozen-files.o: $(BUILD)/frozen-files.c - $(call compile_c) - -$(BUILD)/frozen-files.c: $(shell find $(FROZEN_DIR) -type f) - @$(ECHO) "Creating $@" - $(Q)$(PYTHON) $(MAKE_FROZEN) $(FROZEN_DIR) > $@ endif ifneq ($(FROZEN_MPY_DIR),) diff --git a/stmhal/accel.c b/stmhal/accel.c index e75f1c9942..827aa46e7c 100644 --- a/stmhal/accel.c +++ b/stmhal/accel.c @@ -57,15 +57,9 @@ #define MMA_AXIS_SIGNED_VALUE(i) (((i) & 0x3f) | ((i) & 0x20 ? (~0x1f) : 0)) void accel_init(void) { - GPIO_InitTypeDef GPIO_InitStructure; - // PB5 is connected to AVDD; pull high to enable MMA accel device - GPIO_clear_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn off AVDD - GPIO_InitStructure.Pin = MICROPY_HW_MMA_AVDD_PIN.pin_mask; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Speed = GPIO_SPEED_LOW; - GPIO_InitStructure.Pull = GPIO_NOPULL; - HAL_GPIO_Init(MICROPY_HW_MMA_AVDD_PIN.gpio, &GPIO_InitStructure); + mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off AVDD + mp_hal_pin_output(&MICROPY_HW_MMA_AVDD_PIN); } STATIC void accel_start(void) { @@ -81,9 +75,9 @@ STATIC void accel_start(void) { i2c_init(&I2CHandle1); // turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again - GPIO_clear_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn off + mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off HAL_Delay(30); - GPIO_set_pin(MICROPY_HW_MMA_AVDD_PIN.gpio, MICROPY_HW_MMA_AVDD_PIN.pin_mask); // turn on + mp_hal_pin_high(&MICROPY_HW_MMA_AVDD_PIN); // turn on HAL_Delay(30); HAL_StatusTypeDef status; diff --git a/stmhal/boards/ESPRUINO_PICO/mpconfigboard.h b/stmhal/boards/ESPRUINO_PICO/mpconfigboard.h index 885cedc893..d18abb908c 100644 --- a/stmhal/boards/ESPRUINO_PICO/mpconfigboard.h +++ b/stmhal/boards/ESPRUINO_PICO/mpconfigboard.h @@ -66,6 +66,5 @@ #define MICROPY_HW_LED2 (pin_B12) // green #define MICROPY_HW_LED3 (pin_B12) // green #define MICROPY_HW_LED4 (pin_B12) // green -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/stmhal/boards/HYDRABUS/mpconfigboard.h b/stmhal/boards/HYDRABUS/mpconfigboard.h index 4fe0874d73..06d1692360 100644 --- a/stmhal/boards/HYDRABUS/mpconfigboard.h +++ b/stmhal/boards/HYDRABUS/mpconfigboard.h @@ -69,9 +69,8 @@ #define MICROPY_HW_LED2 (pin_A4) // same as LED1 #define MICROPY_HW_LED3 (pin_A4) // same as LED1 #define MICROPY_HW_LED4 (pin_A4) // same as LED1 -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch (not used, always on) #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) diff --git a/stmhal/boards/LIMIFROG/mpconfigboard.h b/stmhal/boards/LIMIFROG/mpconfigboard.h index 782c9c90f8..47b8922336 100644 --- a/stmhal/boards/LIMIFROG/mpconfigboard.h +++ b/stmhal/boards/LIMIFROG/mpconfigboard.h @@ -63,9 +63,8 @@ void LIMIFROG_board_early_init(void); // LEDs #define MICROPY_HW_LED1 (pin_C3) // red -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRR = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRR = pin->pin_mask<<16) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config // #define MICROPY_HW_USB_OTG_ID_PIN (pin_C12) // This is not the official ID Pin which should be PA10 diff --git a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h index 8ec8df645f..3155b63098 100644 --- a/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h +++ b/stmhal/boards/NETDUINO_PLUS_2/mpconfigboard.h @@ -64,9 +64,8 @@ void NETDUINO_PLUS_2_board_early_init(void); #define MICROPY_HW_LED2 (pin_C13) // White LED (aka Power) #define MICROPY_HW_LED3 (pin_A10) // Same as Led(1) #define MICROPY_HW_LED4 (pin_C13) // Same as Led(2) -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB VBUS detect pin #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) diff --git a/stmhal/boards/NUCLEO_F401RE/mpconfigboard.h b/stmhal/boards/NUCLEO_F401RE/mpconfigboard.h index 780eaf8fc4..518f65824b 100644 --- a/stmhal/boards/NUCLEO_F401RE/mpconfigboard.h +++ b/stmhal/boards/NUCLEO_F401RE/mpconfigboard.h @@ -54,6 +54,5 @@ // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/stmhal/boards/NUCLEO_F411RE/mpconfigboard.h b/stmhal/boards/NUCLEO_F411RE/mpconfigboard.h index e7ffd85100..4dac804931 100644 --- a/stmhal/boards/NUCLEO_F411RE/mpconfigboard.h +++ b/stmhal/boards/NUCLEO_F411RE/mpconfigboard.h @@ -65,6 +65,5 @@ // LEDs #define MICROPY_HW_LED1 (pin_A5) // Green LD2 LED on Nucleo -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) diff --git a/stmhal/boards/OLIMEX_E407/mpconfigboard.h b/stmhal/boards/OLIMEX_E407/mpconfigboard.h index c9241fe63a..63ddcfb5d6 100644 --- a/stmhal/boards/OLIMEX_E407/mpconfigboard.h +++ b/stmhal/boards/OLIMEX_E407/mpconfigboard.h @@ -71,9 +71,8 @@ // LEDs #define MICROPY_HW_LED1 (pin_C13) -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRH = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRL = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C11) diff --git a/stmhal/boards/PYBLITEV10/mpconfigboard.h b/stmhal/boards/PYBLITEV10/mpconfigboard.h index 83dcb938b3..3147d2d7ab 100644 --- a/stmhal/boards/PYBLITEV10/mpconfigboard.h +++ b/stmhal/boards/PYBLITEV10/mpconfigboard.h @@ -73,9 +73,8 @@ #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_B5) diff --git a/stmhal/boards/PYBV10/mpconfigboard.h b/stmhal/boards/PYBV10/mpconfigboard.h index c654ec9a70..2540cc4eb3 100644 --- a/stmhal/boards/PYBV10/mpconfigboard.h +++ b/stmhal/boards/PYBV10/mpconfigboard.h @@ -84,9 +84,8 @@ #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) diff --git a/stmhal/boards/PYBV11/mpconfigboard.h b/stmhal/boards/PYBV11/mpconfigboard.h index 9b5b7de27b..881e1ccf02 100644 --- a/stmhal/boards/PYBV11/mpconfigboard.h +++ b/stmhal/boards/PYBV11/mpconfigboard.h @@ -84,9 +84,8 @@ #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) diff --git a/stmhal/boards/PYBV3/mpconfigboard.h b/stmhal/boards/PYBV3/mpconfigboard.h index 44fb221610..48d5549253 100644 --- a/stmhal/boards/PYBV3/mpconfigboard.h +++ b/stmhal/boards/PYBV3/mpconfigboard.h @@ -73,9 +73,8 @@ #define MICROPY_HW_LED4 (pin_C5) // G2 - green #define MICROPY_HW_LED1_PWM { TIM1, 1, TIM_CHANNEL_1, GPIO_AF1_TIM1 } #define MICROPY_HW_LED2_PWM { TIM1, 1, TIM_CHANNEL_3, GPIO_AF1_TIM1 } -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRH = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRL = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_low(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_high(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C13) diff --git a/stmhal/boards/PYBV4/mpconfigboard.h b/stmhal/boards/PYBV4/mpconfigboard.h index cc931fb6bf..3e8300d15b 100644 --- a/stmhal/boards/PYBV4/mpconfigboard.h +++ b/stmhal/boards/PYBV4/mpconfigboard.h @@ -81,9 +81,8 @@ #define MICROPY_HW_LED4 (pin_B4) // blue #define MICROPY_HW_LED3_PWM { TIM2, 2, TIM_CHANNEL_1, GPIO_AF1_TIM2 } #define MICROPY_HW_LED4_PWM { TIM3, 3, TIM_CHANNEL_1, GPIO_AF2_TIM3 } -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_A8) diff --git a/stmhal/boards/STM32F411DISC/mpconfigboard.h b/stmhal/boards/STM32F411DISC/mpconfigboard.h index 3bab1304c0..be3589cd9f 100644 --- a/stmhal/boards/STM32F411DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F411DISC/mpconfigboard.h @@ -63,9 +63,8 @@ #define MICROPY_HW_LED2 (pin_D12) // green #define MICROPY_HW_LED3 (pin_D13) // orange #define MICROPY_HW_LED4 (pin_D15) // blue -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) diff --git a/stmhal/boards/STM32F429DISC/mpconfigboard.h b/stmhal/boards/STM32F429DISC/mpconfigboard.h index f2cf6c1422..63f22e02c2 100644 --- a/stmhal/boards/STM32F429DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F429DISC/mpconfigboard.h @@ -67,9 +67,8 @@ // LEDs #define MICROPY_HW_LED1 (pin_G14) // red #define MICROPY_HW_LED2 (pin_G13) // green -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_B13) diff --git a/stmhal/boards/STM32F4DISC/mpconfigboard.h b/stmhal/boards/STM32F4DISC/mpconfigboard.h index 01202e0c95..841bf7d15b 100644 --- a/stmhal/boards/STM32F4DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F4DISC/mpconfigboard.h @@ -82,9 +82,8 @@ #define MICROPY_HW_LED2 (pin_D12) // green #define MICROPY_HW_LED3 (pin_D13) // orange #define MICROPY_HW_LED4 (pin_D15) // blue -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRRL = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRRH = pin->pin_mask) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config #define MICROPY_HW_USB_VBUS_DETECT_PIN (pin_A9) diff --git a/stmhal/boards/STM32F7DISC/mpconfigboard.h b/stmhal/boards/STM32F7DISC/mpconfigboard.h index a1dbc0f468..acdc4d0055 100644 --- a/stmhal/boards/STM32F7DISC/mpconfigboard.h +++ b/stmhal/boards/STM32F7DISC/mpconfigboard.h @@ -79,9 +79,8 @@ void STM32F7DISC_board_early_init(void); // LEDs #define MICROPY_HW_LED1 (pin_I1) // green -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRR = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRR = (pin->pin_mask << 16)) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // SD card detect switch #define MICROPY_HW_SDCARD_DETECT_PIN (pin_C13) diff --git a/stmhal/boards/STM32L476DISC/mpconfigboard.h b/stmhal/boards/STM32L476DISC/mpconfigboard.h index 07e3ec7fdc..55e7c9b563 100644 --- a/stmhal/boards/STM32L476DISC/mpconfigboard.h +++ b/stmhal/boards/STM32L476DISC/mpconfigboard.h @@ -61,9 +61,8 @@ // LEDs #define MICROPY_HW_LED1 (pin_B2) // red #define MICROPY_HW_LED2 (pin_E8) // green -#define MICROPY_HW_LED_OTYPE (GPIO_MODE_OUTPUT_PP) -#define MICROPY_HW_LED_ON(pin) (pin->gpio->BSRR = pin->pin_mask) -#define MICROPY_HW_LED_OFF(pin) (pin->gpio->BSRR = pin->pin_mask<<16) +#define MICROPY_HW_LED_ON(pin) (mp_hal_pin_high(pin)) +#define MICROPY_HW_LED_OFF(pin) (mp_hal_pin_low(pin)) // USB config // #define MICROPY_HW_USB_OTG_ID_PIN (pin_C12) // This is not the official ID Pin which should be PA10 diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 1909f81606..07269bce5e 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -238,8 +238,8 @@ void i2c_init(I2C_HandleTypeDef *i2c) { } // init the GPIO lines - mp_hal_gpio_set_af(scl_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit); - mp_hal_gpio_set_af(sda_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit); + mp_hal_pin_set_af(scl_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit); + mp_hal_pin_set_af(sda_pin, &GPIO_InitStructure, AF_FN_I2C, i2c_unit); // init the I2C device if (HAL_I2C_Init(i2c) != HAL_OK) { diff --git a/stmhal/lcd.c b/stmhal/lcd.c index 92f19b8186..c406d64477 100644 --- a/stmhal/lcd.c +++ b/stmhal/lcd.c @@ -113,16 +113,16 @@ STATIC void lcd_delay(void) { STATIC void lcd_out(pyb_lcd_obj_t *lcd, int instr_data, uint8_t i) { lcd_delay(); - GPIO_clear_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); // CS=0; enable + mp_hal_pin_low(lcd->pin_cs1); // CS=0; enable if (instr_data == LCD_INSTR) { - GPIO_clear_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); // A0=0; select instr reg + mp_hal_pin_low(lcd->pin_a0); // A0=0; select instr reg } else { - GPIO_set_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); // A0=1; select data reg + mp_hal_pin_high(lcd->pin_a0); // A0=1; select data reg } lcd_delay(); HAL_SPI_Transmit(lcd->spi, &i, 1, 1000); lcd_delay(); - GPIO_set_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); // CS=1; disable + mp_hal_pin_high(lcd->pin_cs1); // CS=1; disable } // write a string to the LCD at the current cursor location @@ -262,34 +262,22 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, mp_uint_t n_args, mp spi_init(lcd->spi, false); // set the pins to default values - GPIO_set_pin(lcd->pin_cs1->gpio, lcd->pin_cs1->pin_mask); - GPIO_set_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); - GPIO_set_pin(lcd->pin_a0->gpio, lcd->pin_a0->pin_mask); - GPIO_clear_pin(lcd->pin_bl->gpio, lcd->pin_bl->pin_mask); + mp_hal_pin_high(lcd->pin_cs1); + mp_hal_pin_high(lcd->pin_rst); + mp_hal_pin_high(lcd->pin_a0); + mp_hal_pin_low(lcd->pin_bl); // init the pins to be push/pull outputs - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Speed = GPIO_SPEED_HIGH; - GPIO_InitStructure.Pull = GPIO_NOPULL; - - GPIO_InitStructure.Pin = lcd->pin_cs1->pin_mask; - HAL_GPIO_Init(lcd->pin_cs1->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = lcd->pin_rst->pin_mask; - HAL_GPIO_Init(lcd->pin_rst->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = lcd->pin_a0->pin_mask; - HAL_GPIO_Init(lcd->pin_a0->gpio, &GPIO_InitStructure); - - GPIO_InitStructure.Pin = lcd->pin_bl->pin_mask; - HAL_GPIO_Init(lcd->pin_bl->gpio, &GPIO_InitStructure); + mp_hal_pin_output(lcd->pin_cs1); + mp_hal_pin_output(lcd->pin_rst); + mp_hal_pin_output(lcd->pin_a0); + mp_hal_pin_output(lcd->pin_bl); // init the LCD HAL_Delay(1); // wait a bit - GPIO_clear_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); // RST=0; reset + mp_hal_pin_low(lcd->pin_rst); // RST=0; reset HAL_Delay(1); // wait for reset; 2us min - GPIO_set_pin(lcd->pin_rst->gpio, lcd->pin_rst->pin_mask); // RST=1; enable + mp_hal_pin_high(lcd->pin_rst); // RST=1; enable HAL_Delay(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) @@ -372,9 +360,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_lcd_contrast_obj, pyb_lcd_contrast); STATIC mp_obj_t pyb_lcd_light(mp_obj_t self_in, mp_obj_t value) { pyb_lcd_obj_t *self = self_in; if (mp_obj_is_true(value)) { - GPIO_set_pin(self->pin_bl->gpio, self->pin_bl->pin_mask); // set pin high to turn backlight on + mp_hal_pin_high(self->pin_bl); // set pin high to turn backlight on } else { - GPIO_clear_pin(self->pin_bl->gpio, self->pin_bl->pin_mask); // set pin low to turn backlight off + mp_hal_pin_low(self->pin_bl); // set pin low to turn backlight off } return mp_const_none; } diff --git a/stmhal/led.c b/stmhal/led.c index fdf5b04d8e..310efdcda9 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -67,21 +67,12 @@ STATIC const pyb_led_obj_t pyb_led_obj[] = { #define NUM_LEDS MP_ARRAY_SIZE(pyb_led_obj) void led_init(void) { - /* GPIO structure */ - GPIO_InitTypeDef GPIO_InitStructure; - - /* Configure I/O speed, mode, output type and pull */ - GPIO_InitStructure.Speed = GPIO_SPEED_LOW; - GPIO_InitStructure.Mode = MICROPY_HW_LED_OTYPE; - GPIO_InitStructure.Pull = GPIO_NOPULL; - /* Turn off LEDs and initialize */ for (int led = 0; led < NUM_LEDS; led++) { const pin_obj_t *led_pin = pyb_led_obj[led].led_pin; mp_hal_gpio_clock_enable(led_pin->gpio); MICROPY_HW_LED_OFF(led_pin); - GPIO_InitStructure.Pin = led_pin->pin_mask; - HAL_GPIO_Init(led_pin->gpio, &GPIO_InitStructure); + mp_hal_pin_output(led_pin); } } diff --git a/stmhal/modmachine.c b/stmhal/modmachine.c index 8bd04f3ec9..7a337adb69 100644 --- a/stmhal/modmachine.c +++ b/stmhal/modmachine.c @@ -33,6 +33,7 @@ #include "extmod/machine_mem.h" #include "extmod/machine_pulse.h" #include "extmod/machine_i2c.h" +#include "lib/utils/pyexec.h" #include "lib/fatfs/ff.h" #include "lib/fatfs/diskio.h" #include "gccollect.h" @@ -172,6 +173,12 @@ STATIC mp_obj_t machine_reset(void) { } MP_DEFINE_CONST_FUN_OBJ_0(machine_reset_obj, machine_reset); +STATIC mp_obj_t machine_soft_reset(void) { + pyexec_system_exit = PYEXEC_FORCED_EXIT; + nlr_raise(mp_obj_new_exception(&mp_type_SystemExit)); +} +MP_DEFINE_CONST_FUN_OBJ_0(machine_soft_reset_obj, machine_soft_reset); + // Activate the bootloader without BOOT* pins. STATIC NORETURN mp_obj_t machine_bootloader(void) { pyb_usb_dev_deinit(); @@ -502,6 +509,7 @@ STATIC const mp_map_elem_t machine_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_info), (mp_obj_t)&machine_info_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_unique_id), (mp_obj_t)&machine_unique_id_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_reset), (mp_obj_t)&machine_reset_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_soft_reset), (mp_obj_t)&machine_soft_reset_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_bootloader), (mp_obj_t)&machine_bootloader_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_freq), (mp_obj_t)&machine_freq_obj }, #if MICROPY_HW_ENABLE_RNG diff --git a/stmhal/modnwwiznet5k.c b/stmhal/modnwwiznet5k.c index c8b5d628f4..f349e40aff 100644 --- a/stmhal/modnwwiznet5k.c +++ b/stmhal/modnwwiznet5k.c @@ -65,11 +65,11 @@ STATIC void wiz_cris_exit(void) { } STATIC void wiz_cs_select(void) { - GPIO_clear_pin(wiznet5k_obj.cs->gpio, wiznet5k_obj.cs->pin_mask); + mp_hal_pin_low(wiznet5k_obj.cs); } STATIC void wiz_cs_deselect(void) { - GPIO_set_pin(wiznet5k_obj.cs->gpio, wiznet5k_obj.cs->pin_mask); + mp_hal_pin_high(wiznet5k_obj.cs); } STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) { @@ -344,22 +344,12 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, mp_uint_t n_args, m wiznet5k_obj.spi->Init.CRCPolynomial = 7; // unused spi_init(wiznet5k_obj.spi, false); - GPIO_InitTypeDef GPIO_InitStructure; - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Pin = wiznet5k_obj.cs->pin_mask; - HAL_GPIO_Init(wiznet5k_obj.cs->gpio, &GPIO_InitStructure); + mp_hal_pin_output(wiznet5k_obj.cs); + mp_hal_pin_output(wiznet5k_obj.rst); - GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStructure.Speed = GPIO_SPEED_FAST; - GPIO_InitStructure.Pull = GPIO_NOPULL; - GPIO_InitStructure.Pin = wiznet5k_obj.rst->pin_mask; - HAL_GPIO_Init(wiznet5k_obj.rst->gpio, &GPIO_InitStructure); - - GPIO_clear_pin(wiznet5k_obj.rst->gpio, wiznet5k_obj.rst->pin_mask); + mp_hal_pin_low(wiznet5k_obj.rst); HAL_Delay(1); // datasheet says 2us - GPIO_set_pin(wiznet5k_obj.rst->gpio, wiznet5k_obj.rst->pin_mask); + mp_hal_pin_high(wiznet5k_obj.rst); HAL_Delay(160); // datasheet says 150ms reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); diff --git a/stmhal/modpyb.c b/stmhal/modpyb.c index 17c3411ebb..5b2bf7aa99 100644 --- a/stmhal/modpyb.c +++ b/stmhal/modpyb.c @@ -62,6 +62,7 @@ #include "portmodules.h" #include "modmachine.h" #include "extmod/fsusermount.h" +#include "extmod/utime_mphal.h" /// \function millis() /// Returns the number of milliseconds since the board was last reset. @@ -162,8 +163,8 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { 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_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&time_sleep_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&time_sleep_us_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&mp_utime_sleep_ms_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_udelay), (mp_obj_t)&mp_utime_sleep_us_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_sync), (mp_obj_t)&mod_os_sync_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mount), (mp_obj_t)&fsuser_mount_obj }, diff --git a/stmhal/modutime.c b/stmhal/modutime.c index 60c92d60c1..fae360bb02 100644 --- a/stmhal/modutime.c +++ b/stmhal/modutime.c @@ -31,6 +31,7 @@ #include "py/nlr.h" #include "py/smallint.h" #include "py/obj.h" +#include "extmod/utime_mphal.h" #include "systick.h" #include "timeutils.h" #include "portmodules.h" @@ -129,84 +130,19 @@ STATIC mp_obj_t time_time(void) { } MP_DEFINE_CONST_FUN_OBJ_0(time_time_obj, time_time); -/// \function sleep(seconds) -/// Sleep for the given number of seconds. Seconds can be a floating-point number to -/// sleep for a fractional number of seconds. -STATIC mp_obj_t time_sleep(mp_obj_t seconds_o) { -#if MICROPY_PY_BUILTINS_FLOAT - if (MP_OBJ_IS_INT(seconds_o)) { -#endif - HAL_Delay(1000 * mp_obj_get_int(seconds_o)); -#if MICROPY_PY_BUILTINS_FLOAT - } else { - HAL_Delay((uint32_t)(1000 * mp_obj_get_float(seconds_o))); - } -#endif - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_obj, time_sleep); - -STATIC mp_obj_t time_sleep_ms(mp_obj_t ms_in) { - mp_int_t ms = mp_obj_get_int(ms_in); - if (ms > 0) { - HAL_Delay(ms); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_ms_obj, time_sleep_ms); - -STATIC mp_obj_t time_sleep_us(mp_obj_t usec_in) { - mp_int_t usec = mp_obj_get_int(usec_in); - if (usec > 0) { - sys_tick_udelay(usec); - } - return mp_const_none; -} -MP_DEFINE_CONST_FUN_OBJ_1(time_sleep_us_obj, time_sleep_us); - -STATIC mp_obj_t time_ticks_ms(void) { - return MP_OBJ_NEW_SMALL_INT(HAL_GetTick() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_ms_obj, time_ticks_ms); - -STATIC mp_obj_t time_ticks_us(void) { - return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds() & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_us_obj, time_ticks_us); - -STATIC mp_obj_t time_ticks_cpu(void) { - static bool enabled = false; - if (!enabled) { - CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - DWT->CYCCNT = 0; - DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; - enabled = true; - } - return MP_OBJ_NEW_SMALL_INT(DWT->CYCCNT & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_0(time_ticks_cpu_obj, time_ticks_cpu); - -STATIC mp_obj_t time_ticks_diff(mp_obj_t start_in, mp_obj_t end_in) { - // we assume that the arguments come from ticks_xx so are small ints - uint32_t start = MP_OBJ_SMALL_INT_VALUE(start_in); - uint32_t end = MP_OBJ_SMALL_INT_VALUE(end_in); - return MP_OBJ_NEW_SMALL_INT((end - start) & MP_SMALL_INT_POSITIVE_MASK); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(time_ticks_diff_obj, time_ticks_diff); - STATIC const mp_map_elem_t time_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_utime) }, { MP_OBJ_NEW_QSTR(MP_QSTR_localtime), (mp_obj_t)&time_localtime_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mktime), (mp_obj_t)&time_mktime_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_time), (mp_obj_t)&time_time_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&time_sleep_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&time_sleep_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&time_sleep_us_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&time_ticks_ms_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&time_ticks_us_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&time_ticks_cpu_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&time_ticks_diff_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep), (mp_obj_t)&mp_utime_sleep_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_ms), (mp_obj_t)&mp_utime_sleep_ms_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_sleep_us), (mp_obj_t)&mp_utime_sleep_us_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_ms), (mp_obj_t)&mp_utime_ticks_ms_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_us), (mp_obj_t)&mp_utime_ticks_us_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_cpu), (mp_obj_t)&mp_utime_ticks_cpu_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_ticks_diff), (mp_obj_t)&mp_utime_ticks_diff_obj }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); diff --git a/stmhal/mpconfigport.h b/stmhal/mpconfigport.h index 52fbcad681..264db3029d 100644 --- a/stmhal/mpconfigport.h +++ b/stmhal/mpconfigport.h @@ -67,10 +67,13 @@ #define MICROPY_USE_INTERNAL_ERRNO (1) #define MICROPY_PY_FUNCTION_ATTRS (1) #define MICROPY_PY_BUILTINS_STR_UNICODE (1) +#define MICROPY_PY_BUILTINS_STR_CENTER (1) +#define MICROPY_PY_BUILTINS_STR_PARTITION (1) #define MICROPY_PY_BUILTINS_STR_SPLITLINES (1) #define MICROPY_PY_BUILTINS_MEMORYVIEW (1) #define MICROPY_PY_BUILTINS_FROZENSET (1) #define MICROPY_PY_BUILTINS_EXECFILE (1) +#define MICROPY_PY_BUILTINS_COMPILE (1) #define MICROPY_PY_ALL_SPECIAL_METHODS (1) #define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_ARRAY_SLICE_ASSIGN (1) @@ -94,6 +97,7 @@ #define MICROPY_PY_URE (1) #define MICROPY_PY_UHEAPQ (1) #define MICROPY_PY_UHASHLIB (1) +#define MICROPY_PY_UTIME_MP_HAL (1) #define MICROPY_PY_MACHINE (1) #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_I2C (1) @@ -176,6 +180,7 @@ extern const struct _mp_obj_module_t mp_module_network; // extra constants #define MICROPY_PORT_CONSTANTS \ { MP_OBJ_NEW_QSTR(MP_QSTR_umachine), (mp_obj_t)&machine_module }, \ + { MP_OBJ_NEW_QSTR(MP_QSTR_machine), (mp_obj_t)&machine_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_pyb), (mp_obj_t)&pyb_module }, \ { MP_OBJ_NEW_QSTR(MP_QSTR_stm), (mp_obj_t)&stm_module }, \ diff --git a/stmhal/mphalport.c b/stmhal/mphalport.c index f392550b80..8d6aa1a759 100644 --- a/stmhal/mphalport.c +++ b/stmhal/mphalport.c @@ -7,6 +7,8 @@ #include "usb.h" #include "uart.h" +bool mp_hal_ticks_cpu_enabled = false; + // this table converts from HAL_StatusTypeDef to POSIX errno const byte mp_hal_status_to_errno_table[4] = { [HAL_OK] = 0, @@ -71,6 +73,15 @@ void mp_hal_stdout_tx_strn_cooked(const char *str, size_t len) { } } +void mp_hal_ticks_cpu_enable(void) { + if (!mp_hal_ticks_cpu_enabled) { + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; + mp_hal_ticks_cpu_enabled = true; + } +} + void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { if (0) { #ifdef __GPIOA_CLK_ENABLE @@ -120,7 +131,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { } } -void mp_hal_gpio_config(GPIO_TypeDef *gpio, uint32_t pin, uint32_t mode, uint32_t pull, uint32_t alt) { +void mp_hal_pin_config(mp_hal_pin_obj_t pin_obj, uint32_t mode, uint32_t pull, uint32_t alt) { + GPIO_TypeDef *gpio = pin_obj->gpio; + uint32_t pin = pin_obj->pin; mp_hal_gpio_clock_enable(gpio); gpio->MODER = (gpio->MODER & ~(3 << (2 * pin))) | ((mode & 3) << (2 * pin)); gpio->OTYPER = (gpio->OTYPER & ~(1 << pin)) | ((mode >> 2) << pin); @@ -129,7 +142,7 @@ void mp_hal_gpio_config(GPIO_TypeDef *gpio, uint32_t pin, uint32_t mode, uint32_ gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); } -bool mp_hal_gpio_set_af(const pin_obj_t *pin, GPIO_InitTypeDef *init, uint8_t fn, uint8_t unit) { +bool mp_hal_pin_set_af(mp_hal_pin_obj_t pin, GPIO_InitTypeDef *init, uint8_t fn, uint8_t unit) { mp_hal_gpio_clock_enable(pin->gpio); const pin_af_obj_t *af = pin_find_af(pin, fn, unit); diff --git a/stmhal/mphalport.h b/stmhal/mphalport.h index 29a9fd6c39..e58bb33b5f 100644 --- a/stmhal/mphalport.h +++ b/stmhal/mphalport.h @@ -14,41 +14,51 @@ #error mphalport.h: Unrecognized MCU_SERIES #endif -// Basic GPIO functions -#define GPIO_read_pin(gpio, pin) (((gpio)->IDR >> (pin)) & 1) -#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4) -#define GPIO_set_pin(gpio, pin_mask) (((gpio)->BSRR) = (pin_mask)) -#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->BSRR) = ((pin_mask) << 16)) -#else -#define GPIO_set_pin(gpio, pin_mask) (((gpio)->BSRRL) = (pin_mask)) -#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->BSRRH) = (pin_mask)) -#endif -#define GPIO_read_output_pin(gpio, pin) (((gpio)->ODR >> (pin)) & 1) - -void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); -void mp_hal_gpio_config(GPIO_TypeDef *gpio, uint32_t pin, uint32_t mode, uint32_t pull, uint32_t alt); -bool mp_hal_gpio_set_af(const pin_obj_t *pin, GPIO_InitTypeDef *init, uint8_t fn, uint8_t unit); - extern const unsigned char mp_hal_status_to_errno_table[4]; NORETURN void mp_hal_raise(HAL_StatusTypeDef status); 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() +extern bool mp_hal_ticks_cpu_enabled; +void mp_hal_ticks_cpu_enable(void); +static inline mp_uint_t mp_hal_ticks_cpu(void) { + if (!mp_hal_ticks_cpu_enabled) { + mp_hal_ticks_cpu_enable(); + } + return DWT->CYCCNT; +} + // C-level pin HAL + #include "stmhal/pin.h" + #define mp_hal_pin_obj_t const pin_obj_t* -#define mp_hal_get_pin_obj(o) pin_find(o) -#define mp_hal_pin_input(p) mp_hal_gpio_config((p)->gpio, (p)->pin, 0, 0, 0) -#define mp_hal_pin_output(p) mp_hal_gpio_config((p)->gpio, (p)->pin, 1, 0, 0) -#define mp_hal_pin_open_drain(p) mp_hal_gpio_config((p)->gpio, (p)->pin, 5, 0, 0) -#define mp_hal_pin_od_low(p) GPIO_clear_pin((p)->gpio, (p)->pin_mask) -#define mp_hal_pin_od_high(p) GPIO_set_pin((p)->gpio, (p)->pin_mask) -#define mp_hal_pin_read(p) GPIO_read_pin((p)->gpio, (p)->pin) -#define mp_hal_pin_write(p, v) do { if (v) { GPIO_set_pin((p)->gpio, (p)->pin_mask); } else { GPIO_clear_pin((p)->gpio, (p)->pin_mask); } } while (0) +#define mp_hal_get_pin_obj(o) pin_find(o) +#define mp_hal_pin_input(p) mp_hal_pin_config((p), 0, 0, 0) +#define mp_hal_pin_output(p) mp_hal_pin_config((p), 1, 0, 0) +#define mp_hal_pin_open_drain(p) mp_hal_pin_config((p), 5, 0, 0) +#if defined(MCU_SERIES_F7) || defined(MCU_SERIES_L4) +#define mp_hal_pin_high(p) (((p)->gpio->BSRR) = (p)->pin_mask) +#define mp_hal_pin_low(p) (((p)->gpio->BSRR) = ((p)->pin_mask << 16)) +#else +#define mp_hal_pin_high(p) (((p)->gpio->BSRRL) = (p)->pin_mask) +#define mp_hal_pin_low(p) (((p)->gpio->BSRRH) = (p)->pin_mask) +#endif +#define mp_hal_pin_od_low(p) mp_hal_pin_low(p) +#define mp_hal_pin_od_high(p) mp_hal_pin_high(p) +#define mp_hal_pin_read(p) (((p)->gpio->IDR >> (p)->pin) & 1) +#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) + +void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); +void mp_hal_pin_config(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint32_t alt); +bool mp_hal_pin_set_af(mp_hal_pin_obj_t pin, GPIO_InitTypeDef *init, uint8_t fn, uint8_t unit); diff --git a/stmhal/pin.c b/stmhal/pin.c index 9bd4e7a6d9..21012d1865 100644 --- a/stmhal/pin.c +++ b/stmhal/pin.c @@ -266,14 +266,10 @@ STATIC mp_obj_t pin_call(mp_obj_t self_in, mp_uint_t n_args, mp_uint_t n_kw, con pin_obj_t *self = self_in; if (n_args == 0) { // get pin - return MP_OBJ_NEW_SMALL_INT(GPIO_read_pin(self->gpio, self->pin)); + return MP_OBJ_NEW_SMALL_INT(mp_hal_pin_read(self)); } else { // set pin - if (mp_obj_is_true(args[0])) { - GPIO_set_pin(self->gpio, self->pin_mask); - } else { - GPIO_clear_pin(self->gpio, self->pin_mask); - } + mp_hal_pin_write(self, mp_obj_is_true(args[0])); return mp_const_none; } } @@ -371,11 +367,7 @@ STATIC mp_obj_t pin_obj_init_helper(const pin_obj_t *self, mp_uint_t n_args, con // if given, set the pin value before initialising to prevent glitches if (args[3].u_obj != MP_OBJ_NULL) { - if (mp_obj_is_true(args[3].u_obj)) { - GPIO_set_pin(self->gpio, self->pin_mask); - } else { - GPIO_clear_pin(self->gpio, self->pin_mask); - } + mp_hal_pin_write(self, mp_obj_is_true(args[3].u_obj)); } // configure the GPIO as requested @@ -411,7 +403,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pin_value_obj, 1, 2, pin_value); /// Set the pin to a low logic level. STATIC mp_obj_t pin_low(mp_obj_t self_in) { pin_obj_t *self = self_in; - GPIO_clear_pin(self->gpio, self->pin_mask);; + mp_hal_pin_low(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); @@ -420,7 +412,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_low_obj, pin_low); /// Set the pin to a high logic level. STATIC mp_obj_t pin_high(mp_obj_t self_in) { pin_obj_t *self = self_in; - GPIO_set_pin(self->gpio, self->pin_mask);; + mp_hal_pin_high(self); return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_1(pin_high_obj, pin_high); diff --git a/stmhal/pybstdio.c b/stmhal/pybstdio.c index cf31f53acf..9cc787ce2d 100644 --- a/stmhal/pybstdio.c +++ b/stmhal/pybstdio.c @@ -85,7 +85,7 @@ STATIC mp_uint_t stdio_write(mp_obj_t self_in, const void *buf, mp_uint_t size, } } -STATIC mp_obj_t stdio_obj___exit__(mp_uint_t n_args, const mp_obj_t *args) { +STATIC mp_obj_t stdio_obj___exit__(size_t n_args, const mp_obj_t *args) { return mp_const_none; } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(stdio_obj___exit___obj, 4, 4, stdio_obj___exit__); diff --git a/stmhal/spi.c b/stmhal/spi.c index 7f805709d6..e72810d287 100644 --- a/stmhal/spi.c +++ b/stmhal/spi.c @@ -332,7 +332,7 @@ void spi_init(SPI_HandleTypeDef *spi, bool enable_nss_pin) { } for (uint i = (enable_nss_pin && pins[0] ? 0 : 1); i < 4; i++) { - mp_hal_gpio_set_af(pins[i], &GPIO_InitStructure, AF_FN_SPI, (self - &pyb_spi_obj[0]) + 1); + mp_hal_pin_set_af(pins[i], &GPIO_InitStructure, AF_FN_SPI, (self - &pyb_spi_obj[0]) + 1); } // init the SPI device diff --git a/teensy/main.c b/teensy/main.c index 890ee81493..ba7207fe83 100644 --- a/teensy/main.c +++ b/teensy/main.c @@ -317,7 +317,7 @@ soft_reset: pyexec_frozen_module("main.py"); #else { - vstr_t *vstr = vstr_new(); + vstr_t *vstr = vstr_new(16); vstr_add_str(vstr, "/"); if (pyb_config_main == MP_OBJ_NULL) { vstr_add_str(vstr, "main.py"); diff --git a/teensy/teensy_hal.h b/teensy/teensy_hal.h index b00b6e4ac6..80f320e0c5 100644 --- a/teensy/teensy_hal.h +++ b/teensy/teensy_hal.h @@ -118,7 +118,9 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio); void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *init); -#define GPIO_read_pin(gpio, pin) (((gpio)->PDIR >> (pin)) & 1) -#define GPIO_set_pin(gpio, pin_mask) (((gpio)->PSOR) = (pin_mask)) -#define GPIO_clear_pin(gpio, pin_mask) (((gpio)->PCOR) = (pin_mask)) -#define GPIO_read_output_pin(gpio, pin) (((gpio)->PDOR >> (pin)) & 1) +struct _pin_obj_t; +#define mp_hal_pin_obj_t const struct _pin_obj_t* +#define mp_hal_pin_high(p) (((p)->gpio->PSOR) = (p)->pin_mask) +#define mp_hal_pin_low(p) (((p)->gpio->PCOR) = (p)->pin_mask) +#define mp_hal_pin_read(p) (((p)->gpio->PDIR >> (p)->pin) & 1) +#define mp_hal_pin_write(p, v) do { if (v) { mp_hal_pin_high(p); } else { mp_hal_pin_low(p); } } while (0) diff --git a/tests/basics/array1.py b/tests/basics/array1.py index e5ea6683c3..c45b883c94 100644 --- a/tests/basics/array1.py +++ b/tests/basics/array1.py @@ -21,6 +21,10 @@ print(array.array('i')) print(bool(array.array('i'))) print(bool(array.array('i', [1]))) +# containment, with incorrect type +print('12' in array.array('B', b'12')) +print([] in array.array('B', b'12')) + # bad typecode try: array.array('X') diff --git a/tests/basics/async_def.py b/tests/basics/async_def.py new file mode 100644 index 0000000000..e345703d74 --- /dev/null +++ b/tests/basics/async_def.py @@ -0,0 +1,16 @@ +# test async def + +def dec(f): + print('decorator') + return f + +# test definition with a decorator +@dec +async def foo(): + print('foo') + +coro = foo() +try: + coro.send(None) +except StopIteration: + print('StopIteration') diff --git a/tests/basics/async_def.py.exp b/tests/basics/async_def.py.exp new file mode 100644 index 0000000000..f555ace99a --- /dev/null +++ b/tests/basics/async_def.py.exp @@ -0,0 +1,3 @@ +decorator +foo +StopIteration diff --git a/tests/basics/async_with.py b/tests/basics/async_with.py index 9eccfd816c..5af0c5d955 100644 --- a/tests/basics/async_with.py +++ b/tests/basics/async_with.py @@ -3,6 +3,7 @@ class AContext: async def __aenter__(self): print('enter') + return 1 async def __aexit__(self, exc_type, exc, tb): print('exit', exc_type, exc) @@ -17,7 +18,8 @@ except StopIteration: print('finished') async def g(): - async with AContext(): + async with AContext() as ac: + print(ac) raise ValueError('error') o = g() diff --git a/tests/basics/async_with.py.exp b/tests/basics/async_with.py.exp index 6072a3e0b3..d00b18c969 100644 --- a/tests/basics/async_with.py.exp +++ b/tests/basics/async_with.py.exp @@ -3,5 +3,6 @@ body exit None None finished enter +1 exit error ValueError diff --git a/tests/basics/builtin_range.py b/tests/basics/builtin_range.py index 9110cf12cd..59fc0344a4 100644 --- a/tests/basics/builtin_range.py +++ b/tests/basics/builtin_range.py @@ -50,3 +50,9 @@ try: range(1)[0] = 1 except TypeError: print("TypeError") + +# bad attr (can't store) +try: + range(4).start = 0 +except AttributeError: + print('AttributeError') diff --git a/tests/basics/del_global.py b/tests/basics/del_global.py index 77d11cb3c4..d740357b03 100644 --- a/tests/basics/del_global.py +++ b/tests/basics/del_global.py @@ -54,3 +54,8 @@ try: print(c) except NameError: print("NameError") + +a = 1 +b = 2 +c = 3 +del (a, (b, c)) diff --git a/tests/basics/dict1.py b/tests/basics/dict1.py index c70ca588a7..20fa9def31 100644 --- a/tests/basics/dict1.py +++ b/tests/basics/dict1.py @@ -16,3 +16,27 @@ while x < 100: d[x] = x x += 1 print(d[50]) + +# equality operator on dicts of different size +print({} == {1:1}) + +# equality operator on dicts of same size but with different keys +print({1:1} == {2:1}) + +# value not found +try: + {}[0] +except KeyError as er: + print('KeyError', er, repr(er), er.args) + +# unsupported unary op +try: + +{} +except TypeError: + print('TypeError') + +# unsupported binary op +try: + {} + {} +except TypeError: + print('TypeError') diff --git a/tests/basics/dict_views.py b/tests/basics/dict_views.py index fbf63fa0ac..7ebcc1f56d 100644 --- a/tests/basics/dict_views.py +++ b/tests/basics/dict_views.py @@ -3,4 +3,19 @@ for m in d.items, d.values, d.keys: print(m()) print(list(m())) +# print a view with more than one item +print({1:1, 2:1}.values()) + +# unsupported binary op on a dict values view +try: + {1:1}.values() + 1 +except TypeError: + print('TypeError') + +# unsupported binary op on a dict keys view +try: + {1:1}.keys() + 1 +except TypeError: + print('TypeError') + # set operations still to come diff --git a/tests/basics/for_range.py b/tests/basics/for_range.py index ddff5ebd44..58a8f7caa7 100644 --- a/tests/basics/for_range.py +++ b/tests/basics/for_range.py @@ -34,6 +34,11 @@ try: print(x) except TypeError: print('TypeError') +try: + for x in range(start=0, end=1): + print(x) +except TypeError: + print('TypeError') try: for x in range(0, 1, step=1): print(x) diff --git a/tests/basics/int_constfolding.py b/tests/basics/int_constfolding.py index c01f964daa..aa38fa6b80 100644 --- a/tests/basics/int_constfolding.py +++ b/tests/basics/int_constfolding.py @@ -38,3 +38,8 @@ 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/slice_attrs.py b/tests/basics/slice_attrs.py index 76368a78c6..67456ff8e6 100644 --- a/tests/basics/slice_attrs.py +++ b/tests/basics/slice_attrs.py @@ -14,3 +14,12 @@ except: A()[1:2:3] + +# test storing to attr (shouldn't be allowed) +class B: + def __getitem__(self, idx): + try: + idx.start = 0 + except AttributeError: + print('AttributeError') +B()[:] diff --git a/tests/basics/syntaxerror.py b/tests/basics/syntaxerror.py index 2ae0183f8b..e5cbbac060 100644 --- a/tests/basics/syntaxerror.py +++ b/tests/basics/syntaxerror.py @@ -49,6 +49,9 @@ test_syntax("f[0]**2 = 1") # can't assign to empty tuple test_syntax("() = 1") +# can't have *x on RHS +test_syntax("x = *x") + # can't have multiple *x on LHS test_syntax("*a, *b = c") @@ -76,6 +79,7 @@ test_syntax("continue") test_syntax("return") test_syntax("yield") test_syntax("nonlocal a") +test_syntax("await 1") # error on uPy, warning on CPy #test_syntax("def f():\n a = 1\n global a") diff --git a/tests/basics/unpack1.py b/tests/basics/unpack1.py index 10e01dea06..0e8ec592c9 100644 --- a/tests/basics/unpack1.py +++ b/tests/basics/unpack1.py @@ -12,6 +12,7 @@ a, b, c = range(3); print(a, b, c) (a,) = range(1); print(a) (a, b) = range(2); print(a, b) (a, b, c) = range(3); print(a, b, c) +(a, (b, c)) = [-1, range(2)]; print(a, b, c) # lists diff --git a/tests/cmdline/cmd_showbc.py b/tests/cmdline/cmd_showbc.py index 9989a7229a..2f4e953bb2 100644 --- a/tests/cmdline/cmd_showbc.py +++ b/tests/cmdline/cmd_showbc.py @@ -34,12 +34,14 @@ def f(): # subscript p = b[0] b[0] = p + b[0] += p # slice a = b[::] # sequenc unpacking a, b = c + a, *a = a # tuple swapping a, b = b, a @@ -79,6 +81,7 @@ def f(): b while not a: b + a = a or a # for loop for a in b: @@ -92,6 +95,11 @@ def f(): b finally: c + while a: + try: + break + except: + pass # with with a: @@ -117,6 +125,12 @@ def f(): return return 1 +# function with lots of locals +def f(): + l1 = l2 = l3 = l4 = l5 = l6 = l7 = l8 = l9 = l10 = 1 + m1 = m2 = m3 = m4 = m5 = m6 = m7 = m8 = m9 = m10 = 2 + l10 + m10 + # functions with default args def f(a=1): pass @@ -133,3 +147,6 @@ def f(): # class class Class: pass + +# delete name +del Class diff --git a/tests/cmdline/cmd_showbc.py.exp b/tests/cmdline/cmd_showbc.py.exp index 0e5c559424..1f0c054cf9 100644 --- a/tests/cmdline/cmd_showbc.py.exp +++ b/tests/cmdline/cmd_showbc.py.exp @@ -7,9 +7,11 @@ arg names: (N_EXC_STACK 0) bc=-1 line=1 ######## - bc=\\d\+ line=134 + bc=\\d\+ line=152 00 MAKE_FUNCTION \.\+ \\d\+ STORE_NAME f +\\d\+ MAKE_FUNCTION \.\+ +\\d\+ STORE_NAME f \\d\+ LOAD_CONST_SMALL_INT 1 \\d\+ BUILD_TUPLE 1 \\d\+ LOAD_NULL @@ -22,6 +24,7 @@ arg names: \\d\+ LOAD_CONST_STRING 'Class' \\d\+ CALL_FUNCTION n=2 nkw=0 \\d\+ STORE_NAME Class +\\d\+ DELETE_NAME Class \\d\+ LOAD_CONST_NONE \\d\+ RETURN_VALUE File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) @@ -35,7 +38,7 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): (INIT_CELL 16) bc=-4 line=1 ######## - bc=\\d\+ line=118 + bc=\\d\+ line=126 00 LOAD_CONST_NONE 01 LOAD_CONST_FALSE 02 BINARY_OP 5 __add__ @@ -123,6 +126,14 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_CONST_SMALL_INT 0 \\d\+ STORE_SUBSCR \\d\+ LOAD_DEREF 14 +\\d\+ LOAD_CONST_SMALL_INT 0 +\\d\+ DUP_TOP_TWO +\\d\+ LOAD_SUBSCR +\\d\+ LOAD_FAST 12 +\\d\+ BINARY_OP 18 __iadd__ +\\d\+ ROT_THREE +\\d\+ STORE_SUBSCR +\\d\+ LOAD_DEREF 14 \\d\+ LOAD_CONST_NONE \\d\+ LOAD_CONST_NONE \\d\+ BUILD_SLICE 2 @@ -132,6 +143,10 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ UNPACK_SEQUENCE 2 \\d\+ STORE_FAST 0 \\d\+ STORE_DEREF 14 +\\d\+ LOAD_FAST 0 +\\d\+ UNPACK_EX 1 +\\d\+ STORE_FAST 0 +\\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ LOAD_FAST 0 \\d\+ ROT_TWO @@ -225,6 +240,10 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ POP_TOP \\d\+ LOAD_FAST 0 \\d\+ POP_JUMP_IF_FALSE \\d\+ +\\d\+ LOAD_FAST 0 +\\d\+ JUMP_IF_TRUE_OR_POP \\d\+ +\\d\+ LOAD_FAST 0 +\\d\+ STORE_FAST 0 \\d\+ LOAD_DEREF 14 \\d\+ GET_ITER \\d\+ FOR_ITER \\d\+ @@ -251,6 +270,17 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): \\d\+ LOAD_FAST 1 \\d\+ POP_TOP \\d\+ END_FINALLY +\\d\+ JUMP \\d\+ +\\d\+ SETUP_EXCEPT \\d\+ +\\d\+ UNWIND_JUMP \\d\+ 1 +\\d\+ POP_BLOCK +\\d\+ JUMP \\d\+ +\\d\+ POP_TOP +\\d\+ POP_EXCEPT +\\d\+ JUMP \\d\+ +\\d\+ END_FINALLY +\\d\+ LOAD_FAST 0 +\\d\+ POP_JUMP_IF_TRUE \\d\+ \\d\+ LOAD_FAST 0 \\d\+ SETUP_WITH \\d\+ \\d\+ POP_TOP @@ -291,13 +321,68 @@ Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): ######## +\.\+rg names: +(N_STATE 22) +(N_EXC_STACK 0) + bc=-1 line=1 +######## + bc=\\d\+ line=132 +00 LOAD_CONST_SMALL_INT 1 +01 DUP_TOP +02 STORE_FAST 0 +03 DUP_TOP +04 STORE_FAST 1 +05 DUP_TOP +06 STORE_FAST 2 +07 DUP_TOP +08 STORE_FAST 3 +09 DUP_TOP +10 STORE_FAST 4 +11 DUP_TOP +12 STORE_FAST 5 +13 DUP_TOP +14 STORE_FAST 6 +15 DUP_TOP +16 STORE_FAST 7 +17 DUP_TOP +18 STORE_FAST 8 +19 STORE_FAST 9 +20 LOAD_CONST_SMALL_INT 2 +21 DUP_TOP +22 STORE_FAST 10 +23 DUP_TOP +24 STORE_FAST 11 +25 DUP_TOP +26 STORE_FAST 12 +27 DUP_TOP +28 STORE_FAST 13 +29 DUP_TOP +30 STORE_FAST 14 +31 DUP_TOP +32 STORE_FAST 15 +33 DUP_TOP +34 STORE_FAST_N 16 +36 DUP_TOP +37 STORE_FAST_N 17 +39 DUP_TOP +40 STORE_FAST_N 18 +42 STORE_FAST_N 19 +44 LOAD_FAST 9 +45 LOAD_FAST_N 19 +47 BINARY_OP 5 __add__ +48 POP_TOP +49 LOAD_CONST_NONE +50 RETURN_VALUE +File cmdline/cmd_showbc.py, code block 'f' (descriptor: \.\+, bytecode @\.\+ bytes) +Raw bytecode (code_info_size=\\d\+, bytecode_size=\\d\+): +######## \.\+5b arg names: a (N_STATE 5) (N_EXC_STACK 0) (INIT_CELL 0) ######## - bc=\\d\+ line=124 + bc=\\d\+ line=138 00 LOAD_CONST_SMALL_INT 2 01 BUILD_TUPLE 1 03 LOAD_NULL @@ -314,9 +399,9 @@ arg names: (N_STATE 2) (N_EXC_STACK 0) bc=-1 line=1 - bc=0 line=129 - bc=3 line=130 - bc=6 line=131 + bc=0 line=143 + bc=3 line=144 + bc=6 line=145 00 LOAD_CONST_NONE 01 YIELD_VALUE 02 POP_TOP @@ -338,7 +423,7 @@ arg names: (N_STATE 1) (N_EXC_STACK 0) bc=-1 line=1 - bc=13 line=135 + bc=13 line=149 00 LOAD_NAME __name__ (cache=0) 04 STORE_NAME __module__ 07 LOAD_CONST_STRING 'Class' @@ -411,7 +496,7 @@ arg names: * (N_EXC_STACK 0) bc=-\\d\+ line=1 ######## - bc=\\d\+ line=105 + bc=\\d\+ line=113 00 LOAD_DEREF 0 02 LOAD_CONST_SMALL_INT 1 03 BINARY_OP 5 __add__ @@ -430,7 +515,7 @@ arg names: * b (N_EXC_STACK 0) bc=-\\d\+ line=1 ######## - bc=\\d\+ line=125 + bc=\\d\+ line=139 00 LOAD_FAST 1 01 LOAD_DEREF 0 03 BINARY_OP 5 __add__ diff --git a/tests/cmdline/repl_basic.py b/tests/cmdline/repl_basic.py index b416493dce..cbd5d3a4ac 100644 --- a/tests/cmdline/repl_basic.py +++ b/tests/cmdline/repl_basic.py @@ -1,3 +1,4 @@ # basic REPL tests print(1)  +2 diff --git a/tests/cmdline/repl_basic.py.exp b/tests/cmdline/repl_basic.py.exp index 96b8c28dce..2b390ea98b 100644 --- a/tests/cmdline/repl_basic.py.exp +++ b/tests/cmdline/repl_basic.py.exp @@ -5,4 +5,6 @@ Use \.\+ 1 >>> print(1) 1 +>>> 2 +2 >>> diff --git a/tests/extmod/ujson_load.py b/tests/extmod/ujson_load.py new file mode 100644 index 0000000000..bf484a2074 --- /dev/null +++ b/tests/extmod/ujson_load.py @@ -0,0 +1,11 @@ +try: + from uio import StringIO + import ujson as json +except: + from io import StringIO + import json + +print(json.load(StringIO('null'))) +print(json.load(StringIO('"abc\\u0064e"'))) +print(json.load(StringIO('[false, true, 1, -2]'))) +print(json.load(StringIO('{"a":true}'))) diff --git a/tests/extmod/vfs_fat_ramdisk.py b/tests/extmod/vfs_fat_ramdisk.py index f470dbcfe7..6380761c6d 100644 --- a/tests/extmod/vfs_fat_ramdisk.py +++ b/tests/extmod/vfs_fat_ramdisk.py @@ -41,8 +41,8 @@ except MemoryError: uos.VfsFat.mkfs(bdev) -assert b"FOO_FILETXT" not in bdev.data -assert b"hello!" not in bdev.data +print(b"FOO_FILETXT" not in bdev.data) +print(b"hello!" not in bdev.data) vfs = uos.VfsFat(bdev, "/ramdisk") print("statvfs:", vfs.statvfs("/ramdisk")) @@ -57,44 +57,66 @@ f2 = vfs.open("foo_file.txt") print(f2.read()) f2.close() -assert b"FOO_FILETXT" in bdev.data -assert b"hello!" in bdev.data +print(b"FOO_FILETXT" in bdev.data) +print(b"hello!" in bdev.data) -assert vfs.listdir() == ['foo_file.txt'] +print(vfs.listdir()) + +try: + vfs.rmdir("foo_file.txt") +except OSError as e: + print(e.args[0] == 20) # uerrno.ENOTDIR vfs.remove('foo_file.txt') -assert vfs.listdir() == [] +print(vfs.listdir()) vfs.mkdir("foo_dir") -assert vfs.listdir() == ['foo_dir'] +print(vfs.listdir()) + +try: + vfs.remove("foo_dir") +except OSError as e: + print(e.args[0] == uerrno.EISDIR) + f = vfs.open("foo_dir/file-in-dir.txt", "w") f.write("data in file") f.close() -assert vfs.listdir("foo_dir") == ['file-in-dir.txt'] +print(vfs.listdir("foo_dir")) vfs.rename("foo_dir/file-in-dir.txt", "moved-to-root.txt") -assert vfs.listdir() == ['foo_dir', 'moved-to-root.txt'] +print(vfs.listdir()) vfs.chdir("foo_dir") print("getcwd:", vfs.getcwd()) -assert vfs.listdir() == [] +print(vfs.listdir()) with vfs.open("sub_file.txt", "w") as f: f.write("test2") -assert vfs.listdir() == ["sub_file.txt"] +print(vfs.listdir()) + +try: + vfs.chdir("sub_file.txt") +except OSError as e: + print(e.args[0] == uerrno.ENOENT) vfs.chdir("..") print("getcwd:", vfs.getcwd()) +try: + vfs.rmdir("foo_dir") +except OSError as e: + print(e.args[0] == uerrno.EACCES) + +vfs.remove("foo_dir/sub_file.txt") +vfs.rmdir("foo_dir") +print(vfs.listdir()) vfs.umount() try: vfs.listdir() except OSError as e: - assert e.args[0] == uerrno.ENODEV -else: - raise AssertionError("expected OSError not thrown") + print(e.args[0] == uerrno.ENODEV) vfs = uos.VfsFat(bdev, "/ramdisk") -assert vfs.listdir() == ['foo_dir', 'moved-to-root.txt'] +print(vfs.listdir()) diff --git a/tests/extmod/vfs_fat_ramdisk.py.exp b/tests/extmod/vfs_fat_ramdisk.py.exp index fd893b6e4c..8a498b2fc4 100644 --- a/tests/extmod/vfs_fat_ramdisk.py.exp +++ b/tests/extmod/vfs_fat_ramdisk.py.exp @@ -1,5 +1,23 @@ +True +True statvfs: (512, 512, 14, 14, 14, 0, 0, 0, 0, 255) getcwd: /ramdisk hello! +True +True +['foo_file.txt'] +True +[] +['foo_dir'] +True +['file-in-dir.txt'] +['foo_dir', 'moved-to-root.txt'] getcwd: /ramdisk/foo_dir +[] +['sub_file.txt'] +True getcwd: /ramdisk +True +['moved-to-root.txt'] +True +['moved-to-root.txt'] diff --git a/tests/import/import2a.py b/tests/import/import2a.py index ce32b10b1b..def6aeb6aa 100644 --- a/tests/import/import2a.py +++ b/tests/import/import2a.py @@ -1,2 +1,5 @@ from import1b import var print(var) + +from import1b import var as var2 +print(var2) diff --git a/tests/micropython/emg_exc.py b/tests/micropython/emg_exc.py new file mode 100644 index 0000000000..d228e6faab --- /dev/null +++ b/tests/micropython/emg_exc.py @@ -0,0 +1,20 @@ +# test that emergency exceptions work + +import micropython +import sys + +# some ports need to allocate heap for the emg exc +try: + micropython.alloc_emergency_exception_buf(256) +except AttributeError: + pass + +def f(): + micropython.heap_lock() + try: + raise ValueError(1) + except ValueError as er: + sys.print_exception(er) + micropython.heap_unlock() + +f() diff --git a/tests/micropython/emg_exc.py.exp b/tests/micropython/emg_exc.py.exp new file mode 100644 index 0000000000..82b10b5f54 --- /dev/null +++ b/tests/micropython/emg_exc.py.exp @@ -0,0 +1 @@ +ValueError: diff --git a/tests/micropython/heap_lock.py b/tests/micropython/heap_lock.py new file mode 100644 index 0000000000..0f0a70eff1 --- /dev/null +++ b/tests/micropython/heap_lock.py @@ -0,0 +1,14 @@ +# check that heap_lock/heap_unlock work as expected + +import micropython + +micropython.heap_lock() + +try: + print([]) +except MemoryError: + print('MemoryError') + +micropython.heap_unlock() + +print([]) diff --git a/tests/micropython/heap_lock.py.exp b/tests/micropython/heap_lock.py.exp new file mode 100644 index 0000000000..67b208cfc5 --- /dev/null +++ b/tests/micropython/heap_lock.py.exp @@ -0,0 +1,2 @@ +MemoryError +[] diff --git a/tests/micropython/heapalloc.py b/tests/micropython/heapalloc.py index 2dc7fa5e7e..a651158ca5 100644 --- a/tests/micropython/heapalloc.py +++ b/tests/micropython/heapalloc.py @@ -1,6 +1,6 @@ # check that we can do certain things without allocating heap memory -import gc +import micropython def f1(a): print(a) @@ -28,12 +28,7 @@ def test(): f2(i, i) # 2 args f3(1, 2, 3, 4) # function with lots of local state -# call h with heap allocation disabled and all memory used up -gc.disable() -try: - while True: - 'a'.lower # allocates 1 cell for boundmeth -except MemoryError: - pass +# call test() with heap allocation disabled +micropython.heap_lock() test() -gc.enable() +micropython.heap_unlock() diff --git a/tests/micropython/opt_level.py b/tests/micropython/opt_level.py new file mode 100644 index 0000000000..4e2f2f4ea3 --- /dev/null +++ b/tests/micropython/opt_level.py @@ -0,0 +1,14 @@ +import micropython as micropython + +# check we can get and set the level +micropython.opt_level(0) +print(micropython.opt_level()) +micropython.opt_level(1) +print(micropython.opt_level()) + +# check that the optimisation levels actually differ +micropython.opt_level(0) +exec('print(__debug__)') +micropython.opt_level(1) +exec('print(__debug__)') +exec('assert 0') diff --git a/tests/micropython/opt_level.py.exp b/tests/micropython/opt_level.py.exp new file mode 100644 index 0000000000..74b3dd74e8 --- /dev/null +++ b/tests/micropython/opt_level.py.exp @@ -0,0 +1,4 @@ +0 +1 +True +False diff --git a/tests/micropython/viper_args.py b/tests/micropython/viper_args.py index ca2a5e6704..2aebe1b048 100644 --- a/tests/micropython/viper_args.py +++ b/tests/micropython/viper_args.py @@ -26,3 +26,11 @@ def f4(x1:int, x2:int, x3:int, x4:int): f4(1, 2, 3, 4) # only up to 4 arguments currently supported + +# test compiling *x, **x, * args (currently unsupported at runtime) +@micropython.viper +def f(*x, **y): + pass +@micropython.viper +def f(*): + pass diff --git a/tests/misc/non_compliant.py b/tests/misc/non_compliant.py index 1157ff8b29..677438b832 100644 --- a/tests/misc/non_compliant.py +++ b/tests/misc/non_compliant.py @@ -3,6 +3,18 @@ import array import ustruct +# when super can't find self +try: + exec('def f(): super()') +except SyntaxError: + print('SyntaxError') + +# store to exception attribute is not allowed +try: + ValueError().x = 0 +except AttributeError: + print('AttributeError') + # array deletion not implemented try: a = array.array('b', (1, 2, 3)) @@ -17,6 +29,12 @@ try: except NotImplementedError: print('NotImplementedError') +# containment, looking for integer not implemented +try: + print(1 in array.array('B', b'12')) +except NotImplementedError: + print('NotImplementedError') + # should raise type error try: print(set('12') >= '1') @@ -59,6 +77,12 @@ try: except NotImplementedError: print('NotImplementedError') +# str subscr with step!=1 not implemented +try: + print('abc'[1:2:3]) +except NotImplementedError: + print('NotImplementedError') + # bytes(...) with keywords not implemented try: bytes('abc', encoding='utf8') diff --git a/tests/misc/non_compliant.py.exp b/tests/misc/non_compliant.py.exp index c03580442d..737650e9e9 100644 --- a/tests/misc/non_compliant.py.exp +++ b/tests/misc/non_compliant.py.exp @@ -1,5 +1,8 @@ +SyntaxError +AttributeError TypeError NotImplementedError +NotImplementedError True True TypeError, ValueError @@ -12,5 +15,6 @@ NotImplementedError NotImplementedError NotImplementedError NotImplementedError +NotImplementedError b'\x01\x02' b'\x01\x00' diff --git a/tests/run-tests b/tests/run-tests index cb920c0946..4ac7d8e28f 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -237,7 +237,6 @@ def run_tests(pyb, tests, args): skip_tests.add('float/float_divmod.py') # tested by float/float_divmod_relaxed.py instead skip_tests.add('float/float2int_doubleprec.py') # requires double precision floating point to work skip_tests.add('micropython/meminfo.py') # output is very different to PC output - skip_tests.add('extmod/machine1.py') # raw memory access not supported skip_tests.add('extmod/machine_mem.py') # raw memory access not supported if args.target == 'wipy': @@ -273,7 +272,7 @@ def run_tests(pyb, tests, args): if args.emit == 'native': skip_tests.update({'basics/%s.py' % t for t in 'gen_yield_from gen_yield_from_close gen_yield_from_ducktype gen_yield_from_exc gen_yield_from_iter gen_yield_from_send gen_yield_from_stopped gen_yield_from_throw generator1 generator2 generator_args generator_close generator_closure generator_exc generator_return generator_send'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'bytes_gen class_store_class globals_del string_join'.split()}) # require yield - skip_tests.update({'basics/async_%s.py' % t for t in 'await await2 for for2 with with2'.split()}) # require yield + skip_tests.update({'basics/async_%s.py' % t for t in 'def await await2 for for2 with with2'.split()}) # require yield skip_tests.update({'basics/%s.py' % t for t in 'try_reraise try_reraise2'.split()}) # require raise_varargs skip_tests.update({'basics/%s.py' % t for t in 'with_break with_continue with_return'.split()}) # require complete with support skip_tests.add('basics/array_construct2.py') # requires generators diff --git a/tests/unicode/unicode.py b/tests/unicode/unicode.py index b31f064e9c..5f29bc1c95 100644 --- a/tests/unicode/unicode.py +++ b/tests/unicode/unicode.py @@ -18,8 +18,9 @@ enc = s.encode() print(enc, enc.decode() == s) # printing of unicode chars using repr -# TODO we don't do this correctly -#print(repr(s)) +# NOTE: for some characters (eg \u10ff) we differ to CPython +print(repr('a\uffff')) +print(repr('a\U0001ffff')) # test invalid escape code try: diff --git a/tools/micropython-upip-1.0.tar.gz b/tools/micropython-upip-1.0.tar.gz deleted file mode 100644 index f349150708..0000000000 Binary files a/tools/micropython-upip-1.0.tar.gz and /dev/null differ diff --git a/tools/micropython-upip-1.1.3.tar.gz b/tools/micropython-upip-1.1.3.tar.gz new file mode 100644 index 0000000000..90f726d862 Binary files /dev/null and b/tools/micropython-upip-1.1.3.tar.gz differ diff --git a/tools/tinytest-codegen.py b/tools/tinytest-codegen.py index 091c1b065f..bab937135f 100755 --- a/tools/tinytest-codegen.py +++ b/tools/tinytest-codegen.py @@ -46,8 +46,15 @@ testgroup_member = ( ## XXX: may be we could have `--without ` argument... # currently these tests are selected because they pass on qemu-arm -test_dirs = ('basics', 'micropython', 'inlineasm') # 'float', 'import', 'io', 'misc') -exclude_tests = ('inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py', 'inlineasm/asmfpsqrt.py',) +test_dirs = ('basics', 'micropython', 'extmod', 'inlineasm') # 'float', 'import', 'io', 'misc') +exclude_tests = ( + 'inlineasm/asmfpaddsub.py', 'inlineasm/asmfpcmp.py', 'inlineasm/asmfpldrstr.py', 'inlineasm/asmfpmuldiv.py', 'inlineasm/asmfpsqrt.py', + 'extmod/time_ms_us.py', + 'extmod/ujson_dumps_float.py', 'extmod/ujson_loads_float.py', + 'extmod/uctypes_native_float.py', 'extmod/uctypes_le_float.py', + 'extmod/machine_pinbase.py', 'extmod/machine_pulse.py', + 'extmod/vfs_fat_ramdisk.py', +) output = [] diff --git a/unix/Makefile b/unix/Makefile index 4a313b3a80..53ff4cb487 100644 --- a/unix/Makefile +++ b/unix/Makefile @@ -273,7 +273,7 @@ coverage_test: coverage gcov -o build-coverage/extmod ../extmod/*.c $(BUILD)/_frozen_upip.c: $(BUILD)/frozen_upip/upip.py - ../tools/make-frozen.py $(dir $^) > $@ + $(MAKE_FROZEN) $(dir $^) > $@ # Select latest upip version available UPIP_TARBALL := $(shell ls -1 -v ../tools/micropython-upip-*.tar.gz | tail -n1) diff --git a/unix/coverage.c b/unix/coverage.c index c84a653f75..6a1b43fdce 100644 --- a/unix/coverage.c +++ b/unix/coverage.c @@ -34,7 +34,7 @@ STATIC mp_obj_t extra_coverage(void) { // vstr { mp_printf(&mp_plat_print, "# vstr\n"); - vstr_t *vstr = vstr_new_size(16); + vstr_t *vstr = vstr_new(16); vstr_hint_size(vstr, 32); vstr_add_str(vstr, "ts"); vstr_ins_byte(vstr, 1, 'e'); diff --git a/zephyr/Makefile b/zephyr/Makefile index d0dce488db..9682dc5ccf 100644 --- a/zephyr/Makefile +++ b/zephyr/Makefile @@ -15,6 +15,8 @@ BOARD ?= qemu_x86 # Zephyr 1.6.0 OUTDIR_PREFIX = $(BOARD) +FROZEN_DIR = scripts + # Zephyr (generated) config files - must be defined before include below Z_SYSGEN_H = outdir/$(OUTDIR_PREFIX)/misc/generated/sysgen/sysgen.h Z_EXPORTS = outdir/$(OUTDIR_PREFIX)/Makefile.export @@ -31,13 +33,19 @@ INC += -I$(ZEPHYR_BASE)/net/ip/contiki INC += -I$(ZEPHYR_BASE)/net/ip/contiki/os SRC_C = main.c \ + help.c \ uart_core.c \ lib/utils/stdout_helpers.c \ lib/utils/printf.c \ lib/utils/pyexec.c \ + lib/utils/interrupt_char.c \ + lib/utils/pyhelp.c \ lib/mp-readline/readline.c \ $(SRC_MOD) +# List of sources for qstr extraction +SRC_QSTR += $(SRC_C) + OBJ = $(PY_O) $(addprefix $(BUILD)/, $(SRC_C:.c=.o)) CFLAGS = $(KBUILD_CFLAGS) $(NOSTDINC_FLAGS) $(ZEPHYRINCLUDE) \ diff --git a/zephyr/README.md b/zephyr/README.md index 43e92c787b..63fb0e39f4 100644 --- a/zephyr/README.md +++ b/zephyr/README.md @@ -41,5 +41,5 @@ qemu_cortex_m3): make qemu -For deploying/flashing teh application on a real board, follow Zephyr +For deploying/flashing the application on a real board, follow Zephyr documentation for a given board. diff --git a/zephyr/help.c b/zephyr/help.c new file mode 100644 index 0000000000..e574adf473 --- /dev/null +++ b/zephyr/help.c @@ -0,0 +1,56 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013-2016 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 + +#include "lib/utils/pyhelp.h" + +STATIC const char *help_text = +"Welcome to MicroPython!\n" +"\n" +"Control commands:\n" +" CTRL-A -- on a blank line, enter raw REPL mode\n" +" CTRL-B -- on a blank line, enter normal REPL mode\n" +" CTRL-C -- interrupt a running program\n" +" CTRL-D -- on a blank line, do a soft reset of the board\n" +" CTRL-E -- on a blank line, enter paste mode\n" +"\n" +"For further help on a specific object, type help(obj)\n" +; + +STATIC mp_obj_t builtin_help(uint n_args, const mp_obj_t *args) { + if (n_args == 0) { + // print a general help message + printf("%s", help_text); + + } else { + // try to print something sensible about the given object + pyhelp_print_obj(args[0]); + } + + return mp_const_none; +} +MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_help_obj, 0, 1, builtin_help); diff --git a/zephyr/main.c b/zephyr/main.c index 65074b157e..8d319098b2 100644 --- a/zephyr/main.c +++ b/zephyr/main.c @@ -1,3 +1,29 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2013, 2014 Damien P. George + * Copyright (c) 2016 Linaro Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include #include #include @@ -7,7 +33,9 @@ #include "py/runtime.h" #include "py/repl.h" #include "py/gc.h" +#include "py/stackctrl.h" #include "lib/utils/pyexec.h" +#include "lib/mp-readline/readline.h" 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); @@ -35,11 +63,16 @@ static char heap[16 * 1024]; int real_main(void) { int stack_dummy; stack_top = (char*)&stack_dummy; + mp_stack_set_top(stack_top); + // Should be set to stack size in prj.mdef minus fuzz factor + mp_stack_set_limit(3584); #if MICROPY_ENABLE_GC gc_init(heap, heap + sizeof(heap)); #endif mp_init(); + MP_STATE_PORT(mp_kbd_exception) = mp_obj_new_exception(&mp_type_KeyboardInterrupt); + pyexec_frozen_module("main.py"); #if MICROPY_REPL_EVENT_DRIVEN pyexec_event_repl_init(); for (;;) { diff --git a/zephyr/mpconfigport.h b/zephyr/mpconfigport.h index cf5884e0e7..1654e79b8c 100644 --- a/zephyr/mpconfigport.h +++ b/zephyr/mpconfigport.h @@ -1,10 +1,39 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Linaro Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include +// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles +#include "autoconf.h" + // Saving extra crumbs to make sure binary fits in 128K #define MICROPY_COMP_CONST_FOLDING (0) #define MICROPY_COMP_CONST (0) #define MICROPY_COMP_DOUBLE_TUPLE_ASSIGN (0) +#define MICROPY_STACK_CHECK (1) #define MICROPY_ENABLE_GC (1) #define MICROPY_HELPER_REPL (1) #define MICROPY_REPL_AUTO_INDENT (1) @@ -23,6 +52,7 @@ #define MICROPY_PY_COLLECTIONS (0) #define MICROPY_PY_CMATH (0) #define MICROPY_PY_IO (0) +#define MICROPY_PY_MICROPYTHON_MEM_INFO (1) #define MICROPY_PY_STRUCT (0) #define MICROPY_PY_SYS_MODULES (0) #define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) @@ -30,6 +60,7 @@ #define MICROPY_PY_BUILTINS_COMPLEX (0) #define MICROPY_HW_BOARD_NAME "zephyr-generic" #define MICROPY_HW_MCU_NAME "unknown-cpu" +#define MICROPY_MODULE_FROZEN_STR (1) typedef int mp_int_t; // must be pointer size typedef unsigned mp_uint_t; // must be pointer size @@ -43,7 +74,10 @@ typedef long mp_off_t; #define MP_STATE_PORT MP_STATE_VM #define MICROPY_PORT_ROOT_POINTERS \ + mp_obj_t mp_kbd_exception; \ const char *readline_hist[8]; -// Include Zephyr's autoconf.h, which should be made first by Zephyr makefiles -#include "autoconf.h" +// extra built in names to add to the global namespace +#define MICROPY_PORT_BUILTINS \ + { MP_OBJ_NEW_QSTR(MP_QSTR_help), (mp_obj_t)&mp_builtin_help_obj }, \ + diff --git a/zephyr/mphalport.h b/zephyr/mphalport.h index 60d68bd2d6..1bb64e0002 100644 --- a/zephyr/mphalport.h +++ b/zephyr/mphalport.h @@ -1,2 +1 @@ static inline mp_uint_t mp_hal_ticks_ms(void) { return 0; } -static inline void mp_hal_set_interrupt_char(char c) {} diff --git a/zephyr/src/zephyr_getchar.c b/zephyr/src/zephyr_getchar.c index 3a1898a607..89e3e0efbc 100644 --- a/zephyr/src/zephyr_getchar.c +++ b/zephyr/src/zephyr_getchar.c @@ -20,6 +20,9 @@ #include #include "zephyr_getchar.h" +extern int mp_interrupt_char; +void mp_keyboard_interrupt(void); + static struct nano_sem uart_sem; #define UART_BUFSIZE 256 static uint8_t uart_ringbuf[UART_BUFSIZE]; @@ -32,8 +35,13 @@ static int console_irq_input_hook(struct device *dev, uint8_t ch) printk("UART buffer overflow - char dropped\n"); return 1; } - uart_ringbuf[i_put] = ch; - i_put = i_next; + if (ch == mp_interrupt_char) { + mp_keyboard_interrupt(); + return 1; + } else { + uart_ringbuf[i_put] = ch; + i_put = i_next; + } //printk("%x\n", ch); nano_isr_sem_give(&uart_sem); return 1; diff --git a/zephyr/src/zephyr_start.c b/zephyr/src/zephyr_start.c index b490cc7709..9e8a90bebd 100644 --- a/zephyr/src/zephyr_start.c +++ b/zephyr/src/zephyr_start.c @@ -1,3 +1,28 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Linaro Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include #include "zephyr_getchar.h" diff --git a/zephyr/uart_core.c b/zephyr/uart_core.c index 5f48f973f6..702c97d20a 100644 --- a/zephyr/uart_core.c +++ b/zephyr/uart_core.c @@ -1,3 +1,28 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2016 Linaro Limited + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ #include #include "py/mpconfig.h" #include "src/zephyr_getchar.h"