Feature - RTC alarm on every second #370

Open
Reneg973 wants to merge 10 commits from Reneg973/RTC-Changes into develop
Reneg973 commented 2021-05-01 14:03:30 -05:00 (Migrated from github.com)

The PR includes 2 changes

  1. better const correctness
  2. the mentioned feature, every second the ISR is triggered to update the clock output
The PR includes 2 changes 1. better const correctness 2. the mentioned feature, every second the ISR is triggered to update the clock output
kilograham (Migrated from github.com) reviewed 2021-05-01 14:31:49 -05:00
kilograham (Migrated from github.com) left a comment
  1. Please rebase onto develop
  2. We don't have a CONTRIBUTING.md but please match the existing code style:
    • 4 spaces, not tabs
    • { on same line as if
    • if's without braces on same line as if only
    • variable names are not Hungarian
1) Please rebase onto develop 2) We don't have a CONTRIBUTING.md but please match the existing code style: - 4 spaces, not tabs - { on same line as if - if's without braces on same line as if only - variable names are not Hungarian
@ -11,9 +11,28 @@
#include "hardware/resets.h"
#include "hardware/clocks.h"
kilograham (Migrated from github.com) commented 2021-05-01 14:21:38 -05:00

prefer to use an enum for 3 repeat types

prefer to use an enum for 3 repeat types
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
kilograham (Migrated from github.com) commented 2021-05-01 14:31:38 -05:00

This seems race prone; is using the RTC clock for an every second interrupt useful?

This seems race prone; is using the RTC clock for an every second interrupt useful?
Reneg973 (Migrated from github.com) reviewed 2021-05-01 15:12:12 -05:00
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
Reneg973 (Migrated from github.com) commented 2021-05-01 15:12:12 -05:00

at least it works fine - updating my display every second while pushing the current time on UART.
But there is another more critical thing missing. ATM an attached exclusive interrupt can't be removed.

at least it works fine - updating my display every second while pushing the current time on UART. But there is another more critical thing missing. ATM an attached exclusive interrupt can't be removed.
Reneg973 (Migrated from github.com) reviewed 2021-05-01 15:13:11 -05:00
@ -11,9 +11,28 @@
#include "hardware/resets.h"
#include "hardware/clocks.h"
Reneg973 (Migrated from github.com) commented 2021-05-01 15:13:11 -05:00

I'll upate it

I'll upate it
Reneg973 (Migrated from github.com) reviewed 2021-05-01 16:50:03 -05:00
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
Reneg973 (Migrated from github.com) commented 2021-05-01 16:50:03 -05:00

the current ISR still enables rtc_alarm before user callback has returned. Maybe we should change this too?

the current ISR still enables rtc_alarm before user callback has returned. Maybe we should change this too?
Reneg973 (Migrated from github.com) reviewed 2021-05-01 17:35:17 -05:00
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
Reneg973 (Migrated from github.com) commented 2021-05-01 17:35:17 -05:00

Another question, usually RTC uses 32.768kHz clock, here 46.875kHz is programmed. What is the cause for this?

Another question, usually RTC uses 32.768kHz clock, here 46.875kHz is programmed. What is the cause for this?
lurch commented 2021-05-02 03:01:13 -05:00 (Migrated from github.com)

You need to click the "Edit" button at the top of this page and change the base branch 😉 (which will clean up the messy commit history that GH is currently displaying)

You need to click the "Edit" button at the top of this page and change the base branch :wink: (which will clean up the messy commit history that GH is currently displaying)
lurch (Migrated from github.com) reviewed 2021-05-02 03:19:26 -05:00
@ -11,9 +11,28 @@
#include "hardware/resets.h"
#include "hardware/clocks.h"
lurch (Migrated from github.com) commented 2021-05-02 03:19:26 -05:00

This looks like it might be a typo for CONTINUOUS_REPEAT_ONE_SEC 😉 Perhaps CONTINUOUS_REPEAT_EVERY_SECOND might be less ambiguous?

This looks like it might be a typo for `CONTINUOUS_REPEAT_ONE_SEC` :wink: Perhaps `CONTINUOUS_REPEAT_EVERY_SECOND` might be less ambiguous?
lurch (Migrated from github.com) reviewed 2021-05-02 03:29:00 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:29:00 -05:00

Graham might feel differently to me, but I wonder if explicitly doing

if (t->year < 0 && t->month < 0 && t->day < 0 && t->dotw < 0 && t->hour < 0 && t->min < 0 && t->sec < 0)

