rp2: Switch rp2 and drivers to use new event functions.

This commit changes all uses in the rp2 port, and drivers that are
optionally supported by that port.

The old MICROPY_EVENT_POLL_HOOK and MICROPY_EVENT_POLL_HOOK_FAST macros are
no longer used for rp2 builds and are removed (C user code will need to be
changed to suit).

Also take the opportunity to change some timeouts that used 64-bit
arithmetic to 32-bit, to hopefully claw back a little code size.

This work was funded through GitHub Sponsors.

Signed-off-by: Angus Gratton <angus@redyak.com.au>
This commit is contained in:
Angus Gratton 2023-11-30 14:34:07 +11:00 committed by Damien George
parent df3948d3c2
commit 28529351ae
8 changed files with 59 additions and 52 deletions

View File

@ -68,7 +68,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
mp_bluetooth_hci_uart_write((void *)buf, len); mp_bluetooth_hci_uart_write((void *)buf, len);
for (int c, i = 0; i < 6; ++i) { for (int c, i = 0; i < 6; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK mp_event_wait_indefinite();
} }
buf[i] = c; buf[i] = c;
} }
@ -88,7 +88,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) {
int sz = buf[2] - 3; int sz = buf[2] - 3;
for (int c, i = 0; i < sz; ++i) { for (int c, i = 0; i < sz; ++i) {
while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { while ((c = mp_bluetooth_hci_uart_readchar()) == -1) {
MICROPY_EVENT_POLL_HOOK mp_event_wait_indefinite();
} }
buf[i] = c; buf[i] = c;
} }

View File

@ -75,12 +75,13 @@ static int nina_hci_cmd(int ogf, int ocf, size_t param_len, const uint8_t *param
// Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen). // Receive HCI event packet, initially reading 3 bytes (HCI Event, Event code, Plen).
for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) { for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) {
while (!mp_bluetooth_hci_uart_any()) { while (!mp_bluetooth_hci_uart_any()) {
MICROPY_EVENT_POLL_HOOK mp_uint_t elapsed = mp_hal_ticks_ms() - start;
// Timeout. // Timeout.
if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) { if (elapsed > HCI_COMMAND_TIMEOUT) {
error_printf("timeout waiting for HCI packet\n"); error_printf("timeout waiting for HCI packet\n");
return -1; return -1;
} }
mp_event_wait_ms(HCI_COMMAND_TIMEOUT - elapsed);
} }
buf[i] = mp_bluetooth_hci_uart_readchar(); buf[i] = mp_bluetooth_hci_uart_readchar();

View File

@ -30,6 +30,7 @@
#include "py/mpconfig.h" #include "py/mpconfig.h"
#include "py/mperrno.h" #include "py/mperrno.h"
#include "py/mphal.h" #include "py/mphal.h"
#include "py/runtime.h"
#include "extmod/modnetwork.h" #include "extmod/modnetwork.h"
#include "pendsv.h" #include "pendsv.h"
@ -119,6 +120,6 @@ static inline void cyw43_delay_ms(uint32_t ms) {
mp_hal_delay_ms(ms); mp_hal_delay_ms(ms);
} }
#define CYW43_EVENT_POLL_HOOK MICROPY_EVENT_POLL_HOOK_FAST #define CYW43_EVENT_POLL_HOOK mp_event_handle_nowait()
#endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H #endif // MICROPY_INCLUDED_RP2_CYW43_CONFIGPORT_H

View File

