Add a delay after rtc_set_datetime (#2156)

If you call rtc_get_datetime immediately after rtc_set_datetime you get
junk back. According to the datasheet "Writing to the RTC will take
2 clk_rtc clock periods to arrive". So add a delay after calling
rtc_set_datetime in aon_timer_set_time_calendar.

Fixes #2148
This commit is contained in:
Peter Harper 2025-02-06 15:24:30 +00:00 committed by GitHub
parent 111fa7de2d
commit 7dfbb3c958
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 64 additions and 10 deletions

View file

@ -6,10 +6,14 @@ cc_library(
name = "pico_aon_timer",
srcs = ["aon_timer.c"],
hdrs = ["include/pico/aon_timer.h"],
defines = [
"LIB_PICO_AON_TIMER=1",
],
includes = ["include"],
target_compatible_with = compatible_with_rp2(),
deps = [
"//src/common/pico_util",
"//src/common/pico_time",
"//src/rp2_common:hardware_regs",
"//src/rp2_common:pico_platform",
"//src/rp2_common/hardware_irq",

View file

@ -12,6 +12,7 @@ pico_mirrored_target_link_libraries(pico_aon_timer INTERFACE pico_util)
if (TARGET hardware_rtc)
pico_mirrored_target_link_libraries(pico_aon_timer INTERFACE hardware_rtc)
target_link_libraries(pico_aon_timer_headers INTERFACE pico_time_headers)
endif()
if (TARGET hardware_powman)

View file

@ -13,6 +13,8 @@ static aon_timer_alarm_handler_t aon_timer_alarm_handler;
#if HAS_RP2040_RTC
#include "hardware/rtc.h"
#include "pico/util/datetime.h"
#include "pico/time.h"
#include "hardware/clocks.h"
#elif HAS_POWMAN_TIMER
#include "hardware/powman.h"
@ -56,6 +58,10 @@ bool aon_timer_set_time_calendar(const struct tm *tm) {
datetime_t dt;
tm_to_datetime(tm, &dt);
rtc_set_datetime(&dt);
// Writing to the RTC will take 2 clk_rtc clock periods to arrive
uint rtc_freq = clock_get_hz(clk_rtc);
busy_wait_us(((1000000 + rtc_freq - 1) / rtc_freq) * 2);
return true;
#elif HAS_POWMAN_TIMER
struct timespec ts;

View file

@ -12,6 +12,7 @@ cc_binary(
target_compatible_with = compatible_with_rp2(),
deps = [
"//src/rp2_common/pico_stdlib",
"//src/rp2_common/pico_aon_timer",
"//test/pico_test",
],
)

View file

@ -4,5 +4,8 @@ if (NOT PICO_TIME_NO_ALARM_SUPPORT)
PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS=250
)
target_link_libraries(pico_time_test PRIVATE pico_test)
if (PICO_RP2040)
target_link_libraries(pico_time_test PRIVATE pico_aon_timer)
endif()
pico_add_extra_outputs(pico_time_test)
endif()

View file

@ -13,6 +13,11 @@
#endif
#include "pico/stdlib.h"
#include "pico/test.h"
#if LIB_PICO_AON_TIMER
#include "pico/aon_timer.h"
#endif
// Include sys/types.h before inttypes.h to work around issue with
// certain versions of GCC and newlib which causes omission of PRIi64
#include <sys/types.h>
@ -74,11 +79,12 @@ static bool repeating_timer_callback(struct repeating_timer *t) {
#define RESOLUTION_ALLOWANCE PICO_HARDWARE_TIMER_RESOLUTION_US
#endif
int issue_195_test(void);
int issue_1812_test(void);
int issue_1953_test(void);
int issue_2118_test(void);
int issue_2186_test(void);
static int issue_195_test(void);
static int issue_1812_test(void);
static int issue_1953_test(void);
static int issue_2118_test(void);
static int issue_2148_test(void);
static int issue_2186_test(void);
int main() {
setup_default_uart();
@ -253,6 +259,8 @@ int main() {
issue_2118_test();
issue_2148_test();
issue_2186_test();
PICOTEST_END_TEST();
@ -265,7 +273,7 @@ int64_t issue_195_callback(alarm_id_t id, void *user_data) {
return -ISSUE_195_TIMER_DELAY;
}
int issue_195_test(void) {
static int issue_195_test(void) {
PICOTEST_START_SECTION("Issue #195 race condition - without fix may hang on gcc 10.2.1 release builds");
absolute_time_t t1 = get_absolute_time();
int id = add_alarm_in_us(ISSUE_195_TIMER_DELAY, issue_195_callback, NULL, true);
@ -284,7 +292,7 @@ int issue_195_test(void) {
}
// Setting an alarm should not swallow a sev
int issue_1812_test(void) {
static int issue_1812_test(void) {
PICOTEST_START_SECTION("Issue #1812 defect - Setting an alarm should not ignore a sev");
__sev(); // Make sure the call below does not ignore this
@ -308,7 +316,7 @@ static void alarm_pool_stuck_issue_1953(uint alarm) {
hard_assert(false);
}
int issue_1953_test(void) {
static int issue_1953_test(void) {
PICOTEST_START_SECTION("Issue #1953 defect - Alarm can be set in the past");
int alarm = hardware_alarm_claim_unused(true);
hardware_alarm_set_callback(alarm, alarm_pool_stuck_issue_1953);
@ -341,7 +349,7 @@ static bool timer_callback_issue_2118(repeating_timer_t *rt) {
return true;
}
int issue_2118_test(void) {
static int issue_2118_test(void) {
PICOTEST_START_SECTION("Issue #2118 defect - failure to set an alarm");
#if PICO_ON_DEVICE
@ -373,7 +381,7 @@ int issue_2118_test(void) {
return 0;
}
int issue_2186_test(void) {
static int issue_2186_test(void) {
PICOTEST_START_SECTION("Issue #2186 defect - ta_wakes_up_on_or_before");
hard_assert(best_effort_wfe_or_timeout(get_absolute_time() - 1));
@ -382,3 +390,34 @@ int issue_2186_test(void) {
PICOTEST_END_SECTION();
return 0;
}
static int issue_2148_test(void) {
#if HAS_RP2040_RTC
PICOTEST_START_SECTION("Issue #2148 defect - get time after rtc start");
struct tm tm = { 0 };
struct tm tm_check = { 0 };
tm.tm_sec = 55;
tm.tm_min = 36;
tm.tm_hour = 20;
tm.tm_mday = 21;
tm.tm_mon = 10;
tm.tm_year = 124;
tm.tm_wday = 4;
tm.tm_yday = 325;
tm.tm_isdst = 0;
hard_assert(aon_timer_start_calendar(&tm));
hard_assert(aon_timer_get_time_calendar(&tm_check));
PICOTEST_CHECK(tm.tm_sec == tm_check.tm_sec || tm.tm_sec == tm_check.tm_sec - 1, "failed to get seconds");
PICOTEST_CHECK(tm.tm_min == tm_check.tm_min, "failed to get minutes");
PICOTEST_CHECK(tm.tm_hour == tm_check.tm_hour, "failed to get hour");
PICOTEST_CHECK(tm.tm_mday == tm_check.tm_mday, "failed to get day");
PICOTEST_CHECK(tm.tm_mon == tm_check.tm_mon, "failed to get month");
PICOTEST_CHECK(tm.tm_year == tm_check.tm_year, "failed to get year");
aon_timer_stop();
PICOTEST_END_SECTION();
#endif
return 0;
}