Merge branch 'master' into nrf5_no_sdk
This commit is contained in:
commit
fd8f2c36f5
4
.gitignore
vendored
4
.gitignore
vendored
@ -38,3 +38,7 @@ __pycache__/
|
|||||||
######################
|
######################
|
||||||
GNUmakefile
|
GNUmakefile
|
||||||
user.props
|
user.props
|
||||||
|
|
||||||
|
# Generated rst files
|
||||||
|
######################
|
||||||
|
genrst/
|
||||||
|
@ -48,6 +48,7 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
|
|||||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||||
|
|
||||||
void nlr_jump_fail(void *val) {
|
void nlr_jump_fail(void *val) {
|
||||||
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NORETURN __fatal_error(const char *msg) {
|
void NORETURN __fatal_error(const char *msg) {
|
||||||
|
@ -26,8 +26,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include "std.h"
|
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "hw_ints.h"
|
#include "hw_ints.h"
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "std.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
@ -25,8 +25,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <ctype.h>
|
#include <stdio.h>
|
||||||
#include "std.h"
|
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
@ -500,12 +499,12 @@ static void ftp_wait_for_enabled (void) {
|
|||||||
|
|
||||||
static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
|
static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
|
||||||
SlSockNonblocking_t nonBlockingOption;
|
SlSockNonblocking_t nonBlockingOption;
|
||||||
sockaddr_in sServerAddress;
|
SlSockAddrIn_t sServerAddress;
|
||||||
_i16 _sd;
|
_i16 _sd;
|
||||||
_i16 result;
|
_i16 result;
|
||||||
|
|
||||||
// Open a socket for ftp data listen
|
// Open a socket for ftp data listen
|
||||||
ASSERT ((*sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_IP)) > 0);
|
ASSERT ((*sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_IP)) > 0);
|
||||||
_sd = *sd;
|
_sd = *sd;
|
||||||
|
|
||||||
if (_sd > 0) {
|
if (_sd > 0) {
|
||||||
@ -514,12 +513,12 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
|
|||||||
|
|
||||||
// Enable non-blocking mode
|
// Enable non-blocking mode
|
||||||
nonBlockingOption.NonblockingEnabled = 1;
|
nonBlockingOption.NonblockingEnabled = 1;
|
||||||
ASSERT ((result = sl_SetSockOpt(_sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
|
ASSERT ((result = sl_SetSockOpt(_sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
|
||||||
|
|
||||||
// Bind the socket to a port number
|
// Bind the socket to a port number
|
||||||
sServerAddress.sin_family = AF_INET;
|
sServerAddress.sin_family = SL_AF_INET;
|
||||||
sServerAddress.sin_addr.s_addr = INADDR_ANY;
|
sServerAddress.sin_addr.s_addr = SL_INADDR_ANY;
|
||||||
sServerAddress.sin_port = htons(port);
|
sServerAddress.sin_port = sl_Htons(port);
|
||||||
|
|
||||||
ASSERT ((result |= sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
|
ASSERT ((result |= sl_Bind(_sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
|
||||||
|
|
||||||
@ -535,7 +534,7 @@ static bool ftp_create_listening_socket (_i16 *sd, _u16 port, _u8 backlog) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) {
|
static ftp_result_t ftp_wait_for_connection (_i16 l_sd, _i16 *n_sd) {
|
||||||
sockaddr_in sClientAddress;
|
SlSockAddrIn_t sClientAddress;
|
||||||
SlSocklen_t in_addrSize;
|
SlSocklen_t in_addrSize;
|
||||||
|
|
||||||
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
|
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
|
||||||
@ -932,6 +931,13 @@ static void ftp_close_cmd_data (void) {
|
|||||||
ftp_close_filesystem_on_error ();
|
ftp_close_filesystem_on_error ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void stoupper (char *str) {
|
||||||
|
while (str && *str != '\0') {
|
||||||
|
*str = (char)unichar_toupper((int)(*str));
|
||||||
|
str++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ftp_cmd_index_t ftp_pop_command (char **str) {
|
static ftp_cmd_index_t ftp_pop_command (char **str) {
|
||||||
char _cmd[FTP_CMD_SIZE_MAX];
|
char _cmd[FTP_CMD_SIZE_MAX];
|
||||||
ftp_pop_param (str, _cmd);
|
ftp_pop_param (str, _cmd);
|
||||||
|
@ -98,13 +98,6 @@ int main (void) {
|
|||||||
for ( ; ; );
|
for ( ; ; );
|
||||||
}
|
}
|
||||||
|
|
||||||
void stoupper (char *str) {
|
|
||||||
while (str && *str != '\0') {
|
|
||||||
*str = (char)toupper((int)(*str));
|
|
||||||
str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need this when configSUPPORT_STATIC_ALLOCATION is enabled
|
// We need this when configSUPPORT_STATIC_ALLOCATION is enabled
|
||||||
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
|
void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer,
|
||||||
StackType_t **ppxIdleTaskStackBuffer,
|
StackType_t **ppxIdleTaskStackBuffer,
|
||||||
|
@ -40,9 +40,6 @@ STATIC void mpexception_set_user_interrupt (int chr, void *data);
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE EXPORTED DATA
|
DECLARE EXPORTED DATA
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
const char mpexception_os_resource_not_avaliable[] = "resource not available";
|
|
||||||
const char mpexception_os_operation_failed[] = "the requested operation failed";
|
|
||||||
const char mpexception_os_request_not_possible[] = "the requested operation is not possible";
|
|
||||||
const char mpexception_value_invalid_arguments[] = "invalid argument(s) value";
|
const char mpexception_value_invalid_arguments[] = "invalid argument(s) value";
|
||||||
const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type";
|
const char mpexception_num_type_invalid_arguments[] = "invalid argument(s) num/type";
|
||||||
const char mpexception_uncaught[] = "uncaught exception";
|
const char mpexception_uncaught[] = "uncaught exception";
|
||||||
|
@ -28,9 +28,6 @@
|
|||||||
#ifndef MPEXCEPTION_H_
|
#ifndef MPEXCEPTION_H_
|
||||||
#define MPEXCEPTION_H_
|
#define MPEXCEPTION_H_
|
||||||
|
|
||||||
extern const char mpexception_os_resource_not_avaliable[];
|
|
||||||
extern const char mpexception_os_operation_failed[];
|
|
||||||
extern const char mpexception_os_request_not_possible[];
|
|
||||||
extern const char mpexception_value_invalid_arguments[];
|
extern const char mpexception_value_invalid_arguments[];
|
||||||
extern const char mpexception_num_type_invalid_arguments[];
|
extern const char mpexception_num_type_invalid_arguments[];
|
||||||
extern const char mpexception_uncaught[];
|
extern const char mpexception_uncaught[];
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "std.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "std.h"
|
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
@ -25,12 +25,11 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <std.h>
|
|
||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/nlr.h"
|
#include "py/nlr.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "modnetwork.h"
|
#include "modnetwork.h"
|
||||||
#include "mpexception.h"
|
#include "mpexception.h"
|
||||||
@ -101,7 +100,7 @@ STATIC mp_obj_t network_server_make_new(const mp_obj_type_t *type, size_t n_args
|
|||||||
// check the server id
|
// check the server id
|
||||||
if (args[0].u_obj != MP_OBJ_NULL) {
|
if (args[0].u_obj != MP_OBJ_NULL) {
|
||||||
if (mp_obj_get_int(args[0].u_obj) != 0) {
|
if (mp_obj_get_int(args[0].u_obj) != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ STATIC void hash_update_internal(mp_obj_t self_in, mp_obj_t data, bool digest) {
|
|||||||
self->digested = false;
|
self->digested = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +106,7 @@ STATIC mp_obj_t hash_read (mp_obj_t self_in) {
|
|||||||
}
|
}
|
||||||
} else if (self->c_size < self->b_size) {
|
} else if (self->c_size < self->b_size) {
|
||||||
// it's a fixed len block which is still incomplete
|
// it's a fixed len block which is still incomplete
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!self->digested) {
|
if (!self->digested) {
|
||||||
|
@ -173,9 +173,6 @@ STATIC const mp_map_elem_t os_module_globals_table[] = {
|
|||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&mp_vfs_umount_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_umount), (mp_obj_t)&mp_vfs_umount_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_VfsFat), (mp_obj_t)&mp_fat_vfs_type },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_VfsFat), (mp_obj_t)&mp_fat_vfs_type },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&os_dupterm_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_dupterm), (mp_obj_t)&os_dupterm_obj },
|
||||||
|
|
||||||
/// \constant sep - separation character used in paths
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_sep), MP_OBJ_NEW_QSTR(MP_QSTR__slash_) },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
STATIC MP_DEFINE_CONST_DICT(os_module_globals, os_module_globals_table);
|
||||||
|
@ -36,10 +36,252 @@
|
|||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "netutils.h"
|
#include "netutils.h"
|
||||||
#include "modnetwork.h"
|
#include "modnetwork.h"
|
||||||
#include "modwlan.h"
|
|
||||||
#include "modusocket.h"
|
#include "modusocket.h"
|
||||||
#include "mpexception.h"
|
#include "mpexception.h"
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
// The following set of macros and functions provide a glue between the CC3100
|
||||||
|
// simplelink layer and the functions/methods provided by the usocket module.
|
||||||
|
// They were historically in a separate file because usocket was designed to
|
||||||
|
// work with multiple NICs, and the wlan_XXX functions just provided one
|
||||||
|
// particular NIC implementation (that of the CC3100). But the CC3200 port only
|
||||||
|
// supports a single NIC (being the CC3100) so it's unnecessary and inefficient
|
||||||
|
// to provide an intermediate wrapper layer. Hence the wlan_XXX functions
|
||||||
|
// are provided below as static functions so they can be inlined directly by
|
||||||
|
// the corresponding usocket calls.
|
||||||
|
|
||||||
|
#define WLAN_MAX_RX_SIZE 16000
|
||||||
|
#define WLAN_MAX_TX_SIZE 1476
|
||||||
|
|
||||||
|
#define MAKE_SOCKADDR(addr, ip, port) SlSockAddr_t addr; \
|
||||||
|
addr.sa_family = SL_AF_INET; \
|
||||||
|
addr.sa_data[0] = port >> 8; \
|
||||||
|
addr.sa_data[1] = port; \
|
||||||
|
addr.sa_data[2] = ip[3]; \
|
||||||
|
addr.sa_data[3] = ip[2]; \
|
||||||
|
addr.sa_data[4] = ip[1]; \
|
||||||
|
addr.sa_data[5] = ip[0];
|
||||||
|
|
||||||
|
#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
|
||||||
|
ip[0] = addr.sa_data[5]; \
|
||||||
|
ip[1] = addr.sa_data[4]; \
|
||||||
|
ip[2] = addr.sa_data[3]; \
|
||||||
|
ip[3] = addr.sa_data[2];
|
||||||
|
|
||||||
|
STATIC int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
|
||||||
|
uint32_t ip;
|
||||||
|
int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
|
||||||
|
out_ip[0] = ip;
|
||||||
|
out_ip[1] = ip >> 8;
|
||||||
|
out_ip[2] = ip >> 16;
|
||||||
|
out_ip[3] = ip >> 24;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
|
||||||
|
int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto);
|
||||||
|
if (sd < 0) {
|
||||||
|
*_errno = sd;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
s->sock_base.sd = sd;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC void wlan_socket_close(mod_network_socket_obj_t *s) {
|
||||||
|
// this is to prevent the finalizer to close a socket that failed when being created
|
||||||
|
if (s->sock_base.sd >= 0) {
|
||||||
|
modusocket_socket_delete(s->sock_base.sd);
|
||||||
|
sl_Close(s->sock_base.sd);
|
||||||
|
s->sock_base.sd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
|
||||||
|
MAKE_SOCKADDR(addr, ip, port)
|
||||||
|
int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr));
|
||||||
|
if (ret != 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
|
||||||
|
int ret = sl_Listen(s->sock_base.sd, backlog);
|
||||||
|
if (ret != 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
|
||||||
|
// accept incoming connection
|
||||||
|
int16_t sd;
|
||||||
|
SlSockAddr_t addr;
|
||||||
|
SlSocklen_t addr_len = sizeof(addr);
|
||||||
|
|
||||||
|
sd = sl_Accept(s->sock_base.sd, &addr, &addr_len);
|
||||||
|
// save the socket descriptor
|
||||||
|
s2->sock_base.sd = sd;
|
||||||
|
if (sd < 0) {
|
||||||
|
*_errno = sd;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// return ip and port
|
||||||
|
UNPACK_SOCKADDR(addr, ip, *port);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
|
||||||
|
MAKE_SOCKADDR(addr, ip, port)
|
||||||
|
int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr));
|
||||||
|
if (ret != 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
|
||||||
|
mp_int_t bytes = 0;
|
||||||
|
if (len > 0) {
|
||||||
|
bytes = sl_Send(s->sock_base.sd, (const void *)buf, len, 0);
|
||||||
|
}
|
||||||
|
if (bytes <= 0) {
|
||||||
|
*_errno = bytes;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
|
||||||
|
int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
|
||||||
|
MAKE_SOCKADDR(addr, ip, port)
|
||||||
|
int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (SlSockAddr_t*)&addr, sizeof(addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
||||||
|
SlSockAddr_t addr;
|
||||||
|
SlSocklen_t addr_len = sizeof(addr);
|
||||||
|
mp_int_t ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
UNPACK_SOCKADDR(addr, ip, *port);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
|
||||||
|
int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) {
|
||||||
|
int ret;
|
||||||
|
bool has_timeout;
|
||||||
|
if (timeout_s == 0 || timeout_s == -1) {
|
||||||
|
SlSockNonblocking_t option;
|
||||||
|
if (timeout_s == 0) {
|
||||||
|
// set non-blocking mode
|
||||||
|
option.NonblockingEnabled = 1;
|
||||||
|
} else {
|
||||||
|
// set blocking mode
|
||||||
|
option.NonblockingEnabled = 0;
|
||||||
|
}
|
||||||
|
ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &option, sizeof(option));
|
||||||
|
has_timeout = false;
|
||||||
|
} else {
|
||||||
|
// set timeout
|
||||||
|
struct SlTimeval_t timeVal;
|
||||||
|
timeVal.tv_sec = timeout_s; // seconds
|
||||||
|
timeVal.tv_usec = 0; // microseconds. 10000 microseconds resolution
|
||||||
|
ret = sl_SetSockOpt(s->sock_base.sd, SL_SOL_SOCKET, SL_SO_RCVTIMEO, &timeVal, sizeof(timeVal));
|
||||||
|
has_timeout = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
*_errno = ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
s->sock_base.has_timeout = has_timeout;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
STATIC int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
||||||
|
mp_int_t ret;
|
||||||
|
if (request == MP_STREAM_POLL) {
|
||||||
|
mp_uint_t flags = arg;
|
||||||
|
ret = 0;
|
||||||
|
int32_t sd = s->sock_base.sd;
|
||||||
|
|
||||||
|
// init fds
|
||||||
|
SlFdSet_t rfds, wfds, xfds;
|
||||||
|
SL_FD_ZERO(&rfds);
|
||||||
|
SL_FD_ZERO(&wfds);
|
||||||
|
SL_FD_ZERO(&xfds);
|
||||||
|
|
||||||
|
// set fds if needed
|
||||||
|
if (flags & MP_STREAM_POLL_RD) {
|
||||||
|
SL_FD_SET(sd, &rfds);
|
||||||
|
}
|
||||||
|
if (flags & MP_STREAM_POLL_WR) {
|
||||||
|
SL_FD_SET(sd, &wfds);
|
||||||
|
}
|
||||||
|
if (flags & MP_STREAM_POLL_HUP) {
|
||||||
|
SL_FD_SET(sd, &xfds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// call simplelink's select with minimum timeout
|
||||||
|
SlTimeval_t tv;
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 1;
|
||||||
|
int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
|
||||||
|
|
||||||
|
// check for errors
|
||||||
|
if (nfds == -1) {
|
||||||
|
*_errno = nfds;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check return of select
|
||||||
|
if (SL_FD_ISSET(sd, &rfds)) {
|
||||||
|
ret |= MP_STREAM_POLL_RD;
|
||||||
|
}
|
||||||
|
if (SL_FD_ISSET(sd, &wfds)) {
|
||||||
|
ret |= MP_STREAM_POLL_WR;
|
||||||
|
}
|
||||||
|
if (SL_FD_ISSET(sd, &xfds)) {
|
||||||
|
ret |= MP_STREAM_POLL_HUP;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*_errno = MP_EINVAL;
|
||||||
|
ret = MP_STREAM_ERROR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DEFINE PRIVATE CONSTANTS
|
DEFINE PRIVATE CONSTANTS
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -95,13 +337,13 @@ void modusocket_socket_delete (int16_t sd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void modusocket_enter_sleep (void) {
|
void modusocket_enter_sleep (void) {
|
||||||
fd_set socketset;
|
SlFdSet_t socketset;
|
||||||
int16_t maxfd = 0;
|
int16_t maxfd = 0;
|
||||||
|
|
||||||
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
|
for (int i = 0; i < MOD_NETWORK_MAX_SOCKETS; i++) {
|
||||||
int16_t sd;
|
int16_t sd;
|
||||||
if ((sd = modusocket_sockets[i].sd) >= 0) {
|
if ((sd = modusocket_sockets[i].sd) >= 0) {
|
||||||
FD_SET(sd, &socketset);
|
SL_FD_SET(sd, &socketset);
|
||||||
maxfd = (maxfd > sd) ? maxfd : sd;
|
maxfd = (maxfd > sd) ? maxfd : sd;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -133,9 +375,9 @@ STATIC mp_obj_t socket_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||||||
// create socket object
|
// create socket object
|
||||||
mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
|
mod_network_socket_obj_t *s = m_new_obj_with_finaliser(mod_network_socket_obj_t);
|
||||||
s->base.type = (mp_obj_t)&socket_type;
|
s->base.type = (mp_obj_t)&socket_type;
|
||||||
s->sock_base.u_param.domain = AF_INET;
|
s->sock_base.u_param.domain = SL_AF_INET;
|
||||||
s->sock_base.u_param.type = SOCK_STREAM;
|
s->sock_base.u_param.type = SL_SOCK_STREAM;
|
||||||
s->sock_base.u_param.proto = IPPROTO_TCP;
|
s->sock_base.u_param.proto = SL_IPPROTO_TCP;
|
||||||
s->sock_base.u_param.fileno = -1;
|
s->sock_base.u_param.fileno = -1;
|
||||||
s->sock_base.has_timeout = false;
|
s->sock_base.has_timeout = false;
|
||||||
s->sock_base.cert_req = false;
|
s->sock_base.cert_req = false;
|
||||||
@ -180,7 +422,7 @@ STATIC mp_obj_t socket_bind(mp_obj_t self_in, mp_obj_t addr_in) {
|
|||||||
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
|
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
|
||||||
|
|
||||||
// call the NIC to bind the socket
|
// call the NIC to bind the socket
|
||||||
int _errno;
|
int _errno = 0;
|
||||||
if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
|
if (wlan_socket_bind(self, ip, port, &_errno) != 0) {
|
||||||
mp_raise_OSError(-_errno);
|
mp_raise_OSError(-_errno);
|
||||||
}
|
}
|
||||||
@ -217,8 +459,8 @@ STATIC mp_obj_t socket_accept(mp_obj_t self_in) {
|
|||||||
|
|
||||||
// accept the incoming connection
|
// accept the incoming connection
|
||||||
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
|
uint8_t ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
|
||||||
mp_uint_t port;
|
mp_uint_t port = 0;
|
||||||
int _errno;
|
int _errno = 0;
|
||||||
if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
|
if (wlan_socket_accept(self, socket2, ip, &port, &_errno) != 0) {
|
||||||
mp_raise_OSError(-_errno);
|
mp_raise_OSError(-_errno);
|
||||||
}
|
}
|
||||||
@ -277,8 +519,8 @@ STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) {
|
|||||||
int _errno;
|
int _errno;
|
||||||
mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
|
mp_int_t ret = wlan_socket_recv(self, (byte*)vstr.buf, len, &_errno);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (_errno == EAGAIN && self->sock_base.has_timeout) {
|
if (_errno == MP_EAGAIN && self->sock_base.has_timeout) {
|
||||||
mp_raise_msg(&mp_type_TimeoutError, "timed out");
|
mp_raise_OSError(MP_ETIMEDOUT);
|
||||||
}
|
}
|
||||||
mp_raise_OSError(-_errno);
|
mp_raise_OSError(-_errno);
|
||||||
}
|
}
|
||||||
@ -304,7 +546,7 @@ STATIC mp_obj_t socket_sendto(mp_obj_t self_in, mp_obj_t data_in, mp_obj_t addr_
|
|||||||
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
|
mp_uint_t port = netutils_parse_inet_addr(addr_in, ip, NETUTILS_LITTLE);
|
||||||
|
|
||||||
// call the nic to sendto
|
// call the nic to sendto
|
||||||
int _errno;
|
int _errno = 0;
|
||||||
mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
|
mp_int_t ret = wlan_socket_sendto(self, bufinfo.buf, bufinfo.len, ip, port, &_errno);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
mp_raise_OSError(-_errno);
|
mp_raise_OSError(-_errno);
|
||||||
@ -319,12 +561,12 @@ STATIC mp_obj_t socket_recvfrom(mp_obj_t self_in, mp_obj_t len_in) {
|
|||||||
vstr_t vstr;
|
vstr_t vstr;
|
||||||
vstr_init_len(&vstr, mp_obj_get_int(len_in));
|
vstr_init_len(&vstr, mp_obj_get_int(len_in));
|
||||||
byte ip[4];
|
byte ip[4];
|
||||||
mp_uint_t port;
|
mp_uint_t port = 0;
|
||||||
int _errno;
|
int _errno = 0;
|
||||||
mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
|
mp_int_t ret = wlan_socket_recvfrom(self, (byte*)vstr.buf, vstr.len, ip, &port, &_errno);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (_errno == EAGAIN && self->sock_base.has_timeout) {
|
if (_errno == MP_EAGAIN && self->sock_base.has_timeout) {
|
||||||
mp_raise_msg(&mp_type_TimeoutError, "timed out");
|
mp_raise_OSError(MP_ETIMEDOUT);
|
||||||
}
|
}
|
||||||
mp_raise_OSError(-_errno);
|
mp_raise_OSError(-_errno);
|
||||||
}
|
}
|
||||||
@ -501,13 +743,13 @@ STATIC mp_obj_t mod_usocket_getaddrinfo(mp_obj_t host_in, mp_obj_t port_in) {
|
|||||||
|
|
||||||
// ipv4 only
|
// ipv4 only
|
||||||
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
|
uint8_t out_ip[MOD_NETWORK_IPV4ADDR_BUF_SIZE];
|
||||||
int32_t result = wlan_gethostbyname(host, hlen, out_ip, AF_INET);
|
int32_t result = wlan_gethostbyname(host, hlen, out_ip, SL_AF_INET);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
mp_raise_OSError(-result);
|
mp_raise_OSError(-result);
|
||||||
}
|
}
|
||||||
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
mp_obj_tuple_t *tuple = mp_obj_new_tuple(5, NULL);
|
||||||
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(AF_INET);
|
tuple->items[0] = MP_OBJ_NEW_SMALL_INT(SL_AF_INET);
|
||||||
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SOCK_STREAM);
|
tuple->items[1] = MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM);
|
||||||
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
tuple->items[2] = MP_OBJ_NEW_SMALL_INT(0);
|
||||||
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
tuple->items[3] = MP_OBJ_NEW_QSTR(MP_QSTR_);
|
||||||
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
|
tuple->items[4] = netutils_format_inet_addr(out_ip, port, NETUTILS_LITTLE);
|
||||||
@ -521,18 +763,15 @@ STATIC const mp_map_elem_t mp_module_usocket_globals_table[] = {
|
|||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_socket), (mp_obj_t)&socket_type },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_getaddrinfo), (mp_obj_t)&mod_usocket_getaddrinfo_obj },
|
||||||
|
|
||||||
// class exceptions
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_timeout), (mp_obj_t)&mp_type_TimeoutError },
|
|
||||||
|
|
||||||
// class constants
|
// class constants
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(AF_INET) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_AF_INET), MP_OBJ_NEW_SMALL_INT(SL_AF_INET) },
|
||||||
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SOCK_STREAM) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_STREAM), MP_OBJ_NEW_SMALL_INT(SL_SOCK_STREAM) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SOCK_DGRAM) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_SOCK_DGRAM), MP_OBJ_NEW_SMALL_INT(SL_SOCK_DGRAM) },
|
||||||
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_SEC), MP_OBJ_NEW_SMALL_INT(SL_SEC_SOCKET) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_SEC), MP_OBJ_NEW_SMALL_INT(SL_SEC_SOCKET) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(IPPROTO_TCP) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_TCP), MP_OBJ_NEW_SMALL_INT(SL_IPPROTO_TCP) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(IPPROTO_UDP) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_IPPROTO_UDP), MP_OBJ_NEW_SMALL_INT(SL_IPPROTO_UDP) },
|
||||||
};
|
};
|
||||||
|
|
||||||
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
|
STATIC MP_DEFINE_CONST_DICT(mp_module_usocket_globals, mp_module_usocket_globals_table);
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <std.h>
|
|
||||||
|
|
||||||
#include "simplelink.h"
|
#include "simplelink.h"
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "std.h"
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "simplelink.h"
|
#include "simplelink.h"
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
@ -35,13 +35,8 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "inc/hw_types.h"
|
#include "lib/timeutils/timeutils.h"
|
||||||
#include "inc/hw_ints.h"
|
#include "lib/netutils/netutils.h"
|
||||||
#include "inc/hw_memmap.h"
|
|
||||||
#include "rom_map.h"
|
|
||||||
#include "prcm.h"
|
|
||||||
#include "timeutils.h"
|
|
||||||
#include "netutils.h"
|
|
||||||
#include "modnetwork.h"
|
#include "modnetwork.h"
|
||||||
#include "modusocket.h"
|
#include "modusocket.h"
|
||||||
#include "modwlan.h"
|
#include "modwlan.h"
|
||||||
@ -117,26 +112,6 @@ typedef enum{
|
|||||||
|
|
||||||
#define ASSERT_ON_ERROR(x) ASSERT((x) >= 0)
|
#define ASSERT_ON_ERROR(x) ASSERT((x) >= 0)
|
||||||
|
|
||||||
#define IPV4_ADDR_STR_LEN_MAX (16)
|
|
||||||
|
|
||||||
#define WLAN_MAX_RX_SIZE 16000
|
|
||||||
#define WLAN_MAX_TX_SIZE 1476
|
|
||||||
|
|
||||||
#define MAKE_SOCKADDR(addr, ip, port) sockaddr addr; \
|
|
||||||
addr.sa_family = AF_INET; \
|
|
||||||
addr.sa_data[0] = port >> 8; \
|
|
||||||
addr.sa_data[1] = port; \
|
|
||||||
addr.sa_data[2] = ip[3]; \
|
|
||||||
addr.sa_data[3] = ip[2]; \
|
|
||||||
addr.sa_data[4] = ip[1]; \
|
|
||||||
addr.sa_data[5] = ip[0];
|
|
||||||
|
|
||||||
#define UNPACK_SOCKADDR(addr, ip, port) port = (addr.sa_data[0] << 8) | addr.sa_data[1]; \
|
|
||||||
ip[0] = addr.sa_data[5]; \
|
|
||||||
ip[1] = addr.sa_data[4]; \
|
|
||||||
ip[2] = addr.sa_data[3]; \
|
|
||||||
ip[3] = addr.sa_data[2];
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PRIVATE DATA
|
DECLARE PRIVATE DATA
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
@ -161,7 +136,9 @@ STATIC const mp_irq_methods_t wlan_irq_methods;
|
|||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PUBLIC DATA
|
DECLARE PUBLIC DATA
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
OsiLockObj_t wlan_LockObj;
|
OsiLockObj_t wlan_LockObj;
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
DECLARE PRIVATE FUNCTIONS
|
DECLARE PRIVATE FUNCTIONS
|
||||||
@ -396,14 +373,18 @@ void SimpleLinkSockEventHandler(SlSockEvent_t *pSock) {
|
|||||||
__attribute__ ((section (".boot")))
|
__attribute__ ((section (".boot")))
|
||||||
void wlan_pre_init (void) {
|
void wlan_pre_init (void) {
|
||||||
// create the wlan lock
|
// create the wlan lock
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock"));
|
ASSERT(OSI_OK == sl_LockObjCreate(&wlan_LockObj, "WlanLock"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlan_first_start (void) {
|
void wlan_first_start (void) {
|
||||||
if (wlan_obj.mode < 0) {
|
if (wlan_obj.mode < 0) {
|
||||||
CLR_STATUS_BIT_ALL(wlan_obj.status);
|
CLR_STATUS_BIT_ALL(wlan_obj.status);
|
||||||
wlan_obj.mode = sl_Start(0, 0, 0);
|
wlan_obj.mode = sl_Start(0, 0, 0);
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
sl_LockObjUnlock (&wlan_LockObj);
|
sl_LockObjUnlock (&wlan_LockObj);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the mac address
|
// get the mac address
|
||||||
@ -512,7 +493,9 @@ void wlan_update(void) {
|
|||||||
|
|
||||||
void wlan_stop (uint32_t timeout) {
|
void wlan_stop (uint32_t timeout) {
|
||||||
wlan_servers_stop();
|
wlan_servers_stop();
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
||||||
|
#endif
|
||||||
sl_Stop(timeout);
|
sl_Stop(timeout);
|
||||||
wlan_clear_data();
|
wlan_clear_data();
|
||||||
wlan_obj.mode = -1;
|
wlan_obj.mode = -1;
|
||||||
@ -568,11 +551,15 @@ STATIC void wlan_clear_data (void) {
|
|||||||
|
|
||||||
STATIC void wlan_reenable (SlWlanMode_t mode) {
|
STATIC void wlan_reenable (SlWlanMode_t mode) {
|
||||||
// stop and start again
|
// stop and start again
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
sl_LockObjLock (&wlan_LockObj, SL_OS_WAIT_FOREVER);
|
||||||
|
#endif
|
||||||
sl_Stop(SL_STOP_TIMEOUT);
|
sl_Stop(SL_STOP_TIMEOUT);
|
||||||
wlan_clear_data();
|
wlan_clear_data();
|
||||||
wlan_obj.mode = sl_Start(0, 0, 0);
|
wlan_obj.mode = sl_Start(0, 0, 0);
|
||||||
|
#ifdef SL_PLATFORM_MULTI_THREADED
|
||||||
sl_LockObjUnlock (&wlan_LockObj);
|
sl_LockObjUnlock (&wlan_LockObj);
|
||||||
|
#endif
|
||||||
ASSERT (wlan_obj.mode == mode);
|
ASSERT (wlan_obj.mode == mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -810,8 +797,9 @@ STATIC mp_obj_t wlan_init_helper(wlan_obj_t *self, const mp_arg_val_t *args) {
|
|||||||
wlan_validate_channel(channel);
|
wlan_validate_channel(channel);
|
||||||
|
|
||||||
// get the antenna type
|
// get the antenna type
|
||||||
uint8_t antenna = args[4].u_int;
|
uint8_t antenna = 0;
|
||||||
#if MICROPY_HW_ANTENNA_DIVERSITY
|
#if MICROPY_HW_ANTENNA_DIVERSITY
|
||||||
|
antenna = args[4].u_int;
|
||||||
wlan_validate_antenna(antenna);
|
wlan_validate_antenna(antenna);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -827,7 +815,9 @@ STATIC const mp_arg_t wlan_init_args[] = {
|
|||||||
{ MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
{ MP_QSTR_ssid, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} },
|
||||||
{ MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
{ MP_QSTR_auth, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} },
|
||||||
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
{ MP_QSTR_channel, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = 1} },
|
||||||
|
#if MICROPY_HW_ANTENNA_DIVERSITY
|
||||||
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
|
{ MP_QSTR_antenna, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = ANTENNA_TYPE_INTERNAL} },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||||
// parse args
|
// parse args
|
||||||
@ -846,7 +836,7 @@ STATIC mp_obj_t wlan_make_new(const mp_obj_type_t *type, size_t n_args, size_t n
|
|||||||
if (n_args > 1 || n_kw > 0) {
|
if (n_args > 1 || n_kw > 0) {
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
// start the peripheral
|
// start the peripheral
|
||||||
wlan_init_helper(self, &args[1]);
|
wlan_init_helper(self, &args[1]);
|
||||||
@ -870,7 +860,7 @@ STATIC mp_obj_t wlan_scan(mp_obj_t self_in) {
|
|||||||
|
|
||||||
// check for correct wlan mode
|
// check for correct wlan mode
|
||||||
if (wlan_obj.mode == ROLE_AP) {
|
if (wlan_obj.mode == ROLE_AP) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sl_WlanNetworkEntry_t wlanEntry;
|
Sl_WlanNetworkEntry_t wlanEntry;
|
||||||
@ -924,7 +914,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
|||||||
|
|
||||||
// check for the correct wlan mode
|
// check for the correct wlan mode
|
||||||
if (wlan_obj.mode == ROLE_AP) {
|
if (wlan_obj.mode == ROLE_AP) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse args
|
// parse args
|
||||||
@ -972,7 +962,7 @@ STATIC mp_obj_t wlan_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_
|
|||||||
modwlan_Status_t status;
|
modwlan_Status_t status;
|
||||||
status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout);
|
status = wlan_do_connect (ssid, ssid_len, bssid, auth, key, key_len, timeout);
|
||||||
if (status == MODWLAN_ERROR_TIMEOUT) {
|
if (status == MODWLAN_ERROR_TIMEOUT) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_ETIMEDOUT);
|
||||||
} else if (status == MODWLAN_ERROR_INVALID_PARAMS) {
|
} else if (status == MODWLAN_ERROR_INVALID_PARAMS) {
|
||||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||||
}
|
}
|
||||||
@ -1003,7 +993,7 @@ STATIC mp_obj_t wlan_ifconfig (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
|||||||
|
|
||||||
// check the interface id
|
// check the interface id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the configuration
|
// get the configuration
|
||||||
@ -1234,13 +1224,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(wlan_irq_obj, 1, wlan_irq);
|
|||||||
// strcpy(urn, p);
|
// 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) {
|
// if (sl_NetAppSet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, len, (unsigned char *)urn) < 0) {
|
||||||
// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
// mp_raise_OSError(MP_EIO);
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// else {
|
// else {
|
||||||
// // get the URN
|
// // 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) {
|
// if (sl_NetAppGet(SL_NET_APP_DEVICE_CONFIG_ID, NETAPP_SET_GET_DEV_CONF_OPT_DEVICE_URN, &len, (uint8_t *)urn) < 0) {
|
||||||
// mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
// mp_raise_OSError(MP_EIO);
|
||||||
// }
|
// }
|
||||||
// return mp_obj_new_str(urn, (len - 1), false);
|
// return mp_obj_new_str(urn, (len - 1), false);
|
||||||
// }
|
// }
|
||||||
@ -1254,9 +1244,9 @@ STATIC mp_obj_t wlan_print_ver(void) {
|
|||||||
byte config_opt = SL_DEVICE_GENERAL_VERSION;
|
byte config_opt = SL_DEVICE_GENERAL_VERSION;
|
||||||
byte config_len = sizeof(ver);
|
byte config_len = sizeof(ver);
|
||||||
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver);
|
sl_DevGet(SL_DEVICE_GENERAL_CONFIGURATION, &config_opt, &config_len, (byte*)&ver);
|
||||||
printf("NWP: %d.%d.%d.%d\n", ver.NwpVersion[0], ver.NwpVersion[1], ver.NwpVersion[2], ver.NwpVersion[3]);
|
printf("NWP: %d.%d.%d.%d\n", (int)ver.NwpVersion[0], (int)ver.NwpVersion[1], (int)ver.NwpVersion[2], (int)ver.NwpVersion[3]);
|
||||||
printf("MAC: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.FwVersion[0], ver.ChipFwAndPhyVersion.FwVersion[1],
|
printf("MAC: %d.%d.%d.%d\n", (int)ver.ChipFwAndPhyVersion.FwVersion[0], (int)ver.ChipFwAndPhyVersion.FwVersion[1],
|
||||||
ver.ChipFwAndPhyVersion.FwVersion[2], ver.ChipFwAndPhyVersion.FwVersion[3]);
|
(int)ver.ChipFwAndPhyVersion.FwVersion[2], (int)ver.ChipFwAndPhyVersion.FwVersion[3]);
|
||||||
printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1],
|
printf("PHY: %d.%d.%d.%d\n", ver.ChipFwAndPhyVersion.PhyVersion[0], ver.ChipFwAndPhyVersion.PhyVersion[1],
|
||||||
ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]);
|
ver.ChipFwAndPhyVersion.PhyVersion[2], ver.ChipFwAndPhyVersion.PhyVersion[3]);
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
@ -1288,8 +1278,10 @@ STATIC const mp_map_elem_t wlan_locals_dict_table[] = {
|
|||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WEP) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_WEP), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WEP) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_WPA2), MP_OBJ_NEW_SMALL_INT(SL_SEC_TYPE_WPA_WPA2) },
|
||||||
|
#if MICROPY_HW_ANTENNA_DIVERSITY
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_INTERNAL) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_INT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_INTERNAL) },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_EXT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_EXTERNAL) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_EXT_ANT), MP_OBJ_NEW_SMALL_INT(ANTENNA_TYPE_EXTERNAL) },
|
||||||
|
#endif
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANY_EVENT), MP_OBJ_NEW_SMALL_INT(MODWLAN_WIFI_EVENT_ANY) },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_ANY_EVENT), MP_OBJ_NEW_SMALL_INT(MODWLAN_WIFI_EVENT_ANY) },
|
||||||
};
|
};
|
||||||
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
|
STATIC MP_DEFINE_CONST_DICT(wlan_locals_dict, wlan_locals_dict_table);
|
||||||
@ -1309,221 +1301,3 @@ STATIC const mp_irq_methods_t wlan_irq_methods = {
|
|||||||
.disable = wlan_lpds_irq_disable,
|
.disable = wlan_lpds_irq_disable,
|
||||||
.flags = wlan_irq_flags,
|
.flags = wlan_irq_flags,
|
||||||
};
|
};
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
// Micro Python bindings; WLAN socket
|
|
||||||
|
|
||||||
int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family) {
|
|
||||||
uint32_t ip;
|
|
||||||
int result = sl_NetAppDnsGetHostByName((_i8 *)name, (_u16)len, (_u32*)&ip, (_u8)family);
|
|
||||||
out_ip[0] = ip;
|
|
||||||
out_ip[1] = ip >> 8;
|
|
||||||
out_ip[2] = ip >> 16;
|
|
||||||
out_ip[3] = ip >> 24;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno) {
|
|
||||||
int16_t sd = sl_Socket(s->sock_base.u_param.domain, s->sock_base.u_param.type, s->sock_base.u_param.proto);
|
|
||||||
if (sd < 0) {
|
|
||||||
*_errno = sd;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
s->sock_base.sd = sd;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlan_socket_close(mod_network_socket_obj_t *s) {
|
|
||||||
// this is to prevent the finalizer to close a socket that failed when being created
|
|
||||||
if (s->sock_base.sd >= 0) {
|
|
||||||
modusocket_socket_delete(s->sock_base.sd);
|
|
||||||
sl_Close(s->sock_base.sd);
|
|
||||||
s->sock_base.sd = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
|
|
||||||
MAKE_SOCKADDR(addr, ip, port)
|
|
||||||
int ret = sl_Bind(s->sock_base.sd, &addr, sizeof(addr));
|
|
||||||
if (ret != 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno) {
|
|
||||||
int ret = sl_Listen(s->sock_base.sd, backlog);
|
|
||||||
if (ret != 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno) {
|
|
||||||
// accept incoming connection
|
|
||||||
int16_t sd;
|
|
||||||
sockaddr addr;
|
|
||||||
socklen_t addr_len = sizeof(addr);
|
|
||||||
|
|
||||||
sd = sl_Accept(s->sock_base.sd, &addr, &addr_len);
|
|
||||||
// save the socket descriptor
|
|
||||||
s2->sock_base.sd = sd;
|
|
||||||
if (sd < 0) {
|
|
||||||
*_errno = sd;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return ip and port
|
|
||||||
UNPACK_SOCKADDR(addr, ip, *port);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno) {
|
|
||||||
MAKE_SOCKADDR(addr, ip, port)
|
|
||||||
int ret = sl_Connect(s->sock_base.sd, &addr, sizeof(addr));
|
|
||||||
if (ret != 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno) {
|
|
||||||
mp_int_t bytes = 0;
|
|
||||||
if (len > 0) {
|
|
||||||
bytes = sl_Send(s->sock_base.sd, (const void *)buf, len, 0);
|
|
||||||
}
|
|
||||||
if (bytes <= 0) {
|
|
||||||
*_errno = bytes;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno) {
|
|
||||||
int ret = sl_Recv(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0);
|
|
||||||
if (ret < 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno) {
|
|
||||||
MAKE_SOCKADDR(addr, ip, port)
|
|
||||||
int ret = sl_SendTo(s->sock_base.sd, (byte*)buf, len, 0, (sockaddr*)&addr, sizeof(addr));
|
|
||||||
if (ret < 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
|
||||||
sockaddr addr;
|
|
||||||
socklen_t addr_len = sizeof(addr);
|
|
||||||
mp_int_t ret = sl_RecvFrom(s->sock_base.sd, buf, MIN(len, WLAN_MAX_RX_SIZE), 0, &addr, &addr_len);
|
|
||||||
if (ret < 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
UNPACK_SOCKADDR(addr, ip, *port);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
|
|
||||||
int ret = sl_SetSockOpt(s->sock_base.sd, level, opt, optval, optlen);
|
|
||||||
if (ret < 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno) {
|
|
||||||
int ret;
|
|
||||||
bool has_timeout;
|
|
||||||
if (timeout_s == 0 || timeout_s == -1) {
|
|
||||||
SlSockNonblocking_t option;
|
|
||||||
if (timeout_s == 0) {
|
|
||||||
// set non-blocking mode
|
|
||||||
option.NonblockingEnabled = 1;
|
|
||||||
} else {
|
|
||||||
// set blocking mode
|
|
||||||
option.NonblockingEnabled = 0;
|
|
||||||
}
|
|
||||||
ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_NONBLOCKING, &option, sizeof(option));
|
|
||||||
has_timeout = false;
|
|
||||||
} else {
|
|
||||||
// set timeout
|
|
||||||
struct SlTimeval_t timeVal;
|
|
||||||
timeVal.tv_sec = timeout_s; // seconds
|
|
||||||
timeVal.tv_usec = 0; // microseconds. 10000 microseconds resolution
|
|
||||||
ret = sl_SetSockOpt(s->sock_base.sd, SOL_SOCKET, SO_RCVTIMEO, &timeVal, sizeof(timeVal));
|
|
||||||
has_timeout = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
*_errno = ret;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->sock_base.has_timeout = has_timeout;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
|
||||||
mp_int_t ret;
|
|
||||||
if (request == MP_STREAM_POLL) {
|
|
||||||
mp_uint_t flags = arg;
|
|
||||||
ret = 0;
|
|
||||||
int32_t sd = s->sock_base.sd;
|
|
||||||
|
|
||||||
// init fds
|
|
||||||
fd_set rfds, wfds, xfds;
|
|
||||||
FD_ZERO(&rfds);
|
|
||||||
FD_ZERO(&wfds);
|
|
||||||
FD_ZERO(&xfds);
|
|
||||||
|
|
||||||
// set fds if needed
|
|
||||||
if (flags & MP_STREAM_POLL_RD) {
|
|
||||||
FD_SET(sd, &rfds);
|
|
||||||
}
|
|
||||||
if (flags & MP_STREAM_POLL_WR) {
|
|
||||||
FD_SET(sd, &wfds);
|
|
||||||
}
|
|
||||||
if (flags & MP_STREAM_POLL_HUP) {
|
|
||||||
FD_SET(sd, &xfds);
|
|
||||||
}
|
|
||||||
|
|
||||||
// call simplelink's select with minimum timeout
|
|
||||||
SlTimeval_t tv;
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = 1;
|
|
||||||
int32_t nfds = sl_Select(sd + 1, &rfds, &wfds, &xfds, &tv);
|
|
||||||
|
|
||||||
// check for errors
|
|
||||||
if (nfds == -1) {
|
|
||||||
*_errno = nfds;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check return of select
|
|
||||||
if (FD_ISSET(sd, &rfds)) {
|
|
||||||
ret |= MP_STREAM_POLL_RD;
|
|
||||||
}
|
|
||||||
if (FD_ISSET(sd, &wfds)) {
|
|
||||||
ret |= MP_STREAM_POLL_WR;
|
|
||||||
}
|
|
||||||
if (FD_ISSET(sd, &xfds)) {
|
|
||||||
ret |= MP_STREAM_POLL_HUP;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
*_errno = EINVAL;
|
|
||||||
ret = MP_STREAM_ERROR;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@ -97,19 +97,4 @@ extern bool wlan_is_connected (void);
|
|||||||
extern void wlan_set_current_time (uint32_t seconds_since_2000);
|
extern void wlan_set_current_time (uint32_t seconds_since_2000);
|
||||||
extern void wlan_off_on (void);
|
extern void wlan_off_on (void);
|
||||||
|
|
||||||
extern int wlan_gethostbyname(const char *name, mp_uint_t len, uint8_t *out_ip, uint8_t family);
|
|
||||||
extern int wlan_socket_socket(mod_network_socket_obj_t *s, int *_errno);
|
|
||||||
extern void wlan_socket_close(mod_network_socket_obj_t *s);
|
|
||||||
extern int wlan_socket_bind(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
|
|
||||||
extern int wlan_socket_listen(mod_network_socket_obj_t *s, mp_int_t backlog, int *_errno);
|
|
||||||
extern int wlan_socket_accept(mod_network_socket_obj_t *s, mod_network_socket_obj_t *s2, byte *ip, mp_uint_t *port, int *_errno);
|
|
||||||
extern int wlan_socket_connect(mod_network_socket_obj_t *s, byte *ip, mp_uint_t port, int *_errno);
|
|
||||||
extern int wlan_socket_send(mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, int *_errno);
|
|
||||||
extern int wlan_socket_recv(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, int *_errno);
|
|
||||||
extern int wlan_socket_sendto( mod_network_socket_obj_t *s, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
|
|
||||||
extern int wlan_socket_recvfrom(mod_network_socket_obj_t *s, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno);
|
|
||||||
extern int wlan_socket_setsockopt(mod_network_socket_obj_t *s, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno);
|
|
||||||
extern int wlan_socket_settimeout(mod_network_socket_obj_t *s, mp_uint_t timeout_s, int *_errno);
|
|
||||||
extern int wlan_socket_ioctl (mod_network_socket_obj_t *s, mp_uint_t request, mp_uint_t arg, int *_errno);
|
|
||||||
|
|
||||||
#endif /* MODWLAN_H_ */
|
#endif /* MODWLAN_H_ */
|
||||||
|
@ -33,6 +33,7 @@
|
|||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/binary.h"
|
#include "py/binary.h"
|
||||||
#include "py/gc.h"
|
#include "py/gc.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "bufhelper.h"
|
#include "bufhelper.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
#include "inc/hw_adc.h"
|
#include "inc/hw_adc.h"
|
||||||
@ -104,7 +105,7 @@ STATIC void pyb_adc_init (pyb_adc_obj_t *self) {
|
|||||||
STATIC void pyb_adc_check_init(void) {
|
STATIC void pyb_adc_check_init(void) {
|
||||||
// not initialized
|
// not initialized
|
||||||
if (!pyb_adc_obj.enabled) {
|
if (!pyb_adc_obj.enabled) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,7 +150,7 @@ STATIC mp_obj_t adc_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_
|
|||||||
|
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check the number of bits
|
// check the number of bits
|
||||||
@ -206,7 +207,7 @@ STATIC mp_obj_t adc_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t
|
|||||||
if (args[0].u_obj != MP_OBJ_NULL) {
|
if (args[0].u_obj != MP_OBJ_NULL) {
|
||||||
ch_id = mp_obj_get_int(args[0].u_obj);
|
ch_id = mp_obj_get_int(args[0].u_obj);
|
||||||
if (ch_id >= PYB_ADC_NUM_CHANNELS) {
|
if (ch_id >= PYB_ADC_NUM_CHANNELS) {
|
||||||
mp_raise_ValueError(mpexception_os_resource_not_avaliable);
|
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||||
} else if (args[1].u_obj != mp_const_none) {
|
} 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);
|
uint pin_ch_id = pin_find_peripheral_type (args[1].u_obj, PIN_FN_ADC, 0);
|
||||||
if (ch_id != pin_ch_id) {
|
if (ch_id != pin_ch_id) {
|
||||||
@ -277,7 +278,7 @@ STATIC mp_obj_t adc_channel_value(mp_obj_t self_in) {
|
|||||||
|
|
||||||
// the channel must be enabled
|
// the channel must be enabled
|
||||||
if (!self->enabled) {
|
if (!self->enabled) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait until a new value is available
|
// wait until a new value is available
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "bufhelper.h"
|
#include "bufhelper.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
@ -144,7 +145,7 @@ STATIC bool pyb_i2c_transaction(uint cmd) {
|
|||||||
STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
|
STATIC void pyb_i2c_check_init(pyb_i2c_obj_t *self) {
|
||||||
// not initialized
|
// not initialized
|
||||||
if (!self->baudrate) {
|
if (!self->baudrate) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ STATIC void pyb_i2c_read_into (mp_arg_val_t *args, vstr_t *vstr) {
|
|||||||
|
|
||||||
// receive the data
|
// receive the data
|
||||||
if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
|
if (!pyb_i2c_read(args[0].u_int, (byte *)vstr->buf, vstr->len)) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +276,7 @@ STATIC void pyb_i2c_readmem_into (mp_arg_val_t *args, vstr_t *vstr) {
|
|||||||
if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
|
if (pyb_i2c_mem_addr_write (i2c_addr, (byte *)&mem_addr, mem_addr_size)) {
|
||||||
// Read the specified length of data
|
// Read the specified length of data
|
||||||
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
|
if (!pyb_i2c_read (i2c_addr, (byte *)vstr->buf, vstr->len)) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +342,7 @@ STATIC mp_obj_t pyb_i2c_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
|
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the object
|
// setup the object
|
||||||
@ -445,7 +446,7 @@ STATIC mp_obj_t pyb_i2c_writeto(mp_uint_t n_args, const mp_obj_t *pos_args, mp_m
|
|||||||
|
|
||||||
// send the data
|
// send the data
|
||||||
if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
|
if (!pyb_i2c_write(args[0].u_int, bufinfo.buf, bufinfo.len, args[2].u_bool)) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// return the number of bytes written
|
// return the number of bytes written
|
||||||
@ -514,7 +515,7 @@ STATIC mp_obj_t pyb_i2c_writeto_mem(mp_uint_t n_args, const mp_obj_t *pos_args,
|
|||||||
return mp_obj_new_int(bufinfo.len);
|
return mp_obj_new_int(bufinfo.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(pyb_i2c_writeto_mem_obj, 1, pyb_i2c_writeto_mem);
|
||||||
|
|
||||||
|
@ -25,11 +25,10 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <std.h>
|
|
||||||
|
|
||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
#include "inc/hw_ints.h"
|
#include "inc/hw_ints.h"
|
||||||
#include "inc/hw_memmap.h"
|
#include "inc/hw_memmap.h"
|
||||||
@ -294,7 +293,7 @@ STATIC mp_obj_t pyb_rtc_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
|
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the object
|
// setup the object
|
||||||
@ -362,7 +361,7 @@ STATIC mp_obj_t pyb_rtc_alarm (mp_uint_t n_args, const mp_obj_t *pos_args, mp_ma
|
|||||||
|
|
||||||
// check the alarm id
|
// check the alarm id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t f_seconds;
|
uint32_t f_seconds;
|
||||||
@ -397,7 +396,7 @@ STATIC mp_obj_t pyb_rtc_alarm_left (mp_uint_t n_args, const mp_obj_t *args) {
|
|||||||
|
|
||||||
// only alarm id 0 is available
|
// only alarm id 0 is available
|
||||||
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the current time
|
// get the current time
|
||||||
@ -415,7 +414,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_rtc_alarm_left_obj, 1, 2, pyb_rtc
|
|||||||
STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
|
STATIC mp_obj_t pyb_rtc_alarm_cancel (mp_uint_t n_args, const mp_obj_t *args) {
|
||||||
// only alarm id 0 is available
|
// only alarm id 0 is available
|
||||||
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
if (n_args > 1 && mp_obj_get_int(args[1]) != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
// disable the alarm
|
// disable the alarm
|
||||||
pyb_rtc_disable_alarm();
|
pyb_rtc_disable_alarm();
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "lib/oofatfs/ff.h"
|
#include "lib/oofatfs/ff.h"
|
||||||
#include "lib/oofatfs/diskio.h"
|
#include "lib/oofatfs/diskio.h"
|
||||||
#include "extmod/vfs_fat.h"
|
#include "extmod/vfs_fat.h"
|
||||||
@ -108,7 +109,7 @@ STATIC mp_obj_t pyb_sd_init_helper (pybsd_obj_t *self, const mp_arg_val_t *args)
|
|||||||
|
|
||||||
pyb_sd_hw_init (self);
|
pyb_sd_hw_init (self);
|
||||||
if (sd_disk_init() != 0) {
|
if (sd_disk_init() != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// register it with the sleep module
|
// register it with the sleep module
|
||||||
@ -133,7 +134,7 @@ STATIC mp_obj_t pyb_sd_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||||||
|
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup and initialize the object
|
// setup and initialize the object
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#include "py/mpstate.h"
|
#include "py/mpstate.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "bufhelper.h"
|
#include "bufhelper.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
#include "inc/hw_mcspi.h"
|
#include "inc/hw_mcspi.h"
|
||||||
@ -131,7 +132,7 @@ STATIC void pybspi_rx (pyb_spi_obj_t *self, void *data) {
|
|||||||
|
|
||||||
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
|
STATIC void pybspi_transfer (pyb_spi_obj_t *self, const char *txdata, char *rxdata, uint32_t len, uint32_t *txchar) {
|
||||||
if (!self->baudrate) {
|
if (!self->baudrate) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
// send and receive the data
|
// send and receive the data
|
||||||
MAP_SPICSEnable(GSPI_BASE);
|
MAP_SPICSEnable(GSPI_BASE);
|
||||||
@ -234,7 +235,7 @@ STATIC mp_obj_t pyb_spi_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
|
|
||||||
// check the peripheral id
|
// check the peripheral id
|
||||||
if (args[0].u_int != 0) {
|
if (args[0].u_int != 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup the object
|
// setup the object
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "py/nlr.h"
|
#include "py/nlr.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/gc.h"
|
#include "py/gc.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
#include "inc/hw_ints.h"
|
#include "inc/hw_ints.h"
|
||||||
@ -329,7 +330,7 @@ STATIC mp_obj_t pyb_timer_make_new(const mp_obj_type_t *type, size_t n_args, siz
|
|||||||
// create a new Timer object
|
// create a new Timer object
|
||||||
int32_t timer_idx = mp_obj_get_int(args[0]);
|
int32_t timer_idx = mp_obj_get_int(args[0]);
|
||||||
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
|
if (timer_idx < 0 || timer_idx > (PYBTIMER_NUM_TIMERS - 1)) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
|
pyb_timer_obj_t *tim = &pyb_timer_obj[timer_idx];
|
||||||
@ -370,7 +371,7 @@ STATIC mp_obj_t pyb_timer_channel(mp_uint_t n_args, const mp_obj_t *pos_args, mp
|
|||||||
|
|
||||||
// verify that the timer has been already initialized
|
// verify that the timer has been already initialized
|
||||||
if (!tim->config) {
|
if (!tim->config) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
|
if (channel_n != TIMER_A && channel_n != TIMER_B && channel_n != (TIMER_A | TIMER_B)) {
|
||||||
// invalid channel
|
// invalid channel
|
||||||
|
@ -279,7 +279,7 @@ STATIC void UARTGenericIntHandler(uint32_t uart_id) {
|
|||||||
STATIC void uart_check_init(pyb_uart_obj_t *self) {
|
STATIC void uart_check_init(pyb_uart_obj_t *self) {
|
||||||
// not initialized
|
// not initialized
|
||||||
if (!self->baudrate) {
|
if (!self->baudrate) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +471,7 @@ STATIC mp_obj_t pyb_uart_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uart_id > PYB_UART_1) {
|
if (uart_id > PYB_UART_1) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
// get the correct uart instance
|
// get the correct uart instance
|
||||||
@ -596,8 +596,8 @@ STATIC mp_uint_t pyb_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, i
|
|||||||
|
|
||||||
// wait for first char to become available
|
// wait for first char to become available
|
||||||
if (!uart_rx_wait(self)) {
|
if (!uart_rx_wait(self)) {
|
||||||
// return EAGAIN error to indicate non-blocking (then read() method returns None)
|
// return MP_EAGAIN error to indicate non-blocking (then read() method returns None)
|
||||||
*errcode = EAGAIN;
|
*errcode = MP_EAGAIN;
|
||||||
return MP_STREAM_ERROR;
|
return MP_STREAM_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -619,7 +619,7 @@ STATIC mp_uint_t pyb_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t
|
|||||||
|
|
||||||
// write the data
|
// write the data
|
||||||
if (!uart_tx_strn(self, buf, size)) {
|
if (!uart_tx_strn(self, buf, size)) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_operation_failed);
|
mp_raise_OSError(MP_EIO);
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@ -639,7 +639,7 @@ STATIC mp_uint_t pyb_uart_ioctl(mp_obj_t self_in, mp_uint_t request, mp_uint_t a
|
|||||||
ret |= MP_STREAM_POLL_WR;
|
ret |= MP_STREAM_POLL_WR;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
*errcode = EINVAL;
|
*errcode = MP_EINVAL;
|
||||||
ret = MP_STREAM_ERROR;
|
ret = MP_STREAM_ERROR;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "py/mpconfig.h"
|
#include "py/mpconfig.h"
|
||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mperrno.h"
|
||||||
#include "py/mphal.h"
|
#include "py/mphal.h"
|
||||||
#include "inc/hw_types.h"
|
#include "inc/hw_types.h"
|
||||||
#include "inc/hw_gpio.h"
|
#include "inc/hw_gpio.h"
|
||||||
@ -100,14 +101,14 @@ STATIC mp_obj_t pyb_wdt_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
mp_arg_parse_all(n_args, all_args, &kw_args, MP_ARRAY_SIZE(args), pyb_wdt_init_args, args);
|
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) {
|
if (args[0].u_obj != mp_const_none && mp_obj_get_int(args[0].u_obj) > 0) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_resource_not_avaliable);
|
mp_raise_OSError(MP_ENODEV);
|
||||||
}
|
}
|
||||||
uint timeout_ms = args[1].u_int;
|
uint timeout_ms = args[1].u_int;
|
||||||
if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) {
|
if (timeout_ms < PYBWDT_MIN_TIMEOUT_MS) {
|
||||||
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
mp_raise_ValueError(mpexception_value_invalid_arguments);
|
||||||
}
|
}
|
||||||
if (pyb_wdt_obj.running) {
|
if (pyb_wdt_obj.running) {
|
||||||
mp_raise_msg(&mp_type_OSError, mpexception_os_request_not_possible);
|
mp_raise_OSError(MP_EPERM);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable the WDT peripheral clock
|
// Enable the WDT peripheral clock
|
||||||
|
@ -75,10 +75,10 @@
|
|||||||
#define MICROPY_STREAMS_NON_BLOCK (1)
|
#define MICROPY_STREAMS_NON_BLOCK (1)
|
||||||
#define MICROPY_MODULE_WEAK_LINKS (1)
|
#define MICROPY_MODULE_WEAK_LINKS (1)
|
||||||
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
#define MICROPY_CAN_OVERRIDE_BUILTINS (1)
|
||||||
|
#define MICROPY_USE_INTERNAL_ERRNO (1)
|
||||||
#define MICROPY_VFS (1)
|
#define MICROPY_VFS (1)
|
||||||
#define MICROPY_VFS_FAT (1)
|
#define MICROPY_VFS_FAT (1)
|
||||||
#define MICROPY_PY_ASYNC_AWAIT (0)
|
#define MICROPY_PY_ASYNC_AWAIT (0)
|
||||||
#define MICROPY_PY_BUILTINS_TIMEOUTERROR (1)
|
|
||||||
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
#define MICROPY_PY_ALL_SPECIAL_METHODS (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
|
#define MICROPY_PY_BUILTINS_HELP_TEXT cc3200_help_text
|
||||||
@ -106,6 +106,8 @@
|
|||||||
#define MICROPY_PY_CMATH (0)
|
#define MICROPY_PY_CMATH (0)
|
||||||
#define MICROPY_PY_IO (1)
|
#define MICROPY_PY_IO (1)
|
||||||
#define MICROPY_PY_IO_FILEIO (1)
|
#define MICROPY_PY_IO_FILEIO (1)
|
||||||
|
#define MICROPY_PY_UERRNO (1)
|
||||||
|
#define MICROPY_PY_UERRNO_ERRORCODE (0)
|
||||||
#define MICROPY_PY_THREAD (1)
|
#define MICROPY_PY_THREAD (1)
|
||||||
#define MICROPY_PY_THREAD_GIL (1)
|
#define MICROPY_PY_THREAD_GIL (1)
|
||||||
#define MICROPY_PY_UBINASCII (0)
|
#define MICROPY_PY_UBINASCII (0)
|
||||||
@ -121,6 +123,14 @@
|
|||||||
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
#define MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF (1)
|
||||||
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
#define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (0)
|
||||||
|
|
||||||
|
// We define our own list of errno constants to include in uerrno module
|
||||||
|
#define MICROPY_PY_UERRNO_LIST \
|
||||||
|
X(EPERM) \
|
||||||
|
X(EIO) \
|
||||||
|
X(ENODEV) \
|
||||||
|
X(EINVAL) \
|
||||||
|
X(ETIMEDOUT) \
|
||||||
|
|
||||||
// TODO these should be generic, not bound to fatfs
|
// TODO these should be generic, not bound to fatfs
|
||||||
#define mp_type_fileio fatfs_type_fileio
|
#define mp_type_fileio fatfs_type_fileio
|
||||||
#define mp_type_textio fatfs_type_textio
|
#define mp_type_textio fatfs_type_textio
|
||||||
@ -160,6 +170,7 @@ extern const struct _mp_obj_module_t mp_module_ussl;
|
|||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_ussl), (mp_obj_t)&mp_module_ussl }, \
|
||||||
|
|
||||||
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
|
#define MICROPY_PORT_BUILTIN_MODULE_WEAK_LINKS \
|
||||||
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_errno), (mp_obj_t)&mp_module_uerrno }, \
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_struct), (mp_obj_t)&mp_module_ustruct }, \
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_re), (mp_obj_t)&mp_module_ure }, \
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_json), (mp_obj_t)&mp_module_ujson }, \
|
||||||
|
@ -163,7 +163,7 @@ extern "C" {
|
|||||||
|
|
||||||
\warning
|
\warning
|
||||||
*/
|
*/
|
||||||
#define SL_INC_STD_BSD_API_NAMING
|
/* #define SL_INC_STD_BSD_API_NAMING */
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -296,23 +296,23 @@ static void telnet_wait_for_enabled (void) {
|
|||||||
|
|
||||||
static bool telnet_create_socket (void) {
|
static bool telnet_create_socket (void) {
|
||||||
SlSockNonblocking_t nonBlockingOption;
|
SlSockNonblocking_t nonBlockingOption;
|
||||||
sockaddr_in sServerAddress;
|
SlSockAddrIn_t sServerAddress;
|
||||||
_i16 result;
|
_i16 result;
|
||||||
|
|
||||||
// Open a socket for telnet
|
// Open a socket for telnet
|
||||||
ASSERT ((telnet_data.sd = sl_Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) > 0);
|
ASSERT ((telnet_data.sd = sl_Socket(SL_AF_INET, SL_SOCK_STREAM, SL_IPPROTO_TCP)) > 0);
|
||||||
if (telnet_data.sd > 0) {
|
if (telnet_data.sd > 0) {
|
||||||
// add the socket to the network administration
|
// add the socket to the network administration
|
||||||
modusocket_socket_add(telnet_data.sd, false);
|
modusocket_socket_add(telnet_data.sd, false);
|
||||||
|
|
||||||
// Enable non-blocking mode
|
// Enable non-blocking mode
|
||||||
nonBlockingOption.NonblockingEnabled = 1;
|
nonBlockingOption.NonblockingEnabled = 1;
|
||||||
ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
|
ASSERT ((result = sl_SetSockOpt(telnet_data.sd, SL_SOL_SOCKET, SL_SO_NONBLOCKING, &nonBlockingOption, sizeof(nonBlockingOption))) == SL_SOC_OK);
|
||||||
|
|
||||||
// Bind the socket to a port number
|
// Bind the socket to a port number
|
||||||
sServerAddress.sin_family = AF_INET;
|
sServerAddress.sin_family = SL_AF_INET;
|
||||||
sServerAddress.sin_addr.s_addr = INADDR_ANY;
|
sServerAddress.sin_addr.s_addr = SL_INADDR_ANY;
|
||||||
sServerAddress.sin_port = htons(TELNET_PORT);
|
sServerAddress.sin_port = sl_Htons(TELNET_PORT);
|
||||||
|
|
||||||
ASSERT ((result |= sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
|
ASSERT ((result |= sl_Bind(telnet_data.sd, (const SlSockAddr_t *)&sServerAddress, sizeof(sServerAddress))) == SL_SOC_OK);
|
||||||
|
|
||||||
@ -330,7 +330,7 @@ static bool telnet_create_socket (void) {
|
|||||||
|
|
||||||
static void telnet_wait_for_connection (void) {
|
static void telnet_wait_for_connection (void) {
|
||||||
SlSocklen_t in_addrSize;
|
SlSocklen_t in_addrSize;
|
||||||
sockaddr_in sClientAddress;
|
SlSockAddrIn_t sClientAddress;
|
||||||
|
|
||||||
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
|
// accepts a connection from a TCP client, if there is any, otherwise returns SL_EAGAIN
|
||||||
telnet_data.n_sd = sl_Accept(telnet_data.sd, (SlSockAddr_t *)&sClientAddress, (SlSocklen_t *)&in_addrSize);
|
telnet_data.n_sd = sl_Accept(telnet_data.sd, (SlSockAddr_t *)&sClientAddress, (SlSocklen_t *)&in_addrSize);
|
||||||
|
@ -2,10 +2,14 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
# You can set these variables from the command line.
|
# You can set these variables from the command line.
|
||||||
|
PYTHON = python3
|
||||||
SPHINXOPTS =
|
SPHINXOPTS =
|
||||||
SPHINXBUILD = sphinx-build
|
SPHINXBUILD = sphinx-build
|
||||||
PAPER =
|
PAPER =
|
||||||
BUILDDIR = build/$(MICROPY_PORT)
|
BUILDDIR = build/$(MICROPY_PORT)
|
||||||
|
CPYDIFFDIR = ../tools
|
||||||
|
CPYDIFF = gen-cpydiff.py
|
||||||
|
GENRSTDIR = genrst
|
||||||
# Run "make FORCE= ..." to avoid rebuilding from scratch (and risk
|
# Run "make FORCE= ..." to avoid rebuilding from scratch (and risk
|
||||||
# producing incorrect docs).
|
# producing incorrect docs).
|
||||||
FORCE = -E
|
FORCE = -E
|
||||||
@ -48,11 +52,18 @@ help:
|
|||||||
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
|
||||||
@echo " linkcheck to check all external links for integrity"
|
@echo " linkcheck to check all external links for integrity"
|
||||||
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
@echo " cpydiff to generate the MicroPython differences from CPython"
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILDDIR)/*
|
rm -rf $(BUILDDIR)/*
|
||||||
|
rm -f $(GENRSTDIR)/*
|
||||||
|
|
||||||
html:
|
cpydiff:
|
||||||
|
@echo "Generating MicroPython Differences."
|
||||||
|
rm -f $(GENRSTDIR)/*
|
||||||
|
cd $(CPYDIFFDIR) && $(PYTHON) $(CPYDIFF)
|
||||||
|
|
||||||
|
html: cpydiff
|
||||||
$(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
$(SPHINXBUILD) $(FORCE) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
@ -106,20 +117,20 @@ epub:
|
|||||||
@echo
|
@echo
|
||||||
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
latex:
|
latex: cpydiff
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
@echo
|
@echo
|
||||||
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
"(use \`make latexpdf' here to do that automatically)."
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
latexpdf:
|
latexpdf: cpydiff
|
||||||
$(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
$(SPHINXBUILD) $(FORCE) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
@echo "Running LaTeX files through pdflatex..."
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf
|
||||||
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
latexpdfja:
|
latexpdfja: cpydiff
|
||||||
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
@echo "Running LaTeX files through platex and dvipdfmx..."
|
@echo "Running LaTeX files through platex and dvipdfmx..."
|
||||||
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
|
||||||
|
8
docs/differences/index_template.txt
Normal file
8
docs/differences/index_template.txt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
MicroPython Differences from CPython
|
||||||
|
====================================
|
||||||
|
|
||||||
|
The operations listed in this section produce conflicting results in MicroPython when compared to standard Python.
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
@ -72,15 +72,17 @@ For best results it is recommended to first erase the entire flash of your
|
|||||||
device before putting on new MicroPython firmware.
|
device before putting on new MicroPython firmware.
|
||||||
|
|
||||||
Currently we only support esptool.py to copy across the firmware. You can find
|
Currently we only support esptool.py to copy across the firmware. You can find
|
||||||
this tool here: `<https://github.com/themadinventor/esptool/>`__, or install it
|
this tool here: `<https://github.com/espressif/esptool/>`__, or install it
|
||||||
using pip (at least version 1.2.1 is required)::
|
using pip::
|
||||||
|
|
||||||
pip install esptool
|
pip install esptool
|
||||||
|
|
||||||
It requires Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in
|
Versions starting with 1.3 support both Python 2.7 and Python 3.4 (or newer).
|
||||||
the command above. Any other
|
An older version (at least 1.2.1 is needed) works fine but will require Python
|
||||||
flashing program should work, so feel free to try them out, or refer to the
|
2.7.
|
||||||
documentation for your board to see its recommendations.
|
|
||||||
|
Any other flashing program should work, so feel free to try them out or refer
|
||||||
|
to the documentation for your board to see its recommendations.
|
||||||
|
|
||||||
Using esptool.py you can erase the flash with the command::
|
Using esptool.py you can erase the flash with the command::
|
||||||
|
|
||||||
@ -88,7 +90,7 @@ Using esptool.py you can erase the flash with the command::
|
|||||||
|
|
||||||
And then deploy the new firmware using::
|
And then deploy the new firmware using::
|
||||||
|
|
||||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-2016-05-03-v1.8.bin
|
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect 0 esp8266-20170108-v1.8.7.bin
|
||||||
|
|
||||||
You might need to change the "port" setting to something else relevant for your
|
You might need to change the "port" setting to something else relevant for your
|
||||||
PC. You may also need to reduce the baudrate if you get errors when flashing
|
PC. You may also need to reduce the baudrate if you get errors when flashing
|
||||||
@ -99,7 +101,7 @@ For some boards with a particular FlashROM configuration (e.g. some variants of
|
|||||||
a NodeMCU board) you may need to use the following command to deploy
|
a NodeMCU board) you may need to use the following command to deploy
|
||||||
the firmware (note the ``-fm dio`` option)::
|
the firmware (note the ``-fm dio`` option)::
|
||||||
|
|
||||||
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-2016-05-03-v1.8.bin
|
esptool.py --port /dev/ttyUSB0 --baud 460800 write_flash --flash_size=detect -fm dio 0 esp8266-20170108-v1.8.7.bin
|
||||||
|
|
||||||
If the above commands run without error then MicroPython should be installed on
|
If the above commands run without error then MicroPython should be installed on
|
||||||
your board!
|
your board!
|
||||||
@ -158,7 +160,9 @@ after it, here are troubleshooting recommendations:
|
|||||||
esptool.py, which had a different programming algorithm::
|
esptool.py, which had a different programming algorithm::
|
||||||
pip install esptool==1.0.1
|
pip install esptool==1.0.1
|
||||||
This version doesn't support ``--flash_size=detect`` option, so you will
|
This version doesn't support ``--flash_size=detect`` option, so you will
|
||||||
need to specify FlashROM size explicitly (in megabits).
|
need to specify FlashROM size explicitly (in megabits). It also requires
|
||||||
|
Python 2.7, so you may need to use ``pip2`` instead of ``pip`` in the
|
||||||
|
command above.
|
||||||
|
|
||||||
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
* The ``--flash_size`` option in the commands above is mandatory. Omitting
|
||||||
it will lead to a corrupted firmware.
|
it will lead to a corrupted firmware.
|
||||||
@ -179,7 +183,7 @@ after it, here are troubleshooting recommendations:
|
|||||||
application in the ESP8266 community.
|
application in the ESP8266 community.
|
||||||
|
|
||||||
* If you still experience problems with even flashing the firmware, please
|
* If you still experience problems with even flashing the firmware, please
|
||||||
refer to esptool.py project page, https://github.com/themadinventor/esptool
|
refer to esptool.py project page, https://github.com/espressif/esptool
|
||||||
for additional documentation and bug tracker where you can report problems.
|
for additional documentation and bug tracker where you can report problems.
|
||||||
|
|
||||||
* If you are able to flash firmware, but ``--verify`` option or
|
* If you are able to flash firmware, but ``--verify`` option or
|
||||||
|
@ -8,4 +8,5 @@ MicroPython documentation contents
|
|||||||
esp8266/tutorial/index.rst
|
esp8266/tutorial/index.rst
|
||||||
library/index.rst
|
library/index.rst
|
||||||
reference/index.rst
|
reference/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
|
@ -5,6 +5,7 @@ MicroPython documentation and references
|
|||||||
|
|
||||||
esp8266/quickref.rst
|
esp8266/quickref.rst
|
||||||
library/index.rst
|
library/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
esp8266_contents.rst
|
esp8266_contents.rst
|
||||||
|
|
||||||
|
129
docs/library/framebuf.rst
Normal file
129
docs/library/framebuf.rst
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
:mod:`framebuf` --- Frame buffer manipulation
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
.. module:: framebuf
|
||||||
|
:synopsis: Frame buffer manipulation
|
||||||
|
|
||||||
|
This module provides a general frame buffer which can be used to create
|
||||||
|
bitmap images, which can then be sent to a display.
|
||||||
|
|
||||||
|
class FrameBuffer
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
The FrameBuffer class provides a pixel buffer which can be drawn upon with
|
||||||
|
pixels, lines, rectangles, text and even other FrameBuffer's. It is useful
|
||||||
|
when generating output for displays.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
import framebuf
|
||||||
|
|
||||||
|
# FrameBuffer needs 2 bytes for every RGB565 pixel
|
||||||
|
fbuf = FrameBuffer(bytearray(10 * 100 * 2), 10, 100, framebuf.RGB565)
|
||||||
|
|
||||||
|
fbuf.fill(0)
|
||||||
|
fbuf.text('MicroPython!', 0, 0, 0xffff)
|
||||||
|
fbuf.hline(0, 10, 96, 0xffff)
|
||||||
|
|
||||||
|
Constructors
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. class:: FrameBuffer(buffer, width, height, format, stride=width)
|
||||||
|
|
||||||
|
Construct a FrameBuffer object. The parameters are:
|
||||||
|
|
||||||
|
- `buffer` is an object with a buffer protocol which must be large
|
||||||
|
enough to contain every pixel defined by the width, height and
|
||||||
|
format of the FrameBuffer.
|
||||||
|
- `width` is the width of the FrameBuffer in pixels
|
||||||
|
- `height` is the height of the FrameBuffer in pixels
|
||||||
|
- `format` specifies the type of pixel used in the FrameBuffer;
|
||||||
|
valid values are ``framebuf.MVLSB``, ``framebuf.RGB565``
|
||||||
|
and ``framebuf.GS4_HMSB``. MVLSB is monochrome 8-bit color,
|
||||||
|
RGB565 is RGB 16-bit color, and GS4_HMSB is grayscale 4-bit color.
|
||||||
|
Where a color value c is passed to a method, c is a small integer
|
||||||
|
with an encoding that is dependent on the format of the FrameBuffer.
|
||||||
|
- `stride` is the number of pixels between each horizontal line
|
||||||
|
of pixels in the FrameBuffer. This defaults to `width` but may
|
||||||
|
need adjustments when implementing a FrameBuffer within another
|
||||||
|
larger FrameBuffer or screen. The `buffer` size must accommodate
|
||||||
|
an increased step size.
|
||||||
|
|
||||||
|
One must specify valid `buffer`, `width`, `height`, `format` and
|
||||||
|
optionally `stride`. Invalid `buffer` size or dimensions may lead to
|
||||||
|
unexpected errors.
|
||||||
|
|
||||||
|
Drawing primitive shapes
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The following methods draw shapes onto the FrameBuffer.
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.fill(c)
|
||||||
|
|
||||||
|
Fill the entire FrameBuffer with the specified color.
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.pixel(x, y[, c])
|
||||||
|
|
||||||
|
If `c` is not given, get the color value of the specified pixel.
|
||||||
|
If `c` is given, set the specified pixel to the given color.
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.hline(x, y, w, c)
|
||||||
|
.. method:: FrameBuffer.vline(x, y, h, c)
|
||||||
|
.. method:: FrameBuffer.line(x1, y1, x2, y2, c)
|
||||||
|
|
||||||
|
Draw a line from a set of coordinates using the given color and
|
||||||
|
a thickness of 1 pixel. The `line` method draws the line up to
|
||||||
|
a second set of coordinates whereas the `hline` and `vline`
|
||||||
|
methods draw horizontal and vertical lines respectively up to
|
||||||
|
a given length.
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.rect(x, y, w, h, c)
|
||||||
|
.. method:: FrameBuffer.fill_rect(x, y, w, h, c)
|
||||||
|
|
||||||
|
Draw a rectangle at the given location, size and color. The `rect`
|
||||||
|
method draws only a 1 pixel outline whereas the `fill_rect` method
|
||||||
|
draws both the outline and interior.
|
||||||
|
|
||||||
|
Drawing text
|
||||||
|
------------
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.text(s, x, y[, c])
|
||||||
|
|
||||||
|
Write text to the FrameBuffer using the the coordinates as the upper-left
|
||||||
|
corner of the text. The color of the text can be defined by the optional
|
||||||
|
argument but is otherwise a default value of 1. All characters have
|
||||||
|
dimensions of 8x8 pixels and there is currently no way to change the font.
|
||||||
|
|
||||||
|
|
||||||
|
Other methods
|
||||||
|
-------------
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.scroll(xstep, ystep)
|
||||||
|
|
||||||
|
Shift the contents of the FrameBuffer by the given vector. This may
|
||||||
|
leave a footprint of the previous colors in the FrameBuffer.
|
||||||
|
|
||||||
|
.. method:: FrameBuffer.blit(fbuf, x, y[, key])
|
||||||
|
|
||||||
|
Draw another FrameBuffer on top of the current one at the given coordinates.
|
||||||
|
If `key` is specified then it should be a color integer and the
|
||||||
|
corresponding color will be considered transparent: all pixels with that
|
||||||
|
color value will not be drawn.
|
||||||
|
|
||||||
|
This method works between FrameBuffer's utilising different formats, but the
|
||||||
|
resulting colors may be unexpected due to the mismatch in color formats.
|
||||||
|
|
||||||
|
Constants
|
||||||
|
---------
|
||||||
|
|
||||||
|
.. data:: framebuf.MVLSB
|
||||||
|
|
||||||
|
Monochrome (1-bit) color format
|
||||||
|
|
||||||
|
.. data:: framebuf.RGB565
|
||||||
|
|
||||||
|
Red Green Blue (16-bit, 5+6+5) color format
|
||||||
|
|
||||||
|
.. data:: framebuf.GS4_HMSB
|
||||||
|
|
||||||
|
Grayscale (4-bit) color format
|
@ -153,6 +153,7 @@ the following libraries.
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
|
framebuf.rst
|
||||||
machine.rst
|
machine.rst
|
||||||
micropython.rst
|
micropython.rst
|
||||||
network.rst
|
network.rst
|
||||||
|
@ -304,6 +304,10 @@ Advanced commands
|
|||||||
the 16-bit RGB values for the pixels, and they will be written to the area
|
the 16-bit RGB values for the pixels, and they will be written to the area
|
||||||
specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner.
|
specified by :meth:`LCD160CR.set_spi_win`, starting from the top-left corner.
|
||||||
|
|
||||||
|
The `framebuf <framebuf.html>`_ module can be used to construct frame buffers
|
||||||
|
and provides drawing primitives. Using a frame buffer will improve
|
||||||
|
performance of animations when compared to drawing directly to the screen.
|
||||||
|
|
||||||
.. method:: LCD160CR.set_scroll(on)
|
.. method:: LCD160CR.set_scroll(on)
|
||||||
|
|
||||||
Turn scrolling on or off. This controls globally whether any window regions will
|
Turn scrolling on or off. This controls globally whether any window regions will
|
||||||
@ -341,7 +345,9 @@ Advanced commands
|
|||||||
|
|
||||||
.. method:: LCD160CR.jpeg(buf)
|
.. method:: LCD160CR.jpeg(buf)
|
||||||
|
|
||||||
Display a JPEG. `buf` should contain the entire JPEG data.
|
Display a JPEG. `buf` should contain the entire JPEG data. JPEG data should
|
||||||
|
not include EXIF information. The following encodings are supported: Baseline
|
||||||
|
DCT, Huffman coding, 8 bits per sample, 3 color components, YCbCr4:2:2.
|
||||||
The origin of the JPEG is set by :meth:`LCD160CR.set_pos`.
|
The origin of the JPEG is set by :meth:`LCD160CR.set_pos`.
|
||||||
|
|
||||||
.. method:: LCD160CR.jpeg_start(total_len)
|
.. method:: LCD160CR.jpeg_start(total_len)
|
||||||
|
@ -134,24 +134,24 @@ Constants
|
|||||||
---------
|
---------
|
||||||
|
|
||||||
.. data:: machine.IDLE
|
.. data:: machine.IDLE
|
||||||
.. data:: machine.SLEEP
|
machine.SLEEP
|
||||||
.. data:: machine.DEEPSLEEP
|
machine.DEEPSLEEP
|
||||||
|
|
||||||
irq wake values
|
IRQ wake values.
|
||||||
|
|
||||||
.. data:: machine.PWRON_RESET
|
.. data:: machine.PWRON_RESET
|
||||||
.. data:: machine.HARD_RESET
|
machine.HARD_RESET
|
||||||
.. data:: machine.WDT_RESET
|
machine.WDT_RESET
|
||||||
.. data:: machine.DEEPSLEEP_RESET
|
machine.DEEPSLEEP_RESET
|
||||||
.. data:: machine.SOFT_RESET
|
machine.SOFT_RESET
|
||||||
|
|
||||||
reset causes
|
Reset causes.
|
||||||
|
|
||||||
.. data:: machine.WLAN_WAKE
|
.. data:: machine.WLAN_WAKE
|
||||||
.. data:: machine.PIN_WAKE
|
machine.PIN_WAKE
|
||||||
.. data:: machine.RTC_WAKE
|
machine.RTC_WAKE
|
||||||
|
|
||||||
wake reasons
|
Wake-up reasons.
|
||||||
|
|
||||||
Classes
|
Classes
|
||||||
-------
|
-------
|
||||||
|
@ -1,33 +1,41 @@
|
|||||||
:mod:`uhashlib` -- hashing algorithm
|
:mod:`uhashlib` -- hashing algorithms
|
||||||
====================================
|
=====================================
|
||||||
|
|
||||||
.. module:: uhashlib
|
.. module:: uhashlib
|
||||||
:synopsis: hashing algorithm
|
:synopsis: hashing algorithms
|
||||||
|
|
||||||
.. only:: port_pyboard
|
This module implements binary data hashing algorithms. The exact inventory
|
||||||
|
of available algorithms depends on a board. Among the algorithms which may
|
||||||
|
be implemented:
|
||||||
|
|
||||||
This module implements binary data hashing algorithms. Currently, it
|
* SHA256 - The current generation, modern hashing algorithm (of SHA2 series).
|
||||||
implements SHA256 algorithm. Choosing SHA256 was a deliberate choice,
|
It is suitable for cryptographically-secure purposes. Included in the
|
||||||
as a modern, cryptographically secure algorithm. This means that a
|
MicroPython core and any board is recommended to provide this, unless
|
||||||
single algorithm can cover both use cases of "any hash algorithm" and
|
it has particular code size constraints.
|
||||||
security-related usage, and thus save space omitting legacy algorithms
|
|
||||||
like MD5 or SHA1.
|
|
||||||
|
|
||||||
.. only:: port_wipy
|
* SHA1 - A previous generation algorithm. Not recommended for new usages,
|
||||||
|
but SHA1 is a part of number of Internet standards and existing
|
||||||
This module implements binary data hashing algorithms. Currently, it
|
applications, so boards targetting network connectivity and
|
||||||
implements SHA1 and SHA256 algorithms only. These two algorithms are
|
interoperatiability will try to provide this.
|
||||||
more than enough for today's web applications.
|
|
||||||
|
|
||||||
|
* MD5 - A legacy algorithm, not considered cryptographically secure. Only
|
||||||
|
selected boards, targetting interoperatibility with legacy applications,
|
||||||
|
will offer this.
|
||||||
|
|
||||||
Constructors
|
Constructors
|
||||||
------------
|
------------
|
||||||
|
|
||||||
.. only:: port_pyboard
|
.. class:: uhashlib.sha256([data])
|
||||||
|
|
||||||
.. class:: uhashlib.sha256([data])
|
Create an SHA256 hasher object and optionally feed ``data`` into it.
|
||||||
|
|
||||||
Create a hasher object and optionally feed ``data`` into it.
|
.. class:: uhashlib.sha1([data])
|
||||||
|
|
||||||
|
Create an SHA1 hasher object and optionally feed ``data`` into it.
|
||||||
|
|
||||||
|
.. class:: uhashlib.md5([data])
|
||||||
|
|
||||||
|
Create an MD5 hasher object and optionally feed ``data`` into it.
|
||||||
|
|
||||||
.. only:: port_wipy
|
.. only:: port_wipy
|
||||||
|
|
||||||
@ -69,11 +77,7 @@ Methods
|
|||||||
.. method:: hash.digest()
|
.. method:: hash.digest()
|
||||||
|
|
||||||
Return hash for all data passed through hash, as a bytes object. After this
|
Return hash for all data passed through hash, as a bytes object. After this
|
||||||
method is called, more data cannot be fed into hash any longer.
|
method is called, more data cannot be fed into the hash any longer.
|
||||||
|
|
||||||
.. only:: port_wipy
|
|
||||||
|
|
||||||
SHA1 hashes are 20-byte long. SHA256 hashes are 32-byte long.
|
|
||||||
|
|
||||||
.. method:: hash.hexdigest()
|
.. method:: hash.hexdigest()
|
||||||
|
|
||||||
|
@ -9,5 +9,6 @@ MicroPython documentation contents
|
|||||||
library/index.rst
|
library/index.rst
|
||||||
reference/index.rst
|
reference/index.rst
|
||||||
pyboard/hardware/index.rst
|
pyboard/hardware/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ MicroPython documentation and references
|
|||||||
pyboard/tutorial/index.rst
|
pyboard/tutorial/index.rst
|
||||||
library/index.rst
|
library/index.rst
|
||||||
pyboard/hardware/index.rst
|
pyboard/hardware/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
pyboard_contents.rst
|
pyboard_contents.rst
|
||||||
|
|
||||||
|
@ -47,6 +47,10 @@
|
|||||||
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
|
<span class="linkdescr">MicroPython libraries, including the <a href="{{ pathto("library/machine") }}">machine module</a></span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</p>
|
</p>
|
||||||
|
<p class="biglink">
|
||||||
|
<a class="biglink" href="{{ pathto("genrst/index") }}">Micropython Differences</a><br/>
|
||||||
|
<span class="linkdescr">MicroPython operations which differ from CPython</span>
|
||||||
|
</p>
|
||||||
</td>
|
</td>
|
||||||
<td width="40%" style="padding-left:2em;">
|
<td width="40%" style="padding-left:2em;">
|
||||||
<p class="biglink">
|
<p class="biglink">
|
||||||
|
@ -5,4 +5,5 @@ MicroPython documentation contents
|
|||||||
|
|
||||||
library/index.rst
|
library/index.rst
|
||||||
reference/index.rst
|
reference/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
|
@ -4,6 +4,7 @@ MicroPython documentation and references
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
library/index.rst
|
library/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
unix_contents.rst
|
unix_contents.rst
|
||||||
|
|
||||||
|
@ -8,4 +8,5 @@ MicroPython documentation contents
|
|||||||
wipy/tutorial/index.rst
|
wipy/tutorial/index.rst
|
||||||
library/index.rst
|
library/index.rst
|
||||||
reference/index.rst
|
reference/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
|
@ -7,6 +7,7 @@ MicroPython documentation and references
|
|||||||
wipy/general.rst
|
wipy/general.rst
|
||||||
wipy/tutorial/index.rst
|
wipy/tutorial/index.rst
|
||||||
library/index.rst
|
library/index.rst
|
||||||
|
genrst/index.rst
|
||||||
license.rst
|
license.rst
|
||||||
wipy_contents.rst
|
wipy_contents.rst
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ class LCD160CR:
|
|||||||
self._fcmd2('<BBB', 0x19, value)
|
self._fcmd2('<BBB', 0x19, value)
|
||||||
|
|
||||||
def save_to_flash(self):
|
def save_to_flash(self):
|
||||||
self._fcmd2('<BBB', 0x66, 'n')
|
self._send(b'\x02fn')
|
||||||
|
|
||||||
#### PIXEL ACCESS ####
|
#### PIXEL ACCESS ####
|
||||||
|
|
||||||
@ -243,13 +243,13 @@ class LCD160CR:
|
|||||||
self._fcmd2b('<BBBBH', 0x41, x, y, c)
|
self._fcmd2b('<BBBBH', 0x41, x, y, c)
|
||||||
|
|
||||||
def get_pixel(self, x, y):
|
def get_pixel(self, x, y):
|
||||||
self._fcmd2b('<BBBB', 0x61, x, y)
|
self._fcmd2('<BBBB', 0x61, x, y)
|
||||||
t = 1000
|
t = 1000
|
||||||
while t:
|
while t:
|
||||||
self.i2c.readfrom_into(self.i2c_addr, self.buf1)
|
self.i2c.readfrom_into(self.i2c_addr, self.buf1)
|
||||||
if self.buf1[0] >= 2:
|
if self.buf1[0] >= 2:
|
||||||
self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
|
self.i2c.readfrom_into(self.i2c_addr, self.buf[3])
|
||||||
return self.buf[3][1] + self.buf[3][2] << 8
|
return self.buf[3][1] | self.buf[3][2] << 8
|
||||||
t -= 1
|
t -= 1
|
||||||
sleep_ms(1)
|
sleep_ms(1)
|
||||||
raise OSError(uerrno.ETIMEDOUT)
|
raise OSError(uerrno.ETIMEDOUT)
|
||||||
@ -446,6 +446,8 @@ class LCD160CR:
|
|||||||
self._send(s)
|
self._send(s)
|
||||||
|
|
||||||
def jpeg_start(self, l):
|
def jpeg_start(self, l):
|
||||||
|
if l > 0xffff:
|
||||||
|
raise ValueError('length must be 65535 or less')
|
||||||
self.oflush()
|
self.oflush()
|
||||||
self._fcmd2('<BBH', 0x6a, l)
|
self._fcmd2('<BBH', 0x6a, l)
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
#define MICROPY_PY_BUILTINS_PROPERTY (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP (1)
|
#define MICROPY_PY_BUILTINS_HELP (1)
|
||||||
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
|
#define MICROPY_PY_BUILTINS_HELP_TEXT esp_help_text
|
||||||
|
#define MICROPY_PY_BUILTINS_HELP_MODULES (1)
|
||||||
#define MICROPY_PY___FILE__ (0)
|
#define MICROPY_PY___FILE__ (0)
|
||||||
#define MICROPY_PY_GC (1)
|
#define MICROPY_PY_GC (1)
|
||||||
#define MICROPY_PY_ARRAY (1)
|
#define MICROPY_PY_ARRAY (1)
|
||||||
|
@ -74,7 +74,7 @@ STATIC uint32_t yasmarang_randbelow(uint32_t n) {
|
|||||||
STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
|
STATIC mp_obj_t mod_urandom_getrandbits(mp_obj_t num_in) {
|
||||||
int n = mp_obj_get_int(num_in);
|
int n = mp_obj_get_int(num_in);
|
||||||
if (n > 32 || n == 0) {
|
if (n > 32 || n == 0) {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
mp_raise_ValueError(NULL);
|
||||||
}
|
}
|
||||||
uint32_t mask = ~0;
|
uint32_t mask = ~0;
|
||||||
// Beware of C undefined behavior when shifting by >= than bit size
|
// Beware of C undefined behavior when shifting by >= than bit size
|
||||||
@ -102,7 +102,7 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
|
|||||||
if (start > 0) {
|
if (start > 0) {
|
||||||
return mp_obj_new_int(yasmarang_randbelow(start));
|
return mp_obj_new_int(yasmarang_randbelow(start));
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mp_int_t stop = mp_obj_get_int(args[1]);
|
mp_int_t stop = mp_obj_get_int(args[1]);
|
||||||
@ -111,7 +111,7 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
|
|||||||
if (start < stop) {
|
if (start < stop) {
|
||||||
return mp_obj_new_int(start + yasmarang_randbelow(stop - start));
|
return mp_obj_new_int(start + yasmarang_randbelow(stop - start));
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
goto error;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// range(start, stop, step)
|
// range(start, stop, step)
|
||||||
@ -122,15 +122,18 @@ STATIC mp_obj_t mod_urandom_randrange(size_t n_args, const mp_obj_t *args) {
|
|||||||
} else if (step < 0) {
|
} else if (step < 0) {
|
||||||
n = (stop - start + step + 1) / step;
|
n = (stop - start + step + 1) / step;
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
goto error;
|
||||||
}
|
}
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
return mp_obj_new_int(start + step * yasmarang_randbelow(n));
|
return mp_obj_new_int(start + step * yasmarang_randbelow(n));
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error:
|
||||||
|
mp_raise_ValueError(NULL);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_urandom_randrange_obj, 1, 3, mod_urandom_randrange);
|
||||||
|
|
||||||
@ -140,7 +143,7 @@ STATIC mp_obj_t mod_urandom_randint(mp_obj_t a_in, mp_obj_t b_in) {
|
|||||||
if (a <= b) {
|
if (a <= b) {
|
||||||
return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
|
return mp_obj_new_int(a + yasmarang_randbelow(b - a + 1));
|
||||||
} else {
|
} else {
|
||||||
nlr_raise(mp_obj_new_exception(&mp_type_ValueError));
|
mp_raise_ValueError(NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_urandom_randint_obj, mod_urandom_randint);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
* The MIT License (MIT)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2014 Damien P. George
|
* Copyright (c) 2014 Damien P. George
|
||||||
* Copyright (c) 2016 Paul Sokolovsky
|
* Copyright (c) 2016-2017 Paul Sokolovsky
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
struct qentry {
|
struct qentry {
|
||||||
mp_uint_t time;
|
mp_uint_t time;
|
||||||
|
mp_uint_t id;
|
||||||
mp_obj_t callback;
|
mp_obj_t callback;
|
||||||
mp_obj_t args;
|
mp_obj_t args;
|
||||||
};
|
};
|
||||||
@ -54,6 +55,7 @@ typedef struct _mp_obj_utimeq_t {
|
|||||||
struct qentry items[];
|
struct qentry items[];
|
||||||
} mp_obj_utimeq_t;
|
} mp_obj_utimeq_t;
|
||||||
|
|
||||||
|
STATIC mp_uint_t utimeq_id;
|
||||||
|
|
||||||
STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) {
|
STATIC mp_obj_utimeq_t *get_heap(mp_obj_t heap_in) {
|
||||||
return MP_OBJ_TO_PTR(heap_in);
|
return MP_OBJ_TO_PTR(heap_in);
|
||||||
@ -63,6 +65,11 @@ STATIC bool time_less_than(struct qentry *item, struct qentry *parent) {
|
|||||||
mp_uint_t item_tm = item->time;
|
mp_uint_t item_tm = item->time;
|
||||||
mp_uint_t parent_tm = parent->time;
|
mp_uint_t parent_tm = parent->time;
|
||||||
mp_uint_t res = parent_tm - item_tm;
|
mp_uint_t res = parent_tm - item_tm;
|
||||||
|
if (res == 0) {
|
||||||
|
// TODO: This actually should use the same "ring" logic
|
||||||
|
// as for time, to avoid artifacts when id's overflow.
|
||||||
|
return item->id < parent->id;
|
||||||
|
}
|
||||||
if ((mp_int_t)res < 0) {
|
if ((mp_int_t)res < 0) {
|
||||||
res += MODULO;
|
res += MODULO;
|
||||||
}
|
}
|
||||||
@ -125,6 +132,7 @@ STATIC mp_obj_t mod_utimeq_heappush(size_t n_args, const mp_obj_t *args) {
|
|||||||
}
|
}
|
||||||
mp_uint_t l = heap->len;
|
mp_uint_t l = heap->len;
|
||||||
heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
heap->items[l].time = MP_OBJ_SMALL_INT_VALUE(args[1]);
|
||||||
|
heap->items[l].id = utimeq_id++;
|
||||||
heap->items[l].callback = args[2];
|
heap->items[l].callback = args[2];
|
||||||
heap->items[l].args = args[3];
|
heap->items[l].args = args[3];
|
||||||
heap_siftdown(heap, 0, heap->len);
|
heap_siftdown(heap, 0, heap->len);
|
||||||
|
@ -75,11 +75,15 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
|
|||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
#if MICROPY_ENABLE_COMPILER
|
||||||
// source is a lexer, parse and compile the script
|
// source is a lexer, parse and compile the script
|
||||||
mp_lexer_t *lex = source;
|
mp_lexer_t *lex = source;
|
||||||
qstr source_name = lex->source_name;
|
qstr source_name = lex->source_name;
|
||||||
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
|
mp_parse_tree_t parse_tree = mp_parse(lex, input_kind);
|
||||||
module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);
|
module_fun = mp_compile(&parse_tree, source_name, MP_EMIT_OPT_NONE, exec_flags & EXEC_FLAG_IS_REPL);
|
||||||
|
#else
|
||||||
|
mp_raise_msg(&mp_type_RuntimeError, "script compilation not supported");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute code
|
// execute code
|
||||||
@ -137,6 +141,7 @@ STATIC int parse_compile_execute(void *source, mp_parse_input_kind_t input_kind,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if MICROPY_ENABLE_COMPILER
|
||||||
#if MICROPY_REPL_EVENT_DRIVEN
|
#if MICROPY_REPL_EVENT_DRIVEN
|
||||||
|
|
||||||
typedef struct _repl_t {
|
typedef struct _repl_t {
|
||||||
@ -497,6 +502,7 @@ friendly_repl_reset:
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif // MICROPY_REPL_EVENT_DRIVEN
|
#endif // MICROPY_REPL_EVENT_DRIVEN
|
||||||
|
#endif // MICROPY_ENABLE_COMPILER
|
||||||
|
|
||||||
int pyexec_file(const char *filename) {
|
int pyexec_file(const char *filename) {
|
||||||
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
|
mp_lexer_t *lex = mp_lexer_new_from_file(filename);
|
||||||
|
@ -33,3 +33,15 @@ This version of the build will work out-of-the-box on a pyboard (and
|
|||||||
anything similar), and will give you a MicroPython REPL on UART1 at 9600
|
anything similar), and will give you a MicroPython REPL on UART1 at 9600
|
||||||
baud. Pin PA13 will also be driven high, and this turns on the red LED on
|
baud. Pin PA13 will also be driven high, and this turns on the red LED on
|
||||||
the pyboard.
|
the pyboard.
|
||||||
|
|
||||||
|
## Building without the built-in MicroPython compiler
|
||||||
|
|
||||||
|
This minimal port can be built with the built-in MicroPython compiler
|
||||||
|
disabled. This will reduce the firmware by about 20k on a Thumb2 machine,
|
||||||
|
and by about 40k on 32-bit x86. Without the compiler the REPL will be
|
||||||
|
disabled, but pre-compiled scripts can still be executed.
|
||||||
|
|
||||||
|
To test out this feature, change the `MICROPY_ENABLE_COMPILER` config
|
||||||
|
option to "0" in the mpconfigport.h file in this directory. Then
|
||||||
|
recompile and run the firmware and it will execute the frozentest.py
|
||||||
|
file.
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include "py/gc.h"
|
#include "py/gc.h"
|
||||||
#include "lib/utils/pyexec.h"
|
#include "lib/utils/pyexec.h"
|
||||||
|
|
||||||
|
#if MICROPY_ENABLE_COMPILER
|
||||||
void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
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);
|
mp_lexer_t *lex = mp_lexer_new_from_str_len(MP_QSTR__lt_stdin_gt_, src, strlen(src), 0);
|
||||||
if (lex == NULL) {
|
if (lex == NULL) {
|
||||||
@ -28,6 +29,7 @@ void do_str(const char *src, mp_parse_input_kind_t input_kind) {
|
|||||||
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
|
mp_obj_print_exception(&mp_plat_print, (mp_obj_t)nlr.ret_val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static char *stack_top;
|
static char *stack_top;
|
||||||
static char heap[2048];
|
static char heap[2048];
|
||||||
@ -40,6 +42,7 @@ int main(int argc, char **argv) {
|
|||||||
gc_init(heap, heap + sizeof(heap));
|
gc_init(heap, heap + sizeof(heap));
|
||||||
#endif
|
#endif
|
||||||
mp_init();
|
mp_init();
|
||||||
|
#if MICROPY_ENABLE_COMPILER
|
||||||
#if MICROPY_REPL_EVENT_DRIVEN
|
#if MICROPY_REPL_EVENT_DRIVEN
|
||||||
pyexec_event_repl_init();
|
pyexec_event_repl_init();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -53,6 +56,9 @@ int main(int argc, char **argv) {
|
|||||||
#endif
|
#endif
|
||||||
//do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
|
//do_str("print('hello world!', list(x+1 for x in range(10)), end='eol\\n')", MP_PARSE_SINGLE_INPUT);
|
||||||
//do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
|
//do_str("for i in range(10):\r\n print(i)", MP_PARSE_FILE_INPUT);
|
||||||
|
#else
|
||||||
|
pyexec_frozen_module("frozentest.py");
|
||||||
|
#endif
|
||||||
mp_deinit();
|
mp_deinit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -81,6 +87,7 @@ mp_obj_t mp_builtin_open(uint n_args, const mp_obj_t *args, mp_map_t *kwargs) {
|
|||||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||||
|
|
||||||
void nlr_jump_fail(void *val) {
|
void nlr_jump_fail(void *val) {
|
||||||
|
while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NORETURN __fatal_error(const char *msg) {
|
void NORETURN __fatal_error(const char *msg) {
|
||||||
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
// options to control how Micro Python is built
|
// options to control how Micro Python is built
|
||||||
|
|
||||||
|
// You can disable the built-in MicroPython compiler by setting the following
|
||||||
|
// config option to 0. If you do this then you won't get a REPL prompt, but you
|
||||||
|
// will still be able to execute pre-compiled scripts, compiled with mpy-cross.
|
||||||
|
#define MICROPY_ENABLE_COMPILER (1)
|
||||||
|
|
||||||
#define MICROPY_QSTR_BYTES_IN_HASH (1)
|
#define MICROPY_QSTR_BYTES_IN_HASH (1)
|
||||||
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
|
#define MICROPY_QSTR_EXTRA_POOL mp_qstr_frozen_const_pool
|
||||||
#define MICROPY_ALLOC_PATH_MAX (256)
|
#define MICROPY_ALLOC_PATH_MAX (256)
|
||||||
|
39
py/compile.c
39
py/compile.c
@ -47,8 +47,6 @@ typedef enum {
|
|||||||
#include "py/grammar.h"
|
#include "py/grammar.h"
|
||||||
#undef DEF_RULE
|
#undef DEF_RULE
|
||||||
#undef DEF_RULE_NC
|
#undef DEF_RULE_NC
|
||||||
PN_string, // special node for non-interned string
|
|
||||||
PN_bytes, // special node for non-interned bytes
|
|
||||||
PN_const_object, // special node for a constant, generic Python object
|
PN_const_object, // special node for a constant, generic Python object
|
||||||
// define rules without a compile function
|
// define rules without a compile function
|
||||||
#define DEF_RULE(rule, comp, kind, ...)
|
#define DEF_RULE(rule, comp, kind, ...)
|
||||||
@ -1880,8 +1878,6 @@ STATIC void compile_expr_stmt(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|||||||
} else {
|
} else {
|
||||||
// for non-REPL, evaluate then discard the expression
|
// for non-REPL, evaluate then discard the expression
|
||||||
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
|
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0]) && !MP_PARSE_NODE_IS_ID(pns->nodes[0]))
|
||||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)
|
|
||||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_bytes)
|
|
||||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
|
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)) {
|
||||||
// do nothing with a lonely constant
|
// do nothing with a lonely constant
|
||||||
} else {
|
} else {
|
||||||
@ -2600,31 +2596,17 @@ STATIC void compile_atom_expr_await(compiler_t *comp, mp_parse_node_struct_t *pn
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
STATIC void compile_string(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
STATIC mp_obj_t get_const_object(mp_parse_node_struct_t *pns) {
|
||||||
// only create and load the actual str object on the last pass
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
if (comp->pass != MP_PASS_EMIT) {
|
// nodes are 32-bit pointers, but need to extract 64-bit object
|
||||||
EMIT_ARG(load_const_obj, mp_const_none);
|
return (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32);
|
||||||
} else {
|
#else
|
||||||
EMIT_ARG(load_const_obj, mp_obj_new_str((const char*)pns->nodes[0], pns->nodes[1], false));
|
return (mp_obj_t)pns->nodes[0];
|
||||||
}
|
#endif
|
||||||
}
|
|
||||||
|
|
||||||
STATIC void compile_bytes(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
|
||||||
// only create and load the actual bytes object on the last pass
|
|
||||||
if (comp->pass != MP_PASS_EMIT) {
|
|
||||||
EMIT_ARG(load_const_obj, mp_const_none);
|
|
||||||
} else {
|
|
||||||
EMIT_ARG(load_const_obj, mp_obj_new_bytes((const byte*)pns->nodes[0], pns->nodes[1]));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
STATIC void compile_const_object(compiler_t *comp, mp_parse_node_struct_t *pns) {
|
||||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
EMIT_ARG(load_const_obj, get_const_object(pns));
|
||||||
// nodes are 32-bit pointers, but need to extract 64-bit object
|
|
||||||
EMIT_ARG(load_const_obj, (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
|
|
||||||
#else
|
|
||||||
EMIT_ARG(load_const_obj, (mp_obj_t)pns->nodes[0]);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
typedef void (*compile_function_t)(compiler_t*, mp_parse_node_struct_t*);
|
||||||
@ -2637,8 +2619,6 @@ STATIC const compile_function_t compile_function[] = {
|
|||||||
#undef c
|
#undef c
|
||||||
#undef DEF_RULE
|
#undef DEF_RULE
|
||||||
#undef DEF_RULE_NC
|
#undef DEF_RULE_NC
|
||||||
compile_string,
|
|
||||||
compile_bytes,
|
|
||||||
compile_const_object,
|
compile_const_object,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2891,7 +2871,8 @@ STATIC void check_for_doc_string(compiler_t *comp, mp_parse_node_t pn) {
|
|||||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||||
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
|
if ((MP_PARSE_NODE_IS_LEAF(pns->nodes[0])
|
||||||
&& MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
|
&& MP_PARSE_NODE_LEAF_KIND(pns->nodes[0]) == MP_PARSE_NODE_STRING)
|
||||||
|| MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_string)) {
|
|| (MP_PARSE_NODE_IS_STRUCT_KIND(pns->nodes[0], PN_const_object)
|
||||||
|
&& MP_OBJ_IS_STR(get_const_object((mp_parse_node_struct_t*)pns->nodes[0])))) {
|
||||||
// compile the doc string
|
// compile the doc string
|
||||||
compile_node(comp, pns->nodes[0]);
|
compile_node(comp, pns->nodes[0]);
|
||||||
// store the doc string
|
// store the doc string
|
||||||
|
@ -42,8 +42,6 @@ typedef enum {
|
|||||||
#include "py/grammar.h"
|
#include "py/grammar.h"
|
||||||
#undef DEF_RULE
|
#undef DEF_RULE
|
||||||
#undef DEF_RULE_NC
|
#undef DEF_RULE_NC
|
||||||
PN_string, // special node for non-interned string
|
|
||||||
PN_bytes, // special node for non-interned bytes
|
|
||||||
PN_const_object, // special node for a constant, generic Python object
|
PN_const_object, // special node for a constant, generic Python object
|
||||||
// define rules without a compile function
|
// define rules without a compile function
|
||||||
#define DEF_RULE(rule, comp, kind, ...)
|
#define DEF_RULE(rule, comp, kind, ...)
|
||||||
|
11
py/map.c
11
py/map.c
@ -178,8 +178,14 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
|
|||||||
for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) {
|
for (mp_map_elem_t *elem = &map->table[0], *top = &map->table[map->used]; elem < top; elem++) {
|
||||||
if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) {
|
if (elem->key == index || (!compare_only_ptrs && mp_obj_equal(elem->key, index))) {
|
||||||
if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) {
|
if (MP_UNLIKELY(lookup_kind == MP_MAP_LOOKUP_REMOVE_IF_FOUND)) {
|
||||||
elem->key = MP_OBJ_SENTINEL;
|
// remove the found element by moving the rest of the array down
|
||||||
// keep elem->value so that caller can access it if needed
|
mp_obj_t value = elem->value;
|
||||||
|
--map->used;
|
||||||
|
memmove(elem, elem + 1, (top - elem - 1) * sizeof(*elem));
|
||||||
|
// put the found element after the end so the caller can access it if needed
|
||||||
|
elem = &map->table[map->used];
|
||||||
|
elem->key = MP_OBJ_NULL;
|
||||||
|
elem->value = value;
|
||||||
}
|
}
|
||||||
return elem;
|
return elem;
|
||||||
}
|
}
|
||||||
@ -187,7 +193,6 @@ mp_map_elem_t *mp_map_lookup(mp_map_t *map, mp_obj_t index, mp_map_lookup_kind_t
|
|||||||
if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) {
|
if (MP_LIKELY(lookup_kind != MP_MAP_LOOKUP_ADD_IF_NOT_FOUND)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
// TODO shrink array down over any previously-freed slots
|
|
||||||
if (map->used == map->alloc) {
|
if (map->used == map->alloc) {
|
||||||
// TODO: Alloc policy
|
// TODO: Alloc policy
|
||||||
map->alloc += 4;
|
map->alloc += 4;
|
||||||
|
13
py/modsys.c
13
py/modsys.c
@ -32,6 +32,7 @@
|
|||||||
#include "py/objstr.h"
|
#include "py/objstr.h"
|
||||||
#include "py/objint.h"
|
#include "py/objint.h"
|
||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
|
#include "py/smallint.h"
|
||||||
|
|
||||||
#if MICROPY_PY_SYS
|
#if MICROPY_PY_SYS
|
||||||
|
|
||||||
@ -162,12 +163,12 @@ STATIC const mp_rom_map_elem_t mp_module_sys_globals_table[] = {
|
|||||||
|
|
||||||
#if MICROPY_PY_SYS_MAXSIZE
|
#if MICROPY_PY_SYS_MAXSIZE
|
||||||
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
#if MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE
|
||||||
// INT_MAX is not representable as small int, as we know that small int
|
// Maximum mp_int_t value is not representable as small int, so we have
|
||||||
// takes one bit for tag. So, we have little choice but to provide this
|
// little choice but to use MP_SMALL_INT_MAX. Apps also should be careful
|
||||||
// value. Apps also should be careful to not try to compare sys.maxsize
|
// to not try to compare sys.maxsize to some literal number (as this
|
||||||
// with some number (which may not fit in available int size), but instead
|
// number might not fit in available int size), but instead count number
|
||||||
// count number of significant bits in sys.maxsize.
|
// of "one" bits in sys.maxsize.
|
||||||
{ MP_ROM_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(INT_MAX >> 1) },
|
{ MP_ROM_QSTR(MP_QSTR_maxsize), MP_OBJ_NEW_SMALL_INT(MP_SMALL_INT_MAX) },
|
||||||
#else
|
#else
|
||||||
{ MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) },
|
{ MP_ROM_QSTR(MP_QSTR_maxsize), MP_ROM_PTR(&mp_maxsize_obj) },
|
||||||
#endif
|
#endif
|
||||||
|
@ -143,6 +143,8 @@ STATIC mp_obj_t mod_thread_stack_size(size_t n_args, const mp_obj_t *args) {
|
|||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mod_thread_stack_size_obj, 0, 1, mod_thread_stack_size);
|
||||||
|
|
||||||
typedef struct _thread_entry_args_t {
|
typedef struct _thread_entry_args_t {
|
||||||
|
mp_obj_dict_t *dict_locals;
|
||||||
|
mp_obj_dict_t *dict_globals;
|
||||||
size_t stack_size;
|
size_t stack_size;
|
||||||
mp_obj_t fun;
|
mp_obj_t fun;
|
||||||
size_t n_args;
|
size_t n_args;
|
||||||
@ -161,6 +163,10 @@ STATIC void *thread_entry(void *args_in) {
|
|||||||
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
|
mp_stack_set_top(&ts + 1); // need to include ts in root-pointer scan
|
||||||
mp_stack_set_limit(args->stack_size);
|
mp_stack_set_limit(args->stack_size);
|
||||||
|
|
||||||
|
// set locals and globals from the calling context
|
||||||
|
mp_locals_set(args->dict_locals);
|
||||||
|
mp_globals_set(args->dict_globals);
|
||||||
|
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
|
|
||||||
// signal that we are set up and running
|
// signal that we are set up and running
|
||||||
@ -169,7 +175,6 @@ STATIC void *thread_entry(void *args_in) {
|
|||||||
// TODO set more thread-specific state here:
|
// TODO set more thread-specific state here:
|
||||||
// mp_pending_exception? (root pointer)
|
// mp_pending_exception? (root pointer)
|
||||||
// cur_exception (root pointer)
|
// cur_exception (root pointer)
|
||||||
// dict_locals? (root pointer) uPy doesn't make a new locals dict for functions, just for classes, so it's different to CPy
|
|
||||||
|
|
||||||
DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top));
|
DEBUG_printf("[thread] start ts=%p args=%p stack=%p\n", &ts, &args, MP_STATE_THREAD(stack_top));
|
||||||
|
|
||||||
@ -240,6 +245,10 @@ STATIC mp_obj_t mod_thread_start_new_thread(size_t n_args, const mp_obj_t *args)
|
|||||||
th_args->n_args = pos_args_len;
|
th_args->n_args = pos_args_len;
|
||||||
memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
|
memcpy(th_args->args, pos_args_items, pos_args_len * sizeof(mp_obj_t));
|
||||||
|
|
||||||
|
// pass our locals and globals into the new thread
|
||||||
|
th_args->dict_locals = mp_locals_get();
|
||||||
|
th_args->dict_globals = mp_globals_get();
|
||||||
|
|
||||||
// set the stack size to use
|
// set the stack size to use
|
||||||
th_args->stack_size = thread_stack_size;
|
th_args->stack_size = thread_stack_size;
|
||||||
|
|
||||||
|
@ -32,9 +32,10 @@
|
|||||||
|
|
||||||
#if MICROPY_PY_UERRNO
|
#if MICROPY_PY_UERRNO
|
||||||
|
|
||||||
// This list could be defined per port in mpconfigport.h to tailor it to a
|
// This list can be defined per port in mpconfigport.h to tailor it to a
|
||||||
// specific port's needs. But for now we have a common list.
|
// specific port's needs. If it's not defined then we provide a default.
|
||||||
#define ERRNO_LIST \
|
#ifndef MICROPY_PY_UERRNO_LIST
|
||||||
|
#define MICROPY_PY_UERRNO_LIST \
|
||||||
X(EPERM) \
|
X(EPERM) \
|
||||||
X(ENOENT) \
|
X(ENOENT) \
|
||||||
X(EIO) \
|
X(EIO) \
|
||||||
@ -58,9 +59,12 @@
|
|||||||
X(EALREADY) \
|
X(EALREADY) \
|
||||||
X(EINPROGRESS) \
|
X(EINPROGRESS) \
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if MICROPY_PY_UERRNO_ERRORCODE
|
||||||
STATIC const mp_rom_map_elem_t errorcode_table[] = {
|
STATIC const mp_rom_map_elem_t errorcode_table[] = {
|
||||||
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
|
#define X(e) { MP_ROM_INT(MP_ ## e), MP_ROM_QSTR(MP_QSTR_## e) },
|
||||||
ERRNO_LIST
|
MICROPY_PY_UERRNO_LIST
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,13 +79,16 @@ STATIC const mp_obj_dict_t errorcode_dict = {
|
|||||||
.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,
|
.table = (mp_map_elem_t*)(mp_rom_map_elem_t*)errorcode_table,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
|
STATIC const mp_rom_map_elem_t mp_module_uerrno_globals_table[] = {
|
||||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_uerrno) },
|
||||||
|
#if MICROPY_PY_UERRNO_ERRORCODE
|
||||||
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
|
{ MP_ROM_QSTR(MP_QSTR_errorcode), MP_ROM_PTR(&errorcode_dict) },
|
||||||
|
#endif
|
||||||
|
|
||||||
#define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },
|
#define X(e) { MP_ROM_QSTR(MP_QSTR_## e), MP_ROM_INT(MP_ ## e) },
|
||||||
ERRNO_LIST
|
MICROPY_PY_UERRNO_LIST
|
||||||
#undef X
|
#undef X
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,12 +100,23 @@ const mp_obj_module_t mp_module_uerrno = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
qstr mp_errno_to_str(mp_obj_t errno_val) {
|
qstr mp_errno_to_str(mp_obj_t errno_val) {
|
||||||
|
#if MICROPY_PY_UERRNO_ERRORCODE
|
||||||
|
// We have the errorcode dict so can do a lookup using the hash map
|
||||||
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
|
mp_map_elem_t *elem = mp_map_lookup((mp_map_t*)&errorcode_dict.map, errno_val, MP_MAP_LOOKUP);
|
||||||
if (elem == NULL) {
|
if (elem == NULL) {
|
||||||
return MP_QSTR_NULL;
|
return MP_QSTR_NULL;
|
||||||
} else {
|
} else {
|
||||||
return MP_OBJ_QSTR_VALUE(elem->value);
|
return MP_OBJ_QSTR_VALUE(elem->value);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// We don't have the errorcode dict so do a simple search in the modules dict
|
||||||
|
for (size_t i = 0; i < MP_ARRAY_SIZE(mp_module_uerrno_globals_table); ++i) {
|
||||||
|
if (errno_val == mp_module_uerrno_globals_table[i].value) {
|
||||||
|
return MP_OBJ_QSTR_VALUE(mp_module_uerrno_globals_table[i].key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MP_QSTR_NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //MICROPY_PY_UERRNO
|
#endif //MICROPY_PY_UERRNO
|
||||||
|
@ -917,6 +917,11 @@ typedef double mp_float_t;
|
|||||||
#define MICROPY_PY_UERRNO (0)
|
#define MICROPY_PY_UERRNO (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Whether to provide the uerrno.errorcode dict
|
||||||
|
#ifndef MICROPY_PY_UERRNO_ERRORCODE
|
||||||
|
#define MICROPY_PY_UERRNO_ERRORCODE (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Whether to provide "uselect" module (baremetal implementation)
|
// Whether to provide "uselect" module (baremetal implementation)
|
||||||
#ifndef MICROPY_PY_USELECT
|
#ifndef MICROPY_PY_USELECT
|
||||||
#define MICROPY_PY_USELECT (0)
|
#define MICROPY_PY_USELECT (0)
|
||||||
|
14
py/mpstate.h
14
py/mpstate.h
@ -196,11 +196,13 @@ typedef struct _mp_state_vm_t {
|
|||||||
// This structure holds state that is specific to a given thread.
|
// This structure holds state that is specific to a given thread.
|
||||||
// Everything in this structure is scanned for root pointers.
|
// Everything in this structure is scanned for root pointers.
|
||||||
typedef struct _mp_state_thread_t {
|
typedef struct _mp_state_thread_t {
|
||||||
|
mp_obj_dict_t *dict_locals;
|
||||||
|
mp_obj_dict_t *dict_globals;
|
||||||
|
|
||||||
// Note: nlr asm code has the offset of this hard-coded
|
// Note: nlr asm code has the offset of this hard-coded
|
||||||
nlr_buf_t *nlr_top; // ROOT POINTER
|
nlr_buf_t *nlr_top; // ROOT POINTER
|
||||||
|
|
||||||
// Stack top at the start of program
|
// Stack top at the start of program
|
||||||
// Note: this entry is used to locate the end of the root pointer section.
|
|
||||||
char *stack_top;
|
char *stack_top;
|
||||||
|
|
||||||
#if MICROPY_STACK_CHECK
|
#if MICROPY_STACK_CHECK
|
||||||
@ -208,15 +210,11 @@ typedef struct _mp_state_thread_t {
|
|||||||
#endif
|
#endif
|
||||||
} mp_state_thread_t;
|
} mp_state_thread_t;
|
||||||
|
|
||||||
// This structure combines the above 3 structures, and adds the local
|
// This structure combines the above 3 structures.
|
||||||
// and global dicts.
|
// The order of the entries are important for root pointer scanning in the GC to work.
|
||||||
// Note: if this structure changes then revisit all nlr asm code since they
|
// Note: if this structure changes then revisit all nlr asm code since they
|
||||||
// have the offset of nlr_top hard-coded.
|
// have the offset of nlr_top hard-coded.
|
||||||
typedef struct _mp_state_ctx_t {
|
typedef struct _mp_state_ctx_t {
|
||||||
// these must come first for root pointer scanning in GC to work
|
|
||||||
mp_obj_dict_t *dict_locals;
|
|
||||||
mp_obj_dict_t *dict_globals;
|
|
||||||
// these must come next in this order for root pointer scanning in GC to work
|
|
||||||
mp_state_thread_t thread;
|
mp_state_thread_t thread;
|
||||||
mp_state_vm_t vm;
|
mp_state_vm_t vm;
|
||||||
mp_state_mem_t mem;
|
mp_state_mem_t mem;
|
||||||
@ -224,7 +222,7 @@ typedef struct _mp_state_ctx_t {
|
|||||||
|
|
||||||
extern mp_state_ctx_t mp_state_ctx;
|
extern mp_state_ctx_t mp_state_ctx;
|
||||||
|
|
||||||
#define MP_STATE_CTX(x) (mp_state_ctx.x)
|
#define MP_STATE_CTX(x) MP_STATE_THREAD(x)
|
||||||
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
|
#define MP_STATE_VM(x) (mp_state_ctx.vm.x)
|
||||||
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
|
#define MP_STATE_MEM(x) (mp_state_ctx.mem.x)
|
||||||
|
|
||||||
|
2
py/nlr.h
2
py/nlr.h
@ -82,7 +82,7 @@ NORETURN void nlr_jump(void *val);
|
|||||||
// This must be implemented by a port. It's called by nlr_jump
|
// This must be implemented by a port. It's called by nlr_jump
|
||||||
// if no nlr buf has been pushed. It must not return, but rather
|
// if no nlr buf has been pushed. It must not return, but rather
|
||||||
// should bail out with a fatal error.
|
// should bail out with a fatal error.
|
||||||
void nlr_jump_fail(void *val);
|
NORETURN void nlr_jump_fail(void *val);
|
||||||
|
|
||||||
// use nlr_raise instead of nlr_jump so that debugging is easier
|
// use nlr_raise instead of nlr_jump so that debugging is easier
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
|
262
py/nlrx64.S
262
py/nlrx64.S
@ -1,262 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Micro Python project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__x86_64__) && !MICROPY_NLR_SETJMP
|
|
||||||
|
|
||||||
// We only need the functions here if we are on x86-64, and we are not
|
|
||||||
// using setjmp/longjmp.
|
|
||||||
//
|
|
||||||
// For reference, x86-64 callee save regs are:
|
|
||||||
// rbx, rbp, rsp, r12, r13, r14, r15
|
|
||||||
|
|
||||||
// the offset of nlr_top within mp_state_ctx_t
|
|
||||||
#define NLR_TOP_OFFSET (2 * 8)
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
|
|
||||||
#define MP_THREAD_GET_STATE _mp_thread_get_state
|
|
||||||
#else
|
|
||||||
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
|
|
||||||
#define MP_THREAD_GET_STATE mp_thread_get_state
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// offset of nlr_top within mp_state_thread_t structure
|
|
||||||
#define NLR_TOP_TH_OFF (0)
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
#define NLR_OS_WINDOWS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
.file "nlr.s"
|
|
||||||
.text
|
|
||||||
|
|
||||||
#if !defined(NLR_OS_WINDOWS)
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
//
|
|
||||||
// Functions for *nix and OSX.
|
|
||||||
// OSX needs _ prefix for binding to C, and doesn't support some directives.
|
|
||||||
//
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// mp_uint_t nlr_push(rdi=nlr_buf_t *nlr)
|
|
||||||
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
.globl nlr_push
|
|
||||||
.type nlr_push, @function
|
|
||||||
nlr_push:
|
|
||||||
#else
|
|
||||||
.globl _nlr_push
|
|
||||||
_nlr_push:
|
|
||||||
#endif
|
|
||||||
movq (%rsp), %rax # load return %rip
|
|
||||||
movq %rax, 16(%rdi) # store %rip into nlr_buf
|
|
||||||
movq %rbp, 24(%rdi) # store %rbp into nlr_buf
|
|
||||||
movq %rsp, 32(%rdi) # store %rsp into nlr_buf
|
|
||||||
movq %rbx, 40(%rdi) # store %rbx into nlr_buf
|
|
||||||
movq %r12, 48(%rdi) # store %r12 into nlr_buf
|
|
||||||
movq %r13, 56(%rdi) # store %r13 into nlr_buf
|
|
||||||
movq %r14, 64(%rdi) # store %r14 into nlr_buf
|
|
||||||
movq %r15, 72(%rdi) # store %r15 into nlr_buf
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
movq NLR_TOP(%rip), %rax # get last nlr_buf
|
|
||||||
movq %rax, (%rdi) # store it
|
|
||||||
movq %rdi, NLR_TOP(%rip) # stor new nlr_buf (to make linked list)
|
|
||||||
#else
|
|
||||||
movq %rdi, %rbp # since we make a call, must save rdi in rbp
|
|
||||||
callq MP_THREAD_GET_STATE # get mp_state_thread ptr into rax
|
|
||||||
movq NLR_TOP_TH_OFF(%rax), %rsi # get thread.nlr_top (last nlr_buf)
|
|
||||||
movq %rsi, (%rbp) # store it
|
|
||||||
movq %rbp, NLR_TOP_TH_OFF(%rax) # store new nlr_buf (to make linked list)
|
|
||||||
movq 24(%rbp), %rbp # restore rbp
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xorq %rax, %rax # return 0, normal return
|
|
||||||
ret # return
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
.size nlr_push, .-nlr_push
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_pop()
|
|
||||||
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
.globl nlr_pop
|
|
||||||
.type nlr_pop, @function
|
|
||||||
nlr_pop:
|
|
||||||
#else
|
|
||||||
.globl _nlr_pop
|
|
||||||
_nlr_pop:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
movq NLR_TOP(%rip), %rax # get nlr_top into %rax
|
|
||||||
movq (%rax), %rax # load prev nlr_buf
|
|
||||||
movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
|
|
||||||
#else
|
|
||||||
callq MP_THREAD_GET_STATE # get mp_state_thread ptr into rax
|
|
||||||
movq NLR_TOP_TH_OFF(%rax), %rdi # get thread.nlr_top (last nlr_buf)
|
|
||||||
movq (%rdi), %rdi # load prev nlr_buf
|
|
||||||
movq %rdi, NLR_TOP_TH_OFF(%rax) # store prev nlr_buf (to unlink list)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret # return
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
.size nlr_pop, .-nlr_pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_jump(rdi=mp_uint_t val)
|
|
||||||
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
.globl nlr_jump
|
|
||||||
.type nlr_jump, @function
|
|
||||||
nlr_jump:
|
|
||||||
#else
|
|
||||||
.globl _nlr_jump
|
|
||||||
_nlr_jump:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
movq %rdi, %rax # put return value in %rax
|
|
||||||
movq NLR_TOP(%rip), %rdi # get nlr_top into %rdi
|
|
||||||
test %rdi, %rdi # check for nlr_top being NULL
|
|
||||||
je .fail # fail if nlr_top is NULL
|
|
||||||
movq %rax, 8(%rdi) # store return value
|
|
||||||
movq (%rdi), %rax # load prev nlr_buf
|
|
||||||
movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
|
|
||||||
#else
|
|
||||||
movq %rdi, %rbp # put return value in rbp
|
|
||||||
callq MP_THREAD_GET_STATE # get thread ptr in rax
|
|
||||||
movq %rax, %rsi # put thread ptr in rsi
|
|
||||||
movq %rbp, %rax # put return value to rax (for je .fail)
|
|
||||||
movq NLR_TOP_TH_OFF(%rsi), %rdi # get thread.nlr_top in rdi
|
|
||||||
test %rdi, %rdi # check for nlr_top being NULL
|
|
||||||
je .fail # fail if nlr_top is NULL
|
|
||||||
movq %rax, 8(%rdi) # store return value
|
|
||||||
movq (%rdi), %rax # load prev nlr_buf
|
|
||||||
movq %rax, NLR_TOP_TH_OFF(%rsi) # store prev nlr_buf (to unlink list)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
movq 72(%rdi), %r15 # load saved %r15
|
|
||||||
movq 64(%rdi), %r14 # load saved %r14
|
|
||||||
movq 56(%rdi), %r13 # load saved %r13
|
|
||||||
movq 48(%rdi), %r12 # load saved %r12
|
|
||||||
movq 40(%rdi), %rbx # load saved %rbx
|
|
||||||
movq 32(%rdi), %rsp # load saved %rsp
|
|
||||||
movq 24(%rdi), %rbp # load saved %rbp
|
|
||||||
movq 16(%rdi), %rax # load saved %rip
|
|
||||||
movq %rax, (%rsp) # store saved %rip to stack
|
|
||||||
xorq %rax, %rax # clear return register
|
|
||||||
inc %al # increase to make 1, non-local return
|
|
||||||
ret # return
|
|
||||||
.fail:
|
|
||||||
movq %rax, %rdi # put argument back in first-arg register
|
|
||||||
#if !(defined(__APPLE__) && defined(__MACH__))
|
|
||||||
je nlr_jump_fail # transfer control to nlr_jump_fail
|
|
||||||
.size nlr_jump, .-nlr_jump
|
|
||||||
#else
|
|
||||||
je _nlr_jump_fail # transfer control to nlr_jump_fail
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else // !defined(NLR_OS_WINDOWS)
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
//
|
|
||||||
// Functions for Windows
|
|
||||||
//
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// mp_uint_t nlr_push(rcx=nlr_buf_t *nlr)
|
|
||||||
|
|
||||||
.globl nlr_push
|
|
||||||
nlr_push:
|
|
||||||
movq (%rsp), %rax # load return %rip
|
|
||||||
movq %rax, 16(%rcx) # store %rip into nlr_buf
|
|
||||||
movq %rbp, 24(%rcx) # store %rbp into nlr_buf
|
|
||||||
movq %rsp, 32(%rcx) # store %rsp into nlr_buf
|
|
||||||
movq %rbx, 40(%rcx) # store %rbx into nlr_buf
|
|
||||||
movq %r12, 48(%rcx) # store %r12 into nlr_buf
|
|
||||||
movq %r13, 56(%rcx) # store %r13 into nlr_buf
|
|
||||||
movq %r14, 64(%rcx) # store %r14 into nlr_buf
|
|
||||||
movq %r15, 72(%rcx) # store %r15 into
|
|
||||||
movq %rdi, 80(%rcx) # store %rdr into
|
|
||||||
movq %rsi, 88(%rcx) # store %rsi into
|
|
||||||
movq NLR_TOP(%rip), %rax # get last nlr_buf
|
|
||||||
movq %rax, (%rcx) # store it
|
|
||||||
movq %rcx, NLR_TOP(%rip) # stor new nlr_buf (to make linked list)
|
|
||||||
xorq %rax, %rax # return 0, normal return
|
|
||||||
ret # return
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_pop()
|
|
||||||
|
|
||||||
.globl nlr_pop
|
|
||||||
nlr_pop:
|
|
||||||
movq NLR_TOP(%rip), %rax # get nlr_top into %rax
|
|
||||||
movq (%rax), %rax # load prev nlr_buf
|
|
||||||
movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
|
|
||||||
ret # return
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_jump(rcx=mp_uint_t val)
|
|
||||||
|
|
||||||
.globl nlr_jump
|
|
||||||
nlr_jump:
|
|
||||||
movq %rcx, %rax # put return value in %rax
|
|
||||||
movq NLR_TOP(%rip), %rcx # get nlr_top into %rcx
|
|
||||||
test %rcx, %rcx # check for nlr_top being NULL
|
|
||||||
je .fail # fail if nlr_top is NULL
|
|
||||||
movq %rax, 8(%rcx) # store return value
|
|
||||||
movq (%rcx), %rax # load prev nlr_buf
|
|
||||||
movq %rax, NLR_TOP(%rip) # store prev nlr_buf (to unlink list)
|
|
||||||
movq 72(%rcx), %r15 # load saved %r15
|
|
||||||
movq 64(%rcx), %r14 # load saved %r14
|
|
||||||
movq 56(%rcx), %r13 # load saved %r13
|
|
||||||
movq 48(%rcx), %r12 # load saved %r12
|
|
||||||
movq 40(%rcx), %rbx # load saved %rbx
|
|
||||||
movq 32(%rcx), %rsp # load saved %rsp
|
|
||||||
movq 24(%rcx), %rbp # load saved %rbp
|
|
||||||
movq 16(%rcx), %rax # load saved %rip
|
|
||||||
movq 80(%rcx), %rdi # store %rdr into
|
|
||||||
movq 88(%rcx), %rsi # store %rsi into
|
|
||||||
movq %rax, (%rsp) # store saved %rip to stack
|
|
||||||
xorq %rax, %rax # clear return register
|
|
||||||
inc %al # increase to make 1, non-local return
|
|
||||||
ret # return
|
|
||||||
.fail:
|
|
||||||
movq %rax, %rcx # put argument back in first-arg register
|
|
||||||
je nlr_jump_fail # transfer control to nlr_jump_fail
|
|
||||||
|
|
||||||
#endif // !defined(NLR_OS_WINDOWS)
|
|
||||||
|
|
||||||
#endif // defined(__x86_64__) && !MICROPY_NLR_SETJMP
|
|
||||||
#if defined(linux)
|
|
||||||
.section .note.GNU-stack,"",%progbits
|
|
||||||
#endif
|
|
129
py/nlrx64.c
Normal file
129
py/nlrx64.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2017 Damien P. George
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mpstate.h"
|
||||||
|
#include "py/nlr.h"
|
||||||
|
|
||||||
|
#if !MICROPY_NLR_SETJMP && defined(__x86_64__)
|
||||||
|
|
||||||
|
#undef nlr_push
|
||||||
|
|
||||||
|
// x86-64 callee-save registers are:
|
||||||
|
// rbx, rbp, rsp, r12, r13, r14, r15
|
||||||
|
|
||||||
|
#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
|
||||||
|
|
||||||
|
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
|
||||||
|
|
||||||
|
unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||||
|
(void)nlr;
|
||||||
|
|
||||||
|
#if NLR_OS_WINDOWS
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"movq (%rsp), %rax \n" // load return %rip
|
||||||
|
"movq %rax, 16(%rcx) \n" // store %rip into nlr_buf
|
||||||
|
"movq %rbp, 24(%rcx) \n" // store %rbp into nlr_buf
|
||||||
|
"movq %rsp, 32(%rcx) \n" // store %rsp into nlr_buf
|
||||||
|
"movq %rbx, 40(%rcx) \n" // store %rbx into nlr_buf
|
||||||
|
"movq %r12, 48(%rcx) \n" // store %r12 into nlr_buf
|
||||||
|
"movq %r13, 56(%rcx) \n" // store %r13 into nlr_buf
|
||||||
|
"movq %r14, 64(%rcx) \n" // store %r14 into nlr_buf
|
||||||
|
"movq %r15, 72(%rcx) \n" // store %r15 into nlr_buf
|
||||||
|
"movq %rdi, 80(%rcx) \n" // store %rdr into nlr_buf
|
||||||
|
"movq %rsi, 88(%rcx) \n" // store %rsi into nlr_buf
|
||||||
|
"jmp nlr_push_tail \n" // do the rest in C
|
||||||
|
);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"movq (%rsp), %rax \n" // load return %rip
|
||||||
|
"movq %rax, 16(%rdi) \n" // store %rip into nlr_buf
|
||||||
|
"movq %rbp, 24(%rdi) \n" // store %rbp into nlr_buf
|
||||||
|
"movq %rsp, 32(%rdi) \n" // store %rsp into nlr_buf
|
||||||
|
"movq %rbx, 40(%rdi) \n" // store %rbx into nlr_buf
|
||||||
|
"movq %r12, 48(%rdi) \n" // store %r12 into nlr_buf
|
||||||
|
"movq %r13, 56(%rdi) \n" // store %r13 into nlr_buf
|
||||||
|
"movq %r14, 64(%rdi) \n" // store %r14 into nlr_buf
|
||||||
|
"movq %r15, 72(%rdi) \n" // store %r15 into nlr_buf
|
||||||
|
"jmp nlr_push_tail \n" // do the rest in C
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0; // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr->prev = *top;
|
||||||
|
*top = nlr;
|
||||||
|
return 0; // normal return
|
||||||
|
}
|
||||||
|
|
||||||
|
void nlr_pop(void) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
*top = (*top)->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void nlr_jump(void *val) {
|
||||||
|
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr_buf_t *top = *top_ptr;
|
||||||
|
if (top == NULL) {
|
||||||
|
nlr_jump_fail(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
top->ret_val = val;
|
||||||
|
*top_ptr = top->prev;
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"movq %0, %%rcx \n" // %rcx points to nlr_buf
|
||||||
|
#if NLR_OS_WINDOWS
|
||||||
|
"movq 88(%%rcx), %%rsi \n" // load saved %rsi
|
||||||
|
"movq 80(%%rcx), %%rdi \n" // load saved %rdr
|
||||||
|
#endif
|
||||||
|
"movq 72(%%rcx), %%r15 \n" // load saved %r15
|
||||||
|
"movq 64(%%rcx), %%r14 \n" // load saved %r14
|
||||||
|
"movq 56(%%rcx), %%r13 \n" // load saved %r13
|
||||||
|
"movq 48(%%rcx), %%r12 \n" // load saved %r12
|
||||||
|
"movq 40(%%rcx), %%rbx \n" // load saved %rbx
|
||||||
|
"movq 32(%%rcx), %%rsp \n" // load saved %rsp
|
||||||
|
"movq 24(%%rcx), %%rbp \n" // load saved %rbp
|
||||||
|
"movq 16(%%rcx), %%rax \n" // load saved %rip
|
||||||
|
"movq %%rax, (%%rsp) \n" // store saved %rip to stack
|
||||||
|
"xorq %%rax, %%rax \n" // clear return register
|
||||||
|
"inc %%al \n" // increase to make 1, non-local return
|
||||||
|
"ret \n" // return
|
||||||
|
: // output operands
|
||||||
|
: "r"(top) // input operands
|
||||||
|
: // clobbered registers
|
||||||
|
);
|
||||||
|
|
||||||
|
for (;;); // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MICROPY_NLR_SETJMP && defined(__x86_64__)
|
195
py/nlrx86.S
195
py/nlrx86.S
@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Micro Python project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__i386__) && !MICROPY_NLR_SETJMP
|
|
||||||
|
|
||||||
// We only need the functions here if we are on x86, and we are not
|
|
||||||
// using setjmp/longjmp.
|
|
||||||
//
|
|
||||||
// For reference, x86 callee save regs are:
|
|
||||||
// ebx, esi, edi, ebp, esp, eip
|
|
||||||
|
|
||||||
// the offset of nlr_top within mp_state_ctx_t
|
|
||||||
#define NLR_TOP_OFFSET (2 * 4)
|
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
|
||||||
#define NLR_OS_WINDOWS
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__APPLE__) && defined(__MACH__)
|
|
||||||
#define NLR_OS_MAC
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
|
||||||
#define NLR_TOP (_mp_state_ctx + NLR_TOP_OFFSET)
|
|
||||||
#define MP_THREAD_GET_STATE _mp_thread_get_state
|
|
||||||
#else
|
|
||||||
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
|
|
||||||
#define MP_THREAD_GET_STATE mp_thread_get_state
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// offset of nlr_top within mp_state_thread_t structure
|
|
||||||
#define NLR_TOP_TH_OFF (0)
|
|
||||||
|
|
||||||
.file "nlr.s"
|
|
||||||
.text
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// mp_uint_t nlr_push(4(%esp)=nlr_buf_t *nlr)
|
|
||||||
|
|
||||||
#if defined(NLR_OS_WINDOWS)
|
|
||||||
.globl _nlr_push
|
|
||||||
.def _nlr_push; .scl 2; .type 32; .endef
|
|
||||||
_nlr_push:
|
|
||||||
#elif defined(NLR_OS_MAC)
|
|
||||||
.globl _nlr_push
|
|
||||||
_nlr_push:
|
|
||||||
#else
|
|
||||||
.globl nlr_push
|
|
||||||
.type nlr_push, @function
|
|
||||||
nlr_push:
|
|
||||||
#endif
|
|
||||||
mov 4(%esp), %edx # load nlr_buf
|
|
||||||
mov (%esp), %eax # load return %ip
|
|
||||||
mov %eax, 8(%edx) # store %ip into nlr_buf+8
|
|
||||||
mov %ebp, 12(%edx) # store %bp into nlr_buf+12
|
|
||||||
mov %esp, 16(%edx) # store %sp into nlr_buf+16
|
|
||||||
mov %ebx, 20(%edx) # store %bx into nlr_buf+20
|
|
||||||
mov %edi, 24(%edx) # store %di into nlr_buf
|
|
||||||
mov %esi, 28(%edx) # store %si into nlr_buf
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
mov NLR_TOP, %eax # load nlr_top
|
|
||||||
mov %eax, (%edx) # store it
|
|
||||||
mov %edx, NLR_TOP # stor new nlr_buf (to make linked list)
|
|
||||||
#else
|
|
||||||
// to check: stack is aligned to 16-byte boundary before this call
|
|
||||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
|
||||||
mov 4(%esp), %edx # load nlr_buf argument into edx (edx clobbered by call)
|
|
||||||
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
|
|
||||||
mov %ecx, (%edx) # store it
|
|
||||||
mov %edx, NLR_TOP_TH_OFF(%eax) # store new nlr_buf (to make linked list)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xor %eax, %eax # return 0, normal return
|
|
||||||
ret # return
|
|
||||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
|
||||||
.size nlr_push, .-nlr_push
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_pop()
|
|
||||||
|
|
||||||
#if defined(NLR_OS_WINDOWS)
|
|
||||||
.globl _nlr_pop
|
|
||||||
.def _nlr_pop; .scl 2; .type 32; .endef
|
|
||||||
_nlr_pop:
|
|
||||||
#elif defined(NLR_OS_MAC)
|
|
||||||
.globl _nlr_pop
|
|
||||||
_nlr_pop:
|
|
||||||
#else
|
|
||||||
.globl nlr_pop
|
|
||||||
.type nlr_pop, @function
|
|
||||||
nlr_pop:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
mov NLR_TOP, %eax # load nlr_top
|
|
||||||
mov (%eax), %eax # load prev nlr_buf
|
|
||||||
mov %eax, NLR_TOP # store nlr_top (to unlink list)
|
|
||||||
#else
|
|
||||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
|
||||||
mov NLR_TOP_TH_OFF(%eax), %ecx # get thread.nlr_top (last nlr_buf)
|
|
||||||
mov (%ecx), %ecx # load prev nlr_buf
|
|
||||||
mov %ecx, NLR_TOP_TH_OFF(%eax) # store prev nlr_buf (to unlink list)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ret # return
|
|
||||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
|
||||||
.size nlr_pop, .-nlr_pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**************************************/
|
|
||||||
// void nlr_jump(4(%esp)=mp_uint_t val)
|
|
||||||
|
|
||||||
#if defined(NLR_OS_WINDOWS)
|
|
||||||
.globl _nlr_jump
|
|
||||||
.def _nlr_jump; .scl 2; .type 32; .endef
|
|
||||||
_nlr_jump:
|
|
||||||
#elif defined(NLR_OS_MAC)
|
|
||||||
.globl _nlr_jump
|
|
||||||
_nlr_jump:
|
|
||||||
#else
|
|
||||||
.globl nlr_jump
|
|
||||||
.type nlr_jump, @function
|
|
||||||
nlr_jump:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !MICROPY_PY_THREAD
|
|
||||||
mov NLR_TOP, %edx # load nlr_top
|
|
||||||
test %edx, %edx # check for nlr_top being NULL
|
|
||||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
|
||||||
je _nlr_jump_fail # fail if nlr_top is NULL
|
|
||||||
#else
|
|
||||||
je nlr_jump_fail # fail if nlr_top is NULL
|
|
||||||
#endif
|
|
||||||
mov 4(%esp), %eax # load return value
|
|
||||||
mov %eax, 4(%edx) # store return value
|
|
||||||
mov (%edx), %eax # load prev nlr_top
|
|
||||||
mov %eax, NLR_TOP # store nlr_top (to unlink list)
|
|
||||||
#else
|
|
||||||
call MP_THREAD_GET_STATE # get mp_state_thread ptr into eax
|
|
||||||
mov NLR_TOP_TH_OFF(%eax), %edx # get thread.nlr_top (last nlr_buf)
|
|
||||||
test %edx, %edx # check for nlr_top being NULL
|
|
||||||
#if defined(NLR_OS_WINDOWS) || defined(NLR_OS_MAC)
|
|
||||||
je _nlr_jump_fail # fail if nlr_top is NULL
|
|
||||||
#else
|
|
||||||
je nlr_jump_fail # fail if nlr_top is NULL
|
|
||||||
#endif
|
|
||||||
mov 4(%esp), %ecx # load return value
|
|
||||||
mov %ecx, 4(%edx) # store return value
|
|
||||||
mov (%edx), %ecx # load prev nlr_top
|
|
||||||
mov %ecx, NLR_TOP_TH_OFF(%eax) # store nlr_top (to unlink list)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
mov 28(%edx), %esi # load saved %si
|
|
||||||
mov 24(%edx), %edi # load saved %di
|
|
||||||
mov 20(%edx), %ebx # load saved %bx
|
|
||||||
mov 16(%edx), %esp # load saved %sp
|
|
||||||
mov 12(%edx), %ebp # load saved %bp
|
|
||||||
mov 8(%edx), %eax # load saved %ip
|
|
||||||
mov %eax, (%esp) # store saved %ip to stack
|
|
||||||
xor %eax, %eax # clear return register
|
|
||||||
inc %al # increase to make 1, non-local return
|
|
||||||
ret # return
|
|
||||||
#if !defined(NLR_OS_WINDOWS) && !defined(NLR_OS_MAC)
|
|
||||||
.size nlr_jump, .-nlr_jump
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // defined(__i386__) && !MICROPY_NLR_SETJMP
|
|
||||||
#if defined(linux)
|
|
||||||
.section .note.GNU-stack,"",%progbits
|
|
||||||
#endif
|
|
114
py/nlrx86.c
Normal file
114
py/nlrx86.c
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2013-2017 Damien P. George
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mpconfig.h"
|
||||||
|
#include "py/mpstate.h"
|
||||||
|
#include "py/nlr.h"
|
||||||
|
|
||||||
|
#if !MICROPY_NLR_SETJMP && defined(__i386__)
|
||||||
|
|
||||||
|
#undef nlr_push
|
||||||
|
|
||||||
|
// For reference, x86 callee save regs are:
|
||||||
|
// ebx, esi, edi, ebp, esp, eip
|
||||||
|
|
||||||
|
#define NLR_OS_WINDOWS (defined(_WIN32) || defined(__CYGWIN__))
|
||||||
|
|
||||||
|
#if NLR_OS_WINDOWS
|
||||||
|
unsigned int nlr_push_tail(nlr_buf_t *nlr) asm("nlr_push_tail");
|
||||||
|
#else
|
||||||
|
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||||
|
(void)nlr;
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
// Check for Zephyr, which uses a different calling convention
|
||||||
|
// by default.
|
||||||
|
// TODO: Better check for Zephyr.
|
||||||
|
// TODE: Better support for various x86 calling conventions
|
||||||
|
// (unfortunately, __attribute__((naked)) is not supported on x86).
|
||||||
|
#ifndef CONFIG_SOC_IA32
|
||||||
|
"pop %ebp \n" // undo function's prelude
|
||||||
|
#endif
|
||||||
|
"mov 4(%esp), %edx \n" // load nlr_buf
|
||||||
|
"mov (%esp), %eax \n" // load return %eip
|
||||||
|
"mov %eax, 8(%edx) \n" // store %eip into nlr_buf
|
||||||
|
"mov %ebp, 12(%edx) \n" // store %ebp into nlr_buf
|
||||||
|
"mov %esp, 16(%edx) \n" // store %esp into nlr_buf
|
||||||
|
"mov %ebx, 20(%edx) \n" // store %ebx into nlr_buf
|
||||||
|
"mov %edi, 24(%edx) \n" // store %edi into nlr_buf
|
||||||
|
"mov %esi, 28(%edx) \n" // store %esi into nlr_buf
|
||||||
|
"jmp nlr_push_tail \n" // do the rest in C
|
||||||
|
);
|
||||||
|
|
||||||
|
return 0; // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr->prev = *top;
|
||||||
|
*top = nlr;
|
||||||
|
return 0; // normal return
|
||||||
|
}
|
||||||
|
|
||||||
|
void nlr_pop(void) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
*top = (*top)->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void nlr_jump(void *val) {
|
||||||
|
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr_buf_t *top = *top_ptr;
|
||||||
|
if (top == NULL) {
|
||||||
|
nlr_jump_fail(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
top->ret_val = val;
|
||||||
|
*top_ptr = top->prev;
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"mov %0, %%edx \n" // %edx points to nlr_buf
|
||||||
|
"mov 28(%%edx), %%esi \n" // load saved %esi
|
||||||
|
"mov 24(%%edx), %%edi \n" // load saved %edi
|
||||||
|
"mov 20(%%edx), %%ebx \n" // load saved %ebx
|
||||||
|
"mov 16(%%edx), %%esp \n" // load saved %esp
|
||||||
|
"mov 12(%%edx), %%ebp \n" // load saved %ebp
|
||||||
|
"mov 8(%%edx), %%eax \n" // load saved %eip
|
||||||
|
"mov %%eax, (%%esp) \n" // store saved %eip to stack
|
||||||
|
"xor %%eax, %%eax \n" // clear return register
|
||||||
|
"inc %%al \n" // increase to make 1, non-local return
|
||||||
|
"ret \n" // return
|
||||||
|
: // output operands
|
||||||
|
: "r"(top) // input operands
|
||||||
|
: // clobbered registers
|
||||||
|
);
|
||||||
|
|
||||||
|
for (;;); // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MICROPY_NLR_SETJMP && defined(__i386__)
|
119
py/nlrxtensa.S
119
py/nlrxtensa.S
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of the Micro Python project, http://micropython.org/
|
|
||||||
*
|
|
||||||
* The MIT License (MIT)
|
|
||||||
*
|
|
||||||
* Copyright (c) 2014 Damien P. George
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__xtensa__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
calling conventions:
|
|
||||||
a0 = return address
|
|
||||||
a1 = stack pointer
|
|
||||||
a2 = first arg, return value
|
|
||||||
a3-a7 = rest of args
|
|
||||||
*/
|
|
||||||
|
|
||||||
// the offset of nlr_top within mp_state_ctx_t
|
|
||||||
#define NLR_TOP_OFFSET (2 * 4)
|
|
||||||
|
|
||||||
#define NLR_TOP (mp_state_ctx + NLR_TOP_OFFSET)
|
|
||||||
|
|
||||||
.file "nlr.s"
|
|
||||||
.text
|
|
||||||
|
|
||||||
.literal_position
|
|
||||||
.literal .LC0, NLR_TOP
|
|
||||||
.align 4
|
|
||||||
.global nlr_push
|
|
||||||
.type nlr_push, @function
|
|
||||||
nlr_push:
|
|
||||||
// save regs
|
|
||||||
s32i.n a0, a2, 8
|
|
||||||
s32i.n a1, a2, 12
|
|
||||||
s32i.n a8, a2, 16
|
|
||||||
s32i.n a9, a2, 20
|
|
||||||
s32i.n a10, a2, 24
|
|
||||||
s32i.n a11, a2, 28
|
|
||||||
s32i.n a12, a2, 32
|
|
||||||
s32i.n a13, a2, 36
|
|
||||||
s32i.n a14, a2, 40
|
|
||||||
s32i.n a15, a2, 44
|
|
||||||
|
|
||||||
l32r a3, .LC0
|
|
||||||
l32i.n a4, a3, 0
|
|
||||||
s32i.n a2, a3, 0
|
|
||||||
s32i.n a4, a2, 0
|
|
||||||
movi.n a2, 0
|
|
||||||
ret.n
|
|
||||||
.size nlr_push, .-nlr_push
|
|
||||||
|
|
||||||
.literal_position
|
|
||||||
.literal .LC1, NLR_TOP
|
|
||||||
.align 4
|
|
||||||
.global nlr_pop
|
|
||||||
.type nlr_pop, @function
|
|
||||||
nlr_pop:
|
|
||||||
l32r a2, .LC1
|
|
||||||
l32i.n a3, a2, 0
|
|
||||||
l32i.n a3, a3, 0
|
|
||||||
s32i.n a3, a2, 0
|
|
||||||
ret.n
|
|
||||||
.size nlr_pop, .-nlr_pop
|
|
||||||
|
|
||||||
.literal_position
|
|
||||||
.literal .LC2, NLR_TOP
|
|
||||||
.align 4
|
|
||||||
.global nlr_jump
|
|
||||||
.type nlr_jump, @function
|
|
||||||
nlr_jump:
|
|
||||||
l32r a3, .LC2
|
|
||||||
l32i.n a3, a3, 0 // a3 = nlr_top
|
|
||||||
bnez.n a3, .L4
|
|
||||||
call0 nlr_jump_fail
|
|
||||||
.L4:
|
|
||||||
s32i.n a2, a3, 4 // nlr_top->ret_val = val
|
|
||||||
|
|
||||||
// restore regs
|
|
||||||
l32i.n a0, a3, 8
|
|
||||||
l32i.n a1, a3, 12
|
|
||||||
l32i.n a8, a3, 16
|
|
||||||
l32i.n a9, a3, 20
|
|
||||||
l32i.n a10, a3, 24
|
|
||||||
l32i.n a11, a3, 28
|
|
||||||
l32i.n a12, a3, 32
|
|
||||||
l32i.n a13, a3, 36
|
|
||||||
l32i.n a14, a3, 40
|
|
||||||
l32i.n a15, a3, 44
|
|
||||||
|
|
||||||
l32i.n a3, a3, 0 // a3 = nlr_top->prev
|
|
||||||
l32r a2, .LC2
|
|
||||||
s32i.n a3, a2, 0 // nlr_top = a3
|
|
||||||
movi.n a2, 1 // return 1
|
|
||||||
ret.n
|
|
||||||
.size nlr_jump, .-nlr_jump
|
|
||||||
|
|
||||||
#endif // defined(__xtensa__)
|
|
||||||
#if defined(linux)
|
|
||||||
.section .note.GNU-stack,"",%progbits
|
|
||||||
#endif
|
|
103
py/nlrxtensa.c
Normal file
103
py/nlrxtensa.c
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the MicroPython project, http://micropython.org/
|
||||||
|
*
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014-2017 Damien P. George
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "py/mpstate.h"
|
||||||
|
#include "py/nlr.h"
|
||||||
|
|
||||||
|
#if !MICROPY_NLR_SETJMP && defined(__xtensa__)
|
||||||
|
|
||||||
|
#undef nlr_push
|
||||||
|
|
||||||
|
// Xtensa calling conventions:
|
||||||
|
// a0 = return address
|
||||||
|
// a1 = stack pointer
|
||||||
|
// a2 = first arg, return value
|
||||||
|
// a3-a7 = rest of args
|
||||||
|
|
||||||
|
unsigned int nlr_push(nlr_buf_t *nlr) {
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"s32i.n a0, a2, 8 \n" // save regs...
|
||||||
|
"s32i.n a1, a2, 12 \n"
|
||||||
|
"s32i.n a8, a2, 16 \n"
|
||||||
|
"s32i.n a9, a2, 20 \n"
|
||||||
|
"s32i.n a10, a2, 24 \n"
|
||||||
|
"s32i.n a11, a2, 28 \n"
|
||||||
|
"s32i.n a12, a2, 32 \n"
|
||||||
|
"s32i.n a13, a2, 36 \n"
|
||||||
|
"s32i.n a14, a2, 40 \n"
|
||||||
|
"s32i.n a15, a2, 44 \n"
|
||||||
|
"j nlr_push_tail \n" // do the rest in C
|
||||||
|
);
|
||||||
|
|
||||||
|
return 0; // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((used)) unsigned int nlr_push_tail(nlr_buf_t *nlr) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr->prev = *top;
|
||||||
|
*top = nlr;
|
||||||
|
return 0; // normal return
|
||||||
|
}
|
||||||
|
|
||||||
|
void nlr_pop(void) {
|
||||||
|
nlr_buf_t **top = &MP_STATE_THREAD(nlr_top);
|
||||||
|
*top = (*top)->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
NORETURN void nlr_jump(void *val) {
|
||||||
|
nlr_buf_t **top_ptr = &MP_STATE_THREAD(nlr_top);
|
||||||
|
nlr_buf_t *top = *top_ptr;
|
||||||
|
if (top == NULL) {
|
||||||
|
nlr_jump_fail(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
top->ret_val = val;
|
||||||
|
*top_ptr = top->prev;
|
||||||
|
|
||||||
|
__asm volatile (
|
||||||
|
"mov.n a2, %0 \n" // a2 points to nlr_buf
|
||||||
|
"l32i.n a0, a2, 8 \n" // restore regs...
|
||||||
|
"l32i.n a1, a2, 12 \n"
|
||||||
|
"l32i.n a8, a2, 16 \n"
|
||||||
|
"l32i.n a9, a2, 20 \n"
|
||||||
|
"l32i.n a10, a2, 24 \n"
|
||||||
|
"l32i.n a11, a2, 28 \n"
|
||||||
|
"l32i.n a12, a2, 32 \n"
|
||||||
|
"l32i.n a13, a2, 36 \n"
|
||||||
|
"l32i.n a14, a2, 40 \n"
|
||||||
|
"l32i.n a15, a2, 44 \n"
|
||||||
|
"movi.n a2, 1 \n" // return 1, non-local return
|
||||||
|
"ret.n \n" // return
|
||||||
|
: // output operands
|
||||||
|
: "r"(top) // input operands
|
||||||
|
: // clobbered registers
|
||||||
|
);
|
||||||
|
|
||||||
|
for (;;); // needed to silence compiler warning
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !MICROPY_NLR_SETJMP && defined(__xtensa__)
|
@ -418,6 +418,10 @@ STATIC mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
|||||||
uint8_t* dest_items = o->items;
|
uint8_t* dest_items = o->items;
|
||||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||||
if (o->base.type == &mp_type_memoryview) {
|
if (o->base.type == &mp_type_memoryview) {
|
||||||
|
if ((o->typecode & 0x80) == 0) {
|
||||||
|
// store to read-only memoryview not allowed
|
||||||
|
return MP_OBJ_NULL;
|
||||||
|
}
|
||||||
if (len_adj != 0) {
|
if (len_adj != 0) {
|
||||||
goto compat_error;
|
goto compat_error;
|
||||||
}
|
}
|
||||||
|
10
py/objfun.c
10
py/objfun.c
@ -511,17 +511,11 @@ STATIC mp_uint_t convert_obj_for_inline_asm(mp_obj_t obj) {
|
|||||||
// convert float to int (could also pass in float registers)
|
// convert float to int (could also pass in float registers)
|
||||||
return (mp_int_t)mp_obj_float_get(obj);
|
return (mp_int_t)mp_obj_float_get(obj);
|
||||||
#endif
|
#endif
|
||||||
} else if (type == &mp_type_tuple) {
|
} else if (type == &mp_type_tuple || type == &mp_type_list) {
|
||||||
// pointer to start of tuple (could pass length, but then could use len(x) for that)
|
// pointer to start of tuple (could pass length, but then could use len(x) for that)
|
||||||
mp_uint_t len;
|
mp_uint_t len;
|
||||||
mp_obj_t *items;
|
mp_obj_t *items;
|
||||||
mp_obj_tuple_get(obj, &len, &items);
|
mp_obj_get_array(obj, &len, &items);
|
||||||
return (mp_uint_t)items;
|
|
||||||
} else if (type == &mp_type_list) {
|
|
||||||
// pointer to start of list (could pass length, but then could use len(x) for that)
|
|
||||||
mp_uint_t len;
|
|
||||||
mp_obj_t *items;
|
|
||||||
mp_obj_list_get(obj, &len, &items);
|
|
||||||
return (mp_uint_t)items;
|
return (mp_uint_t)items;
|
||||||
} else {
|
} else {
|
||||||
mp_buffer_info_t bufinfo;
|
mp_buffer_info_t bufinfo;
|
||||||
|
10
py/objlist.c
10
py/objlist.c
@ -192,13 +192,13 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||||||
#if MICROPY_PY_BUILTINS_SLICE
|
#if MICROPY_PY_BUILTINS_SLICE
|
||||||
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
if (MP_OBJ_IS_TYPE(index, &mp_type_slice)) {
|
||||||
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
mp_obj_list_t *self = MP_OBJ_TO_PTR(self_in);
|
||||||
mp_check_self(MP_OBJ_IS_TYPE(value, &mp_type_list));
|
mp_uint_t value_len; mp_obj_t *value_items;
|
||||||
mp_obj_list_t *slice = MP_OBJ_TO_PTR(value);
|
mp_obj_get_array(value, &value_len, &value_items);
|
||||||
mp_bound_slice_t slice_out;
|
mp_bound_slice_t slice_out;
|
||||||
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
|
if (!mp_seq_get_fast_slice_indexes(self->len, index, &slice_out)) {
|
||||||
mp_not_implemented("");
|
mp_not_implemented("");
|
||||||
}
|
}
|
||||||
mp_int_t len_adj = slice->len - (slice_out.stop - slice_out.start);
|
mp_int_t len_adj = value_len - (slice_out.stop - slice_out.start);
|
||||||
//printf("Len adj: %d\n", len_adj);
|
//printf("Len adj: %d\n", len_adj);
|
||||||
if (len_adj > 0) {
|
if (len_adj > 0) {
|
||||||
if (self->len + len_adj > self->alloc) {
|
if (self->len + len_adj > self->alloc) {
|
||||||
@ -208,10 +208,10 @@ STATIC mp_obj_t list_subscr(mp_obj_t self_in, mp_obj_t index, mp_obj_t value) {
|
|||||||
self->alloc = self->len + len_adj;
|
self->alloc = self->len + len_adj;
|
||||||
}
|
}
|
||||||
mp_seq_replace_slice_grow_inplace(self->items, self->len,
|
mp_seq_replace_slice_grow_inplace(self->items, self->len,
|
||||||
slice_out.start, slice_out.stop, slice->items, slice->len, len_adj, sizeof(*self->items));
|
slice_out.start, slice_out.stop, value_items, value_len, len_adj, sizeof(*self->items));
|
||||||
} else {
|
} else {
|
||||||
mp_seq_replace_slice_no_grow(self->items, self->len,
|
mp_seq_replace_slice_no_grow(self->items, self->len,
|
||||||
slice_out.start, slice_out.stop, slice->items, slice->len, sizeof(*self->items));
|
slice_out.start, slice_out.stop, value_items, value_len, sizeof(*self->items));
|
||||||
// Clear "freed" elements at the end of list
|
// Clear "freed" elements at the end of list
|
||||||
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
|
mp_seq_clear(self->items, self->len + len_adj, self->len, sizeof(*self->items));
|
||||||
// TODO: apply allocation policy re: alloc_size
|
// TODO: apply allocation policy re: alloc_size
|
||||||
|
15
py/objstr.c
15
py/objstr.c
@ -430,16 +430,13 @@ STATIC mp_obj_t str_join(mp_obj_t self_in, mp_obj_t arg) {
|
|||||||
// process args
|
// process args
|
||||||
mp_uint_t seq_len;
|
mp_uint_t seq_len;
|
||||||
mp_obj_t *seq_items;
|
mp_obj_t *seq_items;
|
||||||
if (MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {
|
|
||||||
mp_obj_tuple_get(arg, &seq_len, &seq_items);
|
if (!MP_OBJ_IS_TYPE(arg, &mp_type_list) && !MP_OBJ_IS_TYPE(arg, &mp_type_tuple)) {
|
||||||
} else {
|
// arg is not a list nor a tuple, try to convert it to a list
|
||||||
if (!MP_OBJ_IS_TYPE(arg, &mp_type_list)) {
|
// TODO: Try to optimize?
|
||||||
// arg is not a list, try to convert it to one
|
arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg);
|
||||||
// TODO: Try to optimize?
|
|
||||||
arg = mp_type_list.make_new(&mp_type_list, 1, 0, &arg);
|
|
||||||
}
|
|
||||||
mp_obj_list_get(arg, &seq_len, &seq_items);
|
|
||||||
}
|
}
|
||||||
|
mp_obj_get_array(arg, &seq_len, &seq_items);
|
||||||
|
|
||||||
// count required length
|
// count required length
|
||||||
size_t required_len = 0;
|
size_t required_len = 0;
|
||||||
|
178
py/parse.c
178
py/parse.c
@ -38,6 +38,7 @@
|
|||||||
#include "py/runtime0.h"
|
#include "py/runtime0.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/objint.h"
|
#include "py/objint.h"
|
||||||
|
#include "py/objstr.h"
|
||||||
#include "py/builtin.h"
|
#include "py/builtin.h"
|
||||||
|
|
||||||
#if MICROPY_ENABLE_COMPILER
|
#if MICROPY_ENABLE_COMPILER
|
||||||
@ -75,8 +76,6 @@ enum {
|
|||||||
#include "py/grammar.h"
|
#include "py/grammar.h"
|
||||||
#undef DEF_RULE
|
#undef DEF_RULE
|
||||||
#undef DEF_RULE_NC
|
#undef DEF_RULE_NC
|
||||||
RULE_string, // special node for non-interned string
|
|
||||||
RULE_bytes, // special node for non-interned bytes
|
|
||||||
RULE_const_object, // special node for a constant, generic Python object
|
RULE_const_object, // special node for a constant, generic Python object
|
||||||
|
|
||||||
// define rules without a compile function
|
// define rules without a compile function
|
||||||
@ -123,8 +122,6 @@ STATIC const rule_t *const rules[] = {
|
|||||||
#include "py/grammar.h"
|
#include "py/grammar.h"
|
||||||
#undef DEF_RULE
|
#undef DEF_RULE
|
||||||
#undef DEF_RULE_NC
|
#undef DEF_RULE_NC
|
||||||
NULL, // RULE_string
|
|
||||||
NULL, // RULE_bytes
|
|
||||||
NULL, // RULE_const_object
|
NULL, // RULE_const_object
|
||||||
|
|
||||||
// define rules without a compile function
|
// define rules without a compile function
|
||||||
@ -150,15 +147,7 @@ typedef struct _mp_parse_chunk_t {
|
|||||||
byte data[];
|
byte data[];
|
||||||
} mp_parse_chunk_t;
|
} mp_parse_chunk_t;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
PARSE_ERROR_NONE = 0,
|
|
||||||
PARSE_ERROR_MEMORY,
|
|
||||||
PARSE_ERROR_CONST,
|
|
||||||
} parse_error_t;
|
|
||||||
|
|
||||||
typedef struct _parser_t {
|
typedef struct _parser_t {
|
||||||
parse_error_t parse_error;
|
|
||||||
|
|
||||||
size_t rule_stack_alloc;
|
size_t rule_stack_alloc;
|
||||||
size_t rule_stack_top;
|
size_t rule_stack_top;
|
||||||
rule_stack_t *rule_stack;
|
rule_stack_t *rule_stack;
|
||||||
@ -219,15 +208,8 @@ STATIC void *parser_alloc(parser_t *parser, size_t num_bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
|
STATIC void push_rule(parser_t *parser, size_t src_line, const rule_t *rule, size_t arg_i) {
|
||||||
if (parser->parse_error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
|
if (parser->rule_stack_top >= parser->rule_stack_alloc) {
|
||||||
rule_stack_t *rs = m_renew_maybe(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC, true);
|
rule_stack_t *rs = m_renew(rule_stack_t, parser->rule_stack, parser->rule_stack_alloc, parser->rule_stack_alloc + MICROPY_ALLOC_PARSE_RULE_INC);
|
||||||
if (rs == NULL) {
|
|
||||||
parser->parse_error = PARSE_ERROR_MEMORY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parser->rule_stack = rs;
|
parser->rule_stack = rs;
|
||||||
parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;
|
parser->rule_stack_alloc += MICROPY_ALLOC_PARSE_RULE_INC;
|
||||||
}
|
}
|
||||||
@ -244,7 +226,6 @@ STATIC void push_rule_from_arg(parser_t *parser, size_t arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
|
STATIC void pop_rule(parser_t *parser, const rule_t **rule, size_t *arg_i, size_t *src_line) {
|
||||||
assert(!parser->parse_error);
|
|
||||||
parser->rule_stack_top -= 1;
|
parser->rule_stack_top -= 1;
|
||||||
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
|
*rule = rules[parser->rule_stack[parser->rule_stack_top].rule_id];
|
||||||
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
|
*arg_i = parser->rule_stack[parser->rule_stack_top].arg_i;
|
||||||
@ -326,11 +307,7 @@ void mp_parse_node_print(mp_parse_node_t pn, size_t indent) {
|
|||||||
} else {
|
} else {
|
||||||
// node must be a mp_parse_node_struct_t
|
// node must be a mp_parse_node_struct_t
|
||||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t*)pn;
|
||||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
|
if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
|
||||||
printf("literal str(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
|
||||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_bytes) {
|
|
||||||
printf("literal bytes(%.*s)\n", (int)pns->nodes[1], (char*)pns->nodes[0]);
|
|
||||||
} else if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_const_object) {
|
|
||||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
|
printf("literal const(%016llx)\n", (uint64_t)pns->nodes[0] | ((uint64_t)pns->nodes[1] << 32));
|
||||||
#else
|
#else
|
||||||
@ -361,58 +338,26 @@ STATIC void result_stack_show(parser_t *parser) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
STATIC mp_parse_node_t pop_result(parser_t *parser) {
|
STATIC mp_parse_node_t pop_result(parser_t *parser) {
|
||||||
if (parser->parse_error) {
|
|
||||||
return MP_PARSE_NODE_NULL;
|
|
||||||
}
|
|
||||||
assert(parser->result_stack_top > 0);
|
assert(parser->result_stack_top > 0);
|
||||||
return parser->result_stack[--parser->result_stack_top];
|
return parser->result_stack[--parser->result_stack_top];
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {
|
STATIC mp_parse_node_t peek_result(parser_t *parser, size_t pos) {
|
||||||
if (parser->parse_error) {
|
|
||||||
return MP_PARSE_NODE_NULL;
|
|
||||||
}
|
|
||||||
assert(parser->result_stack_top > pos);
|
assert(parser->result_stack_top > pos);
|
||||||
return parser->result_stack[parser->result_stack_top - 1 - pos];
|
return parser->result_stack[parser->result_stack_top - 1 - pos];
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
|
STATIC void push_result_node(parser_t *parser, mp_parse_node_t pn) {
|
||||||
if (parser->parse_error) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (parser->result_stack_top >= parser->result_stack_alloc) {
|
if (parser->result_stack_top >= parser->result_stack_alloc) {
|
||||||
mp_parse_node_t *stack = m_renew_maybe(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC, true);
|
mp_parse_node_t *stack = m_renew(mp_parse_node_t, parser->result_stack, parser->result_stack_alloc, parser->result_stack_alloc + MICROPY_ALLOC_PARSE_RESULT_INC);
|
||||||
if (stack == NULL) {
|
|
||||||
parser->parse_error = PARSE_ERROR_MEMORY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
parser->result_stack = stack;
|
parser->result_stack = stack;
|
||||||
parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;
|
parser->result_stack_alloc += MICROPY_ALLOC_PARSE_RESULT_INC;
|
||||||
}
|
}
|
||||||
parser->result_stack[parser->result_stack_top++] = pn;
|
parser->result_stack[parser->result_stack_top++] = pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
STATIC mp_parse_node_t make_node_string_bytes(parser_t *parser, size_t src_line, size_t rule_kind, const char *str, size_t len) {
|
|
||||||
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * 2);
|
|
||||||
if (pn == NULL) {
|
|
||||||
parser->parse_error = PARSE_ERROR_MEMORY;
|
|
||||||
return MP_PARSE_NODE_NULL;
|
|
||||||
}
|
|
||||||
pn->source_line = src_line;
|
|
||||||
pn->kind_num_nodes = rule_kind | (2 << 8);
|
|
||||||
char *p = m_new(char, len);
|
|
||||||
memcpy(p, str, len);
|
|
||||||
pn->nodes[0] = (uintptr_t)p;
|
|
||||||
pn->nodes[1] = len;
|
|
||||||
return (mp_parse_node_t)pn;
|
|
||||||
}
|
|
||||||
|
|
||||||
STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {
|
STATIC mp_parse_node_t make_node_const_object(parser_t *parser, size_t src_line, mp_obj_t obj) {
|
||||||
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
|
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_obj_t));
|
||||||
if (pn == NULL) {
|
|
||||||
parser->parse_error = PARSE_ERROR_MEMORY;
|
|
||||||
return MP_PARSE_NODE_NULL;
|
|
||||||
}
|
|
||||||
pn->source_line = src_line;
|
pn->source_line = src_line;
|
||||||
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
#if MICROPY_OBJ_REPR == MICROPY_OBJ_REPR_D
|
||||||
// nodes are 32-bit pointers, but need to store 64-bit object
|
// nodes are 32-bit pointers, but need to store 64-bit object
|
||||||
@ -436,7 +381,11 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
|
|||||||
mp_map_elem_t *elem;
|
mp_map_elem_t *elem;
|
||||||
if (rule->rule_id == RULE_atom
|
if (rule->rule_id == RULE_atom
|
||||||
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
|
&& (elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP)) != NULL) {
|
||||||
pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
|
if (MP_OBJ_IS_SMALL_INT(elem->value)) {
|
||||||
|
pn = mp_parse_node_new_small_int(MP_OBJ_SMALL_INT_VALUE(elem->value));
|
||||||
|
} else {
|
||||||
|
pn = make_node_const_object(parser, lex->tok_line, elem->value);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
|
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_ID, id);
|
||||||
}
|
}
|
||||||
@ -469,8 +418,11 @@ STATIC void push_result_token(parser_t *parser, const rule_t *rule) {
|
|||||||
// qstr exists, make a leaf node
|
// qstr exists, make a leaf node
|
||||||
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
|
pn = mp_parse_node_new_leaf(lex->tok_kind == MP_TOKEN_STRING ? MP_PARSE_NODE_STRING : MP_PARSE_NODE_BYTES, qst);
|
||||||
} else {
|
} else {
|
||||||
// not interned, make a node holding a pointer to the string/bytes data
|
// not interned, make a node holding a pointer to the string/bytes object
|
||||||
pn = make_node_string_bytes(parser, lex->tok_line, lex->tok_kind == MP_TOKEN_STRING ? RULE_string : RULE_bytes, lex->vstr.buf, lex->vstr.len);
|
mp_obj_t o = mp_obj_new_str_of_type(
|
||||||
|
lex->tok_kind == MP_TOKEN_STRING ? &mp_type_str : &mp_type_bytes,
|
||||||
|
(const byte*)lex->vstr.buf, lex->vstr.len);
|
||||||
|
pn = make_node_const_object(parser, lex->tok_line, o);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
|
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_TOKEN, lex->tok_kind);
|
||||||
@ -666,16 +618,19 @@ STATIC bool fold_constants(parser_t *parser, const rule_t *rule, size_t num_args
|
|||||||
|
|
||||||
// get the value
|
// get the value
|
||||||
mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];
|
mp_parse_node_t pn_value = ((mp_parse_node_struct_t*)((mp_parse_node_struct_t*)pn1)->nodes[1])->nodes[0];
|
||||||
if (!MP_PARSE_NODE_IS_SMALL_INT(pn_value)) {
|
mp_obj_t value;
|
||||||
parser->parse_error = PARSE_ERROR_CONST;
|
if (!mp_parse_node_get_int_maybe(pn_value, &value)) {
|
||||||
return false;
|
mp_obj_t exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
|
||||||
|
"constant must be an integer");
|
||||||
|
mp_obj_exception_add_traceback(exc, parser->lexer->source_name,
|
||||||
|
((mp_parse_node_struct_t*)pn1)->source_line, MP_QSTR_NULL);
|
||||||
|
nlr_raise(exc);
|
||||||
}
|
}
|
||||||
mp_int_t value = MP_PARSE_NODE_LEAF_SMALL_INT(pn_value);
|
|
||||||
|
|
||||||
// store the value in the table of dynamic constants
|
// store the value in the table of dynamic constants
|
||||||
mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
mp_map_elem_t *elem = mp_map_lookup(&parser->consts, MP_OBJ_NEW_QSTR(id), MP_MAP_LOOKUP_ADD_IF_NOT_FOUND);
|
||||||
assert(elem->value == MP_OBJ_NULL);
|
assert(elem->value == MP_OBJ_NULL);
|
||||||
elem->value = MP_OBJ_NEW_SMALL_INT(value);
|
elem->value = value;
|
||||||
|
|
||||||
// If the constant starts with an underscore then treat it as a private
|
// If the constant starts with an underscore then treat it as a private
|
||||||
// variable and don't emit any code to store the value to the id.
|
// variable and don't emit any code to store the value to the id.
|
||||||
@ -770,10 +725,6 @@ STATIC void push_result_rule(parser_t *parser, size_t src_line, const rule_t *ru
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
|
mp_parse_node_struct_t *pn = parser_alloc(parser, sizeof(mp_parse_node_struct_t) + sizeof(mp_parse_node_t) * num_args);
|
||||||
if (pn == NULL) {
|
|
||||||
parser->parse_error = PARSE_ERROR_MEMORY;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
pn->source_line = src_line;
|
pn->source_line = src_line;
|
||||||
pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
|
pn->kind_num_nodes = (rule->rule_id & 0xff) | (num_args << 8);
|
||||||
for (size_t i = num_args; i > 0; i--) {
|
for (size_t i = num_args; i > 0; i--) {
|
||||||
@ -788,15 +739,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
|
|
||||||
parser_t parser;
|
parser_t parser;
|
||||||
|
|
||||||
parser.parse_error = PARSE_ERROR_NONE;
|
|
||||||
|
|
||||||
parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;
|
parser.rule_stack_alloc = MICROPY_ALLOC_PARSE_RULE_INIT;
|
||||||
parser.rule_stack_top = 0;
|
parser.rule_stack_top = 0;
|
||||||
parser.rule_stack = m_new_maybe(rule_stack_t, parser.rule_stack_alloc);
|
parser.rule_stack = m_new(rule_stack_t, parser.rule_stack_alloc);
|
||||||
|
|
||||||
parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;
|
parser.result_stack_alloc = MICROPY_ALLOC_PARSE_RESULT_INIT;
|
||||||
parser.result_stack_top = 0;
|
parser.result_stack_top = 0;
|
||||||
parser.result_stack = m_new_maybe(mp_parse_node_t, parser.result_stack_alloc);
|
parser.result_stack = m_new(mp_parse_node_t, parser.result_stack_alloc);
|
||||||
|
|
||||||
parser.lexer = lex;
|
parser.lexer = lex;
|
||||||
|
|
||||||
@ -807,11 +756,6 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
mp_map_init(&parser.consts, 0);
|
mp_map_init(&parser.consts, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check if we could allocate the stacks
|
|
||||||
if (parser.rule_stack == NULL || parser.result_stack == NULL) {
|
|
||||||
goto memory_error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// work out the top-level rule to use, and push it on the stack
|
// work out the top-level rule to use, and push it on the stack
|
||||||
size_t top_level_rule;
|
size_t top_level_rule;
|
||||||
switch (input_kind) {
|
switch (input_kind) {
|
||||||
@ -830,7 +774,7 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
next_rule:
|
next_rule:
|
||||||
if (parser.rule_stack_top == 0 || parser.parse_error) {
|
if (parser.rule_stack_top == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,15 +874,13 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
// this code discards lonely statements, such as doc strings
|
// this code discards lonely statements, such as doc strings
|
||||||
if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
|
if (input_kind != MP_PARSE_SINGLE_INPUT && rule->rule_id == RULE_expr_stmt && peek_result(&parser, 0) == MP_PARSE_NODE_NULL) {
|
||||||
mp_parse_node_t p = peek_result(&parser, 1);
|
mp_parse_node_t p = peek_result(&parser, 1);
|
||||||
if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p)) || MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_string)) {
|
if ((MP_PARSE_NODE_IS_LEAF(p) && !MP_PARSE_NODE_IS_ID(p))
|
||||||
|
|| MP_PARSE_NODE_IS_STRUCT_KIND(p, RULE_const_object)) {
|
||||||
pop_result(&parser); // MP_PARSE_NODE_NULL
|
pop_result(&parser); // MP_PARSE_NODE_NULL
|
||||||
mp_parse_node_t pn = pop_result(&parser); // possibly RULE_string
|
pop_result(&parser); // const expression (leaf or RULE_const_object)
|
||||||
if (MP_PARSE_NODE_IS_STRUCT(pn)) {
|
// Pushing the "pass" rule here will overwrite any RULE_const_object
|
||||||
mp_parse_node_struct_t *pns = (mp_parse_node_struct_t *)pn;
|
// entry that was on the result stack, allowing the GC to reclaim
|
||||||
if (MP_PARSE_NODE_STRUCT_KIND(pns) == RULE_string) {
|
// the memory from the const object when needed.
|
||||||
m_del(char, (char*)pns->nodes[0], (size_t)pns->nodes[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
|
push_result_rule(&parser, rule_src_line, rules[RULE_pass_stmt], 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1094,27 +1036,12 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
parser.tree.chunk = parser.cur_chunk;
|
parser.tree.chunk = parser.cur_chunk;
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_obj_t exc;
|
if (
|
||||||
|
|
||||||
if (parser.parse_error) {
|
|
||||||
#if MICROPY_COMP_CONST
|
|
||||||
if (parser.parse_error == PARSE_ERROR_CONST) {
|
|
||||||
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
|
|
||||||
"constant must be an integer");
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
assert(parser.parse_error == PARSE_ERROR_MEMORY);
|
|
||||||
memory_error:
|
|
||||||
exc = mp_obj_new_exception_msg(&mp_type_MemoryError,
|
|
||||||
"parser could not allocate enough memory");
|
|
||||||
}
|
|
||||||
parser.tree.root = MP_PARSE_NODE_NULL;
|
|
||||||
} else if (
|
|
||||||
lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream
|
lex->tok_kind != MP_TOKEN_END // check we are at the end of the token stream
|
||||||
|| parser.result_stack_top == 0 // check that we got a node (can fail on empty input)
|
|| parser.result_stack_top == 0 // check that we got a node (can fail on empty input)
|
||||||
) {
|
) {
|
||||||
syntax_error:
|
syntax_error:;
|
||||||
|
mp_obj_t exc;
|
||||||
if (lex->tok_kind == MP_TOKEN_INDENT) {
|
if (lex->tok_kind == MP_TOKEN_INDENT) {
|
||||||
exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
|
exc = mp_obj_new_exception_msg(&mp_type_IndentationError,
|
||||||
"unexpected indent");
|
"unexpected indent");
|
||||||
@ -1125,37 +1052,24 @@ mp_parse_tree_t mp_parse(mp_lexer_t *lex, mp_parse_input_kind_t input_kind) {
|
|||||||
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
|
exc = mp_obj_new_exception_msg(&mp_type_SyntaxError,
|
||||||
"invalid syntax");
|
"invalid syntax");
|
||||||
}
|
}
|
||||||
parser.tree.root = MP_PARSE_NODE_NULL;
|
// add traceback to give info about file name and location
|
||||||
} else {
|
// we don't have a 'block' name, so just pass the NULL qstr to indicate this
|
||||||
// no errors
|
mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
|
||||||
|
nlr_raise(exc);
|
||||||
//result_stack_show(parser);
|
|
||||||
//printf("rule stack alloc: %d\n", parser.rule_stack_alloc);
|
|
||||||
//printf("result stack alloc: %d\n", parser.result_stack_alloc);
|
|
||||||
//printf("number of parse nodes allocated: %d\n", num_parse_nodes_allocated);
|
|
||||||
|
|
||||||
// get the root parse node that we created
|
|
||||||
assert(parser.result_stack_top == 1);
|
|
||||||
exc = MP_OBJ_NULL;
|
|
||||||
parser.tree.root = parser.result_stack[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get the root parse node that we created
|
||||||
|
assert(parser.result_stack_top == 1);
|
||||||
|
parser.tree.root = parser.result_stack[0];
|
||||||
|
|
||||||
// free the memory that we don't need anymore
|
// free the memory that we don't need anymore
|
||||||
m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);
|
m_del(rule_stack_t, parser.rule_stack, parser.rule_stack_alloc);
|
||||||
m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);
|
m_del(mp_parse_node_t, parser.result_stack, parser.result_stack_alloc);
|
||||||
// we also free the lexer on behalf of the caller (see below)
|
|
||||||
|
|
||||||
if (exc != MP_OBJ_NULL) {
|
// we also free the lexer on behalf of the caller
|
||||||
// had an error so raise the exception
|
mp_lexer_free(lex);
|
||||||
// add traceback to give info about file name and location
|
|
||||||
// we don't have a 'block' name, so just pass the NULL qstr to indicate this
|
return parser.tree;
|
||||||
mp_obj_exception_add_traceback(exc, lex->source_name, lex->tok_line, MP_QSTR_NULL);
|
|
||||||
mp_lexer_free(lex);
|
|
||||||
nlr_raise(exc);
|
|
||||||
} else {
|
|
||||||
mp_lexer_free(lex);
|
|
||||||
return parser.tree;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mp_parse_tree_clear(mp_parse_tree_t *tree) {
|
void mp_parse_tree_clear(mp_parse_tree_t *tree) {
|
||||||
|
4
py/py.mk
4
py/py.mk
@ -282,6 +282,10 @@ $(HEADER_BUILD)/qstrdefs.generated.h: $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_C
|
|||||||
$(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
|
$(Q)cat $(PY_QSTR_DEFS) $(QSTR_DEFS) $(QSTR_DEFS_COLLECTED) | $(SED) 's/^Q(.*)/"&"/' | $(CPP) $(CFLAGS) - | $(SED) 's/^"\(Q(.*)\)"/\1/' > $(HEADER_BUILD)/qstrdefs.preprocessed.h
|
||||||
$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@
|
$(Q)$(PYTHON) $(PY_SRC)/makeqstrdata.py $(HEADER_BUILD)/qstrdefs.preprocessed.h > $@
|
||||||
|
|
||||||
|
# Force nlr code to always be compiled with space-saving optimisation so
|
||||||
|
# that the function preludes are of a minimal and predictable form.
|
||||||
|
$(PY_BUILD)/nlr%.o: CFLAGS += -Os
|
||||||
|
|
||||||
# emitters
|
# emitters
|
||||||
|
|
||||||
$(PY_BUILD)/emitnx64.o: CFLAGS += -DN_X64
|
$(PY_BUILD)/emitnx64.o: CFLAGS += -DN_X64
|
||||||
|
23
py/runtime.c
23
py/runtime.c
@ -797,11 +797,7 @@ void mp_unpack_sequence(mp_obj_t seq_in, size_t num, mp_obj_t *items) {
|
|||||||
mp_uint_t seq_len;
|
mp_uint_t seq_len;
|
||||||
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
|
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
|
||||||
mp_obj_t *seq_items;
|
mp_obj_t *seq_items;
|
||||||
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
|
mp_obj_get_array(seq_in, &seq_len, &seq_items);
|
||||||
mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
|
|
||||||
} else {
|
|
||||||
mp_obj_list_get(seq_in, &seq_len, &seq_items);
|
|
||||||
}
|
|
||||||
if (seq_len < num) {
|
if (seq_len < num) {
|
||||||
goto too_short;
|
goto too_short;
|
||||||
} else if (seq_len > num) {
|
} else if (seq_len > num) {
|
||||||
@ -851,16 +847,7 @@ void mp_unpack_ex(mp_obj_t seq_in, size_t num_in, mp_obj_t *items) {
|
|||||||
mp_uint_t seq_len;
|
mp_uint_t seq_len;
|
||||||
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
|
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple) || MP_OBJ_IS_TYPE(seq_in, &mp_type_list)) {
|
||||||
mp_obj_t *seq_items;
|
mp_obj_t *seq_items;
|
||||||
if (MP_OBJ_IS_TYPE(seq_in, &mp_type_tuple)) {
|
mp_obj_get_array(seq_in, &seq_len, &seq_items);
|
||||||
mp_obj_tuple_get(seq_in, &seq_len, &seq_items);
|
|
||||||
} else {
|
|
||||||
if (num_left == 0 && num_right == 0) {
|
|
||||||
// *a, = b # sets a to b if b is a list
|
|
||||||
items[0] = seq_in;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mp_obj_list_get(seq_in, &seq_len, &seq_items);
|
|
||||||
}
|
|
||||||
if (seq_len < num_left + num_right) {
|
if (seq_len < num_left + num_right) {
|
||||||
goto too_short;
|
goto too_short;
|
||||||
}
|
}
|
||||||
@ -1431,7 +1418,11 @@ void *m_malloc_fail(size_t num_bytes) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) {
|
NORETURN void mp_raise_msg(const mp_obj_type_t *exc_type, const char *msg) {
|
||||||
nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
|
if (msg == NULL) {
|
||||||
|
nlr_raise(mp_obj_new_exception(exc_type));
|
||||||
|
} else {
|
||||||
|
nlr_raise(mp_obj_new_exception_msg(exc_type, msg));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NORETURN void mp_raise_ValueError(const char *msg) {
|
NORETURN void mp_raise_ValueError(const char *msg) {
|
||||||
|
@ -36,9 +36,11 @@ LDFLAGS= --specs=nano.specs --specs=rdimon.specs -Wl,--gc-sections -Wl,-Map=$(@:
|
|||||||
|
|
||||||
SRC_C = \
|
SRC_C = \
|
||||||
main.c \
|
main.c \
|
||||||
|
modmachine.c \
|
||||||
|
|
||||||
SRC_TEST_C = \
|
SRC_TEST_C = \
|
||||||
test_main.c \
|
test_main.c \
|
||||||
|
modmachine.c \
|
||||||
|
|
||||||
LIB_SRC_C = $(addprefix lib/,\
|
LIB_SRC_C = $(addprefix lib/,\
|
||||||
libm/math.c \
|
libm/math.c \
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@ -59,4 +60,6 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
|
|||||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||||
|
|
||||||
void nlr_jump_fail(void *val) {
|
void nlr_jump_fail(void *val) {
|
||||||
|
printf("uncaught NLR\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
* The MIT License (MIT)
|
||||||
*
|
*
|
||||||
* Copyright (c) 2013, 2014 Damien P. George
|
* Copyright (c) 2017 Damien P. George
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
@ -24,13 +24,24 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// This file is needed because in some cases we can't include stdio.h,
|
#include "extmod/machine_mem.h"
|
||||||
// because the CC3100 socket driver has name clashes with it.
|
#include "extmod/machine_pinbase.h"
|
||||||
|
#include "extmod/machine_signal.h"
|
||||||
|
|
||||||
typedef unsigned int size_t;
|
STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_umachine) },
|
||||||
|
|
||||||
int printf(const char *fmt, ...);
|
{ MP_ROM_QSTR(MP_QSTR_mem8), MP_ROM_PTR(&machine_mem8_obj) },
|
||||||
int snprintf(char *str, size_t size, const char *fmt, ...);
|
{ MP_ROM_QSTR(MP_QSTR_mem16), MP_ROM_PTR(&machine_mem16_obj) },
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_mem32), MP_ROM_PTR(&machine_mem32_obj) },
|
||||||
|
|
||||||
// Convenience function, defined in main.c.
|
{ MP_ROM_QSTR(MP_QSTR_PinBase), MP_ROM_PTR(&machine_pinbase_type) },
|
||||||
void stoupper (char *str);
|
{ MP_ROM_QSTR(MP_QSTR_Signal), MP_ROM_PTR(&machine_signal_type) },
|
||||||
|
};
|
||||||
|
|
||||||
|
STATIC MP_DEFINE_CONST_DICT(machine_module_globals, machine_module_globals_table);
|
||||||
|
|
||||||
|
const mp_obj_module_t mp_module_machine = {
|
||||||
|
.base = { &mp_type_module },
|
||||||
|
.globals = (mp_obj_dict_t*)&machine_module_globals,
|
||||||
|
};
|
@ -33,6 +33,7 @@
|
|||||||
#define MICROPY_PY_URE (1)
|
#define MICROPY_PY_URE (1)
|
||||||
#define MICROPY_PY_UHEAPQ (1)
|
#define MICROPY_PY_UHEAPQ (1)
|
||||||
#define MICROPY_PY_UHASHLIB (1)
|
#define MICROPY_PY_UHASHLIB (1)
|
||||||
|
#define MICROPY_PY_MACHINE (1)
|
||||||
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
#define MICROPY_USE_INTERNAL_PRINTF (0)
|
||||||
|
|
||||||
// type definitions for the specific machine
|
// type definitions for the specific machine
|
||||||
@ -57,5 +58,8 @@ typedef long mp_off_t;
|
|||||||
#define MICROPY_PORT_BUILTINS \
|
#define MICROPY_PORT_BUILTINS \
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_open), (mp_obj_t)&mp_builtin_open_obj },
|
||||||
|
|
||||||
|
#define MICROPY_PORT_BUILTIN_MODULES \
|
||||||
|
{ MP_ROM_QSTR(MP_QSTR_umachine), MP_ROM_PTR(&mp_module_machine) }, \
|
||||||
|
|
||||||
// We need to provide a declaration/definition of alloca()
|
// We need to provide a declaration/definition of alloca()
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
@ -92,4 +93,6 @@ mp_obj_t mp_builtin_open(size_t n_args, const mp_obj_t *args, mp_map_t *kwargs)
|
|||||||
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_open_obj, 1, mp_builtin_open);
|
||||||
|
|
||||||
void nlr_jump_fail(void *val) {
|
void nlr_jump_fail(void *val) {
|
||||||
|
printf("uncaught NLR\n");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -76,9 +76,9 @@ STATIC void accel_start(void) {
|
|||||||
|
|
||||||
// turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again
|
// turn off AVDD, wait 30ms, turn on AVDD, wait 30ms again
|
||||||
mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off
|
mp_hal_pin_low(&MICROPY_HW_MMA_AVDD_PIN); // turn off
|
||||||
HAL_Delay(30);
|
mp_hal_delay_ms(30);
|
||||||
mp_hal_pin_high(&MICROPY_HW_MMA_AVDD_PIN); // turn on
|
mp_hal_pin_high(&MICROPY_HW_MMA_AVDD_PIN); // turn on
|
||||||
HAL_Delay(30);
|
mp_hal_delay_ms(30);
|
||||||
|
|
||||||
HAL_StatusTypeDef status;
|
HAL_StatusTypeDef status;
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ STATIC void accel_start(void) {
|
|||||||
status = HAL_I2C_Mem_Write(&I2CHandle1, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
|
status = HAL_I2C_Mem_Write(&I2CHandle1, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200);
|
||||||
|
|
||||||
// wait for MMA to become active
|
// wait for MMA to become active
|
||||||
HAL_Delay(30);
|
mp_hal_delay_ms(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -39,7 +39,7 @@ mp_uint_t gc_helper_get_regs_and_sp(mp_uint_t *regs);
|
|||||||
void gc_collect(void) {
|
void gc_collect(void) {
|
||||||
// get current time, in case we want to time the GC
|
// get current time, in case we want to time the GC
|
||||||
#if 0
|
#if 0
|
||||||
uint32_t start = sys_tick_get_microseconds();
|
uint32_t start = mp_hal_ticks_us();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// start the GC
|
// start the GC
|
||||||
@ -66,7 +66,7 @@ void gc_collect(void) {
|
|||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// print GC info
|
// print GC info
|
||||||
uint32_t ticks = sys_tick_get_microseconds() - start;
|
uint32_t ticks = mp_hal_ticks_us() - start;
|
||||||
gc_info_t info;
|
gc_info_t info;
|
||||||
gc_info(&info);
|
gc_info(&info);
|
||||||
printf("GC@%lu %lums\n", start, ticks);
|
printf("GC@%lu %lums\n", start, ticks);
|
||||||
|
@ -346,7 +346,7 @@ STATIC void i2c_reset_after_error(I2C_HandleTypeDef *i2c) {
|
|||||||
// stop bit was generated and bus is back to normal
|
// stop bit was generated and bus is back to normal
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HAL_Delay(1);
|
mp_hal_delay_ms(1);
|
||||||
}
|
}
|
||||||
// bus was/is busy, need to reset the peripheral to get it to work again
|
// bus was/is busy, need to reset the peripheral to get it to work again
|
||||||
i2c_deinit(i2c);
|
i2c_deinit(i2c);
|
||||||
|
@ -274,11 +274,11 @@ STATIC mp_obj_t pyb_lcd_make_new(const mp_obj_type_t *type, size_t n_args, size_
|
|||||||
mp_hal_pin_output(lcd->pin_bl);
|
mp_hal_pin_output(lcd->pin_bl);
|
||||||
|
|
||||||
// init the LCD
|
// init the LCD
|
||||||
HAL_Delay(1); // wait a bit
|
mp_hal_delay_ms(1); // wait a bit
|
||||||
mp_hal_pin_low(lcd->pin_rst); // RST=0; reset
|
mp_hal_pin_low(lcd->pin_rst); // RST=0; reset
|
||||||
HAL_Delay(1); // wait for reset; 2us min
|
mp_hal_delay_ms(1); // wait for reset; 2us min
|
||||||
mp_hal_pin_high(lcd->pin_rst); // RST=1; enable
|
mp_hal_pin_high(lcd->pin_rst); // RST=1; enable
|
||||||
HAL_Delay(1); // wait for reset; 2us min
|
mp_hal_delay_ms(1); // wait for reset; 2us min
|
||||||
lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal
|
lcd_out(lcd, LCD_INSTR, 0xa0); // ADC select, normal
|
||||||
lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display)
|
lcd_out(lcd, LCD_INSTR, 0xc0); // common output mode select, normal (this flips the display)
|
||||||
lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias
|
lcd_out(lcd, LCD_INSTR, 0xa2); // LCD bias set, 1/9 bias
|
||||||
|
@ -275,7 +275,7 @@ void led_debug(int n, int delay) {
|
|||||||
led_state(2, n & 2);
|
led_state(2, n & 2);
|
||||||
led_state(3, n & 4);
|
led_state(3, n & 4);
|
||||||
led_state(4, n & 8);
|
led_state(4, n & 8);
|
||||||
HAL_Delay(delay);
|
mp_hal_delay_ms(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
@ -71,10 +71,10 @@ void flash_error(int n) {
|
|||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
led_state(PYB_LED_RED, 1);
|
led_state(PYB_LED_RED, 1);
|
||||||
led_state(PYB_LED_GREEN, 0);
|
led_state(PYB_LED_GREEN, 0);
|
||||||
HAL_Delay(250);
|
mp_hal_delay_ms(250);
|
||||||
led_state(PYB_LED_RED, 0);
|
led_state(PYB_LED_RED, 0);
|
||||||
led_state(PYB_LED_GREEN, 1);
|
led_state(PYB_LED_GREEN, 1);
|
||||||
HAL_Delay(250);
|
mp_hal_delay_ms(250);
|
||||||
}
|
}
|
||||||
led_state(PYB_LED_GREEN, 0);
|
led_state(PYB_LED_GREEN, 0);
|
||||||
}
|
}
|
||||||
@ -349,7 +349,7 @@ STATIC uint update_reset_mode(uint reset_mode) {
|
|||||||
if (!switch_get()) {
|
if (!switch_get()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
HAL_Delay(20);
|
mp_hal_delay_ms(20);
|
||||||
if (i % 30 == 29) {
|
if (i % 30 == 29) {
|
||||||
if (++reset_mode > 3) {
|
if (++reset_mode > 3) {
|
||||||
reset_mode = 1;
|
reset_mode = 1;
|
||||||
@ -364,13 +364,13 @@ STATIC uint update_reset_mode(uint reset_mode) {
|
|||||||
led_state(2, 0);
|
led_state(2, 0);
|
||||||
led_state(3, 0);
|
led_state(3, 0);
|
||||||
led_state(4, 0);
|
led_state(4, 0);
|
||||||
HAL_Delay(50);
|
mp_hal_delay_ms(50);
|
||||||
led_state(2, reset_mode & 1);
|
led_state(2, reset_mode & 1);
|
||||||
led_state(3, reset_mode & 2);
|
led_state(3, reset_mode & 2);
|
||||||
led_state(4, reset_mode & 4);
|
led_state(4, reset_mode & 4);
|
||||||
HAL_Delay(50);
|
mp_hal_delay_ms(50);
|
||||||
}
|
}
|
||||||
HAL_Delay(400);
|
mp_hal_delay_ms(400);
|
||||||
|
|
||||||
#elif defined(MICROPY_HW_LED1)
|
#elif defined(MICROPY_HW_LED1)
|
||||||
|
|
||||||
@ -383,11 +383,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
led_state(1, 1);
|
led_state(1, 1);
|
||||||
HAL_Delay(100);
|
mp_hal_delay_ms(100);
|
||||||
led_state(1, 0);
|
led_state(1, 0);
|
||||||
HAL_Delay(200);
|
mp_hal_delay_ms(200);
|
||||||
}
|
}
|
||||||
HAL_Delay(400);
|
mp_hal_delay_ms(400);
|
||||||
if (!switch_get()) {
|
if (!switch_get()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -399,11 +399,11 @@ STATIC uint update_reset_mode(uint reset_mode) {
|
|||||||
for (uint i = 0; i < 2; i++) {
|
for (uint i = 0; i < 2; i++) {
|
||||||
for (uint j = 0; j < reset_mode; j++) {
|
for (uint j = 0; j < reset_mode; j++) {
|
||||||
led_state(1, 1);
|
led_state(1, 1);
|
||||||
HAL_Delay(100);
|
mp_hal_delay_ms(100);
|
||||||
led_state(1, 0);
|
led_state(1, 0);
|
||||||
HAL_Delay(200);
|
mp_hal_delay_ms(200);
|
||||||
}
|
}
|
||||||
HAL_Delay(400);
|
mp_hal_delay_ms(400);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#error Need a reset mode update method
|
#error Need a reset mode update method
|
||||||
|
@ -324,7 +324,7 @@ STATIC mp_obj_t machine_freq(mp_uint_t n_args, const mp_obj_t *args) {
|
|||||||
//printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q);
|
//printf("%lu %lu %lu %lu %lu\n", sysclk_source, m, n, p, q);
|
||||||
|
|
||||||
// let the USB CDC have a chance to process before we change the clock
|
// let the USB CDC have a chance to process before we change the clock
|
||||||
HAL_Delay(5);
|
mp_hal_delay_ms(5);
|
||||||
|
|
||||||
// desired system clock source is in sysclk_source
|
// desired system clock source is in sysclk_source
|
||||||
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
RCC_ClkInitTypeDef RCC_ClkInitStruct;
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "py/stream.h"
|
#include "py/stream.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
#include "py/mperrno.h"
|
#include "py/mperrno.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
#include "netutils.h"
|
#include "netutils.h"
|
||||||
#include "modnetwork.h"
|
#include "modnetwork.h"
|
||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
@ -120,7 +121,7 @@ STATIC int cc3k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uin
|
|||||||
if (retry == 0 || CC3000_EXPORT(errno) != -95) {
|
if (retry == 0 || CC3000_EXPORT(errno) != -95) {
|
||||||
return CC3000_EXPORT(errno);
|
return CC3000_EXPORT(errno);
|
||||||
}
|
}
|
||||||
HAL_Delay(50);
|
mp_hal_delay_ms(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ip == 0) {
|
if (ip == 0) {
|
||||||
|
@ -202,7 +202,7 @@ STATIC int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_
|
|||||||
*_errno = MP_ENOTCONN; // ??
|
*_errno = MP_ENOTCONN; // ??
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
HAL_Delay(1);
|
mp_hal_delay_ms(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -348,9 +348,9 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||||||
mp_hal_pin_output(wiznet5k_obj.rst);
|
mp_hal_pin_output(wiznet5k_obj.rst);
|
||||||
|
|
||||||
mp_hal_pin_low(wiznet5k_obj.rst);
|
mp_hal_pin_low(wiznet5k_obj.rst);
|
||||||
HAL_Delay(1); // datasheet says 2us
|
mp_hal_delay_ms(1); // datasheet says 2us
|
||||||
mp_hal_pin_high(wiznet5k_obj.rst);
|
mp_hal_pin_high(wiznet5k_obj.rst);
|
||||||
HAL_Delay(160); // datasheet says 150ms
|
mp_hal_delay_ms(160); // datasheet says 150ms
|
||||||
|
|
||||||
reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
|
reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit);
|
||||||
reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
|
reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect);
|
||||||
@ -371,7 +371,7 @@ STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||||||
ctlnetwork(CN_SET_NETINFO, (void*)&netinfo);
|
ctlnetwork(CN_SET_NETINFO, (void*)&netinfo);
|
||||||
|
|
||||||
// seems we need a small delay after init
|
// seems we need a small delay after init
|
||||||
HAL_Delay(250);
|
mp_hal_delay_ms(250);
|
||||||
|
|
||||||
// register with network module
|
// register with network module
|
||||||
mod_network_register_nic(&wiznet5k_obj);
|
mod_network_register_nic(&wiznet5k_obj);
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "py/obj.h"
|
#include "py/obj.h"
|
||||||
#include "py/gc.h"
|
#include "py/gc.h"
|
||||||
#include "py/builtin.h"
|
#include "py/builtin.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
#include "lib/utils/pyexec.h"
|
#include "lib/utils/pyexec.h"
|
||||||
#include "lib/oofatfs/ff.h"
|
#include "lib/oofatfs/ff.h"
|
||||||
#include "lib/oofatfs/diskio.h"
|
#include "lib/oofatfs/diskio.h"
|
||||||
@ -71,20 +72,6 @@ STATIC mp_obj_t pyb_fault_debug(mp_obj_t value) {
|
|||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_fault_debug_obj, pyb_fault_debug);
|
||||||
|
|
||||||
/// \function millis()
|
|
||||||
/// Returns the number of milliseconds since the board was last reset.
|
|
||||||
///
|
|
||||||
/// The result is always a micropython smallint (31-bit signed number), so
|
|
||||||
/// after 2^30 milliseconds (about 12.4 days) this will start to return
|
|
||||||
/// negative numbers.
|
|
||||||
STATIC mp_obj_t pyb_millis(void) {
|
|
||||||
// We want to "cast" the 32 bit unsigned into a small-int. This means
|
|
||||||
// copying the MSB down 1 bit (extending the sign down), which is
|
|
||||||
// equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
|
|
||||||
return MP_OBJ_NEW_SMALL_INT(HAL_GetTick());
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
|
|
||||||
|
|
||||||
/// \function elapsed_millis(start)
|
/// \function elapsed_millis(start)
|
||||||
/// Returns the number of milliseconds which have elapsed since `start`.
|
/// Returns the number of milliseconds which have elapsed since `start`.
|
||||||
///
|
///
|
||||||
@ -97,25 +84,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_millis_obj, pyb_millis);
|
|||||||
/// # Perform some operation
|
/// # Perform some operation
|
||||||
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
|
STATIC mp_obj_t pyb_elapsed_millis(mp_obj_t start) {
|
||||||
uint32_t startMillis = mp_obj_get_int(start);
|
uint32_t startMillis = mp_obj_get_int(start);
|
||||||
uint32_t currMillis = HAL_GetTick();
|
uint32_t currMillis = mp_hal_ticks_ms();
|
||||||
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
|
return MP_OBJ_NEW_SMALL_INT((currMillis - startMillis) & 0x3fffffff);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_millis_obj, pyb_elapsed_millis);
|
||||||
|
|
||||||
/// \function micros()
|
|
||||||
/// Returns the number of microseconds since the board was last reset.
|
|
||||||
///
|
|
||||||
/// The result is always a micropython smallint (31-bit signed number), so
|
|
||||||
/// after 2^30 microseconds (about 17.8 minutes) this will start to return
|
|
||||||
/// negative numbers.
|
|
||||||
STATIC mp_obj_t pyb_micros(void) {
|
|
||||||
// We want to "cast" the 32 bit unsigned into a small-int. This means
|
|
||||||
// copying the MSB down 1 bit (extending the sign down), which is
|
|
||||||
// equivalent to just using the MP_OBJ_NEW_SMALL_INT macro.
|
|
||||||
return MP_OBJ_NEW_SMALL_INT(sys_tick_get_microseconds());
|
|
||||||
}
|
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
|
|
||||||
|
|
||||||
/// \function elapsed_micros(start)
|
/// \function elapsed_micros(start)
|
||||||
/// Returns the number of microseconds which have elapsed since `start`.
|
/// Returns the number of microseconds which have elapsed since `start`.
|
||||||
///
|
///
|
||||||
@ -128,7 +101,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_micros_obj, pyb_micros);
|
|||||||
/// # Perform some operation
|
/// # Perform some operation
|
||||||
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
|
STATIC mp_obj_t pyb_elapsed_micros(mp_obj_t start) {
|
||||||
uint32_t startMicros = mp_obj_get_int(start);
|
uint32_t startMicros = mp_obj_get_int(start);
|
||||||
uint32_t currMicros = sys_tick_get_microseconds();
|
uint32_t currMicros = mp_hal_ticks_us();
|
||||||
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
|
return MP_OBJ_NEW_SMALL_INT((currMicros - startMicros) & 0x3fffffff);
|
||||||
}
|
}
|
||||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
|
STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_elapsed_micros_obj, pyb_elapsed_micros);
|
||||||
@ -168,9 +141,9 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
|
|||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_have_cdc), (mp_obj_t)&pyb_have_cdc_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj },
|
||||||
|
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&mp_utime_ticks_ms_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_millis), (mp_obj_t)&pyb_elapsed_millis_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&pyb_micros_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_micros), (mp_obj_t)&mp_utime_ticks_us_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_elapsed_micros), (mp_obj_t)&pyb_elapsed_micros_obj },
|
||||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&mp_utime_sleep_ms_obj },
|
{ MP_OBJ_NEW_QSTR(MP_QSTR_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_udelay), (mp_obj_t)&mp_utime_sleep_us_obj },
|
||||||
|
@ -27,13 +27,7 @@ void mp_hal_set_interrupt_char(int c); // -1 to disable
|
|||||||
|
|
||||||
// timing functions
|
// timing functions
|
||||||
|
|
||||||
#include "stmhal/systick.h"
|
#define mp_hal_delay_us_fast(us) mp_hal_delay_us(us)
|
||||||
|
|
||||||
#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;
|
extern bool mp_hal_ticks_cpu_enabled;
|
||||||
void mp_hal_ticks_cpu_enable(void);
|
void mp_hal_ticks_cpu_enable(void);
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
|
|
||||||
#include "py/nlr.h"
|
#include "py/nlr.h"
|
||||||
#include "py/runtime.h"
|
#include "py/runtime.h"
|
||||||
|
#include "py/mphal.h"
|
||||||
#include "lib/oofatfs/ff.h"
|
#include "lib/oofatfs/ff.h"
|
||||||
#include "extmod/vfs_fat.h"
|
#include "extmod/vfs_fat.h"
|
||||||
#include "mphalport.h"
|
|
||||||
|
|
||||||
#include "sdcard.h"
|
#include "sdcard.h"
|
||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
@ -145,7 +145,7 @@ bool sdcard_power_on(void) {
|
|||||||
if (retry == 0) {
|
if (retry == 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
HAL_Delay(50);
|
mp_hal_delay_ms(50);
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure the SD bus width for wide operation
|
// configure the SD bus width for wide operation
|
||||||
|
@ -298,7 +298,7 @@ void SysTick_Handler(void) {
|
|||||||
uwTick += 1;
|
uwTick += 1;
|
||||||
|
|
||||||
// Read the systick control regster. This has the side effect of clearing
|
// Read the systick control regster. This has the side effect of clearing
|
||||||
// the COUNTFLAG bit, which makes the logic in sys_tick_get_microseconds
|
// the COUNTFLAG bit, which makes the logic in mp_hal_ticks_us
|
||||||
// work properly.
|
// work properly.
|
||||||
SysTick->CTRL;
|
SysTick->CTRL;
|
||||||
|
|
||||||
|
@ -24,20 +24,36 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include STM32_HAL_H
|
#include "py/mphal.h"
|
||||||
|
|
||||||
#include "py/obj.h"
|
|
||||||
#include "irq.h"
|
#include "irq.h"
|
||||||
#include "systick.h"
|
#include "systick.h"
|
||||||
#include "pybthread.h"
|
#include "pybthread.h"
|
||||||
|
|
||||||
// We provide our own version of HAL_Delay that calls __WFI while waiting, in
|
extern __IO uint32_t uwTick;
|
||||||
// order to reduce power consumption.
|
|
||||||
// Note: Upon entering this function we may or may not have the GIL.
|
// We provide our own version of HAL_Delay that calls __WFI while waiting,
|
||||||
|
// and works when interrupts are disabled. This function is intended to be
|
||||||
|
// used only by the ST HAL functions.
|
||||||
void HAL_Delay(uint32_t Delay) {
|
void HAL_Delay(uint32_t Delay) {
|
||||||
if (query_irq() == IRQ_STATE_ENABLED) {
|
if (query_irq() == IRQ_STATE_ENABLED) {
|
||||||
// IRQs enabled, so can use systick counter to do the delay
|
// IRQs enabled, so can use systick counter to do the delay
|
||||||
extern __IO uint32_t uwTick;
|
uint32_t start = uwTick;
|
||||||
|
// Wraparound of tick is taken care of by 2's complement arithmetic.
|
||||||
|
while (uwTick - start < Delay) {
|
||||||
|
// Enter sleep mode, waiting for (at least) the SysTick interrupt.
|
||||||
|
__WFI();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// IRQs disabled, use mp_hal_delay_ms routine.
|
||||||
|
mp_hal_delay_ms(Delay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Core delay function that does an efficient sleep and may switch thread context.
|
||||||
|
// Note: Upon entering this function we may or may not have the GIL.
|
||||||
|
void mp_hal_delay_ms(mp_uint_t Delay) {
|
||||||
|
if (query_irq() == IRQ_STATE_ENABLED) {
|
||||||
|
// IRQs enabled, so can use systick counter to do the delay
|
||||||
uint32_t start = uwTick;
|
uint32_t start = uwTick;
|
||||||
// Wraparound of tick is taken care of by 2's complement arithmetic.
|
// Wraparound of tick is taken care of by 2's complement arithmetic.
|
||||||
while (uwTick - start < Delay) {
|
while (uwTick - start < Delay) {
|
||||||
@ -64,11 +80,11 @@ void HAL_Delay(uint32_t Delay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// delay for given number of microseconds
|
// delay for given number of microseconds
|
||||||
void sys_tick_udelay(uint32_t usec) {
|
void mp_hal_delay_us(mp_uint_t usec) {
|
||||||
if (query_irq() == IRQ_STATE_ENABLED) {
|
if (query_irq() == IRQ_STATE_ENABLED) {
|
||||||
// IRQs enabled, so can use systick counter to do the delay
|
// IRQs enabled, so can use systick counter to do the delay
|
||||||
uint32_t start = sys_tick_get_microseconds();
|
uint32_t start = mp_hal_ticks_us();
|
||||||
while (sys_tick_get_microseconds() - start < usec) {
|
while (mp_hal_ticks_us() - start < usec) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// IRQs disabled, so need to use a busy loop for the delay
|
// IRQs disabled, so need to use a busy loop for the delay
|
||||||
@ -92,11 +108,15 @@ void sys_tick_wait_at_least(uint32_t start_tick, uint32_t delay_ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mp_uint_t mp_hal_ticks_ms(void) {
|
||||||
|
return uwTick;
|
||||||
|
}
|
||||||
|
|
||||||
// The SysTick timer counts down at 168 MHz, so we can use that knowledge
|
// The SysTick timer counts down at 168 MHz, so we can use that knowledge
|
||||||
// to grab a microsecond counter.
|
// to grab a microsecond counter.
|
||||||
//
|
//
|
||||||
// We assume that HAL_GetTickis returns milliseconds.
|
// We assume that HAL_GetTickis returns milliseconds.
|
||||||
uint32_t sys_tick_get_microseconds(void) {
|
mp_uint_t mp_hal_ticks_us(void) {
|
||||||
mp_uint_t irq_state = disable_irq();
|
mp_uint_t irq_state = disable_irq();
|
||||||
uint32_t counter = SysTick->VAL;
|
uint32_t counter = SysTick->VAL;
|
||||||
uint32_t milliseconds = HAL_GetTick();
|
uint32_t milliseconds = HAL_GetTick();
|
||||||
|
@ -24,7 +24,5 @@
|
|||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sys_tick_udelay(uint32_t usec);
|
|
||||||
void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
|
void sys_tick_wait_at_least(uint32_t stc, uint32_t delay_ms);
|
||||||
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
|
bool sys_tick_has_passed(uint32_t stc, uint32_t delay_ms);
|
||||||
uint32_t sys_tick_get_microseconds(void);
|
|
||||||
|
@ -4,11 +4,3 @@ print(abs(False))
|
|||||||
print(abs(True))
|
print(abs(True))
|
||||||
print(abs(1))
|
print(abs(1))
|
||||||
print(abs(-1))
|
print(abs(-1))
|
||||||
|
|
||||||
# bignum
|
|
||||||
print(abs(123456789012345678901234567890))
|
|
||||||
print(abs(-123456789012345678901234567890))
|
|
||||||
|
|
||||||
# edge cases for 32 and 64 bit archs (small int overflow when negating)
|
|
||||||
print(abs(-0x3fffffff - 1))
|
|
||||||
print(abs(-0x3fffffffffffffff - 1))
|
|
||||||
|
9
tests/basics/builtin_abs_intbig.py
Normal file
9
tests/basics/builtin_abs_intbig.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# test builtin abs
|
||||||
|
|
||||||
|
# bignum
|
||||||
|
print(abs(123456789012345678901234567890))
|
||||||
|
print(abs(-123456789012345678901234567890))
|
||||||
|
|
||||||
|
# edge cases for 32 and 64 bit archs (small int overflow when negating)
|
||||||
|
print(abs(-0x3fffffff - 1))
|
||||||
|
print(abs(-0x3fffffffffffffff - 1))
|
@ -8,5 +8,4 @@ print(bin(-15))
|
|||||||
print(bin(12345))
|
print(bin(12345))
|
||||||
print(bin(0b10101))
|
print(bin(0b10101))
|
||||||
|
|
||||||
print(bin(12345678901234567890))
|
|
||||||
print(bin(0b10101010101010101010))
|
print(bin(0b10101010101010101010))
|
||||||
|
3
tests/basics/builtin_bin_intbig.py
Normal file
3
tests/basics/builtin_bin_intbig.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# test builtin bin function
|
||||||
|
|
||||||
|
print(bin(12345678901234567890))
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user