kopia lustrzana https://github.com/micropython/micropython
Porównaj commity
19 Commity
53d024a567
...
dc5a6d54cc
Autor | SHA1 | Data |
---|---|---|
Jared Hancock | dc5a6d54cc | |
Damien George | 49ce7a6075 | |
Angus Gratton | 6877987002 | |
Angus Gratton | 4bed614e70 | |
Vonasmic | ce491ab0d1 | |
stijn | 40f7e9ce20 | |
Michiel W. Beijen | 3129b69e0f | |
Simon Wood | 19844b4983 | |
J. Neuschäfer | f76cf29402 | |
Jared Hancock | ed7ef9e48c | |
Jared Hancock | 70190b0c75 | |
Jared Hancock | fc03d95493 | |
Jared Hancock | b96f75cb95 | |
Jared Hancock | 35763b3970 | |
Jared Hancock | e9de433ecf | |
Jared Hancock | c1b0c7eca3 | |
Jared Hancock | 4364ad74ae | |
Jared Hancock | 26d0ea4006 | |
Jared Hancock | 2e371503d6 |
|
@ -8,9 +8,15 @@ on:
|
|||
- 'tools/**'
|
||||
- 'py/**'
|
||||
- 'extmod/**'
|
||||
- 'shared/**'
|
||||
- 'lib/**'
|
||||
- 'ports/bare-arm/**'
|
||||
- 'ports/mimxrt/**'
|
||||
- 'ports/minimal/**'
|
||||
- 'ports/rp2/**'
|
||||
- 'ports/samd/**'
|
||||
- 'ports/stm32/**'
|
||||
- 'ports/unix/**'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
|
|
@ -88,10 +88,11 @@ jobs:
|
|||
(cd ports/unix && gcov -o build-coverage/py ../../py/*.c || true)
|
||||
(cd ports/unix && gcov -o build-coverage/extmod ../../extmod/*.c || true)
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
fail_ci_if_error: true
|
||||
verbose: true
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
- name: Print failures
|
||||
if: failure()
|
||||
run: tests/run-tests.py --print-failures
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||
|
||||
#include "shared/netutils/netutils.h"
|
||||
#include "shared/runtime/softtimer.h"
|
||||
#include "extmod/modnetwork.h"
|
||||
#include "extmod/modmachine.h"
|
||||
#include "extmod/virtpin.h"
|
||||
|
@ -74,6 +75,14 @@
|
|||
#include "lib/wiznet5k/Internet/DNS/dns.h"
|
||||
#include "lib/wiznet5k/Internet/DHCP/dhcp.h"
|
||||
|
||||
// Poll WIZnet every 64ms by default (if not using interrupt pin)
|
||||
#define WIZNET5K_TICK_RATE_MS 64
|
||||
// In DHCP.c, RIP_MSG max size is defined as 312 + 256 (sadly, not in the header)
|
||||
#define MAX_DHCP_BUF_SIZE 568
|
||||
|
||||
// Soft timer for polling and running DHCP in the background.
|
||||
static soft_timer_entry_t mp_network_soft_timer;
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef printf
|
||||
|
@ -99,9 +108,9 @@ typedef struct _wiznet5k_obj_t {
|
|||
void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
||||
mp_hal_pin_obj_t cs;
|
||||
mp_hal_pin_obj_t rst;
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
mp_hal_pin_obj_t pin_intn;
|
||||
bool use_interrupt;
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
uint8_t eth_frame[1514];
|
||||
uint32_t trace_flags;
|
||||
struct netif netif;
|
||||
|
@ -110,9 +119,20 @@ typedef struct _wiznet5k_obj_t {
|
|||
wiz_NetInfo netinfo;
|
||||
uint8_t socket_used;
|
||||
bool active;
|
||||
uint8_t *dhcp_buf;
|
||||
uint8_t dhcp_state;
|
||||
mp_int_t dhcp_socket;
|
||||
uint32_t dhcp_renew;
|
||||
#endif
|
||||
} wiznet5k_obj_t;
|
||||
|
||||
#if WIZNET5K_PROVIDED_STACK
|
||||
typedef struct _wiznet5k_socket_extra_t {
|
||||
byte remote_ip[4];
|
||||
mp_uint_t remote_port;
|
||||
} wiznet5k_socket_extra_t;
|
||||
#endif
|
||||
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
#define IS_ACTIVE(self) (self->netif.flags & NETIF_FLAG_UP)
|
||||
#else // WIZNET5K_PROVIDED_STACK
|
||||
|
@ -170,11 +190,7 @@ static void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) {
|
|||
getSHAR(mac);
|
||||
}
|
||||
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
|
||||
void wiznet5k_try_poll(void);
|
||||
static void wiznet5k_lwip_init(wiznet5k_obj_t *self);
|
||||
|
||||
static mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) {
|
||||
(void)none_in;
|
||||
// Handle incoming data, unless the SPI bus is busy
|
||||
|
@ -197,6 +213,9 @@ static void wiznet5k_config_interrupt(bool enabled) {
|
|||
);
|
||||
}
|
||||
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
static void wiznet5k_lwip_init(wiznet5k_obj_t *self);
|
||||
|
||||
void wiznet5k_deinit(void) {
|
||||
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
|
||||
if (netif == &wiznet5k_obj.netif) {
|
||||
|
@ -350,6 +369,59 @@ void wiznet5k_poll(void) {
|
|||
|
||||
#if WIZNET5K_PROVIDED_STACK
|
||||
|
||||
static mp_int_t wiznet5k_allocate_socket(void) {
|
||||
// get first unused socket number
|
||||
for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
|
||||
if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
|
||||
wiznet5k_obj.socket_used |= (1 << sn);
|
||||
return sn;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern uint8_t DHCP_SOCKET;
|
||||
static void wiznet5k_dhcp_poll(void) {
|
||||
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||
wiznet5k_obj.dhcp_state = DHCP_run();
|
||||
}
|
||||
|
||||
if (wiznet5k_obj.dhcp_state == DHCP_IP_LEASED) {
|
||||
// Every few seconds, check in about renewing the IP
|
||||
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||
// Release socket and reset timeout
|
||||
wiznet5k_obj.socket_used &= ~(1 << wiznet5k_obj.dhcp_socket);
|
||||
wiznet5k_obj.dhcp_socket = -1;
|
||||
|
||||
// Run about once per minute
|
||||
wiznet5k_obj.dhcp_renew = mp_hal_ticks_ms() + 60000;
|
||||
} else if (mp_hal_ticks_ms() > wiznet5k_obj.dhcp_renew) {
|
||||
mp_uint_t sn = wiznet5k_allocate_socket();
|
||||
if (sn != -1) {
|
||||
DHCP_SOCKET = sn;
|
||||
wiznet5k_obj.dhcp_socket = sn;
|
||||
wiznet5k_obj.dhcp_state = DHCP_run();
|
||||
}
|
||||
}
|
||||
} else if (wiznet5k_obj.dhcp_state == DHCP_FAILED || wiznet5k_obj.dhcp_state == DHCP_STOPPED) {
|
||||
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||
wiznet5k_obj.socket_used &= ~(1 << wiznet5k_obj.dhcp_socket);
|
||||
wiznet5k_obj.dhcp_socket = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wiznet5k_try_poll(void) {
|
||||
// If using DHCP for the interface, periodically renew/update the address
|
||||
wiznet5k_dhcp_poll();
|
||||
|
||||
// There's really nothing to do here. The interrupt that triggered this will
|
||||
// release a WFE() wait and will trigger a poll() loop which will
|
||||
// wiznet5k_socket_ioctl will detect the readable or writeable state of the
|
||||
// respective socket(s).
|
||||
}
|
||||
|
||||
static void wiz_dhcp_assign(void) {
|
||||
getIPfromDHCP(wiznet5k_obj.netinfo.ip);
|
||||
getGWfromDHCP(wiznet5k_obj.netinfo.gw);
|
||||
|
@ -359,7 +431,7 @@ static void wiz_dhcp_assign(void) {
|
|||
}
|
||||
|
||||
static void wiz_dhcp_update(void) {
|
||||
;
|
||||
wiz_dhcp_assign();
|
||||
}
|
||||
|
||||
|
||||
|
@ -367,6 +439,22 @@ static void wiz_dhcp_conflict(void) {
|
|||
;
|
||||
}
|
||||
|
||||
// This is called by soft_timer and executes at PendSV level.
|
||||
static void mp_network_soft_timer_callback(soft_timer_entry_t *self) {
|
||||
wiznet5k_try_poll();
|
||||
}
|
||||
|
||||
static void mod_network_wiznet5k_poll_init(void) {
|
||||
soft_timer_static_init(
|
||||
&mp_network_soft_timer,
|
||||
SOFT_TIMER_MODE_PERIODIC,
|
||||
WIZNET5K_TICK_RATE_MS,
|
||||
mp_network_soft_timer_callback
|
||||
);
|
||||
|
||||
soft_timer_reinsert(&mp_network_soft_timer, WIZNET5K_TICK_RATE_MS);
|
||||
}
|
||||
|
||||
static void wiznet5k_init(void) {
|
||||
// Configure wiznet provided TCP / socket interface
|
||||
|
||||
|
@ -388,21 +476,46 @@ static void wiznet5k_init(void) {
|
|||
};
|
||||
wiznet5k_obj.netinfo = netinfo;
|
||||
|
||||
if (wiznet5k_obj.use_interrupt) {
|
||||
mp_hal_pin_input(wiznet5k_obj.pin_intn);
|
||||
wiznet5k_config_interrupt(true);
|
||||
wizchip_setinterruptmask(IK_SOCK_ALL);
|
||||
|
||||
#if _WIZCHIP_ == W5100S
|
||||
// Enable interrupt pin
|
||||
setMR2(getMR2() | MR2_G_IEN);
|
||||
#endif
|
||||
}
|
||||
|
||||
// register with network module
|
||||
mod_network_register_nic(&wiznet5k_obj);
|
||||
mod_network_wiznet5k_poll_init();
|
||||
|
||||
wiznet5k_obj.active = true;
|
||||
wiznet5k_obj.dhcp_socket = -1;
|
||||
wiznet5k_obj.dhcp_state = DHCP_STOPPED;
|
||||
}
|
||||
|
||||
static int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
|
||||
uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
|
||||
uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
|
||||
DNS_init(2, buf);
|
||||
mp_int_t sn = wiznet5k_allocate_socket();
|
||||
if (sn == -1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
DNS_init(sn, buf);
|
||||
if (wiznet5k_obj.netinfo.dns[0]) {
|
||||
memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE);
|
||||
}
|
||||
mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
|
||||
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
|
||||
|
||||
// NOTE: DNS_run will close the socket, so it just needs to be marked as
|
||||
// unused here and clear any interrupts.
|
||||
wiznet5k_obj.socket_used &= ~(1 << sn);
|
||||
wizchip_clrinterrupt(IK_SOCK_0 << sn);
|
||||
|
||||
if (ret == 1) {
|
||||
// success
|
||||
return 0;
|
||||
|
@ -432,18 +545,19 @@ static int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno)
|
|||
|
||||
if (socket->fileno == -1) {
|
||||
// get first unused socket number
|
||||
for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
|
||||
if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
|
||||
wiznet5k_obj.socket_used |= (1 << sn);
|
||||
socket->fileno = sn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
socket->fileno = wiznet5k_allocate_socket();
|
||||
if (socket->fileno == -1) {
|
||||
// too many open sockets
|
||||
*_errno = MP_EMFILE;
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket->_private = NULL;
|
||||
|
||||
// Enable data receive interrupt
|
||||
if (wiznet5k_obj.use_interrupt) {
|
||||
setSn_IMR(socket->fileno, (Sn_IR_RECV | Sn_IR_CON | Sn_IR_DISCON));
|
||||
}
|
||||
}
|
||||
|
||||
// WIZNET does not have a concept of pure "open socket". You need to know
|
||||
|
@ -461,12 +575,27 @@ static void wiznet5k_socket_close(mod_network_socket_obj_t *socket) {
|
|||
if (sn < _WIZCHIP_SOCK_NUM_) {
|
||||
wiznet5k_obj.socket_used &= ~(1 << sn);
|
||||
WIZCHIP_EXPORT(close)(sn);
|
||||
|
||||
// Disable receive interrupts
|
||||
if (wiznet5k_obj.use_interrupt) {
|
||||
setSn_IMR(sn, 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_del(wiznet5k_socket_extra_t, socket->_private, 1);
|
||||
socket->_private = NULL;
|
||||
}
|
||||
|
||||
static int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
|
||||
uint8_t flag = 0;
|
||||
if (socket->timeout == 0) {
|
||||
// Setup non-blocking mode
|
||||
flag |= SOCK_IO_NONBLOCK;
|
||||
}
|
||||
|
||||
// open the socket in server mode (if port != 0)
|
||||
mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, 0);
|
||||
mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, flag);
|
||||
|
||||
if (ret < 0) {
|
||||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
|
@ -531,6 +660,9 @@ static int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, m
|
|||
return -1;
|
||||
}
|
||||
|
||||
// WIZnet doesn't support connect on UDP sockets. Stash the remote
|
||||
// information for use with the ::send method, if used on this UDP socket.
|
||||
if (socket->type == Sn_MR_TCP) {
|
||||
// now connect
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port);
|
||||
|
@ -540,13 +672,37 @@ static int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, m
|
|||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret == SOCK_BUSY) {
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
} else if (socket->type == Sn_MR_UDP) {
|
||||
// For POSIX usage of ::send later, stash the remote IP and port
|
||||
wiznet5k_socket_extra_t *extra = m_new_maybe(wiznet5k_socket_extra_t, 1);
|
||||
if (extra == NULL) {
|
||||
*_errno = MP_ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
memcpy(extra->remote_ip, ip, 4);
|
||||
extra->remote_port = port;
|
||||
socket->_private = extra;
|
||||
}
|
||||
|
||||
// success
|
||||
return 0;
|
||||
}
|
||||
|
||||
static mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
|
||||
static mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
|
||||
if (socket->type == Sn_MR_UDP) {
|
||||
if (socket->_private != NULL) {
|
||||
wiznet5k_socket_extra_t *extra = (wiznet5k_socket_extra_t *)socket->_private;
|
||||
return wiznet5k_socket_sendto(socket, buf, len, extra->remote_ip, extra->remote_port, _errno);
|
||||
}
|
||||
*_errno = MP_ENOTCONN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_int_t ret = WIZCHIP_EXPORT(send)(socket->fileno, (byte *)buf, len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
|
@ -556,11 +712,28 @@ static mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const by
|
|||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret == SOCK_BUSY) {
|
||||
uint8_t status = getSn_SR(socket->fileno);
|
||||
if (status == SOCK_ESTABLISHED || status == SOCK_CLOSE_WAIT) {
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
|
||||
if (socket->timeout > 0) {
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
while (getSn_SR(socket->fileno) == SOCK_ESTABLISHED && getSn_RX_RSR(socket->fileno) == 0) {
|
||||
if (mp_hal_ticks_ms() - start > socket->timeout) {
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
mp_event_wait_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->fileno, buf, len);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
|
@ -570,6 +743,14 @@ static mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *bu
|
|||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret == SOCK_BUSY) {
|
||||
// NOTE: SOCK_BUSY is zero (0) which is confusing if the socket is closed
|
||||
// and at EOF
|
||||
uint8_t status = getSn_SR(socket->fileno);
|
||||
if (status == SOCK_ESTABLISHED || status == SOCK_CLOSE_WAIT) {
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -590,12 +771,27 @@ static mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const
|
|||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret == SOCK_BUSY) {
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
||||
uint16_t port2;
|
||||
|
||||
if (socket->timeout > 0) {
|
||||
mp_uint_t start = mp_hal_ticks_ms();
|
||||
while (getSn_SR(socket->fileno) != SOCK_CLOSED && getSn_RX_RSR(socket->fileno) == 0) {
|
||||
if (mp_hal_ticks_ms() - start > socket->timeout) {
|
||||
*_errno = MP_ETIMEDOUT;
|
||||
return -1;
|
||||
}
|
||||
mp_event_wait_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
MP_THREAD_GIL_EXIT();
|
||||
mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->fileno, buf, len, ip, &port2);
|
||||
MP_THREAD_GIL_ENTER();
|
||||
|
@ -604,39 +800,78 @@ static mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte
|
|||
wiznet5k_socket_close(socket);
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
} else if (ret == SOCK_BUSY) {
|
||||
*_errno = MP_EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
|
||||
// TODO
|
||||
switch (opt) {
|
||||
// level: SOL_SOCKET
|
||||
case MOD_NETWORK_SO_REUSEADDR:
|
||||
case MOD_NETWORK_SO_BROADCAST:
|
||||
// Implied/not-required in Wiznet sockets
|
||||
break;
|
||||
|
||||
default:
|
||||
*_errno = MP_EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
|
||||
// TODO
|
||||
*_errno = MP_EINVAL;
|
||||
return -1;
|
||||
|
||||
/*
|
||||
uint8_t arg;
|
||||
if (timeout_ms == 0) {
|
||||
// set non-blocking mode
|
||||
uint8_t arg = SOCK_IO_NONBLOCK;
|
||||
WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg);
|
||||
arg = SOCK_IO_NONBLOCK;
|
||||
} else {
|
||||
arg = SOCK_IO_BLOCK;
|
||||
}
|
||||
*/
|
||||
|
||||
mp_int_t ret = WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg);
|
||||
if (ret < 0) {
|
||||
*_errno = -ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
socket->timeout = timeout_ms;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
||||
uint8_t sn = (uint8_t)socket->fileno;
|
||||
|
||||
if (request == MP_STREAM_POLL) {
|
||||
int ret = 0;
|
||||
if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->fileno) != 0) {
|
||||
if (sn < _WIZCHIP_SOCK_NUM_) {
|
||||
if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(sn) != 0) {
|
||||
ret |= MP_STREAM_POLL_RD;
|
||||
}
|
||||
if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->fileno) != 0) {
|
||||
if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(sn) != 0) {
|
||||
ret |= MP_STREAM_POLL_WR;
|
||||
}
|
||||
|
||||
uint8_t status = getSn_SR(sn);
|
||||
if (status == SOCK_CLOSE_WAIT || getSn_IR(sn) & Sn_IR_DISCON) {
|
||||
// Peer-closed socket is both readable and writable: read will
|
||||
// return EOF, write - error. Without this poll will hang on a
|
||||
// socket which was closed by peer.
|
||||
ret |= arg & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR);
|
||||
} else if (status == SOCK_CLOSED) {
|
||||
ret |= MP_STREAM_POLL_ERR;
|
||||
}
|
||||
} else {
|
||||
ret |= MP_STREAM_POLL_NVAL;
|
||||
}
|
||||
|
||||
if (wiznet5k_obj.use_interrupt) {
|
||||
setSn_IR(sn, (Sn_IR_RECV | Sn_IR_CON | Sn_IR_DISCON));
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
*_errno = MP_EINVAL;
|
||||
|
@ -645,23 +880,31 @@ static int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t req
|
|||
}
|
||||
|
||||
static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
|
||||
uint8_t test_buf[2048];
|
||||
uint8_t ret = 0;
|
||||
uint8_t dhcp_retry = 0;
|
||||
self->dhcp_state = DHCP_STOPPED;
|
||||
self->dhcp_buf = m_new_maybe(uint8_t, MAX_DHCP_BUF_SIZE);
|
||||
if (self->dhcp_buf == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (ret != DHCP_IP_LEASED) {
|
||||
self->dhcp_socket = wiznet5k_allocate_socket();
|
||||
if (self->dhcp_socket == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (self->dhcp_state != DHCP_IP_LEASED) {
|
||||
mp_uint_t timeout = mp_hal_ticks_ms() + 3000;
|
||||
DHCP_init(1, test_buf);
|
||||
DHCP_init(self->dhcp_socket, self->dhcp_buf);
|
||||
|
||||
while (1) {
|
||||
ret = DHCP_run();
|
||||
if (ret == DHCP_IP_LEASED) {
|
||||
mpy_wiznet_yield();
|
||||
if (self->dhcp_state == DHCP_IP_LEASED) {
|
||||
break;
|
||||
} else if (ret == DHCP_FAILED || mp_hal_ticks_ms() > timeout) {
|
||||
} else if (self->dhcp_state == DHCP_FAILED || mp_hal_ticks_ms() > timeout) {
|
||||
dhcp_retry++;
|
||||
break;
|
||||
}
|
||||
mpy_wiznet_yield();
|
||||
}
|
||||
|
||||
if (dhcp_retry > 3) {
|
||||
|
@ -670,9 +913,11 @@ static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ret == DHCP_IP_LEASED) {
|
||||
if (self->dhcp_state == DHCP_IP_LEASED) {
|
||||
ctlnetwork(CN_GET_NETINFO, &self->netinfo);
|
||||
}
|
||||
|
||||
wizchip_clrinterrupt(IK_SOCK_0 << self->dhcp_socket);
|
||||
}
|
||||
|
||||
#endif // WIZNET5K_PROVIDED_STACK
|
||||
|
@ -686,11 +931,10 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
mp_obj_base_t *spi;
|
||||
mp_hal_pin_obj_t cs;
|
||||
mp_hal_pin_obj_t rst;
|
||||
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
mp_hal_pin_obj_t pin_intn = (mp_hal_pin_obj_t)NULL;
|
||||
bool use_interrupt = false;
|
||||
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
// Bring down interface while configuring
|
||||
wiznet5k_obj.netif.flags = 0;
|
||||
#endif
|
||||
|
@ -713,7 +957,7 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
|
||||
cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)}));
|
||||
rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)}));
|
||||
#if WIZNET5K_WITH_LWIP_STACK && defined(MICROPY_HW_WIZNET_PIN_INTN)
|
||||
#ifdef MICROPY_HW_WIZNET_PIN_INTN
|
||||
pin_intn = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_INTN)}));
|
||||
use_interrupt = true;
|
||||
#endif
|
||||
|
@ -722,20 +966,14 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
#endif
|
||||
{
|
||||
// If passing in args, must supply spi, pin_cs, pin_rst and optionally pin_intn
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
mp_arg_check_num(n_args, n_kw, 3, 4, false);
|
||||
#else
|
||||
mp_arg_check_num(n_args, n_kw, 3, 3, false);
|
||||
#endif
|
||||
spi = mp_hal_get_spi_obj(args[0]);
|
||||
cs = mp_hal_get_pin_obj(args[1]);
|
||||
rst = mp_hal_get_pin_obj(args[2]);
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
if (n_args > 3) {
|
||||
pin_intn = mp_hal_get_pin_obj(args[3]);
|
||||
use_interrupt = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
mp_hal_pin_output(cs);
|
||||
|
@ -748,9 +986,9 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer;
|
||||
wiznet5k_obj.cs = cs;
|
||||
wiznet5k_obj.rst = rst;
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
wiznet5k_obj.pin_intn = pin_intn;
|
||||
wiznet5k_obj.use_interrupt = use_interrupt;
|
||||
#if WIZNET5K_WITH_LWIP_STACK
|
||||
wiznet5k_obj.trace_flags = 0;
|
||||
#else // WIZNET5K_PROVIDED_STACK
|
||||
wiznet5k_obj.active = false;
|
||||
|
@ -894,6 +1132,11 @@ static mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
|
|||
} else {
|
||||
// Set static IP addresses
|
||||
self->netinfo.dhcp = NETINFO_STATIC;
|
||||
self->dhcp_state = DHCP_STOPPED;
|
||||
if (self->dhcp_buf) {
|
||||
m_del(uint8_t, self->dhcp_buf, MAX_DHCP_BUF_SIZE);
|
||||
self->dhcp_buf = NULL;
|
||||
}
|
||||
mp_obj_t *items;
|
||||
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
||||
netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG);
|
||||
|
|
|
@ -37,7 +37,7 @@ You can also build the standard CMake way. The final firmware is found in
|
|||
the top-level of the CMake build directory (`build` by default) and is
|
||||
called `firmware.uf2`.
|
||||
|
||||
If you are using a different board other than a Rasoberry Pi Pico, then you should
|
||||
If you are using a board other than a Raspberry Pi Pico, you should
|
||||
pass the board name to the build; e.g. for Raspberry Pi Pico W:
|
||||
|
||||
$ make BOARD=RPI_PICO_W submodules
|
||||
|
|
|
@ -127,10 +127,10 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
|||
|
||||
const uint32_t xosc_hz = XOSC_MHZ * 1000000;
|
||||
|
||||
uint32_t my_interrupts = save_and_disable_interrupts();
|
||||
uint32_t my_interrupts = mp_thread_begin_atomic_section();
|
||||
#if MICROPY_PY_NETWORK_CYW43
|
||||
if (cyw43_has_pending && cyw43_poll != NULL) {
|
||||
restore_interrupts(my_interrupts);
|
||||
mp_thread_end_atomic_section(my_interrupts);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
@ -165,8 +165,15 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
|||
} else {
|
||||
uint32_t sleep_en0 = clocks_hw->sleep_en0;
|
||||
uint32_t sleep_en1 = clocks_hw->sleep_en1;
|
||||
bool timer3_enabled = irq_is_enabled(3);
|
||||
|
||||
clocks_hw->sleep_en0 = CLOCKS_SLEEP_EN0_CLK_RTC_RTC_BITS;
|
||||
if (use_timer_alarm) {
|
||||
// Make sure ALARM3/IRQ3 is enabled on _this_ core
|
||||
timer_hw->inte |= 1 << 3;
|
||||
if (!timer3_enabled) {
|
||||
irq_set_enabled(3, true);
|
||||
}
|
||||
// Use timer alarm to wake.
|
||||
clocks_hw->sleep_en1 = CLOCKS_SLEEP_EN1_CLK_SYS_TIMER_BITS;
|
||||
timer_hw->alarm[3] = timer_hw->timerawl + delay_ms * 1000;
|
||||
|
@ -177,6 +184,9 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
|||
scb_hw->scr |= M0PLUS_SCR_SLEEPDEEP_BITS;
|
||||
__wfi();
|
||||
scb_hw->scr &= ~M0PLUS_SCR_SLEEPDEEP_BITS;
|
||||
if (!timer3_enabled) {
|
||||
irq_set_enabled(3, false);
|
||||
}
|
||||
clocks_hw->sleep_en0 = sleep_en0;
|
||||
clocks_hw->sleep_en1 = sleep_en1;
|
||||
}
|
||||
|
@ -186,7 +196,7 @@ static void mp_machine_lightsleep(size_t n_args, const mp_obj_t *args) {
|
|||
|
||||
// Bring back all clocks.
|
||||
clocks_init();
|
||||
restore_interrupts(my_interrupts);
|
||||
mp_thread_end_atomic_section(my_interrupts);
|
||||
}
|
||||
|
||||
NORETURN static void mp_machine_deepsleep(size_t n_args, const mp_obj_t *args) {
|
||||
|
|
|
@ -218,6 +218,10 @@ extern const struct _mp_obj_type_t mod_network_nic_type_nina;
|
|||
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
||||
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
||||
// This Network interface requires the extended socket state for timeouts and non-blocking
|
||||
#ifndef MICROPY_PY_SOCKET_EXTENDED_STATE
|
||||
#define MICROPY_PY_SOCKET_EXTENDED_STATE (1)
|
||||
#endif
|
||||
#else
|
||||
#define MICROPY_HW_NIC_WIZNET5K
|
||||
#endif
|
||||
|
|
|
@ -202,6 +202,10 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type;
|
|||
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
||||
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
||||
// This Network interface requires the extended socket state for timeouts and non-blocking
|
||||
#ifndef MICROPY_PY_SOCKET_EXTENDED_STATE
|
||||
#define MICROPY_PY_SOCKET_EXTENDED_STATE (1)
|
||||
#endif
|
||||
#else
|
||||
#define MICROPY_HW_NIC_WIZNET5K
|
||||
#endif
|
||||
|
|
28
py/obj.h
28
py/obj.h
|
@ -753,20 +753,20 @@ typedef struct _mp_obj_full_type_t {
|
|||
// Do not use these directly, instead use MP_DEFINE_CONST_OBJ_TYPE.
|
||||
// Generated with:
|
||||
// for i in range(13):
|
||||
// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .name = _name, .flags = _flags{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}")
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slots = { v1, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .name = _name, .flags = _flags, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } }
|
||||
// print(f"#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_{i}(_struct_type, _typename, _name, _flags{''.join(f', f{j+1}, v{j+1}' for j in range(i))}) const _struct_type _typename = {{ .base = {{ &mp_type_type }}, .flags = _flags, .name = _name{''.join(f', .slot_index_##f{j+1} = {j+1}' for j in range(i))}{', .slots = { ' + ''.join(f'v{j+1}, ' for j in range(i)) + '}' if i else '' } }}")
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_0(_struct_type, _typename, _name, _flags) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_1(_struct_type, _typename, _name, _flags, f1, v1) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slots = { v1, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_2(_struct_type, _typename, _name, _flags, f1, v1, f2, v2) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slots = { v1, v2, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_3(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slots = { v1, v2, v3, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_4(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slots = { v1, v2, v3, v4, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_5(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slots = { v1, v2, v3, v4, v5, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_6(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slots = { v1, v2, v3, v4, v5, v6, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_7(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slots = { v1, v2, v3, v4, v5, v6, v7, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_8(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_9(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_10(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_11(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, } }
|
||||
#define MP_DEFINE_CONST_OBJ_TYPE_NARGS_12(_struct_type, _typename, _name, _flags, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10, f11, v11, f12, v12) const _struct_type _typename = { .base = { &mp_type_type }, .flags = _flags, .name = _name, .slot_index_##f1 = 1, .slot_index_##f2 = 2, .slot_index_##f3 = 3, .slot_index_##f4 = 4, .slot_index_##f5 = 5, .slot_index_##f6 = 6, .slot_index_##f7 = 7, .slot_index_##f8 = 8, .slot_index_##f9 = 9, .slot_index_##f10 = 10, .slot_index_##f11 = 11, .slot_index_##f12 = 12, .slots = { v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, } }
|
||||
|
||||
// Because the mp_obj_type_t instances are in (zero-initialised) ROM, we take
|
||||
// slot_index_foo=0 to mean that the slot is unset. This also simplifies checking
|
||||
|
|
|
@ -424,6 +424,13 @@ static mp_obj_t array_extend(mp_obj_t self_in, mp_obj_t arg_in) {
|
|||
if (self->free < len) {
|
||||
self->items = m_renew(byte, self->items, (self->len + self->free) * sz, (self->len + len) * sz);
|
||||
self->free = 0;
|
||||
|
||||
if (self_in == arg_in) {
|
||||
// Get arg_bufinfo again in case self->items has moved
|
||||
//
|
||||
// (Note not possible to handle case that arg_in is a memoryview into self)
|
||||
mp_get_buffer_raise(arg_in, &arg_bufinfo, MP_BUFFER_READ);
|
||||
}
|
||||
} else {
|
||||
self->free -= len;
|
||||
}
|
||||
|
@ -456,7 +463,8 @@ static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
|||
#if MICROPY_PY_ARRAY_SLICE_ASSIGN
|
||||
// Assign
|
||||
size_t src_len;
|
||||
void *src_items;
|
||||
uint8_t *src_items;
|
||||
size_t src_offs = 0;
|
||||
size_t item_sz = mp_binary_get_size('@', o->typecode & TYPECODE_MASK, NULL);
|
||||
if (mp_obj_is_obj(value) && MP_OBJ_TYPE_GET_SLOT_OR_NULL(((mp_obj_base_t *)MP_OBJ_TO_PTR(value))->type, subscr) == array_subscr) {
|
||||
// value is array, bytearray or memoryview
|
||||
|
@ -469,7 +477,7 @@ static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
|||
src_items = src_slice->items;
|
||||
#if MICROPY_PY_BUILTINS_MEMORYVIEW
|
||||
if (mp_obj_is_type(value, &mp_type_memoryview)) {
|
||||
src_items = (uint8_t *)src_items + (src_slice->memview_offset * item_sz);
|
||||
src_offs = src_slice->memview_offset * item_sz;
|
||||
}
|
||||
#endif
|
||||
} else if (mp_obj_is_type(value, &mp_type_bytes)) {
|
||||
|
@ -504,13 +512,17 @@ static mp_obj_t array_subscr(mp_obj_t self_in, mp_obj_t index_in, mp_obj_t value
|
|||
// TODO: alloc policy; at the moment we go conservative
|
||||
o->items = m_renew(byte, o->items, (o->len + o->free) * item_sz, (o->len + len_adj) * item_sz);
|
||||
o->free = len_adj;
|
||||
// m_renew may have moved o->items
|
||||
if (src_items == dest_items) {
|
||||
src_items = o->items;
|
||||
}
|
||||
dest_items = o->items;
|
||||
}
|
||||
mp_seq_replace_slice_grow_inplace(dest_items, o->len,
|
||||
slice.start, slice.stop, src_items, src_len, len_adj, item_sz);
|
||||
slice.start, slice.stop, src_items + src_offs, src_len, len_adj, item_sz);
|
||||
} else {
|
||||
mp_seq_replace_slice_no_grow(dest_items, o->len,
|
||||
slice.start, slice.stop, src_items, src_len, item_sz);
|
||||
slice.start, slice.stop, src_items + src_offs, src_len, item_sz);
|
||||
// Clear "freed" elements at the end of list
|
||||
// TODO: This is actually only needed for typecode=='O'
|
||||
mp_seq_clear(dest_items, o->len + len_adj, o->len, item_sz);
|
||||
|
|
|
@ -56,14 +56,14 @@ void mp_obj_fun_bc_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest);
|
|||
#if MICROPY_EMIT_NATIVE
|
||||
|
||||
static inline mp_obj_t mp_obj_new_fun_native(const mp_obj_t *def_args, const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) {
|
||||
mp_obj_fun_bc_t *o = MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table));
|
||||
mp_obj_fun_bc_t *o = (mp_obj_fun_bc_t *)MP_OBJ_TO_PTR(mp_obj_new_fun_bc(def_args, (const byte *)fun_data, mc, child_table));
|
||||
o->base.type = &mp_type_fun_native;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
static inline mp_obj_t mp_obj_new_fun_viper(const void *fun_data, const mp_module_context_t *mc, struct _mp_raw_code_t *const *child_table) {
|
||||
mp_obj_fun_bc_t *o = mp_obj_malloc(mp_obj_fun_bc_t, &mp_type_fun_viper);
|
||||
o->bytecode = fun_data;
|
||||
o->bytecode = (const byte *)fun_data;
|
||||
o->context = mc;
|
||||
o->child_table = child_table;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
|
@ -101,9 +101,9 @@ static inline void *mp_obj_fun_native_get_generator_resume(const mp_obj_fun_bc_t
|
|||
|
||||
#if MICROPY_EMIT_INLINE_ASM
|
||||
static inline mp_obj_t mp_obj_new_fun_asm(size_t n_args, const void *fun_data, mp_uint_t type_sig) {
|
||||
mp_obj_fun_asm_t *o = mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm);
|
||||
mp_obj_fun_asm_t *o = (mp_obj_fun_asm_t *)mp_obj_malloc(mp_obj_fun_asm_t, &mp_type_fun_asm);
|
||||
o->n_args = n_args;
|
||||
o->fun_data = fun_data;
|
||||
o->fun_data = (const byte *)fun_data;
|
||||
o->type_sig = type_sig;
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
|
|
@ -15,4 +15,11 @@ print(b)
|
|||
|
||||
# this inplace add tests the code when the buffer doesn't need to be increased
|
||||
b = bytearray()
|
||||
b += b''
|
||||
b += b""
|
||||
|
||||
# extend a bytearray from itself
|
||||
b = bytearray(b"abcdefgh")
|
||||
for _ in range(4):
|
||||
c = bytearray(b) # extra allocation, as above
|
||||
b.extend(b)
|
||||
print(b)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# add a bytearray to itself
|
||||
# This is not supported by CPython as of 3.11.18.
|
||||
|
||||
b = bytearray(b"123456789")
|
||||
for _ in range(4):
|
||||
c = bytearray(b) # extra allocation increases chance 'b' has to relocate
|
||||
b += b
|
||||
print(b)
|
|
@ -0,0 +1 @@
|
|||
bytearray(b'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789')
|
|
@ -61,8 +61,14 @@ b[1:1] = b"12345"
|
|||
print(b)
|
||||
|
||||
# Growth of bytearray via slice extension
|
||||
b = bytearray(b'12345678')
|
||||
b = bytearray(b"12345678")
|
||||
b.append(57) # expand and add a bit of unused space at end of the bytearray
|
||||
for i in range(400):
|
||||
b[-1:] = b'ab' # grow slowly into the unused space
|
||||
b[-1:] = b"ab" # grow slowly into the unused space
|
||||
print(len(b), b)
|
||||
|
||||
# Growth of bytearray via slice extension from itself
|
||||
b = bytearray(b"1234567")
|
||||
for i in range(3):
|
||||
b[-1:] = b
|
||||
print(len(b), b)
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
"""
|
||||
categories: Types,memoryview
|
||||
description: memoryview can become invalid if its target is resized
|
||||
cause: CPython prevents a ``bytearray`` or ``io.bytesIO`` object from changing size while there is a ``memoryview`` object that references it. MicroPython requires the programmer to manually ensure that an object is not resized while any ``memoryview`` references it.
|
||||
|
||||
In the worst case scenario, resizing an object which is the target of a memoryview can cause the memoryview(s) to reference invalid freed memory (a use-after-free bug) and corrupt the MicroPython runtime.
|
||||
workaround: Do not change the size of any ``bytearray`` or ``io.bytesIO`` object that has a ``memoryview`` assigned to it.
|
||||
"""
|
||||
b = bytearray(b"abcdefg")
|
||||
m = memoryview(b)
|
||||
b.extend(b"hijklmnop")
|
||||
print(b, bytes(m))
|
Ładowanie…
Reference in New Issue