diff --git a/src/rp2_common/pico_aon_timer/aon_timer.c b/src/rp2_common/pico_aon_timer/aon_timer.c index 01f8ee09c..a4d594f63 100644 --- a/src/rp2_common/pico_aon_timer/aon_timer.c +++ b/src/rp2_common/pico_aon_timer/aon_timer.c @@ -14,9 +14,6 @@ static aon_timer_alarm_handler_t aon_timer_alarm_handler; #include "hardware/rtc.h" #include "pico/util/datetime.h" -static __force_inline bool ts_to_tm(const struct timespec *ts, struct tm *tm) { - return pico_localtime_r(&ts->tv_sec, tm) != NULL; -} #elif HAS_POWMAN_TIMER #include "hardware/powman.h" @@ -28,6 +25,9 @@ static void powman_timer_irq_handler(void) { if (aon_timer_alarm_handler) aon_timer_alarm_handler(); } +static bool ts_to_tm(const struct timespec *ts, struct tm *tm) { + return pico_localtime_r(&ts->tv_sec, tm) != NULL; +} #endif static bool tm_to_ts(const struct tm *tm, struct timespec *ts) { @@ -89,8 +89,8 @@ bool aon_timer_get_time_calendar(struct tm *tm) { return true; #elif HAS_POWMAN_TIMER struct timespec ts; - bool ok = tm_to_ts(tm, &ts); - return ok && aon_timer_get_time(&ts); + aon_timer_get_time(&ts); + return ts_to_tm(&ts, tm); #else panic_unsupported(); #endif @@ -179,29 +179,36 @@ void aon_timer_start_with_timeofday(void) { aon_timer_start(&ts); } -void aon_timer_start(const struct timespec *ts) { +bool aon_timer_start(const struct timespec *ts) { #if HAS_RP2040_RTC rtc_init(); - aon_timer_set_time(ts); + return aon_timer_set_time(ts); #elif HAS_POWMAN_TIMER // todo how best to allow different configurations; this should just be the default powman_timer_set_1khz_tick_source_xosc(); - powman_timer_set_ms(timespec_to_ms(ts)); - powman_timer_start(); + bool ok = aon_timer_set_time(ts); + if (ok) { + powman_timer_set_ms(timespec_to_ms(ts)); + powman_timer_start(); + } + return ok; #else panic_unsupported(); #endif } -void aon_timer_start_calendar(const struct tm *tm) { +bool aon_timer_start_calendar(const struct tm *tm) { #if HAS_RP2040_RTC rtc_init(); - aon_timer_set_time_calendar(tm); + return aon_timer_set_time_calendar(tm); #elif HAS_POWMAN_TIMER // todo how best to allow different configurations; this should just be the default powman_timer_set_1khz_tick_source_xosc(); - aon_timer_set_time_calendar(tm); - powman_timer_start(); + bool ok = aon_timer_set_time_calendar(tm); + if (ok) { + powman_timer_start(); + } + return ok; #else panic_unsupported(); #endif diff --git a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h index ebe55ebb7..1a3eb5037 100644 --- a/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h +++ b/src/rp2_common/pico_aon_timer/include/pico/aon_timer.h @@ -24,21 +24,34 @@ * This library uses the Powman Timer on RP2350. * \endif * - * This library supports both `aon_timer_xxx_calendar()` methods which take a calendar date/time (as struct tm), - * and `aon_timer_xxx()` methods which take a time since epoch (as struct timespec) + * This library supports both `aon_timer_xxx_calendar()` methods which use a calendar date/time (as struct tm), + * and `aon_timer_xxx()` methods which use a linear time value relative an internal reference time (via struct timespec). * * \if rp2040_specific - * NOTE: On RP2040 the non date/time methods must convert the struct timespec to a date/time value which is handled via - * the \ref pico_localtime_r method. By default, this pulls in the C library local_time_r method which can lead to a big increase in binary size. - * `pico_localtime_r` is weak, so can be overridden if a better/smaller alternative is available, otherwise you might consider - * using the `aon_timer_xxx_calendar()` variants on RP2040 + * NOTE: On RP2040 the non 'calendar date/time' methods must convert the linear time value to a calendar date/time internally; these methods are: + * + * * \ref aon_timer_start_with_timeofday + * * \ref aon_timer_start + * * \ref aon_timer_set_time + * * \ref aon_timer_get_time + * * \ref aon_timer_enable_alarm + * + * This conversion is handled by the \ref pico_localtime_r method. By default, this pulls in the C library `local_time_r` method + * which can lead to a big increase in binary size. The default implementation of `pico_localtime_r` is weak, so it can be overridden + * if a better/smaller alternative is available, otherwise you might consider the method variants ending in `_calendar()` instead on RP2040. * \endif * * \if rp2350_specific - * NOTE: On RP2350 the date/time methods must convert the struct tm to a struct timespec value which is handled via - * the \ref pico_mktime method. By default, this pulls in the C library mktime method which can lead to a big increase in binary size. - * `pico_mktime` is weak, so can be overridden if a better/smaller alternative is available, otherwise you might consider - * using the `aon_timer_xxx()` variants on RP2350 + * NOTE: On RP2350 the 'calendar date/time' methods must convert the calendar date/time to a linear time value internally; these methods are: + * + * * \ref aon_timer_start_calendar + * * \ref aon_timer_set_time_calendar + * * \ref aon_timer_get_time_calendar + * * \ref aon_timer_enable_alarm_calendar + * + * This conversion is handled by the \ref pico_mktime method. By default, this pulls in the C library `mktime` method + * which can lead to a big increase in binary size. The default implementation of `pico_mktime` is weak, so it can be overridden + * if a better/smaller alternative is available, otherwise you might consider the method variants not ending in `_calendar()` instead on RP2350. * \endif */ @@ -66,6 +79,11 @@ typedef void (*aon_timer_alarm_handler_t)(void); /** * \brief Start the AON timer running using the result from the gettimeofday() function as the current time + * + * \if rp2040_specific + * See \ref pico_aon_timer for caveats with using this method on RP2040 + * \endif + * * \ingroup pico_aon_timer */ void aon_timer_start_with_timeofday(void); @@ -73,10 +91,30 @@ void aon_timer_start_with_timeofday(void); /** * \brief Start the AON timer running using the specified timespec as the current time * \ingroup pico_aon_timer - * \param ts the current time + * + * \if rp2040_specific + * See \ref pico_aon_timer for caveats with using this method on RP2040 + * \endif + * + * \param ts the time to set as 'now' + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_start_calendar */ -void aon_timer_start(const struct timespec *ts); -void aon_timer_start_calendar(const struct tm *tm); +bool aon_timer_start(const struct timespec *ts); + +/** + * \brief Start the AON timer running using the specified calendar date/time as the current time + * + * \if rp2350_specific + * See \ref pico_aon_timer for caveats with using this method on RP2350 + * \endif + * + * \ingroup pico_aon_timer + * \param tm the calendar date/time to set as 'now' + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_start + */ +bool aon_timer_start_calendar(const struct tm *tm); /** * \brief Stop the AON timer @@ -85,19 +123,59 @@ void aon_timer_start_calendar(const struct tm *tm); void aon_timer_stop(void); /** - * \brief Update the current time of the AON timer + * \brief Set the current time of the AON timer * \ingroup pico_aon_timer + * + * \if rp2040_specific + * See \ref pico_aon_timer for caveats with using this method on RP2040 + * \endif + * * \param ts the new current time + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_set_time_calendar */ bool aon_timer_set_time(const struct timespec *ts); + +/** + * \brief Set the current time of the AON timer to the given calendar date/time + * \ingroup pico_aon_timer + * + * \if rp2350_specific + * See \ref pico_aon_timer for caveats with using this method on RP2350 + * \endif + * + * \param tm the new current time + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_set_time + */ bool aon_timer_set_time_calendar(const struct tm *tm); /** * \brief Get the current time of the AON timer * \ingroup pico_aon_timer + * + * \if rp2040_specific + * See \ref pico_aon_timer for caveats with using this method on RP2040 + * \endif + * * \param ts out value for the current time + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_get_time_calendar */ bool aon_timer_get_time(struct timespec *ts); + + /** + * \brief Get the current time of the AON timer as a calendar date/time + * \ingroup pico_aon_timer + * + * \if rp2350_specific + * See \ref pico_aon_timer for caveats with using this method on RP2350 + * \endif + * + * \param tm out value for the current calendar date/time + * \return true on success, false if internal time format conversion failed + * \sa aon_timer_get_time + */ bool aon_timer_get_time_calendar(struct tm *tm); /** @@ -116,16 +194,40 @@ void aon_timer_get_resolution(struct timespec *ts); * \endif * \if rp2040_specific * On RP2040 the alarm will not fire if it is in the past. + * + * See \ref pico_aon_timer for caveats with using this method on RP2040 * \endif * * \param ts the alarm time * \param handler a callback to call when the timer fires (can be NULL for wakeup_from_low_power = true) * \param wakeup_from_low_power true if the AON timer is to be used to wake up from a DORMANT state * \return on success the old handler (or NULL if there was none) - * on failure, PICO_ERROR_INVALID_ARG + * or PICO_ERROR_INVALID_ARG if internal time format conversion failed * \sa pico_localtime_r */ aon_timer_alarm_handler_t aon_timer_enable_alarm(const struct timespec *ts, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power); + +/** + * \brief Enable an AON timer alarm for a specified calendar date/time + * \ingroup pico_aon_timer + * + * \if rp2350_specific + * On RP2350 the alarm will fire if it is in the past + * + * See \ref pico_aon_timer for caveats with using this method on RP2350 + * \endif + * + * \if rp2040_specific + * On RP2040 the alarm will not fire if it is in the past. + * \endif + * + * \param tm the alarm calendar date/time + * \param handler a callback to call when the timer fires (can be NULL for wakeup_from_low_power = true) + * \param wakeup_from_low_power true if the AON timer is to be used to wake up from a DORMANT state + * \return on success the old handler (or NULL if there was none) + * or PICO_ERROR_INVALID_ARG if internal time format conversion failed + * \sa pico_localtime_r + */ aon_timer_alarm_handler_t aon_timer_enable_alarm_calendar(const struct tm *tm, aon_timer_alarm_handler_t handler, bool wakeup_from_low_power); /**