diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index e073ff6aca63a..1bedd5348d7b3 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -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 diff --git a/arch/xtensa/src/common/xtensa_cpupause.c b/arch/xtensa/src/common/xtensa_cpupause.c index 59de3ccbe554f..a19aae38e1f92 100644 --- a/arch/xtensa/src/common/xtensa_cpupause.c +++ b/arch/xtensa/src/common/xtensa_cpupause.c @@ -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; @@ -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); + } } /**************************************************************************** diff --git a/arch/xtensa/src/common/xtensa_schedsigaction.c b/arch/xtensa/src/common/xtensa_schedsigaction.c index 693e55545d70b..e989d4f30f0ac 100644 --- a/arch/xtensa/src/common/xtensa_schedsigaction.c +++ b/arch/xtensa/src/common/xtensa_schedsigaction.c @@ -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 diff --git a/arch/xtensa/src/esp32/esp32_intercpu_interrupt.c b/arch/xtensa/src/esp32/esp32_intercpu_interrupt.c index eade8e5ff4c61..42eba07f50ee9 100644 --- a/arch/xtensa/src/esp32/esp32_intercpu_interrupt.c +++ b/arch/xtensa/src/esp32/esp32_intercpu_interrupt.c @@ -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 ****************************************************************************/ @@ -82,10 +67,9 @@ 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 */ @@ -93,29 +77,9 @@ static int esp32_fromcpu_interrupt(int fromcpu) 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; } @@ -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); diff --git a/boards/xtensa/esp32/esp32-core/configs/smp/defconfig b/boards/xtensa/esp32/esp32-core/configs/smp/defconfig index 7e82870190e6a..fc6467997801f 100644 --- a/boards/xtensa/esp32/esp32-core/configs/smp/defconfig +++ b/boards/xtensa/esp32/esp32-core/configs/smp/defconfig @@ -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 @@ -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 @@ -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"