diff options
| author | Tyler <[email protected]> | 2023-09-29 20:02:24 -0600 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-09-29 20:02:24 -0600 |
| commit | 2f9b59c5cf21f1e2761a9ccefdfd86f0edea829c (patch) | |
| tree | 8964744b4fb753cf98f6f413464106c4d2a72976 /examples/stm32l4 | |
| parent | ce91fb2bfc846570ef543a09396c428d70675245 (diff) | |
| parent | 95b3d9eb3b3657de3d7bc9c04f8fb83eae901640 (diff) | |
Merge branch 'main' into issue-1974-add-sai-driver
Diffstat (limited to 'examples/stm32l4')
| -rw-r--r-- | examples/stm32l4/.cargo/config.toml | 2 | ||||
| -rw-r--r-- | examples/stm32l4/Cargo.toml | 16 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/rtc.rs | 3 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/spe_adin1110_http_server.rs | 450 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/usart.rs | 2 | ||||
| -rw-r--r-- | examples/stm32l4/src/bin/usart_dma.rs | 2 |
6 files changed, 467 insertions, 8 deletions
diff --git a/examples/stm32l4/.cargo/config.toml b/examples/stm32l4/.cargo/config.toml index 36e74e5a5..db3a7ceff 100644 --- a/examples/stm32l4/.cargo/config.toml +++ b/examples/stm32l4/.cargo/config.toml | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` | 2 | # replace STM32F429ZITx with your chip as listed in `probe-rs chip list` |
| 3 | #runner = "probe-rs run --chip STM32L475VGT6" | 3 | #runner = "probe-rs run --chip STM32L475VGT6" |
| 4 | #runner = "probe-rs run --chip STM32L475VG" | 4 | #runner = "probe-rs run --chip STM32L475VG" |
| 5 | runner = "probe-rs run --chip STM32L4S5VI" | 5 | runner = "probe-run --chip STM32L4S5QI" |
| 6 | 6 | ||
| 7 | [build] | 7 | [build] |
| 8 | target = "thumbv7em-none-eabi" | 8 | target = "thumbv7em-none-eabi" |
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index f552a6109..59e89c537 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml | |||
| @@ -1,17 +1,22 @@ | |||
| 1 | [package] | 1 | [package] |
| 2 | edition = "2021" | 2 | edition = "2021" |
| 3 | name = "embassy-stm32l4-examples" | 3 | name = "embassy-stm32l4-examples" |
| 4 | version = "0.1.0" | 4 | version = "0.1.1" |
| 5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | # Change stm32l4s5vi to your chip name, if necessary. | 8 | # Change stm32l4s5vi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5qi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } |
| 10 | embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.3.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.3.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.1.3", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768", "unstable-traits", "nightly"] } |
| 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } | 13 | embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } |
| 14 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } | 14 | embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } |
| 15 | embassy-net-adin1110 = { version = "0.2.0", path = "../../embassy-net-adin1110" } | ||
| 16 | embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "udp", "tcp", "dhcpv4", "medium-ethernet"] } | ||
| 17 | embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } | ||
| 18 | embedded-io-async = { version = "0.5.0", features = ["defmt-03"] } | ||
| 19 | embedded-io = { version = "0.5.0", features = ["defmt-03"] } | ||
| 15 | 20 | ||
| 16 | defmt = "0.3" | 21 | defmt = "0.3" |
| 17 | defmt-rtt = "0.4" | 22 | defmt-rtt = "0.4" |
| @@ -21,10 +26,13 @@ cortex-m-rt = "0.7.0" | |||
| 21 | embedded-hal = "0.2.6" | 26 | embedded-hal = "0.2.6" |
| 22 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } | 27 | embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-rc.1" } |
| 23 | embedded-hal-async = { version = "=1.0.0-rc.1" } | 28 | embedded-hal-async = { version = "=1.0.0-rc.1" } |
| 29 | embedded-hal-bus = { version = "=0.1.0-rc.1", features = ["async"] } | ||
| 24 | panic-probe = { version = "0.3", features = ["print-defmt"] } | 30 | panic-probe = { version = "0.3", features = ["print-defmt"] } |
| 25 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | 31 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } |
| 26 | heapless = { version = "0.7.5", default-features = false } | 32 | heapless = { version = "0.7.5", default-features = false } |
| 27 | chrono = { version = "^0.4", default-features = false } | 33 | chrono = { version = "^0.4", default-features = false } |
| 34 | rand = { version = "0.8.5", default-features = false } | ||
| 35 | static_cell = {version = "1.1", features = ["nightly"]} | ||
| 28 | 36 | ||
| 29 | micromath = "2.0.0" | 37 | micromath = "2.0.0" |
| 30 | 38 | ||
diff --git a/examples/stm32l4/src/bin/rtc.rs b/examples/stm32l4/src/bin/rtc.rs index 294ea456c..eb1eed012 100644 --- a/examples/stm32l4/src/bin/rtc.rs +++ b/examples/stm32l4/src/bin/rtc.rs | |||
| @@ -23,7 +23,8 @@ async fn main(_spawner: Spawner) { | |||
| 23 | PLLMul::Mul20, | 23 | PLLMul::Mul20, |
| 24 | None, | 24 | None, |
| 25 | ); | 25 | ); |
| 26 | config.rcc.rtc_mux = rcc::RtcClockSource::LSE32; | 26 | config.rcc.lse = Some(Hertz(32_768)); |
| 27 | config.rcc.rtc_mux = rcc::RtcClockSource::LSE; | ||
| 27 | embassy_stm32::init(config) | 28 | embassy_stm32::init(config) |
| 28 | }; | 29 | }; |
| 29 | info!("Hello World!"); | 30 | info!("Hello World!"); |
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs new file mode 100644 index 000000000..287521582 --- /dev/null +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs | |||
| @@ -0,0 +1,450 @@ | |||
| 1 | #![deny(clippy::pedantic)] | ||
| 2 | #![allow(clippy::doc_markdown)] | ||
| 3 | #![no_main] | ||
| 4 | #![no_std] | ||
| 5 | // Needed unitl https://github.com/rust-lang/rust/issues/63063 is stablised. | ||
| 6 | #![feature(type_alias_impl_trait)] | ||
| 7 | #![feature(associated_type_bounds)] | ||
| 8 | #![allow(clippy::missing_errors_doc)] | ||
| 9 | |||
| 10 | // This example works on a ANALOG DEVICE EVAL-ADIN110EBZ board. | ||
| 11 | // Settings switch S201 "HW CFG": | ||
| 12 | // - Without SPI CRC: OFF-ON-OFF-OFF-OFF | ||
| 13 | // - With SPI CRC: ON -ON-OFF-OFF-OFF | ||
| 14 | // Settings switch S303 "uC CFG": | ||
| 15 | // - CFG0: On = static ip, Off = Dhcp | ||
| 16 | // - CFG1: Ethernet `FCS` on TX path: On, Off | ||
| 17 | // The webserver shows the actual temperature of the onboard i2c temp sensor. | ||
| 18 | |||
| 19 | use core::marker::PhantomData; | ||
| 20 | use core::sync::atomic::{AtomicI32, Ordering}; | ||
| 21 | |||
| 22 | use defmt::{error, info, println, unwrap, Format}; | ||
| 23 | use defmt_rtt as _; // global logger | ||
| 24 | use embassy_executor::Spawner; | ||
| 25 | use embassy_futures::select::{select, Either}; | ||
| 26 | use embassy_futures::yield_now; | ||
| 27 | use embassy_net::tcp::TcpSocket; | ||
| 28 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; | ||
| 29 | use embassy_time::{Delay, Duration, Ticker, Timer}; | ||
| 30 | use embedded_hal_async::i2c::I2c as I2cBus; | ||
| 31 | use embedded_io::Write as bWrite; | ||
| 32 | use embedded_io_async::Write; | ||
| 33 | use hal::gpio::{Input, Level, Output, Speed}; | ||
| 34 | use hal::i2c::{self, I2c}; | ||
| 35 | use hal::rcc::{self}; | ||
| 36 | use hal::rng::{self, Rng}; | ||
| 37 | use hal::{bind_interrupts, exti, pac, peripherals}; | ||
| 38 | use heapless::Vec; | ||
| 39 | use rand::RngCore; | ||
| 40 | use static_cell::make_static; | ||
| 41 | use {embassy_stm32 as hal, panic_probe as _}; | ||
| 42 | |||
| 43 | bind_interrupts!(struct Irqs { | ||
| 44 | I2C3_EV => i2c::InterruptHandler<peripherals::I2C3>; | ||
| 45 | RNG => rng::InterruptHandler<peripherals::RNG>; | ||
| 46 | }); | ||
| 47 | |||
| 48 | use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; | ||
| 49 | use embedded_hal_bus::spi::ExclusiveDevice; | ||
| 50 | use hal::gpio::Pull; | ||
| 51 | use hal::i2c::Config as I2C_Config; | ||
| 52 | use hal::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; | ||
| 53 | use hal::spi::{Config as SPI_Config, Spi}; | ||
| 54 | use hal::time::Hertz; | ||
| 55 | |||
| 56 | // Basic settings | ||
| 57 | // MAC-address used by the adin1110 | ||
| 58 | const MAC: [u8; 6] = [0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff]; | ||
| 59 | // Static IP settings | ||
| 60 | const IP_ADDRESS: Ipv4Cidr = Ipv4Cidr::new(Ipv4Address([192, 168, 1, 5]), 24); | ||
| 61 | // Listen port for the webserver | ||
| 62 | const HTTP_LISTEN_PORT: u16 = 80; | ||
| 63 | |||
| 64 | pub type SpeSpi = Spi<'static, peripherals::SPI2, peripherals::DMA1_CH1, peripherals::DMA1_CH2>; | ||
| 65 | pub type SpeSpiCs = ExclusiveDevice<SpeSpi, Output<'static, peripherals::PB12>, Delay>; | ||
| 66 | pub type SpeInt = exti::ExtiInput<'static, peripherals::PB11>; | ||
| 67 | pub type SpeRst = Output<'static, peripherals::PC7>; | ||
| 68 | pub type Adin1110T = ADIN1110<SpeSpiCs>; | ||
| 69 | pub type TempSensI2c = I2c<'static, peripherals::I2C3, peripherals::DMA1_CH6, peripherals::DMA1_CH7>; | ||
| 70 | |||
| 71 | static TEMP: AtomicI32 = AtomicI32::new(0); | ||
| 72 | |||
| 73 | #[embassy_executor::main] | ||
| 74 | async fn main(spawner: Spawner) { | ||
| 75 | defmt::println!("Start main()"); | ||
| 76 | |||
| 77 | let mut config = embassy_stm32::Config::default(); | ||
| 78 | |||
| 79 | // 80Mhz clock (Source: 8 / SrcDiv: 1 * PLLMul 20 / ClkDiv 2) | ||
| 80 | // 80MHz highest frequency for flash 0 wait. | ||
| 81 | config.rcc.mux = ClockSrc::PLL( | ||
| 82 | PLLSource::HSE(Hertz(8_000_000)), | ||
| 83 | PLLClkDiv::Div2, | ||
| 84 | PLLSrcDiv::Div1, | ||
| 85 | PLLMul::Mul20, | ||
| 86 | None, | ||
| 87 | ); | ||
| 88 | config.rcc.hsi48 = true; // needed for rng | ||
| 89 | config.rcc.rtc_mux = rcc::RtcClockSource::LSI; | ||
| 90 | |||
| 91 | let dp = embassy_stm32::init(config); | ||
| 92 | |||
| 93 | // RM0432rev9, 5.1.2: Independent I/O supply rail | ||
| 94 | // After reset, the I/Os supplied by VDDIO2 are logically and electrically isolated and | ||
| 95 | // therefore are not available. The isolation must be removed before using any I/O from | ||
| 96 | // PG[15:2], by setting the IOSV bit in the PWR_CR2 register, once the VDDIO2 supply is present | ||
| 97 | pac::PWR.cr2().modify(|w| w.set_iosv(true)); | ||
| 98 | |||
| 99 | let reset_status = pac::RCC.bdcr().read().0; | ||
| 100 | defmt::println!("bdcr before: 0x{:X}", reset_status); | ||
| 101 | |||
| 102 | defmt::println!("Setup IO pins"); | ||
| 103 | |||
| 104 | // Setup LEDs | ||
| 105 | let _led_uc1_green = Output::new(dp.PC13, Level::Low, Speed::Low); | ||
| 106 | let mut led_uc2_red = Output::new(dp.PE2, Level::High, Speed::Low); | ||
| 107 | let led_uc3_yellow = Output::new(dp.PE6, Level::High, Speed::Low); | ||
| 108 | let led_uc4_blue = Output::new(dp.PG15, Level::High, Speed::Low); | ||
| 109 | |||
| 110 | // Read the uc_cfg switches | ||
| 111 | let uc_cfg0 = Input::new(dp.PB2, Pull::None); | ||
| 112 | let uc_cfg1 = Input::new(dp.PF11, Pull::None); | ||
| 113 | let _uc_cfg2 = Input::new(dp.PG6, Pull::None); | ||
| 114 | let _uc_cfg3 = Input::new(dp.PG11, Pull::None); | ||
| 115 | |||
| 116 | // Setup I2C pins | ||
| 117 | let temp_sens_i2c = I2c::new( | ||
| 118 | dp.I2C3, | ||
| 119 | dp.PG7, | ||
| 120 | dp.PG8, | ||
| 121 | Irqs, | ||
| 122 | dp.DMA1_CH6, | ||
| 123 | dp.DMA1_CH7, | ||
| 124 | Hertz(100_000), | ||
| 125 | I2C_Config::default(), | ||
| 126 | ); | ||
| 127 | |||
| 128 | // Setup IO and SPI for the SPE chip | ||
| 129 | let spe_reset_n = Output::new(dp.PC7, Level::Low, Speed::Low); | ||
| 130 | let spe_cfg0 = Input::new(dp.PC8, Pull::None); | ||
| 131 | let spe_cfg1 = Input::new(dp.PC9, Pull::None); | ||
| 132 | let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); | ||
| 133 | |||
| 134 | let spe_int = Input::new(dp.PB11, Pull::None); | ||
| 135 | let spe_int = exti::ExtiInput::new(spe_int, dp.EXTI11); | ||
| 136 | |||
| 137 | let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); | ||
| 138 | let spe_spi_sclk = dp.PB13; | ||
| 139 | let spe_spi_miso = dp.PB14; | ||
| 140 | let spe_spi_mosi = dp.PB15; | ||
| 141 | |||
| 142 | // Don't turn the clock to high, clock must fit within the system clock as we get a runtime panic. | ||
| 143 | let mut spi_config = SPI_Config::default(); | ||
| 144 | spi_config.frequency = Hertz(25_000_000); | ||
| 145 | |||
| 146 | let spe_spi: SpeSpi = Spi::new( | ||
| 147 | dp.SPI2, | ||
| 148 | spe_spi_sclk, | ||
| 149 | spe_spi_mosi, | ||
| 150 | spe_spi_miso, | ||
| 151 | dp.DMA1_CH1, | ||
| 152 | dp.DMA1_CH2, | ||
| 153 | spi_config, | ||
| 154 | ); | ||
| 155 | let spe_spi = SpeSpiCs::new(spe_spi, spe_spi_cs_n, Delay); | ||
| 156 | |||
| 157 | let cfg0_without_crc = spe_cfg0.is_high(); | ||
| 158 | let cfg1_spi_mode = spe_cfg1.is_high(); | ||
| 159 | let uc_cfg1_fcs_en = uc_cfg1.is_low(); | ||
| 160 | |||
| 161 | defmt::println!( | ||
| 162 | "ADIN1110: CFG SPI-MODE 1-{}, CRC-bit 0-{} FCS-{}", | ||
| 163 | cfg1_spi_mode, | ||
| 164 | cfg0_without_crc, | ||
| 165 | uc_cfg1_fcs_en | ||
| 166 | ); | ||
| 167 | |||
| 168 | // Check the SPI mode selected with the "HW CFG" dip-switch | ||
| 169 | if !cfg1_spi_mode { | ||
| 170 | error!("Driver doesn´t support SPI Protolcol \"OPEN Alliance\".\nplease use the \"Generic SPI\"! Turn On \"HW CFG\": \"SPI_CFG1\""); | ||
| 171 | loop { | ||
| 172 | led_uc2_red.toggle(); | ||
| 173 | Timer::after(Duration::from_hz(10)).await; | ||
| 174 | } | ||
| 175 | }; | ||
| 176 | |||
| 177 | let state = make_static!(embassy_net_adin1110::State::<8, 8>::new()); | ||
| 178 | |||
| 179 | let (device, runner) = embassy_net_adin1110::new( | ||
| 180 | MAC, | ||
| 181 | state, | ||
| 182 | spe_spi, | ||
| 183 | spe_int, | ||
| 184 | spe_reset_n, | ||
| 185 | !cfg0_without_crc, | ||
| 186 | uc_cfg1_fcs_en, | ||
| 187 | ) | ||
| 188 | .await; | ||
| 189 | |||
| 190 | // Start task blink_led | ||
| 191 | unwrap!(spawner.spawn(heartbeat_led(led_uc3_yellow))); | ||
| 192 | // Start task temperature measurement | ||
| 193 | unwrap!(spawner.spawn(temp_task(temp_sens_i2c, led_uc4_blue))); | ||
| 194 | // Start ethernet task | ||
| 195 | unwrap!(spawner.spawn(ethernet_task(runner))); | ||
| 196 | |||
| 197 | let mut rng = Rng::new(dp.RNG, Irqs); | ||
| 198 | // Generate random seed | ||
| 199 | let seed = rng.next_u64(); | ||
| 200 | |||
| 201 | let ip_cfg = if uc_cfg0.is_low() { | ||
| 202 | println!("Waiting for DHCP..."); | ||
| 203 | let dhcp4_config = embassy_net::DhcpConfig::default(); | ||
| 204 | embassy_net::Config::dhcpv4(dhcp4_config) | ||
| 205 | } else { | ||
| 206 | embassy_net::Config::ipv4_static(StaticConfigV4 { | ||
| 207 | address: IP_ADDRESS, | ||
| 208 | gateway: None, | ||
| 209 | dns_servers: Vec::new(), | ||
| 210 | }) | ||
| 211 | }; | ||
| 212 | |||
| 213 | // Init network stack | ||
| 214 | let stack = &*make_static!(Stack::new( | ||
| 215 | device, | ||
| 216 | ip_cfg, | ||
| 217 | make_static!(StackResources::<2>::new()), | ||
| 218 | seed | ||
| 219 | )); | ||
| 220 | |||
| 221 | // Launch network task | ||
| 222 | unwrap!(spawner.spawn(net_task(stack))); | ||
| 223 | |||
| 224 | let cfg = wait_for_config(stack).await; | ||
| 225 | let local_addr = cfg.address.address(); | ||
| 226 | |||
| 227 | // Then we can use it! | ||
| 228 | let mut rx_buffer = [0; 4096]; | ||
| 229 | let mut tx_buffer = [0; 4096]; | ||
| 230 | let mut mb_buf = [0; 4096]; | ||
| 231 | loop { | ||
| 232 | let mut socket = TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); | ||
| 233 | socket.set_timeout(Some(Duration::from_secs(1))); | ||
| 234 | |||
| 235 | info!("Listening on http://{}:{}...", local_addr, HTTP_LISTEN_PORT); | ||
| 236 | if let Err(e) = socket.accept(HTTP_LISTEN_PORT).await { | ||
| 237 | defmt::error!("accept error: {:?}", e); | ||
| 238 | continue; | ||
| 239 | } | ||
| 240 | |||
| 241 | loop { | ||
| 242 | let _n = match socket.read(&mut mb_buf).await { | ||
| 243 | Ok(0) => { | ||
| 244 | defmt::info!("read EOF"); | ||
| 245 | break; | ||
| 246 | } | ||
| 247 | Ok(n) => n, | ||
| 248 | Err(e) => { | ||
| 249 | defmt::error!("{:?}", e); | ||
| 250 | break; | ||
| 251 | } | ||
| 252 | }; | ||
| 253 | led_uc2_red.set_low(); | ||
| 254 | |||
| 255 | let status_line = "HTTP/1.1 200 OK"; | ||
| 256 | let contents = PAGE; | ||
| 257 | let length = contents.len(); | ||
| 258 | |||
| 259 | let _ = write!( | ||
| 260 | &mut mb_buf[..], | ||
| 261 | "{status_line}\r\nContent-Length: {length}\r\n\r\n{contents}\r\n\0" | ||
| 262 | ); | ||
| 263 | let loc = mb_buf.iter().position(|v| *v == b'#').unwrap(); | ||
| 264 | |||
| 265 | let temp = TEMP.load(Ordering::Relaxed); | ||
| 266 | let cel = temp / 1000; | ||
| 267 | let mcel = temp % 1000; | ||
| 268 | |||
| 269 | info!("{}.{}", cel, mcel); | ||
| 270 | |||
| 271 | let _ = write!(&mut mb_buf[loc..loc + 7], "{cel}.{mcel}"); | ||
| 272 | |||
| 273 | let n = mb_buf.iter().position(|v| *v == 0).unwrap(); | ||
| 274 | |||
| 275 | if let Err(e) = socket.write_all(&mb_buf[..n]).await { | ||
| 276 | error!("write error: {:?}", e); | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | led_uc2_red.set_high(); | ||
| 281 | } | ||
| 282 | } | ||
| 283 | } | ||
| 284 | |||
| 285 | async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfigV4 { | ||
| 286 | loop { | ||
| 287 | if let Some(config) = stack.config_v4() { | ||
| 288 | return config; | ||
| 289 | } | ||
| 290 | yield_now().await; | ||
| 291 | } | ||
| 292 | } | ||
| 293 | |||
| 294 | #[embassy_executor::task] | ||
| 295 | async fn heartbeat_led(mut led: Output<'static, peripherals::PE6>) { | ||
| 296 | let mut tmr = Ticker::every(Duration::from_hz(3)); | ||
| 297 | loop { | ||
| 298 | led.toggle(); | ||
| 299 | tmr.next().await; | ||
| 300 | } | ||
| 301 | } | ||
| 302 | |||
| 303 | // ADT7422 | ||
| 304 | #[embassy_executor::task] | ||
| 305 | async fn temp_task(temp_dev_i2c: TempSensI2c, mut led: Output<'static, peripherals::PG15>) -> ! { | ||
| 306 | let mut tmr = Ticker::every(Duration::from_hz(1)); | ||
| 307 | let mut temp_sens = ADT7422::new(temp_dev_i2c, 0x48).unwrap(); | ||
| 308 | |||
| 309 | loop { | ||
| 310 | led.set_low(); | ||
| 311 | match select(temp_sens.read_temp(), Timer::after(Duration::from_millis(500))).await { | ||
| 312 | Either::First(i2c_ret) => match i2c_ret { | ||
| 313 | Ok(value) => { | ||
| 314 | led.set_high(); | ||
| 315 | let temp = i32::from(value); | ||
| 316 | println!("TEMP: {:04x}, {}", temp, temp * 78 / 10); | ||
| 317 | TEMP.store(temp * 78 / 10, Ordering::Relaxed); | ||
| 318 | } | ||
| 319 | Err(e) => defmt::println!("ADT7422: {}", e), | ||
| 320 | }, | ||
| 321 | Either::Second(_) => println!("Timeout"), | ||
| 322 | } | ||
| 323 | |||
| 324 | tmr.next().await; | ||
| 325 | } | ||
| 326 | } | ||
| 327 | |||
| 328 | #[embassy_executor::task] | ||
| 329 | async fn ethernet_task(runner: Runner<'static, SpeSpiCs, SpeInt, SpeRst>) -> ! { | ||
| 330 | runner.run().await | ||
| 331 | } | ||
| 332 | |||
| 333 | #[embassy_executor::task] | ||
| 334 | async fn net_task(stack: &'static Stack<Device<'static>>) -> ! { | ||
| 335 | stack.run().await | ||
| 336 | } | ||
| 337 | |||
| 338 | // same panicking *behavior* as `panic-probe` but doesn't print a panic message | ||
| 339 | // this prevents the panic message being printed *twice* when `defmt::panic` is invoked | ||
| 340 | #[defmt::panic_handler] | ||
| 341 | fn panic() -> ! { | ||
| 342 | cortex_m::asm::udf() | ||
| 343 | } | ||
| 344 | |||
| 345 | #[allow(non_camel_case_types)] | ||
| 346 | #[repr(C)] | ||
| 347 | pub enum Registers { | ||
| 348 | Temp_MSB = 0x00, | ||
| 349 | Temp_LSB, | ||
| 350 | Status, | ||
| 351 | Cfg, | ||
| 352 | T_HIGH_MSB, | ||
| 353 | T_HIGH_LSB, | ||
| 354 | T_LOW_MSB, | ||
| 355 | T_LOW_LSB, | ||
| 356 | T_CRIT_MSB, | ||
| 357 | T_CRIT_LSB, | ||
| 358 | T_HYST, | ||
| 359 | ID, | ||
| 360 | SW_RESET = 0x2F, | ||
| 361 | } | ||
| 362 | |||
| 363 | pub struct ADT7422<'d, BUS: I2cBus> { | ||
| 364 | addr: u8, | ||
| 365 | phantom: PhantomData<&'d ()>, | ||
| 366 | bus: BUS, | ||
| 367 | } | ||
| 368 | |||
| 369 | #[derive(Debug, Format)] | ||
| 370 | pub enum Error<I2cError: Format> { | ||
| 371 | I2c(I2cError), | ||
| 372 | Address, | ||
| 373 | } | ||
| 374 | |||
| 375 | impl<'d, BUS> ADT7422<'d, BUS> | ||
| 376 | where | ||
| 377 | BUS: I2cBus, | ||
| 378 | BUS::Error: Format, | ||
| 379 | { | ||
| 380 | pub fn new(bus: BUS, addr: u8) -> Result<Self, Error<BUS::Error>> { | ||
| 381 | if !(0x48..=0x4A).contains(&addr) { | ||
| 382 | return Err(Error::Address); | ||
| 383 | } | ||
| 384 | |||
| 385 | Ok(Self { | ||
| 386 | bus, | ||
| 387 | phantom: PhantomData, | ||
| 388 | addr, | ||
| 389 | }) | ||
| 390 | } | ||
| 391 | |||
| 392 | pub async fn init(&mut self) -> Result<(), Error<BUS::Error>> { | ||
| 393 | let mut cfg = 0b000_0000; | ||
| 394 | // if self.int.is_some() { | ||
| 395 | // // Set 1 SPS mode | ||
| 396 | // cfg |= 0b10 << 5; | ||
| 397 | // } else { | ||
| 398 | // One shot mode | ||
| 399 | cfg |= 0b01 << 5; | ||
| 400 | // } | ||
| 401 | |||
| 402 | self.write_cfg(cfg).await | ||
| 403 | } | ||
| 404 | |||
| 405 | pub async fn read(&mut self, reg: Registers) -> Result<u8, Error<BUS::Error>> { | ||
| 406 | let mut buffer = [0u8; 1]; | ||
| 407 | self.bus | ||
| 408 | .write_read(self.addr, &[reg as u8], &mut buffer) | ||
| 409 | .await | ||
| 410 | .map_err(Error::I2c)?; | ||
| 411 | Ok(buffer[0]) | ||
| 412 | } | ||
| 413 | |||
| 414 | pub async fn write_cfg(&mut self, cfg: u8) -> Result<(), Error<BUS::Error>> { | ||
| 415 | let buf = [Registers::Cfg as u8, cfg]; | ||
| 416 | self.bus.write(self.addr, &buf).await.map_err(Error::I2c) | ||
| 417 | } | ||
| 418 | |||
| 419 | pub async fn read_temp(&mut self) -> Result<i16, Error<BUS::Error>> { | ||
| 420 | let mut buffer = [0u8; 2]; | ||
| 421 | |||
| 422 | // if let Some(int) = &mut self.int { | ||
| 423 | // // Wait for interrupt | ||
| 424 | // int.wait_for_low().await.unwrap(); | ||
| 425 | // } else { | ||
| 426 | // Start: One shot | ||
| 427 | let cfg = 0b01 << 5; | ||
| 428 | self.write_cfg(cfg).await?; | ||
| 429 | Timer::after(Duration::from_millis(250)).await; | ||
| 430 | self.bus | ||
| 431 | .write_read(self.addr, &[Registers::Temp_MSB as u8], &mut buffer) | ||
| 432 | .await | ||
| 433 | .map_err(Error::I2c)?; | ||
| 434 | Ok(i16::from_be_bytes(buffer)) | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | // Web page | ||
| 439 | const PAGE: &str = r#"<!DOCTYPE html> | ||
| 440 | <html lang="en"> | ||
| 441 | <head> | ||
| 442 | <meta charset="utf-8"> | ||
| 443 | <meta http-equiv="refresh" content="1" > | ||
| 444 | <title>ADIN1110 with Rust</title> | ||
| 445 | </head> | ||
| 446 | <body> | ||
| 447 | <p>EVAL-ADIN1110EBZ</p> | ||
| 448 | <table><td>Temp Sensor ADT7422:</td><td> #00.00 °C</td></table> | ||
| 449 | </body> | ||
| 450 | </html>"#; | ||
diff --git a/examples/stm32l4/src/bin/usart.rs b/examples/stm32l4/src/bin/usart.rs index beb5ec558..f4da6b5ae 100644 --- a/examples/stm32l4/src/bin/usart.rs +++ b/examples/stm32l4/src/bin/usart.rs | |||
| @@ -19,7 +19,7 @@ fn main() -> ! { | |||
| 19 | let p = embassy_stm32::init(Default::default()); | 19 | let p = embassy_stm32::init(Default::default()); |
| 20 | 20 | ||
| 21 | let config = Config::default(); | 21 | let config = Config::default(); |
| 22 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config); | 22 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, NoDma, NoDma, config).unwrap(); |
| 23 | 23 | ||
| 24 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); | 24 | unwrap!(usart.blocking_write(b"Hello Embassy World!\r\n")); |
| 25 | info!("wrote Hello, starting echo"); | 25 | info!("wrote Hello, starting echo"); |
diff --git a/examples/stm32l4/src/bin/usart_dma.rs b/examples/stm32l4/src/bin/usart_dma.rs index b7d4cb01e..2f3b2a0f0 100644 --- a/examples/stm32l4/src/bin/usart_dma.rs +++ b/examples/stm32l4/src/bin/usart_dma.rs | |||
| @@ -22,7 +22,7 @@ async fn main(_spawner: Spawner) { | |||
| 22 | info!("Hello World!"); | 22 | info!("Hello World!"); |
| 23 | 23 | ||
| 24 | let config = Config::default(); | 24 | let config = Config::default(); |
| 25 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config); | 25 | let mut usart = Uart::new(p.UART4, p.PA1, p.PA0, Irqs, p.DMA1_CH3, NoDma, config).unwrap(); |
| 26 | 26 | ||
| 27 | for n in 0u32.. { | 27 | for n in 0u32.. { |
| 28 | let mut s: String<128> = String::new(); | 28 | let mut s: String<128> = String::new(); |
