Skip to content

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

Merged
merged 4 commits into from
May 14, 2018

Conversation

kl-cruz
Copy link
Collaborator

@kl-cruz kl-cruz commented Apr 10, 2018

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

@carlescufi carlescufi requested a review from tbursztyka April 10, 2018 13:05
@carlescufi carlescufi changed the title [RFC][DNM] Shim for nrfx wdt driver [RFC][DNM] Watchdog API redesign and shim for nrfx wdt driver Apr 10, 2018
@codecov-io
Copy link

codecov-io commented Apr 10, 2018

Codecov Report

Merging #7007 into master will increase coverage by 3.27%.
The diff coverage is n/a.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
tests/net/neighbor/src/main.c 52.9% <0%> (-34.28%) ⬇️
tests/kernel/workq/work_queue_api/src/main.c 66.66% <0%> (-32.72%) ⬇️
tests/kernel/tickless/tickless_concept/src/main.c 66.66% <0%> (-30.84%) ⬇️
tests/kernel/critical/src/main.c 66.66% <0%> (-29.34%) ⬇️
tests/net/ipv6/src/main.c 64.34% <0%> (-29.28%) ⬇️
...sts/kernel/mem_pool/mem_pool_threadsafe/src/main.c 66.66% <0%> (-28.99%) ⬇️
subsys/net/lib/http/http.c 0% <0%> (-27.36%) ⬇️
subsys/net/lib/app/server.c 25.25% <0%> (-27.28%) ⬇️
tests/kernel/irq_offload/src/main.c 66.66% <0%> (-25%) ⬇️
subsys/net/lib/app/net_app.c 20.47% <0%> (-22.69%) ⬇️
... and 147 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 03f9f66...bacbb38. Read the comment docs.

Copy link
Contributor

@dbkinder dbkinder left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks OK

@kl-cruz kl-cruz force-pushed the nrfx_shim_wdt branch 2 times, most recently from 1aa13d1 to 009ba88 Compare April 11, 2018 06:35
@kl-cruz
Copy link
Collaborator Author

kl-cruz commented Apr 11, 2018

Reworked comments in test and text in shim-related commit message. Fixed code issue found by failing test.

Copy link
Collaborator

@tbursztyka tbursztyka left a 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.

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
Copy link
Collaborator

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

Copy link
Collaborator Author

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

Copy link
Collaborator Author

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)

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);
Copy link
Collaborator

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.

Copy link
Collaborator Author

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

Copy link
Collaborator Author

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

}

IRQ_CONNECT(CONFIG_WDT_NRF_IRQ,
CONFIG_WDT_NRF_IRQ_PRI, wdt_nrf_isr,
Copy link
Collaborator

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)

{
ARG_UNUSED(dev);

nrfx_err_t err_code = nrfx_wdt_channel_alloc(&m_ch[m_ch_id]);
Copy link
Collaborator

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()

@galak galak added the platform: nRF Nordic nRFx label Apr 12, 2018
@kl-cruz
Copy link
Collaborator Author

kl-cruz commented Apr 17, 2018

Splitted shim to shim and dts commits

@galak galak mentioned this pull request Apr 17, 2018
33 tasks
@carlescufi carlescufi requested a review from MaureenHelm April 17, 2018 16:12
{
ARG_UNUSED(dev);
/* Deprecated function. No implementation needed. */
SYS_LOG_ERR("Function not implemented!");
Copy link
Member

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?

@@ -30,4 +57,6 @@ source "drivers/watchdog/Kconfig.esp32"

source "drivers/watchdog/Kconfig.sam0"

source "drivers/watchdog/Kconfig.nrf"
Copy link
Member

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.

int "Reload value in [ms]"
depends on WDT_NRF
default 2000
range 1 130150524
Copy link
Member

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?


struct wdt_nrf_dev_data {
void (*cb)(struct device *dev, void *handle);
};
Copy link
Member

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.

@kl-cruz kl-cruz force-pushed the nrfx_shim_wdt branch 2 times, most recently from 2e14558 to 03680c9 Compare April 20, 2018 13:33

config WDT_NRF_DEVICE_NAME
string "Device name for Watchdog (WDT)"
depends on WDT_NRFX
Copy link
Member

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).

{
/* Started watchdog cannot be stopped on nRF devices. */
ARG_UNUSED(dev);
return 0;
Copy link
Member

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.

* 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)) {
Copy link
Member

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.

Copy link
Collaborator Author

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

* The m_alloc_ch_num variable stores number of currently allocated
* and activated watchdog channels.
*/
static u32_t m_alloc_ch_num;
Copy link
Member

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?

Copy link
Collaborator Author

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.

/* 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];
Copy link
Member

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".

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be changed

return 0;
}

static void wdt_nrf_enable(struct device *dev)
Copy link
Member

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.

return -ENOMEM;
}

cfg->handle = &m_ch[m_alloc_ch_num];
Copy link
Member

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.

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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

Copy link
Member

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.

nrfx_err_t err_code;

/* Set default value according to default value in MCU. */
config.behaviour = NRF_WDT_BEHAVIOUR_RUN_SLEEP;
Copy link
Member

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?

Copy link
Collaborator Author

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

Copy link
Collaborator Author

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.

* window differs from windows for alarms installed so far.
*/
static inline int wdt_install_timeout(struct device *dev,
struct wdt_timeout_cfg *cfg)
Copy link
Member

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.

{
nrfx_err_t err_code;
ARG_UNUSED(dev);

Copy link
Member

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.

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);
Copy link
Member

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.

Copy link
Member

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.

Copy link
Collaborator Author

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.

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);
Copy link
Member

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.

