Merge pull request #2297 from jepler/tick-refactor

Call background tasks only once per ms
This commit is contained in:
Scott Shawcroft 2019-12-02 16:45:51 -08:00 committed by GitHub
commit fce81e6868
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 287 additions and 167 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"
@ -44,6 +45,23 @@ bool stack_ok_so_far = true;
static bool running_background_tasks = false;
#ifdef MONITOR_BACKGROUND_TASKS
// PB03 is physical pin "SCL" on the Metro M4 express
// so you can't use this code AND an i2c peripheral
// at the same time unless you change this
STATIC void start_background_task(void) {
REG_PORT_DIRSET1 = (1<<3);
REG_PORT_OUTSET1 = (1<<3);
}
STATIC void finish_background_task(void) {
REG_PORT_OUTCLR1 = (1<<3);
}
#else
STATIC void start_background_task(void) {}
STATIC void finish_background_task(void) {}
#endif
void background_tasks_reset(void) {
running_background_tasks = false;
}
@ -53,6 +71,9 @@ void run_background_tasks(void) {
if (running_background_tasks) {
return;
}
start_background_task();
assert_heap_ok();
running_background_tasks = true;
@ -71,9 +92,10 @@ void run_background_tasks(void) {
running_background_tasks = false;
assert_heap_ok();
last_finished_tick = ticks_ms;
last_finished_tick = supervisor_ticks_ms64();
finish_background_task();
}
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.

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"
@ -343,7 +344,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() ) {

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

@ -250,10 +250,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, same as nrf
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;
//restart if it failed in the callback
if (errflag != HAL_OK) {

View File

@ -48,9 +48,9 @@ STATIC uint32_t get_us(void) {
uint32_t ticks_per_us = HAL_RCC_GetSysClockFreq()/1000000;
uint32_t micros, sys_cycles;
do {
micros = ticks_ms;
micros = supervisor_ticks_ms32();
sys_cycles = SysTick->VAL; //counts backwards
} while (micros != ticks_ms); //try again if ticks_ms rolled over
} while (micros != supervisor_ticks_ms32()); //try again if ticks_ms rolled over
return (micros * 1000) + (ticks_per_us * 1000 - sys_cycles) / ticks_per_us;
}

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

@ -28,11 +28,12 @@
// sure that the same feature set and settings are used, such as in atmel-samd
// and nrf.
#include <stdint.h>
#ifndef __INCLUDED_MPCONFIG_CIRCUITPY_H
#define __INCLUDED_MPCONFIG_CIRCUITPY_H
#include <stdint.h>
#include <stdatomic.h>
// This is CircuitPython.
#define CIRCUITPY 1
@ -652,14 +653,14 @@ extern const struct _mp_obj_module_t ustack_module;
FLASH_ROOT_POINTERS \
NETWORK_ROOT_POINTERS \
void run_background_tasks(void);
#define RUN_BACKGROUND_TASKS (run_background_tasks())
void supervisor_run_background_tasks_if_tick(void);
#define RUN_BACKGROUND_TASKS (supervisor_run_background_tasks_if_tick())
// TODO: Used in wiznet5k driver, but may not be needed in the long run.
#define MICROPY_THREAD_YIELD()
#define MICROPY_VM_HOOK_LOOP run_background_tasks();
#define MICROPY_VM_HOOK_RETURN run_background_tasks();
#define MICROPY_VM_HOOK_LOOP RUN_BACKGROUND_TASKS;
#define MICROPY_VM_HOOK_RETURN RUN_BACKGROUND_TASKS;
#define CIRCUITPY_AUTORELOAD_DELAY_MS 500
#define CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS 1000

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

@ -36,6 +36,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>
@ -176,7 +177,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;
}
@ -340,7 +341,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);

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

@ -0,0 +1,94 @@
/*
* 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;
static volatile uint32_t background_ticks_ms32;
#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;
}
extern void run_background_tasks(void);
void supervisor_run_background_tasks_if_tick() {
uint32_t now32 = ticks_ms;
if (now32 == background_ticks_ms32) {
return;
}
background_ticks_ms32 = now32;
run_background_tasks();
}
void supervisor_fake_tick() {
uint32_t now32 = ticks_ms;
background_ticks_ms32 = (now32 - 1);
}

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

@ -0,0 +1,67 @@
/*
* 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>
/** @brief To be called once every ms
*
* The port must call supervisor_tick once per millisecond to perform regular tasks.
* This is called from the SysTick interrupt or similar, and is safe to call in an
* interrupt context.
*/
extern void supervisor_tick(void);
/** @brief Cause background tasks to be called soon
*
* Normally, background tasks are only run once per tick. For other cases where
* an event noticed from an interrupt context needs to be completed by a background
* task activity, the interrupt can call supervisor_fake_tick.
*/
extern void supervisor_fake_tick(void);
/** @brief Get the lower 32 bits of the time in milliseconds
*
* This can be more efficient than supervisor_ticks_ms64, for sites where a wraparound
* of ~49.5 days is not harmful.
*/
extern uint32_t supervisor_ticks_ms32(void);
/** @brief Get the full time in milliseconds
*
* Because common ARM mcus cannot atomically work with 64-bit quantities, this
* function must briefly disable interrupts in order to return the value. If
* only relative durations of less than about ~49.5 days need to be considered,
* then it may be possible to use supervisor_ticks_ms64 instead.
*/
extern uint64_t supervisor_ticks_ms64(void);
/** @brief Run background ticks, but only about every millisecond.
*
* Normally, this is not called directly. Instead use the RUN_BACKGROUND_TASKS
* macro.
*/
extern void supervisor_run_background_if_tick(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)