From 28529351aebe45c24e982eaecdba2383d05d2dd4 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 30 Nov 2023 14:34:07 +1100 Subject: [PATCH] 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 --- drivers/cyw43/cywbt.c | 4 ++-- drivers/ninaw10/nina_bt_hci.c | 5 +++-- ports/rp2/cyw43_configport.h | 3 ++- ports/rp2/machine_uart.c | 34 +++++++++++++++++++++------------- ports/rp2/mpconfigport.h | 21 +++++++++++---------- ports/rp2/mphalport.c | 29 +++++++++++++---------------- ports/rp2/rp2_flash.c | 11 +++++------ ports/rp2/rp2_pio.c | 4 ++-- 8 files changed, 59 insertions(+), 52 deletions(-) diff --git a/drivers/cyw43/cywbt.c b/drivers/cyw43/cywbt.c index d1b19382c5..3f454485ab 100644 --- a/drivers/cyw43/cywbt.c +++ b/drivers/cyw43/cywbt.c @@ -68,7 +68,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { mp_bluetooth_hci_uart_write((void *)buf, len); for (int c, i = 0; i < 6; ++i) { while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { - MICROPY_EVENT_POLL_HOOK + mp_event_wait_indefinite(); } buf[i] = c; } @@ -88,7 +88,7 @@ STATIC int cywbt_hci_cmd_raw(size_t len, uint8_t *buf) { int sz = buf[2] - 3; for (int c, i = 0; i < sz; ++i) { while ((c = mp_bluetooth_hci_uart_readchar()) == -1) { - MICROPY_EVENT_POLL_HOOK + mp_event_wait_indefinite(); } buf[i] = c; } diff --git a/drivers/ninaw10/nina_bt_hci.c b/drivers/ninaw10/nina_bt_hci.c index 754e99ed76..f0d1b9bc89 100644 --- a/drivers/ninaw10/nina_bt_hci.c +++ b/drivers/ninaw10/nina_bt_hci.c @@ -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). for (mp_uint_t start = mp_hal_ticks_ms(), size = 3, i = 0; i < size;) { while (!mp_bluetooth_hci_uart_any()) { - MICROPY_EVENT_POLL_HOOK + mp_uint_t elapsed = mp_hal_ticks_ms() - start; // Timeout. - if ((mp_hal_ticks_ms() - start) > HCI_COMMAND_TIMEOUT) { + if (elapsed > HCI_COMMAND_TIMEOUT) { error_printf("timeout waiting for HCI packet\n"); return -1; } + mp_event_wait_ms(HCI_COMMAND_TIMEOUT - elapsed); } buf[i] = mp_bluetooth_hci_uart_readchar(); diff --git a/ports/rp2/cyw43_configport.h b/ports/rp2/cyw43_configport.h index 96324ee5ec..b69cfbc263 100644 --- a/ports/rp2/cyw43_configport.h +++ b/ports/rp2/cyw43_configport.h @@ -30,6 +30,7 @@ #include "py/mpconfig.h" #include "py/mperrno.h" #include "py/mphal.h" +#include "py/runtime.h" #include "extmod/modnetwork.h" #include "pendsv.h" @@ -119,6 +120,6 @@ static inline void cyw43_delay_ms(uint32_t 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 diff --git a/ports/rp2/machine_uart.c b/ports/rp2/machine_uart.c index dae57012a8..e48924f09a 100644 --- a/ports/rp2/machine_uart.c +++ b/ports/rp2/machine_uart.c @@ -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) { machine_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; - uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; + mp_uint_t start = mp_hal_ticks_ms(); + mp_uint_t timeout = self->timeout; uint8_t *dest = buf_in; 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); 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) { *errcode = MP_EAGAIN; 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; } } - MICROPY_EVENT_POLL_HOOK + mp_event_wait_ms(timeout - elapsed); } *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; } 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); - uint64_t t = time_us_64() + (uint64_t)self->timeout * 1000; - uint64_t timeout_char_us = (uint64_t)self->timeout_char * 1000; + mp_uint_t start = mp_hal_ticks_ms(); + mp_uint_t timeout = self->timeout; const uint8_t *src = buf_in; 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) { // Wait for the first/next character to be sent. 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) { *errcode = MP_EAGAIN; 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; } } - MICROPY_EVENT_POLL_HOOK + mp_event_wait_ms(timeout - elapsed); } ringbuf_put(&(self->write_buffer), *src++); ++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); } @@ -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. uint64_t timeout = time_us_64() + (uint64_t)(33 + self->write_buffer.size) * 13000000ll * 2 / self->baudrate; - do { + while (1) { if (mp_machine_uart_txdone(self)) { return 0; } - MICROPY_EVENT_POLL_HOOK - } while (time_us_64() < timeout); + uint64_t now = time_us_64(); + if (now >= timeout) { + break; + } + mp_event_wait_ms((timeout - now) / 1000); + } *errcode = MP_ETIMEDOUT; ret = MP_STREAM_ERROR; } else { diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h index 5ff384c923..b349e0d67b 100644 --- a/ports/rp2/mpconfigport.h +++ b/ports/rp2/mpconfigport.h @@ -249,18 +249,19 @@ extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k; #define MICROPY_PY_LWIP_REENTER lwip_lock_acquire(); #define MICROPY_PY_LWIP_EXIT lwip_lock_release(); -#define MICROPY_EVENT_POLL_HOOK_FAST \ - do { \ - extern void mp_handle_pending(bool); \ - mp_handle_pending(true); \ +// 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 { \ + if ((TIMEOUT_MS) < 0) { \ + __wfe(); \ + } else { \ + best_effort_wfe_or_timeout(make_timeout_time_ms(TIMEOUT_MS)); \ + } \ } while (0) -#define MICROPY_EVENT_POLL_HOOK \ - do { \ - MICROPY_EVENT_POLL_HOOK_FAST; \ - __wfe(); \ - } while (0); - #define MICROPY_MAKE_POINTER_CALLABLE(p) ((void *)((mp_uint_t)(p) | 1)) #define MP_SSIZE_MAX (0x7fffffff) diff --git a/ports/rp2/mphalport.c b/ports/rp2/mphalport.c index 1fb833f2e5..1c784fd737 100644 --- a/ports/rp2/mphalport.c +++ b/ports/rp2/mphalport.c @@ -59,24 +59,17 @@ ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array) }; #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 uint8_t cdc_itf_pending; // keep track of cdc interfaces which need attention to poll 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? if (cdc_itf_pending && ringbuf_free(&stdin_ringbuf)) { for (uint8_t itf = 0; itf < 8; ++itf) { @@ -153,7 +146,7 @@ int mp_hal_stdin_rx_chr(void) { return dupterm_c; } #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; // Wait with a max of USC_CDC_TIMEOUT ms 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) { 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) { absolute_time_t t = make_timeout_time_ms(ms); do { - MICROPY_EVENT_POLL_HOOK_FAST; + mp_event_handle_nowait(); } while (!best_effort_wfe_or_timeout(t)); } diff --git a/ports/rp2/rp2_flash.c b/ports/rp2/rp2_flash.c index bc284cd976..b1afe1cbd1 100644 --- a/ports/rp2/rp2_flash.c +++ b/ports/rp2/rp2_flash.c @@ -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]); } 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 - // system. MICROPY_EVENT_POLL_HOOK_FAST calls tud_task(). As the alternative - // tud_task() should be called in the USB IRQ. See discussion in PR #10423. - MICROPY_EVENT_POLL_HOOK_FAST; + // system. mp_event_handle_nowait() will call the TinyUSB task if needed. + mp_event_handle_nowait(); return mp_const_none; } 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(); flash_range_erase(self->flash_base + offset, bufinfo.len); MICROPY_END_ATOMIC_SECTION(atomic_state); - MICROPY_EVENT_POLL_HOOK_FAST; + mp_event_handle_nowait(); // TODO check return value } else { 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(); flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len); MICROPY_END_ATOMIC_SECTION(atomic_state); - MICROPY_EVENT_POLL_HOOK_FAST; + mp_event_handle_nowait(); // TODO check return value return mp_const_none; } diff --git a/ports/rp2/rp2_pio.c b/ports/rp2/rp2_pio.c index 2e30475257..3a0ab844ea 100644 --- a/ports/rp2/rp2_pio.c +++ b/ports/rp2/rp2_pio.c @@ -729,7 +729,7 @@ STATIC mp_obj_t rp2_state_machine_get(size_t n_args, const mp_obj_t *args) { for (;;) { while (pio_sm_is_rx_fifo_empty(self->pio, self->sm)) { // 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; 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)) { // This delay must be fast. - MICROPY_EVENT_POLL_HOOK_FAST; + mp_event_handle_nowait(); } pio_sm_put(self->pio, self->sm, value << shift); }