Microvisor is in a pre-release phase and the information contained in this document is subject to change. Some features referenced below may not be fully available until Microvisor's General Availability (GA) release.
Microvisor system calls include the following functions for application timekeeping operations:
All of the functions described below return a 32-bit integer that is one of the values from the standard Microvisor enumeration MvStatus
. All possible error values for a given system call are provided with each function's description.
Success is always signaled by a return value of zero (MV_STATUS_OKAY
).
Gets the current value of Microvisor's free-running microsecond clock
_10extern enum MvStatus mvGetMicroseconds(uint64_t *usec);
Parameter | Description |
---|---|
usec | A pointer to non-secure memory into which the microsecond counter value will be written by Microvisor |
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT | usec does not reference memory accessible to the application |
Microvisor's microsecond clock starts from zero when Microvisor is run, and counts up from then on. It has no relation to — and may drift with respect to — wall time.
_12// Tick counters_12uint64_t last_tick = 0;_12uint64_t tick = 0;_12_12while (true) {_12 enum MvStatus status = mvGetMicroseconds(&tick);_12 if (status == MV_STATUS_OKAY && tick - last_tick > LED_FLASH_PERIOD_US) {_12 // Toggle the USER LED's GPIO pin every LED_FLASH_PERIOD_US microseconds_12 HAL_GPIO_TogglePin(LED_GPIO_BANK, LED_GPIO_PIN);_12 last_tick = tick;_12 }_12}
Gets the current time in non-leap microseconds since the Unix epoch
_10extern enum MvStatus mvGetWallTime(uint64_t *usec);
Parameter | Description |
---|---|
usec | A pointer to non-secure memory into which the microsecond wall time will be written by Microvisor |
Error Value | Description |
---|---|
MV_STATUS_PARAMETERFAULT | usec does not reference memory accessible to the application |
MV_STATUS_TIMENOTSET | The device's RTC has not yet been set from the server |
This will return MV_STATUS_TIMENOTSET
on restart until the real-time clock (RTC) is synchronized with the server. Clock synchronization takes place periodically during application lifecycle: for example, it is updated regularly while the device is connected, and again when the device connects or re-connects. The value written into usec
may therefore jump forward or backward in response to an updated time from the server.
This example, which modifies a section of the FreeRTOS demo code logging.c
file's _write()
function, shows how to use the 64-bit wall clock time to feed the standard gmtime()
and strftime()
functions (defined in <time.h>
) to create a timestamp string to prefix any output sent to printf()
. The code uses the same source to include the millisecond time:
_102022-05-10 13:40:57.489 [DEBUG] Temperature: 25.31_102022-05-10 13:40:57.490 [DEBUG] Network handle: 321452355_102022-05-10 13:40:57.491 [DEBUG] HTTP channel handle: 1702803732_102022-05-10 13:40:57.492 [DEBUG] Sending HTTP request_102022-05-10 13:40:58.023 [ERROR] HTTP status code: 429_102022-05-10 13:40:58.024 [DEBUG] HTTP channel closed
Here is the code:
_40// Prepare and add a timestamp to log output if we can._40// If we can't, we show no time_40char timestamp[64] = {0};_40uint64_t usec = 0;_40enum MvStatus status = mvGetWallTime(&usec);_40if (status == MV_STATUS_OKAY) {_40 // Get the second and millisecond times_40 time_t sec = (time_t)usec / 1000000;_40 time_t msec = (time_t)usec / 1000;_40_40 // Write time string as "2022-05-10 13:30:58.XXX "_40 strftime(timestamp, 64, "%F %T.XXX ", gmtime(&sec));_40_40 // Insert the millisecond time over the XXX_40 sprintf(×tamp[20], "%03u ", (unsigned)(msec % 1000));_40}_40_40// Write out the time string. Confirm that Microvisor_40// has accepted the request to write data to the channel._40uint32_t time_chars = 0;_40size_t len = strlen(timestamp);_40if (len > 0) {_40 status = mvWriteChannelStream(log_handles.channel, (const uint8_t*)timestamp, len, &time_chars);_40 if (status != MV_STATUS_OKAY) {_40 errno = EIO;_40 return -1;_40 }_40}_40_40// Write out the message string. Confirm that Microvisor_40// has accepted the request to write data to the channel._40uint32_t msg_chars = 0;_40status = mvWriteChannelStream(log_handles.channel, (const uint8_t*)ptr, length, &msg_chars);_40if (status == MV_STATUS_OKAY) {_40 // Return the number of characters written to the channel_40 return time_chars + msg_chars;_40} else {_40 errno = EIO;_40 return -1;_40}