Skip to content

Commit

Permalink
[nrf fromtree] drivers: watchdog: nrfx: add synchronization after stop
Browse files Browse the repository at this point in the history
In order to ensure that watchdog channels are freed in proper
driver state, synchronization in form of simple loop needs
to be added after stopping. In no irq variant, it is already done
on nrfx level. NRFY function can be replaced by NRFX one in
the future.

Signed-off-by: Michał Stasiak <[email protected]>
(cherry picked from commit b578ffa49a13f58288e44af5f44a11a3f44b3d00)
  • Loading branch information
mstasiaknordic committed Jan 17, 2025
1 parent 5f2a1de commit 6279270
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions drivers/watchdog/wdt_nrfx.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/kernel.h>
#include <zephyr/sys/math_extras.h>
#include <nrfx_wdt.h>
#include <zephyr/drivers/watchdog.h>
Expand All @@ -13,11 +14,18 @@
#include <zephyr/irq.h>
LOG_MODULE_REGISTER(wdt_nrfx);

#if !CONFIG_WDT_NRFX_NO_IRQ && NRF_WDT_HAS_STOP
#define WDT_NRFX_SYNC_STOP 1
#endif

struct wdt_nrfx_data {
wdt_callback_t m_callbacks[NRF_WDT_CHANNEL_NUMBER];
uint32_t m_timeout;
uint8_t m_allocated_channels;
bool enabled;
#if defined(WDT_NRFX_SYNC_STOP)
struct k_sem sync_stop;
#endif
};

struct wdt_nrfx_config {
Expand Down Expand Up @@ -73,6 +81,10 @@ static int wdt_nrf_disable(const struct device *dev)
return -EFAULT;
}

#if defined(WDT_NRFX_SYNC_STOP)
k_sem_take(&data->sync_stop, K_FOREVER);
#endif

nrfx_wdt_channels_free(&config->wdt);

for (channel_id = 0; channel_id < data->m_allocated_channels; channel_id++) {
Expand Down Expand Up @@ -170,11 +182,17 @@ static const struct wdt_driver_api wdt_nrfx_driver_api = {
static void wdt_event_handler(const struct device *dev, nrf_wdt_event_t event_type,
uint32_t requests, void *p_context)
{
struct wdt_nrfx_data *data = dev->data;

#if defined(WDT_NRFX_SYNC_STOP)
if (event_type == NRF_WDT_EVENT_STOPPED) {
k_sem_give(&data->sync_stop);
}
#else
(void)event_type;
#endif
(void)p_context;

struct wdt_nrfx_data *data = dev->data;

while (requests) {
uint8_t i = u32_count_trailing_zeros(requests);

Expand Down Expand Up @@ -217,7 +235,11 @@ static void wdt_event_handler(const struct device *dev, nrf_wdt_event_t event_ty
} \
return 0; \
} \
static struct wdt_nrfx_data wdt_##idx##_data; \
static struct wdt_nrfx_data wdt_##idx##_data = { \
IF_ENABLED(WDT_NRFX_SYNC_STOP, \
(.sync_stop = Z_SEM_INITIALIZER( \
wdt_##idx##_data.sync_stop, 0, 1),)) \
}; \
static const struct wdt_nrfx_config wdt_##idx##z_config = { \
.wdt = NRFX_WDT_INSTANCE(idx), \
}; \
Expand Down

0 comments on commit 6279270

Please sign in to comment.