2121#include <zephyr/pm/device_runtime.h>
2222#include "i2c_ll_stm32.h"
2323
24+ #ifdef CONFIG_DCACHE
25+ #include <zephyr/cache.h>
26+ #include <zephyr/linker/linker-defs.h>
27+ #include <zephyr/mem_mgmt/mem_attr.h>
28+ #include <zephyr/dt-bindings/memory-attr/memory-attr-arm.h>
29+ #endif /* CONFIG_DCACHE */
30+
2431#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL
2532#include <zephyr/logging/log.h>
2633LOG_MODULE_REGISTER (i2c_ll_stm32_v2 );
@@ -676,6 +683,35 @@ void stm32_i2c_error_isr(void *arg)
676683}
677684#endif
678685
686+ #ifdef CONFIG_DCACHE
687+ static bool buf_in_nocache (uintptr_t buf , size_t len_bytes )
688+ {
689+ bool buf_within_nocache = false;
690+
691+ #ifdef CONFIG_NOCACHE_MEMORY
692+ /* Check if buffer is in nocache region defined by the linker */
693+ buf_within_nocache = (buf >= ((uintptr_t )_nocache_ram_start )) &&
694+ ((buf + len_bytes - 1 ) <= ((uintptr_t )_nocache_ram_end ));
695+ if (buf_within_nocache ) {
696+ return true;
697+ }
698+ #endif /* CONFIG_NOCACHE_MEMORY */
699+
700+ /* Check if buffer is in nocache memory region defined in DT */
701+ buf_within_nocache = mem_attr_check_buf (
702+ (void * )buf , len_bytes , DT_MEM_ARM (ATTR_MPU_RAM_NOCACHE )) == 0 ;
703+ if (buf_within_nocache ) {
704+ return true;
705+ }
706+
707+ /* Check if buffer is in RO region (Flash..) */
708+ buf_within_nocache = (buf >= ((uintptr_t )__rodata_region_start )) &&
709+ ((buf + len_bytes - 1 ) <= ((uintptr_t )__rodata_region_end ));
710+
711+ return buf_within_nocache ;
712+ }
713+ #endif /* CONFIG_DCACHE */
714+
679715static int stm32_i2c_msg_write (const struct device * dev , struct i2c_msg * msg ,
680716 uint8_t * next_msg_flags , uint16_t slave )
681717{
@@ -691,6 +727,14 @@ static int stm32_i2c_msg_write(const struct device *dev, struct i2c_msg *msg,
691727 data -> current .is_err = 0U ;
692728 data -> current .msg = msg ;
693729
730+ #ifdef CONFIG_DCACHE
731+ if (!buf_in_nocache ((uintptr_t )msg -> buf , msg -> len )) {
732+ LOG_DBG ("Tx buffer at %p (len %zu) is in cached memory; cleaning cache" , msg -> buf ,
733+ msg -> len );
734+ sys_cache_data_flush_range ((void * )msg -> buf , msg -> len );
735+ }
736+ #endif /* CONFIG_DCACHE */
737+
694738 msg_init (dev , msg , next_msg_flags , slave , LL_I2C_REQUEST_WRITE );
695739
696740 stm32_i2c_enable_transfer_interrupts (dev );
@@ -762,6 +806,14 @@ static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg,
762806 is_timeout = true;
763807 }
764808
809+ #ifdef CONFIG_DCACHE
810+ if (!buf_in_nocache ((uintptr_t )msg -> buf , msg -> len )) {
811+ LOG_DBG ("Rx buffer at %p (len %zu) is in cached memory; invalidating cache" ,
812+ msg -> buf , msg -> len );
813+ sys_cache_data_invd_range ((void * )msg -> buf , msg -> len );
814+ }
815+ #endif /* CONFIG_DCACHE */
816+
765817 if (data -> current .is_nack || data -> current .is_err ||
766818 data -> current .is_arlo || is_timeout ) {
767819 goto error ;
0 commit comments