aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorklownfish <[email protected]>2024-09-24 20:46:04 +0200
committerklownfish <[email protected]>2024-09-24 20:46:04 +0200
commit60347976b2e56eb8484e10d4aec5fa12534457f7 (patch)
treefe1af22314ae008f2a93f34e1bb2b4129d4d85da /examples
parentfe868fc1948472666b6d8386a3191a074468a34e (diff)
parent0ede8479dc4c6a58cfab0a5d4df41c0592405971 (diff)
Merge remote-tracking branch 'origin/main' into u5_adc
Diffstat (limited to 'examples')
-rw-r--r--examples/boot/application/nrf/build.rs3
-rw-r--r--examples/boot/application/nrf/src/bin/a.rs11
-rw-r--r--examples/rp/src/bin/pio_onewire.rs155
-rw-r--r--examples/rp23/src/bin/trng.rs64
-rw-r--r--examples/stm32f4/src/bin/eth_compliance_test.rs77
-rw-r--r--examples/stm32h7rs/src/bin/usb_serial.rs140
6 files changed, 450 insertions, 0 deletions
diff --git a/examples/boot/application/nrf/build.rs b/examples/boot/application/nrf/build.rs
index cd1a264c4..e1da69328 100644
--- a/examples/boot/application/nrf/build.rs
+++ b/examples/boot/application/nrf/build.rs
@@ -31,4 +31,7 @@ fn main() {
31 31
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 if env::var("CARGO_FEATURE_DEFMT").is_ok() {
35 println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
36 }
34} 37}
diff --git a/examples/boot/application/nrf/src/bin/a.rs b/examples/boot/application/nrf/src/bin/a.rs
index 851a3d721..2c1d1a7bb 100644
--- a/examples/boot/application/nrf/src/bin/a.rs
+++ b/examples/boot/application/nrf/src/bin/a.rs
@@ -2,6 +2,9 @@
2#![no_main] 2#![no_main]
3#![macro_use] 3#![macro_use]
4 4
5#[cfg(feature = "defmt")]
6use defmt_rtt as _;
7use embassy_boot::State;
5use embassy_boot_nrf::{FirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_nrf::{FirmwareUpdater, FirmwareUpdaterConfig};
6use embassy_embedded_hal::adapter::BlockingAsync; 9use embassy_embedded_hal::adapter::BlockingAsync;
7use embassy_executor::Spawner; 10use embassy_executor::Spawner;
@@ -22,6 +25,7 @@ async fn main(_spawner: Spawner) {
22 25
23 let mut button = Input::new(p.P0_11, Pull::Up); 26 let mut button = Input::new(p.P0_11, Pull::Up);
24 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); 27 let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard);
28 let mut led_reverted = Output::new(p.P0_14, Level::High, OutputDrive::Standard);
25 29
26 //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard); 30 //let mut led = Output::new(p.P1_10, Level::Low, OutputDrive::Standard);
27 //let mut button = Input::new(p.P1_02, Pull::Up); 31 //let mut button = Input::new(p.P1_02, Pull::Up);
@@ -53,6 +57,13 @@ async fn main(_spawner: Spawner) {
53 let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc); 57 let config = FirmwareUpdaterConfig::from_linkerfile(&nvmc, &nvmc);
54 let mut magic = [0; 4]; 58 let mut magic = [0; 4];
55 let mut updater = FirmwareUpdater::new(config, &mut magic); 59 let mut updater = FirmwareUpdater::new(config, &mut magic);
60 let state = updater.get_state().await.unwrap();
61 if state == State::Revert {
62 led_reverted.set_low();
63 } else {
64 led_reverted.set_high();
65 }
66
56 loop { 67 loop {
57 led.set_low(); 68 led.set_low();
58 button.wait_for_any_edge().await; 69 button.wait_for_any_edge().await;
diff --git a/examples/rp/src/bin/pio_onewire.rs b/examples/rp/src/bin/pio_onewire.rs
new file mode 100644
index 000000000..5076101ec
--- /dev/null
+++ b/examples/rp/src/bin/pio_onewire.rs
@@ -0,0 +1,155 @@
1//! This example shows how you can use PIO to read a `DS18B20` one-wire temperature sensor.
2
3#![no_std]
4#![no_main]
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_rp::bind_interrupts;
8use embassy_rp::peripherals::PIO0;
9use embassy_rp::pio::{self, Common, Config, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine};
10use embassy_time::Timer;
11use {defmt_rtt as _, panic_probe as _};
12
13bind_interrupts!(struct Irqs {
14 PIO0_IRQ_0 => InterruptHandler<PIO0>;
15});
16
17#[embassy_executor::main]
18async fn main(_spawner: Spawner) {
19 let p = embassy_rp::init(Default::default());
20 let mut pio = Pio::new(p.PIO0, Irqs);
21 let mut sensor = Ds18b20::new(&mut pio.common, pio.sm0, p.PIN_2);
22
23 loop {
24 sensor.start().await; // Start a new measurement
25 Timer::after_secs(1).await; // Allow 1s for the measurement to finish
26 match sensor.temperature().await {
27 Ok(temp) => info!("temp = {:?} deg C", temp),
28 _ => error!("sensor error"),
29 }
30 Timer::after_secs(1).await;
31 }
32}
33
34/// DS18B20 temperature sensor driver
35pub struct Ds18b20<'d, PIO: pio::Instance, const SM: usize> {
36 sm: StateMachine<'d, PIO, SM>,
37}
38
39impl<'d, PIO: pio::Instance, const SM: usize> Ds18b20<'d, PIO, SM> {
40 /// Create a new instance the driver
41 pub fn new(common: &mut Common<'d, PIO>, mut sm: StateMachine<'d, PIO, SM>, pin: impl PioPin) -> Self {
42 let prg = pio_proc::pio_asm!(
43 r#"
44 .wrap_target
45 again:
46 pull block
47 mov x, osr
48 jmp !x, read
49 write:
50 set pindirs, 1
51 set pins, 0
52 loop1:
53 jmp x--,loop1
54 set pindirs, 0 [31]
55 wait 1 pin 0 [31]
56 pull block
57 mov x, osr
58 bytes1:
59 pull block
60 set y, 7
61 set pindirs, 1
62 bit1:
63 set pins, 0 [1]
64 out pins,1 [31]
65 set pins, 1 [20]
66 jmp y--,bit1
67 jmp x--,bytes1
68 set pindirs, 0 [31]
69 jmp again
70 read:
71 pull block
72 mov x, osr
73 bytes2:
74 set y, 7
75 bit2:
76 set pindirs, 1
77 set pins, 0 [1]
78 set pindirs, 0 [5]
79 in pins,1 [10]
80 jmp y--,bit2
81 jmp x--,bytes2
82 .wrap
83 "#,
84 );
85
86 let pin = common.make_pio_pin(pin);
87 let mut cfg = Config::default();
88 cfg.use_program(&common.load_program(&prg.program), &[]);
89 cfg.set_out_pins(&[&pin]);
90 cfg.set_in_pins(&[&pin]);
91 cfg.set_set_pins(&[&pin]);
92 cfg.shift_in = ShiftConfig {
93 auto_fill: true,
94 direction: ShiftDirection::Right,
95 threshold: 8,
96 };
97 cfg.clock_divider = 255_u8.into();
98 sm.set_config(&cfg);
99 sm.set_enable(true);
100 Self { sm }
101 }
102
103 /// Write bytes over the wire
104 async fn write_bytes(&mut self, bytes: &[u8]) {
105 self.sm.tx().wait_push(250).await;
106 self.sm.tx().wait_push(bytes.len() as u32 - 1).await;
107 for b in bytes {
108 self.sm.tx().wait_push(*b as u32).await;
109 }
110 }
111
112 /// Read bytes from the wire
113 async fn read_bytes(&mut self, bytes: &mut [u8]) {
114 self.sm.tx().wait_push(0).await;
115 self.sm.tx().wait_push(bytes.len() as u32 - 1).await;
116 for b in bytes.iter_mut() {
117 *b = (self.sm.rx().wait_pull().await >> 24) as u8;
118 }
119 }
120
121 /// Calculate CRC8 of the data
122 fn crc8(data: &[u8]) -> u8 {
123 let mut temp;
124 let mut data_byte;
125 let mut crc = 0;
126 for b in data {
127 data_byte = *b;
128 for _ in 0..8 {
129 temp = (crc ^ data_byte) & 0x01;
130 crc >>= 1;
131 if temp != 0 {
132 crc ^= 0x8C;
133 }
134 data_byte >>= 1;
135 }
136 }
137 crc
138 }
139
140 /// Start a new measurement. Allow at least 1000ms before getting `temperature`.
141 pub async fn start(&mut self) {
142 self.write_bytes(&[0xCC, 0x44]).await;
143 }
144
145 /// Read the temperature. Ensure >1000ms has passed since `start` before calling this.
146 pub async fn temperature(&mut self) -> Result<f32, ()> {
147 self.write_bytes(&[0xCC, 0xBE]).await;
148 let mut data = [0; 9];
149 self.read_bytes(&mut data).await;
150 match Self::crc8(&data) == 0 {
151 true => Ok(((data[1] as u32) << 8 | data[0] as u32) as f32 / 16.),
152 false => Err(()),
153 }
154 }
155}
diff --git a/examples/rp23/src/bin/trng.rs b/examples/rp23/src/bin/trng.rs
new file mode 100644
index 000000000..e146baa2e
--- /dev/null
+++ b/examples/rp23/src/bin/trng.rs
@@ -0,0 +1,64 @@
1//! This example shows TRNG usage
2
3#![no_std]
4#![no_main]
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_rp::bind_interrupts;
9use embassy_rp::block::ImageDef;
10use embassy_rp::gpio::{Level, Output};
11use embassy_rp::peripherals::TRNG;
12use embassy_rp::trng::Trng;
13use embassy_time::Timer;
14use rand::RngCore;
15use {defmt_rtt as _, panic_probe as _};
16
17#[link_section = ".start_block"]
18#[used]
19pub static IMAGE_DEF: ImageDef = ImageDef::secure_exe();
20
21// Program metadata for `picotool info`
22#[link_section = ".bi_entries"]
23#[used]
24pub static PICOTOOL_ENTRIES: [embassy_rp::binary_info::EntryAddr; 4] = [
25 embassy_rp::binary_info::rp_program_name!(c"example"),
26 embassy_rp::binary_info::rp_cargo_version!(),
27 embassy_rp::binary_info::rp_program_description!(c"Blinky"),
28 embassy_rp::binary_info::rp_program_build_attribute!(),
29];
30
31bind_interrupts!(struct Irqs {
32 TRNG_IRQ => embassy_rp::trng::InterruptHandler<TRNG>;
33});
34
35#[embassy_executor::main]
36async fn main(_spawner: Spawner) {
37 let peripherals = embassy_rp::init(Default::default());
38
39 // Initialize the TRNG with default configuration
40 let mut trng = Trng::new(peripherals.TRNG, Irqs, embassy_rp::trng::Config::default());
41 // A buffer to collect random bytes in.
42 let mut randomness = [0u8; 58];
43
44 let mut led = Output::new(peripherals.PIN_25, Level::Low);
45
46 loop {
47 trng.fill_bytes(&mut randomness).await;
48 info!("Random bytes async {}", &randomness);
49 trng.blocking_fill_bytes(&mut randomness);
50 info!("Random bytes blocking {}", &randomness);
51 let random_u32 = trng.next_u32();
52 let random_u64 = trng.next_u64();
53 info!("Random u32 {} u64 {}", random_u32, random_u64);
54 // Random number of blinks between 0 and 31
55 let blinks = random_u32 % 32;
56 for _ in 0..blinks {
57 led.set_high();
58 Timer::after_millis(20).await;
59 led.set_low();
60 Timer::after_millis(20).await;
61 }
62 Timer::after_millis(1000).await;
63 }
64}
diff --git a/examples/stm32f4/src/bin/eth_compliance_test.rs b/examples/stm32f4/src/bin/eth_compliance_test.rs
new file mode 100644
index 000000000..5946fed79
--- /dev/null
+++ b/examples/stm32f4/src/bin/eth_compliance_test.rs
@@ -0,0 +1,77 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::eth::generic_smi::GenericSMI;
7use embassy_stm32::eth::{Ethernet, PacketQueue, StationManagement};
8use embassy_stm32::time::Hertz;
9use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config};
10use embassy_time::Timer;
11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _};
13
14bind_interrupts!(struct Irqs {
15 ETH => eth::InterruptHandler;
16 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
17});
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) -> ! {
21 let mut config = Config::default();
22 {
23 use embassy_stm32::rcc::*;
24 config.rcc.hse = Some(Hse {
25 freq: Hertz(8_000_000),
26 mode: HseMode::Bypass,
27 });
28 config.rcc.pll_src = PllSource::HSE;
29 config.rcc.pll = Some(Pll {
30 prediv: PllPreDiv::DIV4,
31 mul: PllMul::MUL180,
32 divp: Some(PllPDiv::DIV2), // 8mhz / 4 * 180 / 2 = 180Mhz.
33 divq: None,
34 divr: None,
35 });
36 config.rcc.ahb_pre = AHBPrescaler::DIV1;
37 config.rcc.apb1_pre = APBPrescaler::DIV4;
38 config.rcc.apb2_pre = APBPrescaler::DIV2;
39 config.rcc.sys = Sysclk::PLL1_P;
40 }
41 let p = embassy_stm32::init(config);
42
43 info!("Hello Compliance World!");
44
45 let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF];
46
47 const PHY_ADDR: u8 = 0;
48 static PACKETS: StaticCell<PacketQueue<4, 4>> = StaticCell::new();
49 let mut device = Ethernet::new(
50 PACKETS.init(PacketQueue::<4, 4>::new()),
51 p.ETH,
52 Irqs,
53 p.PA1,
54 p.PA2,
55 p.PC1,
56 p.PA7,
57 p.PC4,
58 p.PC5,
59 p.PG13,
60 p.PB13,
61 p.PG11,
62 GenericSMI::new(PHY_ADDR),
63 mac_addr,
64 );
65
66 let sm = unsafe { device.station_management() };
67
68 // Just an example. Exact register settings depend on the specific PHY and test.
69 sm.smi_write(PHY_ADDR, 0, 0x2100);
70 sm.smi_write(PHY_ADDR, 11, 0xA000);
71
72 // NB: Remember to reset the PHY after testing before starting the networking stack
73
74 loop {
75 Timer::after_secs(1).await;
76 }
77}
diff --git a/examples/stm32h7rs/src/bin/usb_serial.rs b/examples/stm32h7rs/src/bin/usb_serial.rs
new file mode 100644
index 000000000..6773f7843
--- /dev/null
+++ b/examples/stm32h7rs/src/bin/usb_serial.rs
@@ -0,0 +1,140 @@
1#![no_std]
2#![no_main]
3
4use defmt::{panic, *};
5use embassy_executor::Spawner;
6use embassy_futures::join::join;
7use embassy_stm32::time::Hertz;
8use embassy_stm32::usb::{Driver, Instance};
9use embassy_stm32::{bind_interrupts, peripherals, usb, Config};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError;
12use embassy_usb::Builder;
13use {defmt_rtt as _, panic_probe as _};
14
15bind_interrupts!(struct Irqs {
16 OTG_HS => usb::InterruptHandler<peripherals::USB_OTG_HS>;
17});
18
19// If you are trying this and your USB device doesn't connect, the most
20// common issues are the RCC config and vbus_detection
21//
22// See https://embassy.dev/book/#_the_usb_examples_are_not_working_on_my_board_is_there_anything_else_i_need_to_configure
23// for more information.
24#[embassy_executor::main]
25async fn main(_spawner: Spawner) {
26 info!("Hello World!");
27
28 let mut config = Config::default();
29
30 {
31 use embassy_stm32::rcc::*;
32 config.rcc.hse = Some(Hse {
33 freq: Hertz(24_000_000),
34 mode: HseMode::Oscillator,
35 });
36 config.rcc.pll1 = Some(Pll {
37 source: PllSource::HSE,
38 prediv: PllPreDiv::DIV12,
39 mul: PllMul::MUL300,
40 divp: Some(PllDiv::DIV1), //600 MHz
41 divq: Some(PllDiv::DIV2), // 300 MHz
42 divr: Some(PllDiv::DIV2), // 300 MHz
43 });
44 config.rcc.sys = Sysclk::PLL1_P; // 600 MHz
45 config.rcc.ahb_pre = AHBPrescaler::DIV2; // 300 MHz
46 config.rcc.apb1_pre = APBPrescaler::DIV2; // 150 MHz
47 config.rcc.apb2_pre = APBPrescaler::DIV2; // 150 MHz
48 config.rcc.apb4_pre = APBPrescaler::DIV2; // 150 MHz
49 config.rcc.apb5_pre = APBPrescaler::DIV2; // 150 MHz
50 config.rcc.voltage_scale = VoltageScale::HIGH;
51 config.rcc.mux.usbphycsel = mux::Usbphycsel::HSE;
52 }
53
54 let p = embassy_stm32::init(config);
55
56 // Create the driver, from the HAL.
57 let mut ep_out_buffer = [0u8; 256];
58 let mut config = embassy_stm32::usb::Config::default();
59
60 // Do not enable vbus_detection. This is a safe default that works in all boards.
61 // However, if your USB device is self-powered (can stay powered on if USB is unplugged), you need
62 // to enable vbus_detection to comply with the USB spec. If you enable it, the board
63 // has to support it or USB won't work at all. See docs on `vbus_detection` for details.
64 config.vbus_detection = false;
65
66 let driver = Driver::new_hs(p.USB_OTG_HS, Irqs, p.PM6, p.PM5, &mut ep_out_buffer, config);
67
68 // Create embassy-usb Config
69 let mut config = embassy_usb::Config::new(0xc0de, 0xcafe);
70 config.manufacturer = Some("Embassy");
71 config.product = Some("USB-serial example");
72 config.serial_number = Some("12345678");
73 // Required for windows compatibility.
74 // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help
75 config.device_class = 0xEF;
76 config.device_sub_class = 0x02;
77 config.device_protocol = 0x01;
78 config.composite_with_iads = true;
79
80 // Create embassy-usb DeviceBuilder using the driver and config.
81 // It needs some buffers for building the descriptors.
82 let mut config_descriptor = [0; 256];
83 let mut bos_descriptor = [0; 256];
84 let mut control_buf = [0; 64];
85
86 let mut state = State::new();
87
88 let mut builder = Builder::new(
89 driver,
90 config,
91 &mut config_descriptor,
92 &mut bos_descriptor,
93 &mut [], // no msos descriptors
94 &mut control_buf,
95 );
96
97 // Create classes on the builder.
98 let mut class = CdcAcmClass::new(&mut builder, &mut state, 64);
99
100 // Build the builder.
101 let mut usb = builder.build();
102
103 // Run the USB device.
104 let usb_fut = usb.run();
105
106 // Do stuff with the class!
107 let echo_fut = async {
108 loop {
109 class.wait_connection().await;
110 info!("Connected");
111 let _ = echo(&mut class).await;
112 info!("Disconnected");
113 }
114 };
115
116 // Run everything concurrently.
117 // If we had made everything `'static` above instead, we could do this using separate tasks instead.
118 join(usb_fut, echo_fut).await;
119}
120
121struct Disconnected {}
122
123impl From<EndpointError> for Disconnected {
124 fn from(val: EndpointError) -> Self {
125 match val {
126 EndpointError::BufferOverflow => panic!("Buffer overflow"),
127 EndpointError::Disabled => Disconnected {},
128 }
129 }
130}
131
132async fn echo<'d, T: Instance + 'd>(class: &mut CdcAcmClass<'d, Driver<'d, T>>) -> Result<(), Disconnected> {
133 let mut buf = [0; 64];
134 loop {
135 let n = class.read_packet(&mut buf).await?;
136 let data = &buf[..n];
137 info!("data: {:x}", data);
138 class.write_packet(data).await?;
139 }
140}