Skip to content

Commit 4e15d3b

Browse files
rakonsnordicjm
authored andcommitted
uart_async_adapter: Provide UART Async Adapter
This commit moves UART Async Adapter as separate subsystem. JIRA: NCSDK-26505 Signed-off-by: Radoslaw Koppel <radoslaw.koppel@nordicsemi.no> Signed-off-by: Pekka Niskanen <pekka.niskanen@nordicsemi.no>
1 parent b5447ff commit 4e15d3b

File tree

16 files changed

+173
-46
lines changed

16 files changed

+173
-46
lines changed

CODEOWNERS

+1
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ Kconfig* @tejlmand
268268
/subsys/shell/ @nordic-krch
269269
/subsys/nrf_security/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky
270270
/subsys/trusted_storage/ @frkv @Vge0rge @vili-nordic @SebastianBoe @mswarowsky
271+
/subsys/uart_async_adapter/ @rakons
271272
/subsys/net_core_monitor/ @maje-emb
272273
/subsys/zigbee/ @milewr
273274
/tests/ @PerMac @katgiadla
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
.. _lib_uart_async_adapter:
2+
3+
UART async adapter
4+
##################
5+
6+
.. contents::
7+
:local:
8+
:depth: 2
9+
10+
UART async adapter library works as an interface between interrupt-driven API of a UART device and software that is using the asynchronous API interface.
11+
12+
.. note::
13+
The current implementation is :ref:`experimental <software_maturity>`.
14+
15+
Overview
16+
********
17+
18+
Zephyr provides the following three different ways to access a UART peripheral:
19+
20+
* Pooling API
21+
* Interrupt-driven API
22+
* Asynchronous API
23+
24+
While most of the UART drivers provide all three APIs, some drivers still do not provide the asynchronous UART API.
25+
An example of such a driver is USB CDC ACM.
26+
The UART async adapter library is initialized with a UART device and communicates with it using the interrupt-driven API, providing an asynchronous API for the application.
27+
28+
This removes the need to implement two ways of interfacing with UART devices in software.
29+
When using the UART async adapter library, the software only needs to implement interaction with a UART device using the asynchronous API and just initialize the adapter for the ones that do not support it.
30+
31+
Requirements
32+
************
33+
34+
To use the library, you need to enable the :kconfig:option:`CONFIG_UART_ASYNC_API` and :kconfig:option:`CONFIG_UART_INTERRUPT_DRIVEN` Kconfig options.
35+
36+
Configuration
37+
*************
38+
39+
Use the :kconfig:option:`CONFIG_UART_ASYNC_ADAPTER` Kconfig option to enable the library in the build system.
40+
41+
Usage
42+
*****
43+
44+
See the following code snippet to learn how to use this library:
45+
46+
.. code-block:: c
47+
48+
#include <uart_async_adapter.h>
49+
50+
...
51+
/* Get the UART device we want to use */
52+
static const struct device *uart = DEVICE_DT_GET([UART node identifier]);
53+
54+
/* Create UART async adapter instance */
55+
UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
56+
57+
/* UART initialization (called before any UART usage) */
58+
static int uart_init(void)
59+
{
60+
if (!uart_test_async_api(uart)) {
61+
/* Implement API adapter */
62+
uart_async_adapter_init(async_adapter, uart);
63+
uart = async_adapter;
64+
}
65+
/* Continue initialization using asynchronous API on uart device */
66+
(...)
67+
}
68+
69+
.. note::
70+
When using the library in the way shown in the code snippet, it is totally transparent to the application.
71+
72+
If the selected UART device provides the asynchronous API, the adapter is not initialized.
73+
If the selected UART device does not provide the asynchronous API, the adapter is initialized to use such a device and a direct pointer to the device is replaced by the adapter.
74+
75+
Samples using the library
76+
*************************
77+
78+
The following |NCS| sample use this library:
79+
80+
* :ref:`peripheral_uart`
81+
82+
Limitations
83+
***********
84+
85+
Using this library adds code and performance overhead over direct usage of UART asynchronous API provided by the driver.
86+
For UART drivers that only provide the interrupt-driven API, consider using it directly in the application.
87+
The library allows using UART devices with different APIs with only one API in the application, speeding up the development process.
88+
89+
Dependencies
90+
************
91+
92+
This module may use :ref:`zephyr:logging_api`.
93+
94+
API documentation
95+
*****************
96+
97+
| Header file: :file:`include/uart_async_adapter.h`
98+
| Source files: :file:`subsys/uart_async_adapter/`
99+
100+
.. doxygengroup:: uart_async_adapter
101+
:project: nrf
102+
:members:

doc/nrf/releases_and_maturity/releases/release-notes-changelog.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ Security libraries
362362
Other libraries
363363
---------------
364364

365-
|no_changes_yet_note|
365+
* Added the :ref:`lib_uart_async_adapter` library.
366366

367367
Common Application Framework (CAF)
368368
----------------------------------

samples/bluetooth/peripheral_uart/src/uart_async_adapter.h include/uart_async_adapter.h

+23-13
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,31 @@
33
*
44
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
55
*/
6+
#ifndef __UART_ASYNC_ADAPTER_H
7+
#define __UART_ASYNC_ADAPTER_H
68

79
/** @file
810
* @brief UART asynchronous API adapter
911
*/
12+
#include <zephyr/device.h>
13+
#include <zephyr/drivers/uart.h>
14+
#include <zephyr/kernel.h>
15+
16+
#ifdef __cplusplus
17+
extern "C" {
18+
#endif
1019

1120
/**
12-
* @brief UART asynchronous API universal adapter
13-
* @defgroup uart_async_adapter UART ASYNC adapter
21+
* @defgroup uart_async_adapter UART async adapter
1422
* @{
23+
* @brief UART asynchronous API universal adapter
1524
*
1625
* This module acts as an adapter between UART interrupt and async interface.
1726
*
18-
* @note The UART ASYNC API adapter implementation is experimental.
27+
* @note The UART async API adapter implementation is experimental.
1928
* It means it is not guaranteed to work in any corner situation.
2029
*/
2130

22-
#include <zephyr/device.h>
23-
#include <zephyr/drivers/uart.h>
24-
#include <zephyr/kernel.h>
25-
26-
2731
/**
2832
* @brief UART asynch adapter data structure
2933
*
@@ -42,7 +46,7 @@ struct uart_async_adapter_data {
4246
struct k_spinlock lock;
4347

4448
/** Data used for output transmission */
45-
struct {
49+
struct uart_async_adapter_data_rx {
4650
/** The original buffer pointer set when data transfer was requested */
4751
const uint8_t *buf;
4852
/** Current buffer position */
@@ -56,7 +60,7 @@ struct uart_async_adapter_data {
5660
} tx;
5761

5862
/** Data used for input transmission */
59-
struct {
63+
struct uart_async_adapter_data_tx {
6064
/** Base buffer pointer used now for data reception */
6165
uint8_t *buf;
6266
/** Current position to write data into */
@@ -79,7 +83,7 @@ struct uart_async_adapter_data {
7983
};
8084

8185
/**
82-
* @brief Driver API for ASYNC adapter
86+
* @brief Driver API for async adapter
8387
*
8488
* The API of the UART async adapter uses standard UART API structure.
8589
*/
@@ -88,7 +92,7 @@ extern const struct uart_driver_api uart_async_adapter_driver_api;
8892
/**
8993
* @brief The name of the data instance connected with created device instance
9094
*
91-
* @name _dev_name The name of the created device instance
95+
* @param _dev_name The name of the created device instance
9296
*/
9397
#define UART_ASYNC_ADAPTER_INST_DATA_NAME(_dev_name) _CONCAT(uart_async_adapter_data_, _dev_name)
9498

@@ -99,7 +103,7 @@ extern const struct uart_driver_api uart_async_adapter_driver_api;
99103
/**
100104
* @brief The macro that creates and instance of the UART async adapter
101105
*
102-
* @name _dev The name of the created device instance
106+
* @param _dev The name of the created device instance
103107
*/
104108
#define UART_ASYNC_ADAPTER_INST_DEFINE(_dev) \
105109
static struct uart_async_adapter_data UART_ASYNC_ADAPTER_INST_DATA_NAME(_dev); \
@@ -124,3 +128,9 @@ extern const struct uart_driver_api uart_async_adapter_driver_api;
124128
void uart_async_adapter_init(const struct device *dev, const struct device *target);
125129

126130
/** @} */
131+
132+
#ifdef __cplusplus
133+
}
134+
#endif
135+
136+
#endif /* __UART_ASYNC_ADAPTER_H */

samples/bluetooth/peripheral_uart/CMakeLists.txt

-5
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,6 @@ target_sources(app PRIVATE
1313
src/main.c
1414
)
1515

16-
# Include UART ASYNC API adapter
17-
target_sources_ifdef(CONFIG_BT_NUS_UART_ASYNC_ADAPTER app PRIVATE
18-
src/uart_async_adapter.c
19-
)
20-
2116
# NORDIC SDK APP END
2217

2318
zephyr_library_include_directories(.)

samples/bluetooth/peripheral_uart/Kconfig

-7
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,4 @@ config BT_NUS_UART_RX_WAIT_TIME
3333
help
3434
Wait for RX complete event time in microseconds
3535

36-
config BT_NUS_UART_ASYNC_ADAPTER
37-
bool "Enable UART async adapter"
38-
select SERIAL_SUPPORT_ASYNC
39-
help
40-
Enables asynchronous adapter for UART drives that supports only
41-
IRQ interface.
42-
4336
endmenu

samples/bluetooth/peripheral_uart/README.rst

+6-11
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,11 @@ See :ref:`peripheral_uart_sample_activating_variants` for details about how to b
9191
Async adapter experimental module
9292
---------------------------------
9393

94-
The default sample configuration uses the UART async API, which is an :ref:`experimental <software_maturity>` module.
95-
The UART async adapter creates and initializes an instance of the async module.
94+
The default sample configuration uses the UART async API.
95+
The sample uses the :ref:`lib_uart_async_adapter` library to communicate with the USB CDC ACM driver.
9696
This is needed because the USB CDC ACM implementation provides only the interrupt interface.
97-
The adapter uses data provided in the :c:struct:`uart_async_adapter_data` to connect to the UART device that does not use the asynchronous interface.
9897

99-
The module requires the :ref:`CONFIG_BT_NUS_UART_ASYNC_ADAPTER <CONFIG_BT_NUS_UART_ASYNC_ADAPTER>` to be set to ``y``.
100-
For more information about the adapter, see the :file:`uart_async_adapter` source files available in the :file:`peripheral_uart/src` directory.
98+
To use the library, set the :kconfig:option:`CONFIG_UART_ASYNC_ADAPTER` Kconfig option to ``y``.
10199

102100
MCUboot with serial recovery of the networking core image
103101
=========================================================
@@ -148,9 +146,9 @@ Configuration options
148146

149147
Check and configure the following configuration options for the sample:
150148

151-
.. _CONFIG_BT_NUS_UART_ASYNC_ADAPTER:
149+
.. _CONFIG_UART_ASYNC_ADAPTER:
152150

153-
CONFIG_BT_NUS_UART_ASYNC_ADAPTER - Enable UART async adapter
151+
CONFIG_UART_ASYNC_ADAPTER - Enable UART async adapter
154152
Enables asynchronous adapter for UART drives that supports only IRQ interface.
155153

156154
Building and running
@@ -210,12 +208,9 @@ After programming the sample to your development kit, complete the following ste
210208
Dependencies
211209
************
212210

213-
This sample uses the following sample-specific library:
214-
215-
* :file:`uart_async_adapter` at :file:`peripheral_uart/src`
216-
217211
This sample uses the following |NCS| libraries:
218212

213+
* :ref:`lib_uart_async_adapter`
219214
* :ref:`nus_service_readme`
220215
* :ref:`dk_buttons_and_leds_readme`
221216

samples/bluetooth/peripheral_uart/boards/thingy53_nrf5340_cpuapp.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y
2020
# Enable back logging over UART as this sample config uses only RTT by default
2121
CONFIG_LOG_BACKEND_UART=y
2222

23-
CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y
23+
CONFIG_UART_ASYNC_ADAPTER=y
2424
CONFIG_UART_INTERRUPT_DRIVEN=y
2525

2626
# Disable the UARTE0 enabled in default project configuration

samples/bluetooth/peripheral_uart/boards/thingy53_nrf5340_cpuapp_ns.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ CONFIG_USB_COMPOSITE_DEVICE=y
2020
# Enable back logging over UART as this sample config uses only RTT by default
2121
CONFIG_LOG_BACKEND_UART=y
2222

23-
CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y
23+
CONFIG_UART_ASYNC_ADAPTER=y
2424
CONFIG_UART_INTERRUPT_DRIVEN=y
2525

2626
# Disable the UARTE0 enabled in default project configuration

samples/bluetooth/peripheral_uart/prj_cdc.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
# Enable the UART driver
88
CONFIG_UART_LINE_CTRL=y
99
CONFIG_UART_INTERRUPT_DRIVEN=y
10-
CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y
10+
CONFIG_UART_ASYNC_ADAPTER=y
1111
CONFIG_USB_DEVICE_STACK=y
1212
CONFIG_USB_DEVICE_REMOTE_WAKEUP=n
1313
CONFIG_USB_CDC_ACM=y

samples/bluetooth/peripheral_uart/src/main.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
/** @file
88
* @brief Nordic UART Bridge Service (NUS) sample
99
*/
10-
#include "uart_async_adapter.h"
10+
#include <uart_async_adapter.h>
1111

1212
#include <zephyr/types.h>
1313
#include <zephyr/kernel.h>
@@ -81,10 +81,10 @@ static const struct bt_data sd[] = {
8181
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
8282
};
8383

84-
#if CONFIG_BT_NUS_UART_ASYNC_ADAPTER
84+
#ifdef CONFIG_UART_ASYNC_ADAPTER
8585
UART_ASYNC_ADAPTER_INST_DEFINE(async_adapter);
8686
#else
87-
static const struct device *const async_adapter;
87+
#define async_adapter NULL
8888
#endif
8989

9090
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
@@ -260,7 +260,7 @@ static int uart_init(void)
260260
k_work_init_delayable(&uart_work, uart_work_handler);
261261

262262

263-
if (IS_ENABLED(CONFIG_BT_NUS_UART_ASYNC_ADAPTER) && !uart_test_async_api(uart)) {
263+
if (IS_ENABLED(CONFIG_UART_ASYNC_ADAPTER) && !uart_test_async_api(uart)) {
264264
/* Implement API adapter */
265265
uart_async_adapter_init(async_adapter, uart);
266266
uart = async_adapter;

subsys/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@ add_subdirectory_ifdef(CONFIG_NRF_DM dm)
6868
add_subdirectory_ifdef(CONFIG_EMDS emds)
6969
add_subdirectory_ifdef(CONFIG_NET_CORE_MONITOR net_core_monitor)
7070
add_subdirectory_ifdef(CONFIG_AUDIO_MODULE audio_module)
71+
add_subdirectory_ifdef(CONFIG_UART_ASYNC_ADAPTER uart_async_adapter)

subsys/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,6 @@ rsource "dm/Kconfig"
3333
rsource "nrf_security/Kconfig"
3434
rsource "net_core_monitor/Kconfig"
3535
rsource "audio_module/Kconfig"
36+
rsource "uart_async_adapter/Kconfig"
3637
rsource "trusted_storage/Kconfig"
3738
endmenu
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
zephyr_sources(uart_async_adapter.c)

subsys/uart_async_adapter/Kconfig

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#
2+
# Copyright (c) 2024 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
menuconfig UART_ASYNC_ADAPTER
8+
bool "Enable UART async adapter [EXPERIMENTAL]"
9+
select EXPERIMENTAL
10+
select SERIAL_SUPPORT_ASYNC
11+
depends on SERIAL_SUPPORT_INTERRUPT
12+
help
13+
Enables asynchronous adapter for UART drives that supports only
14+
IRQ interface.
15+
16+
if UART_ASYNC_ADAPTER
17+
18+
module = UART_ASYNC_ADAPTER
19+
module-str = UART Async Adapter
20+
source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config"
21+
22+
endif

samples/bluetooth/peripheral_uart/src/uart_async_adapter.c subsys/uart_async_adapter/uart_async_adapter.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77
/** @file
88
* @brief UART asynchronous API adapter implementation
99
*/
10-
#include "uart_async_adapter.h"
10+
#include <uart_async_adapter.h>
1111
#include <zephyr/drivers/uart.h>
1212
#include <zephyr/sys/__assert.h>
1313

1414
#include <zephyr/logging/log.h>
15-
LOG_MODULE_REGISTER(uart_async_adapter);
15+
LOG_MODULE_REGISTER(uart_async_adapter, CONFIG_UART_ASYNC_ADAPTER_LOG_LEVEL);
1616

1717

1818
#if !IS_ENABLED(CONFIG_UART_ASYNC_API)

0 commit comments

Comments
 (0)