Skip to content

Commit 4183339

Browse files
committed
Fix autoreload, neopixel, monotonic_ns and sleep w/o SD
1 parent 6f60afe commit 4183339

9 files changed

Lines changed: 80 additions & 42 deletions

File tree

main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -428,7 +428,7 @@ int __attribute__((used)) main(void) {
428428
filesystem_init(safe_mode == NO_SAFE_MODE, false);
429429

430430
// displays init after filesystem, since they could share the flash SPI
431-
board_init();
431+
board_init();
432432

433433
// Reset everything and prep MicroPython to run boot.py.
434434
reset_port();

ports/nrf/common-hal/neopixel_write/__init__.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "py/mphal.h"
2828
#include "py/mpstate.h"
2929
#include "shared-bindings/neopixel_write/__init__.h"
30+
#include "supervisor/port.h"
3031
#include "nrf_pwm.h"
3132

3233
// https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.cpp
@@ -103,8 +104,7 @@ void neopixel_write_reset(void) {
103104
pixels_pattern_heap_size = 0;
104105
}
105106

106-
uint64_t next_start_tick_ms = 0;
107-
uint32_t next_start_tick_us = 1000;
107+
uint64_t next_start_raw_ticks = 0;
108108

109109
void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout, uint8_t *pixels, uint32_t numBytes) {
110110
// To support both the SoftDevice + Neopixels we use the EasyDMA
@@ -173,8 +173,9 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
173173
}
174174
}
175175

176-
// Wait to make sure we don't append onto the last transmission.
177-
// wait_until(next_start_tick_ms, next_start_tick_us);
176+
// Wait to make sure we don't append onto the last transmission. This should only be a tick or
177+
// two.
178+
while (port_get_raw_ticks(NULL) < next_start_raw_ticks) {}
178179

179180
// Use the identified device to choose the implementation
180181
// If a PWM device is available and we have a buffer, use DMA.
@@ -321,11 +322,5 @@ void common_hal_neopixel_write (const digitalio_digitalinout_obj_t* digitalinout
321322
}
322323

323324
// Update the next start.
324-
// current_tick(&next_start_tick_ms, &next_start_tick_us);
325-
// if (next_start_tick_us < 100) {
326-
// next_start_tick_ms += 1;
327-
// next_start_tick_us = 100 - next_start_tick_us;
328-
// } else {
329-
// next_start_tick_us -= 100;
330-
// }
325+
next_start_raw_ticks = port_get_raw_ticks(NULL) + 4;
331326
}

ports/nrf/common-hal/rtc/RTC.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,12 +40,12 @@
4040
static uint32_t rtc_offset = 0;
4141

4242
void common_hal_rtc_get_time(timeutils_struct_time_t *tm) {
43-
uint64_t ticks_s = port_get_raw_ticks() / 1024;
43+
uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024;
4444
timeutils_seconds_since_2000_to_struct_time(rtc_offset + ticks_s, tm);
4545
}
4646

