Skip to content

Commit

Permalink
raspberrypi: Make port_idle_until_interrupt work
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jepler committed Nov 12, 2022
1 parent f76351d commit 78fc43b
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 7 deletions.
1 change: 1 addition & 0 deletions ports/raspberrypi/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ INC += \
-I../shared/timeutils \
-Iboards/$(BOARD) \
-Iboards/ \
-isystem ./../../lib/cmsis/inc \
-isystem sdk/ \
-isystem sdk/src/common/pico_base/include/ \
-isystem sdk/src/common/pico_binary_info/include/ \
Expand Down
27 changes: 20 additions & 7 deletions ports/raspberrypi/supervisor/port.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@

#include "supervisor/serial.h"

#include "tusb.h"
#include <cmsis_compiler.h>

extern volatile bool mp_msc_enabled;

STATIC void _tick_callback(uint alarm_num);
Expand Down Expand Up @@ -241,38 +244,48 @@ uint32_t port_get_saved_word(void) {
return __scratch_x_start__;
}

static volatile bool ticks_enabled;

uint64_t port_get_raw_ticks(uint8_t *subticks) {
uint64_t microseconds = time_us_64();
return 1024 * (microseconds / 1000000) + (microseconds % 1000000) / 977;
}

STATIC void _tick_callback(uint alarm_num) {
supervisor_tick();
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
if (ticks_enabled) {
supervisor_tick();
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}
}

// Enable 1/1024 second tick.
void port_enable_tick(void) {
ticks_enabled = true;
hardware_alarm_set_target(0, delayed_by_us(get_absolute_time(), 977));
}

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

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

void port_idle_until_interrupt(void) {
common_hal_mcu_disable_interrupts();
if (!background_callback_pending()) {
// TODO: Does not work when board is power-cycled.
// asm volatile ("dsb 0xF" ::: "memory");
// __wfi();
if (!background_callback_pending() && !tud_task_event_ready()) {
__DSB();
__WFI();
}
common_hal_mcu_enable_interrupts();
}
Expand Down

0 comments on commit 78fc43b

Please sign in to comment.