drivers: serial: nrfx_uarte: Use ENDTX_STOPTX short if possible

Use short which is available on some devices.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
This commit is contained in:
Krzysztof Chruściński 2024-06-21 11:50:54 +02:00 committed by Anas Nashif
parent b7b25fe09c
commit ffdf9a978d
2 changed files with 35 additions and 19 deletions

View file

@ -20,7 +20,7 @@ config UART_$(nrfx_uart_num)_ASYNC
config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT config UART_$(nrfx_uart_num)_ENHANCED_POLL_OUT
bool "Efficient poll out on port $(nrfx_uart_num)" bool "Efficient poll out on port $(nrfx_uart_num)"
depends on !SOC_SERIES_NRF54LX depends on !$(dt_nodelabel_has_prop,uart$(nrfx_uart_num),short-endtx-stoptx)
default y default y
depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) depends on HAS_HW_NRF_UARTE$(nrfx_uart_num)
depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC

View file

@ -39,9 +39,13 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
#error "No PPI or DPPI" #error "No PPI or DPPI"
#endif #endif
#define UARTE(idx) DT_NODELABEL(uart##idx)
#define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop)
#define UARTE_PROP(idx, prop) DT_PROP(UARTE(idx), prop)
/* Execute macro f(x) for all instances. */ /* Execute macro f(x) for all instances. */
#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code) \ #define UARTE_FOR_EACH_INSTANCE(f, sep, off_code, ...) \
NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, _) NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, __VA_ARGS__)
/* Determine if any instance is using interrupt driven API. */ /* Determine if any instance is using interrupt driven API. */
#define IS_INT_DRIVEN(unused, prefix, i, _) \ #define IS_INT_DRIVEN(unused, prefix, i, _) \
@ -85,6 +89,15 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL);
#define UARTE_ENHANCED_POLL_OUT 1 #define UARTE_ENHANCED_POLL_OUT 1
#endif #endif
#define INSTANCE_PROP(unused, prefix, i, prop) UARTE_PROP(prefix##i, prop)
#define INSTANCE_PRESENT(unused, prefix, i, prop) 1
/* Driver supports case when all or none instances support that HW feature. */
#if (UARTE_FOR_EACH_INSTANCE(INSTANCE_PROP, (+), (0), endtx_stoptx_supported)) == \
(UARTE_FOR_EACH_INSTANCE(INSTANCE_PRESENT, (+), (0), endtx_stoptx_supported))
#define UARTE_HAS_ENDTX_STOPTX_SHORT 1
#endif
/* /*
* RX timeout is divided into time slabs, this define tells how many divisions * RX timeout is divided into time slabs, this define tells how many divisions
* should be made. More divisions - higher timeout accuracy and processor usage. * should be made. More divisions - higher timeout accuracy and processor usage.
@ -269,7 +282,8 @@ static void uarte_nrfx_isr_int(const void *arg)
/* If interrupt driven and asynchronous APIs are disabled then UART /* If interrupt driven and asynchronous APIs are disabled then UART
* interrupt is still called to stop TX. Unless it is done using PPI. * interrupt is still called to stop TX. Unless it is done using PPI.
*/ */
if (nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK) && if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) &&
nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK) &&
nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) { nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) {
endtx_isr(dev); endtx_isr(dev);
} }
@ -455,7 +469,8 @@ static bool is_tx_ready(const struct device *dev)
{ {
const struct uarte_nrfx_config *config = dev->config; const struct uarte_nrfx_config *config = dev->config;
NRF_UARTE_Type *uarte = get_uarte_instance(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev);
bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX; bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX ||
IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT);
return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) || return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) ||
(!ppi_endtx ? (!ppi_endtx ?
@ -1450,14 +1465,14 @@ static void uarte_nrfx_isr_async(const void *arg)
rxto_isr(dev); rxto_isr(dev);
} }
if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) &&
&& nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK)) { (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) &&
nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK))) {
endtx_isr(dev); endtx_isr(dev);
} }
if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) &&
&& nrf_uarte_int_enable_check(uarte, nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_TXSTOPPED_MASK)) {
NRF_UARTE_INT_TXSTOPPED_MASK)) {
txstopped_isr(dev); txstopped_isr(dev);
} }
} }
@ -1739,6 +1754,7 @@ static const struct uart_driver_api uart_nrfx_uarte_driver_api = {
#endif /* UARTE_INTERRUPT_DRIVEN */ #endif /* UARTE_INTERRUPT_DRIVEN */
}; };
#ifdef UARTE_ENHANCED_POLL_OUT
static int endtx_stoptx_ppi_init(NRF_UARTE_Type *uarte, static int endtx_stoptx_ppi_init(NRF_UARTE_Type *uarte,
struct uarte_nrfx_data *data) struct uarte_nrfx_data *data)
{ {
@ -1757,6 +1773,7 @@ static int endtx_stoptx_ppi_init(NRF_UARTE_Type *uarte,
return 0; return 0;
} }
#endif /* UARTE_ENHANCED_POLL_OUT */
static int uarte_instance_init(const struct device *dev, static int uarte_instance_init(const struct device *dev,
uint8_t interrupts_active) uint8_t interrupts_active)
@ -1790,14 +1807,16 @@ static int uarte_instance_init(const struct device *dev,
nrf_uarte_configure(uarte, &cfg->hw_config); nrf_uarte_configure(uarte, &cfg->hw_config);
#endif #endif
if (IS_ENABLED(UARTE_ENHANCED_POLL_OUT) && #ifdef UARTE_HAS_ENDTX_STOPTX_SHORT
cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX) { nrf_uarte_shorts_enable(uarte, NRF_UARTE_SHORT_ENDTX_STOPTX);
#elif defined(UARTE_ENHANCED_POLL_OUT)
if (cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX) {
err = endtx_stoptx_ppi_init(uarte, data); err = endtx_stoptx_ppi_init(uarte, data);
if (err < 0) { if (err < 0) {
return err; return err;
} }
} }
#endif
#ifdef UARTE_ANY_ASYNC #ifdef UARTE_ANY_ASYNC
if (data->async) { if (data->async) {
@ -1819,7 +1838,7 @@ static int uarte_instance_init(const struct device *dev,
} }
} }
if (!(cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX)) { if (!IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT) && !(cfg->flags & UARTE_CFG_FLAG_PPI_ENDTX)) {
nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK);
} }
@ -1850,7 +1869,8 @@ static int uarte_instance_init(const struct device *dev,
static void wait_for_tx_stopped(const struct device *dev) static void wait_for_tx_stopped(const struct device *dev)
{ {
const struct uarte_nrfx_config *config = dev->config; const struct uarte_nrfx_config *config = dev->config;
bool ppi_endtx = config->flags & UARTE_CFG_FLAG_PPI_ENDTX; bool ppi_endtx = (config->flags & UARTE_CFG_FLAG_PPI_ENDTX) ||
IS_ENABLED(UARTE_HAS_ENDTX_STOPTX_SHORT);
NRF_UARTE_Type *uarte = get_uarte_instance(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev);
bool res; bool res;
@ -1982,10 +2002,6 @@ static int uarte_nrfx_pm_action(const struct device *dev,
} }
#endif /* CONFIG_PM_DEVICE */ #endif /* CONFIG_PM_DEVICE */
#define UARTE(idx) DT_NODELABEL(uart##idx)
#define UARTE_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(UARTE(idx), prop)
#define UARTE_PROP(idx, prop) DT_PROP(UARTE(idx), prop)
#define UARTE_IRQ_CONFIGURE(idx, isr_handler) \ #define UARTE_IRQ_CONFIGURE(idx, isr_handler) \
do { \ do { \
IRQ_CONNECT(DT_IRQN(UARTE(idx)), DT_IRQ(UARTE(idx), priority), \ IRQ_CONNECT(DT_IRQN(UARTE(idx)), DT_IRQ(UARTE(idx), priority), \