Skip to content

Commit bb820d6

Browse files
committed
drivers: serial: nrfx_uarte: Support for low power polling mode
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]>
1 parent aba960c commit bb820d6

File tree

2 files changed

+43
-7
lines changed

2 files changed

+43
-7
lines changed

drivers/serial/Kconfig.nrfx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ config UART_NRFX_UARTE
2828
imply NRFX_UARTE_CONFIG_SKIP_PSEL_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM
2929
imply NRFX_UARTE_CONFIG_SKIP_GPIO_CONFIG if !UART_NRFX_UARTE_LEGACY_SHIM
3030

31+
config UART_NRFX_UARTE_NO_IRQ
32+
bool "Polling without interrupt"
33+
depends on UART_NRFX_UARTE
34+
depends on !UART_ASYNC_API && !UART_INTERRUPT_DRIVEN
35+
default y
36+
3137
config UART_NRFX_UARTE_LEGACY_SHIM
3238
bool "Legacy UARTE shim"
3339
depends on UART_NRFX_UARTE

drivers/serial/uart_nrfx_uarte.c

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ static inline NRF_UARTE_Type *get_uarte_instance(const struct device *dev)
354354
return config->uarte_regs;
355355
}
356356

357+
#if !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ)
358+
357359
static void endtx_isr(const struct device *dev)
358360
{
359361
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
@@ -369,6 +371,8 @@ static void endtx_isr(const struct device *dev)
369371

370372
}
371373

374+
#endif
375+
372376
/** @brief Disable UARTE peripheral is not used by RX or TX.
373377
*
374378
* It must be called with interrupts locked so that deciding if no direction is
@@ -407,7 +411,7 @@ static void uarte_disable_locked(const struct device *dev, uint32_t dis_mask)
407411
nrf_uarte_disable(get_uarte_instance(dev));
408412
}
409413

410-
#ifdef UARTE_ANY_NONE_ASYNC
414+
#if defined(UARTE_ANY_NONE_ASYNC) && !defined(CONFIG_UART_NRFX_UARTE_NO_IRQ)
411415
/**
412416
* @brief Interrupt service routine.
413417
*
@@ -484,7 +488,7 @@ static void uarte_nrfx_isr_int(const void *arg)
484488
}
485489
#endif /* UARTE_INTERRUPT_DRIVEN */
486490
}
487-
#endif /* UARTE_ANY_NONE_ASYNC */
491+
#endif /* UARTE_ANY_NONE_ASYNC && !CONFIG_UART_NRFX_UARTE_NO_IRQ */
488492

489493
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
490494
/**
@@ -1927,14 +1931,37 @@ static void uarte_nrfx_poll_out(const struct device *dev, unsigned char c)
19271931
}
19281932
}
19291933

1930-
if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(config)) {
1934+
if (!IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ) &&
1935+
(IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME) || LOW_POWER_ENABLED(config))) {
19311936
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK);
19321937
}
19331938

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

19371942
irq_unlock(key);
1943+
1944+
if (IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
1945+
key = wait_tx_ready(dev);
1946+
if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) &&
1947+
!(config->flags & UARTE_CFG_FLAG_PPI_ENDTX)) {
1948+
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX);
1949+
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED);
1950+
while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED)) {
1951+
}
1952+
}
1953+
1954+
if (IS_ENABLED(CONFIG_PM_DEVICE_RUNTIME)) {
1955+
if (!(data->flags & UARTE_FLAG_POLL_OUT)) {
1956+
data->flags &= ~UARTE_FLAG_POLL_OUT;
1957+
pm_device_runtime_put(dev);
1958+
}
1959+
} else if (LOW_POWER_ENABLED(config)) {
1960+
uarte_disable_locked(dev, UARTE_FLAG_LOW_POWER_TX);
1961+
}
1962+
irq_unlock(key);
1963+
}
1964+
19381965
}
19391966

19401967

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

2205-
if (!ppi_endtx) {
2232+
if (!ppi_endtx && !IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
22062233
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
22072234
}
22082235
}
@@ -2347,7 +2374,9 @@ static int uarte_tx_path_init(const struct device *dev)
23472374
}
23482375
nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX);
23492376
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX);
2350-
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
2377+
if (!IS_ENABLED(CONFIG_UART_NRFX_UARTE_NO_IRQ)) {
2378+
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
2379+
}
23512380
}
23522381
while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED)) {
23532382
}
@@ -2525,9 +2554,10 @@ static int uarte_instance_init(const struct device *dev,
25252554
}; \
25262555
static int uarte_##idx##_init(const struct device *dev) \
25272556
{ \
2528-
COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \
2557+
COND_CODE_1(CONFIG_UART_NRFX_UARTE_NO_IRQ, (), \
2558+
(COND_CODE_1(CONFIG_UART_##idx##_ASYNC, \
25292559
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_async);), \
2530-
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_int);)) \
2560+
(UARTE_IRQ_CONFIGURE(idx, uarte_nrfx_isr_int);)))) \
25312561
return uarte_instance_init( \
25322562
dev, \
25332563
IS_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN)); \

0 commit comments

Comments
 (0)