Supervisor: move most of systick to the supervisor

This code is shared by most parts, except where not all the #ifdefs
inside the tick function were present in all ports.  This mostly would
have broken gamepad tick support on non-samd ports.

The "ms32" and "ms64" variants of the tick functions are introduced
because there is no 64-bit atomic read.  Disabling interrupts avoids
a low probability bug where milliseconds could be off by ~49.5 days
once every ~49.5 days (2^32 ms).

Avoiding disabling interrupts when only the low 32 bits are needed is a minor
optimization.

Testing performed: on metro m4 express, USB still works and
time.monotonic_ns() still counts up
This commit is contained in:
Jeff Epler 2019-11-18 08:22:41 -06:00
parent 45d1b290ee
commit 7f744a2369
37 changed files with 214 additions and 163 deletions

View File

@ -52,7 +52,7 @@
#include <string.h>
#include <stdlib.h>
#include "tick.h"
#include "supervisor/shared/tick.h"
//#include "Ethernet/socket.h"
//#include "Internet/DNS/dns.h"
@ -125,7 +125,7 @@ uint16_t DNS_MSGID; // DNS message ID
uint32_t HAL_GetTick(void) {
return ticks_ms;
return supervisor_ticks_ms32();
}
uint32_t hal_sys_tick;

View File

@ -28,6 +28,7 @@
#include "audio_dma.h"
#include "tick.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "py/runtime.h"
@ -71,9 +72,9 @@ void run_background_tasks(void) {
running_background_tasks = false;
assert_heap_ok();
last_finished_tick = ticks_ms;
last_finished_tick = supervisor_ticks_ms64();
}
bool background_tasks_ok(void) {
return ticks_ms - last_finished_tick < 1000;
return supervisor_ticks_ms64() - last_finished_tick < 1000;
}

View File

