}
/****************************************************************************
- * Name: up_rtcinitialize
+ * Name: up_rtc_initialize
*
* Description:
* Function called by OS to initialize RTC.
*
****************************************************************************/
-int up_rtcinitialize(void)
+int up_rtc_initialize(void)
{
#ifdef CONFIG_S5J_RTC
int ret;
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* Private Types
****************************************************************************/
-struct rtc_upperhalf_s {
- FAR struct rtc_lowerhalf_s *lower; /* Contained lower half driver */
+#ifdef CONFIG_RTC_ALARM
+struct rtc_alarminfo_s
+{
+ bool active; /* True: alarm is active */
+ uint8_t signo; /* Signal number for alarm notification */
+ pid_t pid; /* Identifies task to be notified */
+ union sigval sigvalue; /* Data passed with notification */
+};
+#endif
+
+struct rtc_upperhalf_s
+{
+ FAR struct rtc_lowerhalf_s *lower; /* Contained lower half driver */
+
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
- uint8_t crefs; /* Number of open references */
- bool unlinked; /* True if the driver has been unlinked */
+ uint8_t crefs; /* Number of open references */
+ bool unlinked; /* True if the driver has been unlinked */
+#endif
+
+#ifdef CONFIG_RTC_ALARM
+ /*
+ * This is an array, indexed by the alarm ID, that provides
+ * information needed to map an alarm expiration to a signal event.
+ */
+
+ struct rtc_alarminfo_s alarminfo[CONFIG_RTC_NALARMS];
#endif
};
/* Internal logic */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
-static void rtc_destroy(FAR struct rtc_upperhalf_s *upper);
+static void rtc_destroy(FAR struct rtc_upperhalf_s *upper);
+#endif
+
+#ifdef CONFIG_RTC_ALARM
+static void rtc_alarm_callback(FAR void *priv, int id);
#endif
/* Character driver methods */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
-static int rtc_open(FAR struct file *filep);
-static int rtc_close(FAR struct file *filep);
+static int rtc_open(FAR struct file *filep);
+static int rtc_close(FAR struct file *filep);
#endif
-static ssize_t rtc_read(FAR struct file *filep, FAR char *buffer, size_t buflen);
-static ssize_t rtc_write(FAR struct file *filep, FAR const char *buffer, size_t buflen);
-static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
+static ssize_t rtc_read(FAR struct file *filep, FAR char *buffer,
+ size_t buflen);
+static ssize_t rtc_write(FAR struct file *filep, FAR const char *buffer,
+ size_t buflen);
+static int rtc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
-static int rtc_unlink(FAR struct inode *inode);
+static int rtc_unlink(FAR struct inode *inode);
#endif
/****************************************************************************
* Private Data
****************************************************************************/
-static const struct file_operations rtc_fops = {
+static const struct file_operations rtc_fops =
+{
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
- rtc_open, /* open */
- rtc_close, /* close */
+ rtc_open, /* open */
+ rtc_close, /* close */
#else
- 0, /* open */
- 0, /* close */
+ 0, /* open */
+ 0, /* close */
#endif
- rtc_read, /* read */
- rtc_write, /* write */
- 0, /* seek */
- rtc_ioctl, /* ioctl */
+ rtc_read, /* read */
+ rtc_write, /* write */
+ 0, /* seek */
+ rtc_ioctl, /* ioctl */
#ifndef CONFIG_DISABLE_POLL
- 0, /* poll */
+ 0, /* poll */
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
- rtc_unlink /* unlink */
+ rtc_unlink /* unlink */
#endif
};
****************************************************************************/
/****************************************************************************
- * Name: rtc_destory
+ * Name: rtc_destroy
****************************************************************************/
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
static void rtc_destroy(FAR struct rtc_upperhalf_s *upper)
{
- /* If the lower half driver provided a destroy method, then call that
- * method now in order order to clean up resources used by the lower-half
- * driver.
+ /*
+ * If the lower half driver provided a destroy method, then call that
+ * method now in order order to clean up resources used by the
+ * lower-half driver.
*/
DEBUGASSERT(upper->lower && upper->lower->ops);
#endif
/****************************************************************************
+ * Name: rtc_alarm_callback
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC_ALARM
+static void rtc_alarm_callback(FAR void *priv, int alarmid)
+{
+ FAR struct rtc_upperhalf_s *upper = (FAR struct rtc_upperhalf_s *)priv;
+ FAR struct rtc_alarminfo_s *alarminfo;
+
+ DEBUGASSERT(upper != NULL && alarmid >= 0 &&
+ alarmid < CONFIG_RTC_NALARMS);
+ alarminfo = &upper->alarminfo[alarmid];
+
+ /*
+ * Do we think that the alaram is active? It might be due to some
+ * race condition between a cancellation event and the alarm
+ * expiration.
+ */
+
+ if (alarminfo->active) {
+ /* Yes.. signal the alarm expriration */
+
+#ifdef CONFIG_CAN_PASS_STRUCTS
+ (void)sigqueue(alarminfo->pid, alarminfo->signo,
+ alarminfo->sigvalue);
+#else
+ (void)sigqueue(alarminfo->pid, alarminfo->signo,
+ alarminfo->sigvalue->sival_ptr);
+#endif
+ }
+
+ /* The alarm is no longer active */
+
+ alarminfo->active = false;
+}
+#endif
+
+/****************************************************************************
* Name: rtc_open
****************************************************************************/
FAR struct inode *inode;
FAR struct rtc_upperhalf_s *upper;
- /* Get the reference to our internal state structure from the inode
+ /*
+ * Get the reference to our internal state structure from the inode
* structure.
*/
FAR struct inode *inode;
FAR struct rtc_upperhalf_s *upper;
- /* Get the reference to our internal state structure from the inode
+ /*
+ * Get the reference to our internal state structure from the inode
* structure.
*/
DEBUGASSERT(upper->crefs > 0);
upper->crefs--;
- /* If the count has decremented to zero and the driver has been unlinked,
- * then commit Hara-Kiri now.
+ /*
+ * If the count has decremented to zero and the driver has been
+ * unlinked, then commit Hara-Kiri now.
*/
- if (upper->crefs == 0 && upper->unlinked) {
+ if (upper->crefs == 0 && upper->unlinked)
+ {
rtc_destroy(upper);
}
static ssize_t rtc_read(FAR struct file *filep, FAR char *buffer, size_t len)
{
- return 0; /* Return EOF */
+ return 0; /* Return EOF */
}
/****************************************************************************
* Name: rtc_write
****************************************************************************/
-static ssize_t rtc_write(FAR struct file *filep, FAR const char *buffer, size_t len)
+static ssize_t rtc_write(FAR struct file *filep, FAR const char *buffer,
+ size_t len)
{
- return len; /* Say that everything was written */
+ return len; /* Say that everything was written */
}
/****************************************************************************
FAR const struct rtc_ops_s *ops;
int ret = -ENOSYS;
- /* Get the reference to our internal state structure from the inode
+ /*
+ * Get the reference to our internal state structure from the inode
* structure.
*/
upper = inode->i_private;
DEBUGASSERT(upper->lower && upper->lower->ops);
- /* We simply forward all ioctl() commands to the lower half. The upper
+ /*
+ * We simply forward all ioctl() commands to the lower half. The upper
* half is nothing more than a thin driver shell over the lower level
* RTC implementation.
*/
ops = upper->lower->ops;
switch (cmd) {
- /* RTC_RD_TIME returns the current RTC time.
+
+ /*
+ * RTC_RD_TIME returns the current RTC time.
*
- * Argument: A writeable reference to a struct rtc_time to receive the
- * RTC's time.
+ * Argument: A writeable reference to a struct rtc_time to
+ * receive the RTC's time.
*/
case RTC_RD_TIME: {
- FAR struct rtc_time *rtctime = (FAR struct rtc_time *)((uintptr_t)arg);
+ FAR struct rtc_time *rtctime =
+ (FAR struct rtc_time *)((uintptr_t)arg);
if (ops->rdtime) {
ret = ops->rdtime(upper->lower, rtctime);
}
break;
- /* RTC_SET_TIME sets the RTC's time
+ /*
+ * RTC_SET_TIME sets the RTC's time
*
* Argument: A read-only reference to a struct rtc_time containing the
* the new time to be set.
*/
case RTC_SET_TIME: {
- FAR const struct rtc_time *rtctime = (FAR const struct rtc_time *)((uintptr_t)arg);
+ FAR const struct rtc_time *rtctime =
+ (FAR const struct rtc_time *)((uintptr_t)arg);
if (ops->settime) {
ret = ops->settime(upper->lower, rtctime);
break;
#ifdef CONFIG_RTC_ALARM
- /* RTC_ALM_READ reads the alarm time (for RTCs that support alarms)
- *
- * Argument: A writeable reference to a struct rtc_time to receive the
- * RTC's alarm time.
- */
-
- case RTC_ALM_READ: {
- FAR struct rtc_time *almtime = (FAR struct rtc_time *)((uintptr_t)arg);
-
- if (ops->almread) {
- ret = ops->almread(upper->lower, almtime);
- }
- }
- break;
-
- /* RTC_ALM_SET sets the alarm time (for RTCs that support alarms).
+ /*
+ * RTC_SET_ALARM sets the alarm time.
*
* Argument: A read-only reference to a struct rtc_time containing the
* new alarm time to be set.
*/
- case RTC_ALM_SET: {
- FAR const struct rtc_time *almtime = (FAR const struct rtc_time *)((uintptr_t)arg);
+ case RTC_SET_ALARM: {
+ FAR const struct rtc_setalarm_s *alarminfo =
+ (FAR const struct rtc_setalarm_s *)((uintptr_t)arg);
+ FAR struct rtc_alarminfo_s *upperinfo;
+ struct lower_setalarm_s lowerinfo;
+ int alarmid;
- if (ops->almset) {
- ret = ops->almset(upper->lower, almtime);
- }
- }
- break;
-#endif /* CONFIG_RTC_ALARM */
+ DEBUGASSERT(alarminfo != NULL);
+ alarmid = alarminfo->id;
+ DEBUGASSERT(alarmid >= 0 && alarmid < CONFIG_RTC_NALARMS);
-#ifdef CONFIG_RTC_PERIODIC
- /* RTC_IRQP_READ read the frequency for periodic interrupts (for RTCs
- * that support periodic interrupts)
- *
- * Argument: A pointer to a writeable unsigned long value in which to
- * receive the frequency value.
- */
+ /* Is the alarm active? */
+
+ upperinfo = &upper->alarminfo[alarmid];
+ if (upperinfo->active) {
+ /* Yes, cancel the alarm */
- case RTC_IRQP_READ: {
- FAR unsigned long *irqpfreq = (FAR unsigned long *)((uintptr_t)arg);
+ if (ops->cancelalarm) {
+ (void)ops->cancelalarm(upper->lower, alarmid);
+ }
- if (ops->irqpread) {
- ret = ops->irqpread(upper->lower, irqpfreq);
+ upperinfo->active = false;
}
- }
- break;
- /* RTC_IRQP_SET set the frequency for periodic interrupts (for RTCs that
- * support periodic interrupts)
- *
- * Argument: An unsigned long value providing the new periodic frequency
- */
+ if (ops->setalarm) {
+ pid_t pid;
- case RTC_IRQP_SET: {
- if (ops->irqpset) {
- ret = ops->irqpset(upper->lower, arg);
- }
- }
- break;
-#endif /* CONFIG_RTC_PERIODIC */
+ /* A PID of zero means to signal the calling task */
-#ifdef CONFIG_RTC_ALARM
- /* RTC_AIE_ON enable alarm interrupts (for RTCs that support alarms)
- *
- * Argument: None
- */
+ pid = alarminfo->pid;
+ if (pid == 0) {
+ pid = getpid();
+ }
- case RTC_AIE_ON: {
- if (ops->aie) {
- ret = ops->aie(upper->lower, true);
- }
- }
- break;
+ /*
+ * Save the signal info to be used to notify the
+ * caller when the alarm expires.
+ */
- /* RTC_AIE_OFF disable the alarm interrupt (for RTCs that support
- * alarms)
- *
- * Argument: None
- */
+ upperinfo->active = true;
+ upperinfo->signo = alarminfo->signo;
+ upperinfo->pid = pid;
+ upperinfo->sigvalue = alarminfo->sigvalue;
- case RTC_AIE_OFF: {
- if (ops->aie) {
- ret = ops->aie(upper->lower, false);
- }
- }
- break;
-#endif /* CONFIG_RTC_ALARM */
+ /*
+ * Format the alarm info needed by the lower half
+ * driver
+ */
-#ifdef CONFIG_RTC_ONESEC
- /* RTC_UIE_ON enable the interrupt on every clock update (for RTCs that
- * support this once-per-second interrupt).
- *
- * Argument: None
- */
+ lowerinfo.id = alarmid;
+ lowerinfo.cb = rtc_alarm_callback;
+ lowerinfo.priv = (FAR void *)upper;
+ lowerinfo.time = alarminfo->time;
+
+ /* Then set the alarm */
- case RTC_UIE_ON: {
- if (ops->uie) {
- ret = ops->uie(upper->lower, true);
+ ret = ops->setalarm(upper->lower, &lowerinfo);
+ if (ret < 0) {
+ upperinfo->active = false;
+ }
}
}
break;
- /* RTC_UIE_OFF disable the interrupt on every clock update (for RTCs
- * that support this once-per-second interrupt).
+ /*
+ * RTC_SET_RELATIVE sets the alarm time relative to the current time.
*
- * Argument: None
+ * Argument: A read-only reference to a struct rtc_setrelative_s
+ * containing the new relative alarm time to be set.
*/
- case RTC_UIE_OFF: {
- if (ops->uie) {
- ret = ops->uie(upper->lower, false);
- }
- }
- break;
-#endif /* CONFIG_RTC_ONESEC */
+ case RTC_SET_RELATIVE: {
+ FAR const struct rtc_setrelative_s *alarminfo =
+ (FAR const struct rtc_setrelative_s *)((uintptr_t)arg);
+ FAR struct rtc_alarminfo_s *upperinfo;
+ struct lower_setrelative_s lowerinfo;
+ int alarmid;
-#ifdef CONFIG_RTC_PERIODIC
- /* RTC_PIE_ON enable the periodic interrupt (for RTCs that support these
- * periodic interrupts).
- *
- * Argument: None
- */
+ DEBUGASSERT(alarminfo != NULL);
+ alarmid = alarminfo->id;
+ DEBUGASSERT(alarmid >= 0 && alarmid < CONFIG_RTC_NALARMS);
- case RTC_PIE_ON: {
- if (ops->pie) {
- ret = ops->pie(upper->lower, true);
- }
- }
- break;
+ /* Is the alarm active? */
- /* RTC_PIE_OFF disable the periodic interrupt (for RTCs that support
- * these periodic interrupts).
- *
- * Argument: None
- */
+ upperinfo = &upper->alarminfo[alarmid];
+ if (upperinfo->active) {
+ /* Yes, cancel the alarm */
- case RTC_PIE_OFF: {
- if (ops->pie) {
- ret = ops->pie(upper->lower, false);
+ if (ops->cancelalarm) {
+ (void)ops->cancelalarm(upper->lower, alarmid);
+ }
+
+ upperinfo->active = false;
}
- }
- break;
-#endif /* CONFIG_RTC_PERIODIC */
-#ifdef CONFIG_RTC_EPOCHYEAR
- /* RTC_EPOCH_READ read the Epoch.
- *
- * Argument: A reference to a writeable unsigned low variable that will
- * receive the Epoch value.
- */
+ if (ops->setrelative) {
+ pid_t pid;
- case RTC_EPOCH_READ: {
- FAR unsigned long *epoch = (FAR unsigned long *)((uintptr_t)arg);
+ /* A PID of zero means to signal the calling task */
- if (ops->rdepoch) {
- ret = ops->rdepoch(upper->lower, epoch);
- }
- }
- break;
+ pid = alarminfo->pid;
+ if (pid == 0) {
+ pid = getpid();
+ }
- /* RTC_EPOCH_SET set the Epoch
- *
- * Argument: An unsigned long value containing the new Epoch value to be
- * set.
- */
+ /*
+ * Save the signal info to be used to notify the
+ * caller when the alarm expires.
+ */
- case RTC_EPOCH_SET: {
- if (ops->setepoch) {
- ret = ops->setepoch(upper->lower, arg);
- }
- }
- break;
-#endif /* CONFIG_RTC_EPOCHYEAR */
+ upperinfo->active = true;
+ upperinfo->signo = alarminfo->signo;
+ upperinfo->pid = pid;
+ upperinfo->sigvalue = alarminfo->sigvalue;
-#ifdef CONFIG_RTC_ALARM
- /* RTC_WKALM_RD read the current alarm
- *
- * Argument: A writeable reference to struct rtc_wkalrm to receive the
- * current alarm settings.
- */
+ /*
+ * Format the alarm info needed by the lower half
+ * driver
+ */
+
+ lowerinfo.id = alarmid;
+ lowerinfo.cb = rtc_alarm_callback;
+ lowerinfo.priv = (FAR void *)upper;
+ lowerinfo.reltime = alarminfo->reltime;
- case RTC_WKALM_RD: {
- FAR struct rtc_wkalrm *wkalrm = (FAR struct rtc_wkalrm *)((uintptr_t)arg);
+ /* Then set the alarm */
- if (ops->rdwkalm) {
- ret = ops->rdwkalm(upper->lower, wkalrm);
+ ret = ops->setrelative(upper->lower, &lowerinfo);
+ if (ret < 0) {
+ upperinfo->active = false;
+ }
}
}
break;
- /* RTC_WKALM_SET set the alarm.
+ /*
+ * RTC_WKALRM_CANCEL cancel the alarm.
*
- * Argument: A read-only reference to struct rtc_wkalrm containing the
- * new alarm settings.
+ * Argument: An ALARM ID value that indicates which alarm should be
+ * canceled.
*/
- case RTC_WKALM_SET: {
- FAR const struct rtc_wkalrm *wkalrm = (FAR const struct rtc_wkalrm *)((uintptr_t)arg);
+ case RTC_CANCEL_ALARM: {
+ int alarmid = (int)arg;
- if (ops->setwkalm) {
- ret = ops->setwkalm(upper->lower, wkalrm);
+ DEBUGASSERT(alarmid >= 0 && alarmid < CONFIG_RTC_NALARMS);
+ if (ops->cancelalarm) {
+ ret = ops->cancelalarm(upper->lower, alarmid);
}
}
break;
-#endif /* CONFIG_RTC_ALARM */
- /* Forward any unrecognized IOCTLs to the lower half driver... they
+#endif /* CONFIG_RTC_ALARM */
+
+ /*
+ * Forward any unrecognized IOCTLs to the lower half driver... they
* may represent some architecture-specific command.
*/
{
FAR struct rtc_upperhalf_s *upper;
- /* Get the reference to our internal state structure from the inode
+ /*
+ * Get the reference to our internal state structure from the inode
* structure.
*/
upper->unlinked = true;
- /* If there are no further open references to the driver, then commit
+ /*
+ * If there are no further open references to the driver, then commit
* Hara-Kiri now.
*/
/* Allocate an upper half container structure */
- upper = (FAR struct rtc_upperhalf_s *)kmm_malloc(sizeof(struct rtc_upperhalf_s));
+ upper = (FAR struct rtc_upperhalf_s *)kmm_zalloc(
+ sizeof(struct rtc_upperhalf_s));
if (!upper) {
return -ENOMEM;
}
/* Initialize the upper half container */
- upper->lower = lower; /* Contain lower half driver */
+ upper->lower = lower; /* Contain lower half driver */
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
- upper->crefs = 0; /* No open references */
- upper->unlinked = false; /* Driver is not unlinked */
+ upper->crefs = 0; /* No open references */
+ upper->unlinked = false; /* Driver is not unlinked */
#endif
- /* Create the driver name. There is space for the a minor number up to 6
- * characters
+ /*
+ * Create the driver name. There is space for the a minor number
+ * up to 6 characters
*/
snprintf(devpath, 16, "/dev/rtc%d", minor);
EXTERN uint32_t g_oneshot_maxticks;
#endif
+#ifdef CONFIG_RTC
+/*
+ * Variable determines the state of the RTC module.
+ *
+ * After initialization value is set to 'true' if RTC starts successfully.
+ * The value can be changed to false also during operation if RTC for
+ * some reason fails.
+ */
+
+EXTERN volatile bool g_rtc_enabled;
+#endif
+
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
#endif
/****************************************************************************
+ * Name: up_rtc_initialize
+ *
+ * Description:
+ * Initialize the builtin, MCU hardware RTC per the selected
+ * configuration. This function is called once very early in the OS
+ * initialization sequence.
+ *
+ * NOTE that initialization of external RTC hardware that depends on the
+ * availability of OS resources (such as SPI or I2C) must be deferred
+ * until the system has fully booted. Other, RTC-specific initialization
+ * functions are used in that case.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno on failure
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_RTC) && !defined(CONFIG_RTC_EXTERNAL)
+int up_rtc_initialize(void);
+#endif
+
+/****************************************************************************
+ * Name: up_rtc_time
+ *
+ * Description:
+ * Get the current time in seconds. This is similar to the standard time()
+ * function. This interface is only required if the low-resolution
+ * RTC/counter hardware implementation selected. It is only used by the
+ * RTOS during initialization to set up the system time when CONFIG_RTC is
+ * set but neither CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set.
+ *
+ * Input Parameters:
+ * None
+ *
+ * Returned Value:
+ * The current time in seconds.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_RTC) && !defined(CONFIG_RTC_HIRES)
+time_t up_rtc_time(void);
+#endif
+
+/****************************************************************************
+ * Name: up_rtc_gettime
+ *
+ * Description:
+ * Get the current time from the high resolution RTC clock/counter. This
+ * interface is only supported by the high-resolution RTC/counter hardware
+ * implementation. It is used to replace the system timer.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_RTC) && defined(CONFIG_RTC_HIRES)
+int up_rtc_gettime(FAR struct timespec *tp);
+#endif
+
+/****************************************************************************
+ * Name: up_rtc_getdatetime
+ *
+ * Description:
+ * Get the current date and time from the date/time RTC. This interface
+ * is only supported by the date/time RTC hardware implementation.
+ * It is used to replace the system timer. It is only used by the RTOS
+ * during initialization to set up the system time when CONFIG_RTC and
+ * CONFIG_RTC_DATETIME are selected (and CONFIG_RTC_HIRES is not).
+ *
+ * NOTE: Some date/time RTC hardware is capability of sub-second accuracy.
+ * That sub-second accuracy is lost in this interface. However, since the
+ * system time is reinitialized on each power-up/reset, there will be no
+ * timing inaccuracy in the long run.
+ *
+ * Input Parameters:
+ * tp - The location to return the high resolution time value.
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_RTC) && defined(CONFIG_RTC_DATETIME)
+int up_rtc_getdatetime(FAR struct tm *tp);
+#endif
+
+/****************************************************************************
+ * Name: up_rtc_settime
+ *
+ * Description:
+ * Set the RTC to the provided time. All RTC implementations must be able
+ * to set their time based on a standard timespec.
+ *
+ * Input Parameters:
+ * tp - the time to use
+ *
+ * Returned Value:
+ * Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_RTC
+int up_rtc_settime(FAR const struct timespec *tp);
+#endif
+
+/****************************************************************************
* Board-specific button interfaces exported by the board-specific logic
****************************************************************************/
/****************************************************************************
*
- * Copyright 2016 Samsung Electronics All Rights Reserved.
+ * Copyright 2017 Samsung Electronics All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
****************************************************************************/
/****************************************************************************
+ * os/include/tinyara/rtc.h
*
* Copyright(C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu>
*
* With extensions, modifications by:
*
- * Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
+ * Copyright (C) 2011-2012, 2015-2016 Gregory Nutt. All rights reserved.
* Author: Gregroy Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
*
****************************************************************************/
-#ifndef __INCLUDE_RTC_H
-#define __INCLUDE_RTC_H
+#ifndef __INCLUDE_TINYARA_RTC_H
+#define __INCLUDE_TINYARA_RTC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <tinyara/config.h>
+#include <tinyara/compiler.h>
-#include <stdint.h>
#include <stdbool.h>
-
+#include <signal.h>
#include <time.h>
+
#include <tinyara/fs/ioctl.h>
#ifdef CONFIG_RTC
* A full date / time RTC the provides the date and time information, often
* in BCD format. If CONFIG_RTC_DATETIME is selected, it specifies this
* second kind of RTC. In this case, the RTC is used to "seed" the normal
- * TinyAra timer and the TinyAra system timer provides for higher resoution
+ * TinyARA timer and the TinyARA system timer provides for higher resolution
* time.
*
* CONFIG_RTC_HIRES - If CONFIG_RTC_DATETIME not selected, then the simple,
* of such simple counters based on the time resolution of the counter:
* The typical RTC keeps time to resolution of 1 second, usually
* supporting a 32-bit time_t value. In this case, the RTC is used to
- * "seed" the normal TinyAra timer and the TinyAra timer provides for higher
+ * "seed" the normal TinyARA timer and the TinyARA timer provides for higher
* resolution time.
*
- * If CONFIG_RTC_HIRES is enabled in the TinyAra configuration, then the
+ * If CONFIG_RTC_HIRES is enabled in the TinyARA configuration, then the
* RTC provides higher resolution time and completely replaces the system
* timer for purpose of date and time.
*
*/
#ifdef CONFIG_RTC_HIRES
-#ifdef CONFIG_RTC_DATETIME
-#error "CONFIG_RTC_HIRES and CONFIG_RTC_DATETIME are both defined"
-#endif
-#ifndef CONFIG_RTC_FREQUENCY
-#error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES"
-#endif
+# ifdef CONFIG_RTC_DATETIME
+# error "CONFIG_RTC_HIRES and CONFIG_RTC_DATETIME are both defined"
+# endif
+# ifndef CONFIG_RTC_FREQUENCY
+# error "CONFIG_RTC_FREQUENCY is required for CONFIG_RTC_HIRES"
+# endif
#else
-#ifndef CONFIG_RTC_FREQUENCY
-#define CONFIG_RTC_FREQUENCY 1
-#endif
-#if CONFIG_RTC_FREQUENCY != 1
-#error "The low resolution RTC must have frequency 1Hz"
+# ifndef CONFIG_RTC_FREQUENCY
+# define CONFIG_RTC_FREQUENCY 1
+# endif
+# if CONFIG_RTC_FREQUENCY != 1
+# error "The low resolution RTC must have frequency 1Hz"
+# endif
#endif
+
+#ifdef CONFIG_RTC_ALARM
+# ifdef CONFIG_DISABLE_SIGNALS
+# error RTC driver alarm support depends on signals
+# endif
+# ifndef CONFIG_RTC_NALARMS
+# define CONFIG_RTC_NALARMS 1
+# endif
#endif
/* The remainder of the contain of this header file is only valid if the
#define RTC_SET_TIME _RTCIOC(0x0002)
-/* RTC_ALM_READ reads the alarm time (for RTCs that support alarms)
- *
- * Argument: A writeable reference to a struct rtc_time to receive the RTC's
- * alarm time.
- */
-
-#define RTC_ALM_READ _RTCIOC(0x0003)
-
-/* RTC_ALM_SET sets the alarm time (for RTCs that support alarms).
+/* RTC_SET_ALARM sets the alarm time (for RTCs that support alarms).
*
- * Argument: A read-only reference to a struct rtc_time containing the
+ * Argument: A read-only reference to a struct rtc_setalarm_s containing the
* new alarm time to be set.
*/
-#define RTC_ALM_SET _RTCIOC(0x0004)
-
-/* RTC_IRQP_READ read the frequency for periodic interrupts (for RTCs that
- * support periodic interrupts)
- *
- * Argument: A pointer to a writeable unsigned long value in which to
- * receive the frequency value.
- */
-
-#define RTC_IRQP_READ _RTCIOC(0x0005)
-
-/* RTC_IRQP_SET set the frequency for periodic interrupts (for RTCs that
- * support periodic interrupts)
- *
- * Argument: An unsigned long value providing the new periodic frequency
- */
-
-#define RTC_IRQP_SET _RTCIOC(0x0006)
-
-/* RTC_AIE_ON enable alarm interrupts (for RTCs that support alarms)
- *
- * Argument: None
- */
-
-#define RTC_AIE_ON _RTCIOC(0x0007)
-
-/* RTC_AIE_OFF disable the alarm interrupt (for RTCs that support alarms)
- *
- * Argument: None
- */
-
-#define RTC_AIE_OFF _RTCIOC(0x0008)
-
-/* RTC_UIE_ON enable the interrupt on every clock update (for RTCs that
- * support this once-per-second interrupt).
- *
- * Argument: None
- */
-
-#define RTC_UIE_ON _RTCIOC(0x0009)
-
-/* RTC_UIE_OFF disable the interrupt on every clock update (for RTCs that
- * support this once-per-second interrupt).
- *
- * Argument: None
- */
-
-#define RTC_UIE_OFF _RTCIOC(0x000a)
-
-/* RTC_PIE_ON enable the periodic interrupt (for RTCs that support these
- * periodic interrupts).
- *
- * Argument: None
- */
-
-#define RTC_PIE_ON _RTCIOC(0x000b)
-
-/* RTC_PIE_OFF disable the periodic interrupt (for RTCs that support these
- * periodic interrupts).
- *
- * Argument: None
- */
-
-#define RTC_PIE_OFF _RTCIOC(0x000c)
-
-/* RTC_EPOCH_READ and RTC_EPOCH_SET.
- *
- * Many RTCs encode the year in an 8-bit register which is either interpreted
- * as an 8-bit binary number or as a BCD number. In both cases, the number is
- * interpreted relative to this RTC's Epoch. The RTC's Epoch is initialized to
- * 1900 on most systems but on Alpha and MIPS it might also be initialized to
- * 1952, 1980, or 2000, depending on the value of an RTC register for the year.
- * With some RTCs, these operations can be used to read or to set the RTC's
- * Epoch, respectively.
- */
-
-/* RTC_EPOCH_READ read the Epoch.
- *
- * Argument: A reference to a writeable unsigned low variable that will
- * receive the Epoch value.
- */
-
-#define RTC_EPOCH_READ _RTCIOC(0x000d)
-
-/* RTC_EPOCH_SET set the Epoch
- *
- * Argument: An unsigned long value containing the new Epoch value to be set.
- */
-
-#define RTC_EPOCH_SET _RTCIOC(0x000e)
-
-/* RTC_WKALM_RD and RTC_WKALM_SET.
- *
- * Some RTCs support a more powerful alarm interface, using these ioctls to
- * read or write the RTC's alarm time (respectively) with the rtc_wkalrm.
- */
+#define RTC_SET_ALARM _RTCIOC(0x0003)
-/* RTC_WKALM_RD read the current alarm
+/* RTC_SET_RELATIVE sets the alarm time relative to the current time.
*
- * Argument: A writeable reference to struct rtc_wkalrm to receive the
- * current alarm settings.
+ * Argument: A read-only reference to a struct rtc_setrelative_s containing
+ * the new relative alarm time to be set.
*/
-#define RTC_WKALM_RD _RTCIOC(0x000f)
+#define RTC_SET_RELATIVE _RTCIOC(0x0004)
-/* RTC_WKALM_SET set the alarm.
+/* RTC_SET_RELATIVE cancel the alarm.
*
- * Argument: A read-only reference to struct rtc_wkalrm containing the
- * new alarm settings.
+ * Argument: An ALARM ID value that indicates which alarm should be canceled.
*/
-#define RTC_WKALM_SET _RTCIOC(0x0010)
+#define RTC_CANCEL_ALARM _RTCIOC(0x0005)
/* Architecture-specific RTC IOCTLS should begin at RTC_USER_IOCBASE. For
* example:
* etc.
*/
-#define RTC_USER_IOCBASE 0x0011
+#define RTC_USER_IOCBASE 0x0006
/****************************************************************************
* Public Types
* structure be cast compatible with struct tm! They must be interchangeable.
*/
-struct rtc_time {
- int tm_sec; /* Seconds (0-61, allows for leap seconds) */
- int tm_min; /* Minutes (0-59) */
- int tm_hour; /* Hours (0-23) */
- int tm_mday; /* Day of the month (1-31) */
- int tm_mon; /* Month (0-11) */
- int tm_year; /* Years since 1900 */
+struct rtc_time
+{
+ int tm_sec; /* Seconds (0-61, allows for leap seconds) */
+ int tm_min; /* Minutes (0-59) */
+ int tm_hour; /* Hours (0-23) */
+ int tm_mday; /* Day of the month (1-31) */
+ int tm_mon; /* Month (0-11) */
+ int tm_year; /* Years since 1900 */
#if defined(CONFIG_LIBC_LOCALTIME) || defined(CONFIG_TIME_EXTENDED)
- int tm_wday; /* Day of the week (0-6) (unused) */
- int tm_yday; /* Day of the year (0-365) (unused) */
- int tm_isdst; /* Non-0 if daylight savings time is in effect (unused) */
+ int tm_wday; /* Day of the week (0-6) (unused) */
+ int tm_yday; /* Day of the year (0-365) (unused) */
+ int tm_isdst; /* Non-0 if daylight savings time is in effect (unused) */
#endif
};
#ifdef CONFIG_RTC_ALARM
-/* Structure used with the RTC_WKALM_RD and RTC_WKALM_SET IOCTL commands.
- *
- * The enabled flag is used to enable or disable the alarm interrupt, or to
- * read its current status; when using these calls, RTC_AIE_ON and
- * RTC_AIE_OFF are not used. The pending flag is used by RTC_WKALM_RD to
- * report a pending interrupt . The time field is as used with RTC_ALM_READ
- * and RTC_ALM_SET except that the tm_mday, tm_mon, and tm_year fields are
- * also valid.
+/* Structure used with the RTC_RD_ALARM IOCTL command and with
+ * rdalarm() method.
+ */
+
+struct rtc_rdalarm_s
+{
+ uint8_t id; /* Indicates the alarm being queried */
+ bool active; /* Alarm actively timing or disabled */
+ struct rtc_time time; /* Current RTC time (if enabled) */
+};
+
+/* Structure used with the RTC_SET_ALARM IOCTL command. */
+
+struct rtc_setalarm_s
+{
+ uint8_t id; /* Indicates the alarm to be set */
+ uint8_t signo; /* Signal number for alarm notification */
+ pid_t pid; /* Identifies task to be notified (0=caller) */
+ union sigval sigvalue; /* Data passed with notification */
+ struct rtc_time time; /* Alarm time */
+};
+
+/* Structure used with the RTC_SET_RELATIVE IOCTL command. */
+
+struct rtc_setrelative_s
+{
+ uint8_t id; /* Indicates the alarm to be set */
+ uint8_t signo; /* Signal number for alarm notification */
+ pid_t pid; /* Identifies task to be notified (0=caller) */
+ union sigval sigvalue; /* Data passed with notification */
+ time_t reltime; /* Relative time in seconds */
+};
+
+/*
+ * Callback type used by the RTC harware to notify the RTC driver when the
+ * alarm expires.
*/
-struct rtc_wkalrm {
- unsigned char enabled;
- unsigned char pending;
- struct rtc_time time;
+typedef CODE void (*rtc_alarm_callback_t)(FAR void *priv, int alarmid);
+
+/* Structure used with the setalarm method */
+
+struct lower_setalarm_s
+{
+ uint8_t id; /* Indicates the alarm to be set */
+ rtc_alarm_callback_t cb; /* Callback when the alarm expires */
+ FAR void *priv; /* Private argurment to accompany callback */
+ struct rtc_time time; /* Alarm time */
+};
+
+/* Structure used with the setrelative method */
+
+struct lower_setrelative_s
+{
+ uint8_t id; /* Indicates the alarm to be set */
+ rtc_alarm_callback_t cb; /* Callback when the alarm expires */
+ FAR void *priv; /* Private argurment to accompany callback */
+ time_t reltime; /* Relative time in seconds */
};
#endif
-/* The RTC driver is implemented as a common, upper-half character driver
+/*
+ * The RTC driver is implemented as a common, upper-half character driver
* that provides the RTC driver structure and a lower-level, hardware
* specific implementation that performs the actual RTC operations.
*
*/
struct rtc_lowerhalf_s;
-struct rtc_ops_s {
+struct rtc_ops_s
+{
/* rdtime() returns the current RTC time. */
- CODE int (*rdtime)(FAR struct rtc_lowerhalf_s *lower, FAR struct rtc_time *rtctime);
+ CODE int (*rdtime)(FAR struct rtc_lowerhalf_s *lower,
+ FAR struct rtc_time *rtctime);
/* settime sets the RTC's time */
- CODE int (*settime)(FAR struct rtc_lowerhalf_s *lower, FAR const struct rtc_time *rtctime);
+ CODE int (*settime)(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct rtc_time *rtctime);
#ifdef CONFIG_RTC_ALARM
- /* almread reads the alarm time (for RTCs that support alarms) */
-
- CODE int (*almread)(FAR struct rtc_lowerhalf_s *lower, FAR struct rtc_time *almtime);
-
- /* almset sets the alarm time (for RTCs that support alarms). */
+ /* setalarm sets up a new alarm. */
- CODE int (*almset)(FAR struct rtc_lowerhalf_s *lower, FAR const struct rtc_time *almtime);
-#endif
-
-#ifdef CONFIG_RTC_PERIODIC
- /* irqpread the frequency for periodic interrupts (for RTCs that support
- * periodic interrupts)
- */
+ CODE int (*setalarm)(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setalarm_s *alarminfo);
- CODE int (*irqpread)(FAR struct rtc_lowerhalf_s *lower, FAR unsigned long *irqpfreq);
+ /* setalarm sets up a new alarm relative to the current time. */
- /* irqpset set the frequency for periodic interrupts (for RTCs that
- * support periodic interrupts)
- */
-
- CODE int (*irqpset)(FAR struct rtc_lowerhalf_s *lower, unsigned long irqpfreq);
-#endif
+ CODE int (*setrelative)(FAR struct rtc_lowerhalf_s *lower,
+ FAR const struct lower_setrelative_s *alarminfo);
-#ifdef CONFIG_RTC_ALARM
- /* aie enable/disable alarm interrupts (for RTCs that support alarms) */
-
- CODE int (*aie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
-#endif
-
-#ifdef CONFIG_RTC_ONESEC
- /* uie enable/disable the interrupt on every clock update (for RTCs that
- * support this once-per-second interrupt).
- */
+ /* cancelalarm cancels the current alarm. */
- CODE int (*uie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
-#endif
-
-#ifdef CONFIG_RTC_PERIODIC
- /* pie enable the periodic interrupt (for RTCs that support these periodic
- * interrupts).
- */
-
- CODE int (*pie)(FAR struct rtc_lowerhalf_s *lower, bool enable);
-#endif
-
-#ifdef CONFIG_RTC_EPOCHYEAR
- /* rdepoch read the Epoch. */
-
- CODE int (*rdepoch)(FAR struct rtc_lowerhalf_s *lower, FAR unsigned long *epoch);
-
- /* setepoch set the Epoch */
-
- CODE int (*setepoch)(FAR struct rtc_lowerhalf_s *lower, unsigned long epoch);
-#endif
-
-#ifdef CONFIG_RTC_ALARM
- /* rdwkalm read the current alarm */
-
- CODE int (*rdwkalm)(FAR struct rtc_lowerhalf_s *lower, FAR struct rtc_wkalrm *wkalrm);
-
- /* setwkalm set the alarm. */
-
- CODE int (*setwkalm)(FAR struct rtc_lowerhalf_s *lower, FAR const struct rtc_wkalrm *wkalrm);
+ CODE int (*cancelalarm)(FAR struct rtc_lowerhalf_s *lower, int alarmid);
#endif
#ifdef CONFIG_RTC_IOCTL
/* Support for architecture-specific RTC operations */
- CODE int (*ioctl)(FAR struct rtc_lowerhalf_s *lower, int cmd, unsigned long arg);
+ CODE int (*ioctl)(FAR struct rtc_lowerhalf_s *lower, int cmd,
+ unsigned long arg);
#endif
#ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
- /* The driver has been unlinked and there are no further open references
- * to the driver.
+ /*
+ * The driver has been unlinked and there are no further open
+ * references to the driver.
*/
CODE int (*destroy)(FAR struct rtc_lowerhalf_s *lower);
#endif
};
-/* When the RTC driver is instantiated, a reference to struct
+/*
+ * When the RTC driver is instantiated, a reference to struct
* rtc_lowerhalf_s is passed to the initialization function and bound to
* the driver. The actual content of the state structure used by different
* lower half drivers will vary from implementation to implementation. But
* struct rtc_lowerhalf_s that is understood by the upper half driver.
*/
-struct rtc_lowerhalf_s {
- /* This is the contained reference to the read-only, lower-half
+struct rtc_lowerhalf_s
+{
+ /*
+ * This is the contained reference to the read-only, lower-half
* operations vtable (which may lie in FLASH or ROM)
*/
/* Data following this can vary from RTC driver-to-driver */
};
-/* The form of an alarm callback */
-
-typedef CODE void (*alarmcb_t)(void);
-
/****************************************************************************
* Public Data
****************************************************************************/
-/* Variable determines the state of the RTC module.
- *
- * After initialization value is set to 'true' if RTC starts successfully.
- * The value can be changed to false also during operation if RTC for
- * some reason fails.
- */
-
-extern volatile bool g_rtc_enabled;
-
-/****************************************************************************
- * Public Functions
- ****************************************************************************/
-
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
-extern "C" {
+extern "C"
+{
#else
#define EXTERN extern
#endif
-/************************************************************************************
- * Name: up_rtcinitialize
- *
- * Description:
- * Initialize the hardware RTC per the selected configuration. This function is
- * called once during the OS initialization sequence
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-EXTERN int up_rtcinitialize(void);
-
-/************************************************************************************
- * Name: up_rtc_time
- *
- * Description:
- * Get the current time in seconds. This is similar to the standard time()
- * function. This interface is only required if the low-resolution RTC/counter
- * hardware implementation selected. It is only used by the RTOS during
- * initializeation to set up the system time when CONFIG_RTC is set but neither
- * CONFIG_RTC_HIRES nor CONFIG_RTC_DATETIME are set.
- *
- * Input Parameters:
- * None
- *
- * Returned Value:
- * The current time in seconds
- *
- ************************************************************************************/
-
-#ifndef CONFIG_RTC_HIRES
-EXTERN time_t up_rtc_time(void);
-#endif
-
-/************************************************************************************
- * Name: up_rtc_gettime
- *
- * Description:
- * Get the current time from the high resolution RTC clock/counter. This interface
- * is only supported by the high-resolution RTC/counter hardware implementation.
- * It is used to replace the system timer.
- *
- * Input Parameters:
- * tp - The location to return the high resolution time value.
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-#ifdef CONFIG_RTC_HIRES
-EXTERN int up_rtc_gettime(FAR struct timespec *tp);
-#endif
-
-/************************************************************************************
- * Name: up_rtc_getdatetime
- *
- * Description:
- * Get the current date and time from the date/time RTC. This interface
- * is only supported by the date/time RTC hardware implementation.
- * It is used to replace the system timer. It is only used by the RTOS during
- * initializeation to set up the system time when CONFIG_RTC and CONFIG_RTC_DATETIME
- * are selected (and CONFIG_RTC_HIRES is not).
- *
- * NOTE: Some date/time RTC hardware is capability of sub-second accuracy. That
- * sub-second accuracy is lost in this interface. However, since the system time
- * is reinitialized on each power-up/reset, there will be no timing inaccuracy in
- * the long run.
- *
- * Input Parameters:
- * tp - The location to return the high resolution time value.
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-#ifdef CONFIG_RTC_DATETIME
-EXTERN int up_rtc_getdatetime(FAR struct tm *tp);
-#endif
-
-/************************************************************************************
- * Name: up_rtc_settime
- *
- * Description:
- * Set the RTC to the provided time. All RTC implementations must be able to
- * set their time based on a standard timespec.
- *
- * Input Parameters:
- * tp - the time to use
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-EXTERN int up_rtc_settime(FAR const struct timespec *tp);
-
-/************************************************************************************
- * Name: up_rtc_setalarm
- *
- * Description:
- * Set up an alarm.
- *
- * Input Parameters:
- * tp - the time to set the alarm
- * callback - the function to call when the alarm expires.
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-#ifdef CONFIG_RTC_ALARM
-EXTERN int up_rtc_setalarm(FAR const struct timespec *tp, alarmcb_t callback);
-#endif
-
-/************************************************************************************
- * Name: up_rtc_cancelalarm
- *
- * Description:
- * Cancel a pending alarm alarm
- *
- * Input Parameters:
- * none
- *
- * Returned Value:
- * Zero (OK) on success; a negated errno on failure
- *
- ************************************************************************************/
-
-#ifdef CONFIG_RTC_ALARM
-EXTERN int up_rtc_cancelalarm(void);
-#endif
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
/****************************************************************************
* Name: rtc_initialize
*
****************************************************************************/
-EXTERN int rtc_initialize(int minor, FAR struct rtc_lowerhalf_s *lower);
+#ifdef __KERNEL__
+int rtc_initialize(int minor, FAR struct rtc_lowerhalf_s *lower);
+#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
-#endif /* CONFIG_RTC_DRIVER */
-#endif /* CONFIG_RTC */
-#endif /* __INCLUDE_RTC_H */
+
+#endif /* CONFIG_RTC_DRIVER */
+#endif /* CONFIG_RTC */
+#endif /* __INCLUDE_TINYARA_RTC_H */
/* Initialize the RTC hardware */
#if defined(CONFIG_RTC)
- up_rtcinitialize();
+ up_rtc_initialize();
#endif
/* Initialize the time value to match the RTC */
************************************************************************/
#include <tinyara/config.h>
-#include <tinyara/rtc.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
+#include <tinyara/arch.h>
#include <arch/irq.h>
+
#include "clock/clock.h"
/************************************************************************