Porównaj commity

...

19 Commity

Autor SHA1 Wiadomość Data
Jared Hancock dc5a6d54cc
Merge ed7ef9e48c into 49ce7a6075 2024-04-22 21:13:44 +08:00
Damien George 49ce7a6075 github/workflows: Run code size workflow on shared or port code changes.
To get more insight to firmware size changes when code changes.

Signed-off-by: Damien George <damien@micropython.org>
2024-04-22 12:38:29 +10:00
Angus Gratton 6877987002 tests/cpydiff: Add a note about risk of resizing memoryview targets.
This a stop-gap until there is a proper fix for this.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-04-22 11:51:18 +10:00
Angus Gratton 4bed614e70 py/objarray: Fix use-after-free if extending a bytearray from itself.
Two cases, one assigning to a slice.
Closes https://github.com/micropython/micropython/issues/13283

Second is extending a slice from itself, similar logic.

In both cases the problem occurs when m_renew causes realloc to move the
buffer, leaving a dangling pointer behind.

There are more complex and hard to fix cases when either argument is a
memoryview into the buffer, currently resizing to a new address breaks
memoryviews into that object.

Reproducing this bug and confirming the fix was done by running the unix
port under valgrind with GC-aware extensions.

Note in default configurations with GIL this bug exists but has no impact
(the free buffer won't be reused while the function is still executing, and
is no longer referenced after it returns).

Signed-off-by: Angus Gratton <angus@redyak.com.au>
2024-04-22 11:50:52 +10:00
Vonasmic ce491ab0d1 py/obj: Fix initialiser order in MP_DEFINE_CONST_OBJ_TYPE_NARGS_ macros.
This commit swaps the order of the `flags` and `name` struct initialisers
for `mp_obj_type_t`, to fix an incompatibility with C++.  The original
order of the initialiser didn't match the definition of the type, and
although that's still legal C, it's not legal C++.

Signed-off-by: Vonasmic <kasarkal123@gmail.com>
2024-04-22 11:10:23 +10:00
stijn 40f7e9ce20 py/objfun: Fix C++ compatibility with casting in inline functions.
Explicit casts are needed.

Fixes recent changes from 648a7578da and
9400229766.

Signed-off-by: stijn <stijn@ignitron.net>
2024-04-22 10:34:01 +10:00
Michiel W. Beijen 3129b69e0f rp2/README: Fix typo, improve sentence about building with other boards.
Signed-off-by: Michiel W. Beijen <mb@x14.nl>
2024-04-22 10:20:54 +10:00
Simon Wood 19844b4983 rp2/modmachine: Prevent lock-up when lightsleep() called within thread.
When `lightsleep()` is called from within a thread the interrupts may not
be enabled on current core, and thus the call to `lightsleep()` never
completes.

Fixes issue #14092.

Signed-off-by: Simon Wood <simon@mungewell.org>
2024-04-22 10:09:30 +10:00
J. Neuschäfer f76cf29402 github/workflows: Update coverage workflow to codecov-action@v4.
Fixes: https://github.com/micropython/micropython/issues/14340

Signed-off-by: J. Neuschäfer <j.ne@posteo.net>
2024-04-20 19:43:50 +02:00
Jared Hancock ed7ef9e48c wiznet5k: Fix reported formatting issues.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-15 21:57:10 -05:00
Jared Hancock 70190b0c75 wiznet5k: Technically ::send and ::recv is valid in CLOSE_WAIT state.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-15 21:42:45 -05:00
Jared Hancock fc03d95493 wiznet5k: dns: Support using dynamic socket number.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-15 21:42:36 -05:00
Jared Hancock b96f75cb95 wiznet5k: Support running DHCP in background and renewing address.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-15 21:42:32 -05:00
Jared Hancock 35763b3970 wiznet5k: Fix ambiguity with SOCK_BUSY return value.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:03:39 -05:00
Jared Hancock e9de433ecf wiznet5k: Add support for using interrupt without lwIP.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:03:33 -05:00
Jared Hancock c1b0c7eca3 wiznet5k: stm32: Add support for nonblocking and settimeout.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:03:25 -05:00
Jared Hancock 4364ad74ae wiznet5k: Add support for ::send on UDP sockets.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:03:17 -05:00
Jared Hancock 26d0ea4006 wiznet5k: Add support for read timeouts.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:03:09 -05:00
Jared Hancock 2e371503d6 wiznet5k: Add support for nonblocking and settimeout.
Signed-off-by: Jared Hancock <jared@greezybacon.me>
2024-04-07 18:02:38 -05:00
15 zmienionych plików z 405 dodań i 91 usunięć

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -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,22 +660,49 @@ static int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, m
return -1;
}
// now connect
MP_THREAD_GIL_EXIT();
mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port);
MP_THREAD_GIL_ENTER();
// 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);
MP_THREAD_GIL_ENTER();
if (ret < 0) {
wiznet5k_socket_close(socket);
*_errno = -ret;
return -1;
if (ret < 0) {
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
*_errno = MP_EINVAL;
return -1;
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) {
ret |= MP_STREAM_POLL_RD;
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(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 (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->fileno) != 0) {
ret |= MP_STREAM_POLL_WR;
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);

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

@ -0,0 +1 @@
bytearray(b'123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789')

Wyświetl plik

@ -18,7 +18,7 @@ l = bytearray(x)
l[1:3] = bytearray()
print(l)
l = bytearray(x)
#del l[1:3]
# del l[1:3]
print(l)
l = bytearray(x)
@ -28,7 +28,7 @@ l = bytearray(x)
l[:3] = bytearray()
print(l)
l = bytearray(x)
#del l[:3]
# del l[:3]
print(l)
l = bytearray(x)
@ -38,7 +38,7 @@ l = bytearray(x)
l[:-3] = bytearray()
print(l)
l = bytearray(x)
#del l[:-3]
# del l[:-3]
print(l)
# slice assignment that extends the array
@ -61,8 +61,14 @@ b[1:1] = b"12345"
print(b)
# Growth of bytearray via slice extension
b = bytearray(b'12345678')
b.append(57) # expand and add a bit of unused space at end of the bytearray
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)

Wyświetl plik

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