2026-01-02 1:45 PM - last edited on 2026-01-03 2:17 AM by Andrew Neil
Zephyr RTOS 4.3.
I am trying to get this sample working on my STM32 Nucleo F767ZI board:
zephyr/samples/drivers/uart/async_api/
I created an overlay file.
nucleo_f767zi.overlay
dut: &usart3 {
dmas = <&dma1 2 STM32_DMA_PERIPH_TX>,
<&dma1 3 STM32_DMA_PERIPH_RX>;
dma-names = "tx", "rx";
};
&dma1 {
status = "okay";
};
Building and running the sample I get the following output:
*** Booting Zephyr OS build v4.3.0-929-g1d6e0d533a81 ***
[00:00:05.000,000] <inf> sample: Loop 0: Sending 3 packets
[00:00:05.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:05.000,000] <err> sample: Unknown error (-14)
[00:00:05.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:05.000,000] <err> sample: Unknown error (-14)
[00:00:05.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:05.000,000] <err> sample: Unknown error (-14)
[00:00:05.000,000] <inf> sample: RX is now enabled
I then updated my prj.conf adding nocache support:
prj.conf
CONFIG_LOG=y
CONFIG_NET_BUF=y
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_NOCACHE_MEMORY=y
I then pulled over the macro definition for this line:
NET_BUF_POOL_DEFINE(tx_pool, LOOP_ITER_MAX_TX, MAX_TX_LEN, 0, NULL);
And changed:
static uint8_t __noinit net_buf_data_##_name[_count][_data_size] __net_buf_align;
to:
static uint8_t __nocache net_buf_data_##_name[_count][_data_size] __net_buf_align;
Thus putting the Tx buffer in nocache memory, but now I am getting these errors:
*** Booting Zephyr OS build v4.3.0-929-g1d6e0d533a81 ***
[00:00:05.000,000] <inf> sample: Loop 0: Sending 3 packets
[00:00:05.000,000] <err> dma_stm32: Memcopy not supported for device dma@40026000
[00:00:05.000,000] <err> uart_stm32: dma tx config error!
[00:00:05.000,000] <err> sample: Unknown error (-22)
[00:00:05.000,000] <dbg> sample: main: Queuing buffer 0x20022458
[00:00:05.000,000] <dbg> sample: main: Queuing buffer 0x20022470
[00:00:05.000,000] <inf> sample: RX is now enabled
[00:00:06.044,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:06.044,000] <dbg> sample: uart_callback: TX complete 0
[00:00:06.044,000] <err> dma_stm32: Memcopy not supported for device dma@40026000
[00:00:06.044,000] <err> uart_stm32: dma tx config error!
[00:00:06.044,000] <err> sample: TX from ISR failed (-22)
[00:00:07.076,000] <dbg> sample: uart_callback: EVENT: 0
I also noticed in my build output the messages:
/home/myuser/Projects/uart_async_api/build/primary/zephyr/zephyr.dts:550.4-551.31: Warning (dmas_property): /soc/serial@40004800:dmas: cell 5 is not a phandle reference
/home/myuser/Projects/uart_async_api/build/primary/zephyr/zephyr.dts:550.4-551.31: Warning (dmas_property): /soc/serial@40004800:dmas: Could not get phandle node for (cell 5)
Is the above related to the issues I am seeing?
Does the STM32 Zephyr driver support the UART Async API?
If so, how can I get it working?
Thank you.
2026-01-20 1:50 AM
hello @digitalone
Regarding your question: Does the STM32 Zephyr driver support the UART Async API?
Yes, it does support the UART Async API, provided that:
CONFIG_LOG=y
CONFIG_NET_BUF=y
CONFIG_SERIAL=y
CONFIG_UART_ASYNC_API=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_DMA=y
CONFIG_NOCACHE_MEMORY=y
CONFIG_NOCACHE_MEMORY_STATIC=y
also, to fix the issues you are seeing:
Correct the DTS overlay so that it complies with the Zephyr binding for the STM32 DMA v2 implementation:
Zephyr implementation st,stm32-dma-v2
Example:
&usart3 {
status = "okay";
current-speed = <115200>;
dmas = <&dma1 2 1 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH)>,
<&dma1 3 1 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH)>;
dma-names = "tx", "rx";
};
&dma1 {
status = "okay";
};
with these adjustments, the samples/drivers/uart/async_api/ example works on the Nucleo-F767ZI with UART3 + DMA, with no DTS warnings and no DMA/UART driver errors.
best regrads,
Hamdi
2026-01-20 7:37 PM
Thank you for the reply.
I am getting compile errors now.
It occurs as soon as I add "CONFIG_NOCACHE_MEMORY_STATIC=y" to the prj.conf file.
I cannot find it defined anywhere, what does it do?
If I comment out the above and update the device tree overlay with what you provided above I get this error:
devicetree error: <Node /clocks/pll in ~/zephyrproject/zephyr/dts/arm/st/f7/stm32f7.dtsi:87> lacks #dma-cells
I don't understand this as when I look in that file I do see dma-cells.
2026-01-26 8:44 AM
Hello @digitalone
In your Zephyr 4.3 + STM32F7 setup, CONFIG_NOCACHE_MEMORY_STATIC is not defined.
That option exists only on some SoCs/boards; it is not universal.
The error:
devicetree error: <Node /clocks/pll in .../stm32f7.dtsi:87> lacks #dma-cells
After checking, you need to adapt this to DMA v1 (st, stm32-dma-v1, #dma-cells = <4>) instead of v2.
For v1, each dmas entry must have 4 integers after the phandle.
A corrected version for DMA v1is:
&usart3 {
status = "okay";
current-speed = <115200>;
dmas = <&dma1 2 4 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEMORY_INC) 0>,
<&dma1 3 4 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEMORY_INC) 0>;
dma-names = "tx", "rx";
};
&dma1 {
status = "okay";
};
best regards,
2026-01-26 5:01 PM
Thank you for the reply.
I was getting device tree errors with the above so I had to remove STM32_DMA_MEMORY_INC from both of them as shown below. VSCode was underlining them with red squiggles in addition to the error.
&usart3 {
status = "okay";
current-speed = <115200>;
dmas = <&dma1 2 4 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH) 0>,
<&dma1 3 4 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH) 0>;
dma-names = "tx", "rx";
};
&dma1 {
status = "okay";
};I was able to build and run it but am seeing some errors. For example "<err> uart_stm32: dma tx config error!"
See the serial output below. Why am I getting these errors?
---- Opened the serial port /dev/ttyACM0 ----
*** Booting Zephyr OS build v4.3.0-929-g1d6e0d533a81 ***
[00:00:05.000,000] <inf> sample: Loop 0: Sending 4 packets
[00:00:05.000,000] <dbg> sample: main: Queuing buffer 0x20022458
[00:00:05.000,000] <dbg> sample: main: Queuing buffer 0x20022470
[00:00:05.000,000] <dbg> sample: main: Queuing buffer 0x20022488
[00:00:05.000,000] <dbg> sample: uart_callback: EVENT: 2
[00:00:05.000,000] <inf> sample: RX_RDY
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........
[00:00:05.000,000] <dbg> sample: uart_callback: EVENT: 3
[00:00:05.000,000] <dbg> sample: uart_callback: Providing buffer index 1
[00:00:05.000,000] <inf> sample: RX is now enabled
[00:00:05.000,000] <dbg> sample: uart_callback: EVENT: 4
[00:00:05.000,000] <dbg> sample: uart_callback: EVENT: 4
[00:00:05.000,000] <dbg> sample: uart_callback: EVENT: 5
[00:00:05.088,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:05.088,000] <dbg> sample: uart_callback: TX complete 0x20022440
[00:00:05.088,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:05.088,000] <err> uart_stm32: dma tx config error!
[00:00:05.088,000] <err> sample: TX from ISR failed (-22)
[00:00:06.119,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:06.119,000] <dbg> sample: uart_callback: TX complete 0
[00:00:06.119,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:06.119,000] <err> uart_stm32: dma tx config error!
[00:00:06.119,000] <err> sample: TX from ISR failed (-22)
[00:00:07.149,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:07.149,000] <dbg> sample: uart_callback: TX complete 0
[00:00:07.149,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:07.149,000] <err> uart_stm32: dma tx config error!
[00:00:07.149,000] <err> sample: TX from ISR failed (-22)
[00:00:08.179,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:08.179,000] <dbg> sample: uart_callback: TX complete 0
[00:00:10.000,000] <inf> sample: Loop 1: Sending 3 packets
[00:00:10.000,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:10.000,000] <err> uart_stm32: dma tx config error!
[00:00:10.000,000] <err> sample: Unknown error (-22)
[00:00:10.000,000] <dbg> sample: main: Queuing buffer 0x20022470
[00:00:10.000,000] <dbg> sample: main: Queuing buffer 0x20022458
[00:00:10.000,000] <dbg> sample: uart_callback: EVENT: 5
[00:00:10.000,000] <inf> sample: RX is now disabled
[00:00:11.048,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:11.048,000] <dbg> sample: uart_callback: TX complete 0
[00:00:11.048,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:11.048,000] <err> uart_stm32: dma tx config error!
[00:00:11.048,000] <err> sample: TX from ISR failed (-22)
[00:00:12.078,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:12.078,000] <dbg> sample: uart_callback: TX complete 0
[00:00:12.078,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:12.078,000] <err> uart_stm32: dma tx config error!
[00:00:12.078,000] <err> sample: TX from ISR failed (-22)
[00:00:13.108,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:13.108,000] <dbg> sample: uart_callback: TX complete 0
[00:00:15.000,000] <inf> sample: Loop 2: Sending 4 packets
[00:00:15.000,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:15.000,000] <err> uart_stm32: dma tx config error!
[00:00:15.000,000] <err> sample: Unknown error (-22)
[00:00:15.000,000] <dbg> sample: main: Queuing buffer 0x20022470
[00:00:15.000,000] <dbg> sample: main: Queuing buffer 0x20022440
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 0
[00:00:16.037,000] <dbg> sample: uart_callback: TX complete 0
[00:00:16.037,000] <err> dma_stm32: dma stream 2 is busy.
[00:00:16.037,000] <err> uart_stm32: dma tx config error!
[00:00:16.037,000] <err> sample: TX from ISR failed (-22)
[00:00:16.037,000] <dbg> sample: main: Queuing buffer 0x20022470
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 2
[00:00:16.037,000] <inf> sample: RX_RDY
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |........ ........
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 3
[00:00:16.037,000] <dbg> sample: uart_callback: Providing buffer index 1
[00:00:16.037,000] <inf> sample: RX is now enabled
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 4
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 4
[00:00:16.037,000] <dbg> sample: uart_callback: EVENT: 5
---- Closed the serial port /dev/ttyACM0 ----
2026-01-28 7:49 AM
Hello @digitalone
Please correct your DTS file with these two lines, according to the reference manual.
dmas = <&dma1 3 4 (STM32_DMA_PERIPH_TX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_INC) 0>,
<&dma1 1 4 (STM32_DMA_PERIPH_RX | STM32_DMA_PRIORITY_HIGH | STM32_DMA_MEM_INC) 0>;
best regards,
hamdi
2026-01-28 6:42 PM - edited 2026-01-28 6:57 PM
Thank you. That fixed the output.
Now I need help with what I was experiencing at the beginning.
With the default code below for "tx_pool"
/* Maximum number of packets to generate per iteration */
#define LOOP_ITER_MAX_TX 4
/* Maximum size of our TX packets */
#define MAX_TX_LEN 32
#define RX_CHUNK_LEN 32
/* Buffer pool for our TX payloads */
NET_BUF_POOL_DEFINE(tx_pool, LOOP_ITER_MAX_TX, MAX_TX_LEN, 0, NULL);
struct k_fifo tx_queue;I get the following errors:
---- Opened the serial port /dev/ttyACM0 ----
[00:00:05.000,000] <inf> sample: Loop 0: Sending 1 packets
[00:00:05.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:05.000,000] <err> sample: Unknown error (-14)
[00:00:05.000,000] <err> uart_stm32: Rx buffer should be placed in a nocache memory region
[00:00:05.000,000] <inf> sample: RX is now enabled
[00:00:10.000,000] <inf> sample: Loop 1: Sending 3 packets
[00:00:10.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:10.000,000] <err> sample: Unknown error (-14)
[00:00:10.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:10.000,000] <err> sample: Unknown error (-14)
[00:00:10.000,000] <err> uart_stm32: Tx buffer should be placed in a nocache memory region
[00:00:10.000,000] <err> sample: Unknown error (-14)
[00:00:10.000,000] <inf> sample: RX is now disabled
---- Closed the serial port /dev/ttyACM0 ----To fix this issue I had to modify the code as followed to apply the __nocache attribute.
/* Maximum number of packets to generate per iteration */
#define LOOP_ITER_MAX_TX 4
/* Maximum size of our TX packets */
#define MAX_TX_LEN 32
#define RX_CHUNK_LEN 32
// #define _NET_BUF_ARRAY_DEFINE(_name, _count, _ud_size) \
// struct _net_buf_##_name { uint8_t b[sizeof(struct net_buf)]; \
// uint8_t ud[_ud_size]; } __net_buf_align; \
// BUILD_ASSERT(_ud_size <= UINT8_MAX); \
// BUILD_ASSERT(offsetof(struct net_buf, user_data) == \
// offsetof(struct _net_buf_##_name, ud), "Invalid offset"); \
// BUILD_ASSERT(__alignof__(struct net_buf) == \
// __alignof__(struct _net_buf_##_name), "Invalid alignment"); \
// BUILD_ASSERT(sizeof(struct _net_buf_##_name) == \
// ROUND_UP(sizeof(struct net_buf) + _ud_size, __alignof__(struct net_buf)), \
// "Size cannot be determined"); \
// static struct _net_buf_##_name _net_buf_##_name[_count] __noinit
struct _net_buf_tx_pool { uint8_t b[sizeof(struct net_buf)];
uint8_t ud[0]; } __net_buf_align;
static struct _net_buf_tx_pool _net_buf_tx_pool[LOOP_ITER_MAX_TX] __noinit;
// #define NET_BUF_POOL_FIXED_DEFINE(_name, _count, _data_size, _ud_size, _destroy) \
// _NET_BUF_ARRAY_DEFINE(_name, _count, _ud_size); \
// static uint8_t __noinit net_buf_data_##_name[_count][_data_size] __net_buf_align; \
// static const struct net_buf_pool_fixed net_buf_fixed_##_name = { \
// .data_pool = (uint8_t *)net_buf_data_##_name, \
// }; \
// static const struct net_buf_data_alloc net_buf_fixed_alloc_##_name = { \
// .cb = &net_buf_fixed_cb, \
// .alloc_data = (void *)&net_buf_fixed_##_name, \
// .max_alloc_size = _data_size, \
// }; \
// static STRUCT_SECTION_ITERABLE(net_buf_pool, _name) = \
// NET_BUF_POOL_INITIALIZER(_name, &net_buf_fixed_alloc_##_name, \
// _net_buf_##_name, _count, _ud_size, \
// _destroy)
static uint8_t __nocache net_buf_data_tx_pool[LOOP_ITER_MAX_TX][MAX_TX_LEN] __net_buf_align;
static const struct net_buf_pool_fixed net_buf_fixed_tx_pool = {
.data_pool = (uint8_t *)net_buf_data_tx_pool,
};
static const struct net_buf_data_alloc net_buf_fixed_alloc_tx_pool = {
.cb = &net_buf_fixed_cb,
.alloc_data = (void *)&net_buf_fixed_tx_pool,
.max_alloc_size = MAX_TX_LEN,
};
static STRUCT_SECTION_ITERABLE(net_buf_pool, tx_pool) = NET_BUF_POOL_INITIALIZER(tx_pool, &net_buf_fixed_alloc_tx_pool, _net_buf_tx_pool, LOOP_ITER_MAX_TX, 0, NULL);
/* Buffer pool for our TX payloads */
//NET_BUF_POOL_DEFINE(tx_pool, LOOP_ITER_MAX_TX, MAX_TX_LEN, 0, NULL);
struct k_fifo tx_queue;
struct net_buf *tx_pending_buffer;
__nocache uint8_t async_rx_buffer[2][RX_CHUNK_LEN];
volatile uint8_t async_rx_buffer_idx;
Is there a way to apply __nocache to the "NET_BUF_POOL_DEFINE(tx_pool, LOOP_ITER_MAX_TX, MAX_TX_LEN, 0, NULL);" line other than what I did, which was getting the source code for the "NET_BUF_POOL_DEFINE" macro and unpacking it and finding the write place to put the __nocache?
It seems like there should be a better way but I could not find one.