-
Notifications
You must be signed in to change notification settings - Fork 7.3k
drivers: wdt: Watchdog API redesign and shim for nrfx wdt driver #7007
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #7007 +/- ##
==========================================
+ Coverage 55.26% 58.54% +3.27%
==========================================
Files 467 464 -3
Lines 51649 47400 -4249
Branches 9888 8783 -1105
==========================================
- Hits 28543 27748 -795
+ Misses 19196 15821 -3375
+ Partials 3910 3831 -79
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 OK
1aa13d1
to
009ba88
Compare
Reworked comments in test and text in shim-related commit message. Fixed code issue found by failing test. |
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.
Tiny comments.
I would have split the shim driver and the dts changes/additions into 2 patches.
drivers/watchdog/Kconfig
Outdated
3 INFO, write SYS_LOG_INF in addition to previous levels | ||
4 DEBUG, write SYS_LOG_DBG in addition to previous levels | ||
|
||
config HAVE_WDT_MULTISTAGE |
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.
This option seems useless to me
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.
This code is part of #1260
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 think this option should be kept: #1260 (review)
include/watchdog.h
Outdated
void (*enable)(struct device *dev); | ||
void (*get_config)(struct device *dev, struct wdt_config *config); | ||
int (*set_config)(struct device *dev, struct wdt_config *config); | ||
void (*reload)(struct device *dev); |
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.
Convention seems to be that you need to declare typedefs first for each type of fonction (not all, as long as signature is same, and name is relevant to match 2+ functions...).
So you'll need to have wdt_api_* function types.
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.
This code is part of #1260
Can be aligned
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.
Aligned only new functions names. Please let me know if I should change old ones too
drivers/watchdog/wdt_nrf.c
Outdated
} | ||
|
||
IRQ_CONNECT(CONFIG_WDT_NRF_IRQ, | ||
CONFIG_WDT_NRF_IRQ_PRI, wdt_nrf_isr, |
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.
is it github that messes up the indentation or is the indentation badly done? (indent should be below last '(' + 1 space)
drivers/watchdog/wdt_nrf.c
Outdated
{ | ||
ARG_UNUSED(dev); | ||
|
||
nrfx_err_t err_code = nrfx_wdt_channel_alloc(&m_ch[m_ch_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.
Variable declaration always at the beginning of a code block, so here above ARG_UNUSED()
Splitted shim to shim and dts commits |
drivers/watchdog/wdt_nrf.c
Outdated
{ | ||
ARG_UNUSED(dev); | ||
/* Deprecated function. No implementation needed. */ | ||
SYS_LOG_ERR("Function not implemented!"); |
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.
This is not entirely true. Though this function is "empty", it is not deprecated. It is called on the initialization of the device (see DEVICE_AND_API_INIT
below). Maybe it would be good to rename it to e.g. init_wdt
to differentiate from the ones needed for filling the wdt_driver_api
structure and avoid confusion this way?
drivers/watchdog/Kconfig
Outdated
@@ -30,4 +57,6 @@ source "drivers/watchdog/Kconfig.esp32" | |||
|
|||
source "drivers/watchdog/Kconfig.sam0" | |||
|
|||
source "drivers/watchdog/Kconfig.nrf" |
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.
"Kconfig.nrfx" - that's the convention we decided to use for shims using nrfx drivers.
drivers/watchdog/Kconfig.nrf
Outdated
int "Reload value in [ms]" | ||
depends on WDT_NRF | ||
default 2000 | ||
range 1 130150524 |
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.
This value is strange. I guess it was supposed to be: 0xFFFFFFFF (max value that can be written to NRF_WDT->CRV
) * 30,51 us (1s / 32768) = 131039452 ms. But maybe we should limit it to some more reasonable value. 86400000 would be one day. Could there be a need to reload a watchdog less frequently?
drivers/watchdog/wdt_nrf.c
Outdated
|
||
struct wdt_nrf_dev_data { | ||
void (*cb)(struct device *dev, void *handle); | ||
}; |
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.
Is this still needed? It looks like remains from an earlier version.
See also line 183.
2e14558
to
03680c9
Compare
drivers/watchdog/Kconfig.nrfx
Outdated
|
||
config WDT_NRF_DEVICE_NAME | ||
string "Device name for Watchdog (WDT)" | ||
depends on WDT_NRFX |
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.
Use if WDT_NRFX
to enclose these two config entries instead of specifying depends on WDT_NRFX
for both of them (it's not very likely that new ones will be added here in the future, but this will be consistent with other Kconfigs).
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
{ | ||
/* Started watchdog cannot be stopped on nRF devices. */ | ||
ARG_UNUSED(dev); | ||
return 0; |
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.
This operation is not available, so it would be better to return -ENOTSUP
.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
* Clearing events also clears the reload register and has to be done | ||
* AFTER event handler. | ||
*/ | ||
if (nrf_wdt_int_enable_check(NRF_WDT_INT_TIMEOUT_MASK)) { |
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.
This is unnecessary. The TIMEOUT event is the only one that can trigger the interrupt.
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.
Ok, will be removed. It can speed up code execution a little
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
* The m_alloc_ch_num variable stores number of currently allocated | ||
* and activated watchdog channels. | ||
*/ | ||
static u32_t m_alloc_ch_num; |
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.
u8_t
will be enough.
And what about renaming it to m_activated_channels
?
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'd prefer to use here m_allocated_channels
(if we would like to change it) to be more consistent with nrfx_wdt_channel_alloc
function itself.
u8_t -> okay, that's right.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
/* Each activated and not reloaded channel can generate watchdog interrupt. | ||
* Array m_cb provides storing callbacks for each channel. | ||
*/ | ||
static wdt_callback_t m_cb[NRF_WDT_CHANNELS_NUMBER]; |
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'd suggest m_callbacks
. m_cb
may be confused with "control block".
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.
will be changed
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
return 0; | ||
} | ||
|
||
static void wdt_nrf_enable(struct device *dev) |
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.
This function is deprecated, so it should be "not implemented" like the others.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
return -ENOMEM; | ||
} | ||
|
||
cfg->handle = &m_ch[m_alloc_ch_num]; |
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.
Now I see that we misunderstood the API a bit. This field was not originally supposed to be filled by the driver (see here). But I think such approach is troublesome because driver would need to do some mapping of the handle
pointer to a proper watchdog channel and this will be ineffective. It will be better to use what you proposed earlier - to return from this function the index of the activated channel, and then expect this index to be passed to wdt_feed
.
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.
Well, that's point to discuss. Feed function needs information about channel to be feeded. Now we have two points where we can do it. Solution based on pointer to struct is more generic imo. Now it is not completely compatible with documentation.
Surely it can be done using integer value returned by install_timeout
function (second solution). However it requires a little changes in implementation.
I will align doc to choosen solution.
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.
Okay, My proposal is to return index of allocated watchdog channel in install_timeout
function and use it to deal with feed
function. Index can be easily translated inside the shim layer.
There is only one point to discuss. It requires one change in doc. I mean values started from zero are valid and point to channel index instead of pointing directly to "success" return code:
https://github.com/zephyrproject-rtos/zephyr/pull/1260/files#diff-eb04a3826c198cc49f02f288abf3d859R230
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.
Returning the index in install_timeout
is fine.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
nrfx_err_t err_code; | ||
|
||
/* Set default value according to default value in MCU. */ | ||
config.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP; |
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.
This should be NRF_WDT_BEHAVIOUR_RUN_SLEEP_HALT
, otherwise WDT_OPT_PAUSE_HALTED_BY_DBG
won't be handled correctly.
And perhaps it would be better to keep this line together with others related to the config
structure?
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.
By default watchdog is running when CPU sleeps. I think next lines can be modified to cover all cases. I'll look at it
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.
Ok I got it. Changed.
include/watchdog.h
Outdated
* window differs from windows for alarms installed so far. | ||
*/ | ||
static inline int wdt_install_timeout(struct device *dev, | ||
struct wdt_timeout_cfg *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.
const
should be added here, see these comments.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
{ | ||
nrfx_err_t err_code; | ||
ARG_UNUSED(dev); | ||
|
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.
You should also check cfg->options
here and return -ENOTSUP
for settings other than WDT_FLAG_RESET_SOC
.
include/watchdog.h
Outdated
int (*wdt_api_setup)(struct device *dev, u8_t options); | ||
int (*wdt_api_disable)(struct device *dev); | ||
int (*wdt_api_install_timeout)(struct device *dev, struct wdt_timeout_cfg *cfg); | ||
int (*wdt_api_feed)(struct device *dev, int ch_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.
ch_id
is a bit cryptic, why not name it channel_id
?
And perhaps we could use u8_t
for this parameter. I don't think there will be watchdogs with more than 256 channels.
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.
If we return an int in install_timeout
, then this should also be an int. This would also give the driver the option to check if the value is negative in the event that install_timeout
failed and the application didn't check.
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.
int is better idea in each of these places because of handling error values.
include/watchdog.h
Outdated
wdt_api_get_config get_config; | ||
wdt_api_set_config set_config; | ||
wdt_api_reload reload; | ||
int (*wdt_api_setup)(struct device *dev, u8_t options); |
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.
Can we remove the wdt_api_
prefix from the member names? The prefix is fine if you define typedefs for the function prototypes, but it's redundant to also use the prefix in the struct members. See spi.h for an example.
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.
That's good question. I'd like to keep it consistent in some way with other drivers.
If we use spi as an example then I will prepare typedef for each function and pass it to this structure. It seems to be more readable. Please let me know what do You think about it
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.
It looks good
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
return -ENOMEM; | ||
} | ||
|
||
cfg->handle = &m_ch[m_alloc_ch_num]; |
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.
Returning the index in install_timeout
is fine.
include/watchdog.h
Outdated
int (*wdt_api_setup)(struct device *dev, u8_t options); | ||
int (*wdt_api_disable)(struct device *dev); | ||
int (*wdt_api_install_timeout)(struct device *dev, struct wdt_timeout_cfg *cfg); | ||
int (*wdt_api_feed)(struct device *dev, int ch_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.
If we return an int in install_timeout
, then this should also be an int. This would also give the driver the option to check if the value is negative in the event that install_timeout
failed and the application didn't check.
include/watchdog.h
Outdated
}; | ||
|
||
/** Watchdog callback. */ | ||
typedef void (*wdt_callback_t)(struct device *dev, void *handle); |
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 @anangl, changes with installing new timeout will affect also callback typedef. My proposal is to change callback to:
void (*wdt_callback_t)(struct device *dev, int channel_id);
in case of handling more channels with the same 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.
@anangl of course int
here can be changed to u8_t
I provided some changes with API. I mean - now channel index should be passed to feed function to feed watchdog properly. Channel index is returning by install function. Now doc should be aligned to new behaviour. |
Thanks. I updated the mcux driver accordingly in #7166 |
580f58a
to
8514aac
Compare
recheck |
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
|
||
static struct device DEVICE_NAME_GET(wdt_nrf); | ||
|
||
/* There are eight reload registers (channels) in Nordic's WDT. */ |
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.
Number of channels is defined as NRF_WDT_CHANNEL_NUMBER. Although it is not likely that this number will change, it is risky to mention in the comment that it is eight.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
static struct device DEVICE_NAME_GET(wdt_nrf); | ||
|
||
/* There are eight reload registers (channels) in Nordic's WDT. */ | ||
static nrfx_wdt_channel_id m_ch[NRF_WDT_CHANNELS_NUMBER]; |
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.
Now that nrfx_wdt_channel_feed
is called with (nrfx_wdt_channel_id)channel_id
as the parameter, we should get rid of this to not create a mess.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
} | ||
|
||
m_allocated_channels++; | ||
return (m_allocated_channels - 1); |
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.
Perhaps it would be more readable to use a local variable channel_id
, initialize it to m_allocated_channels
and return its value here.
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
config.reload_value = m_timeout; | ||
|
||
err_code = nrfx_wdt_init(&config, wdt_event_handler); | ||
if (err_code == NRFX_ERROR_INVALID_STATE) { |
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.
err_code != NRFX_SUCCESS
will be safer.
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.
right
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
#define SYS_LOG_LEVEL CONFIG_SYS_LOG_WDT_LEVEL | ||
#include <logging/sys_log.h> | ||
|
||
#define NRF_WDT_CHANNELS_NUMBER 8 |
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.
NRF_WDT_CHANNEL_NUMBER
is defined in nrf_wdt.h
and it should be used instead of this.
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'll change it
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
#include <clock_control.h> | ||
#include <watchdog.h> | ||
|
||
#define SYS_LOG_DOMAIN "WDT NRF" |
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.
"wdt_nrfx_wdt"
But shouldn't we name this file just "wdt_nrfx.c" and then use "wdt_nrfx" here?
drivers/watchdog/wdt_nrfx_wdt.c
Outdated
|
||
#define NRF_WDT_CHANNELS_NUMBER 8 | ||
|
||
static struct device DEVICE_NAME_GET(wdt_nrf); |
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.
DEVICE_DECLARE(wdt_nrf);
@MaureenHelm I changed HAVE_WDT_MULTISTAGE to HAS in Kconfig. Everything else (globally)- no changes. |
recheck |
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.
API changes look good
@@ -18,3 +18,6 @@ config NRFX_SPIM | |||
|
|||
config NRFX_SPIS | |||
bool | |||
|
|||
config NRFX_WDT |
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.
The nrf changes should move to the nrf shim commit
@@ -0,0 +1,38 @@ | |||
--- |
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.
Add license/copyright header
New API enables setting watchdog timeout in the unit of microseconds. It is possible to configure watchdog timer behavior in CPU sleep state as well as when it is halted by the debugger. It supports watchdogs with multiple reload channels. Jira: ZEP-2564 Signed-off-by: Michał Kruszewski <[email protected]> Signed-off-by: Karol Lasończyk <[email protected]>
Commit introduces support for watchdog configuration for Nordic Semiconductor nRF SoCs in device tree. Signed-off-by: Karol Lasończyk <[email protected]>
Changes add a translation layer to make nrfx WDT driver works with Zephyr API. Signed-off-by: Karol Lasończyk <[email protected]>
New test checks watchdog API if the simpliest test cases work correctly. Each test contains description at the begining of the source file. This implementation replace old SoC-centric implementation. Signed-off-by: Karol Lasończyk <[email protected]>
@MaureenHelm @anangl Cleaned-up commits. Waiting for test results |
* @param dev Pointer to the device structure for the driver instance. | ||
* @param cfg Pointer to timeout configuration structure. | ||
* | ||
* @retval 0 If successful. |
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.
It looks like we forgot to update the documentation to inform the user that the function returns channel_id. This makes usage of this API confusing. It should probably be fixed for 1.12 release.
I prepared shim implementation for nrfx watchdog driver. For now it is rather in proof-of-concept state. Changes includes also hard rework of wdt test to meet new API. Test passes on pca10028, pca10040 and pca10056 dev kits.
Due to difficult nature of watchdog peripheral (for test purposes ofc), test should be restarted using pin reset or command:
nrfjprog -r
.Commit with new watchdog API was cherry-picked from: #1260