Skip to content

Commit 63364a5

Browse files
tmediccixiaoxiang781216
authored andcommitted
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.
1 parent 218aa63 commit 63364a5

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

arch/xtensa/src/esp32s3/esp32s3_spiflash.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ struct spiflash_cachestate_s
122122
{
123123
uint32_t value;
124124
irqstate_t flags;
125+
int cpu;
126+
#ifdef CONFIG_SMP
127+
int other;
128+
#endif
125129
};
126130

127131
/****************************************************************************
@@ -137,7 +141,9 @@ static void spiflash_end(void);
137141

138142
extern void spi_flash_guard_set(const struct spiflash_guard_funcs_s *funcs);
139143
extern uint32_t cache_suspend_icache(void);
144+
extern uint32_t cache_suspend_dcache(void);
140145
extern void cache_resume_icache(uint32_t val);
146+
extern void cache_resume_dcache(uint32_t val);
141147
extern int cache_invalidate_addr(uint32_t addr, uint32_t size);
142148

143149
/****************************************************************************
@@ -167,7 +173,20 @@ static struct spiflash_cachestate_s g_state;
167173
static IRAM_ATTR void spiflash_start(void)
168174
{
169175
g_state.flags = enter_critical_section();
176+
g_state.cpu = up_cpu_index();
177+
#ifdef CONFIG_SMP
178+
g_state.other = g_state.cpu ? 0 : 1;
179+
#endif
180+
181+
DEBUGASSERT(g_state.cpu == 0 || g_state.cpu == 1);
182+
#ifdef CONFIG_SMP
183+
DEBUGASSERT(g_state.other == 0 || g_state.other == 1);
184+
DEBUGASSERT(g_state.other != g_state.cpu);
185+
up_cpu_pause(g_state.other);
186+
#endif
187+
170188
g_state.value = cache_suspend_icache() << 16;
189+
g_state.value |= cache_suspend_dcache();
171190
}
172191

173192
/****************************************************************************
@@ -180,7 +199,20 @@ static IRAM_ATTR void spiflash_start(void)
180199

181200
static IRAM_ATTR void spiflash_end(void)
182201
{
202+
DEBUGASSERT(g_state.cpu == 0 || g_state.cpu == 1);
203+
204+
#ifdef CONFIG_SMP
205+
DEBUGASSERT(g_state.other == 0 || g_state.other == 1);
206+
DEBUGASSERT(g_state.other != g_state.cpu);
207+
#endif
208+
183209
cache_resume_icache(g_state.value >> 16);
210+
cache_resume_dcache(g_state.value & 0xffff);
211+
212+
#ifdef CONFIG_SMP
213+
up_cpu_resume(g_state.other);
214+
#endif
215+
184216
leave_critical_section(g_state.flags);
185217
}
186218

boards/xtensa/esp32s3/common/scripts/legacy_sections.ld

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,17 @@ SECTIONS
7676

7777
*(.iram1 .iram1.*)
7878

79+
*libarch.a:esp32s3_spiflash.*(.literal .text .literal.* .text.*)
80+
*libarch.a:xtensa_cpupause.*(.literal .text .literal.* .text.*)
81+
*libarch.a:xtensa_testset.*(.literal .text .literal.* .text.*)
82+
83+
*libsched.a:irq_csection.*(.literal .text .literal.* .text.*)
84+
*libsched.a:irq_dispatch.*(.literal .text .literal.* .text.*)
85+
*libsched.a:sched_note.*(.literal .text .literal.* .text.*)
86+
*libsched.a:sched_suspendscheduler.*(.literal .text .literal.* .text.*)
87+
*libsched.a:sched_thistask.*(.literal .text .literal.* .text.*)
88+
*libsched.a:spinlock.*(.literal .text .literal.* .text.*)
89+
7990
*(.wifirxiram .wifirxiram.*)
8091
*(.wifi0iram .wifi0iram.*)
8192
*(.wifiorslpiram .wifiorslpiram.*)

0 commit comments

Comments
 (0)