Copy link
Collaborator Author

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks good

return -ENOMEM;
}

cfg->handle = &m_ch[m_alloc_ch_num];
Copy link
Member

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.

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);
Copy link
Member

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.

};

/** Watchdog callback. */
typedef void (*wdt_callback_t)(struct device *dev, void *handle);
Copy link
Collaborator Author

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

Copy link
Collaborator Author

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

@kl-cruz
Copy link
Collaborator Author

kl-cruz commented Apr 25, 2018

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.

@MaureenHelm
Copy link
Member

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

@kl-cruz kl-cruz force-pushed the nrfx_shim_wdt branch 3 times, most recently from 580f58a to 8514aac Compare April 26, 2018 06:41
@anangl
Copy link
Member

anangl commented May 8, 2018

recheck

@kl-cruz kl-cruz requested a review from carlescufi as a code owner May 8, 2018 11:27

static struct device DEVICE_NAME_GET(wdt_nrf);

/* There are eight reload registers (channels) in Nordic's WDT. */
Copy link
Member

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.

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];
Copy link
Member

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.

}

m_allocated_channels++;
return (m_allocated_channels - 1);
Copy link
Member

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.

config.reload_value = m_timeout;

err_code = nrfx_wdt_init(&config, wdt_event_handler);
if (err_code == NRFX_ERROR_INVALID_STATE) {
Copy link
Member

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right

#define SYS_LOG_LEVEL CONFIG_SYS_LOG_WDT_LEVEL
#include <logging/sys_log.h>

#define NRF_WDT_CHANNELS_NUMBER 8
Copy link
Member

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change it

#include <clock_control.h>
#include <watchdog.h>

#define SYS_LOG_DOMAIN "WDT NRF"
Copy link
Member

@anangl anangl May 8, 2018

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?


#define NRF_WDT_CHANNELS_NUMBER 8

static struct device DEVICE_NAME_GET(wdt_nrf);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DEVICE_DECLARE(wdt_nrf);

@kl-cruz
Copy link
Collaborator Author

kl-cruz commented May 11, 2018

@MaureenHelm I changed HAVE_WDT_MULTISTAGE to HAS in Kconfig. Everything else (globally)- no changes.
@anangl Introduce changes to nordic implementation.
I removed labels DNM, RFC from pull request name.

@kl-cruz kl-cruz changed the title [RFC][DNM] Watchdog API redesign and shim for nrfx wdt driver drivers: wdt: Watchdog API redesign and shim for nrfx wdt driver May 11, 2018
@anangl
Copy link
Member

anangl commented May 11, 2018

recheck

Copy link
Member

@MaureenHelm MaureenHelm left a 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
Copy link
Member

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 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add license/copyright header

Michał Kruszewski and others added 4 commits May 14, 2018 08:51
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]>
@kl-cruz
Copy link
Collaborator Author

kl-cruz commented May 14, 2018

@MaureenHelm @anangl Cleaned-up commits. Waiting for test results

@MaureenHelm MaureenHelm merged commit c989809 into zephyrproject-rtos:master May 14, 2018
* @param dev Pointer to the device structure for the driver instance.
* @param cfg Pointer to timeout configuration structure.
*
* @retval 0 If successful.
Copy link
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
platform: nRF Nordic nRFx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants