Skip to content

Commit 971407a

Browse files
andrewleechpi-anl
authored andcommitted
nrf/nimble: Use soft timer for hci polling.
Signed-off-by: Andrew Leech <[email protected]>
1 parent 7618e92 commit 971407a

File tree

3 files changed

+79
-29
lines changed

3 files changed

+79
-29
lines changed

ports/nrf/mpbthciport.c

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,53 +29,92 @@
2929
#include "py/runtime.h"
3030
#include "py/mperrno.h"
3131
#include "py/mphal.h"
32+
#include "shared/runtime/softtimer.h"
3233

3334
#if MICROPY_PY_BLUETOOTH
3435

3536
#define DEBUG_printf(...) // mp_printf(&mp_plat_print, "mpbthciport.c: " __VA_ARGS__)
3637

3738
#include "mpbthciport.h"
38-
#include "drivers/ticker.h"
39+
// #include "drivers/ticker.h"
3940

40-
#define BLUETOOTH_TICKER_SLOT 0
41+
// #define BLUETOOTH_TICKER_SLOT 0
42+
43+
// Soft timer and scheduling node for scheduling a HCI poll.
44+
static soft_timer_entry_t mp_bluetooth_hci_soft_timer;
45+
static mp_sched_node_t mp_bluetooth_hci_sched_node;
46+
47+
48+
// This is called by soft_timer and executes at PendSV level.
49+
static void mp_bluetooth_hci_soft_timer_callback(soft_timer_entry_t *self) {
50+
mp_bluetooth_hci_poll_now();
51+
}
4152

4253
// // Prevent double-enqueuing of the scheduled task.
43-
static volatile bool events_task_is_scheduled = false;
54+
// static volatile bool events_task_is_scheduled = false;
4455

4556
void mp_bluetooth_hci_init(void) {
4657
/* Start regular background task to handle events */
47-
events_task_is_scheduled = false;
48-
set_ticker_callback(BLUETOOTH_TICKER_SLOT, mp_bluetooth_hci_poll_now, 0);
58+
// events_task_is_scheduled = false;
59+
// set_ticker_callback(BLUETOOTH_TICKER_SLOT, mp_bluetooth_hci_poll_now, 0);
60+
soft_timer_static_init(
61+
&mp_bluetooth_hci_soft_timer,
62+
SOFT_TIMER_MODE_ONE_SHOT,
63+
0,
64+
mp_bluetooth_hci_soft_timer_callback
65+
);
4966
}
5067

5168
void mp_bluetooth_hci_deinit(void) {
52-
clear_ticker_callback(BLUETOOTH_TICKER_SLOT);
53-
events_task_is_scheduled = false;
69+
// clear_ticker_callback(BLUETOOTH_TICKER_SLOT);
70+
// events_task_is_scheduled = false;
71+
soft_timer_remove(&mp_bluetooth_hci_soft_timer);
72+
73+
}
74+
75+
// // For synchronous mode, we run all BLE stack code inside a scheduled task.
76+
// // This task is scheduled periodically via a timer.
77+
// static mp_obj_t run_events_scheduled_task(mp_obj_t none_in) {
78+
// (void)none_in;
79+
// events_task_is_scheduled = false;
80+
// mp_bluetooth_hci_poll();
81+
// return mp_const_none;
82+
// }
83+
// static MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task);
84+
85+
86+
// // Called periodically (ticker) to request that processing happens in the scheduler.
87+
// int32_t mp_bluetooth_hci_poll_now(void) {
88+
// // Return interval (128ms in 16us ticks) until next callback run
89+
// uint32_t next_tick = 128000 / 16;
90+
// if (!events_task_is_scheduled) {
91+
// events_task_is_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&run_events_scheduled_task_obj), mp_const_none);
92+
// if (!events_task_is_scheduled) {
93+
// // The schedule queue is full, set callback to try again soon (5ms).
94+
// next_tick = 5000 / 16;
95+
// }
96+
// }
97+
// return next_tick;
98+
// }
99+
100+
// static void mp_bluetooth_hci_start_polling(void) {
101+
// mp_bluetooth_hci_poll_now();
102+
// }
103+
104+
void mp_bluetooth_hci_poll_in_ms(uint32_t ms) {
105+
soft_timer_reinsert(&mp_bluetooth_hci_soft_timer, ms);
54106
}
55107