might be more readable than using bitwise-AND ?
(your version is also missing the space between the if and the ( 🙂 )

Graham might feel differently to me, but I wonder if explicitly doing ``` if (t->year < 0 && t->month < 0 && t->day < 0 && t->dotw < 0 && t->hour < 0 && t->min < 0 && t->sec < 0) ``` might be more readable than using bitwise-AND ? (your version is also missing the space between the `if` and the `(` :slightly_smiling_face: )
lurch (Migrated from github.com) reviewed 2021-05-02 03:29:36 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:29:36 -05:00

This comment should probably refer to the enum-values rather than -1 ?

This comment should probably refer to the enum-values rather than -1 ?
lurch (Migrated from github.com) reviewed 2021-05-02 03:30:53 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:30:53 -05:00

Should this be declared to return repeat_type rather than int8_t?

Should this be declared to return `repeat_type` rather than `int8_t`?
lurch (Migrated from github.com) reviewed 2021-05-02 03:34:01 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:34:01 -05:00

Would an alarm be considered "valid" if it e.g. had a month of 14 and a day of -1 ?

Would an alarm be considered "valid" if it e.g. had a month of `14` and a day of `-1` ?
lurch (Migrated from github.com) reviewed 2021-05-02 03:36:42 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:36:42 -05:00

I'm not sure if changing the month and day checks to 1 instead of 0 is wanted here? 🤷

I'm not sure if changing the month and day checks to `1` instead of `0` is wanted here? :shrug:
lurch (Migrated from github.com) reviewed 2021-05-02 03:37:42 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:37:42 -05:00

Should this be the first test in this chain-of-ifs, rather than only appearing in the else clause?

Should this be the first test in this chain-of-ifs, rather than only appearing in the `else` clause?
lurch (Migrated from github.com) reviewed 2021-05-02 03:40:18 -05:00
lurch (Migrated from github.com) commented 2021-05-02 03:40:18 -05:00

Is this change needed because otherwise the RTC alarm would just fire continuously?

Is this change needed because otherwise the RTC alarm would just fire continuously?
lurch (Migrated from github.com) reviewed 2021-05-02 03:44:30 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 03:44:30 -05:00

Might be better to check _alarm_repeats == NO_REPEAT rather than !_alarm_repeats ?

Might be better to check `_alarm_repeats == NO_REPEAT` rather than `!_alarm_repeats` ?
Reneg973 (Migrated from github.com) reviewed 2021-05-02 03:46:15 -05:00
@ -11,9 +11,28 @@
#include "hardware/resets.h"
#include "hardware/clocks.h"
Reneg973 (Migrated from github.com) commented 2021-05-02 03:46:15 -05:00

Not a typo, just a different point of view. An alarm is triggered ON change of x, where x may be SEC or MIN or HOUR, but all other possible alarms/triggers are already included in CONTINUOUS_REPEAT.
From SW pov you are right, I'll modify it

Not a typo, just a different point of view. An alarm is triggered ON change of x, where x may be SEC or MIN or HOUR, but all other possible alarms/triggers are already included in CONTINUOUS_REPEAT. From SW pov you are right, I'll modify it
Reneg973 (Migrated from github.com) reviewed 2021-05-02 03:48:11 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 03:48:11 -05:00

Right, I already changed it, just not pushed - anyway it needs nearly twice the operations and therefore cycles to check

Right, I already changed it, just not pushed - anyway it needs nearly twice the operations and therefore cycles to check
Reneg973 (Migrated from github.com) reviewed 2021-05-02 04:15:27 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 04:15:27 -05:00

Overseen to remove this comment, changed also return type of function

Overseen to remove this comment, changed also return type of function
Reneg973 (Migrated from github.com) reviewed 2021-05-02 04:18:24 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 04:18:24 -05:00

very good objection, needs a better breakdown

very good objection, needs a better breakdown
Reneg973 (Migrated from github.com) reviewed 2021-05-02 04:20:37 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 04:20:36 -05:00

Yes, that is a strange inconsistency in the original code. The RTC reports months from 1-12, but the input allowed a month of 0. If I assume the RTC follows the KISS principle, input and output will have the same ranges. Anyway I am not 100% sure

Yes, that is a strange inconsistency in the original code. The RTC reports months from 1-12, but the input allowed a month of 0. If I assume the RTC follows the KISS principle, input and output will have the same ranges. Anyway I am not 100% sure
Reneg973 (Migrated from github.com) reviewed 2021-05-02 05:20:21 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 05:20:21 -05:00

Is this change needed because otherwise the RTC alarm would just fire continuously?

IRQ has been triggered on second x. This code is to reenable it for second (x+1)%60. If not incremented, it would delay until it reaches second x again

> Is this change needed because otherwise the RTC alarm would just fire continuously? IRQ has been triggered on second x. This code is to reenable it for second (x+1)%60. If not incremented, it would delay until it reaches second x again
Reneg973 (Migrated from github.com) reviewed 2021-05-02 05:21:54 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 05:21:54 -05:00

oh yes, it should be first case

oh yes, it should be first case
Reneg973 (Migrated from github.com) reviewed 2021-05-02 05:26:58 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 05:26:58 -05:00

right and done

right and done
Reneg973 (Migrated from github.com) reviewed 2021-05-02 05:28:12 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-02 05:28:12 -05:00

done

done
kilograham (Migrated from github.com) reviewed 2021-05-02 08:08:20 -05:00
kilograham (Migrated from github.com) left a comment

also white space/formatting issues still

also white space/formatting issues still
@ -15,2 +24,3 @@
static rtc_callback_t _callback = NULL;
static bool _alarm_repeats = false;
static uint8_t _seconds_increment = 1;
kilograham (Migrated from github.com) commented 2021-05-02 08:04:28 -05:00

not sure why this is state; it seems like it should be a macro parameter as the usage on line 161 should always be 1 (not the last value)

not sure why this is state; it seems like it should be a macro parameter as the usage on line 161 should always be 1 (not the last value)
kilograham (Migrated from github.com) commented 2021-05-02 08:07:39 -05:00

even more confused, because t->sec is -1 here always

even more confused, because t->sec is -1 here always
Reneg973 (Migrated from github.com) reviewed 2021-05-02 08:52:46 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 08:52:45 -05:00

maybe best described with an example:
if sec input parameter for rtc_set_alarm() is in range 0<=s<=59, than we have absolute behavior. The alarm always appears when internal comparison of s with the RTC seconds is true.

If sec value is negative, it is interpreted as a relative value. Means if it is -1, _seconds_increment is set to 1, and the alarm appears whenever the seconds change. If now input sec is -2, the increment will be 2 and therefore the ISR is called every 2 seconds. As this input value is just local within rtc_set_alarm(), it must be remembered as a state, so that ISR can access it.

maybe best described with an example: if sec input parameter for rtc_set_alarm() is in range 0<=s<=59, than we have absolute behavior. The alarm always appears when internal comparison of s with the RTC seconds is true. If sec value is negative, it is interpreted as a relative value. Means if it is -1, _seconds_increment is set to 1, and the alarm appears whenever the seconds change. If now input sec is -2, the increment will be 2 and therefore the ISR is called every 2 seconds. As this input value is just local within rtc_set_alarm(), it must be remembered as a state, so that ISR can access it.
lurch (Migrated from github.com) reviewed 2021-05-02 08:56:02 -05:00
@ -33,2 +33,4 @@
#endif
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_RTC, Enable/disable assertions in the RTC module, type=bool, default=0, group=hardware_rtc
#ifndef PARAM_ASSERTIONS_ENABLED_RTC
lurch (Migrated from github.com) commented 2021-05-02 08:56:02 -05:00

Could you add a PICO_CONFIG line as well please? See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_adc/include/hardware/adc.h#L47 for an example.
(This allows the value to be set by https://github.com/raspberrypi/pico-project-generator )

Could you add a PICO_CONFIG line as well please? See https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/hardware_adc/include/hardware/adc.h#L47 for an example. (This allows the value to be set by https://github.com/raspberrypi/pico-project-generator )
lurch (Migrated from github.com) reviewed 2021-05-02 08:58:33 -05:00
@ -11,9 +11,28 @@
#include "hardware/resets.h"
lurch (Migrated from github.com) commented 2021-05-02 08:58:32 -05:00

Which months have 32 days? 😉

Which months have 32 days? :wink:
Reneg973 (Migrated from github.com) reviewed 2021-05-02 08:59:01 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 08:59:00 -05:00

E.g. like snooze function on a clock. Set alarm to -30sec repeat, alarm appears, you press button to switch off the alarm, and after 30s it appears again.

E.g. like snooze function on a clock. Set alarm to -30sec repeat, alarm appears, you press button to switch off the alarm, and after 30s it appears again.
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:06:02 -05:00
@ -11,9 +11,28 @@
#include "hardware/resets.h"
Reneg973 (Migrated from github.com) commented 2021-05-02 09:06:02 -05:00

Oh there are months that won't end at all :)
I was not sure whether <= or < has better readability, and so this slipped through.

Oh there are months that won't end at all :) I was not sure whether <= or < has better readability, and so this slipped through.
lurch (Migrated from github.com) reviewed 2021-05-02 09:07:40 -05:00
@ -114,60 +139,89 @@ void rtc_enable_alarm(void) {
}
lurch (Migrated from github.com) commented 2021-05-02 09:07:40 -05:00

@kilograham Do we definitely want to just return false here (and not set the alarm) if a user_callback wasn't supplied?

@kilograham Do we definitely want to just `return false` here (and not set the alarm) if a `user_callback` wasn't supplied?
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:07:48 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 09:07:47 -05:00

Oh maybe you're confused because _seconds_increment is processed within the macro ADD_AND_ENABLE_REPEATABLE_SECOND?

Oh maybe you're confused because _seconds_increment is processed within the macro ADD_AND_ENABLE_REPEATABLE_SECOND?
lurch (Migrated from github.com) reviewed 2021-05-02 09:12:38 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:12:38 -05:00

Feels like this function would be more robust if this check was done near the end rather than near the start? (or simply remove the check altogether, since _callback later gets set to NULL anyway)

Feels like this function would be more robust if this check was done near the end rather than near the start? (or simply remove the check altogether, since `_callback` later gets set to NULL anyway)
lurch (Migrated from github.com) reviewed 2021-05-02 09:19:09 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:19:08 -05:00

I think @Reneg973 was intending that you could set e.g. "repeat every 5 seconds" by setting t->sec to -5 ?
But I'm not sure if that's desirable behaviour, since e.g. there's no similar functionality to set "repeat every 5 minutes" (and we're not trying to re-implement cron 😉 ) so I think it might be more consistent to revert the "repeat every 5 seconds" functionality, and just stick to the "setting everything to -1 causes the alarm to repeat every second" behaviour. IMHO. For more sophisticated behaviour, the user can always add their own custom logic inside their callback function.

EDIT: That's weird, I was replying to @kilograham 's comment and for some reason GH didn't show me @Reneg973 's comments until after I posted mine! 😕

I think @Reneg973 was intending that you could set e.g. "repeat every 5 seconds" by setting `t->sec` to -5 ? But I'm not sure if that's desirable behaviour, since e.g. there's no similar functionality to set "repeat every 5 minutes" (and we're not trying to re-implement `cron` :wink: ) so I think it might be more consistent to revert the "repeat every 5 seconds" functionality, and just stick to the "setting everything to -1 causes the alarm to repeat every second" behaviour. IMHO. For more sophisticated behaviour, the user can always add their own custom logic inside their callback function. EDIT: That's weird, I was replying to @kilograham 's comment and for some reason GH didn't show me @Reneg973 's comments until after I posted mine! :confused:
kilograham (Migrated from github.com) reviewed 2021-05-02 09:19:31 -05:00
kilograham (Migrated from github.com) commented 2021-05-02 09:19:30 -05:00

no i was confused because I didn't notice you could now set this to negative values other than -1. I'm not sure that this functionality belongs here; there are plenty of other ways of getting repeating timers. hardware_foo libraries are generally intended for exposing hardware functionality in a clean API, not using the hardware to provide additional functionality.
I need to take a closer look at the RTC h/w, so I'll get back to you

no i was confused because I didn't notice you could now set this to negative values other than -1. I'm not sure that this functionality belongs here; there are plenty of other ways of getting repeating timers. `hardware_foo` libraries are generally intended for exposing hardware functionality in a clean API, not using the hardware to provide additional functionality. I need to take a closer look at the RTC h/w, so I'll get back to you
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:19:54 -05:00
@ -114,60 +139,89 @@ void rtc_enable_alarm(void) {
}
Reneg973 (Migrated from github.com) commented 2021-05-02 09:19:54 -05:00

ok this one is wrong - I fix it

Datasheet 4.8.3. says this event is also used to wakeup the pico

ok this one is wrong - I fix it Datasheet 4.8.3. says this event is also used to wakeup the pico
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:22:52 -05:00
@ -114,60 +139,89 @@ void rtc_enable_alarm(void) {
}
Reneg973 (Migrated from github.com) commented 2021-05-02 09:22:52 -05:00

Anyway I think the HAL should differ between a user event and a wakeup from dormant mode, because if it is in dormant mode, the user callback may not be executed as clk_sys may be 0