@ -34,8 +34,7 @@
#include "py/runtime.h"
#include "py/stream.h"
#include "supervisor/shared/translate.h"
#include "tick.h"
#include "supervisor/shared/tick.h"
#include "hpl_sercom_config.h"
#include "peripheral_clk_config.h"
@ -272,10 +271,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
usart_async_get_io_descriptor(usart_desc_p, &io);
size_t total_read = 0;
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
// Busy-wait until timeout or until we've read enough chars.
while (ticks_ms - start_ticks <= self->timeout_ms) {
while (supervisor_ticks_ms64() - start_ticks <= self->timeout_ms) {
// Read as many chars as we can right now, up to len.
size_t num_read = io_read(io, data, len);
@ -289,7 +288,7 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
}
if (num_read > 0) {
// Reset the timeout on every character read.
start_ticks = ticks_ms;
start_ticks = supervisor_ticks_ms64();
}
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
@ -330,9 +329,9 @@ size_t common_hal_busio_uart_write(busio_uart_obj_t *self, const uint8_t *data,
// Wait until write is complete or timeout.
bool done = false;
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
// Busy-wait for timeout.
while (ticks_ms - start_ticks < self->timeout_ms) {
while (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) {
if (usart_async_is_tx_empty(usart_desc_p)) {
done = true;
break;

View File

@ -28,10 +28,10 @@
#include "shared-bindings/time/__init__.h"
#include "tick.h"
#include "supervisor/shared/tick.h"
inline uint64_t common_hal_time_monotonic() {
return ticks_ms;
return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {

View File

@ -45,12 +45,12 @@
#include "mpconfigboard.h"
#include "mphalport.h"
#include "reset.h"
#include "tick.h"
#include "supervisor/shared/tick.h"
extern uint32_t common_hal_mcu_processor_get_frequency(void);
void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
RUN_BACKGROUND_TASKS;
@ -59,7 +59,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
duration = (ticks_ms - start_tick);
duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}

View File

@ -31,11 +31,11 @@
#include "lib/oofatfs/ff.h"
// Global millisecond tick count (driven by SysTick interrupt).
extern volatile uint64_t ticks_ms;
#include "supervisor/shared/tick.h"
// Global millisecond tick count (driven by SysTick interrupt).
static inline mp_uint_t mp_hal_ticks_ms(void) {
return ticks_ms;
return supervisor_ticks_ms32();
}
// Number of bytes in receive buffer
volatile uint8_t usb_rx_count;

View File

@ -28,47 +28,21 @@
#include "peripheral_clk_config.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/tick.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
#if CIRCUITPY_GAMEPAD
#include "shared-module/gamepad/__init__.h"
#endif
#if CIRCUITPY_GAMEPADSHIFT
#include "shared-module/gamepadshift/__init__.h"
#endif
// Global millisecond tick count
volatile uint64_t ticks_ms = 0;
void SysTick_Handler(void) {
// SysTick interrupt handler called when the SysTick timer reaches zero
// (every millisecond).
common_hal_mcu_disable_interrupts();
ticks_ms += 1;
// Read the control register to reset the COUNTFLAG.
(void) SysTick->CTRL;
common_hal_mcu_enable_interrupts();
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
#if CIRCUITPY_GAMEPAD
gamepad_tick();
#endif
#if CIRCUITPY_GAMEPADSHIFT
gamepadshift_tick();
#endif
}
#endif
// Do things common to all ports when the tick occurs
supervisor_tick();
}
void tick_init() {
@ -115,7 +89,7 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t tick_status = SysTick->CTRL;
uint32_t current_us = SysTick->VAL;
uint32_t tick_status2 = SysTick->CTRL;
uint64_t current_ms = ticks_ms;
uint64_t current_ms = supervisor_ticks_ms64();
// The second clause ensures our value actually rolled over. Its possible it hit zero between
// the VAL read and CTRL read.
if ((tick_status & SysTick_CTRL_COUNTFLAG_Msk) != 0 ||
@ -129,5 +103,5 @@ void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
while (ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
while (supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}

View File

@ -28,8 +28,6 @@
#include "py/mpconfig.h"
extern volatile uint64_t ticks_ms;
extern struct timer_descriptor ms_timer;
void tick_init(void);

View File

@ -26,10 +26,10 @@
#include "py/mphal.h"
#include "tick.h"
#include "supervisor/shared/tick.h"
uint64_t common_hal_time_monotonic(void) {
return ticks_ms;
return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {

View File

@ -31,7 +31,7 @@
#include "py/mpstate.h"
#include "tick.h"
#include "supervisor/shared/tick.h"
#define DELAY_CORRECTION (700)
#define DELAY_INTERVAL (50)
@ -57,7 +57,7 @@ mp_uint_t mp_hal_ticks_cpu(void) {
}
void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
#ifdef MICROPY_VM_HOOK_LOOP
@ -68,7 +68,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
duration = (ticks_ms - start_tick);
duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}

View File

@ -31,6 +31,4 @@
#include "lib/utils/interrupt_char.h"
extern volatile uint64_t ticks_ms;
#endif // MICROPY_INCLUDED_CXD56_MPHALPORT_H

View File

@ -27,19 +27,10 @@
#include "tick.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/filesystem.h"
// Global millisecond tick count
volatile uint64_t ticks_ms = 0;
#include "supervisor/shared/tick.h"
void board_timerhook(void)
{
ticks_ms += 1;
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
// Do things common to all ports when the tick occurs
supervisor_tick();
}

View File

@ -29,6 +29,4 @@
#include "py/mpconfig.h"
extern volatile uint64_t ticks_ms;
#endif // MICROPY_INCLUDED_CXD56_TICK_H

View File

@ -40,6 +40,7 @@
#include "py/objstr.h"
#include "py/runtime.h"
#include "supervisor/shared/safe_mode.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Adapter.h"
@ -353,7 +354,7 @@ STATIC bool scan_on_ble_evt(ble_evt_t *ble_evt, void *scan_results_in) {
ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report;
shared_module_bleio_scanresults_append(scan_results,
ticks_ms,
supervisor_ticks_ms64(),
report->type.connectable,
report->type.scan_response,
report->rssi,

View File

@ -39,6 +39,7 @@
#include "shared-bindings/_bleio/__init__.h"
#include "shared-bindings/_bleio/Connection.h"
#include "supervisor/shared/tick.h"
#include "common-hal/_bleio/CharacteristicBuffer.h"
STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
@ -100,10 +101,10 @@ void common_hal_bleio_characteristic_buffer_construct(bleio_characteristic_buffe
}
int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_t *self, uint8_t *data, size_t len, int *errcode) {
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
while ( (ringbuf_count(&self->ringbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {

View File

@ -231,10 +231,10 @@ size_t common_hal_busio_uart_read(busio_uart_obj_t *self, uint8_t *data, size_t
}
size_t rx_bytes = 0;
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->rbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
while ( (ringbuf_count(&self->rbuf) < len) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
@ -265,15 +265,15 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
if ( len == 0 ) return 0;
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
// Wait for on-going transfer to complete
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
}
// Time up
if ( !(ticks_ms - start_ticks < self->timeout_ms) ) {
if ( !(supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
*errcode = MP_EAGAIN;
return MP_STREAM_ERROR;
}
@ -290,7 +290,7 @@ size_t common_hal_busio_uart_write (busio_uart_obj_t *self, const uint8_t *data,
_VERIFY_ERR(*errcode);
(*errcode) = 0;
while ( nrfx_uarte_tx_in_progress(self->uarte) && (ticks_ms - start_ticks < self->timeout_ms) ) {
while ( nrfx_uarte_tx_in_progress(self->uarte) && (supervisor_ticks_ms64() - start_ticks < self->timeout_ms) ) {
RUN_BACKGROUND_TASKS;
}

View File

@ -29,7 +29,7 @@
#include "tick.h"
uint64_t common_hal_time_monotonic(void) {
return ticks_ms;
return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {

View File

@ -31,12 +31,13 @@
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/gc.h"
#include "supervisor/shared/tick.h"
/*------------------------------------------------------------------*/
/* delay
*------------------------------------------------------------------*/
void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
RUN_BACKGROUND_TASKS;
@ -45,7 +46,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
duration = (ticks_ms - start_tick);
duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}

View File

@ -33,12 +33,11 @@
#include "lib/utils/interrupt_char.h"
#include "nrfx_uarte.h"
#include "py/mpconfig.h"
#include "supervisor/shared/tick.h"
extern nrfx_uarte_t serial_instance;
extern volatile uint64_t ticks_ms;
#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms)
#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
bool mp_hal_stdin_any(void);

View File

@ -26,31 +26,14 @@
#include "tick.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/tick.h"
#include "shared-module/gamepad/__init__.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "nrf.h"
// Global millisecond tick count
volatile uint64_t ticks_ms = 0;
void SysTick_Handler(void) {
// SysTick interrupt handler called when the SysTick timer reaches zero
// (every millisecond).
ticks_ms += 1;
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
gamepad_tick();
}
#endif
// Do things common to all ports when the tick occurs
supervisor_tick();
}
void tick_init() {
@ -61,11 +44,11 @@ void tick_init() {
void tick_delay(uint32_t us) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
uint64_t start_ms = ticks_ms;
uint64_t start_ms = supervisor_ticks_ms64();
while (us > 1000) {
while (ticks_ms == start_ms) {}
while (supervisor_ticks_ms64() == start_ms) {}
us -= us_between_ticks;
start_ms = ticks_ms;
start_ms = supervisor_ticks_ms64();
us_between_ticks = 1000;
}
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
@ -74,11 +57,11 @@ void tick_delay(uint32_t us) {
// us counts down!
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
*ms = ticks_ms;
*ms = supervisor_ticks_ms64();
*us_until_ms = SysTick->VAL / ticks_per_us;
}
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = common_hal_mcu_processor_get_frequency() / 1000 / 1000;
while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}

View File

@ -30,8 +30,6 @@
#include <stdint.h>
extern volatile uint64_t ticks_ms;
extern struct timer_descriptor ms_timer;
void tick_init(void);

View File

@ -29,7 +29,7 @@
#include "tick.h"
uint64_t common_hal_time_monotonic(void) {
return ticks_ms;
return supervisor_ticks_ms64();
}
void common_hal_time_delay_ms(uint32_t delay) {

View File

@ -31,11 +31,13 @@
#include "py/mpstate.h"
#include "py/gc.h"
#include "supervisor/shared/tick.h"
/*------------------------------------------------------------------*/
/* delay
*------------------------------------------------------------------*/
void mp_hal_delay_ms(mp_uint_t delay) {
uint64_t start_tick = ticks_ms;
uint64_t start_tick = supervisor_ticks_ms64();
uint64_t duration = 0;
while (duration < delay) {
#ifdef MICROPY_VM_HOOK_LOOP
@ -46,7 +48,7 @@ void mp_hal_delay_ms(mp_uint_t delay) {
MP_STATE_VM(mp_pending_exception) == MP_OBJ_FROM_PTR(&MP_STATE_VM(mp_reload_exception))) {
break;
}
duration = (ticks_ms - start_tick);
duration = (supervisor_ticks_ms64() - start_tick);
// TODO(tannewt): Go to sleep for a little while while we wait.
}
}

View File

@ -32,10 +32,10 @@
#include "lib/utils/interrupt_char.h"
#include "py/mpconfig.h"
#include "supervisor/shared/tick.h"
extern volatile uint64_t ticks_ms;
#define mp_hal_ticks_ms() ((mp_uint_t) ticks_ms)
#define mp_hal_ticks_ms() ((mp_uint_t) supervisor_ticks_ms32())
//#define mp_hal_delay_us(us) NRFX_DELAY_US((uint32_t) (us))
bool mp_hal_stdin_any(void);

View File

@ -26,37 +26,23 @@
#include "tick.h"
#include "supervisor/shared/autoreload.h"
#include "supervisor/filesystem.h"
#include "shared-module/gamepad/__init__.h"
#include "supervisor/shared/tick.h"
#include "shared-bindings/microcontroller/Processor.h"
#include "stm32f4xx.h"
// Global millisecond tick count
volatile uint64_t ticks_ms = 0;
void SysTick_Handler(void) {
// SysTick interrupt handler called when the SysTick timer reaches zero
// (every millisecond).
ticks_ms += 1;
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
gamepad_tick();
}
#endif
// Do things common to all ports when the tick occurs
supervisor_tick();
}
uint32_t HAL_GetTick(void) //override ST HAL
{
return (uint32_t)ticks_ms;
return (uint32_t)supervisor_ticks_ms32();
}
void tick_init() {
@ -72,11 +58,11 @@ void tick_init() {
void tick_delay(uint32_t us) {
uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
uint32_t us_between_ticks = SysTick->VAL / ticks_per_us;
uint64_t start_ms = ticks_ms;
uint64_t start_ms = supervisor_ticks_ms64();
while (us > 1000) {
while (ticks_ms == start_ms) {}
while (supervisor_ticks_ms64() == start_ms) {}
us -= us_between_ticks;
start_ms = ticks_ms;
start_ms = supervisor_ticks_ms64();
us_between_ticks = 1000;
}
while (SysTick->VAL > ((us_between_ticks - us) * ticks_per_us)) {}
@ -85,11 +71,11 @@ void tick_delay(uint32_t us) {
// us counts down!
void current_tick(uint64_t* ms, uint32_t* us_until_ms) {
uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
*ms = ticks_ms;
*ms = supervisor_ticks_ms32();
*us_until_ms = SysTick->VAL / ticks_per_us;
}
void wait_until(uint64_t ms, uint32_t us_until_ms) {
uint32_t ticks_per_us = SystemCoreClock / 1000 / 1000;
while(ticks_ms <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
while(supervisor_ticks_ms64() <= ms && SysTick->VAL / ticks_per_us >= us_until_ms) {}
}

View File

@ -30,8 +30,6 @@
#include <stdint.h>
extern volatile uint64_t ticks_ms;
extern struct timer_descriptor ms_timer;
void tick_init(void);

View File

@ -32,6 +32,7 @@
#define __INCLUDED_MPCONFIG_CIRCUITPY_H
#include <stdint.h>
#include <stdatomic.h>
// This is CircuitPython.
#define CIRCUITPY 1

View File

@ -35,6 +35,7 @@
#include "shared-module/displayio/__init__.h"
#include "shared-module/displayio/display_core.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include <stdint.h>
@ -313,7 +314,7 @@ uint16_t common_hal_displayio_display_get_rotation(displayio_display_obj_t* self
bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_t target_ms_per_frame, uint32_t maximum_ms_per_real_frame) {
if (!self->auto_refresh && !self->first_manual_refresh) {
uint64_t current_time = ticks_ms;
uint64_t current_time = supervisor_ticks_ms64();
uint32_t current_ms_since_real_refresh = current_time - self->core.last_refresh;
// Test to see if the real frame time is below our minimum.
if (current_ms_since_real_refresh > maximum_ms_per_real_frame) {
@ -327,7 +328,7 @@ bool common_hal_displayio_display_refresh(displayio_display_obj_t* self, uint32_
}
uint32_t remaining_time = target_ms_per_frame - (current_ms_since_real_refresh % target_ms_per_frame);
// We're ahead of the game so wait until we align with the frame rate.
while (ticks_ms - self->last_refresh_call < remaining_time) {
while (supervisor_ticks_ms64() - self->last_refresh_call < remaining_time) {
RUN_BACKGROUND_TASKS;
}
}
@ -350,20 +351,20 @@ STATIC void _update_backlight(displayio_display_obj_t* self) {
if (!self->auto_brightness || self->updating_backlight) {
return;
}
if (ticks_ms - self->last_backlight_refresh < 100) {
if (supervisor_ticks_ms64() - self->last_backlight_refresh < 100) {
return;
}
// TODO(tannewt): Fade the backlight based on it's existing value and a target value. The target
// should account for ambient light when possible.
common_hal_displayio_display_set_brightness(self, 1.0);
self->last_backlight_refresh = ticks_ms;
self->last_backlight_refresh = supervisor_ticks_ms64();
}
void displayio_display_background(displayio_display_obj_t* self) {
_update_backlight(self);
if (self->auto_refresh && (ticks_ms - self->core.last_refresh) > self->native_ms_per_frame) {
if (self->auto_refresh && (supervisor_ticks_ms64() - self->core.last_refresh) > self->native_ms_per_frame) {
_refresh_display(self);
}
}

View File

@ -35,6 +35,7 @@
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/tick.h"
#include "supervisor/usb.h"
#include <stdint.h>
@ -175,7 +176,7 @@ uint32_t common_hal_displayio_epaperdisplay_get_time_to_refresh(displayio_epaper
return 0;
}
// Refresh at seconds per frame rate.
uint32_t elapsed_time = ticks_ms - self->core.last_refresh;
uint32_t elapsed_time = supervisor_ticks_ms64() - self->core.last_refresh;
if (elapsed_time > self->milliseconds_per_frame) {
return 0;
}
@ -339,7 +340,7 @@ void displayio_epaperdisplay_background(displayio_epaperdisplay_obj_t* self) {
bool busy = common_hal_digitalio_digitalinout_get_value(&self->busy);
refresh_done = busy != self->busy_state;
} else {
refresh_done = ticks_ms - self->core.last_refresh > self->refresh_time;
refresh_done = supervisor_ticks_ms64() - self->core.last_refresh > self->refresh_time;
}
if (refresh_done) {
self->refreshing = false;

View File

@ -35,6 +35,7 @@
#include "shared-bindings/time/__init__.h"
#include "shared-module/displayio/__init__.h"
#include "supervisor/shared/display.h"
#include "supervisor/shared/tick.h"
#include <stdint.h>
#include <string.h>
@ -281,7 +282,7 @@ void displayio_display_core_set_region_to_update(displayio_display_core_t* self,
}
void displayio_display_core_start_refresh(displayio_display_core_t* self) {
self->last_refresh = ticks_ms;
self->last_refresh = supervisor_ticks_ms64();
}
void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
@ -289,7 +290,7 @@ void displayio_display_core_finish_refresh(displayio_display_core_t* self) {
displayio_group_finish_refresh(self->current_group);
}
self->full_refresh = false;
self->last_refresh = ticks_ms;
self->last_refresh = supervisor_ticks_ms64();
}
void release_display_core(displayio_display_core_t* self) {

View File

@ -31,6 +31,8 @@
#include "py/mphal.h"
#include "py/mperrno.h"
#include "supervisor/shared/tick.h"
#include "shared-bindings/random/__init__.h"
#include "shared-module/network/__init__.h"
@ -53,7 +55,7 @@ void network_module_deinit(void) {
void network_module_background(void) {
static uint32_t next_tick = 0;
uint32_t this_tick = ticks_ms;
uint32_t this_tick = supervisor_ticks_ms32();
if (this_tick < next_tick) return;
next_tick = this_tick + 1000;

View File

@ -30,6 +30,7 @@
#include "shared-bindings/usb_hid/Device.h"
#include "shared-module/usb_hid/Device.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/tick.h"
#include "tusb.h"
uint8_t common_hal_usb_hid_device_get_usage_page(usb_hid_device_obj_t *self) {
@ -46,8 +47,8 @@ void common_hal_usb_hid_device_send_report(usb_hid_device_obj_t *self, uint8_t*
}
// Wait until interface is ready, timeout = 2 seconds
uint64_t end_ticks = ticks_ms + 2000;
while ( (ticks_ms < end_ticks) && !tud_hid_ready() ) {
uint64_t end_ticks = supervisor_ticks_ms64() + 2000;
while ( (supervisor_ticks_ms64() < end_ticks) && !tud_hid_ready() ) {
RUN_BACKGROUND_TASKS;
}

View File

@ -27,6 +27,7 @@
#include "mphalport.h"
#include "shared-bindings/microcontroller/Pin.h"
#include "rgb_led_status.h"
#include "supervisor/shared/tick.h"
#ifdef MICROPY_HW_NEOPIXEL
uint8_t rgb_status_brightness = 63;
@ -360,7 +361,7 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
rgb_status_animation_t* status) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
new_status_color(ALL_DONE);
status->pattern_start = ticks_ms;
status->pattern_start = supervisor_ticks_ms32();
status->safe_mode = safe_mode;
status->found_main = found_main;
status->total_exception_cycle = 0;
@ -405,11 +406,11 @@ void prep_rgb_status_animation(const pyexec_result_t* result,
void tick_rgb_status_animation(rgb_status_animation_t* status) {
#if defined(MICROPY_HW_NEOPIXEL) || (defined(MICROPY_HW_APA102_MOSI) && defined(MICROPY_HW_APA102_SCK)) || (defined(CP_RGB_STATUS_LED))
uint32_t tick_diff = ticks_ms - status->pattern_start;
uint32_t tick_diff = supervisor_ticks_ms32() - status->pattern_start;
if (status->ok) {
// All is good. Ramp ALL_DONE up and down.
if (tick_diff > ALL_GOOD_CYCLE_MS) {
status->pattern_start = ticks_ms;
status->pattern_start = supervisor_ticks_ms32();
tick_diff = 0;
}
@ -424,7 +425,7 @@ void tick_rgb_status_animation(rgb_status_animation_t* status) {
}
} else {
if (tick_diff > status->total_exception_cycle) {
status->pattern_start = ticks_ms;
status->pattern_start = supervisor_ticks_ms32();
tick_diff = 0;
}
// First flash the file color.

View File

@ -34,6 +34,7 @@
#include "supervisor/shared/rgb_led_colors.h"
#include "supervisor/shared/rgb_led_status.h"
#include "supervisor/shared/translate.h"
#include "supervisor/shared/tick.h"
#define SAFE_MODE_DATA_GUARD 0xad0000af
#define SAFE_MODE_DATA_GUARD_MASK 0xff0000ff
@ -59,14 +60,14 @@ safe_mode_t wait_for_safe_mode_reset(void) {
common_hal_digitalio_digitalinout_construct(&status_led, MICROPY_HW_LED_STATUS);
common_hal_digitalio_digitalinout_switch_to_output(&status_led, true, DRIVE_MODE_PUSH_PULL);
#endif
uint64_t start_ticks = ticks_ms;
uint64_t start_ticks = supervisor_ticks_ms64();
uint64_t diff = 0;
while (diff < 700) {
#ifdef MICROPY_HW_LED_STATUS
// Blink on for 100, off for 100, on for 100, off for 100 and on for 200
common_hal_digitalio_digitalinout_set_value(&status_led, diff > 100 && diff / 100 != 2 && diff / 100 != 4);
#endif
diff = ticks_ms - start_ticks;
diff = supervisor_ticks_ms64() - start_ticks;
}
#ifdef MICROPY_HW_LED_STATUS
common_hal_digitalio_digitalinout_deinit(&status_led);

76
supervisor/shared/tick.c Normal file
View File

@ -0,0 +1,76 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "supervisor/shared/tick.h"
#include "supervisor/filesystem.h"
#include "supervisor/shared/autoreload.h"
static volatile uint64_t ticks_ms;
#if CIRCUITPY_GAMEPAD
#include "shared-module/gamepad/__init__.h"
#endif
#if CIRCUITPY_GAMEPADSHIFT
#include "shared-module/gamepadshift/__init__.h"
#endif
#include "shared-bindings/microcontroller/__init__.h"
void supervisor_tick(void) {
ticks_ms ++;
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#ifdef CIRCUITPY_AUTORELOAD_DELAY_MS
autoreload_tick();
#endif
#ifdef CIRCUITPY_GAMEPAD_TICKS
if (!(ticks_ms & CIRCUITPY_GAMEPAD_TICKS)) {
#if CIRCUITPY_GAMEPAD
gamepad_tick();
#endif
#if CIRCUITPY_GAMEPADSHIFT
gamepadshift_tick();
#endif
}
#endif
}
uint64_t supervisor_ticks_ms64() {
uint64_t result;
common_hal_mcu_disable_interrupts();
result = ticks_ms;
common_hal_mcu_enable_interrupts();
return result;
}
uint32_t supervisor_ticks_ms32() {
return ticks_ms;
}

37
supervisor/shared/tick.h Normal file
View File

@ -0,0 +1,37 @@
/*
* This file is part of the MicroPython project, http://micropython.org/
*
* The MIT License (MIT)
*
* Copyright (c) 2019 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef __INCLUDED_SUPERVISOR_TICK_H
#define __INCLUDED_SUPERVISOR_TICK_H
#include <stdint.h>
#include <stdatomic.h>
extern void supervisor_tick(void);
extern uint32_t supervisor_ticks_ms32(void);
extern uint64_t supervisor_ticks_ms64(void);
#endif

View File

@ -10,6 +10,7 @@ SRC_SUPERVISOR = \
supervisor/shared/safe_mode.c \
supervisor/shared/stack.c \
supervisor/shared/status_leds.c \
supervisor/shared/tick.c \
supervisor/shared/translate.c
ifndef $(NO_USB)