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

drivers: serial: Use microseconds to represent timeout



Updated uart_rx_enable() and uart_tx() to use timeout given
in microseconds. Previously argument was given in milliseconds.
However, there are cases when milliseconds granularity is not
enough and can significantly reduce a throughput, e.g. 1ms is
100 bytes at 1Mb.

Updated 4 drivers which implement asynchronous API. Updated
places where API was used.

Signed-off-by: default avatarKrzysztof Chruscinski <krzysztof.chruscinski@nordicsemi.no>
parent cc69ca1a
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -448,7 +448,7 @@ static int uart_nrfx_tx_abort(const struct device *dev)
		return -EINVAL;
	}
#if	HW_FLOW_CONTROL_AVAILABLE
	if (uart0_cb.tx_timeout != SYS_FOREVER_MS) {
	if (uart0_cb.tx_timeout != SYS_FOREVER_US) {
		k_timer_stop(&uart0_cb.tx_timeout_timer);
	}
#endif
@@ -527,7 +527,7 @@ static int uart_nrfx_rx_disable(const struct device *dev)
	}

	uart0_cb.rx_enabled = 0;
	if (uart0_cb.rx_timeout != SYS_FOREVER_MS) {
	if (uart0_cb.rx_timeout != SYS_FOREVER_US) {
		k_timer_stop(&uart0_cb.rx_timeout_timer);
	}
	nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPRX);