Anyway I think the HAL should differ between a user event and a wakeup from dormant mode, because if it is in dormant mode, the user callback may not be executed as clk_sys may be 0
lurch (Migrated from github.com) reviewed 2021-05-02 09:24:26 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:24:26 -05:00

Is this a condition that can actually happen? Won't it be caught by the earlier checks?

Is this a condition that can actually happen? Won't it be caught by the earlier checks?
lurch (Migrated from github.com) reviewed 2021-05-02 09:28:06 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:28:06 -05:00

Should all the if (_alarm_repeats) checks actually be if (_alarm_repeats != NO_REPEAT) ? 🤷

Should all the `if (_alarm_repeats)` checks actually be `if (_alarm_repeats != NO_REPEAT)` ? :shrug:
lurch (Migrated from github.com) reviewed 2021-05-02 09:29:43 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:29:43 -05:00

Probably worth adding a comment here saying that if all values are -1 then we repeat every second?

Probably worth adding a comment here saying that if all values are -1 then we repeat every second?
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:30:16 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 09:30:16 -05:00

it can happen if one parameter is set to a value > range and all others are -1.

it can happen if one parameter is set to a value > range and all others are -1.
lurch (Migrated from github.com) reviewed 2021-05-02 09:32:47 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-02 09:32:47 -05:00

