soc: xtensa: esp32: reenable SMP for esp32
By enabling SMP option plus the APPCPU, also
completes the SMP port by adding the esp32
specific arch_sched_ipi() function
Signed-off-by: Felipe Neves <felipe.neves@espressif.com>
diff --git a/soc/xtensa/esp32/esp32-mp.c b/soc/xtensa/esp32/esp32-mp.c
index 63cc4b0..857ae29 100644
--- a/soc/xtensa/esp32/esp32-mp.c
+++ b/soc/xtensa/esp32/esp32-mp.c
@@ -5,8 +5,13 @@
*/
/* Include esp-idf headers first to avoid redefining BIT() macro */
-#include <soc.h>
+#include "soc/dport_reg.h"
+#include "soc/gpio_periph.h"
+#include "soc/rtc_periph.h"
+#include <drivers/interrupt_controller/intc_esp32.h>
+#include <soc.h>
+#include <device.h>
#include <zephyr.h>
#include <spinlock.h>
#include <kernel_structs.h>
@@ -33,9 +38,11 @@
volatile struct cpustart_rec *start_rec;
static void *appcpu_top;
-
+static bool cpus_active[CONFIG_MP_NUM_CPUS];
static struct k_spinlock loglock;
+extern void z_sched_ipi(void);
+
/* Note that the logging done here is ACTUALLY REQUIRED FOR RELIABLE
* OPERATION! At least one particular board will experience spurious
* hangs during initialization (usually the APPCPU fails to start at
@@ -67,7 +74,6 @@
static void appcpu_entry2(void)
{
volatile int ps, ie;
- smp_log("ESP32: APPCPU running");
/* Copy over VECBASE from the main CPU for an initial value
* (will need to revisit this if we ever allow a user API to
@@ -92,6 +98,8 @@
__asm__ volatile("wsr.MISC0 %0" : : "r"(cpu));
+ smp_log("ESP32: APPCPU running");
+
*start_rec->alive = 1;
start_rec->fn(start_rec->arg);
}
@@ -190,6 +198,34 @@
smp_log("ESP32: APPCPU start sequence complete");
}
+IRAM_ATTR static inline uint32_t prid(void)
+{
+ uint32_t id;
+
+ __asm__ volatile (
+ "rsr.prid %0\n"
+ "extui %0,%0,13,1" : "=r" (id));
+ return id;
+}
+
+IRAM_ATTR static void esp_crosscore_isr(void *arg)
+{
+ ARG_UNUSED(arg);
+
+#ifdef CONFIG_SMP
+ /* Right now this interrupt is only used for IPIs */
+ z_sched_ipi();
+#endif
+
+ const int core_id = prid();
+
+ if (core_id == 0) {
+ DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, 0);
+ } else {
+ DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, 0);
+ }
+}
+
void arch_start_cpu(int cpu_num, k_thread_stack_t *stack, int sz,
arch_cpustart_t fn, void *arg)
{
@@ -219,5 +255,36 @@
while (!alive_flag) {
}
+ cpus_active[0] = true;
+ cpus_active[CONFIG_MP_NUM_CPUS - 1] = true;
+
+ esp_intr_alloc(DT_IRQN(DT_NODELABEL(ipi0)),
+ ESP_INTR_FLAG_IRAM,
+ esp_crosscore_isr,
+ NULL,
+ NULL);
+
+ esp_intr_alloc(DT_IRQN(DT_NODELABEL(ipi1)),
+ ESP_INTR_FLAG_IRAM,
+ esp_crosscore_isr,
+ NULL,
+ NULL);
+
smp_log("ESP32: APPCPU initialized");
}
+
+void arch_sched_ipi(void)
+{
+ const int core_id = prid();
+
+ if (core_id == 0) {
+ DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_0_REG, DPORT_CPU_INTR_FROM_CPU_0);
+ } else {
+ DPORT_WRITE_PERI_REG(DPORT_CPU_INTR_FROM_CPU_1_REG, DPORT_CPU_INTR_FROM_CPU_1);
+ }
+}
+
+IRAM_ATTR bool arch_cpu_active(int cpu_num)
+{
+ return cpus_active[cpu_num];
+}