Skip to content

Commit e783aaf

Browse files
ajarmouni-stnashif
authored andcommitted
drivers: uart_stm32: add DCache support in async DMA mode
Adapt the driver to verify if DMA buffers are located in noncacheable memory when DCache is activated, in order to avoid cache coherency issues. This is required until manual cache coherency management is implemented. Signed-off-by: Abderrahmane Jarmouni <abderrahmane.jarmouni-ext@st.com>
1 parent 0630c5c commit e783aaf

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

drivers/serial/uart_stm32.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/*
22
* Copyright (c) 2016 Open-RnD Sp. z o.o.
33
* Copyright (c) 2016 Linaro Limited.
4+
* Copyright (c) 2024 STMicroelectronics
45
*
56
* SPDX-License-Identifier: Apache-2.0
67
*/
@@ -39,6 +40,12 @@
3940
#include <stm32_ll_exti.h>
4041
#endif /* CONFIG_PM */
4142

43+
#ifdef CONFIG_DCACHE
44+
#include <zephyr/linker/linker-defs.h>
45+
#include <zephyr/mem_mgmt/mem_attr.h>
46+
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
47+
#endif /* CONFIG_DCACHE */
48+
4249
#include <zephyr/logging/log.h>
4350
#include <zephyr/irq.h>
4451
LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
@@ -1301,6 +1308,32 @@ static void uart_stm32_isr(const struct device *dev)
13011308

13021309
#ifdef CONFIG_UART_ASYNC_API
13031310

1311+
#ifdef CONFIG_DCACHE
1312+
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
1313+
{
1314+
bool buf_within_nocache = false;
1315+
1316+
#ifdef CONFIG_NOCACHE_MEMORY
1317+
buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) &&
1318+
((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end));
1319+
if (buf_within_nocache) {
1320+
return true;
1321+
}
1322+
#endif /* CONFIG_NOCACHE_MEMORY */
1323+
1324+
buf_within_nocache = mem_attr_check_buf(
1325+
(void *)buf, len_bytes, DT_MEM_ARM_MPU_RAM_NOCACHE) == 0;
1326+
if (buf_within_nocache) {
1327+
return true;
1328+
}
1329+
1330+
buf_within_nocache = (buf >= ((uintptr_t)__rodata_region_start)) &&
1331+
((buf + len_bytes - 1) <= ((uintptr_t)__rodata_region_end));
1332+
1333+
return buf_within_nocache;
1334+
}
1335+
#endif /* CONFIG_DCACHE */
1336+
13041337
static int uart_stm32_async_callback_set(const struct device *dev,
13051338
uart_callback_t callback,
13061339
void *user_data)
@@ -1512,6 +1545,13 @@ static int uart_stm32_async_tx(const struct device *dev,
15121545
return -EBUSY;
15131546
}
15141547

1548+
#ifdef CONFIG_DCACHE
1549+
if (!buf_in_nocache((uintptr_t)tx_data, buf_size)) {
1550+
LOG_ERR("Tx buffer should be placed in a nocache memory region");
1551+
return -EFAULT;
1552+
}
1553+
#endif /* CONFIG_DCACHE */
1554+
15151555
data->dma_tx.buffer = (uint8_t *)tx_data;
15161556
data->dma_tx.buffer_length = buf_size;
15171557
data->dma_tx.timeout = timeout;
@@ -1572,6 +1612,13 @@ static int uart_stm32_async_rx_enable(const struct device *dev,
15721612
return -EBUSY;
15731613
}
15741614

1615+
#ifdef CONFIG_DCACHE
1616+
if (!buf_in_nocache((uintptr_t)rx_buf, buf_size)) {
1617+
LOG_ERR("Rx buffer should be placed in a nocache memory region");
1618+
return -EFAULT;
1619+
}
1620+
#endif /* CONFIG_DCACHE */
1621+
15751622
data->dma_rx.offset = 0;
15761623
data->dma_rx.buffer = rx_buf;
15771624
data->dma_rx.buffer_length = buf_size;
@@ -1696,6 +1743,12 @@ static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf,
16961743
} else if (!data->dma_rx.enabled) {
16971744
err = -EACCES;
16981745
} else {
1746+
#ifdef CONFIG_DCACHE
1747+
if (!buf_in_nocache((uintptr_t)buf, len)) {
1748+
LOG_ERR("Rx buffer should be placed in a nocache memory region");
1749+
return -EFAULT;
1750+
}
1751+
#endif /* CONFIG_DCACHE */
16991752
data->rx_next_buffer = buf;
17001753
data->rx_next_buffer_len = len;
17011754
}

0 commit comments

Comments
 (0)