4747
void common_hal_rtc_set_time(timeutils_struct_time_t *tm) {
48-
uint64_t ticks_s = port_get_raw_ticks() / 1024;
48+
uint64_t ticks_s = port_get_raw_ticks(NULL) / 1024;
4949
uint32_t epoch_s = timeutils_seconds_since_2000(
5050
tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec
5151
);

ports/nrf/common-hal/time/__init__.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,18 @@
2525
*/
2626

2727
#include "py/mphal.h"
28+
#include "supervisor/port.h"
2829

2930
uint64_t common_hal_time_monotonic(void) {
3031
return supervisor_ticks_ms64();
3132
}
3233

3334
uint64_t common_hal_time_monotonic_ns(void) {
34-
uint64_t ms = 0;
35-
uint32_t us_until_ms = 0;
36-
// FIXME! Re-implement this.
37-
// current_tick(&ms, &us_until_ms);
38-
// us counts down.
39-
return 1000 * (ms * 1000 + (1000 - us_until_ms));
35+
uint8_t subticks = 0;
36+
uint64_t ticks = port_get_raw_ticks(&subticks);
37+
// A tick is 976562.5 nanoseconds so multiply it by the base and add half instead of doing float
38+
// math.
39+
return 976562 * ticks + ticks / 2 + 30518 * subticks;
4040
}
4141

4242
void common_hal_time_delay_ms(uint32_t delay) {

ports/nrf/supervisor/port.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static void power_warning_handler(void) {
6868
const nrfx_rtc_t rtc_instance = NRFX_RTC_INSTANCE(2);
6969

7070
const nrfx_rtc_config_t rtc_config = {
71-
.prescaler = RTC_FREQ_TO_PRESCALER(1024),
71+
.prescaler = RTC_FREQ_TO_PRESCALER(0x8000),
7272
.reliable = 0,
7373
.tick_latency = 0,
7474
.interrupt_priority = 6
@@ -79,10 +79,11 @@ static volatile uint64_t overflowed_ticks = 0;
7979
void rtc_handler(nrfx_rtc_int_type_t int_type) {
8080
if (int_type == NRFX_RTC_INT_OVERFLOW) {
8181
overflowed_ticks += (1L<<24);
82-
}
83-
// Do things common to all ports when the tick occurs
84-
if (int_type == NRFX_RTC_INT_TICK) {
82+
} else if (int_type == NRFX_RTC_INT_TICK && nrfx_rtc_counter_get(&rtc_instance) % 32 == 0) {
83+
// Do things common to all ports when the tick occurs
8584
supervisor_tick();
85+
} else if (int_type == NRFX_RTC_INT_COMPARE0) {
86+
nrfx_rtc_cc_set(&rtc_instance, 0, 0, false);
8687
}
8788
}
8889

@@ -195,8 +196,12 @@ uint32_t port_get_saved_word(void) {
195196
return _ebss;
196197
}
197198

198-
uint64_t port_get_raw_ticks(void) {
199-
return overflowed_ticks + nrfx_rtc_counter_get(&rtc_instance);
199+
uint64_t port_get_raw_ticks(uint8_t* subticks) {
200+
uint32_t rtc = nrfx_rtc_counter_get(&rtc_instance);
201+
if (subticks != NULL) {
202+
*subticks = (rtc % 32);
203+
}
204+
return overflowed_ticks + rtc / 32;
200205
}
201206

202207
// Enable 1/1024 second tick.
@@ -213,7 +218,10 @@ void port_interrupt_after_ticks(uint32_t ticks) {
213218
uint32_t current_ticks = nrfx_rtc_counter_get(&rtc_instance);
214219
uint32_t diff = 3;
215220
if (ticks > diff) {
216-
diff = ticks;
221+
diff = ticks * 32;
222+
}
223+
if (diff > 0xffffff) {
224+
diff = 0xffffff;
217225
}
218226
nrfx_rtc_cc_set(&rtc_instance, 0, current_ticks + diff, true);
219227
}
@@ -225,7 +233,15 @@ void port_sleep_until_interrupt(void) {
225233
(void) __get_FPSCR();
226234
NVIC_ClearPendingIRQ(FPU_IRQn);
227235
}
228-
sd_app_evt_wait();
236+
uint8_t sd_enabled;
237+
238+
sd_softdevice_is_enabled(&sd_enabled);
239+
if (sd_enabled) {
240+
sd_app_evt_wait();
241+
} else {
242+
// Call wait for interrupt ourselves if the SD isn't enabled.
243+
__WFI();
244+
}
229245
}
230246

231247

supervisor/port.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,17 +70,19 @@ uint32_t *port_heap_get_top(void);
7070
void port_set_saved_word(uint32_t);
7171
uint32_t port_get_saved_word(void);
7272

73-
// Get the raw tick count since start up. A tick is 1/32768 of a second, a common low frequency
74-
// clock rate.
75-
uint64_t port_get_raw_ticks(void);
73+
// Get the raw tick count since start up. A tick is 1/1024 of a second, a common low frequency
74+
// clock rate. If subticks is not NULL then the port will fill in the number of subticks where each
75+
// tick is 32 subticks (for a resolution of 1/32768 or 30.5ish microseconds.)
76+
uint64_t port_get_raw_ticks(uint8_t* subticks);
7677

7778
// Enable 1/1024 second tick.
7879
void port_enable_tick(void);
7980

8081
// Disable 1/1024 second tick.
8182
void port_disable_tick(void);
8283

83-
// Wake the CPU after the given number of ticks or sooner.
84+
// Wake the CPU after the given number of ticks or sooner. Only the last call to this will apply.
85+
// Only the common sleep routine should use it.
8486
void port_interrupt_after_ticks(uint32_t ticks);
8587

8688
// Sleep the CPU until an interrupt is received.

supervisor/shared/autoreload.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "py/mphal.h"
3030
#include "py/reload.h"
31+
#include "supervisor/shared/tick.h"
3132

3233
static volatile uint32_t autoreload_delay_ms = 0;
3334
static bool autoreload_enabled = false;
@@ -43,6 +44,7 @@ inline void autoreload_tick() {
4344
!autoreload_suspended && !reload_requested) {
4445
mp_raise_reload_exception();
4546
reload_requested = true;
47+
supervisor_disable_tick();
4648
}
4749
autoreload_delay_ms--;
4850
}
@@ -69,6 +71,9 @@ inline bool autoreload_is_enabled() {
6971
}
7072

7173
void autoreload_start() {
74+
if (autoreload_delay_ms == 0) {
75+
supervisor_enable_tick();
76+
}
7277
autoreload_delay_ms = CIRCUITPY_AUTORELOAD_DELAY_MS;
7378
}
7479

supervisor/shared/tick.c

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ void supervisor_tick(void) {
5252
autoreload_tick();
5353
#endif
5454
#ifdef CIRCUITPY_GAMEPAD_TICKS
55-
if (!(port_get_raw_ticks() & CIRCUITPY_GAMEPAD_TICKS)) {
55+
if (!(port_get_raw_ticks(NULL) & CIRCUITPY_GAMEPAD_TICKS)) {
5656
#if CIRCUITPY_GAMEPAD
5757
gamepad_tick();
5858
#endif
@@ -66,7 +66,7 @@ void supervisor_tick(void) {
6666
uint64_t supervisor_ticks_ms64() {
6767
uint64_t result;
6868
common_hal_mcu_disable_interrupts();
69-
result = port_get_raw_ticks();
69+
result = port_get_raw_ticks(NULL);
7070
common_hal_mcu_enable_interrupts();
7171
result = result * 1000 / 1024;
7272
return result;
@@ -79,23 +79,24 @@ uint32_t supervisor_ticks_ms32() {
7979
extern void run_background_tasks(void);
8080

8181
void PLACE_IN_ITCM(supervisor_run_background_tasks_if_tick)() {
82-
// uint64_t now = port_get_raw_ticks();
82+
uint8_t subticks;
83+
uint64_t now = port_get_raw_ticks(&subticks);
8384

84-
// if (now == background_ticks) {
85-
// return;
86-
// }
87-
// background_ticks = now;
85+
if (now == background_ticks && (subticks & 0x3) != 0) {
86+
return;
87+
}
88+
background_ticks = now;
8889

8990
run_background_tasks();
9091
}
9192

9293
void supervisor_fake_tick() {
93-
uint32_t now = port_get_raw_ticks();
94+
uint32_t now = port_get_raw_ticks(NULL);
9495
background_ticks = (now - 1);
9596
}
9697

9798
void mp_hal_delay_ms(mp_uint_t delay) {
98-
uint64_t start_tick = port_get_raw_ticks();
99+
uint64_t start_tick = port_get_raw_ticks(NULL);
99100
// Adjust the delay to ticks vs ms.
100101
delay = delay * 1024 / 1000;
101102
uint64_t duration = 0;
@@ -110,7 +111,23 @@ void mp_hal_delay_ms(mp_uint_t delay) {
110111
// Sleep until an interrupt happens.
111112
port_sleep_until_interrupt();
112113
// asm("bkpt");
113-
duration = (port_get_raw_ticks() - start_tick);
114+
duration = (port_get_raw_ticks(NULL) - start_tick);
115+
port_interrupt_after_ticks(duration);
116+
}
117+
}
118+
119+
volatile size_t tick_enable_count = 0;
120+
extern void supervisor_enable_tick(void) {
121+
if (tick_enable_count == 0) {
122+
port_enable_tick();
123+
}
124+
tick_enable_count++;
125+
}
126+
127+
extern void supervisor_disable_tick(void) {
128+
tick_enable_count--;
129+
if (tick_enable_count == 0) {
130+
port_disable_tick();
114131
}
115132
}
116133

supervisor/shared/tick.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,7 @@ extern uint64_t supervisor_ticks_ms64(void);
6464
*/
6565
extern void supervisor_run_background_if_tick(void);
6666

67+
extern void supervisor_enable_tick(void);
68+
extern void supervisor_disable_tick(void);
69+
6770
#endif

0 commit comments

Comments
 (0)