Merge pull request #16682 from benpicco/rtt_rtc_settimeofday
rtt_rtc: add rtt_rtc_settimeofday() & rtt_rtc_gettimeofday()
This commit is contained in:
commit
dceb8a7ac8
59
drivers/include/rtt_rtc.h
Normal file
59
drivers/include/rtt_rtc.h
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 ML!PA Consulting GmbH
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup drivers_rtt_rtc RTC emulation on top of a RTT
|
||||||
|
* @ingroup drivers_periph_rtc
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Additional functions provided in addition to the normal RTC API.
|
||||||
|
*
|
||||||
|
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef RTT_RTC_H
|
||||||
|
#define RTT_RTC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the time as epoch with sub-second precision
|
||||||
|
* This feature is an extension provided by the `rtt_rtc` module.
|
||||||
|
*
|
||||||
|
* @note The actual µs precision depends on the underlying hardware.
|
||||||
|
* The smallest time step will be 1 / @ref RTT_FREQUENCY.
|
||||||
|
*
|
||||||
|
* @param[in] s The new epoch timestamp
|
||||||
|
* @param[in] us Sub-Seconds
|
||||||
|
*/
|
||||||
|
void rtt_rtc_settimeofday(uint32_t s, uint32_t us);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the current epoch with sub-second precision
|
||||||
|
* This feature is an extension provided by the `rtt_rtc` module.
|
||||||
|
*
|
||||||
|
* @note The actual µs precision depends on the underlying hardware.
|
||||||
|
* The smallest time step will be 1 / @ref RTT_FREQUENCY.
|
||||||
|
*
|
||||||
|
* @param[out] s The current epoch timestamp
|
||||||
|
* @param[out] us Sub-Seconds
|
||||||
|
*/
|
||||||
|
void rtt_rtc_gettimeofday(uint32_t *s, uint32_t *us);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* RTT_RTC_H */
|
||||||
|
/** @} */
|
||||||
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ingroup drivers_periph_rtc
|
* @ingroup drivers_rtt_rtc
|
||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file
|
* @file
|
||||||
@ -26,9 +26,11 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "irq.h"
|
||||||
#include "periph/rtc.h"
|
#include "periph/rtc.h"
|
||||||
#include "periph/rtt.h"
|
#include "periph/rtt.h"
|
||||||
#include "timex.h"
|
#include "timex.h"
|
||||||
|
#include "rtt_rtc.h"
|
||||||
|
|
||||||
#define ENABLE_DEBUG 0
|
#define ENABLE_DEBUG 0
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
@ -137,31 +139,31 @@ int rtc_set_time(struct tm *time)
|
|||||||
|
|
||||||
int rtc_get_time_ms(struct tm *time, uint16_t *ms)
|
int rtc_get_time_ms(struct tm *time, uint16_t *ms)
|
||||||
{
|
{
|
||||||
uint32_t prev = rtc_now;
|
uint32_t now, tmp;
|
||||||
|
unsigned state = irq_disable();
|
||||||
|
|
||||||
/* repeat calculation if an alarm triggered in between */
|
now = rtt_get_counter();
|
||||||
do {
|
tmp = _rtc_now(now);
|
||||||
uint32_t now = rtt_get_counter();
|
|
||||||
uint32_t tmp = _rtc_now(now);
|
|
||||||
|
|
||||||
rtc_localtime(tmp, time);
|
*ms = (SUBSECONDS(now - last_alarm) * MS_PER_SEC)
|
||||||
*ms = (SUBSECONDS(now) * MS_PER_SEC) / RTT_SECOND;
|
/ RTT_SECOND;
|
||||||
} while (prev != rtc_now);
|
|
||||||
|
irq_restore(state);
|
||||||
|
rtc_localtime(tmp, time);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rtc_get_time(struct tm *time)
|
int rtc_get_time(struct tm *time)
|
||||||
{
|
{
|
||||||
uint32_t prev = rtc_now;
|
uint32_t now, tmp;
|
||||||
|
unsigned state = irq_disable();
|
||||||
|
|
||||||
/* repeat calculation if an alarm triggered in between */
|
now = rtt_get_counter();
|
||||||
do {
|
tmp = _rtc_now(now);
|
||||||
uint32_t now = rtt_get_counter();
|
|
||||||
uint32_t tmp = _rtc_now(now);
|
|
||||||
|
|
||||||
rtc_localtime(tmp, time);
|
irq_restore(state);
|
||||||
} while (prev != rtc_now);
|
rtc_localtime(tmp, time);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -184,6 +186,7 @@ int rtc_set_alarm(struct tm *time, rtc_alarm_cb_t cb, void *arg)
|
|||||||
alarm_cb_arg = arg;
|
alarm_cb_arg = arg;
|
||||||
alarm_cb = cb;
|
alarm_cb = cb;
|
||||||
|
|
||||||
|
/* RTT interrupt is disabled here */
|
||||||
rtc_now = _rtc_now(now);
|
rtc_now = _rtc_now(now);
|
||||||
_update_alarm(now);
|
_update_alarm(now);
|
||||||
|
|
||||||
@ -204,3 +207,27 @@ void rtc_poweroff(void)
|
|||||||
{
|
{
|
||||||
rtt_poweroff();
|
rtt_poweroff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void rtt_rtc_settimeofday(uint32_t s, uint32_t us)
|
||||||
|
{
|
||||||
|
/* disable alarm to prevent race condition */
|
||||||
|
rtt_clear_alarm();
|
||||||
|
uint32_t now = ((uint64_t)us * RTT_SECOND) / US_PER_SEC;
|
||||||
|
rtc_now = s;
|
||||||
|
rtt_set_counter(now);
|
||||||
|
/* calculate next wake-up period */
|
||||||
|
_update_alarm(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtt_rtc_gettimeofday(uint32_t *s, uint32_t *us)
|
||||||
|
{
|
||||||
|
uint32_t now;
|
||||||
|
unsigned state = irq_disable();
|
||||||
|
|
||||||
|
now = rtt_get_counter();
|
||||||
|
*s = _rtc_now(now);
|
||||||
|
*us = ((uint64_t)SUBSECONDS(now - last_alarm) * US_PER_SEC)
|
||||||
|
/ RTT_SECOND;
|
||||||
|
|
||||||
|
irq_restore(state);
|
||||||
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ BOARD_INSUFFICIENT_MEMORY := \
|
|||||||
atmega256rfr2-xpro \
|
atmega256rfr2-xpro \
|
||||||
atmega328p \
|
atmega328p \
|
||||||
atmega328p-xplained-mini \
|
atmega328p-xplained-mini \
|
||||||
|
avsextrem \
|
||||||
b-l072z-lrwan1 \
|
b-l072z-lrwan1 \
|
||||||
blackpill \
|
blackpill \
|
||||||
blackpill-128kib \
|
blackpill-128kib \
|
||||||
|
|||||||
@ -17,6 +17,8 @@
|
|||||||
#include "embUnit.h"
|
#include "embUnit.h"
|
||||||
#include "periph/rtc.h"
|
#include "periph/rtc.h"
|
||||||
#include "periph/rtt.h"
|
#include "periph/rtt.h"
|
||||||
|
#include "timex.h"
|
||||||
|
#include "rtt_rtc.h"
|
||||||
|
|
||||||
void rtt_add_ticks(uint64_t ticks);
|
void rtt_add_ticks(uint64_t ticks);
|
||||||
|
|
||||||
@ -203,6 +205,29 @@ static void test_set_alarm_set_time(void)
|
|||||||
TEST_ASSERT_EQUAL_INT(2, alarm.tm_isdst);
|
TEST_ASSERT_EQUAL_INT(2, alarm.tm_isdst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_rtt_rtc_settimeofday(void)
|
||||||
|
{
|
||||||
|
uint32_t s = 10, sec;
|
||||||
|
uint32_t us = US_PER_SEC / 8, micro_sec;
|
||||||
|
|
||||||
|
rtt_rtc_settimeofday(s, us);
|
||||||
|
rtt_rtc_gettimeofday(&sec, µ_sec);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_INT(s, sec);
|
||||||
|
TEST_ASSERT_EQUAL_INT(us, micro_sec);
|
||||||
|
|
||||||
|
rtt_add_ticks(1LU * RTT_FREQUENCY);
|
||||||
|
s++;
|
||||||
|
rtt_rtc_gettimeofday(&sec, µ_sec);
|
||||||
|
TEST_ASSERT_EQUAL_INT(s, sec);
|
||||||
|
|
||||||
|
rtt_add_ticks(RTT_FREQUENCY / 4);
|
||||||
|
us += US_PER_SEC / 4;
|
||||||
|
rtt_rtc_gettimeofday(&sec, µ_sec);
|
||||||
|
TEST_ASSERT_EQUAL_INT(s, sec);
|
||||||
|
TEST_ASSERT_EQUAL_INT(us, micro_sec);
|
||||||
|
}
|
||||||
|
|
||||||
Test *tests_rtt_rtt_tests(void)
|
Test *tests_rtt_rtt_tests(void)
|
||||||
{
|
{
|
||||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||||
@ -210,6 +235,7 @@ Test *tests_rtt_rtt_tests(void)
|
|||||||
new_TestFixture(test_set_alarm),
|
new_TestFixture(test_set_alarm),
|
||||||
new_TestFixture(test_set_alarm_short),
|
new_TestFixture(test_set_alarm_short),
|
||||||
new_TestFixture(test_set_alarm_set_time),
|
new_TestFixture(test_set_alarm_set_time),
|
||||||
|
new_TestFixture(test_rtt_rtc_settimeofday),
|
||||||
};
|
};
|
||||||
|
|
||||||
EMB_UNIT_TESTCALLER(rtt_rtc_tests, NULL, NULL, fixtures);
|
EMB_UNIT_TESTCALLER(rtt_rtc_tests, NULL, NULL, fixtures);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user