Skip to content

Commit

Permalink
serial: allow callback setting to be exclusive
Browse files Browse the repository at this point in the history
Both the IRQ API and Asynchronous API support callback.
However, since they are both interrupt driven, having
callbacks on both API would interfere with each other
in almost all cases. So this adds a kconfig to signal
that the callbacks should be exclusive to each other.
In other words, if one is set, the other should not
be active. Drivers implementing both APIs have been
updated to remove the callbacks from the other API.
Though, this still leaves the option to disable
the kconfig and allows both APIs to have callbacks
if one desires.

Fixes zephyrproject-rtos#48606

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
  • Loading branch information
dcpleung authored and fabiobaltieri committed Jul 18, 2023
1 parent bbbc28a commit 9f02eea
Show file tree
Hide file tree
Showing 10 changed files with 106 additions and 0 deletions.
9 changes: 9 additions & 0 deletions doc/hardware/peripherals/uart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ The Asynchronous API allows to read and write data in the background using DMA
without interrupting the MCU at all. However, the setup is more complex
than the other methods.

.. warning::

Interrupt-driven API and the Asynchronous API should NOT be used at
the same time, since both APIs require hardware interrupts to function
properly, using the callbacks for both APIs would result in interference
between each other. :kconfig:option:`CONFIG_UART_EXCLUSIVE_API_CALLBACKS`
is enabled by default so that only the callbacks associated with one API
is active at a time.


Configuration Options
*********************
Expand Down
15 changes: 15 additions & 0 deletions drivers/serial/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ config UART_INTERRUPT_DRIVEN
This option enables interrupt support for UART allowing console
input and other UART based drivers.

config UART_EXCLUSIVE_API_CALLBACKS
bool "Use exclusive callbacks for multiple APIs"
depends on UART_ASYNC_API && UART_INTERRUPT_DRIVEN
default y
help
When multiple set of APIs support callbacks, enabling this
option will result in only the callbacks of one set of API
being active at a time. Setting a new callback to one set of
API will remove callbacks to other set of APIs. For example,
calling uart_callback_set() would disable the callback
previously set via uart_irq_callback_set().

Says yes unless you are absolutely sure you know what you are
doing and promise not to file bug when things do not work out.

config UART_LINE_CTRL
bool "Serial Line Control API"
help
Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_esp32.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,11 @@ static void uart_esp32_irq_callback_set(const struct device *dev, uart_irq_callb

data->irq_cb = cb;
data->irq_cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async.cb = NULL;
data->async.user_data = NULL;
#endif
}

#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Expand Down Expand Up @@ -662,6 +667,11 @@ static int uart_esp32_async_callback_set(const struct device *dev, uart_callback
data->async.cb = callback;
data->async.user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->irq_cb = NULL;
data->irq_cb_data = NULL;
#endif

return 0;
}

Expand Down
11 changes: 11 additions & 0 deletions drivers/serial/uart_mcux_flexcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,11 @@ static void mcux_flexcomm_irq_callback_set(const struct device *dev,

data->irq_callback = cb;
data->irq_cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async_callback = NULL;
data->async_cb_data = NULL;
#endif
}
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */

Expand Down Expand Up @@ -400,6 +405,12 @@ static int mcux_flexcomm_uart_callback_set(const struct device *dev,
data->async_callback = callback;
data->async_cb_data = user_data;


#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->irq_callback = NULL;
data->irq_cb_data = NULL;
#endif

return 0;
}

Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_mcux_lpuart.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,11 @@ static void mcux_lpuart_irq_callback_set(const struct device *dev,

data->callback = cb;
data->cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async.user_callback = NULL;
data->async.user_data = NULL;
#endif
}

#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Expand Down Expand Up @@ -661,6 +666,11 @@ static int mcux_lpuart_callback_set(const struct device *dev, uart_callback_t ca
data->async.user_callback = callback;
data->async.user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->callback = NULL;
data->cb_data = NULL;
#endif

return 0;
}

Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_nrfx_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,11 @@ static int uart_nrfx_callback_set(const struct device *dev,
uart0_cb.callback = callback;
uart0_cb.user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
irq_callback = NULL;
irq_cb_data = NULL;
#endif

return 0;
}

Expand Down Expand Up @@ -923,6 +928,11 @@ static void uart_nrfx_irq_callback_set(const struct device *dev,
(void)dev;
irq_callback = cb;
irq_cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
uart0_cb.callback = NULL;
uart0_cb.user_data = NULL;
#endif
}

/**
Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_nrfx_uarte.c
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,11 @@ static int uarte_nrfx_callback_set(const struct device *dev,
data->async->user_callback = callback;
data->async->user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->int_driven->cb = NULL;
data->int_driven->cb_data = NULL;
#endif

return 0;
}

Expand Down Expand Up @@ -1675,6 +1680,11 @@ static void uarte_nrfx_irq_callback_set(const struct device *dev,

data->int_driven->cb = cb;
data->int_driven->cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async->user_callback = NULL;
data->async->user_data = NULL;
#endif
}
#endif /* UARTE_INTERRUPT_DRIVEN */

Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_sam0.c
Original file line number Diff line number Diff line change
Expand Up @@ -935,6 +935,11 @@ static void uart_sam0_irq_callback_set(const struct device *dev,

dev_data->cb = cb;
dev_data->cb_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
dev_data->async_cb = NULL;
dev_data->async_cb_data = NULL;
#endif
}
#endif

Expand All @@ -949,6 +954,11 @@ static int uart_sam0_callback_set(const struct device *dev,
dev_data->async_cb = callback;
dev_data->async_cb_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
dev_data->cb = NULL;
dev_data->cb_data = NULL;
#endif

return 0;
}

Expand Down
10 changes: 10 additions & 0 deletions drivers/serial/uart_stm32.c
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,11 @@ static void uart_stm32_irq_callback_set(const struct device *dev,

data->user_cb = cb;
data->user_data = cb_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async_cb = NULL;
data->async_user_data = NULL;
#endif
}

#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
Expand Down Expand Up @@ -1125,6 +1130,11 @@ static int uart_stm32_async_callback_set(const struct device *dev,
data->async_cb = callback;
data->async_user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->user_cb = NULL;
data->user_data = NULL;
#endif

return 0;
}

Expand Down
11 changes: 11 additions & 0 deletions drivers/serial/uart_xmc4xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,11 @@ static void uart_xmc4xxx_irq_callback_set(const struct device *dev,

data->user_cb = cb;
data->user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->async_cb = NULL;
data->async_user_data = NULL;
#endif
}

#define NVIC_ISPR_BASE 0xe000e200u
Expand Down Expand Up @@ -599,6 +604,12 @@ static int uart_xmc4xxx_async_callback_set(const struct device *dev, uart_callba

data->async_cb = callback;
data->async_user_data = user_data;

#if defined(CONFIG_UART_EXCLUSIVE_API_CALLBACKS)
data->user_cb = NULL;
data->user_data = NULL;
#endif

return 0;
}

Expand Down

0 comments on commit 9f02eea

Please sign in to comment.