Merge branch 'master' into nrf5_no_sdk

This commit is contained in:
Glenn Ruben Bakke 2017-03-07 17:46:34 +01:00
commit fd8f2c36f5
210 changed files with 2371 additions and 1528 deletions

4
.gitignore vendored
View File

@ -38,3 +38,7 @@ __pycache__/
###################### ######################
GNUmakefile GNUmakefile
user.props user.props
# Generated rst files
######################
genrst/

View File

@ -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) {

View File

@ -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"

View File

@ -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"

View File

@ -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);

View File

@ -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,

View File

@ -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";

View File

@ -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[];

View File

@ -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"

View File

@ -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"

View File

@ -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);
} }
} }

View File

@ -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) {

View File

@ -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);

View File

@ -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);

View File

@ -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"

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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 }, \

View File

@ -163,7 +163,7 @@ extern "C" {
\warning \warning
*/ */
#define SL_INC_STD_BSD_API_NAMING /* #define SL_INC_STD_BSD_API_NAMING */
/*! /*!

View File

@ -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);

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View File

@ -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
View 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

View File

@ -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

View File

@ -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)

View File

@ -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
------- -------

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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">

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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.

View 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) {

View File

@ -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)

View File

@ -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

View File

@ -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, ...)

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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
View 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__)

View File

@ -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
View 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__)

View File

@ -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
View 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__)

View File

@ -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;
} }

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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

View File

@ -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) {

View File

@ -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 \

View File

@ -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);
} }

View File

@ -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,
};

View File

@ -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>

View File

@ -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);
} }

View File

@ -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);
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);
} }
/******************************************************************************/ /******************************************************************************/

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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 },

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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);

View File

@ -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))

View 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))

View File

@ -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))

View 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