Time Functions
Microvisor system calls include the following functions for application timekeeping operations:
Return Values and Errors
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
).
mvGetMicroseconds()
Gets the current value of Microvisor’s free-running microsecond clock
Declaration
extern enum MvStatus mvGetMicroseconds(uint64_t *usec);
Parameters
Parameter |
Description |
---|---|
|
A pointer to non-secure memory into which the microsecond counternvalue will be written by Microvisor |
Possible Errors
Error Value |
Description |
---|---|
|
|
Description
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.
Example
// Tick counters
uint64_t last_tick = 0;
uint64_t tick = 0;
while (true) {
enum MvStatus status = mvGetMicroseconds(&tick);
if (status == MV_STATUS_OKAY && tick - last_tick > LED_FLASH_PERIOD_US) {
// Toggle the USER LED's GPIO pin every LED_FLASH_PERIOD_US microseconds
HAL_GPIO_TogglePin(LED_GPIO_BANK, LED_GPIO_PIN);
last_tick = tick;
}
}
mvGetWallTime()
Gets the current time in non-leap microseconds since the Unix epoch
Declaration
extern enum MvStatus mvGetWallTime(uint64_t *usec);
Parameters
Parameter |
Description |
---|---|
|
A pointer to non-secure memory into which the microsecond wall time will be written by Microvisor |
Possible Errors
Error Value |
Description |
---|---|
|
|
|
The device’s RTC has not yet been set from the server |
Description
This call 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.
Example
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:
2022-05-10 13:40:57.489 [DEBUG] Temperature: 25.31
2022-05-10 13:40:57.490 [DEBUG] Network handle: 321452355
2022-05-10 13:40:57.491 [DEBUG] HTTP channel handle: 1702803732
2022-05-10 13:40:57.492 [DEBUG] Sending HTTP request
2022-05-10 13:40:58.023 [ERROR] HTTP status code: 429
2022-05-10 13:40:58.024 [DEBUG] HTTP channel closed
Here is the code:
// Prepare and add a timestamp to log output if we can.
// If we can't, we show no time
char timestamp[64] = {0};
uint64_t usec = 0;
enum MvStatus status = mvGetWallTime(&usec);
if (status == MV_STATUS_OKAY) {
// Get the second and millisecond times
time_t sec = (time_t)usec / 1000000;
time_t msec = (time_t)usec / 1000;
// Write time string as "2022-05-10 13:30:58.XXX "
strftime(timestamp, 64, "%F %T.XXX ", gmtime(&sec));
// Insert the millisecond time over the XXX
sprintf(×tamp[20], "%03u ", (unsigned)(msec % 1000));
}
// Write out the time string. Confirm that Microvisor
// has accepted the request to write data to the channel.
uint32_t time_chars = 0;
size_t len = strlen(timestamp);
if (len > 0) {
status = mvWriteChannelStream(log_handles.channel, (const uint8_t*)timestamp, len, &time_chars);
if (status != MV_STATUS_OKAY) {
errno = EIO;
return -1;
}
}
// Write out the message string. Confirm that Microvisor
// has accepted the request to write data to the channel.
uint32_t msg_chars = 0;
status = mvWriteChannelStream(log_handles.channel, (const uint8_t*)ptr, length, &msg_chars);
if (status == MV_STATUS_OKAY) {
// Return the number of characters written to the channel
return time_chars + msg_chars;
} else {
errno = EIO;
return -1;
}