56108
// For synchronous mode, we run all BLE stack code inside a scheduled task.
57-
// This task is scheduled periodically via a timer.
58-
static mp_obj_t run_events_scheduled_task(mp_obj_t none_in) {
59-
(void)none_in;
60-
events_task_is_scheduled = false;
109+
static void run_events_scheduled_task(mp_sched_node_t *node) {
110+
// This will process all buffered HCI UART data, and run any callouts or events.
61111
mp_bluetooth_hci_poll();
62-
return mp_const_none;
63112
}
64-
static MP_DEFINE_CONST_FUN_OBJ_1(run_events_scheduled_task_obj, run_events_scheduled_task);
65-
66-
67-
// Called periodically (ticker) to request that processing happens in the scheduler.
68-
int32_t mp_bluetooth_hci_poll_now(void) {
69-
// Return interval (128ms in 16us ticks) until next callback run
70-
uint32_t next_tick = 128000 / 16;
71-
if (!events_task_is_scheduled) {
72-
events_task_is_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&run_events_scheduled_task_obj), mp_const_none);
73-
if (!events_task_is_scheduled) {
74-
// The schedule queue is full, set callback to try again soon (5ms).
75-
next_tick = 5000 / 16;
76-
}
77-
}
78-
return next_tick;
113+
114+
// Called periodically (systick) or directly (e.g. UART RX IRQ) in order to
115+
// request that processing happens ASAP in the scheduler.
116+
void mp_bluetooth_hci_poll_now(void) {
117+
mp_sched_schedule_node(&mp_bluetooth_hci_sched_node, run_events_scheduled_task);
79118
}
80119

81120
#endif // MICROPY_PY_BLUETOOTH

ports/nrf/mpbthciport.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@
3030
void mp_bluetooth_hci_init(void);
3131
void mp_bluetooth_hci_deinit(void);
3232

33-
// Poll the HCI now.
34-
int32_t mp_bluetooth_hci_poll_now(void);
33+
// Poll the HCI now, or after a certain timeout.
34+
void mp_bluetooth_hci_poll_now(void);
35+
void mp_bluetooth_hci_poll_in_ms(uint32_t ms);
3536

3637
// Must be provided by the stack bindings (e.g. mpnimbleport.c or mpbtstackport.c).
3738
// Request new HCI data and pass to the stack, and run pending events/callouts.

ports/nrf/mpnimbleport.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ void mp_bluetooth_hci_controller_init(void) {
6161

6262
// Tell the host that we are ready to receive packets
6363
ble_ll_hci_send_noop();
64+
65+
// Start polling for date.
66+
mp_bluetooth_hci_poll_now();
6467
}
6568

6669
void mp_bluetooth_hci_controller_deinit(void) {
6770
mp_bluetooth_hci_deinit();
71+
6872
}
6973

7074
// The global BLE controller LL data object
@@ -92,6 +96,11 @@ void mp_bluetooth_hci_poll(void) {
9296
// Run any remaining events.
9397
mp_bluetooth_nimble_os_eventq_run_all();
9498
}
99+
if (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) {
100+
// Call this function again in 128ms to check for new events.
101+
// TODO: improve this by only calling back when needed.
102+
mp_bluetooth_hci_poll_in_ms(128);
103+
}
95104
}
96105

97106
// --- Port-specific helpers for the generic NimBLE bindings. -----------------
@@ -123,6 +132,7 @@ static func nrf_ble_isr_rtc0 = NULL;
123132
void RADIO_IRQHandler(void) {
124133
if (nrf_ble_isr_phy != NULL) {
125134
nrf_ble_isr_phy();
135+
mp_bluetooth_hci_poll_in_ms(5);
126136
}
127137
}
128138

0 commit comments

Comments
 (0)