drivers: nrf: Fix forever timeout handling in UART async API.
Current implementation directly passes timeout value to workqueue/timer which results in assertion or instant timeout in case when K_FOREVER is passed. This fix ensures that no timer or workqueue is called with K_FOREVER. Signed-off-by: Mieszko Mierunski <mieszko.mierunski@nordicsemi.no>
This commit is contained in:
parent
dc3c906d12
commit
20444869e3
2 changed files with 34 additions and 17 deletions
|
@ -49,7 +49,7 @@ static struct {
|
||||||
size_t rx_secondary_buffer_length;
|
size_t rx_secondary_buffer_length;
|
||||||
volatile size_t rx_counter;
|
volatile size_t rx_counter;
|
||||||
volatile size_t rx_offset;
|
volatile size_t rx_offset;
|
||||||
size_t rx_timeout;
|
s32_t rx_timeout;
|
||||||
struct k_delayed_work rx_timeout_work;
|
struct k_delayed_work rx_timeout_work;
|
||||||
bool rx_enabled;
|
bool rx_enabled;
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static struct {
|
||||||
volatile size_t tx_counter;
|
volatile size_t tx_counter;
|
||||||
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
||||||
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
||||||
size_t tx_timeout;
|
s32_t tx_timeout;
|
||||||
struct k_delayed_work tx_timeout_work;
|
struct k_delayed_work tx_timeout_work;
|
||||||
#endif
|
#endif
|
||||||
} uart0_cb;
|
} uart0_cb;
|
||||||
|
@ -353,7 +353,7 @@ static int uart_nrfx_callback_set(struct device *dev, uart_callback_t callback,
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_nrfx_tx(struct device *dev, const u8_t *buf, size_t len,
|
static int uart_nrfx_tx(struct device *dev, const u8_t *buf, size_t len,
|
||||||
u32_t timeout)
|
s32_t timeout)
|
||||||
{
|
{
|
||||||
if (uart0_cb.tx_buffer_length != 0) {
|
if (uart0_cb.tx_buffer_length != 0) {
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -384,7 +384,9 @@ static int uart_nrfx_tx_abort(struct device *dev)
|
||||||
}
|
}
|
||||||
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
||||||
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
||||||
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
if (uart0_cb.tx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPTX);
|
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPTX);
|
||||||
|
|
||||||
|
@ -403,7 +405,7 @@ static int uart_nrfx_tx_abort(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uart_nrfx_rx_enable(struct device *dev, u8_t *buf, size_t len,
|
static int uart_nrfx_rx_enable(struct device *dev, u8_t *buf, size_t len,
|
||||||
u32_t timeout)
|
s32_t timeout)
|
||||||
{
|
{
|
||||||
if (uart0_cb.rx_buffer_length != 0) {
|
if (uart0_cb.rx_buffer_length != 0) {
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
@ -447,7 +449,9 @@ static int uart_nrfx_rx_disable(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
uart0_cb.rx_enabled = 0;
|
uart0_cb.rx_enabled = 0;
|
||||||
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
if (uart0_cb.rx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
||||||
|
}
|
||||||
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPRX);
|
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPRX);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -524,7 +528,9 @@ static void rx_isr(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uart0_cb.rx_buffer_length == uart0_cb.rx_counter) {
|
if (uart0_cb.rx_buffer_length == uart0_cb.rx_counter) {
|
||||||
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
if (uart0_cb.rx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
||||||
|
}
|
||||||
rx_rdy_evt();
|
rx_rdy_evt();
|
||||||
|
|
||||||
if (uart0_cb.rx_secondary_buffer_length) {
|
if (uart0_cb.rx_secondary_buffer_length) {
|
||||||
|
@ -552,8 +558,10 @@ static void tx_isr(void)
|
||||||
!uart0_cb.tx_abort) {
|
!uart0_cb.tx_abort) {
|
||||||
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
||||||
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
||||||
k_delayed_work_submit(&uart0_cb.tx_timeout_work,
|
if (uart0_cb.tx_timeout != K_FOREVER) {
|
||||||
uart0_cb.tx_timeout);
|
k_delayed_work_submit(&uart0_cb.tx_timeout_work,
|
||||||
|
uart0_cb.tx_timeout);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_TXDRDY);
|
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_TXDRDY);
|
||||||
|
|
||||||
|
@ -563,7 +571,10 @@ static void tx_isr(void)
|
||||||
} else {
|
} else {
|
||||||
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
||||||
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
||||||
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
|
||||||
|
if (uart0_cb.tx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_TXDRDY);
|
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_TXDRDY);
|
||||||
uart0_cb.tx_buffer_length = 0;
|
uart0_cb.tx_buffer_length = 0;
|
||||||
|
@ -586,7 +597,9 @@ static void tx_isr(void)
|
||||||
|
|
||||||
static void error_isr(struct device *dev)
|
static void error_isr(struct device *dev)
|
||||||
{
|
{
|
||||||
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
if (uart0_cb.rx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.rx_timeout_work);
|
||||||
|
}
|
||||||
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_ERROR);
|
nrf_uart_event_clear(uart0_addr, NRF_UART_EVENT_ERROR);
|
||||||
|
|
||||||
if (!uart0_cb.rx_enabled) {
|
if (!uart0_cb.rx_enabled) {
|
||||||
|
@ -653,13 +666,16 @@ static void rx_timeout(struct k_work *work)
|
||||||
{
|
{
|
||||||
rx_rdy_evt();
|
rx_rdy_evt();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
#if defined(DT_NORDIC_NRF_UART_UART_0_RTS_PIN) && \
|
||||||
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
defined(DT_NORDIC_NRF_UART_UART_0_CTS_PIN)
|
||||||
static void tx_timeout(struct k_work *work)
|
static void tx_timeout(struct k_work *work)
|
||||||
{
|
{
|
||||||
struct uart_event evt;
|
struct uart_event evt;
|
||||||
|
|
||||||
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
if (uart0_cb.tx_timeout != K_FOREVER) {
|
||||||
|
k_delayed_work_cancel(&uart0_cb.tx_timeout_work);
|
||||||
|
}
|
||||||
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPTX);
|
nrf_uart_task_trigger(uart0_addr, NRF_UART_TASK_STOPTX);
|
||||||
evt.type = UART_TX_ABORTED;
|
evt.type = UART_TX_ABORTED;
|
||||||
evt.data.tx.buf = uart0_cb.tx_buffer;
|
evt.data.tx.buf = uart0_cb.tx_buffer;
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct uarte_async_cb {
|
||||||
u8_t *rx_next_buf;
|
u8_t *rx_next_buf;
|
||||||
u32_t rx_total_byte_cnt; /* Total number of bytes received */
|
u32_t rx_total_byte_cnt; /* Total number of bytes received */
|
||||||
u32_t rx_total_user_byte_cnt; /* Total number of bytes passed to user */
|
u32_t rx_total_user_byte_cnt; /* Total number of bytes passed to user */
|
||||||
u32_t rx_timeout; /* Timeout set by user */
|
s32_t rx_timeout; /* Timeout set by user */
|
||||||
s32_t rx_timeout_slab; /* rx_timeout divided by RX_TIMEOUT_DIV */
|
s32_t rx_timeout_slab; /* rx_timeout divided by RX_TIMEOUT_DIV */
|
||||||
s32_t rx_timeout_left; /* Current time left until user callback */
|
s32_t rx_timeout_left; /* Current time left until user callback */
|
||||||
struct k_timer rx_timeout_timer;
|
struct k_timer rx_timeout_timer;
|
||||||
|
@ -470,7 +470,7 @@ static int uarte_nrfx_init(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uarte_nrfx_tx(struct device *dev, const u8_t *buf, size_t len,
|
static int uarte_nrfx_tx(struct device *dev, const u8_t *buf, size_t len,
|
||||||
u32_t timeout)
|
s32_t timeout)
|
||||||
{
|
{
|
||||||
struct uarte_nrfx_data *data = get_dev_data(dev);
|
struct uarte_nrfx_data *data = get_dev_data(dev);
|
||||||
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
|
NRF_UARTE_Type *uarte = get_uarte_instance(dev);
|
||||||
|
@ -486,7 +486,8 @@ static int uarte_nrfx_tx(struct device *dev, const u8_t *buf, size_t len,
|
||||||
data->async->tx_size = len;
|
data->async->tx_size = len;
|
||||||
nrf_uarte_tx_buffer_set(uarte, buf, len);
|
nrf_uarte_tx_buffer_set(uarte, buf, len);
|
||||||
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX);
|
nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX);
|
||||||
if (data->uart_config.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS) {
|
if (data->uart_config.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS
|
||||||
|
&& timeout != K_FOREVER) {
|
||||||
k_timer_start(&data->async->tx_timeout_timer, timeout,
|
k_timer_start(&data->async->tx_timeout_timer, timeout,
|
||||||
K_NO_WAIT);
|
K_NO_WAIT);
|
||||||
}
|
}
|
||||||
|
@ -508,7 +509,7 @@ static int uarte_nrfx_tx_abort(struct device *dev)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uarte_nrfx_rx_enable(struct device *dev, u8_t *buf, size_t len,
|
static int uarte_nrfx_rx_enable(struct device *dev, u8_t *buf, size_t len,
|
||||||
u32_t timeout)
|
s32_t timeout)
|
||||||
{
|
{
|
||||||
struct uarte_nrfx_data *data = get_dev_data(dev);
|
struct uarte_nrfx_data *data = get_dev_data(dev);
|
||||||
const struct uarte_nrfx_config *cfg = get_dev_config(dev);
|
const struct uarte_nrfx_config *cfg = get_dev_config(dev);
|
||||||
|
@ -690,7 +691,7 @@ static void rxstarted_isr(struct device *dev)
|
||||||
.type = UART_RX_BUF_REQUEST,
|
.type = UART_RX_BUF_REQUEST,
|
||||||
};
|
};
|
||||||
user_callback(dev, &evt);
|
user_callback(dev, &evt);
|
||||||
if (data->async->rx_timeout) {
|
if (data->async->rx_timeout != K_FOREVER) {
|
||||||
data->async->rx_timeout_left = data->async->rx_timeout;
|
data->async->rx_timeout_left = data->async->rx_timeout;
|
||||||
k_timer_start(&data->async->rx_timeout_timer,
|
k_timer_start(&data->async->rx_timeout_timer,
|
||||||
data->async->rx_timeout_slab,
|
data->async->rx_timeout_slab,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue