diff --git a/esp-hal/Cargo.toml b/esp-hal/Cargo.toml index 6581fcc23f1..ff6dbdfc442 100644 --- a/esp-hal/Cargo.toml +++ b/esp-hal/Cargo.toml @@ -131,8 +131,6 @@ esp32s2 = ["dep:esp32s2", "xtensa", "portable-atomic/critical-section", "procmac esp32s3 = ["dep:esp32s3", "xtensa", "procmacros/has-ulp-core", "xtensa-lx/spin", "xtensa-lx-rt?/esp32s3", "usb-otg"] #! ### RISC-V Exclusive Feature Flags -## Enable direct interrupt vectoring. -direct-vectoring = ["esp-riscv-rt/direct-vectoring"] ## Move the stack to start of RAM to get zero-cost stack overflow protection ## (ESP32-C6 and ESPS32-H2 only!). flip-link = ["esp-riscv-rt/fix-sp"] diff --git a/esp-hal/build.rs b/esp-hal/build.rs index a1d13e3518b..7f7008b7831 100644 --- a/esp-hal/build.rs +++ b/esp-hal/build.rs @@ -113,12 +113,12 @@ fn main() -> Result<(), Box> { panic!("The target does not support PSRAM"); } - // Don't support "interrupt-preemption" and "direct-vectoring" on Xtensa and + // Don't support "interrupt-preemption" on Xtensa and // RISC-V with CLIC: if (config.contains(&String::from("clic")) || config.arch() == Arch::Xtensa) - && (cfg!(feature = "direct-vectoring") || cfg!(feature = "interrupt-preemption")) + && cfg!(feature = "interrupt-preemption") { - panic!("The target does not support interrupt-preemption and direct-vectoring"); + panic!("The target does not support interrupt-preemption"); } // Define all necessary configuration symbols for the configured device: diff --git a/esp-hal/src/embassy/executor/interrupt.rs b/esp-hal/src/embassy/executor/interrupt.rs index 18f2164f4be..ad15c00b1d6 100644 --- a/esp-hal/src/embassy/executor/interrupt.rs +++ b/esp-hal/src/embassy/executor/interrupt.rs @@ -42,11 +42,7 @@ macro_rules! from_cpu { panic!("FROM_CPU_{} is already used by a different executor.", $irq); } - // unsafe block because of direct-vectoring on riscv - #[allow(unused_unsafe)] - unsafe { - unwrap!(interrupt::enable(peripherals::Interrupt::[], priority)); - } + unwrap!(interrupt::enable(peripherals::Interrupt::[], priority)); } fn number() -> usize { diff --git a/esp-hal/src/interrupt/riscv.rs b/esp-hal/src/interrupt/riscv.rs index da13660588b..0d3b06f8afc 100644 --- a/esp-hal/src/interrupt/riscv.rs +++ b/esp-hal/src/interrupt/riscv.rs @@ -185,7 +185,6 @@ mod vectored { /// /// Note that interrupts still need to be enabled globally for interrupts /// to be serviced. - #[cfg(not(feature = "direct-vectoring"))] pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> { if matches!(level, Priority::None) { return Err(Error::InvalidInterruptPriority); @@ -214,8 +213,8 @@ mod vectored { /// /// Note that interrupts still need to be enabled globally for interrupts /// to be serviced. - #[cfg(feature = "direct-vectoring")] - pub unsafe fn enable( + // TODO document used interrupts + pub unsafe fn enable_direct( interrupt: Interrupt, level: Priority, cpu_interrupt: CpuInterrupt, @@ -275,119 +274,119 @@ mod vectored { #[no_mangle] #[ram] - pub unsafe fn interrupt1(context: &mut TrapFrame) { + pub unsafe fn cpu_int_1_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt1, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt2(context: &mut TrapFrame) { + pub unsafe fn cpu_int_2_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt2, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt3(context: &mut TrapFrame) { + pub unsafe fn cpu_int_3_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt3, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt4(context: &mut TrapFrame) { + pub unsafe fn cpu_int_4_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt4, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt5(context: &mut TrapFrame) { + pub unsafe fn cpu_int_5_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt5, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt6(context: &mut TrapFrame) { + pub unsafe fn cpu_int_6_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt6, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt7(context: &mut TrapFrame) { + pub unsafe fn cpu_int_7_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt7, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt8(context: &mut TrapFrame) { + pub unsafe fn cpu_int_8_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt8, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt9(context: &mut TrapFrame) { + pub unsafe fn cpu_int_9_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt9, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt10(context: &mut TrapFrame) { + pub unsafe fn cpu_int_10_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt10, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt11(context: &mut TrapFrame) { + pub unsafe fn cpu_int_11_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt11, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt12(context: &mut TrapFrame) { + pub unsafe fn cpu_int_12_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt12, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt13(context: &mut TrapFrame) { + pub unsafe fn cpu_int_13_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt13, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt14(context: &mut TrapFrame) { + pub unsafe fn cpu_int_14_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt14, context) } #[no_mangle] #[ram] - pub unsafe fn interrupt15(context: &mut TrapFrame) { + pub unsafe fn cpu_int_15_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt15, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt16(context: &mut TrapFrame) { + pub unsafe fn cpu_int_16_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt16, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt17(context: &mut TrapFrame) { + pub unsafe fn cpu_int_17_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt17, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt18(context: &mut TrapFrame) { + pub unsafe fn cpu_int_18_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt18, context) } #[cfg(plic)] #[no_mangle] #[ram] - pub unsafe fn interrupt19(context: &mut TrapFrame) { + pub unsafe fn cpu_int_19_handler(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt19, context) } } @@ -399,125 +398,14 @@ mod vectored { #[link_section = ".trap.rust"] #[export_name = "_start_trap_rust_hal"] pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { - // User code shouldn't usually take the mutable TrapFrame or the TrapFrame in - // general. However this makes things like preemtive multitasking easier in - // future + assert!( + mcause::read().is_exception(), + "Arrived into _start_trap_rust_hal but mcause is not an exception!" + ); extern "C" { - fn interrupt1(frame: &mut TrapFrame); - fn interrupt2(frame: &mut TrapFrame); - fn interrupt3(frame: &mut TrapFrame); - fn interrupt4(frame: &mut TrapFrame); - fn interrupt5(frame: &mut TrapFrame); - fn interrupt6(frame: &mut TrapFrame); - fn interrupt7(frame: &mut TrapFrame); - fn interrupt8(frame: &mut TrapFrame); - fn interrupt9(frame: &mut TrapFrame); - fn interrupt10(frame: &mut TrapFrame); - fn interrupt11(frame: &mut TrapFrame); - fn interrupt12(frame: &mut TrapFrame); - fn interrupt13(frame: &mut TrapFrame); - fn interrupt14(frame: &mut TrapFrame); - fn interrupt15(frame: &mut TrapFrame); - fn interrupt16(frame: &mut TrapFrame); - fn interrupt17(frame: &mut TrapFrame); - fn interrupt18(frame: &mut TrapFrame); - fn interrupt19(frame: &mut TrapFrame); - fn interrupt20(frame: &mut TrapFrame); - fn interrupt21(frame: &mut TrapFrame); - fn interrupt22(frame: &mut TrapFrame); - fn interrupt23(frame: &mut TrapFrame); - fn interrupt24(frame: &mut TrapFrame); - fn interrupt25(frame: &mut TrapFrame); - fn interrupt26(frame: &mut TrapFrame); - fn interrupt27(frame: &mut TrapFrame); - fn interrupt28(frame: &mut TrapFrame); - fn interrupt29(frame: &mut TrapFrame); - fn interrupt30(frame: &mut TrapFrame); - fn interrupt31(frame: &mut TrapFrame); - - // Defined in `esp-riscv-rt` - pub fn DefaultHandler(); - } - - let cause = mcause::read(); - if cause.is_exception() { - extern "C" { - fn ExceptionHandler(tf: *mut TrapFrame); - } - ExceptionHandler(trap_frame); - } else { - #[cfg(feature = "interrupt-preemption")] - let interrupt_priority = _handle_priority(); - - let code = mcause::read().code(); - - // with CLIC the MCAUSE register changed - // 31: Interrupt flag (same as before) - // - // 30: MINHV: Used to indicate whether the processor is fetching the vector - // interrupt entry address. This bit will be set high when the processor - // responds to the vector interrupt. Cleared to 0 after successfully obtaining - // the vector interrupt service routine entry address - // - // 29-28: MPP: This bit is the mirror image of MSTATUS.MPP[1:0], that is, - // reading and writing MCAUSE.MPP will produce the same result as - // reading and writing MSTATUS.MPP. - // - // 27: MPIE: This bit mirrors MSTATUS.MPIE - // - // 23-16: MPIL: This bit saves the interrupt priority level before the - // processor enters the interrupt service routine, that is, the MINTSTATUS.MIL - // bit is copied to this bit. When executing the MRET instruction and returning - // from an interrupt, the processor copies the MPIL bit to the MIL bit in the - // MINTSTATUS register. - // - // 11-0: Exception code: When the processor is configured in CLIC mode, this - // bit field is expanded to 12 bits, supporting up to 4096 interrupt ID number - // records. - // - // So we need to mask out bits other than > 12. We currently only support - // external interrupts so we subtract EXTERNAL_INTERRUPT_OFFSET - #[cfg(clic)] - let code = (code & 0b1111_1111_1111) - EXTERNAL_INTERRUPT_OFFSET as usize; - - match code { - 1 => interrupt1(trap_frame.as_mut().unwrap()), - 2 => interrupt2(trap_frame.as_mut().unwrap()), - 3 => interrupt3(trap_frame.as_mut().unwrap()), - 4 => interrupt4(trap_frame.as_mut().unwrap()), - 5 => interrupt5(trap_frame.as_mut().unwrap()), - 6 => interrupt6(trap_frame.as_mut().unwrap()), - 7 => interrupt7(trap_frame.as_mut().unwrap()), - 8 => interrupt8(trap_frame.as_mut().unwrap()), - 9 => interrupt9(trap_frame.as_mut().unwrap()), - 10 => interrupt10(trap_frame.as_mut().unwrap()), - 11 => interrupt11(trap_frame.as_mut().unwrap()), - 12 => interrupt12(trap_frame.as_mut().unwrap()), - 13 => interrupt13(trap_frame.as_mut().unwrap()), - 14 => interrupt14(trap_frame.as_mut().unwrap()), - 15 => interrupt15(trap_frame.as_mut().unwrap()), - 16 => interrupt16(trap_frame.as_mut().unwrap()), - 17 => interrupt17(trap_frame.as_mut().unwrap()), - 18 => interrupt18(trap_frame.as_mut().unwrap()), - 19 => interrupt19(trap_frame.as_mut().unwrap()), - 20 => interrupt20(trap_frame.as_mut().unwrap()), - 21 => interrupt21(trap_frame.as_mut().unwrap()), - 22 => interrupt22(trap_frame.as_mut().unwrap()), - 23 => interrupt23(trap_frame.as_mut().unwrap()), - 24 => interrupt24(trap_frame.as_mut().unwrap()), - 25 => interrupt25(trap_frame.as_mut().unwrap()), - 26 => interrupt26(trap_frame.as_mut().unwrap()), - 27 => interrupt27(trap_frame.as_mut().unwrap()), - 28 => interrupt28(trap_frame.as_mut().unwrap()), - 29 => interrupt29(trap_frame.as_mut().unwrap()), - 30 => interrupt30(trap_frame.as_mut().unwrap()), - 31 => interrupt31(trap_frame.as_mut().unwrap()), - _ => DefaultHandler(), - }; - - #[cfg(feature = "interrupt-preemption")] - _restore_priority(interrupt_priority); + fn ExceptionHandler(tf: *mut TrapFrame); } + ExceptionHandler(trap_frame); } #[doc(hidden)] @@ -749,7 +637,7 @@ mod classic { .read_volatile(); core::mem::transmute(prio as u8) } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] + #[cfg(feature = "interrupt-preemption")] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _handle_priority() -> u32 { @@ -773,7 +661,7 @@ mod classic { } prev_interrupt_priority } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] + #[cfg(feature = "interrupt-preemption")] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) { @@ -807,7 +695,7 @@ mod plic { const PLIC_MXINT_TYPE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x4; const PLIC_MXINT_CLEAR_REG: u32 = DR_REG_PLIC_MX_BASE + 0x8; const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10; - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] + #[cfg(feature = "interrupt-preemption")] const PLIC_MXINT_THRESH_REG: u32 = DR_REG_PLIC_MX_BASE + 0x90; /// Enable a CPU interrupt pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { @@ -883,7 +771,7 @@ mod plic { .read_volatile(); core::mem::transmute(prio as u8) } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] + #[cfg(feature = "interrupt-preemption")] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _handle_priority() -> u32 { @@ -904,7 +792,7 @@ mod plic { } prev_interrupt_priority } - #[cfg(any(feature = "interrupt-preemption", feature = "direct-vectoring"))] + #[cfg(feature = "interrupt-preemption")] #[no_mangle] #[link_section = ".trap"] pub(super) unsafe extern "C" fn _restore_priority(stored_prio: u32) { diff --git a/esp-riscv-rt/Cargo.toml b/esp-riscv-rt/Cargo.toml index 76e2f35404b..9325c7f8ab0 100644 --- a/esp-riscv-rt/Cargo.toml +++ b/esp-riscv-rt/Cargo.toml @@ -36,14 +36,11 @@ zero-bss = [] zero-rtc-fast-bss = [] #! ### Interrupt Feature Flags -## Enable direct interrupt vectoring. -direct-vectoring = [] ## Enable interrupt preemption. interrupt-preemption = [] # This feature is intended for testing; you probably don't want to enable it: ci = [ - "direct-vectoring", "fix-sp", "has-mie-mip", "init-data", diff --git a/esp-riscv-rt/src/lib.rs b/esp-riscv-rt/src/lib.rs index ee941243bff..28aa2ff3660 100644 --- a/esp-riscv-rt/src/lib.rs +++ b/esp-riscv-rt/src/lib.rs @@ -442,7 +442,7 @@ _abs_start: _start_trap_rust, then restores all saved registers before `mret` */ .section .trap, "ax" -.weak _start_trap +.weak _start_trap /* Exceptions call into _start_trap in vectored mode */ .weak _start_trap1 .weak _start_trap2 .weak _start_trap3 @@ -475,8 +475,12 @@ _abs_start: .weak _start_trap30 .weak _start_trap31 "#, -#[cfg(feature="direct-vectoring")] r#" +_start_trap: // Handle exceptions in vectored mode + addi sp, sp, -40*4 + sw ra, 0(sp) + la ra, _start_trap_rust_hal /* Load the HAL trap handler */ + j _start_trap_direct _start_trap1: addi sp, sp, -40*4 sw ra, 0(sp) @@ -632,44 +636,8 @@ _start_trap31: sw ra, 0(sp) la ra, cpu_int_31_handler j _start_trap_direct -"#, -#[cfg(not(feature="direct-vectoring"))] -r#" -_start_trap1: -_start_trap2: -_start_trap3: -_start_trap4: -_start_trap5: -_start_trap6: -_start_trap7: -_start_trap8: -_start_trap9: -_start_trap10: -_start_trap11: -_start_trap12: -_start_trap13: -_start_trap14: -_start_trap15: -_start_trap16: -_start_trap17: -_start_trap18: -_start_trap19: -_start_trap20: -_start_trap21: -_start_trap22: -_start_trap23: -_start_trap24: -_start_trap25: -_start_trap26: -_start_trap27: -_start_trap28: -_start_trap29: -_start_trap30: -_start_trap31: - -"#, -r#" -_start_trap: +la ra, _start_trap_rust_hal /* this runs on exception, use regular fault handler */ +_start_trap_direct: "#, #[cfg(feature="fix-sp")] r#" @@ -697,14 +665,6 @@ r#" csrr t0, mscratch // now SP is in RAM - continue "#, -r#" - addi sp, sp, -40*4 - sw ra, 0*4(sp)"#, -#[cfg(feature="direct-vectoring")] //for the directly vectored handlers the above is stacked beforehand -r#" - la ra, _start_trap_rust_hal #this runs on exception, use regular fault handler -_start_trap_direct: -"#, r#" sw t0, 1*4(sp) sw t1, 2*4(sp) @@ -749,7 +709,7 @@ r#" add a0, sp, zero "#, - #[cfg(all(feature="interrupt-preemption", feature="direct-vectoring"))] //store current priority, set threshold, enable interrupts + #[cfg(all(feature="interrupt-preemption"))] //store current priority, set threshold, enable interrupts r#" addi sp, sp, -4 #build stack sw ra, 0(sp) @@ -758,15 +718,11 @@ r#" sw a0, 0(sp) #reuse old stack, a0 is return of _handle_priority addi a0, sp, 4 #the proper stack pointer is an argument to the HAL handler "#, - #[cfg(not(feature="direct-vectoring"))] //jump to HAL handler - r#" - jal ra, _start_trap_rust_hal - "#, - #[cfg(feature="direct-vectoring")] //jump to handler loaded in direct handler + // jump to handler loaded in direct handler r#" jalr ra, ra #jump to label loaded in _start_trapx "#, - #[cfg(all(feature="interrupt-preemption", feature="direct-vectoring"))] //restore threshold + #[cfg(all(feature="interrupt-preemption"))] //restore threshold r#" lw a0, 0(sp) #load stored priority jal ra, _restore_priority @@ -866,10 +822,8 @@ _vector_table: j _start_trap29 j _start_trap30 j _start_trap31 - .option pop "#, -#[cfg(feature="direct-vectoring")] r#" #this is required for the linking step, these symbols for in-use interrupts should always be overwritten by the user. .section .trap, "ax" diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml index f717140031f..c5549ea3ebc 100644 --- a/examples/.cargo/config.toml +++ b/examples/.cargo/config.toml @@ -27,5 +27,8 @@ rustflags = [ # "-C", "linker=rust-lld", ] +[env] +ESP_LOGLEVEL = "info" + [unstable] build-std = ["alloc", "core"] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 92b1d2187bf..7c27e52db10 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -23,9 +23,9 @@ embedded-hal-bus = "0.1.0" embedded-io-async = "0.6.1" esp-alloc = "0.3.0" esp-backtrace = { version = "0.11.1", features = ["exception-handler", "panic-handler", "println"] } -esp-hal = { version = "0.16.0", path = "../esp-hal" } +esp-hal = { version = "0.16.0", path = "../esp-hal", features = ["log"] } esp-hal-smartled = { version = "0.9.0", path = "../esp-hal-smartled", optional = true } -esp-println = "0.9.1" +esp-println = { version = "0.9.1", features = ["log"] } heapless = "0.8.0" hex-literal = "0.4.1" hmac = { version = "0.12.1", default-features = false } @@ -39,6 +39,7 @@ ssd1306 = "0.8.4" static_cell = { version = "2.0.0", features = ["nightly"] } usb-device = "0.3.2" usbd-serial = "0.2.1" +log = "0.4" [features] esp32 = ["esp-hal/esp32", "esp-backtrace/esp32", "esp-println/esp32", "esp-hal-smartled/esp32"] @@ -63,7 +64,6 @@ embassy-executor-interrupt = ["esp-hal/embassy-executor-interrupt"] embassy-time-timg0 = ["esp-hal/embassy-time-timg0"] embassy-generic-timers = ["embassy-time/generic-queue-8"] -direct-vectoring = ["esp-hal/direct-vectoring"] interrupt-preemption = ["esp-hal/interrupt-preemption"] opsram-2m = ["esp-hal/opsram-2m"] diff --git a/examples/src/bin/direct_vectoring.rs b/examples/src/bin/direct_vectoring.rs index ab09e5836f1..6fab39b033b 100644 --- a/examples/src/bin/direct_vectoring.rs +++ b/examples/src/bin/direct_vectoring.rs @@ -2,7 +2,6 @@ #![no_std] //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 -//% FEATURES: direct-vectoring use core::{arch::asm, cell::RefCell}; @@ -34,10 +33,10 @@ fn main() -> ! { critical_section::with(|cs| SWINT.borrow_ref_mut(cs).replace(sw_int)); unsafe { - interrupt::enable( + interrupt::enable_direct( Interrupt::FROM_CPU_INTR0, Priority::Priority3, - CpuInterrupt::Interrupt1, + CpuInterrupt::Interrupt20, ) .unwrap(); @@ -69,7 +68,7 @@ fn main() -> ! { } #[no_mangle] -fn cpu_int_1_handler() { +fn cpu_int_20_handler() { unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") } critical_section::with(|cs| { SWINT diff --git a/examples/src/bin/embassy_wait.rs b/examples/src/bin/embassy_wait.rs index 56a8c4c1151..9824007e9a0 100644 --- a/examples/src/bin/embassy_wait.rs +++ b/examples/src/bin/embassy_wait.rs @@ -33,7 +33,10 @@ async fn main(_spawner: Spawner) { embassy::init(&clocks, timg0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + #[cfg(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3"))] let mut input = io.pins.gpio0.into_pull_down_input(); + #[cfg(not(any(feature = "esp32", feature = "esp32s2", feature = "esp32s3")))] + let mut input = io.pins.gpio9.into_pull_down_input(); loop { esp_println::println!("Waiting...");