Menu

Expand
Rate this page:

Time Functions

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

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
usec A pointer to non-secure memory into which the microsecond counter value will be written by Microvisor

Possible errors

Error Value Description
MV_STATUS_PARAMETERFAULT usec 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

// 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
usec A pointer to non-secure memory into which the microsecond wall time will be written by Microvisor

Possible errors

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

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 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:57.493 [DEBUG] Request sent to Twilio
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(&timestamp[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;
}
Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

Thank you for your feedback!

Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

Sending your feedback...
🎉 Thank you for your feedback!
Something went wrong. Please try again.

Thanks for your feedback!

Refer us and get $10 in 3 simple steps!

Step 1

Get link

Get a free personal referral link here

Step 2

Give $10

Your user signs up and upgrade using link

Step 3

Get $10

1,250 free SMSes
OR 1,000 free voice mins
OR 12,000 chats
OR more