nrf/nimble: Use soft timer for hci polling.

Signed-off-by: Andrew Leech <andrew@alelec.net>
pull/8318/head
Andrew Leech 2024-03-27 08:08:21 +11:00
rodzic 6ff6468968
commit 0b200ce34e
3 zmienionych plików z 78 dodań i 28 usunięć

Wyświetl plik

@ -29,53 +29,92 @@
#include "py/runtime.h"
#include "py/mperrno.h"
#include "py/mphal.h"
#include "shared/runtime/softtimer.h"
#if MICROPY_PY_BLUETOOTH
#define DEBUG_printf(...) // mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__)
#include "mpbthciport.h"
#include "drivers/ticker.h"
// #include "drivers/ticker.h"
#define BLUETOOTH_TICKER_SLOT 0
// #define BLUETOOTH_TICKER_SLOT 0
// Soft timer and scheduling node for scheduling a HCI poll.
static soft_timer_entry_t mp_bluetooth_hci_soft_timer;
static mp_sched_node_t mp_bluetooth_hci_sched_node;
// This is called by soft_timer and executes at PendSV level.
static void mp_bluetooth_hci_soft_timer_callback(soft_timer_entry_t *self) {
mp_bluetooth_hci_poll_now();
}
// // Prevent double-enqueuing of the scheduled task.
static volatile bool events_task_is_scheduled = false;
// static volatile bool events_task_is_scheduled = false;
void mp_bluetooth_hci_init(void) {
/* Start regular background task to handle events */
events_task_is_scheduled = false;
set_ticker_callback(BLUETOOTH_TICKER_SLOT, mp_bluetooth_hci_poll_now, 0);
// events_task_is_scheduled = false;
// set_ticker_callback(BLUETOOTH_TICKER_SLOT, mp_bluetooth_hci_poll_now, 0);
soft_timer_static_init(
&mp_bluetooth_hci_soft_timer,
SOFT_TIMER_MODE_ONE_SHOT,
0,
mp_bluetooth_hci_soft_timer_callback
);
}
void mp_bluetooth_hci_deinit(void) {
clear_ticker_callback(BLUETOOTH_TICKER_SLOT);
events_task_is_scheduled = false;
// clear_ticker_callback(BLUETOOTH_TICKER_SLOT);
// events_task_is_scheduled = false;
soft_timer_remove(&mp_bluetooth_hci_soft_timer);
}
// // For synchronous mode, we run all BLE stack code inside a scheduled task.
// // This task is scheduled periodically via a timer.
// static mp_obj_t run_events_scheduled_task(mp_obj_t none_in) {
// (void)none_in;
// events_task_is_scheduled = false;
// mp_bluetooth_hci_poll();
// return mp_const_none;
// }
// static MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task);
// // Called periodically (ticker) to request that processing happens in the scheduler.
// int32_t mp_bluetooth_hci_poll_now(void) {
// // Return interval (128ms in 16us ticks) until next callback run
// uint32_t next_tick = 128000 / 16;
// if (!events_task_is_scheduled) {
// events_task_is_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&run_events_scheduled_task_obj), mp_const_none);
// if (!events_task_is_scheduled) {
// // The schedule queue is full, set callback to try again soon (5ms).
// next_tick = 5000 / 16;
// }
// }
// return next_tick;
// }
// static void mp_bluetooth_hci_start_polling(void) {
// mp_bluetooth_hci_poll_now();
// }
void mp_bluetooth_hci_poll_in_ms(uint32_t ms) {
soft_timer_reinsert(&mp_bluetooth_hci_soft_timer, ms);
}
// For synchronous mode, we run all BLE stack code inside a scheduled task.
// This task is scheduled periodically via a timer.
static mp_obj_t run_events_scheduled_task(mp_obj_t none_in) {
(void)none_in;
events_task_is_scheduled = false;
static void run_events_scheduled_task(mp_sched_node_t *node) {
// This will process all buffered HCI UART data, and run any callouts or events.
mp_bluetooth_hci_poll();
return mp_const_none;
}
static MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task);
// Called periodically (ticker) to request that processing happens in the scheduler.
int32_t mp_bluetooth_hci_poll_now(void) {
// Return interval (128ms in 16us ticks) until next callback run
uint32_t next_tick = 128000 / 16;
if (!events_task_is_scheduled) {
events_task_is_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&run_events_scheduled_task_obj), mp_const_none);
if (!events_task_is_scheduled) {
// The schedule queue is full, set callback to try again soon (5ms).
next_tick = 5000 / 16;
}
}
return next_tick;
// Called periodically (systick) or directly (e.g. UART RX IRQ) in order to
// request that processing happens ASAP in the scheduler.
void mp_bluetooth_hci_poll_now(void) {
mp_sched_schedule_node(&mp_bluetooth_hci_sched_node, run_events_scheduled_task);
}
#endif // MICROPY_PY_BLUETOOTH

Wyświetl plik

@ -30,8 +30,9 @@
void mp_bluetooth_hci_init(void);
void mp_bluetooth_hci_deinit(void);
// Poll the HCI now.
int32_t mp_bluetooth_hci_poll_now(void);
// Poll the HCI now, or after a certain timeout.
void mp_bluetooth_hci_poll_now(void);
void mp_bluetooth_hci_poll_in_ms(uint32_t ms);
// Must be provided by the stack bindings (e.g. mpnimbleport.c or mpbtstackport.c).
// Request new HCI data and pass to the stack, and run pending events/callouts.

Wyświetl plik

@ -61,10 +61,14 @@ void mp_bluetooth_hci_controller_init(void) {
// Tell the host that we are ready to receive packets
ble_ll_hci_send_noop();
// Start polling for date.
mp_bluetooth_hci_poll_now();
}
void mp_bluetooth_hci_controller_deinit(void) {
mp_bluetooth_hci_deinit();
}
// The global BLE controller LL data object
@ -92,6 +96,11 @@ void mp_bluetooth_hci_poll(void) {
// Run any remaining events.
mp_bluetooth_nimble_os_eventq_run_all();
}
if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
// Call this function again in 128ms to check for new events.
// TODO: improve this by only calling back when needed.
mp_bluetooth_hci_poll_in_ms(128);
}
}
// --- Port-specific helpers for the generic NimBLE bindings. -----------------
@ -123,6 +132,7 @@ static func nrf_ble_isr_rtc0 = NULL;
void RADIO_IRQHandler(void) {
if (nrf_ble_isr_phy != NULL) {
nrf_ble_isr_phy();
mp_bluetooth_hci_poll_in_ms(5);
}
}