1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #16347 from benpicco/drivers/rtt_rtc-rtc_get_time_ms

drivers/rtt_rtc: implement rtc_get_time_ms()
This commit is contained in:
benpicco 2021-05-05 19:13:21 +02:00 committed by GitHub
commit 619a444741
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 124 additions and 9 deletions

View File

@ -20,6 +20,7 @@ config CPU_COMMON_ATMEGA
select HAS_PERIPH_GPIO select HAS_PERIPH_GPIO
select HAS_PERIPH_GPIO_IRQ select HAS_PERIPH_GPIO_IRQ
select HAS_PERIPH_PM select HAS_PERIPH_PM
select HAS_PERIPH_RTC_MS
select HAS_PERIPH_RTT_SET_COUNTER select HAS_PERIPH_RTT_SET_COUNTER
select HAS_PERIPH_TIMER_PERIODIC select HAS_PERIPH_TIMER_PERIODIC
select HAS_PERIPH_RTT_OVERFLOW select HAS_PERIPH_RTT_OVERFLOW

View File

@ -10,6 +10,7 @@ FEATURES_PROVIDED += periph_cpuid
FEATURES_PROVIDED += periph_eeprom FEATURES_PROVIDED += periph_eeprom
FEATURES_PROVIDED += periph_gpio periph_gpio_irq FEATURES_PROVIDED += periph_gpio periph_gpio_irq
FEATURES_PROVIDED += periph_pm FEATURES_PROVIDED += periph_pm
FEATURES_PROVIDED += periph_rtc_ms
FEATURES_PROVIDED += periph_rtt_set_counter FEATURES_PROVIDED += periph_rtt_set_counter
FEATURES_PROVIDED += periph_timer_periodic FEATURES_PROVIDED += periph_timer_periodic
FEATURES_PROVIDED += periph_rtt_overflow FEATURES_PROVIDED += periph_rtt_overflow

View File

