diff options
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/mcxa/src/bin/adc_interrupt.rs | 65 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/adc_polling.rs | 58 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/clkout.rs | 3 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/i2c-scan-blocking.rs | 3 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/reset-reason.rs | 15 | ||||
| -rw-r--r-- | examples/mcxa/src/lib.rs | 16 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_tcp_server.rs | 2 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_webrequest.rs | 2 | ||||
| -rw-r--r-- | examples/stm32f4/src/bin/sdmmc.rs | 38 | ||||
| -rw-r--r-- | examples/stm32f7/src/bin/sdmmc.rs | 11 | ||||
| -rw-r--r-- | examples/stm32h7/src/bin/sdmmc.rs | 13 | ||||
| -rw-r--r-- | examples/stm32n6/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/stm32n6/src/bin/crc.rs | 31 | ||||
| -rw-r--r-- | examples/stm32n6/src/bin/hash.rs | 78 | ||||
| -rw-r--r-- | examples/stm32wba/src/bin/rtc.rs | 62 | ||||
| -rw-r--r-- | examples/stm32wba6/src/bin/rtc.rs | 62 |
16 files changed, 343 insertions, 118 deletions
diff --git a/examples/mcxa/src/bin/adc_interrupt.rs b/examples/mcxa/src/bin/adc_interrupt.rs index c88b1fe8d..d2cda631c 100644 --- a/examples/mcxa/src/bin/adc_interrupt.rs +++ b/examples/mcxa/src/bin/adc_interrupt.rs | |||
| @@ -2,34 +2,31 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa_examples::init_adc_pins; | 5 | use embassy_time::{Duration, Ticker}; |
| 6 | use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; | 6 | use hal::adc::{Adc, InterruptHandler, LpadcConfig, TriggerPriorityPolicy}; |
| 7 | use hal::bind_interrupts; | ||
| 7 | use hal::clocks::PoweredClock; | 8 | use hal::clocks::PoweredClock; |
| 9 | use hal::clocks::config::Div8; | ||
| 8 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | 10 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; |
| 11 | use hal::config::Config; | ||
| 9 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | 12 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; |
| 10 | use hal::pac::adc1::cmdl1::{Adch, Mode}; | 13 | use hal::pac::adc1::cmdl1::Mode; |
| 11 | use hal::pac::adc1::ctrl::CalAvgs; | 14 | use hal::pac::adc1::ctrl::CalAvgs; |
| 12 | use hal::pac::adc1::tctrl::Tcmd; | 15 | use hal::peripherals::ADC1; |
| 13 | use hal::{InterruptExt, bind_interrupts}; | ||
| 14 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 16 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 15 | 17 | ||
| 16 | bind_interrupts!(struct Irqs { | 18 | bind_interrupts!(struct Irqs { |
| 17 | ADC1 => hal::adc::AdcHandler; | 19 | ADC1 => InterruptHandler<ADC1>; |
| 18 | }); | 20 | }); |
| 19 | 21 | ||
| 20 | #[used] | ||
| 21 | #[no_mangle] | ||
| 22 | static KEEP_ADC: unsafe extern "C" fn() = ADC1; | ||
| 23 | |||
| 24 | #[embassy_executor::main] | 22 | #[embassy_executor::main] |
| 25 | async fn main(_spawner: Spawner) { | 23 | async fn main(_spawner: Spawner) { |
| 26 | let p = hal::init(hal::config::Config::default()); | 24 | let mut config = Config::default(); |
| 25 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 27 | 26 | ||
| 28 | defmt::info!("ADC interrupt Example"); | 27 | let p = hal::init(config); |
| 29 | 28 | ||
| 30 | unsafe { | 29 | defmt::info!("ADC interrupt Example"); |
| 31 | init_adc_pins(); | ||
| 32 | } | ||
| 33 | 30 | ||
| 34 | let adc_config = LpadcConfig { | 31 | let adc_config = LpadcConfig { |
| 35 | enable_in_doze_mode: true, | 32 | enable_in_doze_mode: true, |
| @@ -41,44 +38,28 @@ async fn main(_spawner: Spawner) { | |||
| 41 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | 38 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, |
| 42 | enable_conv_pause: false, | 39 | enable_conv_pause: false, |
| 43 | conv_pause_delay: 0, | 40 | conv_pause_delay: 0, |
| 44 | fifo_watermark: 0, | ||
| 45 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | 41 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 46 | source: AdcClockSel::FroLfDiv, | 42 | source: AdcClockSel::FroLfDiv, |
| 47 | div: Div4::no_div(), | 43 | div: Div4::no_div(), |
| 48 | }; | 44 | }; |
| 49 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); | 45 | let mut adc = Adc::new_async(p.ADC1, p.P1_10, Irqs, adc_config).unwrap(); |
| 50 | 46 | ||
| 51 | adc.do_offset_calibration(); | 47 | adc.do_offset_calibration(); |
| 52 | adc.do_auto_calibration(); | 48 | adc.do_auto_calibration(); |
| 53 | 49 | adc.set_resolution(Mode::Data16Bits); | |
| 54 | let mut conv_command_config = adc.get_default_conv_command_config(); | ||
| 55 | conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; | ||
| 56 | conv_command_config.conversion_resolution_mode = Mode::Data16Bits; | ||
| 57 | adc.set_conv_command_config(1, &conv_command_config); | ||
| 58 | |||
| 59 | let mut conv_trigger_config = adc.get_default_conv_trigger_config(); | ||
| 60 | conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; | ||
| 61 | conv_trigger_config.enable_hardware_trigger = false; | ||
| 62 | adc.set_conv_trigger_config(0, &conv_trigger_config); | ||
| 63 | 50 | ||
| 64 | defmt::info!("ADC configuration done..."); | 51 | defmt::info!("ADC configuration done..."); |
| 65 | 52 | let mut ticker = Ticker::every(Duration::from_millis(100)); | |
| 66 | adc.enable_interrupt(0x1); | ||
| 67 | |||
| 68 | unsafe { | ||
| 69 | hal::interrupt::ADC1.enable(); | ||
| 70 | } | ||
| 71 | |||
| 72 | unsafe { | ||
| 73 | cortex_m::interrupt::enable(); | ||
| 74 | } | ||
| 75 | 53 | ||
| 76 | loop { | 54 | loop { |
| 77 | adc.do_software_trigger(1); | 55 | ticker.next().await; |
| 78 | while !adc.is_interrupt_triggered() { | 56 | match adc.read().await { |
| 79 | // Wait until the interrupt is triggered | 57 | Ok(value) => { |
| 58 | defmt::info!("ADC value: {}", value); | ||
| 59 | } | ||
| 60 | Err(e) => { | ||
| 61 | defmt::error!("ADC read error: {:?}", e); | ||
| 62 | } | ||
| 80 | } | 63 | } |
| 81 | defmt::info!("*** ADC interrupt TRIGGERED! ***"); | ||
| 82 | //TBD need to print the value | ||
| 83 | } | 64 | } |
| 84 | } | 65 | } |
diff --git a/examples/mcxa/src/bin/adc_polling.rs b/examples/mcxa/src/bin/adc_polling.rs index 07c50f224..5c4d5524c 100644 --- a/examples/mcxa/src/bin/adc_polling.rs +++ b/examples/mcxa/src/bin/adc_polling.rs | |||
| @@ -2,12 +2,15 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa_examples::init_adc_pins; | 5 | use embassy_mcxa::adc::{ConvCommandConfig, ConvTriggerConfig}; |
| 6 | use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; | 6 | use embassy_time::{Duration, Ticker}; |
| 7 | use hal::adc::{Adc, LpadcConfig, TriggerPriorityPolicy}; | ||
| 7 | use hal::clocks::PoweredClock; | 8 | use hal::clocks::PoweredClock; |
| 9 | use hal::clocks::config::Div8; | ||
| 8 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | 10 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; |
| 11 | use hal::config::Config; | ||
| 9 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | 12 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; |
| 10 | use hal::pac::adc1::cmdl1::{Adch, Mode}; | 13 | use hal::pac::adc1::cmdl1::Mode; |
| 11 | use hal::pac::adc1::ctrl::CalAvgs; | 14 | use hal::pac::adc1::ctrl::CalAvgs; |
| 12 | use hal::pac::adc1::tctrl::Tcmd; | 15 | use hal::pac::adc1::tctrl::Tcmd; |
| 13 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 16 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| @@ -16,11 +19,10 @@ const G_LPADC_RESULT_SHIFT: u32 = 0; | |||
| 16 | 19 | ||
| 17 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 21 | async fn main(_spawner: Spawner) { |
| 19 | let p = hal::init(hal::config::Config::default()); | 22 | let mut config = Config::default(); |
| 23 | config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); | ||
| 20 | 24 | ||
| 21 | unsafe { | 25 | let p = hal::init(config); |
| 22 | init_adc_pins(); | ||
| 23 | } | ||
| 24 | 26 | ||
| 25 | defmt::info!("=== ADC polling Example ==="); | 27 | defmt::info!("=== ADC polling Example ==="); |
| 26 | 28 | ||
| @@ -34,35 +36,43 @@ async fn main(_spawner: Spawner) { | |||
| 34 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, | 36 | trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, |
| 35 | enable_conv_pause: false, | 37 | enable_conv_pause: false, |
| 36 | conv_pause_delay: 0, | 38 | conv_pause_delay: 0, |
| 37 | fifo_watermark: 0, | ||
| 38 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | 39 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 39 | source: AdcClockSel::FroLfDiv, | 40 | source: AdcClockSel::FroLfDiv, |
| 40 | div: Div4::no_div(), | 41 | div: Div4::no_div(), |
| 41 | }; | 42 | }; |
| 42 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); | 43 | let adc = Adc::new_blocking(p.ADC1, p.P1_10, adc_config).unwrap(); |
| 43 | 44 | ||
| 44 | adc.do_offset_calibration(); | 45 | adc.do_offset_calibration(); |
| 45 | adc.do_auto_calibration(); | 46 | adc.do_auto_calibration(); |
| 46 | 47 | ||
| 47 | let mut conv_command_config = adc.get_default_conv_command_config(); | 48 | let conv_command_config = ConvCommandConfig { |
| 48 | conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; | 49 | conversion_resolution_mode: Mode::Data16Bits, |
| 49 | conv_command_config.conversion_resolution_mode = Mode::Data16Bits; | 50 | ..ConvCommandConfig::default() |
| 50 | adc.set_conv_command_config(1, &conv_command_config); | 51 | }; |
| 52 | adc.set_conv_command_config(1, &conv_command_config).unwrap(); | ||
| 51 | 53 | ||
| 52 | let mut conv_trigger_config = adc.get_default_conv_trigger_config(); | 54 | let conv_trigger_config = ConvTriggerConfig { |
| 53 | conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; | 55 | target_command_id: Tcmd::ExecuteCmd1, |
| 54 | conv_trigger_config.enable_hardware_trigger = false; | 56 | enable_hardware_trigger: false, |
| 55 | adc.set_conv_trigger_config(0, &conv_trigger_config); | 57 | ..Default::default() |
| 58 | }; | ||
| 59 | adc.set_conv_trigger_config(0, &conv_trigger_config).unwrap(); | ||
| 56 | 60 | ||
| 57 | defmt::info!("=== ADC configuration done... ==="); | 61 | defmt::info!("=== ADC configuration done... ==="); |
| 62 | let mut tick = Ticker::every(Duration::from_millis(100)); | ||
| 58 | 63 | ||
| 59 | loop { | 64 | loop { |
| 60 | adc.do_software_trigger(1); | 65 | tick.next().await; |
| 61 | let mut result: Option<ConvResult> = None; | 66 | adc.do_software_trigger(1).unwrap(); |
| 62 | while result.is_none() { | 67 | let result = loop { |
| 63 | result = hal::adc::get_conv_result(); | 68 | match adc.get_conv_result() { |
| 64 | } | 69 | Ok(res) => break res, |
| 65 | let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; | 70 | Err(_) => { |
| 66 | defmt::info!("value: {=u16}", value); | 71 | // Conversion not ready, continue polling |
| 72 | } | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | let value = result.conv_value >> G_LPADC_RESULT_SHIFT; | ||
| 76 | defmt::info!("ADC value: {=u16}", value); | ||
| 67 | } | 77 | } |
| 68 | } | 78 | } |
diff --git a/examples/mcxa/src/bin/clkout.rs b/examples/mcxa/src/bin/clkout.rs index bfd963540..1e52912d3 100644 --- a/examples/mcxa/src/bin/clkout.rs +++ b/examples/mcxa/src/bin/clkout.rs | |||
| @@ -4,8 +4,7 @@ | |||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; | 5 | use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; |
| 6 | use embassy_mcxa::clocks::PoweredClock; | 6 | use embassy_mcxa::clocks::PoweredClock; |
| 7 | use embassy_mcxa::gpio::{DriveStrength, SlewRate}; | 7 | use embassy_mcxa::gpio::{DriveStrength, Level, Output, SlewRate}; |
| 8 | use embassy_mcxa::{Level, Output}; | ||
| 9 | use embassy_time::Timer; | 8 | use embassy_time::Timer; |
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 11 | 10 | ||
diff --git a/examples/mcxa/src/bin/i2c-scan-blocking.rs b/examples/mcxa/src/bin/i2c-scan-blocking.rs index 0197f9b1d..bd706d712 100644 --- a/examples/mcxa/src/bin/i2c-scan-blocking.rs +++ b/examples/mcxa/src/bin/i2c-scan-blocking.rs | |||
| @@ -2,8 +2,7 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa::Input; | 5 | use embassy_mcxa::gpio::{Input, Pull}; |
| 6 | use embassy_mcxa::gpio::Pull; | ||
| 7 | use embassy_time::Timer; | 6 | use embassy_time::Timer; |
| 8 | use hal::clocks::config::Div8; | 7 | use hal::clocks::config::Div8; |
| 9 | use hal::config::Config; | 8 | use hal::config::Config; |
diff --git a/examples/mcxa/src/bin/reset-reason.rs b/examples/mcxa/src/bin/reset-reason.rs new file mode 100644 index 000000000..c244fbe04 --- /dev/null +++ b/examples/mcxa/src/bin/reset-reason.rs | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use hal::config::Config; | ||
| 6 | use hal::reset_reason::reset_reason; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let config = Config::default(); | ||
| 12 | let _p = hal::init(config); | ||
| 13 | |||
| 14 | defmt::info!("Reset Reason: '{}'", reset_reason()); | ||
| 15 | } | ||
diff --git a/examples/mcxa/src/lib.rs b/examples/mcxa/src/lib.rs deleted file mode 100644 index 2573a6adc..000000000 --- a/examples/mcxa/src/lib.rs +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![allow(clippy::missing_safety_doc)] | ||
| 3 | |||
| 4 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. | ||
| 5 | //! These live with the examples so the HAL stays generic. | ||
| 6 | |||
| 7 | use hal::{clocks, pins}; | ||
| 8 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 9 | |||
| 10 | /// Initialize clocks and pin muxing for ADC. | ||
| 11 | pub unsafe fn init_adc_pins() { | ||
| 12 | // NOTE: Lpuart has been updated to properly enable + reset its own clocks. | ||
| 13 | // GPIO has not. | ||
| 14 | _ = clocks::enable_and_reset::<hal::peripherals::PORT1>(&clocks::periph_helpers::NoConfig); | ||
| 15 | pins::configure_adc_pins(); | ||
| 16 | } | ||
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index e39de4902..ef8d08b76 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -101,7 +101,7 @@ async fn main(spawner: Spawner) { | |||
| 101 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 101 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 102 | .await | 102 | .await |
| 103 | { | 103 | { |
| 104 | info!("join failed with status={}", err.status); | 104 | info!("join failed: {:?}", err); |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | info!("waiting for link..."); | 107 | info!("waiting for link..."); |
diff --git a/examples/rp/src/bin/wifi_webrequest.rs b/examples/rp/src/bin/wifi_webrequest.rs index ce85f4b9a..069afc794 100644 --- a/examples/rp/src/bin/wifi_webrequest.rs +++ b/examples/rp/src/bin/wifi_webrequest.rs | |||
| @@ -106,7 +106,7 @@ async fn main(spawner: Spawner) { | |||
| 106 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) | 106 | .join(WIFI_NETWORK, JoinOptions::new(WIFI_PASSWORD.as_bytes())) |
| 107 | .await | 107 | .await |
| 108 | { | 108 | { |
| 109 | info!("join failed with status={}", err.status); | 109 | info!("join failed: {:?}", err); |
| 110 | } | 110 | } |
| 111 | 111 | ||
| 112 | info!("waiting for link..."); | 112 | info!("waiting for link..."); |
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs index fe0f887bf..098fd6986 100644 --- a/examples/stm32f4/src/bin/sdmmc.rs +++ b/examples/stm32f4/src/bin/sdmmc.rs | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::{DataBlock, Sdmmc}; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, DataBlock, StorageDevice}; | ||
| 7 | use embassy_stm32::time::{Hertz, mhz}; | 8 | use embassy_stm32::time::{Hertz, mhz}; |
| 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -57,31 +58,24 @@ async fn main(_spawner: Spawner) { | |||
| 57 | // Should print 400kHz for initialization | 58 | // Should print 400kHz for initialization |
| 58 | info!("Configured clock: {}", sdmmc.clock().0); | 59 | info!("Configured clock: {}", sdmmc.clock().0); |
| 59 | 60 | ||
| 60 | let mut err = None; | 61 | let mut cmd_block = CmdBlock::new(); |
| 61 | loop { | 62 | |
| 62 | match sdmmc.init_sd_card(mhz(24)).await { | 63 | let mut storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(24)) |
| 63 | Ok(_) => break, | 64 | .await |
| 64 | Err(e) => { | 65 | .unwrap(); |
| 65 | if err != Some(e) { | ||
| 66 | info!("waiting for card error, retrying: {:?}", e); | ||
| 67 | err = Some(e); | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
| 72 | 66 | ||
| 73 | let card = unwrap!(sdmmc.card()); | 67 | let card = storage.card(); |
| 74 | 68 | ||
| 75 | info!("Card: {:#?}", Debug2Format(card)); | 69 | info!("Card: {:#?}", Debug2Format(&card)); |
| 76 | info!("Clock: {}", sdmmc.clock()); | 70 | info!("Clock: {}", storage.sdmmc.clock()); |
| 77 | 71 | ||
| 78 | // Arbitrary block index | 72 | // Arbitrary block index |
| 79 | let block_idx = 16; | 73 | let block_idx = 16; |
| 80 | 74 | ||
| 81 | // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware. | 75 | // SDMMC uses `DataBlock` instead of `&[u8]` to ensure 4 byte alignment required by the hardware. |
| 82 | let mut block = DataBlock([0u8; 512]); | 76 | let mut block = DataBlock::new(); |
| 83 | 77 | ||
| 84 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 78 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 85 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 79 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 86 | 80 | ||
| 87 | if !ALLOW_WRITES { | 81 | if !ALLOW_WRITES { |
| @@ -91,17 +85,17 @@ async fn main(_spawner: Spawner) { | |||
| 91 | 85 | ||
| 92 | info!("Filling block with 0x55"); | 86 | info!("Filling block with 0x55"); |
| 93 | block.fill(0x55); | 87 | block.fill(0x55); |
| 94 | sdmmc.write_block(block_idx, &block).await.unwrap(); | 88 | storage.write_block(block_idx, &block).await.unwrap(); |
| 95 | info!("Write done"); | 89 | info!("Write done"); |
| 96 | 90 | ||
| 97 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 91 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 98 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 92 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 99 | 93 | ||
| 100 | info!("Filling block with 0xAA"); | 94 | info!("Filling block with 0xAA"); |
| 101 | block.fill(0xAA); | 95 | block.fill(0xAA); |
| 102 | sdmmc.write_block(block_idx, &block).await.unwrap(); | 96 | storage.write_block(block_idx, &block).await.unwrap(); |
| 103 | info!("Write done"); | 97 | info!("Write done"); |
| 104 | 98 | ||
| 105 | sdmmc.read_block(block_idx, &mut block).await.unwrap(); | 99 | storage.read_block(block_idx, &mut block).await.unwrap(); |
| 106 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); | 100 | info!("Read: {=[u8]:X}...{=[u8]:X}", block[..8], block[512 - 8..]); |
| 107 | } | 101 | } |
diff --git a/examples/stm32f7/src/bin/sdmmc.rs b/examples/stm32f7/src/bin/sdmmc.rs index 8809b5d0c..e5d261d89 100644 --- a/examples/stm32f7/src/bin/sdmmc.rs +++ b/examples/stm32f7/src/bin/sdmmc.rs | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::Sdmmc; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice}; | ||
| 7 | use embassy_stm32::time::{Hertz, mhz}; | 8 | use embassy_stm32::time::{Hertz, mhz}; |
| 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -54,9 +55,13 @@ async fn main(_spawner: Spawner) { | |||
| 54 | // Should print 400kHz for initialization | 55 | // Should print 400kHz for initialization |
| 55 | info!("Configured clock: {}", sdmmc.clock().0); | 56 | info!("Configured clock: {}", sdmmc.clock().0); |
| 56 | 57 | ||
| 57 | unwrap!(sdmmc.init_sd_card(mhz(25)).await); | 58 | let mut cmd_block = CmdBlock::new(); |
| 58 | 59 | ||
| 59 | let card = unwrap!(sdmmc.card()); | 60 | let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25)) |
| 61 | .await | ||
| 62 | .unwrap(); | ||
| 60 | 63 | ||
| 61 | info!("Card: {:#?}", Debug2Format(card)); | 64 | let card = storage.card(); |
| 65 | |||
| 66 | info!("Card: {:#?}", Debug2Format(&card)); | ||
| 62 | } | 67 | } |
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs index 4977fec79..f2e5bedeb 100644 --- a/examples/stm32h7/src/bin/sdmmc.rs +++ b/examples/stm32h7/src/bin/sdmmc.rs | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | use defmt::*; | 4 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_stm32::sdmmc::Sdmmc; | 6 | use embassy_stm32::sdmmc::Sdmmc; |
| 7 | use embassy_stm32::sdmmc::sd::{CmdBlock, StorageDevice}; | ||
| 7 | use embassy_stm32::time::mhz; | 8 | use embassy_stm32::time::mhz; |
| 8 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; | 9 | use embassy_stm32::{Config, bind_interrupts, peripherals, sdmmc}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -13,7 +14,7 @@ bind_interrupts!(struct Irqs { | |||
| 13 | }); | 14 | }); |
| 14 | 15 | ||
| 15 | #[embassy_executor::main] | 16 | #[embassy_executor::main] |
| 16 | async fn main(_spawner: Spawner) -> ! { | 17 | async fn main(_spawner: Spawner) { |
| 17 | let mut config = Config::default(); | 18 | let mut config = Config::default(); |
| 18 | { | 19 | { |
| 19 | use embassy_stm32::rcc::*; | 20 | use embassy_stm32::rcc::*; |
| @@ -53,11 +54,13 @@ async fn main(_spawner: Spawner) -> ! { | |||
| 53 | // Should print 400kHz for initialization | 54 | // Should print 400kHz for initialization |
| 54 | info!("Configured clock: {}", sdmmc.clock().0); | 55 | info!("Configured clock: {}", sdmmc.clock().0); |
| 55 | 56 | ||
| 56 | unwrap!(sdmmc.init_sd_card(mhz(25)).await); | 57 | let mut cmd_block = CmdBlock::new(); |
| 57 | 58 | ||
| 58 | let card = unwrap!(sdmmc.card()); | 59 | let storage = StorageDevice::new_sd_card(&mut sdmmc, &mut cmd_block, mhz(25)) |
| 60 | .await | ||
| 61 | .unwrap(); | ||
| 59 | 62 | ||
| 60 | info!("Card: {:#?}", Debug2Format(card)); | 63 | let card = storage.card(); |
| 61 | 64 | ||
| 62 | loop {} | 65 | info!("Card: {:#?}", Debug2Format(&card)); |
| 63 | } | 66 | } |
diff --git a/examples/stm32n6/Cargo.toml b/examples/stm32n6/Cargo.toml index 5ed28eed1..5ad5b97ce 100644 --- a/examples/stm32n6/Cargo.toml +++ b/examples/stm32n6/Cargo.toml | |||
| @@ -32,6 +32,8 @@ micromath = "2.0.0" | |||
| 32 | stm32-fmc = "0.3.0" | 32 | stm32-fmc = "0.3.0" |
| 33 | embedded-storage = "0.3.1" | 33 | embedded-storage = "0.3.1" |
| 34 | static_cell = "2" | 34 | static_cell = "2" |
| 35 | hmac = "0.12.1" | ||
| 36 | sha2 = { version = "0.10.9", default-features = false } | ||
| 35 | 37 | ||
| 36 | 38 | ||
| 37 | # cargo build/run | 39 | # cargo build/run |
diff --git a/examples/stm32n6/src/bin/crc.rs b/examples/stm32n6/src/bin/crc.rs new file mode 100644 index 000000000..d1b545d5b --- /dev/null +++ b/examples/stm32n6/src/bin/crc.rs | |||
| @@ -0,0 +1,31 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::crc::{Config, Crc, InputReverseConfig, PolySize}; | ||
| 7 | use {defmt_rtt as _, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let p = embassy_stm32::init(Default::default()); | ||
| 12 | info!("Hello World!"); | ||
| 13 | |||
| 14 | // Setup for: https://crccalc.com/?crc=Life, it never dieWomen are my favorite guy&method=crc32&datatype=ascii&outtype=0 | ||
| 15 | let mut crc = Crc::new( | ||
| 16 | p.CRC, | ||
| 17 | unwrap!(Config::new( | ||
| 18 | InputReverseConfig::Byte, | ||
| 19 | true, | ||
| 20 | PolySize::Width32, | ||
| 21 | 0xFFFFFFFF, | ||
| 22 | 0x04C11DB7 | ||
| 23 | )), | ||
| 24 | ); | ||
| 25 | |||
| 26 | let output = crc.feed_bytes(b"Life, it never die\nWomen are my favorite guy") ^ 0xFFFFFFFF; | ||
| 27 | |||
| 28 | defmt::assert_eq!(output, 0x33F0E26B); | ||
| 29 | |||
| 30 | cortex_m::asm::bkpt(); | ||
| 31 | } | ||
diff --git a/examples/stm32n6/src/bin/hash.rs b/examples/stm32n6/src/bin/hash.rs new file mode 100644 index 000000000..9f248318f --- /dev/null +++ b/examples/stm32n6/src/bin/hash.rs | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::info; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::hash::*; | ||
| 7 | use embassy_stm32::{Config, bind_interrupts, hash, peripherals}; | ||
| 8 | use embassy_time::Instant; | ||
| 9 | use hmac::{Hmac, Mac}; | ||
| 10 | use sha2::{Digest, Sha256}; | ||
| 11 | use {defmt_rtt as _, panic_probe as _}; | ||
| 12 | |||
| 13 | type HmacSha256 = Hmac<Sha256>; | ||
| 14 | |||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | HASH => hash::InterruptHandler<peripherals::HASH>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(_spawner: Spawner) -> ! { | ||
| 21 | let config = Config::default(); | ||
| 22 | let p = embassy_stm32::init(config); | ||
| 23 | |||
| 24 | let test_1: &[u8] = b"as;dfhaslfhas;oifvnasd;nifvnhasd;nifvhndlkfghsd;nvfnahssdfgsdafgsasdfasdfasdfasdfasdfghjklmnbvcalskdjghalskdjgfbaslkdjfgbalskdjgbalskdjbdfhsdfhsfghsfghfgh"; | ||
| 25 | let test_2: &[u8] = b"fdhalksdjfhlasdjkfhalskdjfhgal;skdjfgalskdhfjgalskdjfglafgadfgdfgdafgaadsfgfgdfgadrgsyfthxfgjfhklhjkfgukhulkvhlvhukgfhfsrghzdhxyfufynufyuszeradrtydyytserr"; | ||
| 26 | |||
| 27 | let mut hw_hasher = Hash::new_blocking(p.HASH, Irqs); | ||
| 28 | |||
| 29 | let hw_start_time = Instant::now(); | ||
| 30 | |||
| 31 | // Compute a digest in hardware. | ||
| 32 | let mut context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, None); | ||
| 33 | hw_hasher.update_blocking(&mut context, test_1); | ||
| 34 | hw_hasher.update_blocking(&mut context, test_2); | ||
| 35 | let mut hw_digest: [u8; 32] = [0; 32]; | ||
| 36 | hw_hasher.finish_blocking(context, &mut hw_digest); | ||
| 37 | |||
| 38 | let hw_end_time = Instant::now(); | ||
| 39 | let hw_execution_time = hw_end_time - hw_start_time; | ||
| 40 | |||
| 41 | let sw_start_time = Instant::now(); | ||
| 42 | |||
| 43 | // Compute a digest in software. | ||
| 44 | let mut sw_hasher = Sha256::new(); | ||
| 45 | sw_hasher.update(test_1); | ||
| 46 | sw_hasher.update(test_2); | ||
| 47 | let sw_digest = sw_hasher.finalize(); | ||
| 48 | |||
| 49 | let sw_end_time = Instant::now(); | ||
| 50 | let sw_execution_time = sw_end_time - sw_start_time; | ||
| 51 | |||
| 52 | info!("Hardware Digest: {:?}", hw_digest); | ||
| 53 | info!("Software Digest: {:?}", sw_digest[..]); | ||
| 54 | info!("Hardware Execution Time: {:?}", hw_execution_time); | ||
| 55 | info!("Software Execution Time: {:?}", sw_execution_time); | ||
| 56 | assert_eq!(hw_digest, sw_digest[..]); | ||
| 57 | |||
| 58 | let hmac_key: [u8; 64] = [0x55; 64]; | ||
| 59 | |||
| 60 | // Compute HMAC in hardware. | ||
| 61 | let mut sha256hmac_context = hw_hasher.start(Algorithm::SHA256, DataType::Width8, Some(&hmac_key)); | ||
| 62 | hw_hasher.update_blocking(&mut sha256hmac_context, test_1); | ||
| 63 | hw_hasher.update_blocking(&mut sha256hmac_context, test_2); | ||
| 64 | let mut hw_hmac: [u8; 32] = [0; 32]; | ||
| 65 | hw_hasher.finish_blocking(sha256hmac_context, &mut hw_hmac); | ||
| 66 | |||
| 67 | // Compute HMAC in software. | ||
| 68 | let mut sw_mac = HmacSha256::new_from_slice(&hmac_key).unwrap(); | ||
| 69 | sw_mac.update(test_1); | ||
| 70 | sw_mac.update(test_2); | ||
| 71 | let sw_hmac = sw_mac.finalize().into_bytes(); | ||
| 72 | |||
| 73 | info!("Hardware HMAC: {:?}", hw_hmac); | ||
| 74 | info!("Software HMAC: {:?}", sw_hmac[..]); | ||
| 75 | assert_eq!(hw_hmac, sw_hmac[..]); | ||
| 76 | |||
| 77 | loop {} | ||
| 78 | } | ||
diff --git a/examples/stm32wba/src/bin/rtc.rs b/examples/stm32wba/src/bin/rtc.rs new file mode 100644 index 000000000..cef8501e0 --- /dev/null +++ b/examples/stm32wba/src/bin/rtc.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::*; | ||
| 8 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | pub fn pll_init(config: &mut Config) { | ||
| 13 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 14 | source: PllSource::HSI, | ||
| 15 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 16 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 17 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 18 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 19 | divq: None, | ||
| 20 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 21 | frac: Some(0), // Fractional part (enabled) | ||
| 22 | }); | ||
| 23 | |||
| 24 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 25 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 26 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 27 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 28 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 29 | |||
| 30 | // voltage scale for max performance | ||
| 31 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 32 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 33 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 34 | } | ||
| 35 | |||
| 36 | #[embassy_executor::main] | ||
| 37 | async fn main(_spawner: Spawner) { | ||
| 38 | let mut config = Config::default(); | ||
| 39 | |||
| 40 | pll_init(&mut config); | ||
| 41 | |||
| 42 | let p = embassy_stm32::init(config); | ||
| 43 | |||
| 44 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 45 | |||
| 46 | // Setting datetime | ||
| 47 | let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap(); | ||
| 48 | match rtc.0.set_datetime(initial_datetime) { | ||
| 49 | Ok(()) => info!("RTC set successfully."), | ||
| 50 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 51 | } | ||
| 52 | |||
| 53 | // Reading datetime every 1s | ||
| 54 | loop { | ||
| 55 | match rtc.1.now() { | ||
| 56 | Ok(result) => info!("{}", result), | ||
| 57 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 58 | } | ||
| 59 | |||
| 60 | Timer::after_millis(1000).await; | ||
| 61 | } | ||
| 62 | } | ||
diff --git a/examples/stm32wba6/src/bin/rtc.rs b/examples/stm32wba6/src/bin/rtc.rs new file mode 100644 index 000000000..cef8501e0 --- /dev/null +++ b/examples/stm32wba6/src/bin/rtc.rs | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use defmt::*; | ||
| 5 | use embassy_executor::Spawner; | ||
| 6 | use embassy_stm32::Config; | ||
| 7 | use embassy_stm32::rcc::*; | ||
| 8 | use embassy_stm32::rtc::{DateTime, DayOfWeek, Rtc, RtcConfig}; | ||
| 9 | use embassy_time::Timer; | ||
| 10 | use {defmt_rtt as _, panic_probe as _}; | ||
| 11 | |||
| 12 | pub fn pll_init(config: &mut Config) { | ||
| 13 | config.rcc.pll1 = Some(embassy_stm32::rcc::Pll { | ||
| 14 | source: PllSource::HSI, | ||
| 15 | prediv: PllPreDiv::DIV1, // PLLM = 1 → HSI / 1 = 16 MHz | ||
| 16 | mul: PllMul::MUL30, // PLLN = 30 → 16 MHz * 30 = 480 MHz VCO | ||
| 17 | divr: Some(PllDiv::DIV5), // PLLR = 5 → 96 MHz (Sysclk) | ||
| 18 | // divq: Some(PllDiv::DIV10), // PLLQ = 10 → 48 MHz (NOT USED) | ||
| 19 | divq: None, | ||
| 20 | divp: Some(PllDiv::DIV30), // PLLP = 30 → 16 MHz (USBOTG) | ||
| 21 | frac: Some(0), // Fractional part (enabled) | ||
| 22 | }); | ||
| 23 | |||
| 24 | config.rcc.ahb_pre = AHBPrescaler::DIV1; | ||
| 25 | config.rcc.apb1_pre = APBPrescaler::DIV1; | ||
| 26 | config.rcc.apb2_pre = APBPrescaler::DIV1; | ||
| 27 | config.rcc.apb7_pre = APBPrescaler::DIV1; | ||
| 28 | config.rcc.ahb5_pre = AHB5Prescaler::DIV4; | ||
| 29 | |||
| 30 | // voltage scale for max performance | ||
| 31 | config.rcc.voltage_scale = VoltageScale::RANGE1; | ||
| 32 | // route PLL1_P into the USB‐OTG‐HS block | ||
| 33 | config.rcc.sys = Sysclk::PLL1_R; | ||
| 34 | } | ||
| 35 | |||
| 36 | #[embassy_executor::main] | ||
| 37 | async fn main(_spawner: Spawner) { | ||
| 38 | let mut config = Config::default(); | ||
| 39 | |||
| 40 | pll_init(&mut config); | ||
| 41 | |||
| 42 | let p = embassy_stm32::init(config); | ||
| 43 | |||
| 44 | let mut rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 45 | |||
| 46 | // Setting datetime | ||
| 47 | let initial_datetime = DateTime::from(1970, 1, 1, DayOfWeek::Thursday, 0, 00, 00, 0).unwrap(); | ||
| 48 | match rtc.0.set_datetime(initial_datetime) { | ||
| 49 | Ok(()) => info!("RTC set successfully."), | ||
| 50 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 51 | } | ||
| 52 | |||
| 53 | // Reading datetime every 1s | ||
| 54 | loop { | ||
| 55 | match rtc.1.now() { | ||
| 56 | Ok(result) => info!("{}", result), | ||
| 57 | Err(e) => error!("Failed to set RTC date/time: {:?}", e), | ||
| 58 | } | ||
| 59 | |||
| 60 | Timer::after_millis(1000).await; | ||
| 61 | } | ||
| 62 | } | ||
