From db39d0197aa050450dfcc6406cd5ef8c2e7988cd Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Tue, 28 May 2024 19:58:48 +0100 Subject: [PATCH] Examples and test cleanup (#1590) * initial cull of examples * Remove direct vector example, replace with interrupt latency test * Remove clock monitor in favour of just a test --- examples/src/bin/aes.rs | 82 -- examples/src/bin/aes_dma.rs | 117 -- examples/src/bin/blinky.rs | 2 - examples/src/bin/blinky_erased_pins.rs | 3 - examples/src/bin/clock_monitor.rs | 60 - examples/src/bin/crc.rs | 96 -- examples/src/bin/direct_vectoring.rs | 91 -- examples/src/bin/ecc.rs | 1181 ----------------- .../src/bin/embassy_hello_world_systimer.rs | 50 - examples/src/bin/embassy_multiprio.rs | 3 +- examples/src/bin/embassy_systimer_delay.rs | 41 - examples/src/bin/gpio_interrupt.rs | 2 - examples/src/bin/hello_rgb.rs | 2 - examples/src/bin/interrupt_preemption.rs | 110 -- examples/src/bin/rsa.rs | 185 --- examples/src/bin/sha.rs | 75 -- examples/src/bin/spi_eh1_device_loopback.rs | 162 --- examples/src/bin/spi_eh1_loopback.rs | 108 -- examples/src/bin/systimer.rs | 2 - hil-test/Cargo.toml | 4 + hil-test/tests/interrupt.rs | 126 ++ 21 files changed, 131 insertions(+), 2371 deletions(-) delete mode 100644 examples/src/bin/aes.rs delete mode 100644 examples/src/bin/aes_dma.rs delete mode 100644 examples/src/bin/clock_monitor.rs delete mode 100644 examples/src/bin/crc.rs delete mode 100644 examples/src/bin/direct_vectoring.rs delete mode 100644 examples/src/bin/ecc.rs delete mode 100644 examples/src/bin/embassy_hello_world_systimer.rs delete mode 100644 examples/src/bin/embassy_systimer_delay.rs delete mode 100644 examples/src/bin/interrupt_preemption.rs delete mode 100644 examples/src/bin/rsa.rs delete mode 100644 examples/src/bin/sha.rs delete mode 100644 examples/src/bin/spi_eh1_device_loopback.rs delete mode 100644 examples/src/bin/spi_eh1_loopback.rs create mode 100644 hil-test/tests/interrupt.rs diff --git a/examples/src/bin/aes.rs b/examples/src/bin/aes.rs deleted file mode 100644 index 81fe8709ba6..00000000000 --- a/examples/src/bin/aes.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! Encrypt/Decrypt a message using AES - -//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use aes::{ - cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, - Aes128 as Aes128SW, -}; -use esp_backtrace as _; -use esp_hal::{ - aes::{Aes, Mode}, - peripherals::Peripherals, - prelude::*, -}; -use esp_println::println; -use examples::cycles; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - - let mut aes = Aes::new(peripherals.AES); - - let keytext = "SUp4SeCp@sSw0rd".as_bytes(); - let plaintext = "message".as_bytes(); - - // create an array with aes128 key size - let mut keybuf = [0_u8; 16]; - keybuf[..keytext.len()].copy_from_slice(keytext); - - // create an array with aes block size - let mut block_buf = [0_u8; 16]; - block_buf[..plaintext.len()].copy_from_slice(plaintext); - - let mut block = block_buf.clone(); - let pre_hw_encrypt = cycles(); - aes.process(&mut block, Mode::Encryption128, keybuf); - let post_hw_encrypt = cycles(); - println!( - "it took {} cycles for hw encrypt", - post_hw_encrypt - pre_hw_encrypt - ); - let hw_encrypted = block.clone(); - let pre_hw_decrypt = cycles(); - aes.process(&mut block, Mode::Decryption128, keybuf); - let post_hw_decrypt = cycles(); - println!( - "it took {} cycles for hw decrypt", - post_hw_decrypt - pre_hw_decrypt - ); - let hw_decrypted = block; - - let key = GenericArray::from(keybuf); - let mut block = GenericArray::from(block_buf); - let cipher = Aes128SW::new(&key); - let pre_sw_encrypt = cycles(); - cipher.encrypt_block(&mut block); - let post_sw_encrypt = cycles(); - println!( - "it took {} cycles for sw encrypt", - post_sw_encrypt - pre_sw_encrypt - ); - let sw_encrypted = block.clone(); - let pre_sw_decrypt = cycles(); - cipher.decrypt_block(&mut block); - let post_sw_decrypt = cycles(); - println!( - "it took {} cycles for sw decrypt", - post_sw_decrypt - pre_sw_decrypt - ); - let sw_decrypted = block; - - assert!(&sw_encrypted as &[u8] == &hw_encrypted); - assert!(&sw_decrypted as &[u8] == &hw_decrypted); - - println!("done"); - - loop {} -} diff --git a/examples/src/bin/aes_dma.rs b/examples/src/bin/aes_dma.rs deleted file mode 100644 index 387c1219d3f..00000000000 --- a/examples/src/bin/aes_dma.rs +++ /dev/null @@ -1,117 +0,0 @@ -//! Encrypt/Decrypt a message using AES - -//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3 - -#![no_std] -#![no_main] - -use aes::{ - cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, - Aes128 as Aes128SW, -}; -use esp_backtrace as _; -use esp_hal::{ - aes::{ - dma::{CipherMode, WithDmaAes}, - Aes, - Mode, - }, - dma::{Dma, DmaPriority}, - dma_buffers, - peripherals::Peripherals, - prelude::*, -}; -use esp_println::println; -use examples::cycles; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - - let dma = Dma::new(peripherals.DMA); - let dma_channel = dma.channel0; - - let (input, mut tx_descriptors, mut output, mut rx_descriptors) = dma_buffers!(16, 16); - - let mut aes = Aes::new(peripherals.AES).with_dma(dma_channel.configure( - false, - &mut tx_descriptors, - &mut rx_descriptors, - DmaPriority::Priority0, - )); - - let keytext = [1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; - input.copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - - let pre_hw_encrypt = cycles(); - let transfer = aes - .process( - &input, - &mut output, - Mode::Encryption128, - CipherMode::Ecb, - keytext, - ) - .unwrap(); - transfer.wait().unwrap(); - let post_hw_encrypt = cycles(); - println!( - "it took {} cycles for hw encrypt", - post_hw_encrypt - pre_hw_encrypt - ); - - let mut hw_encrypted = [0u8; 16]; - (&mut hw_encrypted[..]).copy_from_slice(output); - - input.copy_from_slice(output); - - let pre_hw_decrypt = cycles(); - let transfer = aes - .process( - &input, - &mut output, - Mode::Decryption128, - CipherMode::Ecb, - keytext, - ) - .unwrap(); - transfer.wait().unwrap(); - let post_hw_decrypt = cycles(); - println!( - "it took {} cycles for hw decrypt", - post_hw_decrypt - pre_hw_decrypt - ); - - let mut hw_decrypted = [0u8; 16]; - (&mut hw_decrypted[..]).copy_from_slice(output); - - // create an array with aes block size - let mut block_buf = [0_u8; 16]; - block_buf[..].copy_from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]); - - let key = GenericArray::from(keytext); - let mut block = GenericArray::from(block_buf); - let cipher = Aes128SW::new(&key); - let pre_sw_encrypt = cycles(); - cipher.encrypt_block(&mut block); - let post_sw_encrypt = cycles(); - println!( - "it took {} cycles for sw encrypt", - post_sw_encrypt - pre_sw_encrypt - ); - let sw_encrypted = block.clone(); - let pre_sw_decrypt = cycles(); - cipher.decrypt_block(&mut block); - let post_sw_decrypt = cycles(); - println!( - "it took {} cycles for sw decrypt", - post_sw_decrypt - pre_sw_decrypt - ); - let sw_decrypted = block.clone(); - - assert!(&sw_encrypted as &[u8] == &hw_encrypted); - assert!(&sw_decrypted as &[u8] == &hw_decrypted); - - println!("done"); - loop {} -} diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs index 7911d86585d..d7c8aca8ff0 100644 --- a/examples/src/bin/blinky.rs +++ b/examples/src/bin/blinky.rs @@ -27,8 +27,6 @@ fn main() -> ! { let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); let mut led = Output::new(io.pins.gpio0, Level::High); - // Initialize the Delay peripheral, and use it to toggle the LED state in a - // loop. let delay = Delay::new(&clocks); loop { diff --git a/examples/src/bin/blinky_erased_pins.rs b/examples/src/bin/blinky_erased_pins.rs index 8a9b377d29c..43c7995e562 100644 --- a/examples/src/bin/blinky_erased_pins.rs +++ b/examples/src/bin/blinky_erased_pins.rs @@ -41,11 +41,8 @@ fn main() -> ! { let button = AnyInput::new(button, Pull::Up); - // You can use `into` or `degrade`: let mut pins = [led1, led2, led3]; - // Initialize the `Delay` peripheral, and use it to toggle the LED state - // in a loop: let delay = Delay::new(&clocks); loop { diff --git a/examples/src/bin/clock_monitor.rs b/examples/src/bin/clock_monitor.rs deleted file mode 100644 index 3c080be4730..00000000000 --- a/examples/src/bin/clock_monitor.rs +++ /dev/null @@ -1,60 +0,0 @@ -//! This demos a simple monitor for the XTAL frequency, by relying on a special -//! feature of the TIMG0 (Timer Group 0). This feature counts the number of XTAL -//! clock cycles within a given number of RTC_SLOW_CLK cycles. - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use core::cell::RefCell; - -use critical_section::Mutex; -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - peripherals::Peripherals, - prelude::*, - rtc_cntl::Rtc, - system::SystemControl, -}; -use esp_println::println; - -static RTC: Mutex>> = Mutex::new(RefCell::new(None)); - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let mut rtc = Rtc::new(peripherals.LPWR, Some(interrupt_handler)); - rtc.rwdt.set_timeout(2000.millis()); - rtc.rwdt.listen(); - - println!( - "{: <10} XTAL frequency: {} MHz", - "[Expected]", - clocks.xtal_clock.to_MHz() - ); - - critical_section::with(|cs| RTC.borrow_ref_mut(cs).replace(rtc)); - - loop {} -} - -#[handler(priority = esp_hal::interrupt::Priority::min())] -fn interrupt_handler() { - critical_section::with(|cs| { - let mut rtc = RTC.borrow_ref_mut(cs); - let rtc = rtc.as_mut().unwrap(); - - println!( - "{: <10} XTAL frequency: {} MHz", - "[Monitor]", - rtc.estimate_xtal_frequency() - ); - - rtc.rwdt.clear_interrupt(); - }); -} diff --git a/examples/src/bin/crc.rs b/examples/src/bin/crc.rs deleted file mode 100644 index 9cd9727a99b..00000000000 --- a/examples/src/bin/crc.rs +++ /dev/null @@ -1,96 +0,0 @@ -//! This shows example usage of the CRC functions in ROM - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use core::fmt::Write; - -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - delay::Delay, - peripherals::Peripherals, - prelude::*, - rom::{crc, md5}, - system::SystemControl, - uart::Uart, -}; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let delay = Delay::new(&clocks); - - let mut uart0 = Uart::new(peripherals.UART0, &clocks); - - let data = "123456789"; - let sentence = "The quick brown fox jumps over a lazy dog"; - - writeln!( - uart0, - "Performing CRC calculations on test string \"{data}\"" - ) - .unwrap(); - - loop { - let crc_hdlc = crc::crc32_le(!0xffffffff, data.as_ref()); - let crc_bzip2 = crc::crc32_be(!0xffffffff, data.as_ref()); - let crc_mpeg2 = !crc::crc32_be(!0xffffffff, data.as_ref()); - let crc_cksum = crc::crc32_be(!0, data.as_ref()); - let crc_kermit = !crc::crc16_le(!0, data.as_ref()); - let crc_genibus = crc::crc16_be(!0xffff, data.as_ref()); - let crc_rohc = !crc::crc8_le(!0xff, data.as_ref()); - let crc_smbus = !crc::crc8_be(!0, data.as_ref()); - - assert_eq!(crc_hdlc, 0xcbf43926); - assert_eq!(crc_bzip2, 0xfc891918); - assert_eq!(crc_mpeg2, 0x0376e6e7); - assert_eq!(crc_cksum, 0x765e7680); - assert_eq!(crc_kermit, 0x2189); - assert_eq!(crc_genibus, 0xd64e); - assert_eq!(crc_rohc, 0xd0); - assert_eq!(crc_smbus, 0xf4); - - // Hash the sentence one word at a time to *really* test the context - // Use Peekable while iter_intersperse is unstable - let mut md5_ctx = md5::Context::new(); - let mut it = sentence.split_whitespace().peekable(); - while let Some(word) = it.next() { - md5_ctx.consume(word); - if it.peek().is_some() { - md5_ctx.consume(" "); - } - } - let md5_digest = md5_ctx.compute(); - - assert_eq!( - md5_digest, - md5::Digest([ - 0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5, - 0x5a, 0x95 - ]) - ); - - writeln!( - uart0, - "{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}", - crc_hdlc, - crc_bzip2, - crc_mpeg2, - crc_cksum, - crc_kermit, - crc_genibus, - crc_rohc, - crc_smbus, - md5_digest - ) - .unwrap(); - - delay.delay(1.secs()); - } -} diff --git a/examples/src/bin/direct_vectoring.rs b/examples/src/bin/direct_vectoring.rs deleted file mode 100644 index 3f2a5fd70a6..00000000000 --- a/examples/src/bin/direct_vectoring.rs +++ /dev/null @@ -1,91 +0,0 @@ -#![no_main] -#![no_std] - -//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 - -use core::{arch::asm, cell::RefCell}; - -use critical_section::Mutex; -use esp_backtrace as _; -use esp_hal::{ - interrupt::{self, CpuInterrupt, Priority}, - peripherals::{Interrupt, Peripherals}, - prelude::*, - system::{SoftwareInterrupt, SystemControl}, -}; - -static SWINT0: Mutex>>> = Mutex::new(RefCell::new(None)); - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - cfg_if::cfg_if! { - if #[cfg(any(feature = "esp32c6", feature = "esp32h2"))] { - let cpu_intr = &peripherals.INTPRI; - } else { - let cpu_intr = &peripherals.SYSTEM; - } - } - let sw0_trigger_addr = cpu_intr.cpu_intr_from_cpu_0() as *const _ as u32; - - let system = SystemControl::new(peripherals.SYSTEM); - let sw_int = system.software_interrupt_control; - - critical_section::with(|cs| { - SWINT0 - .borrow_ref_mut(cs) - .replace(sw_int.software_interrupt0) - }); - interrupt::enable_direct( - Interrupt::FROM_CPU_INTR0, - Priority::Priority3, - CpuInterrupt::Interrupt20, - ) - .unwrap(); - unsafe { - asm!( - " - csrrwi x0, 0x7e0, 1 #what to count, for cycles write 1 for instructions write 2 - csrrwi x0, 0x7e1, 0 #disable counter - csrrwi x0, 0x7e2, 0 #reset counter - " - ); - } - - // interrupt is raised from assembly for max timer granularity. - unsafe { - asm!( - " - li {bit}, 1 # Flip flag (bit 0) - csrrwi x0, 0x7e1, 1 # enable timer - sw {bit}, 0({addr}) # trigger FROM_CPU_INTR0 - ", - options(nostack), - addr = in(reg) sw0_trigger_addr, - bit = out(reg) _, - ) - } - esp_println::println!("Returned"); - - loop {} -} - -#[no_mangle] -fn interrupt20() { - unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") } - critical_section::with(|cs| { - SWINT0.borrow_ref(cs).as_ref().unwrap().reset(); - }); - - let mut perf_counter: u32 = 0; - unsafe { - asm!( - " - csrr {x}, 0x7e2 - ", - options(nostack), - x = inout(reg) perf_counter, - ) - }; - esp_println::println!("Performance counter:{}", perf_counter); -} diff --git a/examples/src/bin/ecc.rs b/examples/src/bin/ecc.rs deleted file mode 100644 index ab097aeadb9..00000000000 --- a/examples/src/bin/ecc.rs +++ /dev/null @@ -1,1181 +0,0 @@ -//! Demonstrates the use of the ECC peripheral and compares the speed of -//! hardware-accelerated and pure software ECC. - -//% CHIPS: esp32c2 esp32c6 esp32h2 - -#![no_std] -#![no_main] - -use core::ops::Mul; - -use crypto_bigint::{ - modular::runtime_mod::{DynResidue, DynResidueParams}, - Encoding, - U192, - U256, -}; -use elliptic_curve::sec1::ToEncodedPoint; -use esp_backtrace as _; -#[cfg(feature = "esp32h2")] -use esp_hal::ecc::WorkMode; -use esp_hal::{ - ecc::{Ecc, EllipticCurve, Error}, - peripherals::Peripherals, - prelude::*, - rng::Rng, - timer::systimer::SystemTimer, -}; -use esp_println::{print, println}; -use hex_literal::hex; - -struct TestParams<'a> { - prime_fields: &'a [&'a [u8]], - nb_loop_mul: usize, - #[cfg(feature = "esp32c2")] - nb_loop_inv: usize, -} - -const TEST_PARAMS_VECTOR: TestParams = TestParams { - prime_fields: &[ - &hex!("fffffffffffffffffffffffffffffffeffffffffffffffff"), - &hex!("ffffffff00000001000000000000000000000000ffffffffffffffffffffffff"), - ], - nb_loop_mul: 10, - #[cfg(feature = "esp32c2")] - nb_loop_inv: 20, -}; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - - let mut hw_ecc = Ecc::new(peripherals.ECC, None); - let mut rng = Rng::new(peripherals.RNG); - - println!("Beginning stress tests..."); - test_affine_point_multiplication(&mut hw_ecc, &mut rng); - test_affine_point_verification(&mut hw_ecc, &mut rng); - test_afine_point_verification_multiplication(&mut hw_ecc, &mut rng); - test_jacobian_point_multiplication(&mut hw_ecc, &mut rng); - test_jacobian_point_verification(&mut hw_ecc, &mut rng); - test_afine_point_verification_jacobian_multiplication(&mut hw_ecc, &mut rng); - #[cfg(feature = "esp32c2")] - { - test_finite_field_division(&mut hw_ecc, &mut rng); - } - #[cfg(feature = "esp32h2")] - { - test_mod_operations_256(&mut hw_ecc); - test_mod_operations_192(&mut hw_ecc); - test_point_addition_256(&mut hw_ecc); - test_point_addition_192(&mut hw_ecc); - } - println!("Finished stress tests!"); - - loop {} -} - -fn test_affine_point_multiplication(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning affine point multiplication tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 96]; - let (k, x) = t1.split_at_mut(prime_field.len()); - let (x, y) = x.split_at_mut(prime_field.len()); - let (y, _) = y.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - loop { - rng.read(k); - let is_zero = k.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - let curve = match prime_field.len() { - 24 => { - x.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P192 - } - 32 => { - x.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - ecc.affine_point_multiplication(curve, k, x, y) - .expect("Inputs data doesn't match the key length selected."); - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - - let t2 = &mut [0_u8; 64]; - - let (sw_x, sw_y) = t2.split_at_mut(prime_field.len()); - let (sw_y, _) = sw_y.split_at_mut(prime_field.len()); - - match prime_field.len() { - 24 => { - let sw_k = - p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - sw_x.copy_from_slice(q.x().unwrap().as_slice()); - sw_y.copy_from_slice(q.y().unwrap().as_slice()); - } - 32 => { - let sw_k = - p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - sw_x.copy_from_slice(q.x().unwrap().as_slice()); - sw_y.copy_from_slice(q.y().unwrap().as_slice()); - } - _ => unimplemented!(), - }; - - for (a, b) in x.iter().zip(sw_x) { - assert_eq!( - a, b, - "ECC failed during affine point multiplication with d_a = {:02X?} ({:02X?} != {:02X?})", - k, a, b, - ); - } - - for (a, b) in y.iter().zip(sw_y) { - assert_eq!( - a, b, - "ECC failed during affine point multiplication with d_a = {:02X?} ({:02X?} != {:02X?})", - k, a, b, - ); - } - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -fn test_affine_point_verification(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning affine point verification tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 96]; - let (k, x) = t1.split_at_mut(prime_field.len()); - let (x, y) = x.split_at_mut(prime_field.len()); - let (y, _) = y.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - loop { - rng.read(k); - let is_zero = k.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - - let curve = match prime_field.len() { - 24 => { - let sw_k = - p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - x.copy_from_slice(q.x().unwrap().as_slice()); - y.copy_from_slice(q.y().unwrap().as_slice()); - &EllipticCurve::P192 - } - 32 => { - let sw_k = - p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - x.copy_from_slice(q.x().unwrap().as_slice()); - y.copy_from_slice(q.y().unwrap().as_slice()); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - match ecc.affine_point_verification(&curve, x, y) { - Err(Error::SizeMismatchCurve) => { - assert!(false, "Inputs data doesn't match the key length selected.") - } - Err(Error::PointNotOnSelectedCurve) => assert!( - false, - "ECC failed while affine point verification with x = {:02X?} and y = {:02X?}.", - x, y, - ), - _ => {} - } - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -fn test_afine_point_verification_multiplication(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning affine point verification + multiplication tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 96]; - let (k, px) = t1.split_at_mut(prime_field.len()); - let (px, py) = px.split_at_mut(prime_field.len()); - let (py, _) = py.split_at_mut(prime_field.len()); - let mut delta_time = 0; - #[cfg(feature = "esp32h2")] - let qx = &mut [0u8; 8]; - #[cfg(feature = "esp32h2")] - let qy = &mut [0u8; 8]; - #[cfg(feature = "esp32h2")] - let qz = &mut [0u8; 8]; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - loop { - rng.read(k); - let is_zero = k.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - let curve = match prime_field.len() { - 24 => { - px.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - py.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P192 - } - 32 => { - px.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - py.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - #[cfg(not(feature = "esp32h2"))] - let result = ecc.affine_point_verification_multiplication(curve, k, px, py); - #[cfg(feature = "esp32h2")] - let result = ecc.affine_point_verification_multiplication(curve, k, px, py, qx, qy, qz); - match result { - Err(Error::SizeMismatchCurve) => assert!(false, "Inputs data doesn't match the key length selected."), - Err(Error::PointNotOnSelectedCurve) => assert!( - false, "ECC failed while affine point verification + multiplication with x = {:02X?} and y = {:02X?}.", - px, py, - ), - _ => {}, - } - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - - let t2 = &mut [0_u8; 64]; - - let (sw_x, sw_y) = t2.split_at_mut(prime_field.len()); - let (sw_y, _) = sw_y.split_at_mut(prime_field.len()); - - match prime_field.len() { - 24 => { - let sw_k = - p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - sw_x.copy_from_slice(q.x().unwrap().as_slice()); - sw_y.copy_from_slice(q.y().unwrap().as_slice()); - } - 32 => { - let sw_k = - p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - sw_x.copy_from_slice(q.x().unwrap().as_slice()); - sw_y.copy_from_slice(q.y().unwrap().as_slice()); - } - _ => unimplemented!(), - }; - - for (a, b) in px.iter().zip(sw_x) { - assert_eq!( - a, b, - "ECC failed during affine point verification + multiplication with d_a = {:02X?} ({:02X?} != {:02X?})", - k, a, b, - ); - } - - for (a, b) in py.iter().zip(sw_y) { - assert_eq!( - a, b, - "ECC failed during affine point verification + multiplication with d_a = {:02X?} ({:02X?} != {:02X?})", - k, a, b, - ); - } - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -fn test_jacobian_point_multiplication(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning jacobian point multiplication tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 96]; - let (k, x) = t1.split_at_mut(prime_field.len()); - let (x, y) = x.split_at_mut(prime_field.len()); - let (y, _) = y.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - let t2 = &mut [0_u8; 96]; - - let (sw_x, sw_y) = t2.split_at_mut(prime_field.len()); - let (sw_y, sw_k) = sw_y.split_at_mut(prime_field.len()); - let (sw_k, _) = sw_k.split_at_mut(prime_field.len()); - - loop { - rng.read(k); - let is_zero = k.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - sw_k.copy_from_slice(k); - let curve = match prime_field.len() { - 24 => { - x.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P192 - } - 32 => { - x.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - ecc.jacobian_point_multiplication(curve, k, x, y) - .expect("Inputs data doesn't match the key length selected."); - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - - match prime_field.len() { - 24 => { - let sw_k = p192::Scalar::from( - elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(), - ); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U192::from_be_slice(k), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - } - 32 => { - let sw_k = p256::Scalar::from( - elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(), - ); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U256::from_be_slice(k), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - } - _ => unimplemented!(), - }; - - for (a, b) in x.iter().zip(sw_x.iter()) { - assert_eq!( - a, b, - "ECC failed during jacobian point multiplication.\nX = {:02X?}\nX = {:02X?}", - x, sw_x, - ); - } - - for (a, b) in y.iter().zip(sw_y.iter()) { - assert_eq!( - a, b, - "ECC failed during jacobian point multiplication.\nY = {:02X?}\nY = {:02X?}", - y, sw_y, - ); - } - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -fn test_jacobian_point_verification(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning jacobian point verification tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 128]; - let (k, x) = t1.split_at_mut(prime_field.len()); - let (x, y) = x.split_at_mut(prime_field.len()); - let (y, z) = y.split_at_mut(prime_field.len()); - let (z, _) = z.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - loop { - rng.read(k); - rng.read(z); - let is_zero = k.iter().all(|&elt| elt == 0) || z.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b) - || z.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - - let curve = match prime_field.len() { - 24 => { - let sw_k = - p192::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U192::from_be_slice(z), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - &EllipticCurve::P192 - } - 32 => { - let sw_k = - p256::Scalar::from(elliptic_curve::ScalarPrimitive::from_slice(k).unwrap()); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U256::from_be_slice(z), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - match ecc.jacobian_point_verification(&curve, x, y, z) { - Err(Error::SizeMismatchCurve) => { - assert!(false, "Inputs data doesn't match the key length selected.") - } - Err(Error::PointNotOnSelectedCurve) => assert!( - false, - "ECC failed while base point verification with x = {:02X?} and y = {:02X?}.", - x, y, - ), - _ => {} - } - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -fn test_afine_point_verification_jacobian_multiplication( - ecc: &mut Ecc, - rng: &mut Rng, -) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning affine point verification + jacobian point multiplication tests over "); - match prime_field.len() { - 24 => print!("secp192r1..."), - _ => print!("secp256r1..."), - }; - let t1 = &mut [0_u8; 96]; - let (k, x) = t1.split_at_mut(prime_field.len()); - let (x, y) = x.split_at_mut(prime_field.len()); - let (y, _) = y.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_mul { - let t2 = &mut [0_u8; 96]; - - let (sw_x, sw_y) = t2.split_at_mut(prime_field.len()); - let (sw_y, sw_k) = sw_y.split_at_mut(prime_field.len()); - let (sw_k, _) = sw_k.split_at_mut(prime_field.len()); - - loop { - rng.read(k); - let is_zero = k.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - sw_k.copy_from_slice(k); - let curve = match prime_field.len() { - 24 => { - x.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p192::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P192 - } - 32 => { - x.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .x() - .unwrap(), - ); - y.copy_from_slice( - p256::AffinePoint::GENERATOR - .to_encoded_point(false) - .y() - .unwrap(), - ); - &EllipticCurve::P256 - } - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - match ecc.affine_point_verification_jacobian_multiplication(curve, k, x, y) { - Err(Error::SizeMismatchCurve) => assert!(false, "Inputs data doesn't match the key length selected."), - Err(Error::PointNotOnSelectedCurve) => assert!( - false, "ECC failed while affine point verification + multiplication with x = {:02X?} and y = {:02X?}.", - x, y, - ), - _ => {}, - } - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - - match prime_field.len() { - 24 => { - let sw_k = p192::Scalar::from( - elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(), - ); - let q = p192::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U192::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U192::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U192::from_be_slice(k), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - } - 32 => { - let sw_k = p256::Scalar::from( - elliptic_curve::ScalarPrimitive::from_slice(sw_k).unwrap(), - ); - let q = p256::AffinePoint::GENERATOR - .mul(sw_k) - .to_affine() - .to_encoded_point(false); - let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field)); - let x_affine = - DynResidue::new(&U256::from_be_slice(q.x().unwrap().as_slice()), modulus); - let y_affine = - DynResidue::new(&U256::from_be_slice(q.y().unwrap().as_slice()), modulus); - let z = DynResidue::new(&U256::from_be_slice(k), modulus); - let x_jacobian = x_affine * z * z; - let y_jacobian = y_affine * z * z * z; - sw_x.copy_from_slice(x_jacobian.retrieve().to_be_bytes().as_slice()); - sw_y.copy_from_slice(y_jacobian.retrieve().to_be_bytes().as_slice()); - } - _ => unimplemented!(), - }; - - for (a, b) in x.iter().zip(sw_x.iter()) { - assert_eq!( - a, b, - "ECC failed during affine point verification + jacobian point multiplication.\nX = {:02X?}\nX = {:02X?}", - x, sw_x, - ); - } - - for (a, b) in y.iter().zip(sw_y.iter()) { - assert_eq!( - a, b, - "ECC failed during affine point verification + jacobian point multiplication.\nY = {:02X?}\nY = {:02X?}", - y, sw_y, - ); - } - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_mul as u64) - ); - } -} - -#[cfg(feature = "esp32c2")] -fn test_finite_field_division(ecc: &mut Ecc, rng: &mut Rng) { - for &prime_field in TEST_PARAMS_VECTOR.prime_fields { - print!("Beginning finite field division tests over "); - match prime_field.len() { - 24 => print!("P-192..."), - 32 => print!("P-256..."), - _ => unimplemented!(), - }; - let t1 = &mut [0_u8; 64]; - let (k, y) = t1.split_at_mut(prime_field.len()); - let (y, _) = y.split_at_mut(prime_field.len()); - let mut delta_time = 0; - for _ in 0..TEST_PARAMS_VECTOR.nb_loop_inv { - loop { - rng.read(k); - rng.read(y); - let is_zero = k.iter().all(|&elt| elt == 0) || y.iter().all(|&elt| elt == 0); - let is_modulus = k.iter().zip(prime_field).all(|(&a, &b)| a == b) - || y.iter().zip(prime_field).all(|(&a, &b)| a == b); - if is_zero == false && is_modulus == false { - break; - } - } - let t2 = &mut [0_u8; 96]; - let (sw_y, sw_k) = t2.split_at_mut(prime_field.len()); - let (sw_k, sw_res) = sw_k.split_at_mut(prime_field.len()); - let (sw_res, _) = sw_res.split_at_mut(prime_field.len()); - sw_y.copy_from_slice(y); - sw_k.copy_from_slice(k); - let curve = match prime_field.len() { - 24 => &EllipticCurve::P192, - 32 => &EllipticCurve::P256, - _ => unimplemented!(), - }; - - let begin_time = SystemTimer::now(); - ecc.finite_field_division(curve, k, y) - .expect("Inputs data doesn't match the key length selected."); - let end_time = SystemTimer::now(); - delta_time += end_time - begin_time; - - match prime_field.len() { - 24 => { - let modulus = DynResidueParams::new(&U192::from_be_slice(prime_field)); - let sw_y = DynResidue::new(&U192::from_be_slice(sw_y), modulus); - let sw_k = DynResidue::new(&U192::from_be_slice(sw_k), modulus); - let sw_inv_k = sw_k.invert().0; - sw_res.copy_from_slice(sw_y.mul(&sw_inv_k).retrieve().to_be_bytes().as_slice()); - } - 32 => { - let modulus = DynResidueParams::new(&U256::from_be_slice(prime_field)); - let sw_y = DynResidue::new(&U256::from_be_slice(sw_y), modulus); - let sw_k = DynResidue::new(&U256::from_be_slice(sw_k), modulus); - let sw_inv_k = sw_k.invert().0; - sw_res.copy_from_slice(sw_y.mul(&sw_inv_k).retrieve().to_be_bytes().as_slice()); - } - _ => unimplemented!(), - }; - - for (a, b) in y.iter().zip(sw_res) { - assert_eq!( - a, b, - "ECC failed during finite field division with \np_y = {:02X?}\nk= {:02X?}", - sw_y, sw_k, - ); - } - } - println!( - "ok (it took {} cycles in average)", - delta_time / (TEST_PARAMS_VECTOR.nb_loop_inv as u64) - ); - } -} - -// All values are Little-Endian -#[cfg(feature = "esp32h2")] -fn test_point_addition_256(ecc: &mut Ecc) { - const ECC_256_X: [u8; 32] = [ - 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, - 0x77, 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, - 0x17, 0x6B, - ]; - - const ECC_256_Y: [u8; 32] = [ - 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB, 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, - 0x2B, 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E, 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, - 0xE3, 0x4F, - ]; - - const ECC_256_RES_X: [u8; 32] = [ - 0xf, 0xc7, 0xd6, 0x91, 0x83, 0x84, 0x7d, 0x1e, 0xcf, 0xdd, 0x61, 0x4f, 0x27, 0x42, 0x4b, - 0x80, 0x43, 0xde, 0xfc, 0xdc, 0x52, 0x7d, 0x0e, 0x57, 0xad, 0xb5, 0xd1, 0xac, 0x59, 0x8f, - 0x97, 0x9a, - ]; - - const ECC_256_RES_Y: [u8; 32] = [ - 0xd1, 0xf5, 0xd2, 0x90, 0x31, 0xbe, 0x59, 0xfd, 0xd0, 0x8b, 0x66, 0x88, 0x63, 0xc4, 0x7f, - 0xe7, 0x5f, 0x6d, 0x34, 0xe5, 0x38, 0x82, 0x33, 0x05, 0xf9, 0x6a, 0x78, 0x7f, 0x5e, 0x88, - 0x26, 0x41, - ]; - - const ECC_256_RES_Z: [u8; 32] = [ - 0xea, 0xa3, 0x7e, 0x6f, 0xd0, 0x80, 0x6c, 0x97, 0x9d, 0xbd, 0x62, 0xd6, 0xae, 0x66, 0x9c, - 0x57, 0x2c, 0x3c, 0x1f, 0xf8, 0x94, 0xd6, 0xcf, 0x1d, 0x37, 0xff, 0x34, 0xfc, 0xc5, 0x85, - 0xc6, 0x9f, - ]; - - let mut x_256 = ECC_256_X.clone(); - let mut y_256 = ECC_256_Y.clone(); - - let mut z: [u8; 32] = [0u8; 32]; - z[0] = 0x1; - - let mut x_256_1 = ECC_256_X.clone(); - let mut y_256_1 = ECC_256_Y.clone(); - - ecc.affine_point_addition( - &EllipticCurve::P256, - &mut x_256, - &mut y_256, - &mut x_256_1, - &mut y_256_1, - &mut z, - ) - .unwrap(); - - assert_eq!( - x_256_1, ECC_256_RES_X, - "ECC failed during affine_point_addition_X (256) ({:02X?} != {:02X?})", - x_256_1, ECC_256_RES_X - ); - assert_eq!( - y_256_1, ECC_256_RES_Y, - "ECC failed during affine_point_addition_Y (256) ({:02X?} != {:02X?})", - y_256_1, ECC_256_RES_Y - ); - assert_eq!( - z, ECC_256_RES_Z, - "ECC failed during affine_point_addition_Z (256) ({:02X?} != {:02X?})", - z, ECC_256_RES_Z - ); -} - -// All values are Little-Endian -#[cfg(feature = "esp32h2")] -fn test_point_addition_192(ecc: &mut Ecc) { - const ECC_192_X: [u8; 24] = [ - 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4, 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, - 0x7C, 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18, - ]; - - const ECC_192_Y: [u8; 24] = [ - 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73, 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, - 0x63, 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07, - ]; - - const ECC_192_RES_X: [u8; 24] = [ - 0x6, 0x6c, 0xd8, 0x6e, 0x9b, 0xef, 0x62, 0x7a, 0x54, 0xd3, 0x75, 0xfa, 0xdb, 0x36, 0x83, - 0xc1, 0x8f, 0x2b, 0xeb, 0xbd, 0x18, 0x1, 0xf, 0xe1, - ]; - - const ECC_192_RES_Y: [u8; 24] = [ - 0x42, 0xc0, 0x1d, 0x71, 0x0c, 0x1e, 0x4e, 0x29, 0x22, 0x69, 0x21, 0x5b, 0x05, 0x91, 0xea, - 0x60, 0xcf, 0x05, 0x07, 0xfd, 0x79, 0x29, 0x6c, 0x19, - ]; - - const ECC_192_RES_Z: [u8; 24] = [ - 0x22, 0x90, 0xf2, 0x3c, 0x42, 0xef, 0xf2, 0xe7, 0xaa, 0x9b, 0x49, 0xd6, 0xda, 0x23, 0x20, - 0xc6, 0xf0, 0xb4, 0x91, 0xff, 0x2b, 0x57, 0x32, 0xe, - ]; - - let mut x_192 = ECC_192_X.clone(); - let mut y_192 = ECC_192_Y.clone(); - let mut z: [u8; 24] = [0u8; 24]; - z[0] = 0x1; - - let mut x_192_1 = ECC_192_X.clone(); - let mut y_192_1 = ECC_192_Y.clone(); - - ecc.affine_point_addition( - &EllipticCurve::P192, - &mut x_192, - &mut y_192, - &mut x_192_1, - &mut y_192_1, - &mut z, - ) - .unwrap(); - - assert_eq!( - x_192_1, ECC_192_RES_X, - "ECC failed during affine_point_addition_X (192) ({:02X?} != {:02X?})", - x_192_1, ECC_192_RES_X - ); - assert_eq!( - y_192_1, ECC_192_RES_Y, - "ECC failed during affine_point_addition_Y (192) ({:02X?} != {:02X?})", - y_192_1, ECC_192_RES_Y - ); - assert_eq!( - z, ECC_192_RES_Z, - "ECC failed during affine_point_addition_Z (192) ({:02X?} != {:02X?})", - z, ECC_192_RES_Z - ); -} - -// All values are Little-Endian -#[cfg(feature = "esp32h2")] -fn test_mod_operations_256(ecc: &mut Ecc) { - const ECC_256_X: [u8; 32] = [ - 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, - 0x77, 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, - 0x17, 0x6B, - ]; - - const ECC_256_Y: [u8; 32] = [ - 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB, 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, - 0x2B, 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E, 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, - 0xE3, 0x4F, - ]; - - const ECC_256_NUM: [u8; 32] = [ - 0x20, 0x56, 0x14, 0xB6, 0xAF, 0x94, 0xA0, 0xB6, 0x0C, 0xDF, 0x13, 0x1A, 0xE6, 0xBF, 0x57, - 0x87, 0xF1, 0x02, 0x73, 0x96, 0x53, 0x1A, 0xBC, 0xA9, 0x0F, 0x5E, 0xA1, 0xFC, 0x0E, 0xFC, - 0x9D, 0x9B, - ]; - - const ECC_256_DEN: [u8; 32] = [ - 0x54, 0x3B, 0x11, 0x78, 0xC4, 0xCA, 0x52, 0xFD, 0xCC, 0x89, 0x51, 0x0F, 0xFE, 0x7D, 0x37, - 0x83, 0x81, 0xD5, 0x2E, 0x58, 0x42, 0xF9, 0x4F, 0x19, 0x9A, 0x79, 0x78, 0x98, 0xFA, 0x95, - 0x40, 0x2E, - ]; - - const ECC_256_ADD_RES: [u8; 32] = [ - 0x8B, 0x14, 0x58, 0x10, 0xAE, 0x79, 0x57, 0xC0, 0x6F, 0x92, 0x1C, 0x99, 0xD8, 0xB0, 0xD1, - 0xA2, 0x08, 0xDF, 0xB3, 0xDF, 0x2F, 0xD2, 0xA4, 0x87, 0xE3, 0xC1, 0x46, 0xDF, 0xD5, 0x14, - 0xFB, 0xBA, - ]; - - const ECC_256_SUB_RES: [u8; 32] = [ - 0xA1, 0x70, 0xD9, 0xA0, 0xDD, 0xF8, 0xEA, 0x28, 0xD2, 0xD4, 0xB9, 0xC2, 0x29, 0x4A, 0x35, - 0x4B, 0xDC, 0xA2, 0x94, 0xE7, 0x9A, 0xFB, 0xD4, 0x69, 0xAC, 0xC2, 0x11, 0xE3, 0x0F, 0x8F, - 0x34, 0x1B, - ]; - - const ECC_256_MUL_RES: [u8; 32] = [ - 0x18, 0x4D, 0xCE, 0xCC, 0x1A, 0xA8, 0xEC, 0x72, 0xD7, 0x31, 0xDA, 0x41, 0x8C, 0x75, 0x6B, - 0xF1, 0x2A, 0x2E, 0x5B, 0x53, 0x8D, 0xCA, 0x79, 0x61, 0x6B, 0x46, 0xF9, 0x2E, 0x27, 0xB5, - 0x43, 0x15, - ]; - - const ECC_256_INV_MUL_RES: [u8; 32] = [ - 0x33, 0xF3, 0x55, 0x3B, 0x46, 0x8A, 0x13, 0xC0, 0x1D, 0x7E, 0x41, 0xA6, 0xFF, 0x53, 0xFD, - 0x78, 0xD5, 0xC0, 0xE5, 0x9F, 0x78, 0xD1, 0x86, 0x66, 0x77, 0x3C, 0x6E, 0xEF, 0x58, 0xF6, - 0x29, 0x34, - ]; - - let mut x_256 = ECC_256_X.clone(); - let mut y_256 = ECC_256_Y.clone(); - - ecc.mod_operations( - &EllipticCurve::P256, - &mut x_256, - &mut y_256, - WorkMode::ModAdd, - ) - .unwrap(); - assert_eq!( - x_256, ECC_256_ADD_RES, - "ECC failed during add mod (256) operation ({:02X?} != {:02X?})", - x_256, ECC_256_ADD_RES, - ); - - let mut x_256 = ECC_256_X.clone(); - let mut y_256 = ECC_256_Y.clone(); - ecc.mod_operations( - &EllipticCurve::P256, - &mut x_256, - &mut y_256, - WorkMode::ModSub, - ) - .unwrap(); - assert_eq!( - x_256, ECC_256_SUB_RES, - "ECC failed during sub mod (256) operation ({:02X?} != {:02X?})", - x_256, ECC_256_SUB_RES, - ); - - let mut x_256 = ECC_256_X.clone(); - let mut y_256 = ECC_256_Y.clone(); - ecc.mod_operations( - &EllipticCurve::P256, - &mut x_256, - &mut y_256, - WorkMode::ModMulti, - ) - .unwrap(); - assert_eq!( - y_256, ECC_256_MUL_RES, - "ECC failed during mul mod (256) operation ({:02X?} != {:02X?})", - y_256, ECC_256_MUL_RES, - ); - - let mut x_256 = ECC_256_NUM.clone(); - let mut y_256 = ECC_256_DEN.clone(); - ecc.mod_operations( - &EllipticCurve::P256, - &mut x_256, - &mut y_256, - WorkMode::ModDiv, - ) - .unwrap(); - assert_eq!( - y_256, ECC_256_INV_MUL_RES, - "ECC failed during div mod (256) operation ({:02X?} != {:02X?})", - y_256, ECC_256_INV_MUL_RES, - ); - - println!("Mod operation (256) tests successful!"); -} - -// All values are Little-Endian -#[cfg(feature = "esp32h2")] -fn test_mod_operations_192(ecc: &mut Ecc) { - const ECC_192_X: [u8; 24] = [ - 0x1A, 0x80, 0xA1, 0x5F, 0x1F, 0xB7, 0x59, 0x1B, 0x9F, 0xD7, 0xFB, 0xAE, 0xA9, 0xF9, 0x1E, - 0xBA, 0x67, 0xAE, 0x57, 0xB7, 0x27, 0x80, 0x9E, 0x1A, - ]; - - const ECC_192_Y: [u8; 24] = [ - 0x59, 0xC6, 0x3D, 0xD3, 0xD7, 0xDF, 0xA3, 0x44, 0x7C, 0x75, 0x52, 0xB4, 0x42, 0xF3, 0xFC, - 0xA6, 0x0F, 0xA8, 0x8A, 0x8D, 0x1F, 0xA3, 0xDF, 0x54, - ]; - - const ECC_192_NUM: [u8; 24] = [ - 0xBA, 0x0F, 0x2C, 0xD8, 0xBE, 0xCC, 0x2D, 0xD3, 0xD5, 0x74, 0xBD, 0x8C, 0xF3, 0x3E, 0x3B, - 0x7A, 0xA4, 0xD0, 0x71, 0xEC, 0x85, 0xF6, 0x70, 0x00, - ]; - - const ECC_192_DEN: [u8; 24] = [ - 0x15, 0xF9, 0x20, 0xD8, 0x46, 0x5C, 0x03, 0x97, 0x4A, 0x10, 0xEF, 0x8A, 0xFB, 0x12, 0x2E, - 0x65, 0x6E, 0xD6, 0x79, 0x1E, 0x65, 0x6F, 0x3E, 0x64, - ]; - - const ECC_192_ADD_RES: [u8; 24] = [ - 0x73, 0x46, 0xDF, 0x32, 0xF7, 0x96, 0xFD, 0x5F, 0x1B, 0x4D, 0x4E, 0x63, 0xEC, 0xEC, 0x1B, - 0x61, 0x77, 0x56, 0xE2, 0x44, 0x47, 0x23, 0x7E, 0x6F, - ]; - - const ECC_192_SUB_RES: [u8; 24] = [ - 0xF2, 0xE1, 0x35, 0x41, 0xF9, 0xA0, 0x21, 0xEB, 0x58, 0x5A, 0x88, 0x94, 0x66, 0x06, 0x22, - 0x13, 0x58, 0x06, 0xCD, 0x29, 0x08, 0xDD, 0xBE, 0xC5, - ]; - - const ECC_192_MUL_RES: [u8; 24] = [ - 0xB5, 0xB9, 0xFF, 0xBC, 0x52, 0xC8, 0xB8, 0x36, 0x8C, 0xFB, 0xA5, 0xCE, 0x1E, 0x7B, 0xE6, - 0xF3, 0x8F, 0x79, 0x71, 0xCF, 0xD6, 0xF3, 0x41, 0xE6, - ]; - - const ECC_192_INV_MUL_RES: [u8; 24] = [ - 0x6B, 0xB3, 0x6B, 0x2B, 0x56, 0x6A, 0xE5, 0xF7, 0x75, 0x82, 0xF0, 0xCC, 0x93, 0x63, 0x40, - 0xF8, 0xEF, 0x35, 0x2A, 0xAF, 0xBD, 0x56, 0xE9, 0x29, - ]; - - let mut x_192 = ECC_192_X.clone(); - let mut y_192 = ECC_192_Y.clone(); - - ecc.mod_operations( - &EllipticCurve::P192, - &mut x_192, - &mut y_192, - WorkMode::ModAdd, - ) - .unwrap(); - assert_eq!( - x_192, ECC_192_ADD_RES, - "ECC failed during add mod (192) operation ({:02X?} != {:02X?})", - x_192, ECC_192_ADD_RES, - ); - - let mut x_192 = ECC_192_X.clone(); - let mut y_192 = ECC_192_Y.clone(); - ecc.mod_operations( - &EllipticCurve::P192, - &mut x_192, - &mut y_192, - WorkMode::ModSub, - ) - .unwrap(); - assert_eq!( - x_192, ECC_192_SUB_RES, - "ECC failed during sub mod (192) operation ({:02X?} != {:02X?})", - x_192, ECC_192_SUB_RES, - ); - - let mut x_192 = ECC_192_X.clone(); - let mut y_192 = ECC_192_Y.clone(); - ecc.mod_operations( - &EllipticCurve::P192, - &mut x_192, - &mut y_192, - WorkMode::ModMulti, - ) - .unwrap(); - assert_eq!( - y_192, ECC_192_MUL_RES, - "ECC failed during mul mod (192) operation ({:02X?} != {:02X?})", - y_192, ECC_192_MUL_RES, - ); - - let mut x_192 = ECC_192_NUM.clone(); - let mut y_192 = ECC_192_DEN.clone(); - ecc.mod_operations( - &EllipticCurve::P192, - &mut x_192, - &mut y_192, - WorkMode::ModDiv, - ) - .unwrap(); - assert_eq!( - y_192, ECC_192_INV_MUL_RES, - "ECC failed during div mod (192) operation ({:02X?} != {:02X?})", - y_192, ECC_192_INV_MUL_RES, - ); - - println!("Mod operation (192) tests successful!"); -} diff --git a/examples/src/bin/embassy_hello_world_systimer.rs b/examples/src/bin/embassy_hello_world_systimer.rs deleted file mode 100644 index 80636d749fc..00000000000 --- a/examples/src/bin/embassy_hello_world_systimer.rs +++ /dev/null @@ -1,50 +0,0 @@ -//! embassy hello world systimer -//! -//! This is an example of running the embassy executor with multiple tasks -//! concurrently using the systimer time driver. -//! -//! It's not supported on ESP32, on ESP32-S2 the frequency of the systimer is different (so it's left out here) - -//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s3 -//% FEATURES: embassy embassy-time-systick-16mhz embassy-generic-timers - -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::{Duration, Timer}; -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - embassy, - peripherals::Peripherals, - prelude::*, - system::SystemControl, - timer::systimer::SystemTimer, -}; - -#[embassy_executor::task] -async fn run() { - loop { - esp_println::println!("Hello world from embassy using esp-hal-async!"); - Timer::after(Duration::from_millis(1_000)).await; - } -} - -#[main] -async fn main(spawner: Spawner) { - esp_println::println!("Init!"); - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let systimer = SystemTimer::new_async(peripherals.SYSTIMER); - embassy::init(&clocks, systimer); - - spawner.spawn(run()).ok(); - - loop { - esp_println::println!("Bing!"); - Timer::after(Duration::from_millis(5_000)).await; - } -} diff --git a/examples/src/bin/embassy_multiprio.rs b/examples/src/bin/embassy_multiprio.rs index 9bc6d93a885..4a775a429b3 100644 --- a/examples/src/bin/embassy_multiprio.rs +++ b/examples/src/bin/embassy_multiprio.rs @@ -11,8 +11,7 @@ //! demonstrates that this task will continue to run even while the low //! priority blocking task is running. -// HINT: At first it looks a bit suspicious that we need *two* executor features enabled here but that's because we are really using -// both together. The thread-executor is created by the `#[main]` macro and is used to spawn `low_prio_async` and `low_prio_blocking`. +// The thread-executor is created by the `#[main]` macro and is used to spawn `low_prio_async` and `low_prio_blocking`. // The interrupt-executor is created in `main` and is used to spawn `high_prio`. //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 diff --git a/examples/src/bin/embassy_systimer_delay.rs b/examples/src/bin/embassy_systimer_delay.rs deleted file mode 100644 index 3f9ebf3a457..00000000000 --- a/examples/src/bin/embassy_systimer_delay.rs +++ /dev/null @@ -1,41 +0,0 @@ -//! embassy systimer delay -//! -//! This is an example of using the `DelayNs` trait implementation - -//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embassy embassy-time-timg0 embassy-generic-timers async - -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embedded_hal_async::delay::DelayNs; -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - embassy, - peripherals::Peripherals, - prelude::*, - system::SystemControl, - timer::{systimer::SystemTimer, timg::TimerGroup}, -}; - -#[main] -async fn main(_spawner: Spawner) { - esp_println::println!("Init!"); - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let timg0 = TimerGroup::new_async(peripherals.TIMG0, &clocks); - embassy::init(&clocks, timg0); - - let mut alarm0 = SystemTimer::new_async(peripherals.SYSTIMER) - .alarm0 - .into_periodic(); - - loop { - esp_println::println!("Bing!"); - alarm0.delay_ms(1000).await; - } -} diff --git a/examples/src/bin/gpio_interrupt.rs b/examples/src/bin/gpio_interrupt.rs index b98c5aab10b..ecf16bb22f1 100644 --- a/examples/src/bin/gpio_interrupt.rs +++ b/examples/src/bin/gpio_interrupt.rs @@ -51,8 +51,6 @@ fn main() -> ! { }); led.set_high(); - // Initialize the Delay peripheral, and use it to toggle the LED state in a - // loop. let delay = Delay::new(&clocks); loop { diff --git a/examples/src/bin/hello_rgb.rs b/examples/src/bin/hello_rgb.rs index db3e019c6f9..4ba2a442f45 100644 --- a/examples/src/bin/hello_rgb.rs +++ b/examples/src/bin/hello_rgb.rs @@ -66,8 +66,6 @@ fn main() -> ! { let rmt_buffer = smartLedBuffer!(1); let mut led = SmartLedsAdapter::new(rmt.channel0, led_pin, rmt_buffer, &clocks); - // Initialize the Delay peripheral, and use it to toggle the LED state in a - // loop. let delay = Delay::new(&clocks); let mut color = Hsv { diff --git a/examples/src/bin/interrupt_preemption.rs b/examples/src/bin/interrupt_preemption.rs deleted file mode 100644 index a96d9aad248..00000000000 --- a/examples/src/bin/interrupt_preemption.rs +++ /dev/null @@ -1,110 +0,0 @@ -//! Interrupt Preemption -//! -//! An example of how an interrupt can be preempted by another with higher -//! priority. Should show higher-numbered software interrupts happening during -//! the handling of lower-numbered ones. - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use core::cell::RefCell; - -use critical_section::Mutex; -use esp_backtrace as _; -use esp_hal::{ - peripherals::Peripherals, - prelude::*, - system::{SoftwareInterrupt, SystemControl}, -}; - -static SWINT0: Mutex>>> = Mutex::new(RefCell::new(None)); -static SWINT1: Mutex>>> = Mutex::new(RefCell::new(None)); -static SWINT2: Mutex>>> = Mutex::new(RefCell::new(None)); -static SWINT3: Mutex>>> = Mutex::new(RefCell::new(None)); - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let mut sw_int = system.software_interrupt_control; - - critical_section::with(|cs| { - sw_int - .software_interrupt0 - .set_interrupt_handler(swint0_handler); - SWINT0 - .borrow_ref_mut(cs) - .replace(sw_int.software_interrupt0); - - sw_int - .software_interrupt1 - .set_interrupt_handler(swint1_handler); - SWINT1 - .borrow_ref_mut(cs) - .replace(sw_int.software_interrupt1); - - sw_int - .software_interrupt2 - .set_interrupt_handler(swint2_handler); - SWINT2 - .borrow_ref_mut(cs) - .replace(sw_int.software_interrupt2); - - sw_int - .software_interrupt3 - .set_interrupt_handler(swint3_handler); - SWINT3 - .borrow_ref_mut(cs) - .replace(sw_int.software_interrupt3); - }); - - // Raise mid priority interrupt. - // - // The handler raises one interrupt at lower priority, one at same and one at - // higher. We expect to see the higher priority served immeiately before - // exiting the handler Once the handler is exited we expect to see same - // priority and low priority interrupts served in that order. - critical_section::with(|cs| { - SWINT1.borrow_ref(cs).as_ref().unwrap().raise(); - }); - - loop {} -} - -#[handler(priority = esp_hal::interrupt::Priority::Priority1)] -fn swint0_handler() { - esp_println::println!("SW interrupt0"); - critical_section::with(|cs| { - SWINT0.borrow_ref(cs).as_ref().unwrap().reset(); - }); -} - -#[handler(priority = esp_hal::interrupt::Priority::Priority2)] -fn swint1_handler() { - esp_println::println!("SW interrupt1 entry"); - critical_section::with(|cs| { - SWINT1.borrow_ref(cs).as_ref().unwrap().reset(); - SWINT2.borrow_ref(cs).as_ref().unwrap().raise(); // raise interrupt at same priority - SWINT3.borrow_ref(cs).as_ref().unwrap().raise(); // raise interrupt at higher priority - SWINT0.borrow_ref(cs).as_ref().unwrap().raise(); // raise interrupt at lower priority - }); - esp_println::println!("SW interrupt1 exit"); -} - -#[handler(priority = esp_hal::interrupt::Priority::Priority2)] -fn swint2_handler() { - esp_println::println!("SW interrupt2"); - critical_section::with(|cs| { - SWINT2.borrow_ref(cs).as_ref().unwrap().reset(); - }); -} - -#[handler(priority = esp_hal::interrupt::Priority::Priority3)] -fn swint3_handler() { - esp_println::println!("SW interrupt3"); - critical_section::with(|cs| { - SWINT3.borrow_ref(cs).as_ref().unwrap().reset(); - }); -} diff --git a/examples/src/bin/rsa.rs b/examples/src/bin/rsa.rs deleted file mode 100644 index c0ddcbcc376..00000000000 --- a/examples/src/bin/rsa.rs +++ /dev/null @@ -1,185 +0,0 @@ -//! Demonstrates the use of the RSA peripheral and compares the speed of -//! multiple arithmetic operations. - -//% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use crypto_bigint::{ - modular::runtime_mod::{DynResidue, DynResidueParams}, - Uint, - U1024, - U512, -}; -use esp_backtrace as _; -use esp_hal::{ - peripherals::Peripherals, - prelude::*, - rsa::{ - operand_sizes, - Rsa, - RsaModularExponentiation, - RsaModularMultiplication, - RsaMultiplication, - }, -}; -use esp_println::println; -use examples::cycles; - -const BIGNUM_1: U512 = Uint::from_be_hex( - "c7f61058f96db3bd87dbab08ab03b4f7f2f864eac249144adea6a65f97803b719d8ca980b7b3c0389c1c7c6\ - 7dc353c5e0ec11f5fc8ce7f6073796cc8f73fa878", -); -const BIGNUM_2: U512 = Uint::from_be_hex( - "1763db3344e97be15d04de4868badb12a38046bb793f7630d87cf100aa1c759afac15a01f3c4c83ec2d2f66\ - 6bd22f71c3c1f075ec0e2cb0cb29994d091b73f51", -); -const BIGNUM_3: U512 = Uint::from_be_hex( - "6b6bb3d2b6cbeb45a769eaa0384e611e1b89b0c9b45a045aca1c5fd6e8785b38df7118cf5dd45b9b63d293b\ - 67aeafa9ba25feb8712f188cb139b7d9b9af1c361", -); - -const fn compute_r(modulus: &U512) -> U512 { - let mut d = [0_u32; U512::LIMBS * 2 + 1]; - d[d.len() - 1] = 1; - let d = Uint::from_words(d); - d.const_rem(&modulus.resize()).0.resize() -} - -const fn compute_mprime(modulus: &U512) -> u32 { - let m_inv = modulus.inv_mod2k(32).to_words()[0]; - (-1 * m_inv as i64 % 4294967296) as u32 -} - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - - let mut rsa = Rsa::new(peripherals.RSA, None); - nb::block!(rsa.ready()).unwrap(); - - mod_exp_example(&mut rsa); - mod_multi_example(&mut rsa); - multiplication_example(&mut rsa); - - loop {} -} - -fn mod_multi_example(rsa: &mut Rsa) { - let mut outbuf = [0_u32; U512::LIMBS]; - let mut mod_multi = RsaModularMultiplication::::new( - rsa, - #[cfg(not(feature = "esp32"))] - BIGNUM_1.as_words(), - #[cfg(not(feature = "esp32"))] - BIGNUM_2.as_words(), - BIGNUM_3.as_words(), - compute_mprime(&BIGNUM_3), - ); - let r = compute_r(&BIGNUM_3); - let pre_hw_modmul = cycles(); - #[cfg(feature = "esp32")] - { - mod_multi.start_step1(BIGNUM_1.as_words(), r.as_words()); - mod_multi.start_step2(BIGNUM_2.as_words()); - } - #[cfg(not(feature = "esp32"))] - { - mod_multi.start_modular_multiplication(r.as_words()); - } - mod_multi.read_results(&mut outbuf); - let post_hw_modmul = cycles(); - println!( - "it took {} cycles for hw modular multiplication", - post_hw_modmul - pre_hw_modmul - ); - - let residue_params = DynResidueParams::new(&BIGNUM_3); - let residue_num1 = DynResidue::new(&BIGNUM_1, residue_params); - let residue_num2 = DynResidue::new(&BIGNUM_2, residue_params); - let pre_sw_exp = cycles(); - let sw_out = residue_num1.mul(&residue_num2); - let post_sw_exp = cycles(); - println!( - "it took {} cycles for sw modular multiplication", - post_sw_exp - pre_sw_exp - ); - assert_eq!(U512::from_words(outbuf), sw_out.retrieve()); - println!("modular multiplication done"); -} - -fn mod_exp_example(rsa: &mut Rsa) { - #[cfg(not(feature = "esp32"))] - { - rsa.enable_disable_constant_time_acceleration(true); - rsa.enable_disable_search_acceleration(true); - } - - let mut outbuf = [0_u32; U512::LIMBS]; - let mut mod_exp = RsaModularExponentiation::::new( - rsa, - BIGNUM_2.as_words(), - BIGNUM_3.as_words(), - compute_mprime(&BIGNUM_3), - ); - let r = compute_r(&BIGNUM_3); - let base = &BIGNUM_1.as_words(); - let pre_hw_exp = cycles(); - mod_exp.start_exponentiation(&base, r.as_words()); - mod_exp.read_results(&mut outbuf); - let post_hw_exp = cycles(); - println!( - "it took {} cycles for hw modular exponentiation", - post_hw_exp - pre_hw_exp - ); - let residue_params = DynResidueParams::new(&BIGNUM_3); - let residue = DynResidue::new(&BIGNUM_1, residue_params); - let pre_sw_exp = cycles(); - let sw_out = residue.pow(&BIGNUM_2); - let post_sw_exp = cycles(); - println!( - "it took {} cycles for sw modular exponentiation", - post_sw_exp - pre_sw_exp - ); - assert_eq!(U512::from_words(outbuf), sw_out.retrieve()); - println!("modular exponentiation done"); -} - -fn multiplication_example(rsa: &mut Rsa) { - let mut outbuf = [0_u32; U1024::LIMBS]; - - let operand_a = BIGNUM_1.as_words(); - let operand_b = BIGNUM_2.as_words(); - - let pre_hw_mul = cycles(); - - #[cfg(feature = "esp32")] - { - let mut rsamulti = RsaMultiplication::::new(rsa); - rsamulti.start_multiplication(operand_a, operand_b); - rsamulti.read_results(&mut outbuf); - } - #[cfg(not(feature = "esp32"))] - { - let mut rsamulti = - RsaMultiplication::::new(rsa, operand_a); - rsamulti.start_multiplication(operand_b); - rsamulti.read_results(&mut outbuf); - } - - let post_hw_mul = cycles(); - println!( - "it took {} cycles for hw multiplication", - post_hw_mul - pre_hw_mul - ); - let pre_sw_mul = cycles(); - let sw_out = BIGNUM_1.mul_wide(&BIGNUM_2); - let post_sw_mul = cycles(); - println!( - "it took {} cycles for sw multiplication", - post_sw_mul - pre_sw_mul - ); - assert_eq!(U1024::from_words(outbuf), sw_out.1.concat(&sw_out.0)); - println!("multiplication done"); -} diff --git a/examples/src/bin/sha.rs b/examples/src/bin/sha.rs deleted file mode 100644 index f9ed621bf4a..00000000000 --- a/examples/src/bin/sha.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Demonstrates the use of the SHA peripheral and compares the speed of -//! hardware-accelerated and pure software hashing. - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 - -#![no_std] -#![no_main] - -use esp_backtrace as _; -use esp_hal::{ - peripherals::Peripherals, - prelude::*, - sha::{Sha, ShaMode}, -}; -use esp_println::println; -use examples::cycles; -use nb::block; -use sha2::{Digest, Sha256}; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - - let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); - let mut remaining = source_data; - #[cfg(not(feature = "esp32"))] - let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256, None); - #[cfg(feature = "esp32")] - let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256); - - // Short hashes can be created by decreasing the output buffer to the desired - // length - let mut output = [0u8; 32]; - - let pre_calc = cycles(); - // The hardware implementation takes a subslice of the input, and returns the - // unprocessed parts The unprocessed parts can be input in the next - // iteration, you can always add more data until finish() is called. After - // finish() is called update()'s will contribute to a new hash which - // can be extracted again with finish(). - - while remaining.len() > 0 { - // Can add println to view progress, however println takes a few orders of - // magnitude longer than the Sha function itself so not useful for - // comparing processing time println!("Remaining len: {}", - // remaining.len()); - - // All the HW Sha functions are infallible so unwrap is fine to use if you use - // block! - remaining = block!(hasher.update(remaining)).unwrap(); - } - - // Finish can be called as many times as desired to get mutliple copies of the - // output. - block!(hasher.finish(output.as_mut_slice())).unwrap(); - - let post_calc = cycles(); - let hw_time = post_calc - pre_calc; - println!("Took {} cycles", hw_time); - println!("SHA256 Hash output {:02x?}", output); - - let pre_calc = cycles(); - let mut hasher = Sha256::new(); - hasher.update(source_data); - let soft_result = hasher.finalize(); - let post_calc = cycles(); - let soft_time = post_calc - pre_calc; - println!("Took {} cycles", soft_time); - println!("SHA256 Hash output {:02x?}", soft_result); - - assert_eq!(output, soft_result[..]); - println!("HW SHA is {}x faster", soft_time / hw_time); - - loop {} -} diff --git a/examples/src/bin/spi_eh1_device_loopback.rs b/examples/src/bin/spi_eh1_device_loopback.rs deleted file mode 100644 index f590ecd709f..00000000000 --- a/examples/src/bin/spi_eh1_device_loopback.rs +++ /dev/null @@ -1,162 +0,0 @@ -//! SPI loopback test -//! -//! Folowing pins are used: -//! SCLK GPIO0 -//! MISO GPIO2 -//! MOSI GPIO4 -//! CS 1 GPIO5 -//! CS 2 GPIO6 -//! CS 3 GPIO7 -//! -//! Folowing pins are used for ESP32: -//! SCLK GPIO0 -//! MISO GPIO2 -//! MOSI GPIO4 -//! CS 1 GPIO5 -//! CS 2 GPIO13 -//! CS 3 GPIO14 -//! -//! Depending on your target and the board you are using you have to change the -//! pins. -//! -//! This example transfers data via SPI. -//! Connect MISO and MOSI pins to see the outgoing data is read as incoming -//! data. - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embedded-hal - -#![no_std] -#![no_main] - -use core::cell::RefCell; - -use embedded_hal::spi::SpiDevice; -use embedded_hal_bus::spi::RefCellDevice; -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - delay::Delay, - gpio::{self, Io, Level, Output}, - peripherals::Peripherals, - prelude::*, - spi::{master::Spi, SpiMode}, - system::SystemControl, -}; -use esp_println::{print, println}; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let sclk = io.pins.gpio0; - let miso = io.pins.gpio2; - let mosi = io.pins.gpio4; - - let spi_bus = Spi::new(peripherals.SPI2, 1000.kHz(), SpiMode::Mode0, &clocks).with_pins( - Some(sclk), - Some(mosi), - Some(miso), - gpio::NO_PIN, - ); - let spi_bus = RefCell::new(spi_bus); - let mut spi_device_1 = - RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio5, Level::Low)); - - cfg_if::cfg_if! { - if #[cfg(feature = "esp32")] { - let mut spi_device_2 = - RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio13, Level::Low)); - let mut spi_device_3 = - RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio14, Level::Low)); - } else { - let mut spi_device_2 = - RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio6, Level::Low)); - let mut spi_device_3 = - RefCellDevice::new_no_delay(&spi_bus, Output::new(io.pins.gpio7, Level::Low)); - } - } - - let delay = Delay::new(&clocks); - println!("=== SPI example with embedded-hal-1 traits ==="); - - loop { - // --- Symmetric transfer (Read as much as we write) --- - print!("Starting symmetric transfer..."); - let write = [0xde, 0xad, 0xbe, 0xef]; - let mut read: [u8; 4] = [0x00u8; 4]; - - spi_device_1.transfer(&mut read[..], &write[..]).unwrap(); - assert_eq!(write, read); - spi_device_2.transfer(&mut read[..], &write[..]).unwrap(); - spi_device_3.transfer(&mut read[..], &write[..]).unwrap(); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Asymmetric transfer (Read more than we write) --- - print!("Starting asymetric transfer (read > write)..."); - let mut read: [u8; 4] = [0x00; 4]; - - spi_device_1 - .transfer(&mut read[0..2], &write[..]) - .expect("Asymmetric transfer failed"); - assert_eq!(write[0], read[0]); - assert_eq!(read[2], 0x00u8); - spi_device_2 - .transfer(&mut read[0..2], &write[..]) - .expect("Asymmetric transfer failed"); - spi_device_3 - .transfer(&mut read[0..2], &write[..]) - .expect("Asymmetric transfer failed"); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Symmetric transfer with huge buffer --- - // Only your RAM is the limit! - print!("Starting huge transfer..."); - let mut write = [0x55u8; 4096]; - for byte in 0..write.len() { - write[byte] = byte as u8; - } - let mut read = [0x00u8; 4096]; - - spi_device_1 - .transfer(&mut read[..], &write[..]) - .expect("Huge transfer failed"); - assert_eq!(write, read); - spi_device_2 - .transfer(&mut read[..], &write[..]) - .expect("Huge transfer failed"); - spi_device_3 - .transfer(&mut read[..], &write[..]) - .expect("Huge transfer failed"); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Symmetric transfer with huge buffer in-place (No additional allocation - // needed) --- - print!("Starting huge transfer (in-place)..."); - let mut write = [0x55u8; 4096]; - for byte in 0..write.len() { - write[byte] = byte as u8; - } - - spi_device_1 - .transfer_in_place(&mut write[..]) - .expect("Huge transfer failed"); - for byte in 0..write.len() { - assert_eq!(write[byte], byte as u8); - } - spi_device_2 - .transfer_in_place(&mut write[..]) - .expect("Huge transfer failed"); - spi_device_3 - .transfer_in_place(&mut write[..]) - .expect("Huge transfer failed"); - println!(" SUCCESS"); - delay.delay_millis(250); - } -} diff --git a/examples/src/bin/spi_eh1_loopback.rs b/examples/src/bin/spi_eh1_loopback.rs deleted file mode 100644 index 45a4ea71ce7..00000000000 --- a/examples/src/bin/spi_eh1_loopback.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! SPI loopback test -//! -//! Folowing pins are used: -//! SCLK GPIO0 -//! MISO GPIO2 -//! MOSI GPIO4 -//! CS GPIO5 -//! -//! Depending on your target and the board you are using you have to change the -//! pins. -//! -//! This example transfers data via SPI. -//! Connect MISO and MOSI pins to see the outgoing data is read as incoming -//! data. - -//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 -//% FEATURES: embedded-hal - -#![no_std] -#![no_main] - -use embedded_hal::spi::SpiBus; -use esp_backtrace as _; -use esp_hal::{ - clock::ClockControl, - delay::Delay, - gpio::Io, - peripherals::Peripherals, - prelude::*, - spi::{master::Spi, SpiMode}, - system::SystemControl, -}; -use esp_println::{print, println}; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let system = SystemControl::new(peripherals.SYSTEM); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - let io = Io::new(peripherals.GPIO, peripherals.IO_MUX); - let sclk = io.pins.gpio0; - let miso = io.pins.gpio2; - let mosi = io.pins.gpio4; - let cs = io.pins.gpio5; - - let mut spi = Spi::new(peripherals.SPI2, 1000.kHz(), SpiMode::Mode0, &clocks).with_pins( - Some(sclk), - Some(mosi), - Some(miso), - Some(cs), - ); - - let delay = Delay::new(&clocks); - println!("=== SPI example with embedded-hal-1 traits ==="); - - loop { - // --- Symmetric transfer (Read as much as we write) --- - print!("Starting symmetric transfer..."); - let write = [0xde, 0xad, 0xbe, 0xef]; - let mut read: [u8; 4] = [0x00u8; 4]; - - SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Symmetric transfer failed"); - assert_eq!(write, read); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Asymmetric transfer (Read more than we write) --- - print!("Starting asymetric transfer (read > write)..."); - let mut read: [u8; 4] = [0x00; 4]; - - SpiBus::transfer(&mut spi, &mut read[0..2], &write[..]) - .expect("Asymmetric transfer failed"); - assert_eq!(write[0], read[0]); - assert_eq!(read[2], 0x00u8); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Symmetric transfer with huge buffer --- - // Only your RAM is the limit! - print!("Starting huge transfer..."); - let mut write = [0x55u8; 4096]; - for byte in 0..write.len() { - write[byte] = byte as u8; - } - let mut read = [0x00u8; 4096]; - - SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Huge transfer failed"); - assert_eq!(write, read); - println!(" SUCCESS"); - delay.delay_millis(250); - - // --- Symmetric transfer with huge buffer in-place (No additional allocation - // needed) --- - print!("Starting huge transfer (in-place)..."); - let mut write = [0x55u8; 4096]; - for byte in 0..write.len() { - write[byte] = byte as u8; - } - - SpiBus::transfer_in_place(&mut spi, &mut write[..]).expect("Huge transfer failed"); - for byte in 0..write.len() { - assert_eq!(write[byte], byte as u8); - } - println!(" SUCCESS"); - delay.delay_millis(250); - } -} diff --git a/examples/src/bin/systimer.rs b/examples/src/bin/systimer.rs index 5bb4fce4d4f..2fe83b3e37f 100644 --- a/examples/src/bin/systimer.rs +++ b/examples/src/bin/systimer.rs @@ -63,8 +63,6 @@ fn main() -> ! { interrupt::enable(Interrupt::SYSTIMER_TARGET1, Priority::Priority3).unwrap(); interrupt::enable(Interrupt::SYSTIMER_TARGET2, Priority::Priority3).unwrap(); - // Initialize the Delay peripheral, and use it to toggle the LED state in a - // loop. let delay = Delay::new(&clocks); loop { diff --git a/hil-test/Cargo.toml b/hil-test/Cargo.toml index f2b9c683bd2..d41668a6910 100644 --- a/hil-test/Cargo.toml +++ b/hil-test/Cargo.toml @@ -36,6 +36,10 @@ harness = false name = "gpio" harness = false +[[test]] +name = "interrupt" +harness = false + [[test]] name = "spi_full_duplex" harness = false diff --git a/hil-test/tests/interrupt.rs b/hil-test/tests/interrupt.rs new file mode 100644 index 00000000000..94a41f29d37 --- /dev/null +++ b/hil-test/tests/interrupt.rs @@ -0,0 +1,126 @@ +//! Interrupt Test + +//% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 + +#![no_std] +#![no_main] + +use core::{arch::asm, cell::RefCell}; + +use critical_section::Mutex; +use defmt::info; +use defmt_rtt as _; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + interrupt::{self, *}, + peripherals::{Interrupt, Peripherals}, + system::{SoftwareInterrupt, SystemControl}, +}; + +static SWINT0: Mutex>>> = Mutex::new(RefCell::new(None)); + +struct Context { + sw0_trigger_addr: u32, +} + +impl Context { + pub fn init() -> Self { + let peripherals = Peripherals::take(); + + cfg_if::cfg_if! { + if #[cfg(any(feature = "esp32c6", feature = "esp32h2"))] { + let cpu_intr = &peripherals.INTPRI; + } else { + let cpu_intr = &peripherals.SYSTEM; + } + } + + let sw0_trigger_addr = cpu_intr.cpu_intr_from_cpu_0() as *const _ as u32; + + let system = SystemControl::new(peripherals.SYSTEM); + let _clocks = ClockControl::max(system.clock_control).freeze(); + + let sw_int = system.software_interrupt_control; + + critical_section::with(|cs| { + SWINT0 + .borrow_ref_mut(cs) + .replace(sw_int.software_interrupt0) + }); + interrupt::enable_direct( + Interrupt::FROM_CPU_INTR0, + Priority::Priority3, + CpuInterrupt::Interrupt20, + ) + .unwrap(); + + Context { sw0_trigger_addr } + } +} + +#[no_mangle] +fn interrupt20() { + unsafe { asm!("csrrwi x0, 0x7e1, 0 #disable timer") } + critical_section::with(|cs| { + SWINT0.borrow_ref(cs).as_ref().unwrap().reset(); + }); + + let mut perf_counter: u32 = 0; + unsafe { + asm!( + " + csrr {x}, 0x7e2 + ", + options(nostack), + x = inout(reg) perf_counter, + ) + }; + info!("Performance counter:{}", perf_counter); + // TODO these values should be adjusted to catch smaller regressions + cfg_if::cfg_if! { + if #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] { + assert!(perf_counter < 1100); + } else { + assert!(perf_counter < 750); + } + } +} + +#[cfg(test)] +#[embedded_test::tests] +mod tests { + use super::*; + + #[init] + fn init() -> Context { + Context::init() + } + + #[test] + fn interrupt_latency(ctx: Context) { + unsafe { + asm!( + " + csrrwi x0, 0x7e0, 1 #what to count, for cycles write 1 for instructions write 2 + csrrwi x0, 0x7e1, 0 #disable counter + csrrwi x0, 0x7e2, 0 #reset counter + " + ); + } + + // interrupt is raised from assembly for max timer granularity. + unsafe { + asm!( + " + li {bit}, 1 # Flip flag (bit 0) + csrrwi x0, 0x7e1, 1 # enable timer + sw {bit}, 0({addr}) # trigger FROM_CPU_INTR0 + ", + options(nostack), + addr = in(reg) ctx.sw0_trigger_addr, + bit = out(reg) _, + ) + } + } +}