diff --git a/libcpu/arm/cortex-a/cache.c b/libcpu/arm/cortex-a/cache.c index 0a7e702dbb..a6b59182a6 100644 --- a/libcpu/arm/cortex-a/cache.c +++ b/libcpu/arm/cortex-a/cache.c @@ -58,6 +58,37 @@ void rt_hw_cpu_dcache_invalidate(void *addr, int size) asm volatile ("dsb":::"memory"); } +void rt_hw_cpu_dcache_inv_range(void *addr, int size) +{ + rt_uint32_t line_size = rt_cpu_dcache_line_size(); + rt_uint32_t start_addr = (rt_uint32_t)addr; + rt_uint32_t end_addr = (rt_uint32_t)addr + size; + + asm volatile ("dmb":::"memory"); + + if ((start_addr & (line_size - 1)) != 0) + { + start_addr &= ~(line_size - 1); + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr)); + start_addr += line_size; + asm volatile ("dsb":::"memory"); + } + + if ((end_addr & (line_size - 1)) != 0) + { + end_addr &= ~(line_size - 1); + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(end_addr)); + asm volatile ("dsb":::"memory"); + } + + while (start_addr < end_addr) + { + asm volatile ("mcr p15, 0, %0, c7, c6, 1" :: "r"(start_addr)); /* dcimvac */ + start_addr += line_size; + } + asm volatile ("dsb":::"memory"); +} + void rt_hw_cpu_dcache_clean(void *addr, int size) { rt_uint32_t line_size = rt_cpu_dcache_line_size(); @@ -75,6 +106,23 @@ void rt_hw_cpu_dcache_clean(void *addr, int size) asm volatile ("dsb":::"memory"); } +void rt_hw_cpu_dcache_clean_inv(void *addr, int size) +{ + rt_uint32_t line_size = rt_cpu_dcache_line_size(); + rt_uint32_t start_addr = (rt_uint32_t)addr; + rt_uint32_t end_addr = (rt_uint32_t) addr + size + line_size - 1; + + asm volatile ("dmb":::"memory"); + start_addr &= ~(line_size-1); + end_addr &= ~(line_size-1); + while (start_addr < end_addr) + { + asm volatile ("mcr p15, 0, %0, c7, c14, 1" :: "r"(start_addr)); + start_addr += line_size; + } + asm volatile ("dsb":::"memory"); +} + void rt_hw_cpu_icache_ops(int ops, void *addr, int size) { if (ops == RT_HW_CACHE_INVALIDATE)