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>
This commit is contained in:
parent
0630c5cfb5
commit
e783aafdd0
1 changed files with 53 additions and 0 deletions
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Open-RnD Sp. z o.o.
|
||||
* Copyright (c) 2016 Linaro Limited.
|
||||
* Copyright (c) 2024 STMicroelectronics
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -39,6 +40,12 @@
|
|||
#include <stm32_ll_exti.h>
|
||||
#endif /* CONFIG_PM */
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
#include <zephyr/linker/linker-defs.h>
|
||||
#include <zephyr/mem_mgmt/mem_attr.h>
|
||||
#include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/irq.h>
|
||||
LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
|
||||
|
@ -1301,6 +1308,32 @@ static void uart_stm32_isr(const struct device *dev)
|
|||
|
||||
#ifdef CONFIG_UART_ASYNC_API
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
static bool buf_in_nocache(uintptr_t buf, size_t len_bytes)
|
||||
{
|
||||
bool buf_within_nocache = false;
|
||||
|
||||
#ifdef CONFIG_NOCACHE_MEMORY
|
||||
buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) &&
|
||||
((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end));
|
||||
if (buf_within_nocache) {
|
||||
return true;
|
||||
}
|
||||
#endif /* CONFIG_NOCACHE_MEMORY */
|
||||
|
||||
buf_within_nocache = mem_attr_check_buf(
|
||||
(void *)buf, len_bytes, DT_MEM_ARM_MPU_RAM_NOCACHE) == 0;
|
||||
if (buf_within_nocache) {
|
||||
return true;
|
||||
}
|
||||
|
||||
buf_within_nocache = (buf >= ((uintptr_t)__rodata_region_start)) &&
|
||||
((buf + len_bytes - 1) <= ((uintptr_t)__rodata_region_end));
|
||||
|
||||
return buf_within_nocache;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
static int uart_stm32_async_callback_set(const struct device *dev,
|
||||
uart_callback_t callback,
|
||||
void *user_data)
|
||||
|
@ -1512,6 +1545,13 @@ static int uart_stm32_async_tx(const struct device *dev,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
if (!buf_in_nocache((uintptr_t)tx_data, buf_size)) {
|
||||
LOG_ERR("Tx buffer should be placed in a nocache memory region");
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
data->dma_tx.buffer = (uint8_t *)tx_data;
|
||||
data->dma_tx.buffer_length = buf_size;
|
||||
data->dma_tx.timeout = timeout;
|
||||
|
@ -1572,6 +1612,13 @@ static int uart_stm32_async_rx_enable(const struct device *dev,
|
|||
return -EBUSY;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DCACHE
|
||||
if (!buf_in_nocache((uintptr_t)rx_buf, buf_size)) {
|
||||
LOG_ERR("Rx buffer should be placed in a nocache memory region");
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
|
||||
data->dma_rx.offset = 0;
|
||||
data->dma_rx.buffer = rx_buf;
|
||||
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,
|
|||
} else if (!data->dma_rx.enabled) {
|
||||
err = -EACCES;
|
||||
} else {
|
||||
#ifdef CONFIG_DCACHE
|
||||
if (!buf_in_nocache((uintptr_t)buf, len)) {
|
||||
LOG_ERR("Rx buffer should be placed in a nocache memory region");
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif /* CONFIG_DCACHE */
|
||||
data->rx_next_buffer = buf;
|
||||
data->rx_next_buffer_len = len;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue