soc_esp32::crosscore
Interrupting the other core.
The ESP32 has four “from CPU” interrupt sources. Each is a single bit in a
DPORT register that any core may set, and it asserts a level-triggered
interrupt source in the crossbar. Which core it lands on is decided by
[crate::intr_map], not by which register was written: route the source in
one core’s table and leave it parked in the other’s, and the signal is
aimed.
Level-triggered, so the handler must clear the bit. Returning without
calling [clear] re-enters it forever.
Register facts
Section titled “Register facts”From soc/dport_reg.h and soc/soc.h at v4.4, read rather than recalled:
DPORT_CPU_INTR_FROM_CPU_0_REG DPORT + 0x0DC bit 0 source 24DPORT_CPU_INTR_FROM_CPU_1_REG DPORT + 0x0E0 bit 0 source 25DPORT_CPU_INTR_FROM_CPU_2_REG DPORT + 0x0E4 bit 0 source 26DPORT_CPU_INTR_FROM_CPU_3_REG DPORT + 0x0E8 bit 0 source 27esp-idf’s comments assign 0 and 1 to FreeRTOS’s own cross-core yield and 2
and 3 to IPC_ISR. FlintOS uses 2, which is the one esp-idf uses for the
same job — parking the other core for a flash operation.
Signal
Section titled “Signal”enum Signal { FromCpu0, FromCpu1, FromCpu2, FromCpu3,}Which of the four signals.
Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq
Functions
Section titled “Functions”unsafe fn clear(signal: Signal)Clear signal. A handler must do this, or it re-enters forever.
Safety
Section titled “Safety”Writes a DPORT register.
References: Signal
unsafe fn raise(signal: Signal)Raise signal, interrupting whichever core has its source routed.
Written straight through rather than via dport::write: the caller is
about to disable its own cache, and everything from here to the release has
to be reachable without one. A plain store to a DPORT register needs none
of the erratum handling a read-modify-write does.
Safety
Section titled “Safety”Writes a DPORT register. Raising a signal nothing has routed sets a bit that stays set.
References: Signal