mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(esp32s3): patch Cache_WriteBack_Addr api
avoid accessing cachelines that are being writebacked
This commit is contained in:
parent
a2d76ad38a
commit
b1436633c5
@ -46,7 +46,7 @@ if(CONFIG_HAL_WDT_USE_ROM_IMPL)
|
||||
list(APPEND sources "patches/esp_rom_wdt.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG)
|
||||
if(CONFIG_ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG OR CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG)
|
||||
list(APPEND sources "patches/esp_rom_cache_esp32s2_esp32s3.c")
|
||||
endif()
|
||||
|
||||
|
@ -82,3 +82,7 @@ config ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG
|
||||
config ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG
|
||||
bool
|
||||
default y
|
||||
|
||||
config ESP_ROM_HAS_CACHE_WRITEBACK_BUG
|
||||
bool
|
||||
default y
|
||||
|
@ -26,3 +26,4 @@
|
||||
#define ESP_ROM_RAM_APP_NEEDS_MMU_INIT (1) // ROM doesn't init cache MMU when it's a RAM APP, needs MMU hal to init
|
||||
#define ESP_ROM_HAS_FLASH_COUNT_PAGES_BUG (1) // ROM api Cache_Count_Flash_Pages will return unexpected value
|
||||
#define ESP_ROM_HAS_CACHE_SUSPEND_WAITI_BUG (1) // ROM api Cache_Suspend_I/DCache and Cache_Freeze_I/DCache_Enable does not waiti
|
||||
#define ESP_ROM_HAS_CACHE_WRITEBACK_BUG (1) // ROM api Cache_WriteBack_Addr address or size misalignment may cause cache hit with wrong value.
|
||||
|
@ -381,7 +381,7 @@ PROVIDE( Cache_WriteBack_Items = 0x40001698 );
|
||||
PROVIDE( Cache_Op_Addr = 0x400016a4 );
|
||||
PROVIDE( Cache_Invalidate_Addr = 0x400016b0 );
|
||||
PROVIDE( Cache_Clean_Addr = 0x400016bc );
|
||||
PROVIDE( Cache_WriteBack_Addr = 0x400016c8 );
|
||||
PROVIDE( rom_Cache_WriteBack_Addr = 0x400016c8 );
|
||||
PROVIDE( Cache_Invalidate_ICache_All = 0x400016d4 );
|
||||
PROVIDE( Cache_Invalidate_DCache_All = 0x400016e0 );
|
||||
PROVIDE( Cache_Clean_All = 0x400016ec );
|
||||
|
@ -8,10 +8,14 @@
|
||||
#include <stdint.h>
|
||||
#include "soc/soc_caps.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "xtensa/xtruntime.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#endif
|
||||
|
||||
#define ALIGN_UP(addr, align) (((addr) + (align)-1) & ~((align)-1))
|
||||
#define ALIGN_DOWN(addr, align) ((addr) & ~((align) - 1))
|
||||
|
||||
// this api is renamed for patch
|
||||
extern uint32_t rom_Cache_Count_Flash_Pages(uint32_t bus, uint32_t * page0_mapped);
|
||||
uint32_t Cache_Count_Flash_Pages(uint32_t bus, uint32_t * page0_mapped)
|
||||
@ -83,3 +87,89 @@ void Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode)
|
||||
extern void Cache_Freeze_DCache_Enable(cache_freeze_mode_t mode);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if CONFIG_ESP_ROM_HAS_CACHE_WRITEBACK_BUG
|
||||
static void __attribute__((optimize("-O2"))) Cache_WriteBack_Items_Freeze(uint32_t addr, uint32_t items)
|
||||
{
|
||||
/* Please do not modify this function, it must strictly follow the current execution sequence,
|
||||
* otherwise it may cause unexpected errors.
|
||||
*/
|
||||
REG_WRITE(EXTMEM_DCACHE_SYNC_ADDR_REG, addr);
|
||||
REG_SET_FIELD(EXTMEM_DCACHE_SYNC_SIZE_REG, EXTMEM_DCACHE_SYNC_SIZE, items);
|
||||
|
||||
/*enable dcache freeze, mode = CACHE_FREEZE_ACK_BUSY*/
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_MODE);
|
||||
REG_SET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA);
|
||||
while (!REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE));
|
||||
|
||||
REG_SET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_WRITEBACK_ENA);
|
||||
while(!REG_GET_BIT(EXTMEM_DCACHE_SYNC_CTRL_REG, EXTMEM_DCACHE_SYNC_DONE));
|
||||
|
||||
/*disable dcache freeze*/
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_ENA);
|
||||
while (REG_GET_BIT(EXTMEM_DCACHE_FREEZE_REG, EXTMEM_DCACHE_FREEZE_DONE));
|
||||
}
|
||||
|
||||
// renamed for patch
|
||||
extern int rom_Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
int Cache_WriteBack_Addr(uint32_t addr, uint32_t size)
|
||||
{
|
||||
/* Do special processing for unaligned memory at the start and end of the cache writeback memory.
|
||||
* 1. Disable the interrupt to prevent the current CPU accessing the same cacheline.
|
||||
* 2. Enable dcache freeze to prevent the another CPU accessing the same cacheline.
|
||||
*/
|
||||
uint32_t irq_status;
|
||||
uint32_t start_len, end_len;
|
||||
uint32_t start, end;
|
||||
uint32_t dcache_line_size;
|
||||
uint32_t autoload;
|
||||
int ret = 0;
|
||||
start = addr;
|
||||
end = addr + size;
|
||||
dcache_line_size = Cache_Get_DCache_Line_Size();
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*the start address is unaligned*/
|
||||
if (start & (dcache_line_size -1)) {
|
||||
addr = ALIGN_UP(start, dcache_line_size);
|
||||
start_len = addr - start;
|
||||
size = (size < start_len) ? 0 : (size - start_len);
|
||||
|
||||
/*writeback start unaligned mem, one cacheline*/
|
||||
irq_status = XTOS_SET_INTLEVEL(XCHAL_NMILEVEL);//mask all interrupts
|
||||
Cache_WriteBack_Items_Freeze(start, 1);
|
||||
XTOS_RESTORE_INTLEVEL(irq_status);
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*the end address is unaligned*/
|
||||
if (end & (dcache_line_size -1)) {
|
||||
end = ALIGN_DOWN(end, dcache_line_size);
|
||||
end_len = addr + size - end;
|
||||
size = (size - end_len);
|
||||
|
||||
/*writeback end unaligned mem, one cacheline*/
|
||||
irq_status = XTOS_SET_INTLEVEL(XCHAL_NMILEVEL);//mask all interrupts
|
||||
Cache_WriteBack_Items_Freeze(end, 1);
|
||||
XTOS_RESTORE_INTLEVEL(irq_status);
|
||||
|
||||
if (size == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*suspend autoload, avoid load cachelines being written back*/
|
||||
autoload = Cache_Suspend_DCache_Autoload();
|
||||
ret = rom_Cache_WriteBack_Addr(addr, size);
|
||||
Cache_Resume_DCache_Autoload(autoload);
|
||||
|
||||
return ret;
|
||||
}
|
||||
extern int Cache_WriteBack_Addr(uint32_t addr, uint32_t size);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user