esp32s3/spiflash: pause other CPU before SPI flash operations
Whenever a SPI flash operation is going to take place, it's necessary to disable both the instruction and data cache. In order to avoid the other CPU (if SMP is enabled) to retrieve data from the SPI flash, it needs to be paused until the current SPI flash operation finishes. All the code that "pauses" the other CPU (in fact, the CPU spins until `up_cpu_resume` is called) needs to run from the instruction RAM.
This commit is contained in:
parent
218aa63af3
commit
63364a52ff
@ -122,6 +122,10 @@ struct spiflash_cachestate_s
|
||||
{
|
||||
uint32_t value;
|
||||
irqstate_t flags;
|
||||
int cpu;
|
||||
#ifdef CONFIG_SMP
|
||||
int other;
|
||||
#endif
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
@ -137,7 +141,9 @@ static void spiflash_end(void);
|
||||
|
||||
extern void spi_flash_guard_set(const struct spiflash_guard_funcs_s *funcs);
|
||||
extern uint32_t cache_suspend_icache(void);
|
||||
extern uint32_t cache_suspend_dcache(void);
|
||||
extern void cache_resume_icache(uint32_t val);
|
||||
extern void cache_resume_dcache(uint32_t val);
|
||||
extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
|
||||
|
||||
/****************************************************************************
|
||||
@ -167,7 +173,20 @@ static struct spiflash_cachestate_s g_state;
|
||||
static IRAM_ATTR void spiflash_start(void)
|
||||
{
|
||||
g_state.flags = enter_critical_section();
|
||||
g_state.cpu = up_cpu_index();
|
||||
#ifdef CONFIG_SMP
|
||||
g_state.other = g_state.cpu ? 0 : 1;
|
||||
#endif
|
||||
|
||||
DEBUGASSERT(g_state.cpu == 0 || g_state.cpu == 1);
|
||||
#ifdef CONFIG_SMP
|
||||
DEBUGASSERT(g_state.other == 0 || g_state.other == 1);
|
||||
DEBUGASSERT(g_state.other != g_state.cpu);
|
||||
up_cpu_pause(g_state.other);
|
||||
#endif
|
||||
|
||||
g_state.value = cache_suspend_icache() << 16;
|
||||
g_state.value |= cache_suspend_dcache();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
@ -180,7 +199,20 @@ static IRAM_ATTR void spiflash_start(void)
|
||||
|
||||
static IRAM_ATTR void spiflash_end(void)
|
||||
{
|
||||
DEBUGASSERT(g_state.cpu == 0 || g_state.cpu == 1);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
DEBUGASSERT(g_state.other == 0 || g_state.other == 1);
|
||||
DEBUGASSERT(g_state.other != g_state.cpu);
|
||||
#endif
|
||||
|
||||
cache_resume_icache(g_state.value >> 16);
|
||||
cache_resume_dcache(g_state.value & 0xffff);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
up_cpu_resume(g_state.other);
|
||||
#endif
|
||||
|
||||
leave_critical_section(g_state.flags);
|
||||
}
|
||||
|
||||
|
@ -76,6 +76,17 @@ SECTIONS
|
||||
|
||||
*(.iram1 .iram1.*)
|
||||
|
||||
*libarch.a:esp32s3_spiflash.*(.literal .text .literal.* .text.*)
|
||||
*libarch.a:xtensa_cpupause.*(.literal .text .literal.* .text.*)
|
||||
*libarch.a:xtensa_testset.*(.literal .text .literal.* .text.*)
|
||||
|
||||
*libsched.a:irq_csection.*(.literal .text .literal.* .text.*)
|
||||
*libsched.a:irq_dispatch.*(.literal .text .literal.* .text.*)
|
||||
*libsched.a:sched_note.*(.literal .text .literal.* .text.*)
|
||||
*libsched.a:sched_suspendscheduler.*(.literal .text .literal.* .text.*)
|
||||
*libsched.a:sched_thistask.*(.literal .text .literal.* .text.*)
|
||||
*libsched.a:spinlock.*(.literal .text .literal.* .text.*)
|
||||
|
||||
*(.wifirxiram .wifirxiram.*)
|
||||
*(.wifi0iram .wifi0iram.*)
|
||||
*(.wifiorslpiram .wifiorslpiram.*)
|
||||
|
Loading…
Reference in New Issue
Block a user