rp2: Implement time.time_ns with time_us_64 so it has us resolution.
Currently on rp2 the time.time_ns() function has only seconds resolution. This commit makes it have microsecond resolution, by using the output of time_us_64() instead of the RTC. Tested that it does not drift from the RTC over long periods of time. Signed-off-by: Damien George <damien.p.george@gmail.com>
This commit is contained in:
parent
c2e9a6f2a5
commit
6f76d1c7fa
@ -58,6 +58,7 @@ STATIC mp_obj_t machine_rtc_make_new(const mp_obj_type_t *type, size_t n_args, s
|
|||||||
rtc_init();
|
rtc_init();
|
||||||
datetime_t t = { .month = 1, .day = 1 };
|
datetime_t t = { .month = 1, .day = 1 };
|
||||||
rtc_set_datetime(&t);
|
rtc_set_datetime(&t);
|
||||||
|
mp_hal_time_ns_set_from_rtc();
|
||||||
}
|
}
|
||||||
// return constant object
|
// return constant object
|
||||||
return (mp_obj_t)&machine_rtc_obj;
|
return (mp_obj_t)&machine_rtc_obj;
|
||||||
@ -104,6 +105,7 @@ STATIC mp_obj_t machine_rtc_datetime(mp_uint_t n_args, const mp_obj_t *args) {
|
|||||||
if (!rtc_set_datetime(&t)) {
|
if (!rtc_set_datetime(&t)) {
|
||||||
mp_raise_OSError(MP_EINVAL);
|
mp_raise_OSError(MP_EINVAL);
|
||||||
}
|
}
|
||||||
|
mp_hal_time_ns_set_from_rtc();
|
||||||
|
|
||||||
}
|
}
|
||||||
return mp_const_none;
|
return mp_const_none;
|
||||||
|
@ -106,6 +106,7 @@ int main(int argc, char **argv) {
|
|||||||
};
|
};
|
||||||
rtc_init();
|
rtc_init();
|
||||||
rtc_set_datetime(&t);
|
rtc_set_datetime(&t);
|
||||||
|
mp_hal_time_ns_set_from_rtc();
|
||||||
|
|
||||||
// Initialise stack extents and GC heap.
|
// Initialise stack extents and GC heap.
|
||||||
mp_stack_set_top(&__StackTop);
|
mp_stack_set_top(&__StackTop);
|
||||||
|
@ -39,6 +39,10 @@
|
|||||||
#include "lib/cyw43-driver/src/cyw43.h"
|
#include "lib/cyw43-driver/src/cyw43.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// This needs to be added to the result of time_us_64() to get the number of
|
||||||
|
// microseconds since the Epoch.
|
||||||
|
STATIC uint64_t time_us_64_offset_from_epoch;
|
||||||
|
|
||||||
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
|
#if MICROPY_HW_ENABLE_UART_REPL || MICROPY_HW_USB_CDC
|
||||||
|
|
||||||
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
#ifndef MICROPY_HW_STDIN_BUFFER_LEN
|
||||||
@ -176,11 +180,28 @@ void mp_hal_delay_ms(mp_uint_t ms) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t mp_hal_time_ns(void) {
|
void mp_hal_time_ns_set_from_rtc(void) {
|
||||||
|
// Delay at least one RTC clock cycle so it's registers have updated with the most
|
||||||
|
// recent time settings.
|
||||||
|
sleep_us(23);
|
||||||
|
|
||||||
|
// Sample RTC and time_us_64() as close together as possible, so the offset
|
||||||
|
// calculated for the latter can be as accurate as possible.
|
||||||
datetime_t t;
|
datetime_t t;
|
||||||
rtc_get_datetime(&t);
|
rtc_get_datetime(&t);
|
||||||
|
uint64_t us = time_us_64();
|
||||||
|
|
||||||
|
// Calculate the difference between the RTC Epoch seconds and time_us_64().
|
||||||
uint64_t s = timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec);
|
uint64_t s = timeutils_seconds_since_epoch(t.year, t.month, t.day, t.hour, t.min, t.sec);
|
||||||
return s * 1000000000ULL;
|
time_us_64_offset_from_epoch = (uint64_t)s * 1000000ULL - us;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t mp_hal_time_ns(void) {
|
||||||
|
// The RTC only has seconds resolution, so instead use time_us_64() to get a more
|
||||||
|
// precise measure of Epoch time. Both these "clocks" are clocked from the same
|
||||||
|
// source so they remain synchronised, and only differ by a fixed offset (calculated
|
||||||
|
// in mp_hal_time_ns_set_from_rtc).
|
||||||
|
return (time_us_64_offset_from_epoch + time_us_64()) * 1000ULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate a random locally administered MAC address (LAA)
|
// Generate a random locally administered MAC address (LAA)
|
||||||
|
@ -39,6 +39,7 @@ extern int mp_interrupt_char;
|
|||||||
extern ringbuf_t stdin_ringbuf;
|
extern ringbuf_t stdin_ringbuf;
|
||||||
|
|
||||||
void mp_hal_set_interrupt_char(int c);
|
void mp_hal_set_interrupt_char(int c);
|
||||||
|
void mp_hal_time_ns_set_from_rtc(void);
|
||||||
|
|
||||||
static inline void mp_hal_delay_us(mp_uint_t us) {
|
static inline void mp_hal_delay_us(mp_uint_t us) {
|
||||||
sleep_us(us);
|
sleep_us(us);
|
||||||
|
Loading…
Reference in New Issue
Block a user