Merge pull request #15628 from ML-PA-Consulting-GmbH/feat/20201214__native_rtc_settime

cpu/native/rtc: add rtc_set_time implementation
This commit is contained in:
benpicco 2020-12-15 19:52:57 +01:00 committed by GitHub
commit c25cb8467b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 81 additions and 27 deletions

View File

@ -38,19 +38,32 @@
static int _native_rtc_initialized = 0;
static int _native_rtc_powered = 0;
static struct tm _native_rtc_alarm;
static rtc_alarm_cb_t _native_rtc_alarm_callback;
static void *_native_rtc_alarm_argument;
static xtimer_t _timer;
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;
}
void rtc_init(void)
{
DEBUG("rtc_init\n");
xtimer_remove(&_native_rtc_timer);
_native_rtc_timer.callback = _native_rtc_cb;
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
_native_rtc_alarm_callback = NULL;
_native_rtc_alarm_argument = NULL;
_native_rtc_offset = 0;
_native_rtc_initialized = 1;
printf("Native RTC initialized.\n");
@ -81,15 +94,18 @@ void rtc_poweroff(void)
warnx("rtc_poweroff: not powered on");
}
if (_native_rtc_alarm_callback) {
xtimer_remove(&_native_rtc_timer);
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
_native_rtc_alarm_callback = NULL;
}
_native_rtc_powered = 0;
}
/* TODO: implement time setting using a delta */
int rtc_set_time(struct tm *ttime)
{
(void) ttime;
DEBUG("rtc_set_time()\n");
DEBUG_PUTS("rtc_set_time()");
if (!_native_rtc_initialized) {
warnx("rtc_set_time: not initialized");
@ -100,9 +116,21 @@ int rtc_set_time(struct tm *ttime)
return -1;
}
warnx("rtc_set_time: not implemented");
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();
return -1;
if (_native_rtc_alarm_callback) {
rtc_set_alarm(&_native_rtc_alarm, _native_rtc_alarm_callback,
_native_rtc_timer.arg);
}
return 0;
}
int rtc_get_time(struct tm *ttime)
@ -119,7 +147,7 @@ int rtc_get_time(struct tm *ttime)
}
_native_syscall_enter();
t = time(NULL);
t = time(NULL) + _native_rtc_offset;
if (localtime_r(&t, ttime) == NULL) {
err(EXIT_FAILURE, "rtc_get_time: localtime_r");
@ -131,10 +159,6 @@ int rtc_get_time(struct tm *ttime)
int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
{
(void) time;
(void) cb;
(void) arg;
if (!_native_rtc_initialized) {
warnx("rtc_set_alarm: not initialized");
return -1;
@ -147,19 +171,25 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
struct tm now;
rtc_get_time(&now);
_native_rtc_alarm = *time;
time_t tdiff_secs = mktime(time) - mktime(&now);
_timer.callback = cb;
_timer.arg = arg;
xtimer_set64(&_timer, (mktime(time) - mktime(&now)) * US_PER_SEC);
if (_native_rtc_alarm_callback) {
xtimer_remove(&_native_rtc_timer);
}
_native_rtc_alarm = *time;
_native_rtc_alarm_callback = cb;
_native_rtc_timer.arg = arg;
if (tdiff_secs >= 0) {
xtimer_set64(&_native_rtc_timer, tdiff_secs * US_PER_SEC);
}
return 0;
}
int rtc_get_alarm(struct tm *time)
{
(void) time;
if (!_native_rtc_initialized) {
warnx("rtc_get_alarm: not initialized");
return -1;
@ -185,6 +215,7 @@ void rtc_clear_alarm(void)
warnx("rtc_clear_alarm: not powered on");
}
xtimer_remove(&_timer);
xtimer_remove(&_native_rtc_timer);
memset(&_native_rtc_alarm, 0, sizeof(_native_rtc_alarm));
_native_rtc_alarm_callback = NULL;
}

View File

@ -92,8 +92,30 @@ int main(void)
/* verify alarm */
rtc_get_alarm(&time);
print_time(" Alarm is set to ", &time);
/* clear alarm */
rtc_clear_alarm();
rtc_get_time(&time);
print_time(" Alarm cleared at ", &time);
/* verify alarm has been cleared */
xtimer_sleep(PERIOD);
rtc_get_time(&time);
if (mutex_trylock(&rtc_mtx)) {
print_time(" Error: Alarm at ", &time);
}
else {
print_time(" No alarm at ", &time);
}
/* set alarm */
rtc_get_time(&time);
inc_secs(&time, PERIOD);
rtc_set_alarm(&time, cb, &rtc_mtx);
print_time(" Setting alarm to ", &time);
puts("");
/* loop over a few alarm cycles */
while (1) {
mutex_lock(&rtc_mtx);
puts("Alarm!");

View File

@ -21,14 +21,9 @@ def testfunc(child):
alarm_count = int(child.match.group(1))
child.expect(r' Setting clock to ({})'.format(DATE_PATTERN))
clock_set = child.match.group(1)
if BOARD == 'native':
child.expect(r'.*rtc_set_time: not implemented')
child.expect(r'Clock value is now ({})'.format(DATE_PATTERN))
clock_value = child.match.group(1)
if BOARD != 'native':
# Set clock is not implemented for native board so no need to compare
# clock values
assert clock_set == clock_value
assert clock_set == clock_value
child.expect(r' Setting alarm to ({})'.format(DATE_PATTERN))
alarm_set = child.match.group(1)
@ -36,6 +31,12 @@ def testfunc(child):
alarm_value = child.match.group(1)
assert alarm_set == alarm_value
child.expect(r" Alarm cleared at ({})".format(DATE_PATTERN))
child.expect(r" No alarm at ({})".format(DATE_PATTERN))
no_alarm_value = child.match.group(1)
assert alarm_value == no_alarm_value
child.expect(r" Setting alarm to ({})".format(DATE_PATTERN))
for _ in range(alarm_count):
child.expect_exact('Alarm!')