Skip to content

Commit

Permalink
drivers: serial: nrfx_uarte: Support for low power polling mode
Browse files Browse the repository at this point in the history
Add support for getting to the lowest power mode when polling is
used with property and interrupts are not used for
that UARTE. So far disabling of the UARTE peripheral was done in
the interrupt but in some cases interrupt may not be available
and in that case uart_poll_out shall wait until byte is transferred
and put UARTE into the lowest power state.

Signed-off-by: Krzysztof Chruściński <[email protected]>
  • Loading branch information
nordic-krch committed Feb 10, 2025
1 parent aba960c commit bb820d6
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 7 deletions.
6 changes: 6 additions & 0 deletions drivers/serial/Kconfig.nrfx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ config UART_NRFX_UARTE
imply NRFX_UARTE_CONFIG_SKIP_PSEL_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM
imply NRFX_UARTE_CONFIG_SKIP_GPIO_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM

config UART_NRFX_UARTE_NO_IRQ
bool "Polling without interrupt"
depends on UART_NRFX_UARTE
depends on !UART_ASYNC_API && !UART_INTERRUPT_DRIVEN
default y

config UART_NRFX_UARTE_LEGACY_SHIM
bool "Legacy UARTE shim"
depends on UART_NRFX_UARTE
Expand Down
44 changes: 37 additions & 7 deletions drivers/serial/uart_nrfx_uarte.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ static inline NRF_UARTE_Type *get_uarte_instance(const struct device *dev)
return config->uarte_regs;
}

#if !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ)

static void endtx_isr(const struct device *dev)
{
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
Expand All @@ -369,6 +371,8 @@ static void endtx_isr(const struct device *dev)

}

#endif

/** @brief Disable UARTE peripheral is not used by RX or TX.
*
* It must be called with interrupts locked so that deciding if no direction is
Expand Down Expand Up @@ -407,7 +411,7 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask)
nrf_uarte_disable(get_uarte_instance(dev));
}

#ifdef UARTE_ANY_NONE_ASYNC
#if defined(UARTE_ANY_NONE_ASYNC) && !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ)
/**
* @brief Interrupt service routine.
*
Expand Down Expand Up @@ -484,7 +488,7 @@ static void uarte_nrfx_isr_int(const void *arg)
}
#endif /* UARTE_INTERRUPT_DRIVEN */
}
#endif /* UARTE_ANY_NONE_ASYNC */
#endif /* UARTE_ANY_NONE_ASYNC && !CONFIG_UART_NRFX_UARTE_NO_IRQ */

#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
/**
Expand Down Expand Up @@ -1927,14 +1931,37 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c)
}
}

if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(config)) {
if (!IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ) &&
(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(config))) {
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK);
}

*config->poll_out_byte = c;
tx_start(dev, config->poll_out_byte, 1);

irq_unlock(key);

if (IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
key = wait_tx_ready(dev);
if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) &&
!(config->flags & UARTE_CFG_FLAG_PPI_ENDTX)) {
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX);
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED);
while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED)) {
}
}

if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
if (!(data->flags & UARTE_FLAG_POLL_OUT)) {
data->flags &= ~UARTE_FLAG_POLL_OUT;
pm_device_runtime_put(dev);
}
} else if (LOW_POWER_ENABLED(config)) {
uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_TX);
}
irq_unlock(key);
}

}

Check notice on line 1965 in drivers/serial/uart_nrfx_uarte.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

You may want to run clang-format on this change

drivers/serial/uart_nrfx_uarte.c:1965 -


Expand Down Expand Up @@ -2202,7 +2229,7 @@ static void wait_for_tx_stopped(const struct device *dev)
NRFX_WAIT_FOR(nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED),
1000, 1, res);

if (!ppi_endtx) {
if (!ppi_endtx && !IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
}
}
Expand Down Expand Up @@ -2347,7 +2374,9 @@ static int uarte_tx_path_init(const struct device *dev)
}
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX);
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX);
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
if (!IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
}
}
while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED)) {
}
Expand Down Expand Up @@ -2525,9 +2554,10 @@ static int uarte_instance_init(const struct device *dev,
}; \
static int uarte_##idx##_init(const struct device *dev) \
{ \
COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \
COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \
(COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_async);), \
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_int);)) \
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_int);)))) \
return uarte_instance_init( \
dev, \
IS_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN)); \
Expand Down

0 comments on commit bb820d6

Please sign in to comment.