it needs nearly twice the operations and therefore cycles to check

But with RP2040 running at 125MHz, and the RTC alarm only firing at most once per second, I don't think that should be a huge problem? 😉

> it needs nearly twice the operations and therefore cycles to check But with RP2040 running at 125MHz, and the RTC alarm only firing at most once per second, I don't think that should be a huge problem? :wink:
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:38:10 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 09:38:09 -05:00

yes, I removed the user_callback check and therefore it must be removed here too. But this leads to the next issue, see
irq_remove_handler()/irq_set_exclusive_handler(). Seems like a NULL handler is handled as a valid function ptr there.

yes, I removed the user_callback check and therefore it must be removed here too. But this leads to the next issue, see irq_remove_handler()/irq_set_exclusive_handler(). Seems like a NULL handler is handled as a valid function ptr there.
Reneg973 (Migrated from github.com) reviewed 2021-05-02 09:39:45 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 09:39:45 -05:00

a question of coding guidelines. Technically it's the same

a question of coding guidelines. Technically it's the same
lurch (Migrated from github.com) reviewed 2021-05-02 09:57:12 -05:00
lurch (Migrated from github.com) commented 2021-05-02 09:57:12 -05:00

Fair enough, that's a Graham-decision then 🙂

Fair enough, that's a Graham-decision then :slightly_smiling_face:
lurch (Migrated from github.com) reviewed 2021-05-02 10:04:36 -05:00
lurch (Migrated from github.com) commented 2021-05-02 10:04:36 -05:00

Perhaps it's worth adding an is_valid_alarmtime function, and using that as part of the valid_params_if checks?