@ -454,8 +454,8 @@ STATIC void mp_machine_uart_sendbreak(machine_uart_obj_t *self) {
STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) { STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; mp_uint_t start = mp_hal_ticks_ms();
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; mp_uint_t timeout = self->timeout;
uint8_t *dest = buf_in; uint8_t *dest = buf_in;
for (size_t i = 0; i < size; i++) { for (size_t i = 0; i < size; i++) {
@ -466,7 +466,8 @@ STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
uart_drain_rx_fifo(self); uart_drain_rx_fifo(self);
break; break;
} }
if (time_us_64() > t) { // timed out mp_uint_t elapsed = mp_hal_ticks_ms() - start;
if (elapsed > timeout) { // timed out
if (i <= 0) { if (i <= 0) {
*errcode = MP_EAGAIN; *errcode = MP_EAGAIN;
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
@ -474,18 +475,19 @@ STATIC mp_uint_t mp_machine_uart_read(mp_obj_t self_in, void *buf_in, mp_uint_t
return i; return i;
} }
} }
MICROPY_EVENT_POLL_HOOK mp_event_wait_ms(timeout - elapsed);
} }
*dest++ = ringbuf_get(&(self->read_buffer)); *dest++ = ringbuf_get(&(self->read_buffer));
t = time_us_64() + timeout_char_us; start = mp_hal_ticks_ms(); // Inter-character timeout
timeout = self->timeout_char;
} }
return size; return size;
} }
STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) { STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_uint_t size, int *errcode) {
machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in);
uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; mp_uint_t start = mp_hal_ticks_ms();
uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; mp_uint_t timeout = self->timeout;
const uint8_t *src = buf_in; const uint8_t *src = buf_in;
size_t i = 0; size_t i = 0;
@ -502,7 +504,8 @@ STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
while (i < size) { while (i < size) {
// Wait for the first/next character to be sent. // Wait for the first/next character to be sent.
while (ringbuf_free(&(self->write_buffer)) == 0) { while (ringbuf_free(&(self->write_buffer)) == 0) {
if (time_us_64() > t) { // timed out mp_uint_t elapsed = mp_hal_ticks_ms() - start;
if (elapsed > timeout) { // timed out
if (i <= 0) { if (i <= 0) {
*errcode = MP_EAGAIN; *errcode = MP_EAGAIN;
return MP_STREAM_ERROR; return MP_STREAM_ERROR;
@ -510,11 +513,12 @@ STATIC mp_uint_t mp_machine_uart_write(mp_obj_t self_in, const void *buf_in, mp_
return i; return i;
} }
} }
MICROPY_EVENT_POLL_HOOK mp_event_wait_ms(timeout - elapsed);
} }
ringbuf_put(&(self->write_buffer), *src++); ringbuf_put(&(self->write_buffer), *src++);
++i; ++i;
t = time_us_64() + timeout_char_us; start = mp_hal_ticks_ms(); // Inter-character timeout
timeout = self->timeout_char;
uart_fill_tx_fifo(self); uart_fill_tx_fifo(self);
} }
@ -539,12 +543,16 @@ STATIC mp_uint_t mp_machine_uart_ioctl(mp_obj_t self_in, mp_uint_t request, uint
// Take the worst case assumptions at 13 bit symbol size times 2. // Take the worst case assumptions at 13 bit symbol size times 2.
uint64_t timeout = time_us_64() + uint64_t timeout = time_us_64() +
(uint64_t)(33 + self->write_buffer.size) * 13000000ll * 2 / self->baudrate; (uint64_t)(33 + self->write_buffer.size) * 13000000ll * 2 / self->baudrate;
do { while (1) {
if (mp_machine_uart_txdone(self)) { if (mp_machine_uart_txdone(self)) {
return 0; return 0;
} }
MICROPY_EVENT_POLL_HOOK uint64_t now = time_us_64();
} while (time_us_64() < timeout); if (now >= timeout) {
break;
}
mp_event_wait_ms((timeout - now) / 1000);
}
*errcode = MP_ETIMEDOUT; *errcode = MP_ETIMEDOUT;
ret = MP_STREAM_ERROR; ret = MP_STREAM_ERROR;
} else { } else {

View File

@ -249,17 +249,18 @@ extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
#define MICROPY_PY_LWIP_REENTER lwip_lock_acquire(); #define MICROPY_PY_LWIP_REENTER lwip_lock_acquire();
#define MICROPY_PY_LWIP_EXIT lwip_lock_release(); #define MICROPY_PY_LWIP_EXIT lwip_lock_release();
#define MICROPY_EVENT_POLL_HOOK_FAST \ // Port level Wait-for-Event macro
//
// Do not use this macro directly, include py/runtime.h and
// call mp_event_wait_indefinite() or mp_event_wait_ms(timeout)
#define MICROPY_INTERNAL_WFE(TIMEOUT_MS) \
do { \ do { \
extern void mp_handle_pending(bool); \ if ((TIMEOUT_MS) < 0) { \
mp_handle_pending(true); \
} while (0)
#define MICROPY_EVENT_POLL_HOOK \
do { \
MICROPY_EVENT_POLL_HOOK_FAST; \
__wfe(); \ __wfe(); \
} while (0); } else { \
best_effort_wfe_or_timeout(make_timeout_time_ms(TIMEOUT_MS)); \
} \
} while (0)
#define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1))

View File

@ -59,24 +59,17 @@ ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) };
#endif #endif
#if MICROPY_HW_USB_CDC
// Explicitly run the USB stack in case the scheduler is locked (eg we are in an
// interrupt handler) and there is in/out data pending on the USB CDC interface.
#define MICROPY_EVENT_POLL_HOOK_WITH_USB \
do { \
MICROPY_EVENT_POLL_HOOK; \
mp_usbd_task(); \
} while (0)
#else
#define MICROPY_EVENT_POLL_HOOK_WITH_USB MICROPY_EVENT_POLL_HOOK
#endif
#if MICROPY_HW_USB_CDC #if MICROPY_HW_USB_CDC
uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll
void poll_cdc_interfaces(void) { void poll_cdc_interfaces(void) {
if (!cdc_itf_pending) {
// Explicitly run the USB stack as the scheduler may be locked (eg we are in
// an interrupt handler) while there is data pending.
mp_usbd_task();
}
// any CDC interfaces left to poll? // any CDC interfaces left to poll?
if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) { if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) {
for (uint8_t itf = 0; itf < 8; ++itf) { for (uint8_t itf = 0; itf < 8; ++itf) {
@ -153,7 +146,7 @@ int mp_hal_stdin_rx_chr(void) {
return dupterm_c; return dupterm_c;
} }
#endif #endif
MICROPY_EVENT_POLL_HOOK_WITH_USB; mp_event_wait_indefinite();
} }
} }
@ -173,7 +166,11 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
int timeout = 0; int timeout = 0;
// Wait with a max of USC_CDC_TIMEOUT ms // Wait with a max of USC_CDC_TIMEOUT ms
while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) { while (n > tud_cdc_write_available() && timeout++ < MICROPY_HW_USB_CDC_TX_TIMEOUT) {
MICROPY_EVENT_POLL_HOOK_WITH_USB; mp_event_wait_ms(1);
// Explicitly run the USB stack as the scheduler may be locked (eg we
// are in an interrupt handler), while there is data pending.
mp_usbd_task();
} }
if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) { if (timeout >= MICROPY_HW_USB_CDC_TX_TIMEOUT) {
break; break;
@ -193,7 +190,7 @@ void mp_hal_stdout_tx_strn(const char *str, mp_uint_t len) {
void mp_hal_delay_ms(mp_uint_t ms) { void mp_hal_delay_ms(mp_uint_t ms) {
absolute_time_t t = make_timeout_time_ms(ms); absolute_time_t t = make_timeout_time_ms(ms);
do { do {
MICROPY_EVENT_POLL_HOOK_FAST; mp_event_handle_nowait();
} while (!best_effort_wfe_or_timeout(t)); } while (!best_effort_wfe_or_timeout(t));
} }

View File

@ -121,11 +121,10 @@ STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) {
offset += mp_obj_get_int(args[3]); offset += mp_obj_get_int(args[3]);
} }
memcpy(bufinfo.buf, (void *)(XIP_BASE + self->flash_base + offset), bufinfo.len); memcpy(bufinfo.buf, (void *)(XIP_BASE + self->flash_base + offset), bufinfo.len);
// MICROPY_EVENT_POLL_HOOK_FAST is called here to avoid a fail in registering // mp_event_handle_nowait() is called here to avoid a fail in registering
// USB at boot time, if the board is busy loading files or scanning the file // USB at boot time, if the board is busy loading files or scanning the file
// system. MICROPY_EVENT_POLL_HOOK_FAST calls tud_task(). As the alternative // system. mp_event_handle_nowait() will call the TinyUSB task if needed.
// tud_task() should be called in the USB IRQ. See discussion in PR #10423. mp_event_handle_nowait();
MICROPY_EVENT_POLL_HOOK_FAST;
return mp_const_none; return mp_const_none;
} }
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_flash_readblocks_obj, 3, 4, rp2_flash_readblocks); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_flash_readblocks_obj, 3, 4, rp2_flash_readblocks);
@ -140,7 +139,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
flash_range_erase(self->flash_base + offset, bufinfo.len); flash_range_erase(self->flash_base + offset, bufinfo.len);
MICROPY_END_ATOMIC_SECTION(atomic_state); MICROPY_END_ATOMIC_SECTION(atomic_state);
MICROPY_EVENT_POLL_HOOK_FAST; mp_event_handle_nowait();
// TODO check return value // TODO check return value
} else { } else {
offset += mp_obj_get_int(args[3]); offset += mp_obj_get_int(args[3]);
@ -149,7 +148,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION(); mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len); flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len);
MICROPY_END_ATOMIC_SECTION(atomic_state); MICROPY_END_ATOMIC_SECTION(atomic_state);
MICROPY_EVENT_POLL_HOOK_FAST; mp_event_handle_nowait();
// TODO check return value // TODO check return value
return mp_const_none; return mp_const_none;
} }

View File

@ -729,7 +729,7 @@ STATIC mp_obj_t rp2_state_machine_get(size_t n_args, const mp_obj_t *args) {
for (;;) { for (;;) {
while (pio_sm_is_rx_fifo_empty(self->pio, self->sm)) { while (pio_sm_is_rx_fifo_empty(self->pio, self->sm)) {
// This delay must be fast. // This delay must be fast.
MICROPY_EVENT_POLL_HOOK_FAST; mp_event_handle_nowait();
} }
uint32_t value = pio_sm_get(self->pio, self->sm) >> shift; uint32_t value = pio_sm_get(self->pio, self->sm) >> shift;
if (dest == NULL) { if (dest == NULL) {
@ -787,7 +787,7 @@ STATIC mp_obj_t rp2_state_machine_put(size_t n_args, const mp_obj_t *args) {
} }
while (pio_sm_is_tx_fifo_full(self->pio, self->sm)) { while (pio_sm_is_tx_fifo_full(self->pio, self->sm)) {
// This delay must be fast. // This delay must be fast.
MICROPY_EVENT_POLL_HOOK_FAST; mp_event_handle_nowait();
} }
pio_sm_put(self->pio, self->sm, value << shift); pio_sm_put(self->pio, self->sm, value << shift);
} }