@@ -599,15 +599,15 @@ static void rx_isr(const struct device *dev)
		uart0_cb.rx_counter++;
		if (uart0_cb.rx_timeout == 0) {
			rx_rdy_evt(dev);
		} else if (uart0_cb.rx_timeout != SYS_FOREVER_MS) {
		} else if (uart0_cb.rx_timeout != SYS_FOREVER_US) {
			k_timer_start(&uart0_cb.rx_timeout_timer,
				      K_MSEC(uart0_cb.rx_timeout),
				      K_USEC(uart0_cb.rx_timeout),
				      K_NO_WAIT);
		}
	}

	if (uart0_cb.rx_buffer_length == uart0_cb.rx_counter) {
		if (uart0_cb.rx_timeout != SYS_FOREVER_MS) {
		if (uart0_cb.rx_timeout != SYS_FOREVER_US) {
			k_timer_stop(&uart0_cb.rx_timeout_timer);
		}
		rx_rdy_evt(dev);
@@ -643,9 +643,9 @@ static void tx_isr(const struct device *dev)
	if (uart0_cb.tx_counter < uart0_cb.tx_buffer_length &&
	    !uart0_cb.tx_abort) {
#if	HW_FLOW_CONTROL_AVAILABLE
		if (uart0_cb.tx_timeout != SYS_FOREVER_MS) {
		if (uart0_cb.tx_timeout != SYS_FOREVER_US) {
			k_timer_start(&uart0_cb.tx_timeout_timer,
				      K_MSEC(uart0_cb.tx_timeout),
				      K_USEC(uart0_cb.tx_timeout),
				      K_NO_WAIT);
		}
#endif
@@ -657,7 +657,7 @@ static void tx_isr(const struct device *dev)
	} else {
#if	HW_FLOW_CONTROL_AVAILABLE

		if (uart0_cb.tx_timeout != SYS_FOREVER_MS) {
		if (uart0_cb.tx_timeout != SYS_FOREVER_US) {
			k_timer_stop(&uart0_cb.tx_timeout_timer);
		}
#endif
@@ -686,7 +686,7 @@ static void tx_isr(const struct device *dev)

static void error_isr(const struct device *dev)
{
	if (uart0_cb.rx_timeout != SYS_FOREVER_MS) {
	if (uart0_cb.rx_timeout != SYS_FOREVER_US) {
		k_timer_stop(&uart0_cb.rx_timeout_timer);
	}
	nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_ERROR);
@@ -766,7 +766,7 @@ static void tx_timeout(struct k_timer *timer)
{
	struct uart_event evt;

	if (uart0_cb.tx_timeout != SYS_FOREVER_MS) {
	if (uart0_cb.tx_timeout != SYS_FOREVER_US) {
		k_timer_stop(&uart0_cb.tx_timeout_timer);
	}
	nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPTX);
+14 −8
Original line number Diff line number Diff line
@@ -725,8 +725,8 @@ static int uarte_nrfx_tx(const struct device *dev, const uint8_t *buf,
	irq_unlock(key);

	if (data->uart_config.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS
	    && timeout != SYS_FOREVER_MS) {
		k_timer_start(&data->async->tx_timeout_timer, K_MSEC(timeout),
	    && timeout != SYS_FOREVER_US) {
		k_timer_start(&data->async->tx_timeout_timer, K_USEC(timeout),
			      K_NO_WAIT);
	}
	return 0;
@@ -806,9 +806,15 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf,
	}

	data->async->rx_timeout = timeout;
	/* Set minimum interval to 3 RTC ticks. 3 is used due to RTC limitation
	 * which cannot set timeout for next tick. Assuming delay in processing
	 * 3 instead of 2 is used. Note that lower value would work in a similar
	 * way but timeouts would always occur later than expected,  most likely
	 * after ~3 ticks.
	 */
	data->async->rx_timeout_slab =
		MAX(timeout / RX_TIMEOUT_DIV,
		    NRFX_CEIL_DIV(1000, CONFIG_SYS_CLOCK_TICKS_PER_SEC));
		    NRFX_CEIL_DIV(3 * 1000000, CONFIG_SYS_CLOCK_TICKS_PER_SEC));

	data->async->rx_buf = buf;
	data->async->rx_buf_len = len;
@@ -926,7 +932,7 @@ static void tx_timeout(struct k_timer *timer)

/**
 * Whole timeout is divided by RX_TIMEOUT_DIV into smaller units, rx_timeout
 * is executed periodically every rx_timeout_slab ms. If between executions
 * is executed periodically every rx_timeout_slab us. If between executions
 * data was received, then we start counting down time from start, if not, then
 * we subtract rx_timeout_slab from rx_timeout_left.
 * If rx_timeout_left is less than rx_timeout_slab it means that receiving has
@@ -996,7 +1002,7 @@ static void rx_timeout(struct k_timer *timer)
		if (clipped ||
			(data->async->rx_timeout_left
				< data->async->rx_timeout_slab)) {
			/* rx_timeout ms elapsed since last receiving */
			/* rx_timeout us elapsed since last receiving */
			notify_uart_rx_rdy(dev, len);
			data->async->rx_offset += len;
			data->async->rx_total_user_byte_cnt += len;
@@ -1044,11 +1050,11 @@ static void rxstarted_isr(const struct device *dev)
		.type = UART_RX_BUF_REQUEST,
	};
	user_callback(dev, &evt);
	if (data->async->rx_timeout != SYS_FOREVER_MS) {
	if (data->async->rx_timeout != SYS_FOREVER_US) {
		data->async->rx_timeout_left = data->async->rx_timeout;
		k_timer_start(&data->async->rx_timeout_timer,
			      K_MSEC(data->async->rx_timeout_slab),
			      K_MSEC(data->async->rx_timeout_slab));
			      K_USEC(data->async->rx_timeout_slab),
			      K_USEC(data->async->rx_timeout_slab));
	}
}

+7 −7
Original line number Diff line number Diff line
@@ -283,7 +283,7 @@ static void uart_sam0_dma_rx_done(const struct device *dma_dev, void *arg,
	 * reception.  This also catches the case of DMA completion during
	 * timeout handling.
	 */
	if (dev_data->rx_timeout_time != SYS_FOREVER_MS) {
	if (dev_data->rx_timeout_time != SYS_FOREVER_US) {
		dev_data->rx_waiting_for_irq = true;
		regs->INTENSET.reg = SERCOM_USART_INTENSET_RXC;
		irq_unlock(key);
@@ -356,7 +356,7 @@ static void uart_sam0_rx_timeout(struct k_work *work)
	if (dev_data->rx_timeout_from_isr) {
		dev_data->rx_timeout_from_isr = false;
		k_work_reschedule(&dev_data->rx_timeout_work,
				      K_MSEC(dev_data->rx_timeout_chunk));
				      K_USEC(dev_data->rx_timeout_chunk));
		irq_unlock(key);
		return;
	}
@@ -378,7 +378,7 @@ static void uart_sam0_rx_timeout(struct k_work *work)
				      dev_data->rx_timeout_chunk);

		k_work_reschedule(&dev_data->rx_timeout_work,
				      K_MSEC(remaining));
				      K_USEC(remaining));
	}

	irq_unlock(key);
@@ -755,11 +755,11 @@ static void uart_sam0_isr(const struct device *dev)
		 * If we have a timeout, restart the time remaining whenever
		 * we see data.
		 */
		if (dev_data->rx_timeout_time != SYS_FOREVER_MS) {
		if (dev_data->rx_timeout_time != SYS_FOREVER_US) {
			dev_data->rx_timeout_from_isr = true;
			dev_data->rx_timeout_start = k_uptime_get_32();
			k_work_reschedule(&dev_data->rx_timeout_work,
					      K_MSEC(dev_data->rx_timeout_chunk));
					      K_USEC(dev_data->rx_timeout_chunk));
		}

		/* DMA will read the currently ready byte out */
@@ -945,9 +945,9 @@ static int uart_sam0_tx(const struct device *dev, const uint8_t *buf,
		return retval;
	}

	if (timeout != SYS_FOREVER_MS) {
	if (timeout != SYS_FOREVER_US) {
		k_work_reschedule(&dev_data->tx_timeout_work,
				      K_MSEC(timeout));
				      K_USEC(timeout));
	}

	return dma_start(cfg->dma_dev, cfg->tx_dma_channel);
+3 −3
Original line number Diff line number Diff line
@@ -808,10 +808,10 @@ static inline void async_evt_rx_buf_release(struct uart_stm32_data *data)
static inline void async_timer_start(struct k_work_delayable *work,
				     int32_t timeout)
{
	if ((timeout != SYS_FOREVER_MS) && (timeout != 0)) {
	if ((timeout != SYS_FOREVER_US) && (timeout != 0)) {
		/* start timer */
		LOG_DBG("async timer started for %d ms", timeout);
		k_work_reschedule(work, K_MSEC(timeout));
		LOG_DBG("async timer started for %d us", timeout);
		k_work_reschedule(work, K_USEC(timeout));
	}
}

+3 −3
Original line number Diff line number Diff line
@@ -486,8 +486,8 @@ static inline int uart_callback_set(const struct device *dev,
 * @param dev     UART device structure.
 * @param buf     Pointer to transmit buffer.
 * @param len     Length of transmit buffer.
 * @param timeout Timeout in milliseconds. Valid only if flow control is
 *		  enabled. @ref SYS_FOREVER_MS disables timeout.
 * @param timeout Timeout in microseconds. Valid only if flow control is
 *		  enabled. @ref SYS_FOREVER_US disables timeout.
 *
 * @retval -ENOTSUP If not supported.
 * @retval -EBUSY   There is already an ongoing transfer.
@@ -550,7 +550,7 @@ static inline int z_impl_uart_tx_abort(const struct device *dev)
 * @param len     Buffer length.
 * @param timeout Inactivity period after receiving at least a byte which
 *		  triggers  @ref uart_event_type::UART_RX_RDY event. Given in
 *		  milliseconds. @ref SYS_FOREVER_MS disables timeout. See
 *		  microseconds. @ref SYS_FOREVER_US disables timeout. See
 *		  @ref uart_event_type for details.
 *
 * @retval -ENOTSUP If not supported.
Loading