Commit 7bededbc authored by Krzysztof Chruściński's avatar Krzysztof Chruściński Committed by Carles Cufi
Browse files

drivers: serial: nrfx_uarte2: Fix re-enabling the receiver



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: default avatarKrzysztof Chruściński <krzysztof.chruscinski@nordicsemi.no>
parent 490fb201
Loading
Loading
Loading
Loading
+33 −9
Original line number Diff line number Diff line
@@ -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;

@@ -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
	};
@@ -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);
@@ -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;
}

@@ -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,				\