static bool is_valid_alarmtime(const datetime_t *t) {
    return (RANGE_CHECK_YEAR(t) || t->year < 0)
        && (RANGE_CHECK_MONTH(t) || t->month < 0)
        && (RANGE_CHECK_DAY(t) || t->day < 0)
// etc.
Perhaps it's worth adding an `is_valid_alarmtime` function, and using that as part of the `valid_params_if` checks? ``` static bool is_valid_alarmtime(const datetime_t *t) { return (RANGE_CHECK_YEAR(t) || t->year < 0) && (RANGE_CHECK_MONTH(t) || t->month < 0) && (RANGE_CHECK_DAY(t) || t->day < 0) // etc. ```
lurch (Migrated from github.com) reviewed 2021-05-02 10:18:00 -05:00
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
lurch (Migrated from github.com) commented 2021-05-02 10:18:00 -05:00

The RP2040 datasheet says: "XOSC @ 12MHz / 256 = 46875Hz. To get a 1Hz reference CLKDIV_M1 should be set to 46874."
As long as CLKDIV_M1 is set to an appropriate value, I don't think it matters what frequency the RTC clock runs at? (Looks like https://github.com/raspberrypi/pico-sdk/blob/develop/src/rp2_common/hardware_clocks/clocks.c#L187 is where clk_rtc is actually configured)

The RP2040 datasheet says: "XOSC @ 12MHz / 256 = 46875Hz. To get a 1Hz reference CLKDIV_M1 should be set to 46874." As long as `CLKDIV_M1` is set to an appropriate value, I don't think it matters what frequency the RTC clock runs at? (Looks like https://github.com/raspberrypi/pico-sdk/blob/develop/src/rp2_common/hardware_clocks/clocks.c#L187 is where clk_rtc is actually configured)
lurch (Migrated from github.com) reviewed 2021-05-02 10:22:52 -05:00
@ -180,12 +234,19 @@ void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback) {
irq_set_enabled(RTC_IRQ, true);
lurch (Migrated from github.com) commented 2021-05-02 10:22:51 -05:00

Should this be irq_remove_handler(RTC_IRQ, rtc_irq_handler) ? 🤷 (IRQ-related code isn't my strong point!)

Should this be `irq_remove_handler(RTC_IRQ, rtc_irq_handler)` ? :shrug: (IRQ-related code isn't my strong point!)
Reneg973 (Migrated from github.com) reviewed 2021-05-02 10:42:11 -05:00
@ -117,1 +142,3 @@
static void rtc_irq_handler(void) {
void rtc_disable_alarm(void) {
// Disable matching and wait for it to stop being active
hw_clear_bits(&rtc_hw->irq_setup_0, RTC_IRQ_SETUP_0_MATCH_ENA_BITS);
Reneg973 (Migrated from github.com) commented 2021-05-02 10:42:10 -05:00

Exactly, 12MHz / 256... I found it. Would be nice if the comment you linked would say the same

Exactly, 12MHz / 256... I found it. Would be nice if the comment you linked would say the same
Reneg973 (Migrated from github.com) reviewed 2021-05-02 11:18:28 -05:00
@ -180,12 +234,19 @@ void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback) {
irq_set_enabled(RTC_IRQ, true);
Reneg973 (Migrated from github.com) commented 2021-05-02 11:18:28 -05:00

nice, so I had in mind that I made too many changes with 1 commit ... and prompt forgot to fix this.

nice, so I had in mind that I made too many changes with 1 commit ... and prompt forgot to fix this.
Reneg973 (Migrated from github.com) reviewed 2021-05-02 11:22:22 -05:00
@ -180,12 +234,19 @@ void rtc_set_alarm(datetime_t *t, rtc_callback_t user_callback) {
irq_set_enabled(RTC_IRQ, true);
Reneg973 (Migrated from github.com) commented 2021-05-02 11:22:21 -05:00

done

done
Reneg973 (Migrated from github.com) reviewed 2021-05-02 11:36:35 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 11:36:35 -05:00

I don't think it's worth the effort as the function already returns false then. Just an assertion could appear - if they are enable for rtc.

I think the more critical question is, what should happen with a given user_callback, if pico is woken up from RTC event?

I don't think it's worth the effort as the function already returns false then. Just an assertion could appear - if they are enable for rtc. I think the more critical question is, what should happen with a given user_callback, if pico is woken up from RTC event?
lurch (Migrated from github.com) reviewed 2021-05-02 13:02:53 -05:00
lurch (Migrated from github.com) commented 2021-05-02 13:02:53 -05:00

Perhaps it's worth adding an is_valid_alarmtime function

I don't think it's worth the effort

But I think this would successfully reject the "a month of 14 and a day of -1" that I mentioned earlier? Meh 🤷

what should happen with a given user_callback, if pico is woken up from RTC event?

Looking at https://github.com/raspberrypi/pico-extras/blob/master/src/rp2_common/pico_sleep/sleep.c#L106 (linked to from the RP2040 datasheet) it seems that whatever callback is passed to sleep_goto_sleep_until (which of course might be NULL) overwrites any existing RTC user_callback.

BTW I hope you don't feel that I'm being too picky with all my comments, I'm only trying to offer constructive feedback 🙂 And if any of my comments conflict with what @kilograham says, please ignore my comments and listen to Graham 😀

> > Perhaps it's worth adding an `is_valid_alarmtime` function > I don't think it's worth the effort But I _think_ this would successfully reject the "a month of 14 and a day of -1" that I mentioned earlier? Meh :shrug: > what should happen with a given user_callback, if pico is woken up from RTC event? Looking at https://github.com/raspberrypi/pico-extras/blob/master/src/rp2_common/pico_sleep/sleep.c#L106 (linked to from the RP2040 datasheet) it seems that whatever callback is passed to `sleep_goto_sleep_until` (which of course might be NULL) overwrites any existing RTC user_callback. BTW I hope you don't feel that I'm being too picky with all my comments, I'm only trying to offer constructive feedback :slightly_smiling_face: And if any of my comments conflict with what @kilograham says, please ignore my comments and listen to Graham :grinning:
Reneg973 (Migrated from github.com) reviewed 2021-05-02 14:04:17 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 14:04:17 -05:00

It's fine as your comments make sense. And now, good find! Yes, at least sleep_goto_sleep_until tries to overwrite the user callback. But the user callback is set with irq_set_exclusive_handler. And now we find ourselves within an hard_assert(current == __unhandled_user_irq || current == handler);

So my freshly implemented rtc_delete_alarm() is directly required for sleep_goto_sleep_until :-)

It's fine as your comments make sense. And now, good find! Yes, at least `sleep_goto_sleep_until` tries to overwrite the user callback. But the user callback is set with `irq_set_exclusive_handler`. And now we find ourselves within an `hard_assert(current == __unhandled_user_irq || current == handler);` So my freshly implemented rtc_delete_alarm() is directly required for `sleep_goto_sleep_until` :-)
lurch (Migrated from github.com) reviewed 2021-05-02 14:36:06 -05:00
lurch (Migrated from github.com) commented 2021-05-02 14:36:06 -05:00

And now we find ourselves within an hard_assert(current == __unhandled_user_irq || current == handler);

Are you sure? I think you might be mixing up the irq_handler and the user_callback again? AFAICT (and I could easily be entirely wrong!) the sleep_goto_sleep_until only changes the user_callback (which gets called by the irq_handler when the RTC alarm fires), and doesn't actually change the irq_handler? 🤷

> And now we find ourselves within an hard_assert(current == __unhandled_user_irq || current == handler); Are you sure? I think you might be mixing up the irq_handler and the user_callback again? AFAICT (and I could easily be entirely wrong!) the `sleep_goto_sleep_until` only changes the user_callback (which gets called by the irq_handler when the RTC alarm fires), and doesn't actually change the irq_handler? :shrug:
Reneg973 (Migrated from github.com) reviewed 2021-05-02 14:47:32 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 14:47:32 -05:00

ok, second condition then is true (current==handler)

ok, second condition then is true (current==handler)
Reneg973 (Migrated from github.com) reviewed 2021-05-02 16:21:47 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-02 16:21:47 -05:00

From SW side you are right, this functionality could be implemented in a level above.
There are 2 solutions then

  1. set an alarm "repeat every second" -> count the number of IRQs arrived :: fast ISR but highly increased number of IRQs
  2. set an alarm at current_time + x -> get the IRQ -> query datetime_t -> increment by x -> set new alarm via rtc_set_alarm() :: slow ISR but not more IRQs than required.

So both methods produce more overhead than really required.
Anyway I don't know which HAL strategy you want to follow for Pico.

From SW side you are right, this functionality could be implemented in a level above. There are 2 solutions then 1. set an alarm "repeat every second" -> count the number of IRQs arrived :: fast ISR but highly increased number of IRQs 2. set an alarm at current_time + x -> get the IRQ -> query datetime_t -> increment by x -> set new alarm via rtc_set_alarm() :: slow ISR but not more IRQs than required. So both methods produce more overhead than really required. Anyway I don't know which HAL strategy you want to follow for Pico.
lurch (Migrated from github.com) reviewed 2021-05-02 20:23:26 -05:00
lurch (Migrated from github.com) commented 2021-05-02 20:23:26 -05:00

3rd approach: repeat every second -> query datetime_t -> if t->sec % 5 == 0 do something, else ignore 😉

As I mentioned before, with RP2040 running with a CPU clock of 125MHz I don't think you really need to worry about "slow ISR"?

3rd approach: repeat every second -> query datetime_t -> if `t->sec % 5 == 0` do something, else ignore :wink: As I mentioned before, with RP2040 running with a CPU clock of 125MHz I don't think you really need to worry about "slow ISR"?
kilograham (Migrated from github.com) reviewed 2021-05-02 20:26:14 -05:00
kilograham (Migrated from github.com) commented 2021-05-02 20:26:14 -05:00

You do need to worry!

You do need to worry!
Reneg973 (Migrated from github.com) reviewed 2021-05-03 02:16:12 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-03 02:16:12 -05:00

3rd approach = 1st :) - I meant the same! And t->sec % 5 is not correct, you need include the start seconds.
And 125MHz is just the default. I have improved my SPI performance by 22% (increase SPI freq 31.25MHz -> 40MHz), but for this I had to sacrifice 36% of clk_sys by setting it to 80MHz!

3rd approach = 1st :) - I meant the same! And t->sec % 5 is not correct, you need include the start seconds. And 125MHz is just the default. I have improved my SPI performance by 22% (increase SPI freq 31.25MHz -> 40MHz), but for this I had to sacrifice 36% of clk_sys by setting it to 80MHz!
Reneg973 (Migrated from github.com) reviewed 2021-05-03 12:33:58 -05:00
@ -114,60 +139,89 @@ void rtc_enable_alarm(void) {
}
Reneg973 (Migrated from github.com) commented 2021-05-03 12:33:58 -05:00

ok no user callback in sleep because it's overwritten

ok no user callback in sleep because it's overwritten
Reneg973 (Migrated from github.com) reviewed 2021-05-03 12:35:33 -05:00
@ -33,2 +33,4 @@
#endif
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_RTC, Enable/disable assertions in the RTC module, type=bool, default=0, group=hardware_rtc
#ifndef PARAM_ASSERTIONS_ENABLED_RTC
Reneg973 (Migrated from github.com) commented 2021-05-03 12:35:32 -05:00

done

done
Reneg973 (Migrated from github.com) reviewed 2021-05-03 12:48:38 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-03 12:48:38 -05:00

I am simply no friend of increasing the number of execution cycles just to increase readability. If it's not clear, it could be documented.

I am simply no friend of increasing the number of execution cycles just to increase readability. If it's not clear, it could be documented.
lurch (Migrated from github.com) reviewed 2021-05-03 13:51:39 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
lurch (Migrated from github.com) commented 2021-05-03 13:51:39 -05:00

Another Graham-decision I think 😉
EDIT: If "bitwise-ands and a single-check" is preferable to "separate-checks and logical-ands" for performance reasons, perhaps (t->year < 0 || t->month < 0 || t->day < 0 || t->dotw < 0 || t->hour < 0 || t->min < 0 || t->sec < 0) could also be condensed into a "bitwise-or and a single-check"? 🤷‍♂️

Another Graham-decision I think :wink: EDIT: If "bitwise-ands and a single-check" is preferable to "separate-checks and logical-ands" for performance reasons, perhaps `(t->year < 0 || t->month < 0 || t->day < 0 || t->dotw < 0 || t->hour < 0 || t->min < 0 || t->sec < 0)` could also be condensed into a "bitwise-or and a single-check"? :man_shrugging:
Reneg973 (Migrated from github.com) reviewed 2021-05-03 14:16:42 -05:00
@ -118,1 +148,4 @@
}
static void __no_inline_not_in_flash_func(rtc_irq_handler)(void) {
// Always disable the alarm to clear the current IRQ.
Reneg973 (Migrated from github.com) commented 2021-05-03 14:16:42 -05:00

It could, I would be happy to change it if accepted. But of course it's a little bit bit "hacking" at a place where it is not really time critical. Just a few clock cycles and a few bytes binary code size reduction.

It could, I would be happy to change it if accepted. But of course it's a little bit bit "hacking" at a place where it is not really time critical. Just a few clock cycles and a few bytes binary code size reduction.
Reneg973 (Migrated from github.com) reviewed 2021-05-06 04:09:38 -05:00
Reneg973 (Migrated from github.com) commented 2021-05-06 04:09:37 -05:00

no i was confused because I didn't notice you could now set this to negative values other than -1. I'm not sure that this functionality belongs here; there are plenty of other ways of getting repeating timers. hardware_foo libraries are generally intended for exposing hardware functionality in a clean API, not using the hardware to provide additional functionality.
I need to take a closer look at the RTC h/w, so I'll get back to you

@kilograham:
Repeating timers are not repeating clock ticks. Anyway here is my proposal for a modification to be able to do this outside:

  1. generate a new interface function rtc_modify_alarm() which reduces the overhead of rtc_set_alarm() and therefore can be called within the ISR.
  2. in almost all use cases when the user ISR is called, the RTC time will be queried. Give it as a parameter (tell don't ask principle).

What do you think?

> no i was confused because I didn't notice you could now set this to negative values other than -1. I'm not sure that this functionality belongs here; there are plenty of other ways of getting repeating timers. `hardware_foo` libraries are generally intended for exposing hardware functionality in a clean API, not using the hardware to provide additional functionality. > I need to take a closer look at the RTC h/w, so I'll get back to you @kilograham: Repeating timers are not repeating clock ticks. Anyway here is my proposal for a modification to be able to do this outside: 1. generate a new interface function rtc_modify_alarm() which reduces the overhead of rtc_set_alarm() and therefore can be called within the ISR. 2. in almost all use cases when the user ISR is called, the RTC time will be queried. Give it as a parameter (tell don't ask principle). What do you think?
This pull request has changes conflicting with the target branch.
  • src/rp2_common/hardware_rtc/include/hardware/rtc.h
  • src/rp2_common/hardware_rtc/rtc.c
View command line instructions

Manual merge helper

Use this merge commit message when completing the merge manually.

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin 'Reneg973/RTC-Changes:Reneg973/RTC-Changes'
git switch 'Reneg973/RTC-Changes'

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch 'develop'
git merge --no-ff 'Reneg973/RTC-Changes'
git switch 'Reneg973/RTC-Changes'
git rebase 'develop'
git switch 'develop'
git merge --ff-only 'Reneg973/RTC-Changes'
git switch 'Reneg973/RTC-Changes'
git rebase 'develop'
git switch 'develop'
git merge --no-ff 'Reneg973/RTC-Changes'
git switch 'develop'
git merge --squash 'Reneg973/RTC-Changes'
git switch 'develop'
git merge --ff-only 'Reneg973/RTC-Changes'
git switch 'develop'
git merge 'Reneg973/RTC-Changes'
git push origin 'develop'
Sign in to join this conversation.
No reviewers
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-raspberrypi/pico-sdk!370
No description provided.