Skip to contentSkip to navigationSkip to topbar
Rate this page:
On this page

Time Functions


(warning)

Warning

Microvisor Public Beta

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:


Return values and errors

return-values-and-errors page anchor

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

Declaration


_10
extern enum MvStatus mvGetMicroseconds(uint64_t *usec);

Parameters

ParameterDescription
usecA pointer to non-secure memory into which the microsecond counter value will be written by Microvisor

Possible errors

Error ValueDescription
MV_STATUS_PARAMETERFAULTusec does not reference memory accessible to the application

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


_12
// Tick counters
_12
uint64_t last_tick = 0;
_12
uint64_t tick = 0;
_12
_12
while (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

Declaration


_10
extern enum MvStatus mvGetWallTime(uint64_t *usec);

Parameters

ParameterDescription
usecA pointer to non-secure memory into which the microsecond wall time will be written by Microvisor

Possible errors

Error ValueDescription
MV_STATUS_PARAMETERFAULTusec does not reference memory accessible to the application
MV_STATUS_TIMENOTSETThe device's RTC has not yet been set from the server

Description

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.

Example

This example, which modifies a section of the FreeRTOS demo code(link takes you to an external page) 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:


_10
2022-05-10 13:40:57.489 [DEBUG] Temperature: 25.31
_10
2022-05-10 13:40:57.490 [DEBUG] Network handle: 321452355
_10
2022-05-10 13:40:57.491 [DEBUG] HTTP channel handle: 1702803732
_10
2022-05-10 13:40:57.492 [DEBUG] Sending HTTP request
_10
2022-05-10 13:40:58.023 [ERROR] HTTP status code: 429
_10
2022-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
_40
char timestamp[64] = {0};
_40
uint64_t usec = 0;
_40
enum MvStatus status = mvGetWallTime(&usec);
_40
if (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(&timestamp[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.
_40
uint32_t time_chars = 0;
_40
size_t len = strlen(timestamp);
_40
if (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.
_40
uint32_t msg_chars = 0;
_40
status = mvWriteChannelStream(log_handles.channel, (const uint8_t*)ptr, length, &msg_chars);
_40
if (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
}


Rate this page: