Skip to content

Commit

Permalink
drivers: serial: nrfx_uarte2: Fix re-enabling the receiver
Browse files Browse the repository at this point in the history
Move providing of the first buffer in uart_rx_enable from that
function to the callback which is called from nrfx_uarte_rx_enable
context. By doing this nrfx_uarte_rx_buffer_set is called when
RX configuration flags are already known to the driver.

Signed-off-by: Krzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
  • Loading branch information
nordic-krch authored and carlescufi committed Apr 5, 2024
1 parent 490fb20 commit 7bededb
Showing 1 changed file with 33 additions and 9 deletions.
42 changes: 33 additions & 9 deletions drivers/serial/uart_nrfx_uarte2.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ struct uarte_async_data {
uart_callback_t user_callback;
void *user_data;

uint8_t *en_rx_buf;
size_t en_rx_len;

struct k_timer tx_timer;
struct k_timer rx_timer;

Expand Down Expand Up @@ -288,6 +291,22 @@ static void on_rx_buf_req(const struct device *dev)
struct uarte_async_data *adata = data->async;
const nrfx_uarte_t *nrfx_dev = get_nrfx_dev(dev);

/* If buffer is not null it indicates that event comes from RX enabling
* function context. We need to pass provided buffer to the driver.
*/
if (adata->en_rx_buf) {
uint8_t *buf = adata->en_rx_buf;
size_t len = adata->en_rx_len;
nrfx_err_t err;

adata->en_rx_buf = NULL;
adata->en_rx_len = 0;

err = nrfx_uarte_rx_buffer_set(nrfx_dev, buf, len);
__ASSERT_NO_MSG(err == NRFX_SUCCESS);
return;
}

struct uart_event evt = {
.type = UART_RX_BUF_REQUEST
};
Expand All @@ -296,8 +315,6 @@ static void on_rx_buf_req(const struct device *dev)
* reception of one buffer was terminated to restart another transfer.
*/
if (!K_TIMEOUT_EQ(adata->rx_timeout, K_NO_WAIT)) {
/* Read and clear any pending new data information. */
nrfx_uarte_rx_new_data_check(nrfx_dev);
nrfx_uarte_rxdrdy_enable(nrfx_dev);
}
data->async->user_callback(dev, &evt, data->async->user_data);
Expand Down Expand Up @@ -469,22 +486,28 @@ static int api_rx_enable(const struct device *dev, uint8_t *buf, size_t len, int
if (timeout != SYS_FOREVER_US) {
adata->idle_cnt = RX_TIMEOUT_DIV + 1;
adata->rx_timeout = K_USEC(timeout / RX_TIMEOUT_DIV);
nrfx_uarte_rxdrdy_enable(nrfx_dev);
} else {
adata->rx_timeout = K_NO_WAIT;
}

err = nrfx_uarte_rx_buffer_set(nrfx_dev, buf, len);
if (err != NRFX_SUCCESS) {
return -EIO;
}
/* Store the buffer. It will be passed to the driver in the event handler.
* We do that instead of calling nrfx_uarte_rx_buffer_set here to ensure
* that nrfx_uarte_rx_buffer_set is called when RX enable configuration
* flags are already known to the driver (e.g. if flushed data shall be
* kept or not).
*/
adata->en_rx_buf = buf;
adata->en_rx_len = len;

atomic_or(&data->flags, UARTE_DATA_FLAG_RX_ENABLED);

err = nrfx_uarte_rx_enable(nrfx_dev, flags);
if (err != NRFX_SUCCESS) {
atomic_and(&data->flags, ~UARTE_DATA_FLAG_RX_ENABLED);
return (err == NRFX_ERROR_BUSY) ? -EBUSY : -EIO;
}

atomic_or(&data->flags, UARTE_DATA_FLAG_RX_ENABLED);

return 0;
}

Expand Down Expand Up @@ -932,7 +955,8 @@ static int uarte_nrfx_pm_action(const struct device *dev,
UARTE_MEMORY_SECTION(idx) __aligned(4); \
static nrfx_uarte_rx_cache_t uarte##idx##_rx_cache_scratch; \
IF_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN, \
(static uint8_t a2i_rx_buf##idx[CONFIG_UART_##idx##_A2I_RX_SIZE];)) \
(static uint8_t a2i_rx_buf##idx[CONFIG_UART_##idx##_A2I_RX_SIZE] \
UARTE_MEMORY_SECTION(idx) __aligned(4);)) \
PINCTRL_DT_DEFINE(UARTE(idx)); \
static const struct uart_async_to_irq_config uarte_a2i_config_##idx = \
UART_ASYNC_TO_IRQ_API_CONFIG_INITIALIZER(&a2i_api, \
Expand Down

0 comments on commit 7bededb

Please sign in to comment.