One Second Timestamping#
Because Wi-SUN network changes are rare while connection times are in days or months, the underlying unit of time measurement used by the Wi-SUN Stack down to the microsecond is not necessary for long-term observability of network connection. We therefore:
- Set up a 1-second timer to count seconds 
- Add functions to format current time and delays as dd-hh:mm:ss 
To get a 1-second timestamp, do the following steps.
Note: This is all done in
app_timestamp.candapp_timestamp.h, which you can use by copy/pasting both files next to yourapp.cfile.
Simplicity Studio will automatically compile any .c file present under the project folder, so no action is required to add app_timestamp.c to the compilation once the file is copied.
Declaration of a 64-bit app_timestamp Variable#
sl_sleeptimer_timestamp_64_t app_timestamp;Creation of a Callback Function to Increment the Timestamp by 1#
void app_timer_callback(sl_sleeptimer_timer_handle_t *handle, void *data) {
  (void)handle;
  (void)data;
  app_timestamp++;
}Protect Access to the Variable Using a Mutex#
static const osMutexAttr_t _app_timestamp_mutex_attr = {
  .name      = "AppTimestampMutex",
  .attr_bits = osMutexRecursive,
  .cb_mem    = NULL,
  .cb_size   = 0U
};__STATIC_INLINE void _app_timestamp_mutex_acquire(void)
{
  assert(osMutexAcquire(_app_timestamp_mutex, osWaitForever) == osOK);
}__STATIC_INLINE void _app_timestamp_mutex_release(void)
{
  assert(osMutexRelease(_app_timestamp_mutex) == osOK);
}Timestamp Init#
sl_status_t app_timestamp_init(void) {
  sl_status_t status;
  uint32_t app_timer_timeout;
  // init mutex
  _app_timestamp_mutex = osMutexNew(&_app_timestamp_mutex_attr);
  assert(_app_timestamp_mutex != NULL);
  app_timestamp =  0;
  status = sl_sleeptimer_init();
  if (status != SL_STATUS_OK) {
      printf("Error initializing sleeptimer. Status %lu\n", status);
      return status;
  }
  app_timer_timeout = (uint32_t)1.0*sl_sleeptimer_get_timer_frequency();
  status = sl_sleeptimer_start_periodic_timer(&app_timer,
                                              app_timer_timeout,
                                              app_timer_callback,
                                              NULL, 0, 0);
  if (status != SL_STATUS_OK) {
      printf("Error starting periodic timer 'app_timer'. Status %lu\n", status);
      return status;
  }
  return status;
}Following this:
- app_timestampis set to- 0when- app_timestamp_init()is called
- app_timer_callback()is called every second- app_timestampis increased by- 1every second
 
- You can retrieve it safely using the mutex 
Retrieve the Current Timestamp Decimal Value#
uint64_t     now_sec      (void) {
  sl_sleeptimer_timestamp_64_t current_sec;
  _app_timestamp_mutex_acquire();
  current_sec = app_timestamp;
  _app_timestamp_mutex_release();
  return (uint64_t)current_sec;
}You can use now_sec() to store the current time in decimal values:
  uint64_t current_time_secs;
  current_time_secs = now_sec();Utility Functions to Process Timestamp Values#
Transform a Timestamp in days/hours/mins/secs Units#
Mainly used as a convenience function, this should rarely be used from outside this code:
sl_status_t  d_h_m_s_total(sl_sleeptimer_timestamp_64_t timestamp_secs,
                    uint16_t* days,
                    uint64_t* hours,
                    uint64_t* mins,
                    uint64_t* secs
) {
  *days  = timestamp_secs / 60 / 60 / 24;
  *hours = timestamp_secs / 60 / 60;
  *mins  = timestamp_secs / 60;
  *secs  = timestamp_secs;
  return SL_STATUS_OK;
}Transform a Timestamp as days:hours:mins:secs Decimal Values#
sl_status_t  d_h_m_s      (sl_sleeptimer_timestamp_64_t timestamp_secs,
                    uint16_t* days,
                    uint8_t* hours,
                    uint8_t* mins,
                    uint8_t* secs) {
  uint64_t hours_total;
  uint64_t mins_total;
  uint64_t secs_total;
  d_h_m_s_total(timestamp_secs, days, &hours_total, &mins_total, &secs_total);
  *days = *days;
  *hours = hours_total % 24;
  *mins  = mins_total  % 60;
  *secs  = secs_total  % 60;
  return SL_STATUS_OK;
}Format a Timestamp as a days:hours:mins:secs Text String#
char*        dhms         (sl_sleeptimer_timestamp_64_t timestamp_secs) {
  uint16_t days;
  uint8_t  hours, mins, secs;
  d_h_m_s(timestamp_secs, &days, &hours, &mins, &secs);
  snprintf(time_str, TIME_STRING_LEN, "%3d:%02d:%02d:%02d", days, hours, mins, secs);
  return time_str;
}This can be used in traces as follows:
printf("Current time is %s\n", now_str());With a Current time is   0:01:23:45 result, if the application has been running for 0 day, 1 hour, 23 minutes and 45 seconds.
Get app_timestamp as a Text String#
char*        now_str     (void) {
  return dhms(now_sec());
}Trace Timestamping and Routing Macros#
A set of macros are defined to allow sending traces to the console, the RTT traces, or both:
#define printfTime(...)     printf("[%s] ", now_str()); printf(__VA_ARGS__)
#define printfRTT(...)      SEGGER_RTT_printf(0, __VA_ARGS__)
#define printfTimeRTT(...)  SEGGER_RTT_printf(0, "[%s] ", now_str()); SEGGER_RTT_printf(0, __VA_ARGS__)
#define printfBoth(...)     SEGGER_RTT_printf(0, __VA_ARGS__); printf(__VA_ARGS__)
#define printfBothTime(...) SEGGER_RTT_printf(0, "[%s] ", now_str()); SEGGER_RTT_printf(0, __VA_ARGS__); printf("[%s] ", now_str()); printf(__VA_ARGS__)The above makes it easy in the application to:
- Select to add a timestamp or not to traces. 
- Print a trace to the console or the RTT traces, or both. 
Use the Timestamp#
In app.c, #include "app-timestamp.h" to get access to the timestamping resources.
In app.c/app_task(), initialize the one second timestamp:


It is convenient to declare variables to store various time values:
uint64_t connect_time_sec;           // time stamp of Wisun connect call
uint64_t connection_time_sec;        // last connection time stamp
uint64_t disconnection_time_sec;     // last disconnection time stampThese can be used as follows (example code, not part of the sample application):
  printfBothTime("running since %s\n", now_str());
  connect_time_sec = now_sec();
  app_wisun_connect_and_wait();
  /* Some time will pass until we're connected... */
  connection_time_sec = now_sec();
  printfBothTime("Connected in %s\n", dhms(connection_time_sec - connect_time_sec));