Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions arch/xtensa/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ config ARCH_CHIP_ESP32
select XTENSA_HAVE_INTERRUPTS
select ARCH_HAVE_MULTICPU
select ARCH_TOOLCHAIN_GNU
select ARCH_GLOBAL_IRQDISABLE
---help---
The ESP32 is a dual-core system from Expressif with two Harvard
architecture Xtensa LX6 CPUs. All embedded memory, external memory
Expand Down
45 changes: 24 additions & 21 deletions arch/xtensa/src/common/xtensa_cpupause.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,57 +111,50 @@ bool up_cpu_pausereq(int cpu)

int up_cpu_paused(int cpu)
{
FAR struct tcb_s *otcb = this_task();
FAR struct tcb_s *ntcb;
FAR struct tcb_s *tcb = this_task();

/* Update scheduler parameters */

sched_suspend_scheduler(otcb);
sched_suspend_scheduler(tcb);

#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we are paused */

sched_note_cpu_paused(otcb);
sched_note_cpu_paused(tcb);
#endif

/* Copy the CURRENT_REGS into the OLD TCB (otcb). The co-processor state
* will be saved as part of the return from xtensa_irq_dispatch().
*/

xtensa_savestate(otcb->xcp.regs);
xtensa_savestate(tcb->xcp.regs);

/* Wait for the spinlock to be released */

spin_unlock(&g_cpu_paused[cpu]);
spin_lock(&g_cpu_wait[cpu]);

/* Upon return, we will restore the exception context of the new TCB
* (ntcb) at the head of the ready-to-run task list.
/* Restore the exception context of the tcb at the (new) head of the
* assigned task list.
*/

ntcb = this_task();
tcb = this_task();

#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we have resumed */

sched_note_cpu_resumed(ntcb);
sched_note_cpu_resumed(tcb);
#endif

/* Reset scheduler parameters */

sched_resume_scheduler(ntcb);
sched_resume_scheduler(tcb);

/* Did the task at the head of the list change? */

if (otcb != ntcb)
{
/* Set CURRENT_REGS to the context save are of the new TCB to start.
* This will inform the return-from-interrupt logic that a context
* switch must be performed.
*/
/* Then switch contexts. Any necessary address environment changes
* will be made when the interrupt returns.
*/

xtensa_restorestate(ntcb->xcp.regs);
}
xtensa_restorestate(tcb->xcp.regs);

spin_unlock(&g_cpu_wait[cpu]);
return OK;
Expand Down Expand Up @@ -190,7 +183,17 @@ int up_cpu_paused(int cpu)

void xtensa_pause_handler(void)
{
up_cpu_paused(up_cpu_index());
int cpu = up_cpu_index();

/* Check for false alarms. Such false could occur as a consequence of
* some deadlock breaking logic that might have already serviced the SG2
* interrupt by calling up_cpu_paused.
*/

if (spin_islocked(&g_cpu_paused[cpu]))
{
up_cpu_paused(cpu);
}
}

/****************************************************************************
Expand Down
6 changes: 3 additions & 3 deletions arch/xtensa/src/common/xtensa_schedsigaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -284,11 +284,11 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
* disabled
*/

CURRENT_REGS[REG_PC] = (uint32_t)_xtensa_sig_trampoline;
tcb->xcp.regs[REG_PC] = (uint32_t)_xtensa_sig_trampoline;
#ifdef __XTENSA_CALL0_ABI__
CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM);
#else
CURRENT_REGS[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE);
tcb->xcp.regs[REG_PS] = (uint32_t)(PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE);
#endif
}
else
Expand Down
63 changes: 5 additions & 58 deletions arch/xtensa/src/esp32/esp32_intercpu_interrupt.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,6 @@

#ifdef CONFIG_SMP

/****************************************************************************
* Private Data
****************************************************************************/

/* Single parameter passed with the inter-CPU interrupt */

static volatile uint8_t g_intcode[CONFIG_SMP_NCPUS] SP_SECTION;

/* Spinlock protects parameter array */

static volatile spinlock_t g_intercpu_spin[CONFIG_SMP_NCPUS] SP_SECTION =
{
SP_UNLOCKED, SP_UNLOCKED
};

