Skip to content

Commit 78fc43b

Browse files
committed
raspberrypi: Make port_idle_until_interrupt work
This needs thorough testing before it's merged, as we tried and reverted this once before (adafruit#5341 and adafruit#5356). I think that besides checking for tinyusb having "something to do", the fact that `port_interrupt_after_ticks` and `port_disable_tick` weren't implemented that was causing a secondary problem. I've tested this on a pico w over reboot-cycles and ctrl-c-cycles, with and without drive automounting, with and without serial repl open, and on a power-only connection. I didn't notice the problem reported in adafruit#5356 after merely implementing port_idle_until_interrupt; but I did notice that sleeps in general would take over-long until "something" (like writing to the USB drive) happened; I think "something" was probably calling port_enable_tick(). When this problem was happening, sleeps would take a lot longer; for instance, `sleep(.001)` would take about 1/20s and `sleep(.1)` would take about 1/7s.
1 parent f76351d commit 78fc43b

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

ports/raspberrypi/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ INC += \
127127
-I../shared/timeutils \
128128
-Iboards/$(BOARD) \
129129
-Iboards/ \
130+
-isystem ./../../lib/cmsis/inc \
130131
-isystem sdk/ \
131132
-isystem sdk/src/common/pico_base/include/ \
132133
-isystem sdk/src/common/pico_binary_info/include/ \

ports/raspberrypi/supervisor/port.c

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@
7272

7373
#include "supervisor/serial.h"
7474

75+
#include "tusb.h"
76+
#include <cmsis_compiler.h>
77+
7578
extern volatile bool mp_msc_enabled;
7679

7780
STATIC void _tick_callback(uint alarm_num);
@@ -241,38 +244,48 @@ uint32_t port_get_saved_word(void) {
241244
return __scratch_x_start__;
242245
}
243246

247+
static volatile bool ticks_enabled;
248+
244249
uint64_t port_get_raw_ticks(uint8_t *subticks) {
245250
uint64_t microseconds = time_us_64();
246251
return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977;
247252
}
248253

249254
STATIC void _tick_callback(uint alarm_num) {
250-
supervisor_tick();
251-
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
255+
if (ticks_enabled) {
256+
supervisor_tick();
257+
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
258+
}
252259
}
253260

254261
// Enable 1/1024 second tick.
255262
void port_enable_tick(void) {
263+
ticks_enabled = true;
256264
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
257265
}
258266

259267
// Disable 1/1024 second tick.
260268
void port_disable_tick(void) {
261-
// hardware_alarm_cancel(0);
269+
// One additional _tick_callback may occur, but it will just return
270+
// whenever !ticks_enabled. Cancel is not called just in case
271+
// it could nuke a timeout set by port_interrupt_after_ticks.
272+
ticks_enabled = false;
262273
}
263274

264275
// This is called by sleep, we ignore it when our ticks are enabled because
265276
// they'll wake us up earlier. If we don't, we'll mess up ticks by overwriting
266277
// the next RTC wake up time.
267278
void port_interrupt_after_ticks(uint32_t ticks) {
279+
if (!ticks_enabled) {
280+
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), ticks * 977));
281+
}
268282
}
269283

270284
void port_idle_until_interrupt(void) {
271285
common_hal_mcu_disable_interrupts();
272-
if (!background_callback_pending()) {
273-
// TODO: Does not work when board is power-cycled.
274-
// asm volatile ("dsb 0xF" ::: "memory");
275-
// __wfi();
286+
if (!background_callback_pending() && !tud_task_event_ready()) {
287+
__DSB();
288+
__WFI();
276289
}
277290
common_hal_mcu_enable_interrupts();
278291
}

0 commit comments

Comments
 (0)