diff --git a/doc/hardware/peripherals/uart.rst b/doc/hardware/peripherals/uart.rst index b190dcbeea0..42906bca6fa 100644 --- a/doc/hardware/peripherals/uart.rst +++ b/doc/hardware/peripherals/uart.rst @@ -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 ********************* diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 405fda7d074..a803c152919 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -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 diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index 380226dcfe6..a1054ba7d85 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -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 */ @@ -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; } diff --git a/drivers/serial/uart_mcux_flexcomm.c b/drivers/serial/uart_mcux_flexcomm.c index 041f690317d..4332b20cb91 100644 --- a/drivers/serial/uart_mcux_flexcomm.c +++ b/drivers/serial/uart_mcux_flexcomm.c @@ -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 */ @@ -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; } diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index cdafa42d585..e1fe23ea322 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -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 */ @@ -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; } diff --git a/drivers/serial/uart_nrfx_uart.c b/drivers/serial/uart_nrfx_uart.c index 77efdd0050a..96cb190a487 100644 --- a/drivers/serial/uart_nrfx_uart.c +++ b/drivers/serial/uart_nrfx_uart.c @@ -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; } @@ -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 } /** diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index 047405b84c0..16877328e5f 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -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; } @@ -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 */ diff --git a/drivers/serial/uart_sam0.c b/drivers/serial/uart_sam0.c index 82676b4f85b..4f4407bdca9 100644 --- a/drivers/serial/uart_sam0.c +++ b/drivers/serial/uart_sam0.c @@ -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 @@ -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; } diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 45a16e9e893..23be4a9138c 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -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 */ @@ -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; } diff --git a/drivers/serial/uart_xmc4xxx.c b/drivers/serial/uart_xmc4xxx.c index 278e7bcfb10..40e33b9fa45 100644 --- a/drivers/serial/uart_xmc4xxx.c +++ b/drivers/serial/uart_xmc4xxx.c @@ -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 @@ -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; }