/****************************************************************************
* Private Function
****************************************************************************/
Expand All @@ -82,40 +67,19 @@ static volatile spinlock_t g_intercpu_spin[CONFIG_SMP_NCPUS] SP_SECTION =
static int esp32_fromcpu_interrupt(int fromcpu)
{
uintptr_t regaddr;
int intcode;
int tocpu;

DEBUGASSERT((unsigned)fromcpu < CONFIG_SMP_NCPUS);
DEBUGASSERT(fromcpu != up_cpu_index());

/* Clear the interrupt from the other CPU */

regaddr = (fromcpu == 0) ? DPORT_CPU_INTR_FROM_CPU_0_REG :
DPORT_CPU_INTR_FROM_CPU_1_REG;
putreg32(0, regaddr);

/* Get the inter-CPU interrupt code */

tocpu = up_cpu_index();
intcode = g_intcode[tocpu];
g_intcode[tocpu] = CPU_INTCODE_NONE;
/* Call pause handler */

spin_unlock(&g_intercpu_spin[tocpu]);

/* Dispatch the inter-CPU interrupt based on the intcode value */

switch (intcode)
{
case CPU_INTCODE_NONE:
break;

case CPU_INTCODE_PAUSE:
xtensa_pause_handler();
break;

default:
DEBUGPANIC();
break;
}
xtensa_pause_handler();

return OK;
}
Expand Down Expand Up @@ -157,28 +121,11 @@ int xtensa_intercpu_interrupt(int tocpu, int intcode)
DEBUGASSERT((unsigned)tocpu < CONFIG_SMP_NCPUS &&
(unsigned)intcode <= UINT8_MAX);

/* Make sure that each inter-cpu event is atomic. The spinlock should
* only be locked if we just completed sending an interrupt to this
* CPU but the other CPU has not yet processed it.
*/

spin_lock(&g_intercpu_spin[tocpu]);

/* Save the passed parameter. The previous interrupt code should be
* CPU_INTCODE_NONE or we have overrun the other CPU.
*/

DEBUGASSERT(g_intcode[tocpu] == CPU_INTCODE_NONE);
g_intcode[tocpu] = intcode;

/* Interrupt the other CPU (tocpu) form this CPU. NOTE: that this logic
* fails in numerous ways if fromcpu == tocpu (for example because non-
* reentrant spinlocks are used).
*/

fromcpu = up_cpu_index();
DEBUGASSERT(fromcpu != tocpu);

/* Generate an Inter-Processor Interrupt */

if (fromcpu == 0)
{
putreg32(DPORT_CPU_INTR_FROM_CPU_0, DPORT_CPU_INTR_FROM_CPU_0_REG);
Expand Down
10 changes: 10 additions & 0 deletions boards/xtensa/esp32/esp32-core/configs/smp/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_DEBUG_FEATURES=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_ESP32_UART0=y
CONFIG_EXAMPLES_HELLO=y
CONFIG_EXPERIMENTAL=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
Expand All @@ -31,6 +34,7 @@ CONFIG_NFILE_DESCRIPTORS=8
CONFIG_NFILE_STREAMS=8
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
CONFIG_NSH_READLINE=y
CONFIG_NSH_FILEIOSIZE=512
CONFIG_NSH_LINELEN=64
CONFIG_NSH_READLINE=y
Expand All @@ -39,19 +43,25 @@ CONFIG_PREALLOC_TIMERS=4
CONFIG_PREALLOC_WDOGS=16
CONFIG_RAM_SIZE=114688
CONFIG_RAM_START=0x20000000
CONFIG_READLINE_CMD_HISTORY=y
CONFIG_RAW_BINARY=y
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_INSTRUMENTATION=y
CONFIG_SCHED_INSTRUMENTATION_BUFFER=y
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_SMP=y
CONFIG_SMP_NCPUS=2
CONFIG_SPI=y
CONFIG_SPINLOCK_IRQ=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SUPPRESS_CLOCK_CONFIG=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_NSH_CXXINITIALIZE=y
CONFIG_SYSTEM_TASKSET=y
CONFIG_TESTING_OSTEST=y
CONFIG_TESTING_SMP=y
CONFIG_UART0_SERIAL_CONSOLE=y
CONFIG_USER_ENTRYPOINT="nsh_main"