2014-11-22 10:26:01 +01:00
|
|
|
/*
|
2015-09-27 18:58:30 +02:00
|
|
|
* Copyright (C) 2013, 2014 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
2014-10-31 15:57:17 +01:00
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
2014-11-22 10:26:01 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
2017-06-22 15:43:17 +02:00
|
|
|
* @ingroup cpu_native
|
|
|
|
* @ingroup drivers_periph_rtc
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Native CPU periph/rtc.h implementation
|
2014-11-22 10:26:01 +01:00
|
|
|
*
|
|
|
|
* The implementation uses POSIX system calls to emulate a real-time
|
|
|
|
* clock based on the system clock.
|
2014-10-31 15:57:17 +01:00
|
|
|
*
|
2015-09-27 18:58:30 +02:00
|
|
|
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
|
2014-10-31 15:57:17 +01:00
|
|
|
*
|
2017-06-22 15:43:17 +02:00
|
|
|
* @}
|
2014-10-31 15:57:17 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <time.h>
|
|
|
|
#include <stdlib.h>
|
2014-11-22 11:06:23 +01:00
|
|
|
#include <string.h>
|
2014-10-31 15:57:17 +01:00
|
|
|
#include <err.h>
|
|
|
|
|
|
|
|
#include "periph/rtc.h"
|
|
|
|
#include "cpu.h"
|
2020-08-14 17:43:16 +02:00
|
|
|
#include "xtimer.h"
|
2014-10-31 15:57:17 +01:00
|
|
|
|
|
|
|
#include "native_internal.h"
|
|
|
|
|
2020-10-22 11:34:00 +02:00
|
|
|
#define ENABLE_DEBUG 0
|
2014-12-16 15:41:51 +01:00
|
|
|
#include "debug.h"
|
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
static int _native_rtc_initialized = 0;
|
|
|
|
static int _native_rtc_powered = 0;
|
2020-12-14 10:07:27 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
static struct tm _native_rtc_alarm;
|
|
|
|
static rtc_alarm_cb_t _native_rtc_alarm_callback;
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
static time_t _native_rtc_offset;
|
|
|
|
|
|
|
|
static xtimer_t _native_rtc_timer;
|
|
|
|
|
|
|
|
static void _native_rtc_cb(void *arg) {
|
|
|
|
if (_native_rtc_alarm_callback) {
|
|
|
|
_native_rtc_alarm_callback(arg);
|
|
|
|
}
|
|
|
|
_native_rtc_alarm_callback = NULL;
|
|
|
|
}
|
2020-08-14 17:43:16 +02:00
|
|
|
|
2014-10-31 15:57:17 +01:00
|
|
|
void rtc_init(void)
|
|
|
|
{
|
2014-11-22 11:06:23 +01:00
|
|
|
DEBUG("rtc_init\n");
|
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
xtimer_remove(&_native_rtc_timer);
|
|
|
|
_native_rtc_timer.callback = _native_rtc_cb;
|
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
|
|
|
|
_native_rtc_alarm_callback = NULL;
|
2020-12-14 10:07:27 +01:00
|
|
|
|
|
|
|
_native_rtc_offset = 0;
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
_native_rtc_initialized = 1;
|
2014-10-31 15:57:17 +01:00
|
|
|
printf("Native RTC initialized.\n");
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2014-10-31 15:57:17 +01:00
|
|
|
rtc_poweron();
|
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_poweron(void)
|
|
|
|
{
|
|
|
|
DEBUG("rtc_poweron\n");
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_poweron: not initialized");
|
|
|
|
return;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
_native_rtc_powered = 1;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_poweroff(void)
|
|
|
|
{
|
|
|
|
DEBUG("rtc_poweroff()\n");
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_poweroff: not initialized");
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_poweroff: not powered on");
|
|
|
|
}
|
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
if (_native_rtc_alarm_callback) {
|
|
|
|
xtimer_remove(&_native_rtc_timer);
|
|
|
|
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
|
|
|
|
_native_rtc_alarm_callback = NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
_native_rtc_powered = 0;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int rtc_set_time(struct tm *ttime)
|
|
|
|
{
|
2020-12-14 10:07:27 +01:00
|
|
|
DEBUG_PUTS("rtc_set_time()");
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_set_time: not initialized");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_set_time: not powered on");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
time_t tnew = mktime(ttime);
|
|
|
|
if (tnew == -1) {
|
|
|
|
warnx("rtc_set_time: out of time_t range");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
_native_syscall_enter();
|
|
|
|
_native_rtc_offset = tnew - time(NULL);
|
|
|
|
_native_syscall_leave();
|
|
|
|
|
|
|
|
if (_native_rtc_alarm_callback) {
|
|
|
|
rtc_set_alarm(&_native_rtc_alarm, _native_rtc_alarm_callback,
|
|
|
|
_native_rtc_timer.arg);
|
|
|
|
}
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
return 0;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int rtc_get_time(struct tm *ttime)
|
|
|
|
{
|
|
|
|
time_t t;
|
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_get_time: not initialized");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_get_time: not powered on");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
_native_syscall_enter();
|
2020-12-14 10:07:27 +01:00
|
|
|
t = time(NULL) + _native_rtc_offset;
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2014-11-22 11:06:23 +01:00
|
|
|
if (localtime_r(&t, ttime) == NULL) {
|
|
|
|
err(EXIT_FAILURE, "rtc_get_time: localtime_r");
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
2014-11-22 11:06:23 +01:00
|
|
|
_native_syscall_leave();
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2021-03-31 23:51:48 +02:00
|
|
|
/* riot does not handle dst */
|
|
|
|
ttime->tm_isdst=0;
|
|
|
|
|
2014-10-31 15:57:17 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
|
|
|
|
{
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_set_alarm: not initialized");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_set_alarm: not powered on");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-08-14 17:43:16 +02:00
|
|
|
struct tm now;
|
|
|
|
rtc_get_time(&now);
|
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
time_t tdiff_secs = mktime(time) - mktime(&now);
|
|
|
|
|
|
|
|
if (_native_rtc_alarm_callback) {
|
|
|
|
xtimer_remove(&_native_rtc_timer);
|
|
|
|
}
|
|
|
|
|
2019-01-06 22:54:44 +01:00
|
|
|
_native_rtc_alarm = *time;
|
2020-12-14 10:07:27 +01:00
|
|
|
_native_rtc_alarm_callback = cb;
|
|
|
|
_native_rtc_timer.arg = arg;
|
2014-11-22 11:06:23 +01:00
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
if (tdiff_secs >= 0) {
|
|
|
|
xtimer_set64(&_native_rtc_timer, tdiff_secs * US_PER_SEC);
|
|
|
|
}
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2020-08-14 17:43:16 +02:00
|
|
|
return 0;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int rtc_get_alarm(struct tm *time)
|
|
|
|
{
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_get_alarm: not initialized");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_get_alarm: not powered on");
|
|
|
|
return -1;
|
|
|
|
}
|
2014-10-31 15:57:17 +01:00
|
|
|
|
2019-01-06 22:54:44 +01:00
|
|
|
*time = _native_rtc_alarm;
|
2014-11-22 11:06:23 +01:00
|
|
|
|
|
|
|
return 0;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void rtc_clear_alarm(void)
|
|
|
|
{
|
2014-11-22 11:06:23 +01:00
|
|
|
DEBUG("rtc_clear_alarm()\n");
|
|
|
|
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_initialized) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_clear_alarm: not initialized");
|
|
|
|
}
|
2014-12-16 15:46:56 +01:00
|
|
|
if (!_native_rtc_powered) {
|
2014-11-22 11:06:23 +01:00
|
|
|
warnx("rtc_clear_alarm: not powered on");
|
|
|
|
}
|
|
|
|
|
2020-12-14 10:07:27 +01:00
|
|
|
xtimer_remove(&_native_rtc_timer);
|
2014-12-16 15:46:56 +01:00
|
|
|
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
|
2020-12-14 10:07:27 +01:00
|
|
|
_native_rtc_alarm_callback = NULL;
|
2014-10-31 15:57:17 +01:00
|
|
|
}
|