@ -103,6 +103,28 @@ int rtc_get_time(struct tm *time)
return 0; return 0;
} }
int rtc_get_time_ms(struct tm *time, uint16_t *ms)
{
uint8_t cnt_before, cnt_after;
/* loop in case of overflow */
do {
cnt_before = TCNT2;
/* prevent compiler from reordering memory access to tm_now,
* including moving it out of the loop
*/
__asm__ volatile ("" : : : "memory");
*time = tm_now;
cnt_after = TCNT2;
} while (cnt_before > cnt_after);
*ms = (cnt_after * 1000UL) >> 8;
return 0;
}
int rtc_get_alarm(struct tm *time) int rtc_get_alarm(struct tm *time)
{ {
*time = tm_alarm; *time = tm_alarm;

View File

@ -15,6 +15,7 @@ config CPU_FAM_LPC23XX
select HAS_PERIPH_GPIO select HAS_PERIPH_GPIO
select HAS_PERIPH_GPIO_IRQ select HAS_PERIPH_GPIO_IRQ
select HAS_PERIPH_TIMER_PERIODIC select HAS_PERIPH_TIMER_PERIODIC
select HAS_PERIPH_RTC_MS
## CPU Models ## CPU Models
config CPU_MODEL_LPC2387 config CPU_MODEL_LPC2387

View File

@ -4,5 +4,6 @@ FEATURES_PROVIDED += periph_dac
FEATURES_PROVIDED += periph_flashpage FEATURES_PROVIDED += periph_flashpage
FEATURES_PROVIDED += periph_gpio periph_gpio_irq FEATURES_PROVIDED += periph_gpio periph_gpio_irq
FEATURES_PROVIDED += periph_timer_periodic FEATURES_PROVIDED += periph_timer_periodic
FEATURES_PROVIDED += periph_rtc_ms
include $(RIOTCPU)/arm7_common/Makefile.features include $(RIOTCPU)/arm7_common/Makefile.features

View File

@ -28,6 +28,7 @@
#include "periph/rtc.h" #include "periph/rtc.h"
#include "VIC.h" #include "VIC.h"
#include "lpc23xx.h" #include "lpc23xx.h"
#include "timex.h"
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #include "debug.h"
@ -110,6 +111,22 @@ int rtc_get_time(struct tm *localt)
return 0; return 0;
} }
int rtc_get_time_ms(struct tm *time, uint16_t *ms)
{
uint16_t ccr_before, ccr_after;
/* loop in case of overflow */
do {
ccr_before = RTC_CCR >> 1;
rtc_get_time(time);
ccr_after = RTC_CCR >> 1;
} while (ccr_before > ccr_after);
/* CCR is 15-bit counter, increments second with each overflow */
*ms = (ccr_after * MS_PER_SEC) >> 15;
return 0;
}
int rtc_set_alarm(struct tm *localt, rtc_alarm_cb_t cb, void *arg) int rtc_set_alarm(struct tm *localt, rtc_alarm_cb_t cb, void *arg)
{ {

View File

@ -90,6 +90,19 @@ int rtc_set_time(struct tm *time);
*/ */
int rtc_get_time(struct tm *time); int rtc_get_time(struct tm *time);
/**
* @brief Get current RTC time with sub-second component.
* Requires the `periph_rtc_ms` feature.
*
* @param[out] time Pointer to the struct to write the time to.
* @param[out] ms Pointer to a variable to hold the microsecond
* component of the current RTC time.
*
* @return 0 for success
* @return -1 an error occurred
*/
int rtc_get_time_ms(struct tm *time, uint16_t *ms);
/** /**
* @brief Set an alarm for RTC to the specified value. * @brief Set an alarm for RTC to the specified value.
* *

View File

@ -0,0 +1,2 @@
FEATURES_PROVIDED += periph_rtc
FEATURES_PROVIDED += periph_rtc_ms

View File

@ -28,6 +28,7 @@
#include "periph/rtc.h" #include "periph/rtc.h"
#include "periph/rtt.h" #include "periph/rtt.h"
#include "timex.h"
#define ENABLE_DEBUG 0 #define ENABLE_DEBUG 0
#include "debug.h" #include "debug.h"
@ -40,6 +41,7 @@
#define TICKS(x) ( (x) * RTT_SECOND) #define TICKS(x) ( (x) * RTT_SECOND)
#define SECONDS(x) (_RTT(x) / RTT_SECOND) #define SECONDS(x) (_RTT(x) / RTT_SECOND)
#define SUBSECONDS(x) (_RTT(x) % RTT_SECOND)
/* Place counter in .noinit section if no backup RAM is available. /* Place counter in .noinit section if no backup RAM is available.
This means the date is undefined at cold boot, but will likely still This means the date is undefined at cold boot, but will likely still
@ -133,6 +135,22 @@ int rtc_set_time(struct tm *time)
return 0; return 0;
} }
int rtc_get_time_ms(struct tm *time, uint16_t *ms)
{
uint32_t prev = rtc_now;
/* repeat calculation if an alarm triggered in between */
do {
uint32_t now = rtt_get_counter();
uint32_t tmp = _rtc_now(now);
rtc_localtime(tmp, time);
*ms = (SUBSECONDS(now) * MS_PER_SEC) / RTT_SECOND;
} while (prev != rtc_now);
return 0;
}
int rtc_get_time(struct tm *time) int rtc_get_time(struct tm *time)
{ {
uint32_t prev = rtc_now; uint32_t prev = rtc_now;

View File

@ -252,6 +252,11 @@ config HAS_PERIPH_RTC
help help
Indicates that an RTC peripheral is present. Indicates that an RTC peripheral is present.
config HAS_PERIPH_RTC_MS
bool
help
Indicates that the RTC peripheral can provide sub-second timestamps.
config HAS_PERIPH_RTT config HAS_PERIPH_RTT
bool bool
help help

View File

@ -1,6 +1,7 @@
include ../Makefile.tests_common include ../Makefile.tests_common
FEATURES_REQUIRED = periph_rtc FEATURES_REQUIRED += periph_rtc
FEATURES_OPTIONAL += periph_rtc_ms
DISABLE_MODULE += periph_init_rtc DISABLE_MODULE += periph_init_rtc

View File

@ -47,6 +47,18 @@ static void print_time(const char *label, const struct tm *time)
time->tm_sec); time->tm_sec);
} }
static void print_time_ms(const char *label, const struct tm *time, uint16_t ms)
{
printf("%s %04d-%02d-%02d %02d:%02d:%02d.%03d\n", label,
time->tm_year + TM_YEAR_OFFSET,
time->tm_mon + 1,
time->tm_mday,
time->tm_hour,
time->tm_min,
time->tm_sec,
ms);
}
static void inc_secs(struct tm *time, unsigned val) static void inc_secs(struct tm *time, unsigned val)
{ {
time->tm_sec += val; time->tm_sec += val;
@ -81,8 +93,14 @@ int main(void)
rtc_set_time(&time); rtc_set_time(&time);
/* read RTC to confirm value */ /* read RTC to confirm value */
rtc_get_time(&time); if (IS_USED(MODULE_PERIPH_RTC_MS)) {
print_time("Clock value is now ", &time); uint16_t ms;
rtc_get_time_ms(&time, &ms);
print_time_ms("Clock value is now ", &time, ms);
} else {
rtc_get_time(&time);
print_time("Clock value is now ", &time);
}
/* set initial alarm */ /* set initial alarm */
inc_secs(&time, PERIOD); inc_secs(&time, PERIOD);
@ -95,17 +113,32 @@ int main(void)
/* clear alarm */ /* clear alarm */
rtc_clear_alarm(); rtc_clear_alarm();
rtc_get_time(&time); if (IS_USED(MODULE_PERIPH_RTC_MS)) {
print_time(" Alarm cleared at ", &time); uint16_t ms;
rtc_get_time_ms(&time, &ms);
print_time_ms(" Alarm cleared at ", &time, ms);
} else {
rtc_get_time(&time);
print_time(" Alarm cleared at ", &time);
}
/* verify alarm has been cleared */ /* verify alarm has been cleared */
xtimer_sleep(PERIOD); xtimer_sleep(PERIOD);
rtc_get_time(&time);
const char *message;
if (mutex_trylock(&rtc_mtx)) { if (mutex_trylock(&rtc_mtx)) {
print_time(" Error: Alarm at ", &time); message = " Error: Alarm at ";
} else {
message = " No alarm at ";
} }
else {
print_time(" No alarm at ", &time); if (IS_USED(MODULE_PERIPH_RTC_MS)) {
uint16_t ms;
rtc_get_time_ms(&time, &ms);
print_time_ms(message, &time, ms);
} else {
rtc_get_time(&time);
print_time(message, &time);
} }
/* set alarm */ /* set alarm */