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
This commit is contained in:
parent
06bf505093
commit
db39d0197a
@ -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 {}
|
||||
}
|
||||
@ -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 {}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<RefCell<Option<Rtc>>> = 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();
|
||||
});
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
@ -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<RefCell<Option<SoftwareInterrupt<0>>>> = 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);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<RefCell<Option<SoftwareInterrupt<0>>>> = Mutex::new(RefCell::new(None));
|
||||
static SWINT1: Mutex<RefCell<Option<SoftwareInterrupt<1>>>> = Mutex::new(RefCell::new(None));
|
||||
static SWINT2: Mutex<RefCell<Option<SoftwareInterrupt<2>>>> = Mutex::new(RefCell::new(None));
|
||||
static SWINT3: Mutex<RefCell<Option<SoftwareInterrupt<3>>>> = 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();
|
||||
});
|
||||
}
|
||||
@ -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<esp_hal::Blocking>) {
|
||||
let mut outbuf = [0_u32; U512::LIMBS];
|
||||
let mut mod_multi = RsaModularMultiplication::<operand_sizes::Op512, esp_hal::Blocking>::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<esp_hal::Blocking>) {
|
||||
#[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::<operand_sizes::Op512, esp_hal::Blocking>::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<esp_hal::Blocking>) {
|
||||
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::<operand_sizes::Op512, esp_hal::Blocking>::new(rsa);
|
||||
rsamulti.start_multiplication(operand_a, operand_b);
|
||||
rsamulti.read_results(&mut outbuf);
|
||||
}
|
||||
#[cfg(not(feature = "esp32"))]
|
||||
{
|
||||
let mut rsamulti =
|
||||
RsaMultiplication::<operand_sizes::Op512, esp_hal::Blocking>::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");
|
||||
}
|
||||
@ -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 {}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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 {
|
||||
|
||||
@ -36,6 +36,10 @@ harness = false
|
||||
name = "gpio"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "interrupt"
|
||||
harness = false
|
||||
|
||||
[[test]]
|
||||
name = "spi_full_duplex"
|
||||
harness = false
|
||||
|
||||
126
hil-test/tests/interrupt.rs
Normal file
126
hil-test/tests/interrupt.rs
Normal file
@ -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<RefCell<Option<SoftwareInterrupt<0>>>> = 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) _,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user