-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
drivers: counter: Add user_data to alarm callback #11572
drivers: counter: Add user_data to alarm callback #11572
Conversation
Codecov Report
@@ Coverage Diff @@
## topic-counters #11572 +/- ##
===============================================
Coverage 53.94% 53.94%
===============================================
Files 242 242
Lines 27654 27654
Branches 6717 6717
===============================================
Hits 14917 14917
Misses 9932 9932
Partials 2805 2805 Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, with some minor comments. Also Shippable needs to be made happy.
Added renaming @anangl suggested offline that |
include/counter.h
Outdated
*/ | ||
typedef void (*counter_alarm_callback_t)(struct device *dev, | ||
const struct counter_alarm_cfg *cfg, | ||
typedef void (*counter_alarm_callback_t)(void *user_data, u8_t chan_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I commented in #8340 (comment) that I don't agree with removing the dev argument to the callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MaureenHelm can you please summarize how to implement more advanced use cases like the one described in #8340 (comment) without making this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #11976 for rationale for providing both dev and a generic pointer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After reading #11976 and re-thinking this particular case, I think we should keep the dev
pointer and add the generic one as the additional parameter. Apart from the semi-consistency argument raised by @MaureenHelm (see #8340 (comment)) I can imagine cases where using a common user_data
for multiple devices would be desirable and then having only one generic pointer would force the users to use an additional structure for just holding both the dev
and user_data
pointers. This does not seem to be reasonable. Besides, the dev
pointer "comes for free" (we'll almost always have it at hand in the routine that will call the callback, no need to use additional storage for it) so just passing it as the first parameter will not be a big cost.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can imagine cases where using a common
user_data
for multiple devices would be desirable and then having only one generic pointer would force the users to use an additional structure for just holding both thedev
anduser_data
pointers.
The GPIO case described in #11976 is a bit different. Had GPIO callback passed a generic user_data pointer as a parameter there would be no problem getting access to all the required data.
Besides, the
dev
pointer "comes for free"
It does come cheap. But - at least on ARM architecture - only up to 4 parameters are passed to the function as register variables. If the parameter list is longer we need to put them on the stack. So if we decide to have a general convention to always pass pointer to dev
and to user_data
there is a price to pay.
So far I haven't seen anywhere in the Zephyr's code (or an application) a place where having a pointer to user_data
passed in the callback function would turn out to be insufficient. If someone could point to an example that proves to the contrary that certainly would be major argument for passing both parameters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there's any argument that it isn't technically sufficient to pass only user_data
. It's just that in some cases that requires the user of the API to do extra work to capture the desired non-device pointer and the device pointer into an persistent object that wouldn't be needed if the handler were given both values. It's not quite "no problem".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, by "would turn out to be insufficient" I actually meant
requires the user of the API to do extra work to capture the desired non-device pointer and the device pointer into an persistent object that wouldn't be needed if the handler were given both values.
I really haven't seen it. Could you point me to a place in the code where such plumbing was necessary? In the GPIO case the callback doesn't pass user_data
so the example is not adequate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replied here since that's where we're discussing the general case. I don't know enough about the counter API to create an equivalent situation, though I'm pretty sure it could be done.
typedef int (*counter_api_set_alarm)(struct device *dev, | ||
const struct counter_alarm_cfg *alarm_cfg); | ||
typedef int (*counter_api_disable_alarm)(struct device *dev, | ||
typedef int (*counter_api_set_alarm)(struct device *dev, u8_t chan_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the the application need to request a specific channel id? Could we instead return a channel id like the watchdog api?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then driver must implement some kind of allocator. In case of single instance watchdog which is shared between multiple subsystems that's good approach but in case of counter it will most likely be used by single subsystem or object so allocator, imo, is unnecessary complication of the driver.
@@ -148,11 +145,11 @@ void test_single_shot_alarm_instance(const char *dev_name) | |||
err = counter_set_wrap(dev, ticks, wrap_handler, exp_user_data); | |||
zassert_equal(0, err, "Counter failed to set wrap\n"); | |||
|
|||
err = counter_set_alarm(dev, &alarm_cfg); | |||
err = counter_set_ch_alarm(dev, 0, &alarm_cfg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aha! Like you said in the api meeting today, you did change the test to use counter_set_ch_alarm
. It just isn't in the topic branch yet.
include/counter.h
Outdated
@@ -75,8 +75,7 @@ struct counter_alarm_cfg { | |||
typedef void (*counter_wrap_callback_t)(struct device *dev, void *user_data); | |||
|
|||
/* Deprecated counter callback. */ | |||
typedef void (*counter_callback_t)(struct device *dev, | |||
void *user_data); | |||
typedef void (*counter_callback_t)(struct device *dev, void *user_data); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you changing the deprecated callback in this commit? It seems like an unrelated change to the renaming of counter_set_ch_alarm
to counter_set_channel_alarm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep, i will clean up a bit this PR since it became aggregation of couple of changes. Will split them into separate PRs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extracted it to independent commit
One extra vote for a consistent API. Since we seem to agree that passing As far as I know there is no official 'best practices' document on how to do API changes, even though there were talks on creating one. The preferred way however is to use In case of counter API we can use
rather than doing
since that's where all the problems come from. |
46496c8
to
c78e4a1
Compare
@mnkp, issue is with legacy callback having @anangl , @MaureenHelm what do you think about that approach (of course, given that we remove |
@nordic-krch my idea about solving backward compatibility issue was a bit different. I'll explain it in a bit more detail. At the moment Shippable fails with the message
that's because Currently we do
and I believe we shouldn't. I reckon it's better to keep the new implementation straightforward, that means:
i.e. |
2e57cff
to
215f872
Compare
{ | ||
struct device *dev; | ||
int err; | ||
int cnt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nordic-krch isn't cnt variable should be u32_t ? In case of aonpt it is causing overflow as aonpt is down counter and intial value of counter 0xffffffff.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, i've updated that in this PR.
a160175
to
9c24fa0
Compare
@mnkp @anangl @MaureenHelm I've added |
I think we should also rename the |
9c24fa0
to
71643fe
Compare
@anangl added that to this commit |
typedef int (*counter_api_set_alarm)(struct device *dev, | ||
const struct counter_alarm_cfg *alarm_cfg); | ||
typedef int (*counter_api_disable_alarm)(struct device *dev, | ||
typedef int (*counter_api_set_alarm)(struct device *dev, u8_t chan_id, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We've changed the signature of set_alarm function (counter_api_set_alarm) but didn't update all the drivers to reflect the change. The shippable is failing with
/home/buildslave/src/github.com/zephyrproject-rtos/zephyr/drivers/counter/counter_qmsi_aonpt.c:154:15: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
.set_alarm = aon_timer_qmsi_set_alarm,
^~~~~~~~~~~~~~~~~~~~~~~~
/home/buildslave/src/github.com/zephyrproject-rtos/zephyr/drivers/counter/counter_qmsi_aonpt.c:154:15: note: (near initialization for aon_timer_qmsi_api.set_alarm)
The counter_qmsi_aonpt implements the old signature
static int aon_timer_qmsi_set_alarm(struct device *dev,
counter_callback_t callback,
u32_t count, void *user_data)
PR that broke the CI tests was merged earlier but we still need to fix this issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a few more comments regarding function names. I'm however also not sure if they should be handled in this PR. We have Several functions use 'ticks' parameter to pass counter value. Ticks has an immediate connotation with kernel ticks and is therefore very confusing. IMHO the old 'count' name was much better. Also function names like We have a function |
That's subjective. I don't have such connotations. If we change parameter to count then we must have
I agree that |
Yes,
Well, |
+1 I agree with comments from @anangl. The main purpose of the I would like to insist on reconsidering usage of the 'ticks' name:
That said I agree with the following
I don't have a good alternative and having the function is definitely useful. |
I agree with @nordic-krch that this is a subjective thing if one connects ticks primarily with kernel. To me it feels natural to use the term tick also for counters and I personally don't find it confusing even in the context of an RTOS. But I don't really have a strong opinion about this. |
@anangl, @mnkp: I had similar discussion with @andyross when he reworked timer subsystem of the Zephyr. By my understanding the nomenclature is following:
So as you see the TICK in Zephyr (time unit) is much closer to "jiffy" in Linux (also time unit) than the classic tick definition (regular timer interrupt). And this is a bit confusing. |
In some uses the counter is incremented not by time but by an external signal. From that I'm used to thinking of the increment to a counter as being a "tick", even if the same word also describes the OS granularity for timeslicing. Using "cycles" for any counter other than something with a direct (probably 1-1) relation to the fundamental instruction issue rate or CPU frequency would be more confusing. Absent a clean alternative my vote is: stick with tick. |
215f872
to
6b96890
Compare
71643fe
to
8962770
Compare
2f603c6
to
72f7261
Compare
@nordic-krch this one also needs to be converted to a cherry-pick of the one commit. Rebasing makes a mess. I'm not sure how the disable of No rush, now that I know what's going on I'll cherry-pick the pieces I need. |
5af3910
to
2766569
Compare
2766569
to
c873027
Compare
Modify alarm callback to return user_data and channel_id. Set_alarm and disable_alarm updated accordingly. Renamed counter_*_ch_alarm to counter_*_channel_alarm. Updated test and nrf implementations. Updated doxygen comments. Signed-off-by: Krzysztof Chruscinski <[email protected]>
c873027
to
0ff4c78
Compare
Renamed: - counter_set_wrap to counter_set_top_value - counter_get_wrap to counter_get_top_value - counter_get_max_wrap to counter_get_max_top_value Updated nRF implementations and counter test. Signed-off-by: Krzysztof Chruscinski <[email protected]>
@nordic-krch I think it would be best to move the top rename out of this PR. Looking at it I'm noticing some things I think are problematic with the API and need to think about and describe, and I don't want to delay merging the callback rework since it's blocking other platforms from updating. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Never mind waiting; of course this changes API that people have to update for too.
One non-blocking comment.
u32_t wrap; | ||
counter_top_callback_t top_cb; | ||
void *top_user_data; | ||
u32_t top; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer this be top_value
, but I won't block for that.
It's a bit late but this PR is missing one change that we agreed to perform.
It would be good to align these names before |
@mnkp yes, forgot about it. Lets wait with that until all remaining PR's (3 now) will go into topic-counters. It will be easier to change that at once on all implementations then forcing yet another round of aligning for each PR. |
@mnkp @nordic-krch Completely agree about being consistent, but.... Somewhere in an issue comment it was clarified that In my opinion if this is a one-shot alarm it should be set/cancel. If it's a repeating alarm it should be enable/disable. Does this work for everybody? |
Modify alarm callback to return user_data and channel_id.
Set_alarm and disable_alarm updated accordingly.
Updated counter.h
Nordic drivers and test aligned.
Signed-off-by: Krzysztof Chruscinski [email protected]