From d4b61b00172ccc231307e3ef33f66f28cb6b051f Mon Sep 17 00:00:00 2001 From: Damien George Date: Thu, 24 Sep 2020 12:37:02 +1000 Subject: [PATCH] extmod/utime_mphal: Add generic utime.time_ns() function. It requires mp_hal_time_ns() to be provided by a port. This function allows very accurate absolute timestamps. Enabled on unix, windows, stm32, esp8266 and esp32. Signed-off-by: Damien George --- docs/library/utime.rst | 10 ++++++++-- extmod/utime_mphal.c | 6 ++++++ extmod/utime_mphal.h | 1 + ports/esp32/modutime.c | 1 + ports/esp8266/modutime.c | 1 + ports/stm32/modutime.c | 1 + ports/unix/modtime.c | 1 + tests/extmod/utime_time_ns.py | 24 ++++++++++++++++++++++++ tests/extmod/utime_time_ns.py.exp | 2 ++ 9 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 tests/extmod/utime_time_ns.py create mode 100644 tests/extmod/utime_time_ns.py.exp diff --git a/docs/library/utime.rst b/docs/library/utime.rst index 8c222ede5f..86fd27b3a5 100644 --- a/docs/library/utime.rst +++ b/docs/library/utime.rst @@ -216,8 +216,9 @@ Functions function returns number of seconds since a port-specific reference point in time (for embedded boards without a battery-backed RTC, usually since power up or reset). If you want to develop portable MicroPython application, you should not rely on this function - to provide higher than second precision. If you need higher precision, use - `ticks_ms()` and `ticks_us()` functions, if you need calendar time, + to provide higher than second precision. If you need higher precision, absolute + timestamps, use `time_ns()`. If relative times are acceptable then use the + `ticks_ms()` and `ticks_us()` functions. If you need calendar time, `gmtime()` or `localtime()` without an argument is a better choice. .. admonition:: Difference to CPython @@ -233,3 +234,8 @@ Functions hardware also lacks battery-powered RTC, so returns number of seconds since last power-up or from other relative, hardware-specific point (e.g. reset). + +.. function:: time_ns() + + Similar to `time()` but returns nanoseconds since the Epoch, as an integer (usually + a big integer, so will allocate on the heap). diff --git a/extmod/utime_mphal.c b/extmod/utime_mphal.c index 6aff2cac72..d053cf128b 100644 --- a/extmod/utime_mphal.c +++ b/extmod/utime_mphal.c @@ -99,4 +99,10 @@ STATIC mp_obj_t time_ticks_add(mp_obj_t ticks_in, mp_obj_t delta_in) { } MP_DEFINE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj, time_ticks_add); +// Returns the number of nanoseconds since the Epoch, as an integer. +STATIC mp_obj_t time_time_ns(void) { + return mp_obj_new_int_from_ull(mp_hal_time_ns()); +} +MP_DEFINE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj, time_time_ns); + #endif // MICROPY_PY_UTIME_MP_HAL diff --git a/extmod/utime_mphal.h b/extmod/utime_mphal.h index 88a9ed4d37..57fc348832 100644 --- a/extmod/utime_mphal.h +++ b/extmod/utime_mphal.h @@ -37,5 +37,6 @@ MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_us_obj); MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_ticks_cpu_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_diff_obj); MP_DECLARE_CONST_FUN_OBJ_2(mp_utime_ticks_add_obj); +MP_DECLARE_CONST_FUN_OBJ_0(mp_utime_time_ns_obj); #endif // MICROPY_INCLUDED_EXTMOD_UTIME_MPHAL_H diff --git a/ports/esp32/modutime.c b/ports/esp32/modutime.c index ac3edb4e9b..cf7178e0b1 100644 --- a/ports/esp32/modutime.c +++ b/ports/esp32/modutime.c @@ -97,6 +97,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); diff --git a/ports/esp8266/modutime.c b/ports/esp8266/modutime.c index 86534722c7..bcfbf7baf2 100644 --- a/ports/esp8266/modutime.c +++ b/ports/esp8266/modutime.c @@ -120,6 +120,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, { MP_ROM_QSTR(MP_QSTR_time), MP_ROM_PTR(&time_time_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); diff --git a/ports/stm32/modutime.c b/ports/stm32/modutime.c index 2a37a130df..4bce45eb33 100644 --- a/ports/stm32/modutime.c +++ b/ports/stm32/modutime.c @@ -144,6 +144,7 @@ STATIC const mp_rom_map_elem_t time_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) }, }; STATIC MP_DEFINE_CONST_DICT(time_module_globals, time_module_globals_table); diff --git a/ports/unix/modtime.c b/ports/unix/modtime.c index 5343e479c7..e08409e20e 100644 --- a/ports/unix/modtime.c +++ b/ports/unix/modtime.c @@ -219,6 +219,7 @@ STATIC const mp_rom_map_elem_t mp_module_time_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_ticks_cpu), MP_ROM_PTR(&mp_utime_ticks_cpu_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_add), MP_ROM_PTR(&mp_utime_ticks_add_obj) }, { MP_ROM_QSTR(MP_QSTR_ticks_diff), MP_ROM_PTR(&mp_utime_ticks_diff_obj) }, + { MP_ROM_QSTR(MP_QSTR_time_ns), MP_ROM_PTR(&mp_utime_time_ns_obj) }, { MP_ROM_QSTR(MP_QSTR_gmtime), MP_ROM_PTR(&mod_time_gmtime_obj) }, { MP_ROM_QSTR(MP_QSTR_localtime), MP_ROM_PTR(&mod_time_localtime_obj) }, { MP_ROM_QSTR(MP_QSTR_mktime), MP_ROM_PTR(&mod_time_mktime_obj) }, diff --git a/tests/extmod/utime_time_ns.py b/tests/extmod/utime_time_ns.py new file mode 100644 index 0000000000..8f3890f1cb --- /dev/null +++ b/tests/extmod/utime_time_ns.py @@ -0,0 +1,24 @@ +# test utime.time_ns() + +try: + import utime + + utime.sleep_us + utime.time_ns +except (ImportError, AttributeError): + print("SKIP") + raise SystemExit + + +t0 = utime.time_ns() +utime.sleep_us(1000) +t1 = utime.time_ns() + +# Check that time_ns increases. +print(t0 < t1) + +# Check that time_ns counts correctly, but be very lenient with the upper bound (50ms). +if 950000 < t1 - t0 < 50000000: + print(True) +else: + print(t0, t1, t1 - t0) diff --git a/tests/extmod/utime_time_ns.py.exp b/tests/extmod/utime_time_ns.py.exp new file mode 100644 index 0000000000..dbde422651 --- /dev/null +++ b/tests/extmod/utime_time_ns.py.exp @@ -0,0 +1,2 @@ +True +True