forked from adafruit/circuitpython
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathtick.c
More file actions
152 lines (120 loc) · 3.89 KB
/
Copy pathtick.c
File metadata and controls
152 lines (120 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// This file is part of the CircuitPython project: https://circuitpython.org
//
// SPDX-FileCopyrightText: Copyright (c) 2019 Jeff Epler for Adafruit Industries
//
// SPDX-License-Identifier: MIT
#include "supervisor/shared/tick.h"
#include "shared/runtime/interrupt_char.h"
#include "py/mphal.h"
#include "py/mpstate.h"
#include "py/runtime.h"
#include "supervisor/filesystem.h"
#include "supervisor/background_callback.h"
#include "supervisor/port.h"
#include "supervisor/shared/stack.h"
#if CIRCUITPY_BLEIO_HCI
#include "common-hal/_bleio/__init__.h"
#endif
#if CIRCUITPY_DISPLAYIO
#include "shared-module/displayio/__init__.h"
#endif
#if CIRCUITPY_KEYPAD
#include "shared-module/keypad/__init__.h"
#endif
#include "shared-bindings/microcontroller/__init__.h"
#if CIRCUITPY_WATCHDOG
#include "shared-bindings/watchdog/__init__.h"
#define WATCHDOG_EXCEPTION_CHECK() (MP_STATE_VM(mp_pending_exception) == &mp_watchdog_timeout_exception)
#else
#define WATCHDOG_EXCEPTION_CHECK() 0
#endif
static volatile uint64_t PLACE_IN_DTCM_BSS(background_ticks);
static background_callback_t tick_callback;
static volatile uint64_t last_finished_tick = 0;
static volatile size_t tick_enable_count = 0;
static void supervisor_background_tick(void *unused) {
port_start_background_tick();
assert_heap_ok();
#if CIRCUITPY_BLEIO_HCI
bleio_hci_background();
#endif
#if CIRCUITPY_DISPLAYIO
displayio_background();
#endif
filesystem_background();
port_background_tick();
assert_heap_ok();
last_finished_tick = port_get_raw_ticks(NULL);
port_finish_background_tick();
}
bool supervisor_background_ticks_ok(void) {
return port_get_raw_ticks(NULL) - last_finished_tick < 1024;
}
void supervisor_tick(void) {
#if CIRCUITPY_FILESYSTEM_FLUSH_INTERVAL_MS > 0
filesystem_tick();
#endif
#if CIRCUITPY_KEYPAD
keypad_tick();
#endif
background_callback_add(&tick_callback, supervisor_background_tick, NULL);
}
static uint64_t _get_raw_subticks(void) {
uint64_t ticks;
uint8_t subticks;
ticks = port_get_raw_ticks(&subticks);
return (ticks << 5) | subticks;
}
uint64_t supervisor_ticks_ms64(void) {
uint64_t result;
result = port_get_raw_ticks(NULL);
result = result * 1000 / 1024;
return result;
}
uint32_t supervisor_ticks_ms32(void) {
return supervisor_ticks_ms64();
}
void mp_hal_delay_ms(mp_uint_t delay_ms) {
uint64_t start_subtick = _get_raw_subticks();
// Convert delay from ms to subticks
uint64_t delay_subticks = (delay_ms * (uint64_t)32768) / 1000;
uint64_t end_subtick = start_subtick + delay_subticks;
int64_t remaining = delay_subticks;
// Loop until we've waited long enough or we've been CTRL-Ced by autoreload
// or the user.
while (remaining > 0 && !mp_hal_is_interrupted()) {
RUN_BACKGROUND_TASKS;
// Exit if interrupted while running background tasks
if (mp_hal_is_interrupted()) {
break;
}
// Recalculate remaining delay after running background tasks
remaining = end_subtick - _get_raw_subticks();
// If remaining delay is less than 1 tick, idle loop until end of delay
int64_t remaining_ticks = remaining / 32;
if (remaining_ticks > 0) {
port_interrupt_after_ticks(remaining_ticks);
// Idle until an interrupt happens.
port_idle_until_interrupt();
}
remaining = end_subtick - _get_raw_subticks();
}
}
void supervisor_enable_tick(void) {
common_hal_mcu_disable_interrupts();
if (tick_enable_count == 0) {
port_enable_tick();
}
tick_enable_count++;
common_hal_mcu_enable_interrupts();
}
void supervisor_disable_tick(void) {
common_hal_mcu_disable_interrupts();
if (tick_enable_count > 0) {
tick_enable_count--;
}
if (tick_enable_count == 0) {
port_disable_tick();
}
common_hal_mcu_enable_interrupts();
}