diff --git a/.github/ci/test.sh b/.github/ci/test.sh index d014e4bd..2892bcf8 100755 --- a/.github/ci/test.sh +++ b/.github/ci/test.sh @@ -13,7 +13,7 @@ hashtime save /ci/cache/filetime.json cargo test --manifest-path ./embassy-sync/Cargo.toml cargo test --manifest-path ./embassy-embedded-hal/Cargo.toml -cargo test --manifest-path ./embassy-hal-common/Cargo.toml +cargo test --manifest-path ./embassy-hal-internal/Cargo.toml cargo test --manifest-path ./embassy-time/Cargo.toml --features generic-queue cargo test --manifest-path ./embassy-boot/boot/Cargo.toml diff --git a/.vscode/settings.json b/.vscode/settings.json index 725fb69d..29e8812e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -25,6 +25,7 @@ // "examples/stm32f1/Cargo.toml", // "examples/stm32f2/Cargo.toml", // "examples/stm32f3/Cargo.toml", + // "examples/stm32f334/Cargo.toml", // "examples/stm32f4/Cargo.toml", // "examples/stm32f7/Cargo.toml", // "examples/stm32g0/Cargo.toml", diff --git a/ci.sh b/ci.sh index 376cc8f4..32ae7855 100755 --- a/ci.sh +++ b/ci.sh @@ -27,6 +27,8 @@ cargo batch \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,nightly \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,dhcpv4,medium-ethernet,unstable-traits,nightly \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ieee802154 \ + --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,medium-ieee802154 \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,nightly \ --- build --release --manifest-path embassy-net/Cargo.toml --target thumbv7em-none-eabi --features defmt,tcp,udp,dns,proto-ipv6,medium-ethernet,unstable-traits,nightly \ @@ -115,6 +117,7 @@ cargo batch \ --- build --release --manifest-path examples/stm32f1/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f1 \ --- build --release --manifest-path examples/stm32f2/Cargo.toml --target thumbv7m-none-eabi --out-dir out/examples/stm32f2 \ --- build --release --manifest-path examples/stm32f3/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f3 \ + --- build --release --manifest-path examples/stm32f334/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f334 \ --- build --release --manifest-path examples/stm32f4/Cargo.toml --target thumbv7em-none-eabi --out-dir out/examples/stm32f4 \ --- build --release --manifest-path examples/stm32f7/Cargo.toml --target thumbv7em-none-eabihf --out-dir out/examples/stm32f7 \ --- build --release --manifest-path examples/stm32c0/Cargo.toml --target thumbv6m-none-eabi --out-dir out/examples/stm32c0 \ diff --git a/cyw43-firmware/43439A0.bin b/cyw43-firmware/43439A0.bin index b46b3bef..01737527 100755 Binary files a/cyw43-firmware/43439A0.bin and b/cyw43-firmware/43439A0.bin differ diff --git a/cyw43-firmware/43439A0_clm.bin b/cyw43-firmware/43439A0_clm.bin index 6e3ba786..1fedd753 100755 Binary files a/cyw43-firmware/43439A0_clm.bin and b/cyw43-firmware/43439A0_clm.bin differ diff --git a/cyw43-firmware/README.md b/cyw43-firmware/README.md index 7381fdc5..db3d9c9c 100644 --- a/cyw43-firmware/README.md +++ b/cyw43-firmware/README.md @@ -2,4 +2,8 @@ Firmware obtained from https://github.com/Infineon/wifi-host-driver/tree/master/WiFi_Host_Driver/resources/firmware/COMPONENT_43439 -Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt) \ No newline at end of file +Licensed under the [Infineon Permissive Binary License](./LICENSE-permissive-binary-license-1.0.txt) + +## Changelog + +* 2023-07-28: synced with `ad3bad0` - Update 43439 fw from 7.95.55 ot 7.95.62 diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs index dca30c74..830a5b44 100644 --- a/cyw43-pio/src/lib.rs +++ b/cyw43-pio/src/lib.rs @@ -8,7 +8,6 @@ use cyw43::SpiBusCyw43; use embassy_rp::dma::Channel; use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate}; use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine}; -use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef}; use fixed::FixedU32; use pio_proc::pio_asm; @@ -88,8 +87,6 @@ where ".wrap" ); - let relocated = RelocatedProgram::new(&program.program); - let mut pin_io: embassy_rp::pio::Pin = common.make_pio_pin(dio); pin_io.set_pull(Pull::None); pin_io.set_schmitt(true); @@ -102,7 +99,8 @@ where pin_clk.set_slew_rate(SlewRate::Fast); let mut cfg = Config::default(); - cfg.use_program(&common.load_program(&relocated), &[&pin_clk]); + let loaded_program = common.load_program(&program.program); + cfg.use_program(&loaded_program, &[&pin_clk]); cfg.set_out_pins(&[&pin_io]); cfg.set_in_pins(&[&pin_io]); cfg.set_set_pins(&[&pin_io]); @@ -142,7 +140,7 @@ where sm, irq, dma: dma.into_ref(), - wrap_target: relocated.wrap().target, + wrap_target: loaded_program.wrap.target, } } diff --git a/embassy-boot/rp/src/lib.rs b/embassy-boot/rp/src/lib.rs index 25329f9e..35fc104e 100644 --- a/embassy-boot/rp/src/lib.rs +++ b/embassy-boot/rp/src/lib.rs @@ -6,7 +6,7 @@ mod fmt; #[cfg(feature = "nightly")] pub use embassy_boot::FirmwareUpdater; pub use embassy_boot::{AlignedBuffer, BlockingFirmwareUpdater, BootLoaderConfig, FirmwareUpdaterConfig, State}; -use embassy_rp::flash::{Flash, ERASE_SIZE}; +use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE}; use embassy_rp::peripherals::{FLASH, WATCHDOG}; use embassy_rp::watchdog::Watchdog; use embassy_time::Duration; @@ -58,14 +58,14 @@ impl /// A flash implementation that will feed a watchdog when touching flash. pub struct WatchdogFlash<'d, const SIZE: usize> { - flash: Flash<'d, FLASH, SIZE>, + flash: Flash<'d, FLASH, Blocking, SIZE>, watchdog: Watchdog, } impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> { /// Start a new watchdog with a given flash and watchdog peripheral and a timeout pub fn start(flash: FLASH, watchdog: WATCHDOG, timeout: Duration) -> Self { - let flash: Flash<'_, FLASH, SIZE> = Flash::new(flash); + let flash = Flash::<_, Blocking, SIZE>::new(flash); let mut watchdog = Watchdog::new(watchdog); watchdog.start(timeout); Self { flash, watchdog } @@ -73,12 +73,12 @@ impl<'d, const SIZE: usize> WatchdogFlash<'d, SIZE> { } impl<'d, const SIZE: usize> ErrorType for WatchdogFlash<'d, SIZE> { - type Error = as ErrorType>::Error; + type Error = as ErrorType>::Error; } impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> { - const WRITE_SIZE: usize = as NorFlash>::WRITE_SIZE; - const ERASE_SIZE: usize = as NorFlash>::ERASE_SIZE; + const WRITE_SIZE: usize = as NorFlash>::WRITE_SIZE; + const ERASE_SIZE: usize = as NorFlash>::ERASE_SIZE; fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { self.watchdog.feed(); @@ -91,7 +91,7 @@ impl<'d, const SIZE: usize> NorFlash for WatchdogFlash<'d, SIZE> { } impl<'d, const SIZE: usize> ReadNorFlash for WatchdogFlash<'d, SIZE> { - const READ_SIZE: usize = as ReadNorFlash>::READ_SIZE; + const READ_SIZE: usize = as ReadNorFlash>::READ_SIZE; fn read(&mut self, offset: u32, data: &mut [u8]) -> Result<(), Self::Error> { self.watchdog.feed(); self.flash.read(offset, data) diff --git a/embassy-hal-common/Cargo.toml b/embassy-hal-internal/Cargo.toml similarity index 95% rename from embassy-hal-common/Cargo.toml rename to embassy-hal-internal/Cargo.toml index 18c758d7..42e03199 100644 --- a/embassy-hal-common/Cargo.toml +++ b/embassy-hal-internal/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "embassy-hal-common" +name = "embassy-hal-internal" version = "0.1.0" edition = "2021" license = "MIT OR Apache-2.0" diff --git a/embassy-hal-internal/README.md b/embassy-hal-internal/README.md new file mode 100644 index 00000000..d6539701 --- /dev/null +++ b/embassy-hal-internal/README.md @@ -0,0 +1,16 @@ +# embassy-macros + +An [Embassy](https://embassy.dev) project. + +Internal implementation details for Embassy HALs. DO NOT USE DIRECTLY. Embassy HALs (`embassy-nrf`, `embassy-stm32`, `embassy-rp`) already reexport +everything you need to use them effectively. + +## License + +This work is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + ) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or ) + +at your option. diff --git a/embassy-hal-common/build.rs b/embassy-hal-internal/build.rs similarity index 100% rename from embassy-hal-common/build.rs rename to embassy-hal-internal/build.rs diff --git a/embassy-hal-common/src/atomic_ring_buffer.rs b/embassy-hal-internal/src/atomic_ring_buffer.rs similarity index 100% rename from embassy-hal-common/src/atomic_ring_buffer.rs rename to embassy-hal-internal/src/atomic_ring_buffer.rs diff --git a/embassy-hal-common/src/drop.rs b/embassy-hal-internal/src/drop.rs similarity index 100% rename from embassy-hal-common/src/drop.rs rename to embassy-hal-internal/src/drop.rs diff --git a/embassy-hal-common/src/fmt.rs b/embassy-hal-internal/src/fmt.rs similarity index 100% rename from embassy-hal-common/src/fmt.rs rename to embassy-hal-internal/src/fmt.rs diff --git a/embassy-hal-common/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs similarity index 100% rename from embassy-hal-common/src/interrupt.rs rename to embassy-hal-internal/src/interrupt.rs diff --git a/embassy-hal-common/src/lib.rs b/embassy-hal-internal/src/lib.rs similarity index 89% rename from embassy-hal-common/src/lib.rs rename to embassy-hal-internal/src/lib.rs index 235964aa..3640ea18 100644 --- a/embassy-hal-common/src/lib.rs +++ b/embassy-hal-internal/src/lib.rs @@ -1,5 +1,6 @@ #![no_std] #![allow(clippy::new_without_default)] +#![doc = include_str!("../README.md")] // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; diff --git a/embassy-hal-common/src/macros.rs b/embassy-hal-internal/src/macros.rs similarity index 100% rename from embassy-hal-common/src/macros.rs rename to embassy-hal-internal/src/macros.rs diff --git a/embassy-hal-common/src/peripheral.rs b/embassy-hal-internal/src/peripheral.rs similarity index 100% rename from embassy-hal-common/src/peripheral.rs rename to embassy-hal-internal/src/peripheral.rs diff --git a/embassy-hal-common/src/ratio.rs b/embassy-hal-internal/src/ratio.rs similarity index 100% rename from embassy-hal-common/src/ratio.rs rename to embassy-hal-internal/src/ratio.rs diff --git a/embassy-hal-common/src/ring_buffer.rs b/embassy-hal-internal/src/ring_buffer.rs similarity index 100% rename from embassy-hal-common/src/ring_buffer.rs rename to embassy-hal-internal/src/ring_buffer.rs diff --git a/embassy-lora/Cargo.toml b/embassy-lora/Cargo.toml index e4524af5..402ad2d7 100644 --- a/embassy-lora/Cargo.toml +++ b/embassy-lora/Cargo.toml @@ -12,7 +12,7 @@ target = "thumbv7em-none-eabi" [features] stm32wl = ["dep:embassy-stm32"] -time = [] +time = ["embassy-time", "lorawan-device"] defmt = ["dep:defmt", "lorawan-device/defmt"] [dependencies] @@ -20,18 +20,12 @@ defmt = ["dep:defmt", "lorawan-device/defmt"] defmt = { version = "0.3", optional = true } log = { version = "0.4.14", optional = true } -embassy-time = { version = "0.1.2", path = "../embassy-time" } +embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", default-features = false, optional = true } -embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } embedded-hal-async = { version = "=0.2.0-alpha.2" } -embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common", default-features = false } -futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } embedded-hal = { version = "0.2", features = ["unproven"] } -bit_field = { version = "0.10" } +futures = { version = "0.3.17", default-features = false, features = [ "async-await" ] } lora-phy = { version = "1" } -lorawan-device = { version = "0.10.0", default-features = false, features = ["async"] } - -[patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } +lorawan-device = { version = "0.10.0", default-features = false, features = ["async"], optional = true } diff --git a/embassy-net-esp-hosted/src/control.rs b/embassy-net-esp-hosted/src/control.rs index 79f8cde7..37f220da 100644 --- a/embassy-net-esp-hosted/src/control.rs +++ b/embassy-net-esp-hosted/src/control.rs @@ -1,5 +1,4 @@ use ch::driver::LinkState; -use defmt::Debug2Format; use embassy_net_driver_channel as ch; use heapless::String; @@ -57,7 +56,6 @@ impl<'a> Control<'a> { let proto::CtrlMsgPayload::RespConnectAp(resp) = resp.payload.unwrap() else { panic!("unexpected resp") }; - debug!("======= {:?}", Debug2Format(&resp)); assert_eq!(resp.resp, 0); self.state_ch.set_link_state(LinkState::Up); } diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 81c751a2..3f915016 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -32,12 +32,14 @@ pub use smoltcp::iface::MulticastError; use smoltcp::iface::{Interface, SocketHandle, SocketSet, SocketStorage}; #[cfg(feature = "dhcpv4")] use smoltcp::socket::dhcpv4::{self, RetryConfig}; +#[cfg(feature = "medium-ethernet")] +pub use smoltcp::wire::EthernetAddress; +#[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] +pub use smoltcp::wire::HardwareAddress; #[cfg(feature = "udp")] pub use smoltcp::wire::IpListenEndpoint; -#[cfg(feature = "medium-ethernet")] -pub use smoltcp::wire::{EthernetAddress, HardwareAddress}; #[cfg(feature = "medium-ieee802154")] -pub use smoltcp::wire::{HardwareAddress, Ieee802154Address}; +pub use smoltcp::wire::{Ieee802154Address, Ieee802154Frame}; pub use smoltcp::wire::{IpAddress, IpCidr, IpEndpoint}; #[cfg(feature = "proto-ipv4")] pub use smoltcp::wire::{Ipv4Address, Ipv4Cidr}; @@ -583,7 +585,7 @@ impl SocketStack { impl Inner { #[cfg(feature = "proto-ipv4")] fn apply_config_v4(&mut self, s: &mut SocketStack, config: StaticConfigV4) { - #[cfg(feature = "medium-ethernet")] + #[cfg(any(feature = "medium-ethernet", feature = "medium-ieee802154"))] let medium = self.device.capabilities().medium; debug!("Acquired IP configuration:"); diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index 57dd22f1..d10cd2c3 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -93,7 +93,7 @@ _gpio-p1 = [] [dependencies] embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-3"] } +embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-3"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional=true } diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 9bc1c1e7..5a0a3c7c 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -15,8 +15,8 @@ use core::slice; use core::sync::atomic::{compiler_fence, AtomicU8, AtomicUsize, Ordering}; use core::task::Poll; -use embassy_hal_common::atomic_ring_buffer::RingBuffer; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::atomic_ring_buffer::RingBuffer; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; // Re-export SVD variants to allow user to directly set values pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index 8776000c..70e4b486 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024; pub const RESET_PIN: u32 = 21; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -208,7 +208,7 @@ impl_ppi_channel!(PPI_CH31, 31 => static); impl_saadc_input!(P0_04, ANALOG_INPUT2); impl_saadc_input!(P0_05, ANALOG_INPUT3); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index 5519e895..7416d391 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024; pub const RESET_PIN: u32 = 21; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -234,7 +234,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index d5367c59..58801068 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 192 * 1024; pub const RESET_PIN: u32 = 21; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -236,7 +236,7 @@ impl_saadc_input!(P0_29, ANALOG_INPUT5); impl_saadc_input!(P0_30, ANALOG_INPUT6); impl_saadc_input!(P0_31, ANALOG_INPUT7); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 78517044..0ecddaf3 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 256 * 1024; pub const RESET_PIN: u32 = 18; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // USB USBD, @@ -224,7 +224,7 @@ impl_ppi_channel!(PPI_CH29, 29 => static); impl_ppi_channel!(PPI_CH30, 30 => static); impl_ppi_channel!(PPI_CH31, 31 => static); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index b77564a5..ae39628d 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -12,7 +12,7 @@ pub const FLASH_SIZE: usize = 512 * 1024; pub const RESET_PIN: u32 = 21; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -263,7 +263,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index bff7f4eb..b8830b33 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 512 * 1024; pub const RESET_PIN: u32 = 18; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // USB USBD, @@ -306,7 +306,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 9b005082..a490cb07 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -8,7 +8,7 @@ pub const FLASH_SIZE: usize = 1024 * 1024; pub const RESET_PIN: u32 = 18; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // USB USBD, @@ -311,7 +311,7 @@ impl_saadc_input!(P0_31, ANALOG_INPUT7); impl_i2s!(I2S, I2S, I2S); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( POWER_CLOCK, RADIO, UARTE0_UART0, diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs index 410ae921..afc2c4a7 100644 --- a/embassy-nrf/src/chips/nrf5340_app.rs +++ b/embassy-nrf/src/chips/nrf5340_app.rs @@ -218,7 +218,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; pub const FLASH_SIZE: usize = 1024 * 1024; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // USB USBD, @@ -506,7 +506,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( FPU, CACHE, SPU, diff --git a/embassy-nrf/src/chips/nrf5340_net.rs b/embassy-nrf/src/chips/nrf5340_net.rs index 6ac78308..dee666a6 100644 --- a/embassy-nrf/src/chips/nrf5340_net.rs +++ b/embassy-nrf/src/chips/nrf5340_net.rs @@ -109,7 +109,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; pub const FLASH_SIZE: usize = 256 * 1024; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -342,7 +342,7 @@ impl_ppi_channel!(PPI_CH29, 29 => configurable); impl_ppi_channel!(PPI_CH30, 30 => configurable); impl_ppi_channel!(PPI_CH31, 31 => configurable); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( CLOCK_POWER, RADIO, RNG, diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs index 67ea032f..495285ba 100644 --- a/embassy-nrf/src/chips/nrf9160.rs +++ b/embassy-nrf/src/chips/nrf9160.rs @@ -169,7 +169,7 @@ pub const FORCE_COPY_BUFFER_SIZE: usize = 1024; pub const FLASH_SIZE: usize = 1024 * 1024; -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { // RTC RTC0, RTC1, @@ -368,7 +368,7 @@ impl_saadc_input!(P0_18, ANALOG_INPUT5); impl_saadc_input!(P0_19, ANALOG_INPUT6); impl_saadc_input!(P0_20, ANALOG_INPUT7); -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( SPU, CLOCK_POWER, UARTE0_SPIM0_SPIS0_TWIM0_TWIS0, diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 895ab934..ea2b7609 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -5,7 +5,7 @@ use core::convert::Infallible; use core::hint::unreachable_unchecked; use cfg_if::cfg_if; -use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; use self::sealed::Pin as _; use crate::pac::p0 as gpio; diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 6550f2ab..7488bc08 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -4,7 +4,7 @@ use core::convert::Infallible; use core::future::{poll_fn, Future}; use core::task::{Context, Poll}; -use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::gpio::sealed::Pin as _; diff --git a/embassy-nrf/src/i2s.rs b/embassy-nrf/src/i2s.rs index fea38c4c..907acdf4 100644 --- a/embassy-nrf/src/i2s.rs +++ b/embassy-nrf/src/i2s.rs @@ -9,8 +9,8 @@ use core::ops::{Deref, DerefMut}; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::gpio::{AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index d23759f9..355a0049 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -98,7 +98,7 @@ mod chip; /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { @@ -127,7 +127,7 @@ pub use chip::pac; #[cfg(not(feature = "unstable-pac"))] pub(crate) use chip::pac; pub use chip::{peripherals, Peripherals, EASY_DMA_SIZE}; -pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; pub use crate::chip::interrupt; pub use crate::pac::NVIC_PRIO_BITS; diff --git a/embassy-nrf/src/nvmc.rs b/embassy-nrf/src/nvmc.rs index 91a5a272..de840b88 100644 --- a/embassy-nrf/src/nvmc.rs +++ b/embassy-nrf/src/nvmc.rs @@ -2,7 +2,7 @@ use core::{ptr, slice}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embedded_storage::nor_flash::{ ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, }; diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 217884d1..01f41e9f 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -6,8 +6,8 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use fixed::types::I7F1; use futures::future::poll_fn; diff --git a/embassy-nrf/src/ppi/dppi.rs b/embassy-nrf/src/ppi/dppi.rs index 40ccb2f0..0bc7f821 100644 --- a/embassy-nrf/src/ppi/dppi.rs +++ b/embassy-nrf/src/ppi/dppi.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use super::{Channel, ConfigurableChannel, Event, Ppi, Task}; use crate::{pac, Peripheral}; diff --git a/embassy-nrf/src/ppi/mod.rs b/embassy-nrf/src/ppi/mod.rs index ff6593bd..5b4a6438 100644 --- a/embassy-nrf/src/ppi/mod.rs +++ b/embassy-nrf/src/ppi/mod.rs @@ -18,7 +18,7 @@ use core::marker::PhantomData; use core::ptr::NonNull; -use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; use crate::{peripherals, Peripheral}; diff --git a/embassy-nrf/src/ppi/ppi.rs b/embassy-nrf/src/ppi/ppi.rs index 1fe89862..3e9e9fc8 100644 --- a/embassy-nrf/src/ppi/ppi.rs +++ b/embassy-nrf/src/ppi/ppi.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use super::{Channel, ConfigurableChannel, Event, Ppi, StaticChannel, Task}; use crate::{pac, Peripheral}; diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index c8c81fa0..2f039763 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -4,7 +4,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin, PselBits}; diff --git a/embassy-nrf/src/qdec.rs b/embassy-nrf/src/qdec.rs index 8bac87d3..2aa50a2b 100644 --- a/embassy-nrf/src/qdec.rs +++ b/embassy-nrf/src/qdec.rs @@ -6,7 +6,7 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::gpio::sealed::Pin as _; use crate::gpio::{AnyPin, Pin as GpioPin}; diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index baefc796..36ee33f6 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -7,8 +7,8 @@ use core::marker::PhantomData; use core::ptr; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; use crate::gpio::{self, Pin as GpioPin}; diff --git a/embassy-nrf/src/rng.rs b/embassy-nrf/src/rng.rs index 923b8b46..e2803f0d 100644 --- a/embassy-nrf/src/rng.rs +++ b/embassy-nrf/src/rng.rs @@ -8,8 +8,8 @@ use core::ptr; use core::sync::atomic::{AtomicPtr, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::interrupt::typelevel::Interrupt; diff --git a/embassy-nrf/src/saadc.rs b/embassy-nrf/src/saadc.rs index 23292924..662b0561 100644 --- a/embassy-nrf/src/saadc.rs +++ b/embassy-nrf/src/saadc.rs @@ -6,8 +6,8 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::{saadc, SAADC}; use saadc::ch::config::{GAIN_A, REFSEL_A, RESP_A, TACQ_A}; diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index b7dc332e..4673a017 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -8,7 +8,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy_embedded_hal::SetConfig; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use pac::spim0::frequency::FREQUENCY_A as Frequency; diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs index aa438415..21282512 100644 --- a/embassy-nrf/src/spis.rs +++ b/embassy-nrf/src/spis.rs @@ -7,7 +7,7 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; use embassy_embedded_hal::SetConfig; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; use crate::chip::FORCE_COPY_BUFFER_SIZE; diff --git a/embassy-nrf/src/temp.rs b/embassy-nrf/src/temp.rs index 491e92c0..cec46d8d 100644 --- a/embassy-nrf/src/temp.rs +++ b/embassy-nrf/src/temp.rs @@ -3,8 +3,8 @@ use core::future::poll_fn; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::I30F2; diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 04748238..3dbfdac4 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -6,7 +6,7 @@ #![macro_use] -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::ppi::{Event, Task}; use crate::{pac, Peripheral}; diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index 2ad0d19b..fdea480e 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -9,7 +9,7 @@ use core::sync::atomic::Ordering::SeqCst; use core::task::Poll; use embassy_embedded_hal::SetConfig; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; diff --git a/embassy-nrf/src/twis.rs b/embassy-nrf/src/twis.rs index a115d561..c6c02055 100644 --- a/embassy-nrf/src/twis.rs +++ b/embassy-nrf/src/twis.rs @@ -8,7 +8,7 @@ use core::sync::atomic::compiler_fence; use core::sync::atomic::Ordering::SeqCst; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; #[cfg(feature = "time")] use embassy_time::{Duration, Instant}; diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 48d57fea..e79df356 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -18,8 +18,8 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use pac::uarte0::RegisterBlock; // Re-export SVD variants to allow user to directly set values. pub use pac::uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; diff --git a/embassy-nrf/src/usb/mod.rs b/embassy-nrf/src/usb/mod.rs index 76cf40ac..e26b49db 100644 --- a/embassy-nrf/src/usb/mod.rs +++ b/embassy-nrf/src/usb/mod.rs @@ -11,7 +11,7 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; use core::task::Poll; use cortex_m::peripheral::NVIC; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver as driver; use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported}; diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index 8f3ed885..6310ffb6 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -16,7 +16,7 @@ flavors = [ default = [ "rt" ] rt = [ "rp-pac/rt" ] -defmt = ["dep:defmt", "embassy-usb-driver?/defmt", "embassy-hal-common/defmt"] +defmt = ["dep:defmt", "embassy-usb-driver?/defmt", "embassy-hal-internal/defmt"] # critical section that is safe for multicore use critical-section-impl = ["critical-section/restore-state-u8"] @@ -48,7 +48,7 @@ boot2-w25x10cl = [] run-from-ram = [] # Enable nightly-only features -nightly = ["embedded-hal-1", "embedded-hal-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] +nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "embassy-embedded-hal/nightly", "dep:embassy-usb-driver", "dep:embedded-io"] # Implement embedded-hal 1.0 alpha traits. # Implement embedded-hal-async traits if `nightly` is set as well. @@ -58,7 +58,7 @@ unstable-traits = ["embedded-hal-1", "embedded-hal-nb"] embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.2", path = "../embassy-time", features = [ "tick-hz-1_000_000" ] } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-2"] } +embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } atomic-polyfill = "1.0.1" @@ -73,6 +73,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa chrono = { version = "0.4", default-features = false, optional = true } embedded-io = { version = "0.4.0", features = ["async"], optional = true } embedded-storage = { version = "0.3" } +embedded-storage-async = { version = "0.4.0", optional = true } rand_core = "0.6.4" fixed = "1.23.1" diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs index 95780c06..4fba3116 100644 --- a/embassy-rp/src/adc.rs +++ b/embassy-rp/src/adc.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::gpio::sealed::Pin as GpioPin; diff --git a/embassy-rp/src/clocks.rs b/embassy-rp/src/clocks.rs index acb21dce..976d06de 100644 --- a/embassy-rp/src/clocks.rs +++ b/embassy-rp/src/clocks.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use pac::clocks::vals::*; use crate::gpio::sealed::Pin; diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 1a458778..c8f74180 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -4,7 +4,7 @@ use core::pin::Pin; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; -use embassy_hal_common::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::dma::vals::DataSize; diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 96d2d454..70d86731 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -1,11 +1,15 @@ +use core::future::Future; use core::marker::PhantomData; +use core::pin::Pin; +use core::task::{Context, Poll}; -use embassy_hal_common::Peripheral; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embedded_storage::nor_flash::{ check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash, }; +use crate::dma::{AnyChannel, Channel, Transfer}; use crate::pac; use crate::peripherals::FLASH; @@ -24,6 +28,7 @@ pub const PAGE_SIZE: usize = 256; pub const WRITE_SIZE: usize = 1; pub const READ_SIZE: usize = 1; pub const ERASE_SIZE: usize = 4096; +pub const ASYNC_READ_SIZE: usize = 4; /// Error type for NVMC operations. #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -57,13 +62,46 @@ impl NorFlashError for Error { } } -pub struct Flash<'d, T: Instance, const FLASH_SIZE: usize>(PhantomData<&'d mut T>); +/// Future that waits for completion of a background read +#[must_use = "futures do nothing unless you `.await` or poll them"] +pub struct BackgroundRead<'a, 'd, T: Instance, const FLASH_SIZE: usize> { + flash: PhantomData<&'a mut Flash<'d, T, Async, FLASH_SIZE>>, + transfer: Transfer<'a, AnyChannel>, +} -impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { - pub fn new(_flash: impl Peripheral

+ 'd) -> Self { - Self(PhantomData) +impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Future for BackgroundRead<'a, 'd, T, FLASH_SIZE> { + type Output = (); + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + Pin::new(&mut self.transfer).poll(cx) } +} +impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, 'd, T, FLASH_SIZE> { + fn drop(&mut self) { + if pac::XIP_CTRL.stream_ctr().read().0 == 0 { + return; + } + pac::XIP_CTRL + .stream_ctr() + .write_value(pac::xip_ctrl::regs::StreamCtr(0)); + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + // Errata RP2040-E8: Perform an uncached read to make sure there's not a transfer in + // flight that might effect an address written to start a new transfer. This stalls + // until after any transfer is complete, so the address will not change anymore. + const XIP_NOCACHE_NOALLOC_BASE: *const u32 = 0x13000000 as *const _; + unsafe { + core::ptr::read_volatile(XIP_NOCACHE_NOALLOC_BASE); + } + core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst); + } +} + +pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> { + dma: Option>, + phantom: PhantomData<(&'d mut T, M)>, +} + +impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SIZE> { pub fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Error> { trace!( "Reading from 0x{:x} to 0x{:x}", @@ -182,6 +220,8 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { let ch = crate::pac::DMA.ch(n); while ch.read_addr().read() < SRAM_LOWER && ch.ctrl_trig().read().busy() {} } + // Wait for completion of any background reads + while pac::XIP_CTRL.stream_ctr().read().0 > 0 {} // Run our flash operation in RAM operation(); @@ -210,11 +250,73 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, FLASH_SIZE> { } } -impl<'d, T: Instance, const FLASH_SIZE: usize> ErrorType for Flash<'d, T, FLASH_SIZE> { +impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> { + pub fn new(_flash: impl Peripheral

+ 'd) -> Self { + Self { + dma: None, + phantom: PhantomData, + } + } +} + +impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> { + pub fn new(_flash: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd) -> Self { + into_ref!(dma); + Self { + dma: Some(dma.map_into()), + phantom: PhantomData, + } + } + + pub fn background_read<'a>( + &'a mut self, + offset: u32, + data: &'a mut [u32], + ) -> Result, Error> { + trace!( + "Reading in background from 0x{:x} to 0x{:x}", + FLASH_BASE as u32 + offset, + FLASH_BASE as u32 + offset + (data.len() * 4) as u32 + ); + // Can't use check_read because we need to enforce 4-byte alignment + let offset = offset as usize; + let length = data.len() * 4; + if length > self.capacity() || offset > self.capacity() - length { + return Err(Error::OutOfBounds); + } + if offset % 4 != 0 { + return Err(Error::Unaligned); + } + + while !pac::XIP_CTRL.stat().read().fifo_empty() { + pac::XIP_CTRL.stream_fifo().read(); + } + + pac::XIP_CTRL + .stream_addr() + .write_value(pac::xip_ctrl::regs::StreamAddr(FLASH_BASE as u32 + offset as u32)); + pac::XIP_CTRL + .stream_ctr() + .write_value(pac::xip_ctrl::regs::StreamCtr(data.len() as u32)); + + // Use the XIP AUX bus port, rather than the FIFO register access (e.x. + // pac::XIP_CTRL.stream_fifo().as_ptr()) to avoid DMA stalling on + // general XIP access. + const XIP_AUX_BASE: *const u32 = 0x50400000 as *const _; + let transfer = unsafe { crate::dma::read(self.dma.as_mut().unwrap(), XIP_AUX_BASE, data, 37) }; + + Ok(BackgroundRead { + flash: PhantomData, + transfer, + }) + } +} + +impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> ErrorType for Flash<'d, T, M, FLASH_SIZE> { type Error = Error; } -impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, FLASH_SIZE> { +impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, M, FLASH_SIZE> { const READ_SIZE: usize = READ_SIZE; fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { @@ -226,9 +328,9 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> ReadNorFlash for Flash<'d, T, FLA } } -impl<'d, T: Instance, const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<'d, T, FLASH_SIZE> {} +impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> MultiwriteNorFlash for Flash<'d, T, M, FLASH_SIZE> {} -impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_SIZE> { +impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, M, FLASH_SIZE> { const WRITE_SIZE: usize = WRITE_SIZE; const ERASE_SIZE: usize = ERASE_SIZE; @@ -242,6 +344,74 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> NorFlash for Flash<'d, T, FLASH_S } } +#[cfg(feature = "nightly")] +impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash::ReadNorFlash + for Flash<'d, T, Async, FLASH_SIZE> +{ + const READ_SIZE: usize = ASYNC_READ_SIZE; + + async fn read(&mut self, offset: u32, bytes: &mut [u8]) -> Result<(), Self::Error> { + use core::mem::MaybeUninit; + + // Checked early to simplify address validity checks + if bytes.len() % 4 != 0 { + return Err(Error::Unaligned); + } + + // If the destination address is already aligned, then we can just DMA directly + if (bytes.as_ptr() as u32) % 4 == 0 { + // Safety: alignment and size have been checked for compatibility + let mut buf: &mut [u32] = + unsafe { core::slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u32, bytes.len() / 4) }; + self.background_read(offset, &mut buf)?.await; + return Ok(()); + } + + // Destination address is unaligned, so use an intermediate buffer + const REALIGN_CHUNK: usize = PAGE_SIZE; + // Safety: MaybeUninit requires no initialization + let mut buf: [MaybeUninit; REALIGN_CHUNK / 4] = unsafe { MaybeUninit::uninit().assume_init() }; + let mut chunk_offset: usize = 0; + while chunk_offset < bytes.len() { + let chunk_size = (bytes.len() - chunk_offset).min(REALIGN_CHUNK); + let buf = &mut buf[..(chunk_size / 4)]; + + // Safety: this is written to completely by DMA before any reads + let buf = unsafe { &mut *(buf as *mut [MaybeUninit] as *mut [u32]) }; + self.background_read(offset + chunk_offset as u32, buf)?.await; + + // Safety: [u8] has more relaxed alignment and size requirements than [u32], so this is just aliasing + let buf = unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const _, buf.len() * 4) }; + bytes[chunk_offset..(chunk_offset + chunk_size)].copy_from_slice(&buf[..chunk_size]); + + chunk_offset += chunk_size; + } + + Ok(()) + } + + fn capacity(&self) -> usize { + self.capacity() + } +} + +#[cfg(feature = "nightly")] +impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash::NorFlash + for Flash<'d, T, Async, FLASH_SIZE> +{ + const WRITE_SIZE: usize = WRITE_SIZE; + + const ERASE_SIZE: usize = ERASE_SIZE; + + async fn erase(&mut self, from: u32, to: u32) -> Result<(), Self::Error> { + self.erase(from, to) + } + + async fn write(&mut self, offset: u32, bytes: &[u8]) -> Result<(), Self::Error> { + self.write(offset, bytes) + } +} + #[allow(dead_code)] mod ram_helpers { use core::marker::PhantomData; @@ -699,9 +869,24 @@ mod ram_helpers { mod sealed { pub trait Instance {} + pub trait Mode {} } pub trait Instance: sealed::Instance {} +pub trait Mode: sealed::Mode {} impl sealed::Instance for FLASH {} impl Instance for FLASH {} + +macro_rules! impl_mode { + ($name:ident) => { + impl sealed::Mode for $name {} + impl Mode for $name {} + }; +} + +pub struct Blocking; +pub struct Async; + +impl_mode!(Blocking); +impl_mode!(Async); diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index a3d330cd..2807eb67 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -3,7 +3,7 @@ use core::future::Future; use core::pin::Pin as FuturePin; use core::task::{Context, Poll}; -use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::interrupt::InterruptExt; diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 9b85b234..536ad747 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -2,7 +2,7 @@ use core::future; use core::marker::PhantomData; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use pac::i2c; diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4f205a16..45156458 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -33,10 +33,10 @@ pub mod watchdog; // TODO: move `pio_instr_util` and `relocate` to inside `pio` pub mod pio; pub mod pio_instr_util; -pub mod relocate; +pub(crate) mod relocate; // Reexports -pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use rp_pac as pac; #[cfg(not(feature = "unstable-pac"))] @@ -45,7 +45,7 @@ pub(crate) use rp_pac as pac; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; -embassy_hal_common::interrupt_mod!( +embassy_hal_internal::interrupt_mod!( TIMER_IRQ_0, TIMER_IRQ_1, TIMER_IRQ_2, @@ -85,7 +85,7 @@ embassy_hal_common::interrupt_mod!( /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { @@ -107,7 +107,7 @@ macro_rules! bind_interrupts { }; } -embassy_hal_common::peripherals! { +embassy_hal_internal::peripherals! { PIN_0, PIN_1, PIN_2, @@ -219,6 +219,74 @@ select_bootloader! { default => BOOT_LOADER_W25Q080 } +/// Installs a stack guard for the CORE0 stack in MPU region 0. +/// Will fail if the MPU is already confgigured. This function requires +/// a `_stack_end` symbol to be defined by the linker script, and expexcts +/// `_stack_end` to be located at the lowest address (largest depth) of +/// the stack. +/// +/// This method can *only* set up stack guards on the currently +/// executing core. Stack guards for CORE1 are set up automatically, +/// only CORE0 should ever use this. +/// +/// # Usage +/// +/// ```no_run +/// #![feature(type_alias_impl_trait)] +/// use embassy_rp::install_core0_stack_guard; +/// use embassy_executor::{Executor, Spawner}; +/// +/// #[embassy_executor::main] +/// async fn main(_spawner: Spawner) { +/// // set up by the linker as follows: +/// // +/// // MEMORY { +/// // STACK0: ORIGIN = 0x20040000, LENGTH = 4K +/// // } +/// // +/// // _stack_end = ORIGIN(STACK0); +/// // _stack_start = _stack_end + LENGTH(STACK0); +/// // +/// install_core0_stack_guard().expect("MPU already configured"); +/// let p = embassy_rp::init(Default::default()); +/// +/// // ... +/// } +/// ``` +pub fn install_core0_stack_guard() -> Result<(), ()> { + extern "C" { + static mut _stack_end: usize; + } + unsafe { install_stack_guard(&mut _stack_end as *mut usize) } +} + +#[inline(always)] +fn install_stack_guard(stack_bottom: *mut usize) -> Result<(), ()> { + let core = unsafe { cortex_m::Peripherals::steal() }; + + // Fail if MPU is already configured + if core.MPU.ctrl.read() != 0 { + return Err(()); + } + + // The minimum we can protect is 32 bytes on a 32 byte boundary, so round up which will + // just shorten the valid stack range a tad. + let addr = (stack_bottom as u32 + 31) & !31; + // Mask is 1 bit per 32 bytes of the 256 byte range... clear the bit for the segment we want + let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7)); + unsafe { + core.MPU.ctrl.write(5); // enable mpu with background default map + core.MPU.rbar.write((addr & !0xff) | (1 << 4)); // set address and update RNR + core.MPU.rasr.write( + 1 // enable region + | (0x7 << 1) // size 2^(7 + 1) = 256 + | (subregion_select << 8) + | 0x10000000, // XN = disable instruction fetch; no other bits means no permissions + ); + } + Ok(()) +} + pub mod config { use crate::clocks::ClockConfig; diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index 468e8470..91576180 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -52,41 +52,20 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; use crate::interrupt::InterruptExt; use crate::peripherals::CORE1; -use crate::{gpio, interrupt, pac}; +use crate::{gpio, install_stack_guard, interrupt, pac}; const PAUSE_TOKEN: u32 = 0xDEADBEEF; const RESUME_TOKEN: u32 = !0xDEADBEEF; static IS_CORE1_INIT: AtomicBool = AtomicBool::new(false); #[inline(always)] -fn install_stack_guard(stack_bottom: *mut usize) { - let core = unsafe { cortex_m::Peripherals::steal() }; - - // Trap if MPU is already configured - if core.MPU.ctrl.read() != 0 { +fn core1_setup(stack_bottom: *mut usize) { + if let Err(_) = install_stack_guard(stack_bottom) { + // currently only happens if the MPU was already set up, which + // would indicate that the core is already in use from outside + // embassy, somehow. trap if so since we can't deal with that. cortex_m::asm::udf(); } - - // The minimum we can protect is 32 bytes on a 32 byte boundary, so round up which will - // just shorten the valid stack range a tad. - let addr = (stack_bottom as u32 + 31) & !31; - // Mask is 1 bit per 32 bytes of the 256 byte range... clear the bit for the segment we want - let subregion_select = 0xff ^ (1 << ((addr >> 5) & 7)); - unsafe { - core.MPU.ctrl.write(5); // enable mpu with background default map - core.MPU.rbar.write((addr & !0xff) | 0x8); - core.MPU.rasr.write( - 1 // enable region - | (0x7 << 1) // size 2^(7 + 1) = 256 - | (subregion_select << 8) - | 0x10000000, // XN = disable instruction fetch; no other bits means no permissions - ); - } -} - -#[inline(always)] -fn core1_setup(stack_bottom: *mut usize) { - install_stack_guard(stack_bottom); unsafe { gpio::init(); } diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 72a2f44e..3de398af 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs @@ -5,13 +5,13 @@ use core::sync::atomic::{compiler_fence, Ordering}; use core::task::{Context, Poll}; use atomic_polyfill::{AtomicU32, AtomicU8}; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use fixed::types::extra::U8; use fixed::FixedU32; use pac::io::vals::Gpio0ctrlFuncsel; use pac::pio::vals::SmExecctrlStatusSel; -use pio::{SideSet, Wrap}; +use pio::{Program, SideSet, Wrap}; use crate::dma::{Channel, Transfer, Word}; use crate::gpio::sealed::Pin as SealedPin; @@ -734,23 +734,67 @@ pub struct InstanceMemory<'d, PIO: Instance> { pub struct LoadedProgram<'d, PIO: Instance> { pub used_memory: InstanceMemory<'d, PIO>, - origin: u8, - wrap: Wrap, - side_set: SideSet, + pub origin: u8, + pub wrap: Wrap, + pub side_set: SideSet, +} + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum LoadError { + /// Insufficient consecutive free instruction space to load program. + InsufficientSpace, + /// Loading the program would overwrite an instruction address already + /// used by another program. + AddressInUse(usize), } impl<'d, PIO: Instance> Common<'d, PIO> { - pub fn load_program(&mut self, prog: &RelocatedProgram) -> LoadedProgram<'d, PIO> { + /// Load a PIO program. This will automatically relocate the program to + /// an available chunk of free instruction memory if the program origin + /// was not explicitly specified, otherwise it will attempt to load the + /// program only at its origin. + pub fn load_program(&mut self, prog: &Program) -> LoadedProgram<'d, PIO> { match self.try_load_program(prog) { Ok(r) => r, - Err(at) => panic!("Trying to write already used PIO instruction memory at {}", at), + Err(e) => panic!("Failed to load PIO program: {:?}", e), } } + /// Load a PIO program. This will automatically relocate the program to + /// an available chunk of free instruction memory if the program origin + /// was not explicitly specified, otherwise it will attempt to load the + /// program only at its origin. pub fn try_load_program( &mut self, - prog: &RelocatedProgram, + prog: &Program, + ) -> Result, LoadError> { + match prog.origin { + Some(origin) => self + .try_load_program_at(prog, origin) + .map_err(|a| LoadError::AddressInUse(a)), + None => { + // naively search for free space, allowing wraparound since + // PIO does support that. with only 32 instruction slots it + // doesn't make much sense to do anything more fancy. + let mut origin = 0; + while origin < 32 { + match self.try_load_program_at(prog, origin as _) { + Ok(r) => return Ok(r), + Err(a) => origin = a + 1, + } + } + Err(LoadError::InsufficientSpace) + } + } + } + + fn try_load_program_at( + &mut self, + prog: &Program, + origin: u8, ) -> Result, usize> { + let prog = RelocatedProgram::new_with_origin(prog, origin); let used_memory = self.try_write_instr(prog.origin() as _, prog.code())?; Ok(LoadedProgram { used_memory, @@ -760,7 +804,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> { }) } - pub fn try_write_instr(&mut self, start: usize, instrs: I) -> Result, usize> + fn try_write_instr(&mut self, start: usize, instrs: I) -> Result, usize> where I: Iterator, { diff --git a/embassy-rp/src/pwm.rs b/embassy-rp/src/pwm.rs index 20bb8844..c0ddb2a9 100644 --- a/embassy-rp/src/pwm.rs +++ b/embassy-rp/src/pwm.rs @@ -1,6 +1,6 @@ //! Pulse Width Modulation (PWM) -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use fixed::traits::ToFixed; use fixed::FixedU16; use pac::pwm::regs::{ChDiv, Intr}; diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs index 9cb279cc..b35b4ed7 100644 --- a/embassy-rp/src/relocate.rs +++ b/embassy-rp/src/relocate.rs @@ -41,11 +41,6 @@ pub struct RelocatedProgram<'a, const PROGRAM_SIZE: usize> { } impl<'a, const PROGRAM_SIZE: usize> RelocatedProgram<'a, PROGRAM_SIZE> { - pub fn new(program: &Program) -> RelocatedProgram { - let origin = program.origin.unwrap_or(0); - RelocatedProgram { program, origin } - } - pub fn new_with_origin(program: &Program, origin: u8) -> RelocatedProgram { RelocatedProgram { program, origin } } diff --git a/embassy-rp/src/rtc/mod.rs b/embassy-rp/src/rtc/mod.rs index 1b33fdf8..60ca8627 100644 --- a/embassy-rp/src/rtc/mod.rs +++ b/embassy-rp/src/rtc/mod.rs @@ -1,6 +1,6 @@ mod filter; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; pub use self::filter::DateTimeFilter; diff --git a/embassy-rp/src/spi.rs b/embassy-rp/src/spi.rs index af101cf4..544b542e 100644 --- a/embassy-rp/src/spi.rs +++ b/embassy-rp/src/spi.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use embassy_embedded_hal::SetConfig; use embassy_futures::join::join; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Phase, Polarity}; use crate::dma::{AnyChannel, Channel}; diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 30eeb547..9d96db12 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -3,7 +3,7 @@ use core::slice; use core::task::Poll; use atomic_polyfill::{AtomicU8, Ordering}; -use embassy_hal_common::atomic_ring_buffer::RingBuffer; +use embassy_hal_internal::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Timer}; diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs index 7b94bce5..69c6ac2f 100644 --- a/embassy-rp/src/uart/mod.rs +++ b/embassy-rp/src/uart/mod.rs @@ -4,7 +4,7 @@ use core::task::Poll; use atomic_polyfill::{AtomicU16, Ordering}; use embassy_futures::select::{select, Either}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Timer}; use pac::uart::regs::Uartris; diff --git a/embassy-stm32-wpan/Cargo.toml b/embassy-stm32-wpan/Cargo.toml index 6cd12220..96c47484 100644 --- a/embassy-stm32-wpan/Cargo.toml +++ b/embassy-stm32-wpan/Cargo.toml @@ -15,7 +15,7 @@ embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-common = { version = "0.1.0", path = "../embassy-hal-common" } +embassy-hal-internal = { version = "0.1.0", path = "../embassy-hal-internal" } embassy-embedded-hal = { version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver", optional=true } @@ -26,12 +26,12 @@ aligned = "0.4.1" bit_field = "0.10.2" stm32-device-signature = { version = "0.3.3", features = ["stm32wb5x"] } -stm32wb-hci = { version = "0.1.3", optional = true } +stm32wb-hci = { version = "0.1.4", optional = true } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } bitflags = { version = "2.3.3", optional = true } [features] -defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "stm32wb-hci?/defmt"] +defmt = ["dep:defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "stm32wb-hci?/defmt"] ble = ["dep:stm32wb-hci"] mac = ["dep:bitflags", "dep:embassy-net-driver" ] diff --git a/embassy-stm32-wpan/src/lib.rs b/embassy-stm32-wpan/src/lib.rs index 6836d7a8..5ecce2cc 100644 --- a/embassy-stm32-wpan/src/lib.rs +++ b/embassy-stm32-wpan/src/lib.rs @@ -8,7 +8,7 @@ pub mod fmt; use core::mem::MaybeUninit; use core::sync::atomic::{compiler_fence, Ordering}; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_stm32::interrupt; use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler}; use embassy_stm32::peripherals::IPCC; diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index cb064433..8c7dd38c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -34,7 +34,7 @@ flavors = [ embassy-sync = { version = "0.2.0", path = "../embassy-sync" } embassy-time = { version = "0.1.2", path = "../embassy-time", optional = true } embassy-futures = { version = "0.1.0", path = "../embassy-futures" } -embassy-hal-common = {version = "0.1.0", path = "../embassy-hal-common", features = ["cortex-m", "prio-bits-4"] } +embassy-hal-internal = {version = "0.1.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-4"] } embassy-embedded-hal = {version = "0.1.0", path = "../embassy-embedded-hal" } embassy-net-driver = { version = "0.1.0", path = "../embassy-net-driver" } embassy-usb-driver = {version = "0.1.0", path = "../embassy-usb-driver", optional = true } @@ -57,7 +57,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = "13" +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -67,6 +67,7 @@ cfg-if = "1.0.0" embedded-io = { version = "0.4.0", features = ["async"], optional = true } chrono = { version = "^0.4", default-features = false, optional = true} bit_field = "0.10.2" +document-features = "0.2.7" [dev-dependencies] critical-section = { version = "1.1", features = ["std"] } @@ -74,44 +75,67 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { version = "13", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-1f8ab493e029fc601edebc6bac105a63cc9858fe", default-features = false, features = ["metadata"]} [features] default = ["rt"] + +## Enable `stm32-metapac`'s `rt` feature rt = ["stm32-metapac/rt"] -defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-common/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] -memory-x = ["stm32-metapac/memory-x"] +## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging +defmt = ["dep:defmt", "bxcan/unstable-defmt", "embassy-sync/defmt", "embassy-embedded-hal/defmt", "embassy-hal-internal/defmt", "embedded-io?/defmt", "embassy-usb-driver?/defmt", "embassy-net-driver/defmt", "embassy-time?/defmt"] + exti = [] -# Enables additional driver features that depend on embassy-time +## Automatically generate `memory.x` file using [`stm32-metapac`](https://docs.rs/stm32-metapac/) +memory-x = ["stm32-metapac/memory-x"] + +## Enable nightly-only features +nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] + +## Re-export stm32-metapac at `embassy_stm32::pac`. +## This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. +## If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. +## There are no plans to make this stable. +unstable-pac = [] + +## Implement embedded-hal 1.0 alpha traits. +## Implement embedded-hal-async traits if `nightly` is set as well. +unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"] + +#! ## Time + +## Enables additional driver features that depend on embassy-time time = ["dep:embassy-time"] # Features starting with `_` are for internal use only. They're not intended # to be enabled by other crates, and are not covered by semver guarantees. _time-driver = ["time"] + +## Use any time driver time-driver-any = ["_time-driver"] +## Use TIM2 as time driver time-driver-tim2 = ["_time-driver"] +## Use TIM3 as time driver time-driver-tim3 = ["_time-driver"] +## Use TIM4 as time driver time-driver-tim4 = ["_time-driver"] +## Use TIM5 as time driver time-driver-tim5 = ["_time-driver"] +## Use TIM12 as time driver time-driver-tim12 = ["_time-driver"] +## Use TIM15 as time driver time-driver-tim15 = ["_time-driver"] -# Enable nightly-only features -nightly = ["embedded-hal-1", "embedded-hal-async", "embedded-storage-async", "dep:embedded-io", "dep:embassy-usb-driver", "embassy-embedded-hal/nightly"] -# Reexport stm32-metapac at `embassy_stm32::pac`. -# This is unstable because semver-minor (non-breaking) releases of embassy-stm32 may major-bump (breaking) the stm32-metapac version. -# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. -# There are no plans to make this stable. -unstable-pac = [] +#! ## Chip-selection features +#! Select your chip by specifying the model as a feature, e.g. `stm32c011d6`. +#! Check the `Cargo.toml` for the latest list of supported chips. +#! +#! **Important:** Do not forget to adapt the target chip in your toolchain, +#! e.g. in `.cargo/config.toml`. -# Implement embedded-hal 1.0 alpha traits. -# Implement embedded-hal-async traits if `nightly` is set as well. -unstable-traits = ["embedded-hal-1", "dep:embedded-hal-nb"] - -# Chip-selection features stm32c011d6 = [ "stm32-metapac/stm32c011d6" ] stm32c011f4 = [ "stm32-metapac/stm32c011f4" ] stm32c011f6 = [ "stm32-metapac/stm32c011f6" ] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 995ad144..9b3caefd 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -138,7 +138,7 @@ fn main() { let singleton_tokens: Vec<_> = singletons.iter().map(|s| format_ident!("{}", s)).collect(); g.extend(quote! { - embassy_hal_common::peripherals_definition!(#(#singleton_tokens),*); + embassy_hal_internal::peripherals_definition!(#(#singleton_tokens),*); }); let singleton_tokens: Vec<_> = singletons @@ -148,7 +148,7 @@ fn main() { .collect(); g.extend(quote! { - embassy_hal_common::peripherals_struct!(#(#singleton_tokens),*); + embassy_hal_internal::peripherals_struct!(#(#singleton_tokens),*); }); // ======== @@ -160,7 +160,7 @@ fn main() { } g.extend(quote! { - embassy_hal_common::interrupt_mod!( + embassy_hal_internal::interrupt_mod!( #( #irqs, )* @@ -211,7 +211,7 @@ fn main() { let region_type = format_ident!("{}", get_flash_region_type_name(region.name)); flash_regions.extend(quote! { #[cfg(flash)] - pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); + pub struct #region_type<'d, MODE = crate::flash::Async>(pub &'static crate::flash::FlashRegion, pub(crate) embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData); }); } @@ -243,7 +243,7 @@ fn main() { #[cfg(flash)] impl<'d, MODE> FlashLayout<'d, MODE> { - pub(crate) fn new(p: embassy_hal_common::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { + pub(crate) fn new(p: embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self { Self { #(#inits),*, _mode: core::marker::PhantomData, @@ -572,21 +572,31 @@ fn main() { (("fmc", "Clk"), quote!(crate::fmc::ClkPin)), (("fmc", "BA0"), quote!(crate::fmc::BA0Pin)), (("fmc", "BA1"), quote!(crate::fmc::BA1Pin)), - (("timer", "CH1"), quote!(crate::pwm::Channel1Pin)), - (("timer", "CH1N"), quote!(crate::pwm::Channel1ComplementaryPin)), - (("timer", "CH2"), quote!(crate::pwm::Channel2Pin)), - (("timer", "CH2N"), quote!(crate::pwm::Channel2ComplementaryPin)), - (("timer", "CH3"), quote!(crate::pwm::Channel3Pin)), - (("timer", "CH3N"), quote!(crate::pwm::Channel3ComplementaryPin)), - (("timer", "CH4"), quote!(crate::pwm::Channel4Pin)), - (("timer", "CH4N"), quote!(crate::pwm::Channel4ComplementaryPin)), - (("timer", "ETR"), quote!(crate::pwm::ExternalTriggerPin)), - (("timer", "BKIN"), quote!(crate::pwm::BreakInputPin)), - (("timer", "BKIN_COMP1"), quote!(crate::pwm::BreakInputComparator1Pin)), - (("timer", "BKIN_COMP2"), quote!(crate::pwm::BreakInputComparator2Pin)), - (("timer", "BKIN2"), quote!(crate::pwm::BreakInput2Pin)), - (("timer", "BKIN2_COMP1"), quote!(crate::pwm::BreakInput2Comparator1Pin)), - (("timer", "BKIN2_COMP2"), quote!(crate::pwm::BreakInput2Comparator2Pin)), + (("timer", "CH1"), quote!(crate::timer::Channel1Pin)), + (("timer", "CH1N"), quote!(crate::timer::Channel1ComplementaryPin)), + (("timer", "CH2"), quote!(crate::timer::Channel2Pin)), + (("timer", "CH2N"), quote!(crate::timer::Channel2ComplementaryPin)), + (("timer", "CH3"), quote!(crate::timer::Channel3Pin)), + (("timer", "CH3N"), quote!(crate::timer::Channel3ComplementaryPin)), + (("timer", "CH4"), quote!(crate::timer::Channel4Pin)), + (("timer", "CH4N"), quote!(crate::timer::Channel4ComplementaryPin)), + (("timer", "ETR"), quote!(crate::timer::ExternalTriggerPin)), + (("timer", "BKIN"), quote!(crate::timer::BreakInputPin)), + (("timer", "BKIN_COMP1"), quote!(crate::timer::BreakInputComparator1Pin)), + (("timer", "BKIN_COMP2"), quote!(crate::timer::BreakInputComparator2Pin)), + (("timer", "BKIN2"), quote!(crate::timer::BreakInput2Pin)), + (("timer", "BKIN2_COMP1"), quote!(crate::timer::BreakInput2Comparator1Pin)), + (("timer", "BKIN2_COMP2"), quote!(crate::timer::BreakInput2Comparator2Pin)), + (("hrtim", "CHA1"), quote!(crate::hrtim::ChannelAPin)), + (("hrtim", "CHA2"), quote!(crate::hrtim::ChannelAComplementaryPin)), + (("hrtim", "CHB1"), quote!(crate::hrtim::ChannelBPin)), + (("hrtim", "CHB2"), quote!(crate::hrtim::ChannelBComplementaryPin)), + (("hrtim", "CHC1"), quote!(crate::hrtim::ChannelCPin)), + (("hrtim", "CHC2"), quote!(crate::hrtim::ChannelCComplementaryPin)), + (("hrtim", "CHD1"), quote!(crate::hrtim::ChannelDPin)), + (("hrtim", "CHD2"), quote!(crate::hrtim::ChannelDComplementaryPin)), + (("hrtim", "CHE1"), quote!(crate::hrtim::ChannelEPin)), + (("hrtim", "CHE2"), quote!(crate::hrtim::ChannelEComplementaryPin)), (("sdmmc", "CK"), quote!(crate::sdmmc::CkPin)), (("sdmmc", "CMD"), quote!(crate::sdmmc::CmdPin)), (("sdmmc", "D0"), quote!(crate::sdmmc::D0Pin)), diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index 2322204d..e577ec28 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use embedded_hal_02::blocking::delay::DelayUs; use crate::adc::{Adc, AdcPin, Instance, SampleTime}; diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index d9af0c55..e8245884 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use embedded_hal_02::blocking::delay::DelayUs; use crate::adc::{Adc, AdcPin, Instance, InternalChannel, Resolution, SampleTime}; diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 091c1d44..9a7acea5 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use embedded_hal_02::blocking::delay::DelayUs; use super::InternalChannel; diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 3a6e58cf..821cc7f6 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use embedded_hal_02::blocking::delay::DelayUs; use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index c51c6840..64d0f0c7 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -226,7 +226,7 @@ impl Prescaler { impl<'d, T: Instance> Adc<'d, T> { pub fn new(adc: impl Peripheral

+ 'd, delay: &mut impl DelayUs) -> Self { - embassy_hal_common::into_ref!(adc); + embassy_hal_internal::into_ref!(adc); T::enable(); T::reset(); diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index 795becab..448be1cd 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -6,7 +6,7 @@ use core::task::Poll; pub use bxcan; use bxcan::{Data, ExtendedId, Frame, Id, StandardId}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use futures::FutureExt; use crate::gpio::sealed::AFType; @@ -88,6 +88,7 @@ pub struct Can<'d, T: Instance> { } #[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum BusError { Stuff, Form, @@ -101,6 +102,22 @@ pub enum BusError { BusWarning, } +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum TryReadError { + /// Bus error + BusError(BusError), + /// Receive buffer is empty + Empty, +} + +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum TryWriteError { + /// All transmit mailboxes are full + Full, +} + impl<'d, T: Instance> Can<'d, T> { /// Creates a new Bxcan instance, keeping the peripheral in sleep mode. /// You must call [Can::enable_non_blocking] to use the peripheral. @@ -186,56 +203,46 @@ impl<'d, T: Instance> Can<'d, T> { /// Queues the message to be sent but exerts backpressure pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus { - poll_fn(|cx| { - T::state().tx_waker.register(cx.waker()); - if let Ok(status) = self.can.borrow_mut().transmit(frame) { - return Poll::Ready(status); - } - - Poll::Pending - }) - .await + CanTx { can: &self.can }.write(frame).await } - pub async fn flush(&self, mb: bxcan::Mailbox) { - poll_fn(|cx| { - T::state().tx_waker.register(cx.waker()); - if T::regs().tsr().read().tme(mb.index()) { - return Poll::Ready(()); - } + /// Attempts to transmit a frame without blocking. + /// + /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. + pub fn try_write(&mut self, frame: &Frame) -> Result { + CanTx { can: &self.can }.try_write(frame) + } - Poll::Pending - }) - .await; + /// Waits for a specific transmit mailbox to become empty + pub async fn flush(&self, mb: bxcan::Mailbox) { + CanTx { can: &self.can }.flush(mb).await + } + + /// Waits until any of the transmit mailboxes become empty + pub async fn flush_any(&self) { + CanTx { can: &self.can }.flush_any().await + } + + /// Waits until all of the transmit mailboxes become empty + pub async fn flush_all(&self) { + CanTx { can: &self.can }.flush_all().await } /// Returns a tuple of the time the message was received and the message frame pub async fn read(&mut self) -> Result { - poll_fn(|cx| { - T::state().err_waker.register(cx.waker()); - if let Poll::Ready(envelope) = T::state().rx_queue.recv().poll_unpin(cx) { - return Poll::Ready(Ok(envelope)); - } else if let Some(err) = self.curr_error() { - return Poll::Ready(Err(err)); - } - - Poll::Pending - }) - .await + CanRx { can: &self.can }.read().await } - fn curr_error(&self) -> Option { - let err = { T::regs().esr().read() }; - if err.boff() { - return Some(BusError::BusOff); - } else if err.epvf() { - return Some(BusError::BusPassive); - } else if err.ewgf() { - return Some(BusError::BusWarning); - } else if let Some(err) = err.lec().into_bus_err() { - return Some(err); - } - None + /// Attempts to read a can frame without blocking. + /// + /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. + pub fn try_read(&mut self) -> Result { + CanRx { can: &self.can }.try_read() + } + + /// Waits while receive queue is empty. + pub async fn wait_not_empty(&mut self) { + CanRx { can: &self.can }.wait_not_empty().await } unsafe fn receive_fifo(fifo: RxFifo) { @@ -405,6 +412,14 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { .await } + /// Attempts to transmit a frame without blocking. + /// + /// Returns [Err(TryWriteError::Full)] if all transmit mailboxes are full. + pub fn try_write(&mut self, frame: &Frame) -> Result { + self.can.borrow_mut().transmit(frame).map_err(|_| TryWriteError::Full) + } + + /// Waits for a specific transmit mailbox to become empty pub async fn flush(&self, mb: bxcan::Mailbox) { poll_fn(|cx| { T::state().tx_waker.register(cx.waker()); @@ -416,6 +431,42 @@ impl<'c, 'd, T: Instance> CanTx<'c, 'd, T> { }) .await; } + + /// Waits until any of the transmit mailboxes become empty + pub async fn flush_any(&self) { + poll_fn(|cx| { + T::state().tx_waker.register(cx.waker()); + + let tsr = T::regs().tsr().read(); + if tsr.tme(bxcan::Mailbox::Mailbox0.index()) + || tsr.tme(bxcan::Mailbox::Mailbox1.index()) + || tsr.tme(bxcan::Mailbox::Mailbox2.index()) + { + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + } + + /// Waits until all of the transmit mailboxes become empty + pub async fn flush_all(&self) { + poll_fn(|cx| { + T::state().tx_waker.register(cx.waker()); + + let tsr = T::regs().tsr().read(); + if tsr.tme(bxcan::Mailbox::Mailbox0.index()) + && tsr.tme(bxcan::Mailbox::Mailbox1.index()) + && tsr.tme(bxcan::Mailbox::Mailbox2.index()) + { + return Poll::Ready(()); + } + + Poll::Pending + }) + .await; + } } #[allow(dead_code)] @@ -438,6 +489,33 @@ impl<'c, 'd, T: Instance> CanRx<'c, 'd, T> { .await } + /// Attempts to read a CAN frame without blocking. + /// + /// Returns [Err(TryReadError::Empty)] if there are no frames in the rx queue. + pub fn try_read(&mut self) -> Result { + if let Ok(envelope) = T::state().rx_queue.try_recv() { + return Ok(envelope); + } + + if let Some(err) = self.curr_error() { + return Err(TryReadError::BusError(err)); + } + + Err(TryReadError::Empty) + } + + /// Waits while receive queue is empty. + pub async fn wait_not_empty(&mut self) { + poll_fn(|cx| { + if T::state().rx_queue.poll_ready_to_receive(cx) { + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await + } + fn curr_error(&self) -> Option { let err = { T::regs().esr().read() }; if err.boff() { diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index c31a7fc6..f77788db 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -1,5 +1,5 @@ pub use bxcan; -use embassy_hal_common::PeripheralRef; +use embassy_hal_internal::PeripheralRef; use crate::peripherals; diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 3946a2d4..154f2eb9 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::CRC as PAC_CRC; use crate::peripherals::CRC; diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index f337055a..de0c0875 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::crc::vals; use crate::pac::CRC as PAC_CRC; diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 979748bb..a2040b85 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -3,7 +3,7 @@ //! Provide access to the STM32 digital-to-analog converter (DAC). use core::marker::PhantomData; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::dac; use crate::rcc::RccPeripheral; diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 78b026cb..7497f4aa 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -2,7 +2,7 @@ use core::future::poll_fn; use core::marker::PhantomData; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::dma::Transfer; diff --git a/embassy-stm32/src/dma/bdma.rs b/embassy-stm32/src/dma/bdma.rs index 5a87888b..d956047d 100644 --- a/embassy-stm32/src/dma/bdma.rs +++ b/embassy-stm32/src/dma/bdma.rs @@ -6,7 +6,7 @@ use core::sync::atomic::{fence, Ordering}; use core::task::{Context, Poll, Waker}; use atomic_polyfill::AtomicUsize; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; @@ -466,15 +466,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); } - /// Read bytes from the ring buffer + /// Read elements from the ring buffer /// Return a tuple of the length read and the length remaining in the buffer - /// If not all of the bytes were read, then there will be some bytes in the buffer remaining - /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read + /// If not all of the elements were read, then there will be some elements in the buffer remaining + /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) } + /// Read an exact number of elements from the ringbuffer. + /// + /// Returns the remaining number of elements available for immediate reading. + /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. + /// + /// Async/Wake Behavior: + /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, + /// and when it wraps around. This means that when called with a buffer of length 'M', when this + /// ring buffer was created with a buffer of size 'N': + /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. + /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. + pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result { + use core::future::poll_fn; + use core::sync::atomic::compiler_fence; + + let mut read_data = 0; + let buffer_len = buffer.len(); + + poll_fn(|cx| { + self.set_waker(cx.waker()); + + compiler_fence(Ordering::SeqCst); + + match self.read(&mut buffer[read_data..buffer_len]) { + Ok((len, remaining)) => { + read_data += len; + if read_data == buffer_len { + Poll::Ready(Ok(remaining)) + } else { + Poll::Pending + } + } + Err(e) => Poll::Ready(Err(e)), + } + }) + .await + } + /// The capacity of the ringbuffer pub fn cap(&self) -> usize { self.ringbuf.cap() diff --git a/embassy-stm32/src/dma/dma.rs b/embassy-stm32/src/dma/dma.rs index f1408459..219ef2eb 100644 --- a/embassy-stm32/src/dma/dma.rs +++ b/embassy-stm32/src/dma/dma.rs @@ -4,7 +4,7 @@ use core::pin::Pin; use core::sync::atomic::{fence, AtomicUsize, Ordering}; use core::task::{Context, Poll, Waker}; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use super::ringbuffer::{DmaCtrl, DmaRingBuffer, OverrunError}; @@ -711,15 +711,53 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> { self.ringbuf.clear(DmaCtrlImpl(self.channel.reborrow())); } - /// Read bytes from the ring buffer + /// Read elements from the ring buffer /// Return a tuple of the length read and the length remaining in the buffer - /// If not all of the bytes were read, then there will be some bytes in the buffer remaining - /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read + /// If not all of the elements were read, then there will be some elements in the buffer remaining + /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. pub fn read(&mut self, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { self.ringbuf.read(DmaCtrlImpl(self.channel.reborrow()), buf) } + /// Read an exact number of elements from the ringbuffer. + /// + /// Returns the remaining number of elements available for immediate reading. + /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. + /// + /// Async/Wake Behavior: + /// The underlying DMA peripheral only can wake us when its buffer pointer has reached the halfway point, + /// and when it wraps around. This means that when called with a buffer of length 'M', when this + /// ring buffer was created with a buffer of size 'N': + /// - If M equals N/2 or N/2 divides evenly into M, this function will return every N/2 elements read on the DMA source. + /// - Otherwise, this function may need up to N/2 extra elements to arrive before returning. + pub async fn read_exact(&mut self, buffer: &mut [W]) -> Result { + use core::future::poll_fn; + use core::sync::atomic::compiler_fence; + + let mut read_data = 0; + let buffer_len = buffer.len(); + + poll_fn(|cx| { + self.set_waker(cx.waker()); + + compiler_fence(Ordering::SeqCst); + + match self.read(&mut buffer[read_data..buffer_len]) { + Ok((len, remaining)) => { + read_data += len; + if read_data == buffer_len { + Poll::Ready(Ok(remaining)) + } else { + Poll::Pending + } + } + Err(e) => Poll::Ready(Err(e)), + } + }) + .await + } + // The capacity of the ringbuffer pub fn cap(&self) -> usize { self.ringbuf.cap() diff --git a/embassy-stm32/src/dma/gpdma.rs b/embassy-stm32/src/dma/gpdma.rs index b7bcf779..97cc200d 100644 --- a/embassy-stm32/src/dma/gpdma.rs +++ b/embassy-stm32/src/dma/gpdma.rs @@ -5,7 +5,7 @@ use core::pin::Pin; use core::sync::atomic::{fence, Ordering}; use core::task::{Context, Poll}; -use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use super::word::{Word, WordSize}; diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index 0858587b..4f1a58ae 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -26,7 +26,7 @@ pub mod word; use core::mem; -use embassy_hal_common::impl_peripheral; +use embassy_hal_internal::impl_peripheral; #[cfg(dmamux)] pub use self::dmamux::*; diff --git a/embassy-stm32/src/dma/ringbuffer.rs b/embassy-stm32/src/dma/ringbuffer.rs index a2bde986..19079397 100644 --- a/embassy-stm32/src/dma/ringbuffer.rs +++ b/embassy-stm32/src/dma/ringbuffer.rs @@ -72,10 +72,10 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { self.cap() - remaining_transfers } - /// Read bytes from the ring buffer + /// Read elements from the ring buffer /// Return a tuple of the length read and the length remaining in the buffer - /// If not all of the bytes were read, then there will be some bytes in the buffer remaining - /// The length remaining is the capacity, ring_buf.len(), less the bytes remaining after the read + /// If not all of the elements were read, then there will be some elements in the buffer remaining + /// The length remaining is the capacity, ring_buf.len(), less the elements remaining after the read /// OverrunError is returned if the portion to be read was overwritten by the DMA controller. pub fn read(&mut self, mut dma: impl DmaCtrl, buf: &mut [W]) -> Result<(usize, usize), OverrunError> { /* @@ -95,11 +95,11 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { */ let end = self.pos(dma.get_remaining_transfers()); if self.start == end && dma.get_complete_count() == 0 { - // No bytes are available in the buffer + // No elements are available in the buffer Ok((0, self.cap())) } else if self.start < end { // The available, unread portion in the ring buffer DOES NOT wrap - // Copy out the bytes from the dma buffer + // Copy out the elements from the dma buffer let len = self.copy_to(buf, self.start..end); compiler_fence(Ordering::SeqCst); @@ -128,7 +128,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { // The DMA writer has wrapped since we last read and is currently // writing (or the next byte added will be) in the beginning of the ring buffer. - // The provided read buffer is not large enough to include all bytes from the tail of the dma buffer. + // The provided read buffer is not large enough to include all elements from the tail of the dma buffer. // Copy out from the dma buffer let len = self.copy_to(buf, self.start..self.cap()); @@ -154,8 +154,8 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { // The DMA writer has wrapped since we last read and is currently // writing (or the next byte added will be) in the beginning of the ring buffer. - // The provided read buffer is large enough to include all bytes from the tail of the dma buffer, - // so the next read will not have any unread tail bytes in the ring buffer. + // The provided read buffer is large enough to include all elements from the tail of the dma buffer, + // so the next read will not have any unread tail elements in the ring buffer. // Copy out from the dma buffer let tail = self.copy_to(buf, self.start..self.cap()); @@ -180,7 +180,7 @@ impl<'a, W: Word> DmaRingBuffer<'a, W> { } /// Copy from the dma buffer at `data_range` into `buf` fn copy_to(&mut self, buf: &mut [W], data_range: Range) -> usize { - // Limit the number of bytes that can be copied + // Limit the number of elements that can be copied let length = usize::min(data_range.len(), buf.len()); // Copy from dma buffer into read buffer diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index 2a6ea35f..a1e0240c 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -6,7 +6,7 @@ mod tx_desc; use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress, Mw, Pbl, Rsf, St, Tsf}; pub(crate) use self::rx_desc::{RDes, RDesRing}; diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index bb681c42..ada495fd 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -3,7 +3,7 @@ mod descriptors; use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; use super::*; diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 3ff92c9e..925cf39b 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use core::pin::Pin; use core::task::{Context, Poll}; -use embassy_hal_common::impl_peripheral; +use embassy_hal_internal::impl_peripheral; use embassy_sync::waitqueue::AtomicWaker; use crate::gpio::{AnyPin, Input, Pin as GpioPin}; diff --git a/embassy-stm32/src/flash/asynch.rs b/embassy-stm32/src/flash/asynch.rs index f175349c..e966e2a7 100644 --- a/embassy-stm32/src/flash/asynch.rs +++ b/embassy-stm32/src/flash/asynch.rs @@ -1,8 +1,8 @@ use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::into_ref; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::into_ref; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::mutex::Mutex; diff --git a/embassy-stm32/src/flash/common.rs b/embassy-stm32/src/flash/common.rs index 2a374733..16c51129 100644 --- a/embassy-stm32/src/flash/common.rs +++ b/embassy-stm32/src/flash/common.rs @@ -1,8 +1,8 @@ use core::marker::PhantomData; use core::sync::atomic::{fence, Ordering}; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use stm32_metapac::FLASH_BASE; use super::{ diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 4cb39e03..728f6d60 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -14,7 +14,7 @@ use crate::pac; mod alt_regions { use core::marker::PhantomData; - use embassy_hal_common::PeripheralRef; + use embassy_hal_internal::PeripheralRef; use stm32_metapac::FLASH_SIZE; use crate::_generated::flash_regions::{OTPRegion, BANK1_REGION1, BANK1_REGION2, BANK1_REGION3, OTP_REGION}; diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 60d7a00e..177e66a9 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use crate::gpio::sealed::AFType; use crate::gpio::{Pull, Speed}; diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index af3a8eac..0cc269cf 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -1,7 +1,7 @@ #![macro_use] use core::convert::Infallible; -use embassy_hal_common::{impl_peripheral, into_ref, PeripheralRef}; +use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; use crate::pac::gpio::{self, vals}; use crate::{pac, peripherals, Peripheral}; @@ -502,6 +502,20 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { } } +pub enum OutputType { + PushPull, + OpenDrain, +} + +impl From for sealed::AFType { + fn from(value: OutputType) -> Self { + match value { + OutputType::OpenDrain => sealed::AFType::OutputOpenDrain, + OutputType::PushPull => sealed::AFType::OutputPushPull, + } + } +} + pub(crate) mod sealed { use super::*; diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs new file mode 100644 index 00000000..a930ff73 --- /dev/null +++ b/embassy-stm32/src/hrtim/mod.rs @@ -0,0 +1,409 @@ +mod traits; + +use core::marker::PhantomData; + +use embassy_hal_internal::{into_ref, PeripheralRef}; +pub use traits::Instance; + +#[allow(unused_imports)] +use crate::gpio::sealed::{AFType, Pin}; +use crate::gpio::AnyPin; +use crate::time::Hertz; +use crate::Peripheral; + +pub enum Source { + Master, + ChA, + ChB, + ChC, + ChD, + ChE, +} + +pub struct BurstController { + phantom: PhantomData, +} +pub struct Master { + phantom: PhantomData, +} +pub struct ChA { + phantom: PhantomData, +} +pub struct ChB { + phantom: PhantomData, +} +pub struct ChC { + phantom: PhantomData, +} +pub struct ChD { + phantom: PhantomData, +} +pub struct ChE { + phantom: PhantomData, +} + +mod sealed { + use super::Instance; + + pub trait AdvancedChannel { + fn raw() -> usize; + } +} + +pub trait AdvancedChannel: sealed::AdvancedChannel {} + +pub struct PwmPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, +} + +pub struct ComplementaryPwmPin<'d, Perip, Channel> { + _pin: PeripheralRef<'d, AnyPin>, + phantom: PhantomData<(Perip, Channel)>, +} + +macro_rules! advanced_channel_impl { + ($new_chx:ident, $channel:tt, $ch_num:expr, $pin_trait:ident, $complementary_pin_trait:ident) => { + impl<'d, Perip: Instance> PwmPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + PwmPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } + } + + impl<'d, Perip: Instance> ComplementaryPwmPin<'d, Perip, $channel> { + pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + into_ref!(pin); + critical_section::with(|_| { + pin.set_low(); + pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + #[cfg(gpio_v2)] + pin.set_speed(crate::gpio::Speed::VeryHigh); + }); + ComplementaryPwmPin { + _pin: pin.map_into(), + phantom: PhantomData, + } + } + } + + impl sealed::AdvancedChannel for $channel { + fn raw() -> usize { + $ch_num + } + } + impl AdvancedChannel for $channel {} + }; +} + +advanced_channel_impl!(new_cha, ChA, 0, ChannelAPin, ChannelAComplementaryPin); +advanced_channel_impl!(new_chb, ChB, 1, ChannelBPin, ChannelBComplementaryPin); +advanced_channel_impl!(new_chc, ChC, 2, ChannelCPin, ChannelCComplementaryPin); +advanced_channel_impl!(new_chd, ChD, 3, ChannelDPin, ChannelDComplementaryPin); +advanced_channel_impl!(new_che, ChE, 4, ChannelEPin, ChannelEComplementaryPin); + +/// Struct used to divide a high resolution timer into multiple channels +pub struct AdvancedPwm<'d, T: Instance> { + _inner: PeripheralRef<'d, T>, + pub master: Master, + pub burst_controller: BurstController, + pub ch_a: ChA, + pub ch_b: ChB, + pub ch_c: ChC, + pub ch_d: ChD, + pub ch_e: ChE, +} + +impl<'d, T: Instance> AdvancedPwm<'d, T> { + pub fn new( + tim: impl Peripheral

+ 'd, + _cha: Option>>, + _chan: Option>>, + _chb: Option>>, + _chbn: Option>>, + _chc: Option>>, + _chcn: Option>>, + _chd: Option>>, + _chdn: Option>>, + _che: Option>>, + _chen: Option>>, + ) -> Self { + Self::new_inner(tim) + } + + fn new_inner(tim: impl Peripheral

+ 'd) -> Self { + into_ref!(tim); + + T::enable(); + ::reset(); + + // // Enable and and stabilize the DLL + // T::regs().dllcr().modify(|w| { + // // w.set_calen(true); + // // w.set_calrte(11); + // w.set_cal(true); + // }); + // + // debug!("wait for dll calibration"); + // while !T::regs().isr().read().dllrdy() {} + // + // debug!("dll calibration complete"); + + Self { + _inner: tim, + master: Master { phantom: PhantomData }, + burst_controller: BurstController { phantom: PhantomData }, + ch_a: ChA { phantom: PhantomData }, + ch_b: ChB { phantom: PhantomData }, + ch_c: ChC { phantom: PhantomData }, + ch_d: ChD { phantom: PhantomData }, + ch_e: ChE { phantom: PhantomData }, + } + } +} + +impl BurstController { + pub fn set_source(&mut self, _source: Source) { + todo!("burst mode control registers not implemented") + } +} + +/// Represents a fixed-frequency bridge converter +/// +/// Our implementation of the bridge converter uses a single channel and three compare registers, +/// allowing implementation of a synchronous buck or boost converter in continuous or discontinuous +/// conduction mode. +/// +/// It is important to remember that in synchronous topologies, energy can flow in reverse during +/// light loading conditions, and that the low-side switch must be active for a short time to drive +/// a bootstrapped high-side switch. +pub struct BridgeConverter> { + timer: PhantomData, + channel: PhantomData, + dead_time: u16, + primary_duty: u16, + min_secondary_duty: u16, + max_secondary_duty: u16, +} + +impl> BridgeConverter { + pub fn new(_channel: C, frequency: Hertz) -> Self { + use crate::pac::hrtim::vals::{Activeeffect, Inactiveeffect}; + + T::set_channel_frequency(C::raw(), frequency); + + // Always enable preload + T::regs().tim(C::raw()).cr().modify(|w| { + w.set_preen(true); + w.set_repu(true); + w.set_cont(true); + }); + + // Enable timer outputs + T::regs().oenr().modify(|w| { + w.set_t1oen(C::raw(), true); + w.set_t2oen(C::raw(), true); + }); + + // The dead-time generation unit cannot be used because it forces the other output + // to be completely complementary to the first output, which restricts certain waveforms + // Therefore, software-implemented dead time must be used when setting the duty cycles + + // Set output 1 to active on a period event + T::regs() + .tim(C::raw()) + .setr(0) + .modify(|w| w.set_per(Activeeffect::SETACTIVE)); + + // Set output 1 to inactive on a compare 1 event + T::regs() + .tim(C::raw()) + .rstr(0) + .modify(|w| w.set_cmp(0, Inactiveeffect::SETINACTIVE)); + + // Set output 2 to active on a compare 2 event + T::regs() + .tim(C::raw()) + .setr(1) + .modify(|w| w.set_cmp(1, Activeeffect::SETACTIVE)); + + // Set output 2 to inactive on a compare 3 event + T::regs() + .tim(C::raw()) + .rstr(1) + .modify(|w| w.set_cmp(2, Inactiveeffect::SETINACTIVE)); + + Self { + timer: PhantomData, + channel: PhantomData, + dead_time: 0, + primary_duty: 0, + min_secondary_duty: 0, + max_secondary_duty: 0, + } + } + + pub fn start(&mut self) { + T::regs().mcr().modify(|w| w.set_tcen(C::raw(), true)); + } + + pub fn stop(&mut self) { + T::regs().mcr().modify(|w| w.set_tcen(C::raw(), false)); + } + + pub fn enable_burst_mode(&mut self) { + T::regs().tim(C::raw()).outr().modify(|w| { + // Enable Burst Mode + w.set_idlem(0, true); + w.set_idlem(1, true); + + // Set output to active during the burst + w.set_idles(0, true); + w.set_idles(1, true); + }) + } + + pub fn disable_burst_mode(&mut self) { + T::regs().tim(C::raw()).outr().modify(|w| { + // Disable Burst Mode + w.set_idlem(0, false); + w.set_idlem(1, false); + }) + } + + fn update_primary_duty_or_dead_time(&mut self) { + self.min_secondary_duty = self.primary_duty + self.dead_time; + + T::regs().tim(C::raw()).cmp(0).modify(|w| w.set_cmp(self.primary_duty)); + T::regs() + .tim(C::raw()) + .cmp(1) + .modify(|w| w.set_cmp(self.min_secondary_duty)); + } + + /// Set the dead time as a proportion of the maximum compare value + pub fn set_dead_time(&mut self, dead_time: u16) { + self.dead_time = dead_time; + self.max_secondary_duty = self.get_max_compare_value() - dead_time; + self.update_primary_duty_or_dead_time(); + } + + /// Get the maximum compare value of a duty cycle + pub fn get_max_compare_value(&mut self) -> u16 { + T::regs().tim(C::raw()).per().read().per() + } + + /// The primary duty is the period in which the primary switch is active + /// + /// In the case of a buck converter, this is the high-side switch + /// In the case of a boost converter, this is the low-side switch + pub fn set_primary_duty(&mut self, primary_duty: u16) { + self.primary_duty = primary_duty; + self.update_primary_duty_or_dead_time(); + } + + /// The secondary duty is the period in any switch is active + /// + /// If less than or equal to the primary duty, the secondary switch will be active for one tick + /// If a fully complementary output is desired, the secondary duty can be set to the max compare + pub fn set_secondary_duty(&mut self, secondary_duty: u16) { + let secondary_duty = if secondary_duty > self.max_secondary_duty { + self.max_secondary_duty + } else if secondary_duty <= self.min_secondary_duty { + self.min_secondary_duty + 1 + } else { + secondary_duty + }; + + T::regs().tim(C::raw()).cmp(2).modify(|w| w.set_cmp(secondary_duty)); + } +} + +/// Represents a variable-frequency resonant converter +/// +/// This implementation of a resonsant converter is appropriate for a half or full bridge, +/// but does not include secondary rectification, which is appropriate for applications +/// with a low-voltage on the secondary side. +pub struct ResonantConverter> { + timer: PhantomData, + channel: PhantomData, + min_period: u16, + max_period: u16, +} + +impl> ResonantConverter { + pub fn new(_channel: C, min_frequency: Hertz, max_frequency: Hertz) -> Self { + T::set_channel_frequency(C::raw(), min_frequency); + + // Always enable preload + T::regs().tim(C::raw()).cr().modify(|w| { + w.set_preen(true); + w.set_repu(true); + + w.set_cont(true); + w.set_half(true); + }); + + // Enable timer outputs + T::regs().oenr().modify(|w| { + w.set_t1oen(C::raw(), true); + w.set_t2oen(C::raw(), true); + }); + + // Dead-time generator can be used in this case because the primary fets + // of a resonant converter are always complementary + T::regs().tim(C::raw()).outr().modify(|w| w.set_dten(true)); + + let max_period = T::regs().tim(C::raw()).per().read().per(); + let min_period = max_period * (min_frequency.0 / max_frequency.0) as u16; + + Self { + timer: PhantomData, + channel: PhantomData, + min_period: min_period, + max_period: max_period, + } + } + + /// Set the dead time as a proportion of the maximum compare value + pub fn set_dead_time(&mut self, value: u16) { + T::set_channel_dead_time(C::raw(), value); + } + + pub fn set_period(&mut self, period: u16) { + assert!(period < self.max_period); + assert!(period > self.min_period); + + T::regs().tim(C::raw()).per().modify(|w| w.set_per(period)); + } + + /// Get the minimum compare value of a duty cycle + pub fn get_min_period(&mut self) -> u16 { + self.min_period + } + + /// Get the maximum compare value of a duty cycle + pub fn get_max_period(&mut self) -> u16 { + self.max_period + } +} + +pin_trait!(ChannelAPin, Instance); +pin_trait!(ChannelAComplementaryPin, Instance); +pin_trait!(ChannelBPin, Instance); +pin_trait!(ChannelBComplementaryPin, Instance); +pin_trait!(ChannelCPin, Instance); +pin_trait!(ChannelCComplementaryPin, Instance); +pin_trait!(ChannelDPin, Instance); +pin_trait!(ChannelDComplementaryPin, Instance); +pin_trait!(ChannelEPin, Instance); +pin_trait!(ChannelEComplementaryPin, Instance); diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs new file mode 100644 index 00000000..158a6886 --- /dev/null +++ b/embassy-stm32/src/hrtim/traits.rs @@ -0,0 +1,193 @@ +use crate::rcc::sealed::RccPeripheral; +use crate::time::Hertz; + +#[derive(Clone, Copy)] +pub(crate) enum Prescaler { + Div1, + Div2, + Div4, + Div8, + Div16, + Div32, + Div64, + Div128, +} + +impl From for u32 { + fn from(val: Prescaler) -> Self { + match val { + Prescaler::Div1 => 1, + Prescaler::Div2 => 2, + Prescaler::Div4 => 4, + Prescaler::Div8 => 8, + Prescaler::Div16 => 16, + Prescaler::Div32 => 32, + Prescaler::Div64 => 64, + Prescaler::Div128 => 128, + } + } +} + +impl From for u8 { + fn from(val: Prescaler) -> Self { + match val { + Prescaler::Div1 => 0b000, + Prescaler::Div2 => 0b001, + Prescaler::Div4 => 0b010, + Prescaler::Div8 => 0b011, + Prescaler::Div16 => 0b100, + Prescaler::Div32 => 0b101, + Prescaler::Div64 => 0b110, + Prescaler::Div128 => 0b111, + } + } +} + +impl From for Prescaler { + fn from(val: u8) -> Self { + match val { + 0b000 => Prescaler::Div1, + 0b001 => Prescaler::Div2, + 0b010 => Prescaler::Div4, + 0b011 => Prescaler::Div8, + 0b100 => Prescaler::Div16, + 0b101 => Prescaler::Div32, + 0b110 => Prescaler::Div64, + 0b111 => Prescaler::Div128, + _ => unreachable!(), + } + } +} + +impl Prescaler { + pub fn compute_min_high_res(val: u32) -> Self { + *[ + Prescaler::Div1, + Prescaler::Div2, + Prescaler::Div4, + Prescaler::Div8, + Prescaler::Div16, + Prescaler::Div32, + Prescaler::Div64, + Prescaler::Div128, + ] + .iter() + .skip_while(|psc| >::into(**psc) <= val) + .next() + .unwrap() + } + + pub fn compute_min_low_res(val: u32) -> Self { + *[Prescaler::Div32, Prescaler::Div64, Prescaler::Div128] + .iter() + .skip_while(|psc| >::into(**psc) <= val) + .next() + .unwrap() + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance: RccPeripheral { + fn regs() -> crate::pac::hrtim::Hrtim; + + fn set_master_frequency(frequency: Hertz); + + fn set_channel_frequency(channnel: usize, frequency: Hertz); + + /// Set the dead time as a proportion of max_duty + fn set_channel_dead_time(channnel: usize, dead_time: u16); + + // fn enable_outputs(enable: bool); + // + // fn enable_channel(&mut self, channel: usize, enable: bool); + } +} + +pub trait Instance: sealed::Instance + 'static {} + +foreach_interrupt! { + ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { + impl sealed::Instance for crate::peripherals::$inst { + fn regs() -> crate::pac::hrtim::Hrtim { + crate::pac::$inst + } + + fn set_master_frequency(frequency: Hertz) { + use crate::rcc::sealed::RccPeripheral; + + let f = frequency.0; + let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; + + let psc_val: u32 = psc.into(); + let timer_f = 32 * (timer_f / psc_val); + let per: u16 = (timer_f / f) as u16; + + let regs = Self::regs(); + + regs.mcr().modify(|w| w.set_ckpsc(psc.into())); + regs.mper().modify(|w| w.set_mper(per)); + } + + fn set_channel_frequency(channel: usize, frequency: Hertz) { + use crate::rcc::sealed::RccPeripheral; + + let f = frequency.0; + let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; + + let psc_val: u32 = psc.into(); + let timer_f = 32 * (timer_f / psc_val); + let per: u16 = (timer_f / f) as u16; + + let regs = Self::regs(); + + regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); + regs.tim(channel).per().modify(|w| w.set_per(per)); + } + + fn set_channel_dead_time(channel: usize, dead_time: u16) { + + let regs = Self::regs(); + + let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); + let psc_val: u32 = channel_psc.into(); + + + // The dead-time base clock runs 4 times slower than the hrtim base clock + // u9::MAX = 511 + let psc_min = (psc_val * dead_time as u32) / (4 * 511); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; + + let dt_psc_val: u32 = psc.into(); + let dt_val = (dt_psc_val * dead_time as u32) / (4 * psc_val); + + regs.tim(channel).dt().modify(|w| { + w.set_dtprsc(psc.into()); + w.set_dtf(dt_val as u16); + w.set_dtr(dt_val as u16); + }); + } + } + + impl Instance for crate::peripherals::$inst { + + } + }; +} diff --git a/embassy-stm32/src/i2c/timeout.rs b/embassy-stm32/src/i2c/timeout.rs index 939e2750..8dc228b3 100644 --- a/embassy-stm32/src/i2c/timeout.rs +++ b/embassy-stm32/src/i2c/timeout.rs @@ -6,8 +6,8 @@ use super::{Error, I2c, Instance}; /// /// This is useful for recovering from a shorted bus or a device stuck in a clock stretching state. /// A regular [I2c] would freeze until condition is removed. -pub struct TimeoutI2c<'d, T: Instance, TXDMA, RXDMA> { - i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, +pub struct TimeoutI2c<'a, 'd: 'a, T: Instance, TXDMA, RXDMA> { + i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration, } @@ -22,8 +22,8 @@ fn timeout_fn(timeout: Duration) -> impl Fn() -> Result<(), Error> { } } -impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> { - pub fn new(i2c: &'d mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { +impl<'a, 'd, T: Instance, TXDMA, RXDMA> TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { + pub fn new(i2c: &'a mut I2c<'d, T, TXDMA, RXDMA>, timeout: Duration) -> Self { Self { i2c, timeout } } @@ -65,7 +65,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> TimeoutI2c<'d, T, TXDMA, RXDMA> { } } -impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'d, T, TXDMA, RXDMA> { +impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { type Error = Error; fn read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Self::Error> { @@ -73,7 +73,7 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Read for Tim } } -impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'d, T, TXDMA, RXDMA> { +impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { type Error = Error; fn write(&mut self, addr: u8, write: &[u8]) -> Result<(), Self::Error> { @@ -81,7 +81,9 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::Write for Ti } } -impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead for TimeoutI2c<'d, T, TXDMA, RXDMA> { +impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead + for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> +{ type Error = Error; fn write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Self::Error> { @@ -93,11 +95,11 @@ impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_02::blocking::i2c::WriteRead fo mod eh1 { use super::*; - impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'d, T, TXDMA, RXDMA> { + impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::ErrorType for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { type Error = Error; } - impl<'d, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'d, T, TXDMA, RXDMA> { + impl<'a, 'd, T: Instance, TXDMA, RXDMA> embedded_hal_1::i2c::I2c for TimeoutI2c<'a, 'd, T, TXDMA, RXDMA> { fn read(&mut self, address: u8, read: &mut [u8]) -> Result<(), Self::Error> { self.blocking_read(address, read) } diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index aa485cd8..e5254a8c 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -1,7 +1,7 @@ use core::marker::PhantomData; use embassy_embedded_hal::SetConfig; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::dma::NoDma; use crate::gpio::sealed::AFType; diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index 208d1527..eaf980a4 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -4,8 +4,8 @@ use core::marker::PhantomData; use core::task::Poll; use embassy_embedded_hal::SetConfig; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::dma::{NoDma, Transfer}; diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index 62dda69b..8fd3a8c6 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -1,4 +1,4 @@ -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::AnyPin; @@ -165,7 +165,9 @@ impl<'d, T: Instance, Tx, Rx> I2S<'d, T, Tx, Rx> { mck.set_as_af(mck.af_num(), AFType::OutputPushPull); mck.set_speed(crate::gpio::Speed::VeryHigh); - let spi = Spi::new_internal(peri, txdma, rxdma, freq, SpiConfig::default()); + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = freq; + let spi = Spi::new_internal(peri, txdma, rxdma, spi_cfg); #[cfg(all(rcc_f4, not(stm32f410)))] let pclk = unsafe { get_freqs() }.plli2s.unwrap(); diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 45a7b547..34220fbf 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -1,6 +1,9 @@ #![cfg_attr(not(test), no_std)] #![cfg_attr(feature = "nightly", feature(async_fn_in_trait, impl_trait_projections))] +//! ## Feature flags +#![doc = document_features::document_features!(feature_label = r#"{feature}"#)] + // This must go FIRST so that all the other modules see its macros. pub mod fmt; include!(concat!(env!("OUT_DIR"), "/_macros.rs")); @@ -23,6 +26,8 @@ pub mod timer; pub mod adc; #[cfg(can)] pub mod can; +#[cfg(crc)] +pub mod crc; #[cfg(dac)] pub mod dac; #[cfg(dcmi)] @@ -31,19 +36,17 @@ pub mod dcmi; pub mod eth; #[cfg(feature = "exti")] pub mod exti; +pub mod flash; #[cfg(fmc)] pub mod fmc; +#[cfg(hrtim_v1)] +pub mod hrtim; #[cfg(i2c)] pub mod i2c; - -#[cfg(crc)] -pub mod crc; -pub mod flash; #[cfg(all(spi_v1, rcc_f4))] pub mod i2s; #[cfg(stm32wb)] pub mod ipcc; -pub mod pwm; #[cfg(quadspi)] pub mod qspi; #[cfg(rng)] @@ -79,7 +82,7 @@ pub use crate::_generated::interrupt; /// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) /// and implements the right [`Binding`]s for it. You can pass this struct to drivers to /// prove at compile-time that the right interrupts have been bound. -// developer note: this macro can't be in `embassy-hal-common` due to the use of `$crate`. +// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. #[macro_export] macro_rules! bind_interrupts { ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => { @@ -103,7 +106,7 @@ macro_rules! bind_interrupts { // Reexports pub use _generated::{peripherals, Peripherals}; -pub use embassy_hal_common::{into_ref, Peripheral, PeripheralRef}; +pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; #[cfg(feature = "unstable-pac")] pub use stm32_metapac as pac; #[cfg(not(feature = "unstable-pac"))] diff --git a/embassy-stm32/src/pwm/mod.rs b/embassy-stm32/src/pwm/mod.rs deleted file mode 100644 index 5aba2663..00000000 --- a/embassy-stm32/src/pwm/mod.rs +++ /dev/null @@ -1,269 +0,0 @@ -pub mod complementary_pwm; -pub mod simple_pwm; - -use stm32_metapac::timer::vals::Ckd; - -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} - -#[derive(Clone, Copy)] -pub enum Channel { - Ch1, - Ch2, - Ch3, - Ch4, -} - -impl Channel { - pub fn raw(&self) -> usize { - match self { - Channel::Ch1 => 0, - Channel::Ch2 => 1, - Channel::Ch3 => 2, - Channel::Ch4 => 3, - } - } -} - -#[derive(Clone, Copy)] -pub enum OutputCompareMode { - Frozen, - ActiveOnMatch, - InactiveOnMatch, - Toggle, - ForceInactive, - ForceActive, - PwmMode1, - PwmMode2, -} - -impl From for stm32_metapac::timer::vals::Ocm { - fn from(mode: OutputCompareMode) -> Self { - match mode { - OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, - OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, - OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, - OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, - OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, - OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, - OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, - OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, - } - } -} - -pub(crate) mod sealed { - use super::*; - - pub trait CaptureCompare16bitInstance: crate::timer::sealed::GeneralPurpose16bitInstance { - /// Global output enable. Does not do anything on non-advanced timers. - fn enable_outputs(&mut self, enable: bool); - - fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - - fn enable_channel(&mut self, channel: Channel, enable: bool); - - fn set_compare_value(&mut self, channel: Channel, value: u16); - - fn get_max_compare_value(&self) -> u16; - } - - pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { - fn set_dead_time_clock_division(&mut self, value: Ckd); - - fn set_dead_time_value(&mut self, value: u8); - - fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); - } - - pub trait CaptureCompare32bitInstance: crate::timer::sealed::GeneralPurpose32bitInstance { - fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - - fn enable_channel(&mut self, channel: Channel, enable: bool); - - fn set_compare_value(&mut self, channel: Channel, value: u32); - - fn get_max_compare_value(&self) -> u32; - } -} - -pub trait CaptureCompare16bitInstance: - sealed::CaptureCompare16bitInstance + crate::timer::GeneralPurpose16bitInstance + 'static -{ -} - -pub trait ComplementaryCaptureCompare16bitInstance: - sealed::ComplementaryCaptureCompare16bitInstance + crate::timer::AdvancedControlInstance + 'static -{ -} - -pub trait CaptureCompare32bitInstance: - sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + crate::timer::GeneralPurpose32bitInstance + 'static -{ -} - -#[allow(unused)] -macro_rules! impl_compare_capable_16bit { - ($inst:ident) => { - impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn enable_outputs(&mut self, _enable: bool) {} - - fn set_output_compare_mode(&mut self, channel: crate::pwm::Channel, mode: OutputCompareMode) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - let r = Self::regs_gp16(); - let raw_channel: usize = channel.raw(); - r.ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .ccer() - .modify(|w| w.set_cce(channel.raw(), enable)); - } - - fn set_compare_value(&mut self, channel: Channel, value: u16) { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); - } - - fn get_max_compare_value(&self) -> u16 { - use crate::timer::sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().arr().read().arr() - } - } - }; -} - -foreach_interrupt! { - ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl_compare_capable_16bit!($inst); - - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - - } - }; - - ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { - impl_compare_capable_16bit!($inst); - impl crate::pwm::sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { - fn set_output_compare_mode( - &mut self, - channel: crate::pwm::Channel, - mode: OutputCompareMode, - ) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); - } - - fn set_compare_value(&mut self, channel: Channel, value: u32) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); - } - - fn get_max_compare_value(&self) -> u32 { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().arr().read().arr() as u32 - } - } - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - - } - impl CaptureCompare32bitInstance for crate::peripherals::$inst { - - } - }; - - ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { - impl crate::pwm::sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn enable_outputs(&mut self, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - let r = Self::regs_advanced(); - r.bdtr().modify(|w| w.set_moe(enable)); - } - - fn set_output_compare_mode( - &mut self, - channel: crate::pwm::Channel, - mode: OutputCompareMode, - ) { - use crate::timer::sealed::AdvancedControlInstance; - let r = Self::regs_advanced(); - let raw_channel: usize = channel.raw(); - r.ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_cce(channel.raw(), enable)); - } - - fn set_compare_value(&mut self, channel: Channel, value: u16) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccr(channel.raw()) - .modify(|w| w.set_ccr(value)); - } - - fn get_max_compare_value(&self) -> u16 { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().arr().read().arr() - } - } - - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - - } - - impl crate::pwm::sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { - fn set_dead_time_clock_division(&mut self, value: Ckd) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); - } - - fn set_dead_time_value(&mut self, value: u8) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); - } - - fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccne(channel.raw(), enable)); - } - } - - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { - - } - }; -} - -pin_trait!(Channel1Pin, CaptureCompare16bitInstance); -pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance); -pin_trait!(Channel2Pin, CaptureCompare16bitInstance); -pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance); -pin_trait!(Channel3Pin, CaptureCompare16bitInstance); -pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance); -pin_trait!(Channel4Pin, CaptureCompare16bitInstance); -pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance); -pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); -pin_trait!(BreakInputPin, CaptureCompare16bitInstance); -pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); -pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 31b67608..32382fb2 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -2,7 +2,7 @@ pub mod enums; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use enums::*; use crate::dma::Transfer; diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs index df6e9047..6a932634 100644 --- a/embassy-stm32/src/rcc/c0.rs +++ b/embassy-stm32/src/rcc/c0.rs @@ -1,5 +1,6 @@ +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{Hpre, Hsidiv, Ppre, Sw}; +use crate::pac::rcc::vals::{Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -45,58 +46,6 @@ impl Into for HSIPrescaler { } } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> Ppre { - match self { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> Hpre { - match self { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, diff --git a/embassy-stm32/src/rcc/common.rs b/embassy-stm32/src/rcc/common.rs new file mode 100644 index 00000000..62736a43 --- /dev/null +++ b/embassy-stm32/src/rcc/common.rs @@ -0,0 +1,174 @@ +use core::ops::Div; + +#[allow(unused_imports)] +use crate::pac::rcc; +use crate::time::Hertz; + +/// Voltage Scale +/// +/// Represents the voltage range feeding the CPU core. The maximum core +/// clock frequency depends on this value. +/// +/// Scale0 represents the highest voltage range +#[derive(Copy, Clone, PartialEq)] +pub enum VoltageScale { + Scale0, + Scale1, + #[cfg(not(any(rcc_wl5, rcc_wle)))] + Scale2, + #[cfg(not(any(rcc_wl5, rcc_wle)))] + Scale3, +} + +/// AHB prescaler +#[derive(Clone, Copy, PartialEq)] +pub enum AHBPrescaler { + NotDivided, + Div2, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + Div3, + Div4, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + Div5, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + Div6, + Div8, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + Div10, + Div16, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + Div32, + Div64, + Div128, + Div256, + Div512, +} + +impl Div for Hertz { + type Output = Hertz; + + fn div(self, rhs: AHBPrescaler) -> Self::Output { + let divisor = match rhs { + AHBPrescaler::NotDivided => 1, + AHBPrescaler::Div2 => 2, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + AHBPrescaler::Div3 => 3, + AHBPrescaler::Div4 => 4, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + AHBPrescaler::Div5 => 5, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + AHBPrescaler::Div6 => 6, + AHBPrescaler::Div8 => 8, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + AHBPrescaler::Div10 => 10, + AHBPrescaler::Div16 => 16, + #[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] + AHBPrescaler::Div32 => 32, + AHBPrescaler::Div64 => 64, + AHBPrescaler::Div128 => 128, + AHBPrescaler::Div256 => 256, + AHBPrescaler::Div512 => 512, + }; + Hertz(self.0 / divisor) + } +} + +#[cfg(not(any(rcc_g4, rcc_wb, rcc_wl5, rcc_wle)))] +impl From for rcc::vals::Hpre { + fn from(val: AHBPrescaler) -> rcc::vals::Hpre { + use rcc::vals::Hpre; + + match val { + #[cfg(not(rcc_u5))] + AHBPrescaler::NotDivided => Hpre::DIV1, + #[cfg(rcc_u5)] + AHBPrescaler::NotDivided => Hpre::NONE, + AHBPrescaler::Div2 => Hpre::DIV2, + AHBPrescaler::Div4 => Hpre::DIV4, + AHBPrescaler::Div8 => Hpre::DIV8, + AHBPrescaler::Div16 => Hpre::DIV16, + AHBPrescaler::Div64 => Hpre::DIV64, + AHBPrescaler::Div128 => Hpre::DIV128, + AHBPrescaler::Div256 => Hpre::DIV256, + AHBPrescaler::Div512 => Hpre::DIV512, + } + } +} + +#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] +impl From for u8 { + fn from(val: AHBPrescaler) -> u8 { + match val { + AHBPrescaler::NotDivided => 0x0, + AHBPrescaler::Div2 => 0x08, + AHBPrescaler::Div3 => 0x01, + AHBPrescaler::Div4 => 0x09, + AHBPrescaler::Div5 => 0x02, + AHBPrescaler::Div6 => 0x05, + AHBPrescaler::Div8 => 0x0a, + AHBPrescaler::Div10 => 0x06, + AHBPrescaler::Div16 => 0x0b, + AHBPrescaler::Div32 => 0x07, + AHBPrescaler::Div64 => 0x0c, + AHBPrescaler::Div128 => 0x0d, + AHBPrescaler::Div256 => 0x0e, + AHBPrescaler::Div512 => 0x0f, + } + } +} + +/// APB prescaler +#[derive(Clone, Copy)] +pub enum APBPrescaler { + NotDivided, + Div2, + Div4, + Div8, + Div16, +} + +impl Div for Hertz { + type Output = Hertz; + + fn div(self, rhs: APBPrescaler) -> Self::Output { + let divisor = match rhs { + APBPrescaler::NotDivided => 1, + APBPrescaler::Div2 => 2, + APBPrescaler::Div4 => 4, + APBPrescaler::Div8 => 8, + APBPrescaler::Div16 => 16, + }; + Hertz(self.0 / divisor) + } +} + +#[cfg(not(any(rcc_f1, rcc_f100, rcc_f1cl, rcc_g4, rcc_h7, rcc_h7ab, rcc_wb, rcc_wl5, rcc_wle)))] +impl From for rcc::vals::Ppre { + fn from(val: APBPrescaler) -> rcc::vals::Ppre { + use rcc::vals::Ppre; + + match val { + #[cfg(not(rcc_u5))] + APBPrescaler::NotDivided => Ppre::DIV1, + #[cfg(rcc_u5)] + APBPrescaler::NotDivided => Ppre::NONE, + APBPrescaler::Div2 => Ppre::DIV2, + APBPrescaler::Div4 => Ppre::DIV4, + APBPrescaler::Div8 => Ppre::DIV8, + APBPrescaler::Div16 => Ppre::DIV16, + } + } +} + +#[cfg(any(rcc_wb, rcc_wl5, rcc_wle))] +impl From for u8 { + fn from(val: APBPrescaler) -> u8 { + match val { + APBPrescaler::NotDivided => 1, + APBPrescaler::Div2 => 0x04, + APBPrescaler::Div4 => 0x05, + APBPrescaler::Div8 => 0x06, + APBPrescaler::Div16 => 0x07, + } + } +} diff --git a/embassy-stm32/src/rcc/f2.rs b/embassy-stm32/src/rcc/f2.rs index 1525cc3c..d016d1de 100644 --- a/embassy-stm32/src/rcc/f2.rs +++ b/embassy-stm32/src/rcc/f2.rs @@ -1,8 +1,9 @@ use core::convert::TryFrom; use core::ops::{Div, Mul}; +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{Hpre, Pllp, Pllsrc, Ppre, Sw}; +use crate::pac::rcc::vals::{Pllp, Pllsrc, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -58,7 +59,7 @@ impl Default for PLLConfig { impl PLLConfig { pub fn clocks(&self, src_freq: Hertz) -> PLLClocks { let in_freq = src_freq / self.pre_div; - let vco_freq = src_freq * self.mul / self.pre_div; + let vco_freq = Hertz((src_freq.0 as u64 * self.mul.0 as u64 / self.pre_div.0 as u64) as u32); let main_freq = vco_freq / self.main_div; let pll48_freq = vco_freq / self.pll48_div; PLLClocks { @@ -200,114 +201,15 @@ pub struct PLLClocks { pub pll48_freq: Hertz, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} +pub use super::common::VoltageScale; -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: AHBPrescaler) -> Self::Output { - let divisor = match rhs { - AHBPrescaler::NotDivided => 1, - AHBPrescaler::Div2 => 2, - AHBPrescaler::Div4 => 4, - AHBPrescaler::Div8 => 8, - AHBPrescaler::Div16 => 16, - AHBPrescaler::Div64 => 64, - AHBPrescaler::Div128 => 128, - AHBPrescaler::Div256 => 256, - AHBPrescaler::Div512 => 512, - }; - Hertz(self.0 / divisor) - } -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Div for Hertz { - type Output = Hertz; - - fn div(self, rhs: APBPrescaler) -> Self::Output { - let divisor = match rhs { - APBPrescaler::NotDivided => 1, - APBPrescaler::Div2 => 2, - APBPrescaler::Div4 => 4, - APBPrescaler::Div8 => 8, - APBPrescaler::Div16 => 16, - }; - Hertz(self.0 / divisor) - } -} - -impl Into for APBPrescaler { - fn into(self) -> Ppre { - match self { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> Hpre { - match self { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - -/// Voltage Range -/// -/// Represents the system supply voltage range -#[derive(Copy, Clone, PartialEq)] -pub enum VoltageRange { - /// 1.8 to 3.6 V - Min1V8, - /// 2.1 to 3.6 V - Min2V1, - /// 2.4 to 3.6 V - Min2V4, - /// 2.7 to 3.6 V - Min2V7, -} - -impl VoltageRange { +impl VoltageScale { const fn wait_states(&self, ahb_freq: Hertz) -> Option { let ahb_freq = ahb_freq.0; // Reference: RM0033 - Table 3. Number of wait states according to Cortex®-M3 clock // frequency match self { - VoltageRange::Min1V8 => { + VoltageScale::Scale3 => { if ahb_freq <= 16_000_000 { Some(Latency::WS0) } else if ahb_freq <= 32_000_000 { @@ -328,7 +230,7 @@ impl VoltageRange { None } } - VoltageRange::Min2V1 => { + VoltageScale::Scale2 => { if ahb_freq <= 18_000_000 { Some(Latency::WS0) } else if ahb_freq <= 36_000_000 { @@ -347,7 +249,7 @@ impl VoltageRange { None } } - VoltageRange::Min2V4 => { + VoltageScale::Scale1 => { if ahb_freq <= 24_000_000 { Some(Latency::WS0) } else if ahb_freq <= 48_000_000 { @@ -362,7 +264,7 @@ impl VoltageRange { None } } - VoltageRange::Min2V7 => { + VoltageScale::Scale0 => { if ahb_freq <= 30_000_000 { Some(Latency::WS0) } else if ahb_freq <= 60_000_000 { @@ -386,7 +288,7 @@ pub struct Config { pub pll_mux: PLLSrc, pub pll: PLLConfig, pub mux: ClockSrc, - pub voltage: VoltageRange, + pub voltage: VoltageScale, pub ahb_pre: AHBPrescaler, pub apb1_pre: APBPrescaler, pub apb2_pre: APBPrescaler, @@ -400,7 +302,7 @@ impl Default for Config { hsi: true, pll_mux: PLLSrc::HSI, pll: PLLConfig::default(), - voltage: VoltageRange::Min1V8, + voltage: VoltageScale::Scale3, mux: ClockSrc::HSI, ahb_pre: AHBPrescaler::NotDivided, apb1_pre: APBPrescaler::NotDivided, diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs index 2deee80d..321270a7 100644 --- a/embassy-stm32/src/rcc/f3.rs +++ b/embassy-stm32/src/rcc/f3.rs @@ -264,6 +264,7 @@ fn calc_pll(config: &Config, Hertz(sysclk): Hertz) -> (Hertz, PllConfig) { } #[inline] +#[allow(unused_variables)] fn get_usb_pre(config: &Config, sysclk: u32, pclk1: u32, pll_config: &Option) -> Usbpre { cfg_if::cfg_if! { // Some chips do not have USB diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index b8447044..7aa9f0fd 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use stm32_metapac::rcc::vals::{Mco1, Mco2, Mcopre}; use super::sealed::RccPeripheral; diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs index 5e3a7911..bf2d5199 100644 --- a/embassy-stm32/src/rcc/g0.rs +++ b/embassy-stm32/src/rcc/g0.rs @@ -1,5 +1,6 @@ +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::flash::vals::Latency; -use crate::pac::rcc::vals::{self, Hpre, Hsidiv, Ppre, Sw}; +use crate::pac::rcc::vals::{self, Hsidiv, Ppre, Sw}; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -172,58 +173,6 @@ impl From for u32 { } } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> Ppre { - match self { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> Hpre { - match self { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, @@ -425,25 +374,14 @@ pub(crate) unsafe fn init(config: Config) { FLASH.acr().modify(|w| w.set_latency(target_flash_latency)); } - let ahb_div = match config.ahb_pre { - AHBPrescaler::NotDivided => 1, - AHBPrescaler::Div2 => 2, - AHBPrescaler::Div4 => 4, - AHBPrescaler::Div8 => 8, - AHBPrescaler::Div16 => 16, - AHBPrescaler::Div64 => 64, - AHBPrescaler::Div128 => 128, - AHBPrescaler::Div256 => 256, - AHBPrescaler::Div512 => 512, - }; - let ahb_freq = sys_clk / ahb_div; + let ahb_freq = Hertz(sys_clk) / config.ahb_pre; let (apb_freq, apb_tim_freq) = match config.apb_pre { - APBPrescaler::NotDivided => (ahb_freq, ahb_freq), + APBPrescaler::NotDivided => (ahb_freq.0, ahb_freq.0), pre => { let pre: Ppre = pre.into(); let pre: u8 = 1 << (pre.to_bits() - 3); - let freq = ahb_freq / pre as u32; + let freq = ahb_freq.0 / pre as u32; (freq, freq * 2) } }; @@ -455,7 +393,7 @@ pub(crate) unsafe fn init(config: Config) { set_freqs(Clocks { sys: Hertz(sys_clk), - ahb1: Hertz(ahb_freq), + ahb1: ahb_freq, apb1: Hertz(apb_freq), apb1_tim: Hertz(apb_tim_freq), }); diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs index ff8f9754..dff04023 100644 --- a/embassy-stm32/src/rcc/g4.rs +++ b/embassy-stm32/src/rcc/g4.rs @@ -2,6 +2,7 @@ use stm32_metapac::flash::vals::Latency; use stm32_metapac::rcc::vals::{Hpre, Pllsrc, Ppre, Sw}; use stm32_metapac::FLASH; +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::{PWR, RCC}; use crate::rcc::sealed::RccPeripheral; use crate::rcc::{set_freqs, Clocks}; @@ -21,30 +22,6 @@ pub enum ClockSrc { PLL, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - /// PLL clock input source #[derive(Clone, Copy, Debug)] pub enum PllSrc { diff --git a/embassy-stm32/src/rcc/h5.rs b/embassy-stm32/src/rcc/h5.rs index 7e2f75ab..2e72b193 100644 --- a/embassy-stm32/src/rcc/h5.rs +++ b/embassy-stm32/src/rcc/h5.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use stm32_metapac::rcc::vals::{Hpre, Ppre, Timpre}; +use stm32_metapac::rcc::vals::Timpre; use crate::pac::pwr::vals::Vos; use crate::pac::rcc::vals::{Hseext, Hsidiv, Mco1, Mco2, Pllrge, Pllsrc, Pllvcosel, Sw}; @@ -26,21 +26,7 @@ const VCO_MAX: u32 = 420_000_000; const VCO_WIDE_MIN: u32 = 128_000_000; const VCO_WIDE_MAX: u32 = 560_000_000; -/// Voltage Scale -/// -/// Represents the voltage range feeding the CPU core. The maximum core -/// clock frequency depends on this value. -#[derive(Copy, Clone, PartialEq)] -pub enum VoltageScale { - /// VOS 0 range VCORE 1.30V - 1.40V - Scale0, - /// VOS 1 range VCORE 1.15V - 1.26V - Scale1, - /// VOS 2 range VCORE 1.05V - 1.15V - Scale2, - /// VOS 3 range VCORE 0.95V - 1.05V - Scale3, -} +pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; pub enum HseMode { /// crystal/ceramic oscillator (HSEBYP=0) @@ -105,57 +91,7 @@ pub struct Pll { pub divr: Option, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -impl AHBPrescaler { - fn div(&self, clk: Hertz) -> Hertz { - match self { - Self::NotDivided => clk, - Self::Div2 => clk / 2u32, - Self::Div4 => clk / 4u32, - Self::Div8 => clk / 8u32, - Self::Div16 => clk / 16u32, - Self::Div64 => clk / 64u32, - Self::Div128 => clk / 128u32, - Self::Div256 => clk / 256u32, - Self::Div512 => clk / 512u32, - } - } -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - impl APBPrescaler { - fn div(&self, clk: Hertz) -> Hertz { - match self { - Self::NotDivided => clk, - Self::Div2 => clk / 2u32, - Self::Div4 => clk / 4u32, - Self::Div8 => clk / 8u32, - Self::Div16 => clk / 16u32, - } - } - fn div_tim(&self, clk: Hertz, tim: TimerPrescaler) -> Hertz { match (tim, self) { // The timers kernel clock is equal to rcc_hclk1 if PPRE1 or PPRE2 corresponds to a @@ -193,34 +129,6 @@ impl From for Timpre { } } -impl From for Ppre { - fn from(val: APBPrescaler) -> Ppre { - match val { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl From for Hpre { - fn from(val: AHBPrescaler) -> Hpre { - match val { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - /// Configuration of the core clocks #[non_exhaustive] pub struct Config { @@ -406,13 +314,13 @@ pub(crate) unsafe fn init(config: Config) { }; assert!(sys <= max_clk); - let hclk = config.ahb_pre.div(sys); + let hclk = sys / config.ahb_pre; - let apb1 = config.apb1_pre.div(hclk); + let apb1 = hclk / config.apb1_pre; let apb1_tim = config.apb1_pre.div_tim(hclk, config.timer_prescaler); - let apb2 = config.apb2_pre.div(hclk); + let apb2 = hclk / config.apb2_pre; let apb2_tim = config.apb2_pre.div_tim(hclk, config.timer_prescaler); - let apb3 = config.apb3_pre.div(hclk); + let apb3 = hclk / config.apb3_pre; flash_setup(hclk, config.voltage_scale); diff --git a/embassy-stm32/src/rcc/h7.rs b/embassy-stm32/src/rcc/h7.rs index 7e5cd0d1..0788b064 100644 --- a/embassy-stm32/src/rcc/h7.rs +++ b/embassy-stm32/src/rcc/h7.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; pub use pll::PllConfig; use stm32_metapac::rcc::vals::{Mco1, Mco2}; @@ -24,21 +24,7 @@ pub const HSI48_FREQ: Hertz = Hertz(48_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -/// Voltage Scale -/// -/// Represents the voltage range feeding the CPU core. The maximum core -/// clock frequency depends on this value. -#[derive(Copy, Clone, PartialEq)] -pub enum VoltageScale { - /// VOS 0 range VCORE 1.26V - 1.40V - Scale0, - /// VOS 1 range VCORE 1.15V - 1.26V - Scale1, - /// VOS 2 range VCORE 1.05V - 1.15V - Scale2, - /// VOS 3 range VCORE 0.95V - 1.05V - Scale3, -} +pub use super::common::VoltageScale; #[derive(Clone, Copy)] pub enum AdcClockSource { diff --git a/embassy-stm32/src/rcc/l0.rs b/embassy-stm32/src/rcc/l0.rs index 46a528e3..46b58ca7 100644 --- a/embassy-stm32/src/rcc/l0.rs +++ b/embassy-stm32/src/rcc/l0.rs @@ -1,3 +1,4 @@ +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::RCC; #[cfg(crs)] @@ -70,30 +71,6 @@ pub enum PLLMul { Mul48, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -136,34 +113,6 @@ impl From for Pllsrc { } } -impl From for Ppre { - fn from(val: APBPrescaler) -> Ppre { - match val { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl From for Hpre { - fn from(val: AHBPrescaler) -> Hpre { - match val { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - impl From for Msirange { fn from(val: MSIRange) -> Msirange { match val { diff --git a/embassy-stm32/src/rcc/l1.rs b/embassy-stm32/src/rcc/l1.rs index 59a6eac8..bdfc5b87 100644 --- a/embassy-stm32/src/rcc/l1.rs +++ b/embassy-stm32/src/rcc/l1.rs @@ -1,3 +1,4 @@ +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Plldiv, Pllmul, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; @@ -68,30 +69,6 @@ pub enum PLLMul { Mul48, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -134,34 +111,6 @@ impl From for Pllsrc { } } -impl From for Ppre { - fn from(val: APBPrescaler) -> Ppre { - match val { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl From for Hpre { - fn from(val: AHBPrescaler) -> Hpre { - match val { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - impl From for Msirange { fn from(val: MSIRange) -> Msirange { match val { diff --git a/embassy-stm32/src/rcc/l4.rs b/embassy-stm32/src/rcc/l4.rs index 8a9b4adb..237b7bc9 100644 --- a/embassy-stm32/src/rcc/l4.rs +++ b/embassy-stm32/src/rcc/l4.rs @@ -1,9 +1,10 @@ use core::marker::PhantomData; -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use stm32_metapac::rcc::regs::Cfgr; use stm32_metapac::rcc::vals::{Lsedrv, Mcopre, Mcosel}; +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::gpio::sealed::AFType; use crate::gpio::Speed; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; @@ -78,30 +79,6 @@ pub enum PLLDiv { Div4, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -209,34 +186,6 @@ impl From for Pllsrc { } } -impl From for Ppre { - fn from(val: APBPrescaler) -> Ppre { - match val { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl From for Hpre { - fn from(val: AHBPrescaler) -> Hpre { - match val { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - impl From for Msirange { fn from(val: MSIRange) -> Msirange { match val { diff --git a/embassy-stm32/src/rcc/l5.rs b/embassy-stm32/src/rcc/l5.rs index 16da65d5..a85e1488 100644 --- a/embassy-stm32/src/rcc/l5.rs +++ b/embassy-stm32/src/rcc/l5.rs @@ -1,5 +1,6 @@ use stm32_metapac::PWR; +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::rcc::vals::{Hpre, Msirange, Pllsrc, Ppre, Sw}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; @@ -71,30 +72,6 @@ pub enum PLLDiv { Div4, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - /// PLL clock input source #[derive(Clone, Copy)] pub enum PLLSource { @@ -202,34 +179,6 @@ impl From for Pllsrc { } } -impl From for Ppre { - fn from(val: APBPrescaler) -> Ppre { - match val { - APBPrescaler::NotDivided => Ppre::DIV1, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - -impl From for Hpre { - fn from(val: AHBPrescaler) -> Hpre { - match val { - AHBPrescaler::NotDivided => Hpre::DIV1, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - impl From for Msirange { fn from(val: MSIRange) -> Msirange { match val { diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 4ae65d3e..5c69037e 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -1,5 +1,7 @@ #![macro_use] +pub mod common; + use core::mem::MaybeUninit; use crate::time::Hertz; diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index cfc07f06..b5feeb0c 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs @@ -1,5 +1,6 @@ -use stm32_metapac::rcc::vals::{Hpre, Msirange, Msirgsel, Pllm, Pllsrc, Ppre, Sw}; +use stm32_metapac::rcc::vals::{Msirange, Msirgsel, Pllm, Pllsrc, Sw}; +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::pac::{FLASH, RCC}; use crate::rcc::{set_freqs, Clocks}; use crate::time::Hertz; @@ -10,19 +11,7 @@ pub const HSI_FREQ: Hertz = Hertz(16_000_000); /// LSI speed pub const LSI_FREQ: Hertz = Hertz(32_000); -/// Voltage Scale -/// -/// Represents the voltage range feeding the CPU core. The maximum core -/// clock frequency depends on this value. -#[derive(Copy, Clone, PartialEq)] -pub enum VoltageScale { - // Highest frequency - Range1, - Range2, - Range3, - // Lowest power - Range4, -} +pub use super::common::VoltageScale; #[derive(Copy, Clone)] pub enum ClockSrc { @@ -130,36 +119,6 @@ impl Into for PllM { } } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, - Div64, - Div128, - Div256, - Div512, -} - -impl Into for AHBPrescaler { - fn into(self) -> Hpre { - match self { - AHBPrescaler::NotDivided => Hpre::NONE, - AHBPrescaler::Div2 => Hpre::DIV2, - AHBPrescaler::Div4 => Hpre::DIV4, - AHBPrescaler::Div8 => Hpre::DIV8, - AHBPrescaler::Div16 => Hpre::DIV16, - AHBPrescaler::Div64 => Hpre::DIV64, - AHBPrescaler::Div128 => Hpre::DIV128, - AHBPrescaler::Div256 => Hpre::DIV256, - AHBPrescaler::Div512 => Hpre::DIV512, - } - } -} - impl Into for AHBPrescaler { fn into(self) -> u8 { match self { @@ -182,28 +141,6 @@ impl Default for AHBPrescaler { } } -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> Ppre { - match self { - APBPrescaler::NotDivided => Ppre::NONE, - APBPrescaler::Div2 => Ppre::DIV2, - APBPrescaler::Div4 => Ppre::DIV4, - APBPrescaler::Div8 => Ppre::DIV8, - APBPrescaler::Div16 => Ppre::DIV16, - } - } -} - impl Default for APBPrescaler { fn default() -> Self { APBPrescaler::NotDivided @@ -389,12 +326,12 @@ pub(crate) unsafe fn init(config: Config) { } // TODO make configurable - let power_vos = VoltageScale::Range4; + let power_vos = VoltageScale::Scale3; // states and programming delay let wait_states = match power_vos { // VOS 0 range VCORE 1.26V - 1.40V - VoltageScale::Range1 => { + VoltageScale::Scale0 => { if sys_clk < 32_000_000 { 0 } else if sys_clk < 64_000_000 { @@ -408,7 +345,7 @@ pub(crate) unsafe fn init(config: Config) { } } // VOS 1 range VCORE 1.15V - 1.26V - VoltageScale::Range2 => { + VoltageScale::Scale1 => { if sys_clk < 30_000_000 { 0 } else if sys_clk < 60_000_000 { @@ -420,7 +357,7 @@ pub(crate) unsafe fn init(config: Config) { } } // VOS 2 range VCORE 1.05V - 1.15V - VoltageScale::Range3 => { + VoltageScale::Scale2 => { if sys_clk < 24_000_000 { 0 } else if sys_clk < 48_000_000 { @@ -430,7 +367,7 @@ pub(crate) unsafe fn init(config: Config) { } } // VOS 3 range VCORE 0.95V - 1.05V - VoltageScale::Range4 => { + VoltageScale::Scale3 => { if sys_clk < 12_000_000 { 0 } else { diff --git a/embassy-stm32/src/rcc/wb.rs b/embassy-stm32/src/rcc/wb.rs index 4322b950..21aacec5 100644 --- a/embassy-stm32/src/rcc/wb.rs +++ b/embassy-stm32/src/rcc/wb.rs @@ -1,3 +1,4 @@ +pub use super::common::{AHBPrescaler, APBPrescaler}; use crate::rcc::Clocks; use crate::time::{khz, mhz, Hertz}; @@ -102,68 +103,6 @@ pub struct Pll { pub divr: Option, } -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div3, - Div4, - Div5, - Div6, - Div8, - Div10, - Div16, - Div32, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> u8 { - match self { - APBPrescaler::NotDivided => 1, - APBPrescaler::Div2 => 0x04, - APBPrescaler::Div4 => 0x05, - APBPrescaler::Div8 => 0x06, - APBPrescaler::Div16 => 0x07, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> u8 { - match self { - AHBPrescaler::NotDivided => 0x0, - AHBPrescaler::Div2 => 0x08, - AHBPrescaler::Div3 => 0x01, - AHBPrescaler::Div4 => 0x09, - AHBPrescaler::Div5 => 0x02, - AHBPrescaler::Div6 => 0x05, - AHBPrescaler::Div8 => 0x0a, - AHBPrescaler::Div10 => 0x06, - AHBPrescaler::Div16 => 0x0b, - AHBPrescaler::Div32 => 0x07, - AHBPrescaler::Div64 => 0x0c, - AHBPrescaler::Div128 => 0x0d, - AHBPrescaler::Div256 => 0x0e, - AHBPrescaler::Div512 => 0x0f, - } - } -} - /// Clocks configutation pub struct Config { pub hse: Option, diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs index 6b69bb1c..ea6e8dde 100644 --- a/embassy-stm32/src/rcc/wl.rs +++ b/embassy-stm32/src/rcc/wl.rs @@ -1,3 +1,4 @@ +pub use super::common::{AHBPrescaler, APBPrescaler, VoltageScale}; use crate::pac::pwr::vals::Dbp; use crate::pac::{FLASH, PWR, RCC}; use crate::rcc::{set_freqs, Clocks}; @@ -73,9 +74,9 @@ impl MSIRange { fn vos(&self) -> VoltageScale { if self > &MSIRange::Range8 { - VoltageScale::Range1 + VoltageScale::Scale0 } else { - VoltageScale::Range2 + VoltageScale::Scale1 } } } @@ -105,78 +106,6 @@ impl Into for MSIRange { } } -/// Voltage Scale -/// -/// Represents the voltage range feeding the CPU core. The maximum core -/// clock frequency depends on this value. -#[derive(Copy, Clone, PartialEq)] -pub enum VoltageScale { - Range1, - Range2, -} - -/// AHB prescaler -#[derive(Clone, Copy, PartialEq)] -pub enum AHBPrescaler { - NotDivided, - Div2, - Div3, - Div4, - Div5, - Div6, - Div8, - Div10, - Div16, - Div32, - Div64, - Div128, - Div256, - Div512, -} - -/// APB prescaler -#[derive(Clone, Copy)] -pub enum APBPrescaler { - NotDivided, - Div2, - Div4, - Div8, - Div16, -} - -impl Into for APBPrescaler { - fn into(self) -> u8 { - match self { - APBPrescaler::NotDivided => 1, - APBPrescaler::Div2 => 0x04, - APBPrescaler::Div4 => 0x05, - APBPrescaler::Div8 => 0x06, - APBPrescaler::Div16 => 0x07, - } - } -} - -impl Into for AHBPrescaler { - fn into(self) -> u8 { - match self { - AHBPrescaler::NotDivided => 0x0, - AHBPrescaler::Div2 => 0x08, - AHBPrescaler::Div3 => 0x01, - AHBPrescaler::Div4 => 0x09, - AHBPrescaler::Div5 => 0x02, - AHBPrescaler::Div6 => 0x05, - AHBPrescaler::Div8 => 0x0a, - AHBPrescaler::Div10 => 0x06, - AHBPrescaler::Div16 => 0x0b, - AHBPrescaler::Div32 => 0x07, - AHBPrescaler::Div64 => 0x0c, - AHBPrescaler::Div128 => 0x0d, - AHBPrescaler::Div256 => 0x0e, - AHBPrescaler::Div512 => 0x0f, - } - } -} - /// Clocks configutation pub struct Config { pub mux: ClockSrc, @@ -220,8 +149,8 @@ pub enum Lsedrv { pub(crate) unsafe fn init(config: Config) { let (sys_clk, sw, vos) = match config.mux { - ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Range2), - ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Range1), + ClockSrc::HSI16 => (HSI_FREQ.0, 0x01, VoltageScale::Scale1), + ClockSrc::HSE32 => (HSE32_FREQ.0, 0x02, VoltageScale::Scale0), ClockSrc::MSI(range) => (range.freq(), 0x00, range.vos()), }; @@ -266,12 +195,12 @@ pub(crate) unsafe fn init(config: Config) { // Adjust flash latency let flash_clk_src_freq: u32 = shd_ahb_freq; let ws = match vos { - VoltageScale::Range1 => match flash_clk_src_freq { + VoltageScale::Scale0 => match flash_clk_src_freq { 0..=18_000_000 => 0b000, 18_000_001..=36_000_000 => 0b001, _ => 0b010, }, - VoltageScale::Range2 => match flash_clk_src_freq { + VoltageScale::Scale1 => match flash_clk_src_freq { 0..=6_000_000 => 0b000, 6_000_001..=12_000_000 => 0b001, _ => 0b010, diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index b2faec53..2a4978ec 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -1,15 +1,17 @@ #![macro_use] use core::future::poll_fn; +use core::marker::PhantomData; use core::task::Poll; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use rand_core::{CryptoRng, RngCore}; -use crate::{pac, peripherals, Peripheral}; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, pac, peripherals, Peripheral}; -pub(crate) static RNG_WAKER: AtomicWaker = AtomicWaker::new(); +static RNG_WAKER: AtomicWaker = AtomicWaker::new(); #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { @@ -17,68 +19,145 @@ pub enum Error { ClockError, } +pub struct InterruptHandler { + _phantom: PhantomData, +} + +impl interrupt::typelevel::Handler for InterruptHandler { + unsafe fn on_interrupt() { + let bits = T::regs().sr().read(); + if bits.drdy() || bits.seis() || bits.ceis() { + T::regs().cr().modify(|reg| reg.set_ie(false)); + RNG_WAKER.wake(); + } + } +} + pub struct Rng<'d, T: Instance> { _inner: PeripheralRef<'d, T>, } impl<'d, T: Instance> Rng<'d, T> { - pub fn new(inner: impl Peripheral

+ 'd) -> Self { + pub fn new( + inner: impl Peripheral

+ 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, + ) -> Self { T::enable(); T::reset(); into_ref!(inner); let mut random = Self { _inner: inner }; random.reset(); + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + random } + #[cfg(rng_v1)] pub fn reset(&mut self) { - // rng_v2 locks up on seed error, needs reset - #[cfg(rng_v2)] - if T::regs().sr().read().seis() { - T::reset(); - } - T::regs().cr().modify(|reg| { - reg.set_rngen(true); - reg.set_ie(true); + T::regs().cr().write(|reg| { + reg.set_rngen(false); }); T::regs().sr().modify(|reg| { reg.set_seis(false); reg.set_ceis(false); }); + T::regs().cr().modify(|reg| { + reg.set_rngen(true); + }); // Reference manual says to discard the first. let _ = self.next_u32(); } - pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { + #[cfg(not(rng_v1))] + pub fn reset(&mut self) { + T::regs().cr().write(|reg| { + reg.set_rngen(false); + reg.set_condrst(true); + // set RNG config "A" according to reference manual + // this has to be written within the same write access as setting the CONDRST bit + reg.set_nistc(pac::rng::vals::Nistc::DEFAULT); + reg.set_rng_config1(pac::rng::vals::RngConfig1::CONFIGA); + reg.set_rng_config2(pac::rng::vals::RngConfig2::CONFIGA_B); + reg.set_rng_config3(pac::rng::vals::RngConfig3::CONFIGA); + reg.set_clkdiv(pac::rng::vals::Clkdiv::NODIV); + }); + // wait for CONDRST to be set + while !T::regs().cr().read().condrst() {} + // magic number must be written immediately before every read or write access to HTCR + T::regs().htcr().write(|w| w.set_htcfg(pac::rng::vals::Htcfg::MAGIC)); + // write recommended value according to reference manual + // note: HTCR can only be written during conditioning + T::regs() + .htcr() + .write(|w| w.set_htcfg(pac::rng::vals::Htcfg::RECOMMENDED)); + // finish conditioning T::regs().cr().modify(|reg| { reg.set_rngen(true); + reg.set_condrst(false); }); + // wait for CONDRST to be reset + while T::regs().cr().read().condrst() {} + } + pub fn recover_seed_error(&mut self) -> () { + self.reset(); + // reset should also clear the SEIS flag + if T::regs().sr().read().seis() { + warn!("recovering from seed error failed"); + return; + } + // wait for SECS to be cleared by RNG + while T::regs().sr().read().secs() {} + } + + pub async fn async_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> { for chunk in dest.chunks_mut(4) { - poll_fn(|cx| { - RNG_WAKER.register(cx.waker()); - T::regs().cr().modify(|reg| { - reg.set_ie(true); - }); - - let bits = T::regs().sr().read(); - - if bits.drdy() { - Poll::Ready(Ok(())) - } else if bits.seis() { - self.reset(); - Poll::Ready(Err(Error::SeedError)) - } else if bits.ceis() { - self.reset(); - Poll::Ready(Err(Error::ClockError)) - } else { - Poll::Pending + let bits = T::regs().sr().read(); + if bits.seis() { + // in case of noise-source or seed error we try to recover here + // but we must not use the data in DR and we return an error + // to leave retry-logic to the application + self.recover_seed_error(); + return Err(Error::SeedError); + } else if bits.ceis() { + // clock error detected, DR could still be used but keep it safe, + // clear the error and abort + T::regs().sr().modify(|sr| sr.set_ceis(false)); + return Err(Error::ClockError); + } else if bits.drdy() { + // DR can be read up to four times until the output buffer is empty + // DRDY is cleared automatically when that happens + let random_word = T::regs().dr().read(); + // reference manual: always check if DR is zero + if random_word == 0 { + return Err(Error::SeedError); } - }) - .await?; - let random_bytes = T::regs().dr().read().to_be_bytes(); - for (dest, src) in chunk.iter_mut().zip(random_bytes.iter()) { - *dest = *src + // write bytes to chunk + for (dest, src) in chunk.iter_mut().zip(random_word.to_be_bytes().iter()) { + *dest = *src + } + } else { + // wait for interrupt + poll_fn(|cx| { + // quick check to avoid registration if already done. + let bits = T::regs().sr().read(); + if bits.drdy() || bits.seis() || bits.ceis() { + return Poll::Ready(()); + } + RNG_WAKER.register(cx.waker()); + T::regs().cr().modify(|reg| reg.set_ie(true)); + // Need to check condition **after** `register` to avoid a race + // condition that would result in lost notifications. + let bits = T::regs().sr().read(); + if bits.drdy() || bits.seis() || bits.ceis() { + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; } } @@ -129,57 +208,20 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + crate::rcc::RccPeripheral {} +pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { + type Interrupt: interrupt::typelevel::Interrupt; +} -foreach_peripheral!( - (rng, $inst:ident) => { - impl Instance for peripherals::$inst {} +foreach_interrupt!( + ($inst:ident, rng, RNG, GLOBAL, $irq:ident) => { + impl Instance for peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } impl sealed::Instance for peripherals::$inst { fn regs() -> crate::pac::rng::Rng { - crate::pac::RNG + crate::pac::$inst } } }; ); - -#[cfg(feature = "rt")] -macro_rules! irq { - ($irq:ident) => { - mod rng_irq { - use crate::interrupt; - - #[interrupt] - unsafe fn $irq() { - let bits = $crate::pac::RNG.sr().read(); - if bits.drdy() || bits.seis() || bits.ceis() { - $crate::pac::RNG.cr().write(|reg| reg.set_ie(false)); - $crate::rng::RNG_WAKER.wake(); - } - } - } - }; -} - -#[cfg(feature = "rt")] -foreach_interrupt!( - (RNG) => { - irq!(RNG); - }; - - (RNG_LPUART1) => { - irq!(RNG_LPUART1); - }; - - (AES_RNG_LPUART1) => { - irq!(AES_RNG_LPUART1); - }; - - (AES_RNG) => { - irq!(AES_RNG); - }; - - (HASH_RNG) => { - irq!(HASH_RNG); - }; -); diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 12a2ac79..323be318 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -15,7 +15,7 @@ pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError}; #[cfg_attr(any(rtc_v3, rtc_v3u5), path = "v3.rs")] mod _version; pub use _version::*; -use embassy_hal_common::Peripheral; +use embassy_hal_internal::Peripheral; /// Errors that can occur on methods on [RtcClock] #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index a2eace6d..e3b9dfb8 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -39,9 +39,8 @@ impl<'d, T: Instance> super::Rtc<'d, T> { let rtcsel = reg.rtcsel().to_bits(); if !reg.rtcen() || rtcsel != clock_config { - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] + #[cfg(not(any(rtc_v2l0, rtc_v2l1, rtc_v2f2)))] crate::pac::RCC.bdcr().modify(|w| w.set_bdrst(true)); - #[cfg(not(any(rtc_v2l0, rtc_v2l1)))] let cr = crate::pac::RCC.bdcr(); #[cfg(any(rtc_v2l0, rtc_v2l1))] @@ -201,6 +200,11 @@ impl sealed::Instance for crate::peripherals::RTC { // read to allow the pwr clock to enable crate::pac::PWR.cr1().read(); } + #[cfg(any(rtc_v2f2))] + { + crate::pac::RCC.apb1enr().modify(|w| w.set_pwren(true)); + crate::pac::PWR.cr().read(); + } } fn read_backup_register(rtc: &Rtc, register: usize) -> Option { diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 434c56a4..6b532363 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -6,8 +6,8 @@ use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index d5f63f84..bbc7c3b9 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -4,7 +4,7 @@ use core::ptr; use embassy_embedded_hal::SetConfig; use embassy_futures::join::join; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; use crate::dma::{slice_ptr_parts, word, Transfer}; @@ -36,6 +36,7 @@ pub enum BitOrder { pub struct Config { pub mode: Mode, pub bit_order: BitOrder, + pub frequency: Hertz, } impl Default for Config { @@ -43,6 +44,7 @@ impl Default for Config { Self { mode: MODE_0, bit_order: BitOrder::MsbFirst, + frequency: Hertz(1_000_000), } } } @@ -88,7 +90,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso: impl Peripheral

> + 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, - freq: Hertz, config: Config, ) -> Self { into_ref!(peri, sck, mosi, miso); @@ -112,7 +113,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Some(miso.map_into()), txdma, rxdma, - freq, config, ) } @@ -123,7 +123,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso: impl Peripheral

> + 'd, txdma: impl Peripheral

+ 'd, // TODO remove rxdma: impl Peripheral

+ 'd, - freq: Hertz, config: Config, ) -> Self { into_ref!(sck, miso); @@ -139,7 +138,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { Some(miso.map_into()), txdma, rxdma, - freq, config, ) } @@ -150,7 +148,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { mosi: impl Peripheral

> + 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, // TODO remove - freq: Hertz, config: Config, ) -> Self { into_ref!(sck, mosi); @@ -166,7 +163,6 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { None, txdma, rxdma, - freq, config, ) } @@ -176,14 +172,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { mosi: impl Peripheral

> + 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, // TODO: remove - freq: Hertz, config: Config, ) -> Self { into_ref!(mosi); mosi.set_as_af_pull(mosi.af_num(), AFType::OutputPushPull, Pull::Down); mosi.set_speed(crate::gpio::Speed::Medium); - Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, freq, config) + Self::new_inner(peri, None, Some(mosi.map_into()), None, txdma, rxdma, config) } #[cfg(stm32wl)] @@ -201,7 +196,8 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let mut config = Config::default(); config.mode = MODE_0; config.bit_order = BitOrder::MsbFirst; - Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) + config.frequency = freq; + Self::new_inner(peri, None, None, None, txdma, rxdma, config) } #[allow(dead_code)] @@ -209,10 +205,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { peri: impl Peripheral

+ 'd, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, - freq: Hertz, config: Config, ) -> Self { - Self::new_inner(peri, None, None, None, txdma, rxdma, freq, config) + Self::new_inner(peri, None, None, None, txdma, rxdma, config) } fn new_inner( @@ -222,12 +217,12 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso: Option>, txdma: impl Peripheral

+ 'd, rxdma: impl Peripheral

+ 'd, - freq: Hertz, config: Config, ) -> Self { into_ref!(peri, txdma, rxdma); let pclk = T::frequency(); + let freq = config.frequency; let br = compute_baud_rate(pclk, freq.into()); let cpha = config.raw_phase(); @@ -334,19 +329,29 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let lsbfirst = config.raw_byte_order(); + let pclk = T::frequency(); + let freq = config.frequency; + let br = compute_baud_rate(pclk, freq.into()); + #[cfg(any(spi_v1, spi_f1, spi_v2))] T::REGS.cr1().modify(|w| { w.set_cpha(cpha); w.set_cpol(cpol); + w.set_br(br); w.set_lsbfirst(lsbfirst); }); #[cfg(any(spi_v3, spi_v4, spi_v5))] - T::REGS.cfg2().modify(|w| { - w.set_cpha(cpha); - w.set_cpol(cpol); - w.set_lsbfirst(lsbfirst); - }); + { + T::REGS.cfg2().modify(|w| { + w.set_cpha(cpha); + w.set_cpol(cpol); + w.set_lsbfirst(lsbfirst); + }); + T::REGS.cfg1().modify(|w| { + w.set_mbr(br); + }); + } } pub fn get_current_config(&self) -> Config { @@ -354,6 +359,9 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { let cfg = T::REGS.cr1().read(); #[cfg(any(spi_v3, spi_v4, spi_v5))] let cfg = T::REGS.cfg2().read(); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + let cfg1 = T::REGS.cfg1().read(); + let polarity = if cfg.cpol() == vals::Cpol::IDLELOW { Polarity::IdleLow } else { @@ -371,9 +379,18 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { BitOrder::MsbFirst }; + #[cfg(any(spi_v1, spi_f1, spi_v2))] + let br = cfg.br(); + #[cfg(any(spi_v3, spi_v4, spi_v5))] + let br = cfg1.mbr(); + + let pclk = T::frequency(); + let frequency = compute_frequency(pclk, br); + Config { mode: Mode { polarity, phase }, bit_order, + frequency, } } @@ -653,6 +670,21 @@ fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> Br { Br::from_bits(val) } +fn compute_frequency(clocks: Hertz, br: Br) -> Hertz { + let div: u16 = match br { + Br::DIV2 => 2, + Br::DIV4 => 4, + Br::DIV8 => 8, + Br::DIV16 => 16, + Br::DIV32 => 32, + Br::DIV64 => 64, + Br::DIV128 => 128, + Br::DIV256 => 256, + }; + + clocks / div +} + trait RegsExt { fn tx_ptr(&self) -> *mut W; fn rx_ptr(&self) -> *mut W; diff --git a/embassy-stm32/src/pwm/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs similarity index 91% rename from embassy-stm32/src/pwm/complementary_pwm.rs rename to embassy-stm32/src/timer/complementary_pwm.rs index 4d64d005..48cb610f 100644 --- a/embassy-stm32/src/pwm/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -1,13 +1,13 @@ use core::marker::PhantomData; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use stm32_metapac::timer::vals::Ckd; use super::simple_pwm::*; use super::*; #[allow(unused_imports)] use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::AnyPin; +use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::Peripheral; @@ -17,13 +17,13 @@ pub struct ComplementaryPwmPin<'d, Perip, Channel> { } macro_rules! complementary_channel_impl { - ($new_chx:ident, $channel:ident, $pin_trait:ident, $complementary_pin_trait:ident) => { + ($new_chx:ident, $channel:ident, $pin_trait:ident) => { impl<'d, Perip: CaptureCompare16bitInstance> ComplementaryPwmPin<'d, Perip, $channel> { - pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); critical_section::with(|_| { pin.set_low(); - pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + pin.set_as_af(pin.af_num(), output_type.into()); #[cfg(gpio_v2)] pin.set_speed(crate::gpio::Speed::VeryHigh); }); @@ -36,10 +36,10 @@ macro_rules! complementary_channel_impl { }; } -complementary_channel_impl!(new_ch1, Ch1, Channel1Pin, Channel1ComplementaryPin); -complementary_channel_impl!(new_ch2, Ch2, Channel2Pin, Channel2ComplementaryPin); -complementary_channel_impl!(new_ch3, Ch3, Channel3Pin, Channel3ComplementaryPin); -complementary_channel_impl!(new_ch4, Ch4, Channel4Pin, Channel4ComplementaryPin); +complementary_channel_impl!(new_ch1, Ch1, Channel1ComplementaryPin); +complementary_channel_impl!(new_ch2, Ch2, Channel2ComplementaryPin); +complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); +complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); pub struct ComplementaryPwm<'d, T> { inner: PeripheralRef<'d, T>, diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 09b7a377..6c2d6d82 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,3 +1,6 @@ +pub mod complementary_pwm; +pub mod simple_pwm; + use stm32_metapac::timer::vals; use crate::interrupt; @@ -43,15 +46,123 @@ pub(crate) mod sealed { pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { fn regs_advanced() -> crate::pac::timer::TimAdv; } + + pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { + /// Global output enable. Does not do anything on non-advanced timers. + fn enable_outputs(&mut self, enable: bool); + + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + + fn enable_channel(&mut self, channel: Channel, enable: bool); + + fn set_compare_value(&mut self, channel: Channel, value: u16); + + fn get_max_compare_value(&self) -> u16; + } + + pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { + fn set_dead_time_clock_division(&mut self, value: vals::Ckd); + + fn set_dead_time_value(&mut self, value: u8); + + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); + } + + pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + + fn enable_channel(&mut self, channel: Channel, enable: bool); + + fn set_compare_value(&mut self, channel: Channel, value: u32); + + fn get_max_compare_value(&self) -> u32; + } } +#[derive(Clone, Copy)] +pub enum Channel { + Ch1, + Ch2, + Ch3, + Ch4, +} + +impl Channel { + pub fn raw(&self) -> usize { + match self { + Channel::Ch1 => 0, + Channel::Ch2 => 1, + Channel::Ch3 => 2, + Channel::Ch4 => 3, + } + } +} + +#[derive(Clone, Copy)] +pub enum OutputCompareMode { + Frozen, + ActiveOnMatch, + InactiveOnMatch, + Toggle, + ForceInactive, + ForceActive, + PwmMode1, + PwmMode2, +} + +impl From for stm32_metapac::timer::vals::Ocm { + fn from(mode: OutputCompareMode) -> Self { + match mode { + OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, + OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, + OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, + OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, + OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, + OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, + OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, + OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, + } + } +} + +pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} + pub trait GeneralPurpose16bitInstance: sealed::GeneralPurpose16bitInstance + 'static {} pub trait GeneralPurpose32bitInstance: sealed::GeneralPurpose32bitInstance + 'static {} pub trait AdvancedControlInstance: sealed::AdvancedControlInstance + 'static {} -pub trait Basic16bitInstance: sealed::Basic16bitInstance + 'static {} +pub trait CaptureCompare16bitInstance: + sealed::CaptureCompare16bitInstance + GeneralPurpose16bitInstance + 'static +{ +} + +pub trait ComplementaryCaptureCompare16bitInstance: + sealed::ComplementaryCaptureCompare16bitInstance + AdvancedControlInstance + 'static +{ +} + +pub trait CaptureCompare32bitInstance: + sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static +{ +} + +pin_trait!(Channel1Pin, CaptureCompare16bitInstance); +pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance); +pin_trait!(Channel2Pin, CaptureCompare16bitInstance); +pin_trait!(Channel2ComplementaryPin, CaptureCompare16bitInstance); +pin_trait!(Channel3Pin, CaptureCompare16bitInstance); +pin_trait!(Channel3ComplementaryPin, CaptureCompare16bitInstance); +pin_trait!(Channel4Pin, CaptureCompare16bitInstance); +pin_trait!(Channel4ComplementaryPin, CaptureCompare16bitInstance); +pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); +pin_trait!(BreakInputPin, CaptureCompare16bitInstance); +pin_trait!(BreakInputComparator1Pin, CaptureCompare16bitInstance); +pin_trait!(BreakInputComparator2Pin, CaptureCompare16bitInstance); +pin_trait!(BreakInput2Pin, CaptureCompare16bitInstance); +pin_trait!(BreakInput2Comparator1Pin, CaptureCompare16bitInstance); +pin_trait!(BreakInput2Comparator2Pin, CaptureCompare16bitInstance); #[allow(unused)] macro_rules! impl_basic_16bit_timer { @@ -140,33 +251,94 @@ macro_rules! impl_32bit_timer { }; } +#[allow(unused)] +macro_rules! impl_compare_capable_16bit { + ($inst:ident) => { + impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn enable_outputs(&mut self, _enable: bool) {} + + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { + use sealed::GeneralPurpose16bitInstance; + let r = Self::regs_gp16(); + let raw_channel: usize = channel.raw(); + r.ccmr_output(raw_channel / 2) + .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } + + fn enable_channel(&mut self, channel: Channel, enable: bool) { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16() + .ccer() + .modify(|w| w.set_cce(channel.raw(), enable)); + } + + fn set_compare_value(&mut self, channel: Channel, value: u16) { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); + } + + fn get_max_compare_value(&self) -> u16 { + use sealed::GeneralPurpose16bitInstance; + Self::regs_gp16().arr().read().arr() + } + } + }; +} + foreach_interrupt! { ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { impl_basic_16bit_timer!($inst, $irq); - - impl Basic16bitInstance for crate::peripherals::$inst { - } + impl Basic16bitInstance for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { impl_basic_16bit_timer!($inst, $irq); - - impl Basic16bitInstance for crate::peripherals::$inst { - } + impl_compare_capable_16bit!($inst); + impl Basic16bitInstance for crate::peripherals::$inst {} + impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { crate::pac::$inst } } - - impl GeneralPurpose16bitInstance for crate::peripherals::$inst { - } }; ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { impl_basic_16bit_timer!($inst, $irq); + impl_32bit_timer!($inst); + impl_compare_capable_16bit!($inst); + impl Basic16bitInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl CaptureCompare32bitInstance for crate::peripherals::$inst {} + impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} + impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} - impl Basic16bitInstance for crate::peripherals::$inst { + impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { + fn set_output_compare_mode( + &mut self, + channel: Channel, + mode: OutputCompareMode, + ) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + let raw_channel = channel.raw(); + Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } + + fn enable_channel(&mut self, channel: Channel, enable: bool) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); + } + + fn set_compare_value(&mut self, channel: Channel, value: u32) { + use crate::timer::sealed::GeneralPurpose32bitInstance; + Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); + } + + fn get_max_compare_value(&self) -> u32 { + use crate::timer::sealed::GeneralPurpose32bitInstance; + Self::regs_gp32().arr().read().arr() as u32 + } } impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { @@ -174,21 +346,16 @@ foreach_interrupt! { unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } } - - impl GeneralPurpose16bitInstance for crate::peripherals::$inst { - } - - impl_32bit_timer!($inst); - - impl GeneralPurpose32bitInstance for crate::peripherals::$inst { - } }; ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { impl_basic_16bit_timer!($inst, $irq); - impl Basic16bitInstance for crate::peripherals::$inst { - } + impl Basic16bitInstance for crate::peripherals::$inst {} + impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} + impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + impl AdvancedControlInstance for crate::peripherals::$inst {} impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { @@ -196,16 +363,70 @@ foreach_interrupt! { } } - impl GeneralPurpose16bitInstance for crate::peripherals::$inst { - } - impl sealed::AdvancedControlInstance for crate::peripherals::$inst { fn regs_advanced() -> crate::pac::timer::TimAdv { crate::pac::$inst } } - impl AdvancedControlInstance for crate::peripherals::$inst { + impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { + fn enable_outputs(&mut self, enable: bool) { + use crate::timer::sealed::AdvancedControlInstance; + let r = Self::regs_advanced(); + r.bdtr().modify(|w| w.set_moe(enable)); + } + + fn set_output_compare_mode( + &mut self, + channel: Channel, + mode: OutputCompareMode, + ) { + use crate::timer::sealed::AdvancedControlInstance; + let r = Self::regs_advanced(); + let raw_channel: usize = channel.raw(); + r.ccmr_output(raw_channel / 2) + .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } + + fn enable_channel(&mut self, channel: Channel, enable: bool) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced() + .ccer() + .modify(|w| w.set_cce(channel.raw(), enable)); + } + + fn set_compare_value(&mut self, channel: Channel, value: u16) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced() + .ccr(channel.raw()) + .modify(|w| w.set_ccr(value)); + } + + fn get_max_compare_value(&self) -> u16 { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced().arr().read().arr() + } } + + impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { + fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); + } + + fn set_dead_time_value(&mut self, value: u8) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); + } + + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { + use crate::timer::sealed::AdvancedControlInstance; + Self::regs_advanced() + .ccer() + .modify(|w| w.set_ccne(channel.raw(), enable)); + } + } + + }; } diff --git a/embassy-stm32/src/pwm/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs similarity index 93% rename from embassy-stm32/src/pwm/simple_pwm.rs rename to embassy-stm32/src/timer/simple_pwm.rs index 995f59c2..e0a81792 100644 --- a/embassy-stm32/src/pwm/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -1,11 +1,11 @@ use core::marker::PhantomData; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::{into_ref, PeripheralRef}; use super::*; #[allow(unused_imports)] use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::AnyPin; +use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::Peripheral; @@ -22,11 +22,11 @@ pub struct PwmPin<'d, Perip, Channel> { macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { impl<'d, Perip: CaptureCompare16bitInstance> PwmPin<'d, Perip, $channel> { - pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { + pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); critical_section::with(|_| { pin.set_low(); - pin.set_as_af(pin.af_num(), AFType::OutputPushPull); + pin.set_as_af(pin.af_num(), output_type.into()); #[cfg(gpio_v2)] pin.set_speed(crate::gpio::Speed::VeryHigh); }); diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index 433ad299..ca117da8 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -2,7 +2,7 @@ use core::future::poll_fn; use core::slice; use core::task::Poll; -use embassy_hal_common::atomic_ring_buffer::RingBuffer; +use embassy_hal_internal::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use super::*; diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index ea8e525e..d99034bc 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -5,8 +5,8 @@ use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; +use embassy_hal_internal::drop::OnDrop; +use embassy_hal_internal::{into_ref, PeripheralRef}; use futures::future::{select, Either}; use crate::dma::{NoDma, Transfer}; @@ -857,7 +857,7 @@ fn configure(r: Regs, config: &Config, pclk_freq: Hertz, kind: Kind, enable_rx: "Using {} oversampling, desired baudrate: {}, actual baudrate: {}", oversampling, config.baudrate, - pclk_freq.0 / div + (pclk_freq.0 * mul as u32) / div ); r.cr2().write(|w| { diff --git a/embassy-stm32/src/usart/ringbuffered.rs b/embassy-stm32/src/usart/ringbuffered.rs index c74d7e09..80261d04 100644 --- a/embassy-stm32/src/usart/ringbuffered.rs +++ b/embassy-stm32/src/usart/ringbuffered.rs @@ -2,7 +2,7 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use embassy_hal_common::PeripheralRef; +use embassy_hal_internal::PeripheralRef; use futures::future::{select, Either}; use super::{clear_interrupt_flags, rdr, sr, BasicInstance, Error, UartRx}; diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index ecdd1d0b..cef19635 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -5,7 +5,7 @@ use core::marker::PhantomData; use core::sync::atomic::{AtomicBool, Ordering}; use core::task::Poll; -use embassy_hal_common::into_ref; +use embassy_hal_internal::into_ref; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver as driver; use embassy_usb_driver::{ diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb_otg/usb.rs index fd0e22ad..348f0f79 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb_otg/usb.rs @@ -3,7 +3,7 @@ use core::marker::PhantomData; use core::sync::atomic::{AtomicBool, AtomicU16, Ordering}; use core::task::Poll; -use embassy_hal_common::{into_ref, Peripheral}; +use embassy_hal_internal::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver::{ self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index b03e81d6..eafd0336 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -1,6 +1,6 @@ use core::marker::PhantomData; -use embassy_hal_common::{into_ref, Peripheral}; +use embassy_hal_internal::{into_ref, Peripheral}; use stm32_metapac::iwdg::vals::{Key, Pr}; use crate::rcc::LSI_FREQ; diff --git a/examples/boot/application/rp/src/bin/a.rs b/examples/boot/application/rp/src/bin/a.rs index c8497494..b5e1950c 100644 --- a/examples/boot/application/rp/src/bin/a.rs +++ b/examples/boot/application/rp/src/bin/a.rs @@ -7,7 +7,7 @@ use core::cell::RefCell; use defmt_rtt as _; use embassy_boot_rp::*; use embassy_executor::Spawner; -use embassy_rp::flash::Flash; +use embassy_rp::flash::{self, Flash}; use embassy_rp::gpio::{Level, Output}; use embassy_rp::watchdog::Watchdog; use embassy_sync::blocking_mutex::Mutex; @@ -34,7 +34,7 @@ async fn main(_s: Spawner) { let mut watchdog = Watchdog::new(p.WATCHDOG); watchdog.start(Duration::from_secs(8)); - let flash: Flash<_, FLASH_SIZE> = Flash::new(p.FLASH); + let flash = Flash::<_, flash::Blocking, FLASH_SIZE>::new(p.FLASH); let flash = Mutex::new(RefCell::new(flash)); let config = FirmwareUpdaterConfig::from_linkerfile_blocking(&flash); diff --git a/examples/nrf-rtos-trace/Cargo.toml b/examples/nrf-rtos-trace/Cargo.toml index 30b67b7b..068474e7 100644 --- a/examples/nrf-rtos-trace/Cargo.toml +++ b/examples/nrf-rtos-trace/Cargo.toml @@ -34,3 +34,6 @@ log = { version = "0.4.17", optional = true } [[bin]] name = "rtos_trace" required-features = ["nightly"] + +[profile.release] +debug = 2 diff --git a/examples/nrf52840-rtic/Cargo.toml b/examples/nrf52840-rtic/Cargo.toml index ded3b7db..715f1ecf 100644 --- a/examples/nrf52840-rtic/Cargo.toml +++ b/examples/nrf52840-rtic/Cargo.toml @@ -19,3 +19,6 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing cortex-m-rt = "0.7.0" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } + +[profile.release] +debug = 2 diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index 9b41ec5a..780aaeac 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -57,5 +57,5 @@ embedded-hal-async = { version = "0.2.0-alpha.2", optional = true } num-integer = { version = "0.1.45", default-features = false } microfft = "0.5.0" -[patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } +[profile.release] +debug = 2 diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml index f1d45f33..b0e51dcf 100644 --- a/examples/nrf5340/Cargo.toml +++ b/examples/nrf5340/Cargo.toml @@ -53,3 +53,6 @@ rand = { version = "0.8.4", default-features = false } embedded-storage = "0.3.0" usbd-hid = "0.6.0" serde = { version = "1.0.136", default-features = false } + +[profile.release] +debug = 2 diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml index c812cb3e..8c61dc5e 100644 --- a/examples/rp/Cargo.toml +++ b/examples/rp/Cargo.toml @@ -53,7 +53,4 @@ pio = "0.2.1" rand = { version = "0.8.5", default-features = false } [profile.release] -debug = true - -[patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } +debug = 2 diff --git a/examples/rp/src/bin/flash.rs b/examples/rp/src/bin/flash.rs index 4c4982ac..88bb931d 100644 --- a/examples/rp/src/bin/flash.rs +++ b/examples/rp/src/bin/flash.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; +use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE}; use embassy_rp::peripherals::FLASH; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) { // https://github.com/knurling-rs/defmt/pull/683 Timer::after(Duration::from_millis(10)).await; - let mut flash = embassy_rp::flash::Flash::<_, FLASH_SIZE>::new(p.FLASH); + let mut flash = embassy_rp::flash::Flash::<_, Async, FLASH_SIZE>::new(p.FLASH, p.DMA_CH0); // Get JEDEC id let jedec = flash.jedec_id().unwrap(); @@ -40,10 +40,12 @@ async fn main(_spawner: Spawner) { multiwrite_bytes(&mut flash, ERASE_SIZE as u32); + background_read(&mut flash, (ERASE_SIZE * 2) as u32).await; + loop {} } -fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { +fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { info!(">>>> [multiwrite_bytes]"); let mut read_buf = [0u8; ERASE_SIZE]; defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut read_buf)); @@ -71,7 +73,7 @@ fn multiwrite_bytes(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, } } -fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE>, offset: u32) { +fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { info!(">>>> [erase_write_sector]"); let mut buf = [0u8; ERASE_SIZE]; defmt::unwrap!(flash.read(ADDR_OFFSET + offset, &mut buf)); @@ -99,3 +101,35 @@ fn erase_write_sector(flash: &mut embassy_rp::flash::Flash<'_, FLASH, FLASH_SIZE defmt::panic!("unexpected"); } } + +async fn background_read(flash: &mut embassy_rp::flash::Flash<'_, FLASH, Async, FLASH_SIZE>, offset: u32) { + info!(">>>> [background_read]"); + + let mut buf = [0u32; 8]; + defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; + + info!("Addr of flash block is {:x}", ADDR_OFFSET + offset + FLASH_BASE as u32); + info!("Contents start with {=u32:x}", buf[0]); + + defmt::unwrap!(flash.erase(ADDR_OFFSET + offset, ADDR_OFFSET + offset + ERASE_SIZE as u32)); + + defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; + info!("Contents after erase starts with {=u32:x}", buf[0]); + if buf.iter().any(|x| *x != 0xFFFFFFFF) { + defmt::panic!("unexpected"); + } + + for b in buf.iter_mut() { + *b = 0xDABA1234; + } + + defmt::unwrap!(flash.write(ADDR_OFFSET + offset, unsafe { + core::slice::from_raw_parts(buf.as_ptr() as *const u8, buf.len() * 4) + })); + + defmt::unwrap!(flash.background_read(ADDR_OFFSET + offset, &mut buf)).await; + info!("Contents after write starts with {=u32:x}", buf[0]); + if buf.iter().any(|x| *x != 0xDABA1234) { + defmt::panic!("unexpected"); + } +} diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index c001d644..a6d6144b 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs @@ -8,7 +8,6 @@ use embassy_executor::Spawner; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; -use embassy_rp::relocate::RelocatedProgram; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; use {defmt_rtt as _, panic_probe as _}; @@ -29,9 +28,8 @@ fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, ".wrap", ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&pio.load_program(&relocated), &[]); + cfg.use_program(&pio.load_program(&prg.program), &[]); let out_pin = pio.make_pio_pin(pin); cfg.set_out_pins(&[&out_pin]); cfg.set_set_pins(&[&out_pin]); @@ -65,9 +63,8 @@ fn setup_pio_task_sm1<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, ".wrap", ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&pio.load_program(&relocated), &[]); + cfg.use_program(&pio.load_program(&prg.program), &[]); cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); cfg.shift_in.auto_fill = true; cfg.shift_in.direction = ShiftDirection::Right; @@ -96,9 +93,8 @@ fn setup_pio_task_sm2<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, "irq 3 [15]", ".wrap", ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&pio.load_program(&relocated), &[]); + cfg.use_program(&pio.load_program(&prg.program), &[]); cfg.clock_divider = (U56F8!(125_000_000) / 2000).to_fixed(); sm.set_config(&cfg); } diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 9ab72e1f..86e5017a 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs @@ -8,7 +8,6 @@ use embassy_executor::Spawner; use embassy_futures::join::join; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; -use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{bind_interrupts, Peripheral}; use fixed::traits::ToFixed; use fixed_macro::types::U56F8; @@ -46,9 +45,8 @@ async fn main(_spawner: Spawner) { ".wrap", ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&common.load_program(&relocated), &[]); + cfg.use_program(&common.load_program(&prg.program), &[]); cfg.clock_divider = (U56F8!(125_000_000) / U56F8!(10_000)).to_fixed(); cfg.shift_in = ShiftConfig { auto_fill: true, diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index 8aedd24b..d80c5c24 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs @@ -14,7 +14,6 @@ use embassy_rp::pio::{ Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, }; use embassy_rp::pwm::{self, Pwm}; -use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Instant, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -127,9 +126,8 @@ impl<'l> HD44780<'l> { sm0.set_pin_dirs(Direction::Out, &[&rs, &rw, &e, &db4, &db5, &db6, &db7]); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&common.load_program(&relocated), &[&e]); + cfg.use_program(&common.load_program(&prg.program), &[&e]); cfg.clock_divider = 125u8.into(); cfg.set_out_pins(&[&db4, &db5, &db6, &db7]); cfg.shift_out = ShiftConfig { @@ -201,9 +199,8 @@ impl<'l> HD44780<'l> { "# ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&common.load_program(&relocated), &[&e]); + cfg.use_program(&common.load_program(&prg.program), &[&e]); cfg.clock_divider = 8u8.into(); // ~64ns/insn cfg.set_jmp_pin(&db7); cfg.set_set_pins(&[&rs, &rw]); diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs new file mode 100644 index 00000000..4c382c2e --- /dev/null +++ b/examples/rp/src/bin/pio_uart.rs @@ -0,0 +1,394 @@ +//! This example shows how to use the PIO module in the RP2040 chip to implement a duplex UART. +//! The PIO module is a very powerful peripheral that can be used to implement many different +//! protocols. It is a very flexible state machine that can be programmed to do almost anything. +//! +//! This example opens up a USB device that implements a CDC ACM serial port. It then uses the +//! PIO module to implement a UART that is connected to the USB serial port. This allows you to +//! communicate with a device connected to the RP2040 over USB serial. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#![feature(async_fn_in_trait)] + +use defmt::{info, panic, trace}; +use embassy_executor::Spawner; +use embassy_futures::join::{join, join3}; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::{PIO0, USB}; +use embassy_rp::pio::InterruptHandler as PioInterruptHandler; +use embassy_rp::usb::{Driver, Instance, InterruptHandler}; +use embassy_sync::blocking_mutex::raw::NoopRawMutex; +use embassy_sync::pipe::Pipe; +use embassy_usb::class::cdc_acm::{CdcAcmClass, Receiver, Sender, State}; +use embassy_usb::driver::EndpointError; +use embassy_usb::{Builder, Config}; +use embedded_io::asynch::{Read, Write}; +use {defmt_rtt as _, panic_probe as _}; + +use crate::uart::PioUart; +use crate::uart_rx::PioUartRx; +use crate::uart_tx::PioUartTx; + +bind_interrupts!(struct Irqs { + USBCTRL_IRQ => InterruptHandler; + PIO0_IRQ_0 => PioInterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello there!"); + + let p = embassy_rp::init(Default::default()); + + // Create the driver, from the HAL. + let driver = Driver::new(p.USB, Irqs); + + // Create embassy-usb Config + let mut config = Config::new(0xc0de, 0xcafe); + config.manufacturer = Some("Embassy"); + config.product = Some("PIO UART example"); + config.serial_number = Some("12345678"); + config.max_power = 100; + config.max_packet_size_0 = 64; + + // Required for windows compatibility. + // https://developer.nordicsemi.com/nRF_Connect_SDK/doc/1.9.1/kconfig/CONFIG_CDC_ACM_IAD.html#help + config.device_class = 0xEF; + config.device_sub_class = 0x02; + config.device_protocol = 0x01; + config.composite_with_iads = true; + + // Create embassy-usb DeviceBuilder using the driver and config. + // It needs some buffers for building the descriptors. + let mut device_descriptor = [0; 256]; + let mut config_descriptor = [0; 256]; + let mut bos_descriptor = [0; 256]; + let mut control_buf = [0; 64]; + + let mut state = State::new(); + + let mut builder = Builder::new( + driver, + config, + &mut device_descriptor, + &mut config_descriptor, + &mut bos_descriptor, + &mut control_buf, + ); + + // Create classes on the builder. + let class = CdcAcmClass::new(&mut builder, &mut state, 64); + + // Build the builder. + let mut usb = builder.build(); + + // Run the USB device. + let usb_fut = usb.run(); + + // PIO UART setup + let uart = PioUart::new(9600, p.PIO0, p.PIN_4, p.PIN_5); + let (mut uart_tx, mut uart_rx) = uart.split(); + + // Pipe setup + let usb_pipe: Pipe = Pipe::new(); + let mut usb_pipe_writer = usb_pipe.writer(); + let mut usb_pipe_reader = usb_pipe.reader(); + + let uart_pipe: Pipe = Pipe::new(); + let mut uart_pipe_writer = uart_pipe.writer(); + let mut uart_pipe_reader = uart_pipe.reader(); + + let (mut usb_tx, mut usb_rx) = class.split(); + + // Read + write from USB + let usb_future = async { + loop { + info!("Wait for USB connection"); + usb_rx.wait_connection().await; + info!("Connected"); + let _ = join( + usb_read(&mut usb_rx, &mut uart_pipe_writer), + usb_write(&mut usb_tx, &mut usb_pipe_reader), + ) + .await; + info!("Disconnected"); + } + }; + + // Read + write from UART + let uart_future = join( + uart_read(&mut uart_rx, &mut usb_pipe_writer), + uart_write(&mut uart_tx, &mut uart_pipe_reader), + ); + + // Run everything concurrently. + // If we had made everything `'static` above instead, we could do this using separate tasks instead. + join3(usb_fut, usb_future, uart_future).await; +} + +struct Disconnected {} + +impl From for Disconnected { + fn from(val: EndpointError) -> Self { + match val { + EndpointError::BufferOverflow => panic!("Buffer overflow"), + EndpointError::Disabled => Disconnected {}, + } + } +} + +/// Read from the USB and write it to the UART TX pipe +async fn usb_read<'d, T: Instance + 'd>( + usb_rx: &mut Receiver<'d, Driver<'d, T>>, + uart_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>, +) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = usb_rx.read_packet(&mut buf).await?; + let data = &buf[..n]; + trace!("USB IN: {:x}", data); + uart_pipe_writer.write(data).await; + } +} + +/// Read from the USB TX pipe and write it to the USB +async fn usb_write<'d, T: Instance + 'd>( + usb_tx: &mut Sender<'d, Driver<'d, T>>, + usb_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>, +) -> Result<(), Disconnected> { + let mut buf = [0; 64]; + loop { + let n = usb_pipe_reader.read(&mut buf).await; + let data = &buf[..n]; + trace!("USB OUT: {:x}", data); + usb_tx.write_packet(&data).await?; + } +} + +/// Read from the UART and write it to the USB TX pipe +async fn uart_read( + uart_rx: &mut PioUartRx<'_>, + usb_pipe_writer: &mut embassy_sync::pipe::Writer<'_, NoopRawMutex, 20>, +) -> ! { + let mut buf = [0; 64]; + loop { + let n = uart_rx.read(&mut buf).await.expect("UART read error"); + if n == 0 { + continue; + } + let data = &buf[..n]; + trace!("UART IN: {:x}", buf); + usb_pipe_writer.write(data).await; + } +} + +/// Read from the UART TX pipe and write it to the UART +async fn uart_write( + uart_tx: &mut PioUartTx<'_>, + uart_pipe_reader: &mut embassy_sync::pipe::Reader<'_, NoopRawMutex, 20>, +) -> ! { + let mut buf = [0; 64]; + loop { + let n = uart_pipe_reader.read(&mut buf).await; + let data = &buf[..n]; + trace!("UART OUT: {:x}", data); + let _ = uart_tx.write(&data).await; + } +} + +mod uart { + use embassy_rp::peripherals::PIO0; + use embassy_rp::pio::{Pio, PioPin}; + use embassy_rp::Peripheral; + + use crate::uart_rx::PioUartRx; + use crate::uart_tx::PioUartTx; + use crate::Irqs; + + pub struct PioUart<'a> { + tx: PioUartTx<'a>, + rx: PioUartRx<'a>, + } + + impl<'a> PioUart<'a> { + pub fn new( + baud: u64, + pio: impl Peripheral

+ 'a, + tx_pin: impl PioPin, + rx_pin: impl PioPin, + ) -> PioUart<'a> { + let Pio { + mut common, sm0, sm1, .. + } = Pio::new(pio, Irqs); + + let tx = PioUartTx::new(&mut common, sm0, tx_pin, baud); + let rx = PioUartRx::new(&mut common, sm1, rx_pin, baud); + + PioUart { tx, rx } + } + + pub fn split(self) -> (PioUartTx<'a>, PioUartRx<'a>) { + (self.tx, self.rx) + } + } +} + +mod uart_tx { + use core::convert::Infallible; + + use embassy_rp::gpio::Level; + use embassy_rp::peripherals::PIO0; + use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; + use embedded_io::asynch::Write; + use embedded_io::Io; + use fixed::traits::ToFixed; + use fixed_macro::types::U56F8; + + pub struct PioUartTx<'a> { + sm_tx: StateMachine<'a, PIO0, 0>, + } + + impl<'a> PioUartTx<'a> { + pub fn new( + common: &mut Common<'a, PIO0>, + mut sm_tx: StateMachine<'a, PIO0, 0>, + tx_pin: impl PioPin, + baud: u64, + ) -> Self { + let prg = pio_proc::pio_asm!( + r#" + .side_set 1 opt + + ; An 8n1 UART transmit program. + ; OUT pin 0 and side-set pin 0 are both mapped to UART TX pin. + + pull side 1 [7] ; Assert stop bit, or stall with line in idle state + set x, 7 side 0 [7] ; Preload bit counter, assert start bit for 8 clocks + bitloop: ; This loop will run 8 times (8n1 UART) + out pins, 1 ; Shift 1 bit from OSR to the first OUT pin + jmp x-- bitloop [6] ; Each loop iteration is 8 cycles. + "# + ); + let tx_pin = common.make_pio_pin(tx_pin); + sm_tx.set_pins(Level::High, &[&tx_pin]); + sm_tx.set_pin_dirs(Direction::Out, &[&tx_pin]); + + let mut cfg = Config::default(); + + cfg.set_out_pins(&[&tx_pin]); + cfg.use_program(&common.load_program(&prg.program), &[&tx_pin]); + cfg.shift_out.auto_fill = false; + cfg.shift_out.direction = ShiftDirection::Right; + cfg.fifo_join = FifoJoin::TxOnly; + cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed(); + sm_tx.set_config(&cfg); + sm_tx.set_enable(true); + + Self { sm_tx } + } + + pub async fn write_u8(&mut self, data: u8) { + self.sm_tx.tx().wait_push(data as u32).await; + } + } + + impl Io for PioUartTx<'_> { + type Error = Infallible; + } + + impl Write for PioUartTx<'_> { + async fn write(&mut self, buf: &[u8]) -> Result { + for byte in buf { + self.write_u8(*byte).await; + } + Ok(buf.len()) + } + } +} + +mod uart_rx { + use core::convert::Infallible; + + use embassy_rp::gpio::Level; + use embassy_rp::peripherals::PIO0; + use embassy_rp::pio::{Common, Config, Direction, FifoJoin, PioPin, ShiftDirection, StateMachine}; + use embedded_io::asynch::Read; + use embedded_io::Io; + use fixed::traits::ToFixed; + use fixed_macro::types::U56F8; + + pub struct PioUartRx<'a> { + sm_rx: StateMachine<'a, PIO0, 1>, + } + + impl<'a> PioUartRx<'a> { + pub fn new( + common: &mut Common<'a, PIO0>, + mut sm_rx: StateMachine<'a, PIO0, 1>, + rx_pin: impl PioPin, + baud: u64, + ) -> Self { + let prg = pio_proc::pio_asm!( + r#" + ; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and + ; break conditions more gracefully. + ; IN pin 0 and JMP pin are both mapped to the GPIO used as UART RX. + + start: + wait 0 pin 0 ; Stall until start bit is asserted + set x, 7 [10] ; Preload bit counter, then delay until halfway through + rx_bitloop: ; the first data bit (12 cycles incl wait, set). + in pins, 1 ; Shift data bit into ISR + jmp x-- rx_bitloop [6] ; Loop 8 times, each loop iteration is 8 cycles + jmp pin good_rx_stop ; Check stop bit (should be high) + + irq 4 rel ; Either a framing error or a break. Set a sticky flag, + wait 1 pin 0 ; and wait for line to return to idle state. + jmp start ; Don't push data if we didn't see good framing. + + good_rx_stop: ; No delay before returning to start; a little slack is + in null 24 + push ; important in case the TX clock is slightly too fast. + "# + ); + let mut cfg = Config::default(); + cfg.use_program(&common.load_program(&prg.program), &[]); + + let rx_pin = common.make_pio_pin(rx_pin); + sm_rx.set_pins(Level::High, &[&rx_pin]); + cfg.set_in_pins(&[&rx_pin]); + cfg.set_jmp_pin(&rx_pin); + sm_rx.set_pin_dirs(Direction::In, &[&rx_pin]); + + cfg.clock_divider = (U56F8!(125_000_000) / (8 * baud)).to_fixed(); + cfg.shift_in.auto_fill = false; + cfg.shift_in.direction = ShiftDirection::Right; + cfg.shift_in.threshold = 32; + cfg.fifo_join = FifoJoin::RxOnly; + sm_rx.set_config(&cfg); + sm_rx.set_enable(true); + + Self { sm_rx } + } + + pub async fn read_u8(&mut self) -> u8 { + self.sm_rx.rx().wait_pull().await as u8 + } + } + + impl Io for PioUartRx<'_> { + type Error = Infallible; + } + + impl Read for PioUartRx<'_> { + async fn read(&mut self, buf: &mut [u8]) -> Result { + let mut i = 0; + while i < buf.len() { + buf[i] = self.read_u8().await; + i += 1; + } + Ok(i) + } + } +} diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 3de2bd48..bc87016e 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs @@ -12,7 +12,6 @@ use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{ Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, }; -use embassy_rp::relocate::RelocatedProgram; use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; use embassy_time::{Duration, Timer}; use fixed::types::U24F8; @@ -73,8 +72,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> Ws2812<'d, P, S, N> { cfg.set_out_pins(&[&out_pin]); cfg.set_set_pins(&[&out_pin]); - let relocated = RelocatedProgram::new(&prg); - cfg.use_program(&pio.load_program(&relocated), &[&out_pin]); + cfg.use_program(&pio.load_program(&prg), &[&out_pin]); // Clock config, measured in kHz to avoid overflows // TODO CLOCK_FREQ should come from embassy_rp diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml index 92933ab5..42adede1 100644 --- a/examples/std/Cargo.toml +++ b/examples/std/Cargo.toml @@ -23,3 +23,6 @@ clap = { version = "3.0.0-beta.5", features = ["derive"] } rand_core = { version = "0.6.3", features = ["std"] } heapless = { version = "0.7.5", default-features = false } static_cell = { version = "1.1", features = ["nightly"]} + +[profile.release] +debug = 2 diff --git a/examples/stm32c0/Cargo.toml b/examples/stm32c0/Cargo.toml index e74c5357..8534921a 100644 --- a/examples/stm32c0/Cargo.toml +++ b/examples/stm32c0/Cargo.toml @@ -20,3 +20,6 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } + +[profile.release] +debug = 2 diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml index 620a139a..46b6db45 100644 --- a/examples/stm32f0/Cargo.toml +++ b/examples/stm32f0/Cargo.toml @@ -18,3 +18,6 @@ embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["de embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } static_cell = { version = "1.1", features = ["nightly"]} + +[profile.release] +debug = 2 diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 8450c541..5d32992c 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -26,3 +26,6 @@ nb = "1.0.0" [profile.dev] opt-level = "s" + +[profile.release] +debug = 2 diff --git a/examples/stm32f2/Cargo.toml b/examples/stm32f2/Cargo.toml index 147e2ecb..9857fb63 100644 --- a/examples/stm32f2/Cargo.toml +++ b/examples/stm32f2/Cargo.toml @@ -21,3 +21,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" + +[profile.release] +debug = 2 diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml index 6ac5d57e..bd594d16 100644 --- a/examples/stm32f3/Cargo.toml +++ b/examples/stm32f3/Cargo.toml @@ -25,3 +25,6 @@ heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" embedded-storage = "0.3.0" static_cell = { version = "1.1", features = ["nightly"]} + +[profile.release] +debug = 2 diff --git a/examples/stm32f3/src/bin/spi_dma.rs b/examples/stm32f3/src/bin/spi_dma.rs index 95b2b686..a27c1d54 100644 --- a/examples/stm32f3/src/bin/spi_dma.rs +++ b/examples/stm32f3/src/bin/spi_dma.rs @@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut spi = Spi::new( - p.SPI1, - p.PB3, - p.PB5, - p.PB4, - p.DMA1_CH3, - p.DMA1_CH2, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI1, p.PB3, p.PB5, p.PB4, p.DMA1_CH3, p.DMA1_CH2, spi_config); for n in 0u32.. { let mut write: String<128> = String::new(); diff --git a/examples/stm32f334/.cargo/config.toml b/examples/stm32f334/.cargo/config.toml new file mode 100644 index 00000000..caf947be --- /dev/null +++ b/examples/stm32f334/.cargo/config.toml @@ -0,0 +1,9 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +# replace STM32F429ZITx with your chip as listed in `probe-rs-cli chip list` +runner = "probe-run --chip STM32F334R8" + +[build] +target = "thumbv7em-none-eabihf" + +[env] +DEFMT_LOG = "trace" diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml new file mode 100644 index 00000000..6410891a --- /dev/null +++ b/examples/stm32f334/Cargo.toml @@ -0,0 +1,26 @@ +[package] +edition = "2021" +name = "embassy-stm32f3-examples" +version = "0.1.0" +license = "MIT OR Apache-2.0" + +[dependencies] +embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } +embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } +embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f334r8", "unstable-pac", "memory-x", "time-driver-any", "exti"] } +embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } +embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } + +defmt = "0.3" +defmt-rtt = "0.4" + +cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } +cortex-m-rt = "0.7.0" +embedded-hal = "0.2.6" +panic-probe = { version = "0.3", features = ["print-defmt"] } +futures = { version = "0.3.17", default-features = false, features = ["async-await"] } +heapless = { version = "0.7.5", default-features = false } +nb = "1.0.0" +embedded-storage = "0.3.0" +static_cell = { version = "1.1", features = ["nightly"]} diff --git a/examples/stm32f334/build.rs b/examples/stm32f334/build.rs new file mode 100644 index 00000000..8cd32d7e --- /dev/null +++ b/examples/stm32f334/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/stm32f334/src/bin/button.rs b/examples/stm32f334/src/bin/button.rs new file mode 100644 index 00000000..599c0f27 --- /dev/null +++ b/examples/stm32f334/src/bin/button.rs @@ -0,0 +1,27 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::gpio::{Level, Output, Speed}; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + info!("Hello World!"); + + let p = embassy_stm32::init(Default::default()); + + let mut out1 = Output::new(p.PA8, Level::Low, Speed::High); + + out1.set_high(); + Timer::after(Duration::from_millis(500)).await; + out1.set_low(); + + Timer::after(Duration::from_millis(500)).await; + info!("end program"); + + cortex_m::asm::bkpt(); +} diff --git a/examples/stm32f334/src/bin/hello.rs b/examples/stm32f334/src/bin/hello.rs new file mode 100644 index 00000000..65773210 --- /dev/null +++ b/examples/stm32f334/src/bin/hello.rs @@ -0,0 +1,23 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::info; +use embassy_executor::Spawner; +use embassy_stm32::time::Hertz; +use embassy_stm32::Config; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) -> ! { + let mut config = Config::default(); + config.rcc.hse = Some(Hertz(8_000_000)); + config.rcc.sysclk = Some(Hertz(16_000_000)); + let _p = embassy_stm32::init(config); + + loop { + info!("Hello World!"); + Timer::after(Duration::from_secs(1)).await; + } +} diff --git a/examples/stm32f334/src/bin/pwm.rs b/examples/stm32f334/src/bin/pwm.rs new file mode 100644 index 00000000..2660b10c --- /dev/null +++ b/examples/stm32f334/src/bin/pwm.rs @@ -0,0 +1,71 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::hrtim::*; +use embassy_stm32::time::{khz, mhz}; +use embassy_stm32::Config; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config: Config = Default::default(); + config.rcc.sysclk = Some(mhz(64)); + config.rcc.hclk = Some(mhz(64)); + config.rcc.pclk1 = Some(mhz(32)); + config.rcc.pclk2 = Some(mhz(64)); + + let p = embassy_stm32::init(config); + info!("Hello World!"); + + let ch1 = PwmPin::new_cha(p.PA8); + let ch1n = ComplementaryPwmPin::new_cha(p.PA9); + let pwm = AdvancedPwm::new( + p.HRTIM1, + Some(ch1), + Some(ch1n), + None, + None, + None, + None, + None, + None, + None, + None, + ); + + info!("pwm constructed"); + + let mut buck_converter = BridgeConverter::new(pwm.ch_a, khz(5)); + + // embassy_stm32::pac::HRTIM1 + // .tim(0) + // .setr(0) + // .modify(|w| w.set_sst(Activeeffect::SETACTIVE)); + // + // Timer::after(Duration::from_millis(500)).await; + // + // embassy_stm32::pac::HRTIM1 + // .tim(0) + // .rstr(0) + // .modify(|w| w.set_srt(Inactiveeffect::SETINACTIVE)); + + let max_duty = buck_converter.get_max_compare_value(); + + info!("max compare value: {}", max_duty); + + buck_converter.set_dead_time(max_duty / 20); + buck_converter.set_primary_duty(max_duty / 2); + buck_converter.set_secondary_duty(3 * max_duty / 4); + + buck_converter.start(); + + Timer::after(Duration::from_millis(500)).await; + + info!("end program"); + + cortex_m::asm::bkpt(); +} diff --git a/examples/stm32f4/src/bin/eth.rs b/examples/stm32f4/src/bin/eth.rs index d0b16439..49601668 100644 --- a/examples/stm32f4/src/bin/eth.rs +++ b/examples/stm32f4/src/bin/eth.rs @@ -11,13 +11,15 @@ use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::time::mhz; -use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; + bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; + HASH_RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; @@ -36,7 +38,7 @@ async fn main(spawner: Spawner) -> ! { info!("Hello World!"); // Generate random seed. - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; let _ = rng.async_fill_bytes(&mut seed).await; let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32f4/src/bin/pwm.rs b/examples/stm32f4/src/bin/pwm.rs index 7c590205..1013a844 100644 --- a/examples/stm32f4/src/bin/pwm.rs +++ b/examples/stm32f4/src/bin/pwm.rs @@ -4,9 +4,10 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; -use embassy_stm32::pwm::Channel; +use embassy_stm32::gpio::OutputType; use embassy_stm32::time::khz; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::timer::Channel; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -15,7 +16,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1 = PwmPin::new_ch1(p.PE9); + let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10)); let max = pwm.get_max_duty(); pwm.enable(Channel::Ch1); diff --git a/examples/stm32f4/src/bin/pwm_complementary.rs b/examples/stm32f4/src/bin/pwm_complementary.rs index a8a68ed6..83a3c753 100644 --- a/examples/stm32f4/src/bin/pwm_complementary.rs +++ b/examples/stm32f4/src/bin/pwm_complementary.rs @@ -4,10 +4,11 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::pwm::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; -use embassy_stm32::pwm::simple_pwm::PwmPin; -use embassy_stm32::pwm::Channel; +use embassy_stm32::gpio::OutputType; use embassy_stm32::time::khz; +use embassy_stm32::timer::complementary_pwm::{ComplementaryPwm, ComplementaryPwmPin}; +use embassy_stm32::timer::simple_pwm::PwmPin; +use embassy_stm32::timer::Channel; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -16,8 +17,8 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1 = PwmPin::new_ch1(p.PE9); - let ch1n = ComplementaryPwmPin::new_ch1(p.PA7); + let ch1 = PwmPin::new_ch1(p.PE9, OutputType::PushPull); + let ch1n = ComplementaryPwmPin::new_ch1(p.PA7, OutputType::PushPull); let mut pwm = ComplementaryPwm::new( p.TIM1, Some(ch1), diff --git a/examples/stm32f4/src/bin/spi.rs b/examples/stm32f4/src/bin/spi.rs index 05b48f47..0919e987 100644 --- a/examples/stm32f4/src/bin/spi.rs +++ b/examples/stm32f4/src/bin/spi.rs @@ -16,16 +16,10 @@ fn main() -> ! { let p = embassy_stm32::init(Default::default()); - let mut spi = Spi::new( - p.SPI3, - p.PC10, - p.PC12, - p.PC11, - NoDma, - NoDma, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config); let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); diff --git a/examples/stm32f4/src/bin/spi_dma.rs b/examples/stm32f4/src/bin/spi_dma.rs index 3d2a1a1a..f291f7db 100644 --- a/examples/stm32f4/src/bin/spi_dma.rs +++ b/examples/stm32f4/src/bin/spi_dma.rs @@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut spi = Spi::new( - p.SPI1, - p.PB3, - p.PB5, - p.PB4, - p.DMA2_CH3, - p.DMA2_CH2, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI1, p.PB3, p.PB5, p.PB4, p.DMA2_CH3, p.DMA2_CH2, spi_config); for n in 0u32.. { let mut write: String<128> = String::new(); diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index b1f01417..740d3018 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -6,7 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Stack, StackResources}; -use embassy_stm32::rng::Rng; +use embassy_stm32::rng::{self, Rng}; use embassy_stm32::time::mhz; use embassy_stm32::usb_otg::Driver; use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; @@ -38,6 +38,7 @@ async fn net_task(stack: &'static Stack>) -> ! { bind_interrupts!(struct Irqs { OTG_FS => usb_otg::InterruptHandler; + HASH_RNG => rng::InterruptHandler; }); #[embassy_executor::main] @@ -104,7 +105,7 @@ async fn main(spawner: Spawner) { //}); // Generate random seed - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; unwrap!(rng.async_fill_bytes(&mut seed).await); let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml index bbc99fee..a379cbbe 100644 --- a/examples/stm32f7/Cargo.toml +++ b/examples/stm32f7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32f767zi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "unstable-pac", "time-driver-any", "exti"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f767zi", "memory-x", "unstable-pac", "time-driver-any", "exti"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } @@ -28,3 +28,6 @@ rand_core = "0.6.3" critical-section = "1.1" embedded-storage = "0.3.0" static_cell = { version = "1.1", features = ["nightly"]} + +[profile.release] +debug = 2 diff --git a/examples/stm32f7/build.rs b/examples/stm32f7/build.rs index 2b5d412a..8cd32d7e 100644 --- a/examples/stm32f7/build.rs +++ b/examples/stm32f7/build.rs @@ -1,43 +1,5 @@ -//! adapted from https://github.com/stm32-rs/stm32f7xx-hal/blob/master/build.rs -use std::fs::File; -use std::io::prelude::*; -use std::path::PathBuf; -use std::{env, io}; - -#[derive(Debug)] -enum Error { - Env(env::VarError), - Io(io::Error), -} - -impl From for Error { - fn from(error: env::VarError) -> Self { - Self::Env(error) - } -} - -impl From for Error { - fn from(error: io::Error) -> Self { - Self::Io(error) - } -} - -fn main() -> Result<(), Error> { - println!("cargo:rerun-if-changed=build.rs"); - println!("cargo:rerun-if-changed=memory.x"); - - let out_dir = env::var("OUT_DIR")?; - let out_dir = PathBuf::from(out_dir); - - let memory_x = include_bytes!("memory.x").as_ref(); - File::create(out_dir.join("memory.x"))?.write_all(memory_x)?; - - // Tell Cargo where to find the file. - println!("cargo:rustc-link-search={}", out_dir.display()); - +fn main() { println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); - - Ok(()) } diff --git a/examples/stm32f7/memory.x b/examples/stm32f7/memory.x deleted file mode 100644 index 899f7a4b..00000000 --- a/examples/stm32f7/memory.x +++ /dev/null @@ -1,12 +0,0 @@ -/* For STM32F765,767,768,769,777,778,779 devices */ -MEMORY -{ - /* NOTE K = KiBi = 1024 bytes */ - FLASH : ORIGIN = 0x08000000, LENGTH = 2M - RAM : ORIGIN = 0x20000000, LENGTH = 368K + 16K -} - -/* This is where the call stack will be allocated. */ -/* The stack is of the full descending type. */ -/* NOTE Do NOT modify `_stack_start` unless you know what you are doing */ -_stack_start = ORIGIN(RAM) + LENGTH(RAM); diff --git a/examples/stm32f7/src/bin/eth.rs b/examples/stm32f7/src/bin/eth.rs index c6b2ba45..e5abf52b 100644 --- a/examples/stm32f7/src/bin/eth.rs +++ b/examples/stm32f7/src/bin/eth.rs @@ -11,14 +11,16 @@ use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::time::mhz; -use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; + bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; + RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; @@ -37,7 +39,7 @@ async fn main(spawner: Spawner) -> ! { info!("Hello World!"); // Generate random seed. - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; rng.fill_bytes(&mut seed); let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml index 4a14568a..b4dfe3c6 100644 --- a/examples/stm32g0/Cargo.toml +++ b/examples/stm32g0/Cargo.toml @@ -20,3 +20,6 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } + +[profile.release] +debug = 2 diff --git a/examples/stm32g0/src/bin/spi_neopixel.rs b/examples/stm32g0/src/bin/spi_neopixel.rs index 81fdd15c..ee7aaf33 100644 --- a/examples/stm32g0/src/bin/spi_neopixel.rs +++ b/examples/stm32g0/src/bin/spi_neopixel.rs @@ -76,7 +76,9 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Start test using spi as neopixel driver"); - let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, NoDma, Hertz(4_000_000), Config::default()); + let mut config = Config::default(); + config.frequency = Hertz(4_000_000); + let mut spi = Spi::new_txonly_nosck(p.SPI1, p.PB5, p.DMA1_CH3, NoDma, config); let mut neopixels = Ws2812::new(); diff --git a/examples/stm32g4/Cargo.toml b/examples/stm32g4/Cargo.toml index 935997a7..cf3e2ce9 100644 --- a/examples/stm32g4/Cargo.toml +++ b/examples/stm32g4/Cargo.toml @@ -10,7 +10,6 @@ embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [" embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } -embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } defmt = "0.3" @@ -22,3 +21,6 @@ embedded-hal = "0.2.6" panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } + +[profile.release] +debug = 2 diff --git a/examples/stm32g4/src/bin/pwm.rs b/examples/stm32g4/src/bin/pwm.rs index 8f7842ed..01e9cb47 100644 --- a/examples/stm32g4/src/bin/pwm.rs +++ b/examples/stm32g4/src/bin/pwm.rs @@ -4,9 +4,10 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; -use embassy_stm32::pwm::Channel; +use embassy_stm32::gpio::OutputType; use embassy_stm32::time::khz; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::timer::Channel; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -15,7 +16,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let ch1 = PwmPin::new_ch1(p.PC0); + let ch1 = PwmPin::new_ch1(p.PC0, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM1, Some(ch1), None, None, None, khz(10)); let max = pwm.get_max_duty(); pwm.enable(Channel::Ch1); diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index aebc795c..51d3bad1 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h563zi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } diff --git a/examples/stm32h5/memory.x b/examples/stm32h5/memory.x deleted file mode 100644 index 45606150..00000000 --- a/examples/stm32h5/memory.x +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - FLASH : ORIGIN = 0x08000000, LENGTH = 0x200000 - RAM : ORIGIN = 0x20000000, LENGTH = 0x50000 -} diff --git a/examples/stm32h5/src/bin/eth.rs b/examples/stm32h5/src/bin/eth.rs index 0bff85ed..2aa2ab62 100644 --- a/examples/stm32h5/src/bin/eth.rs +++ b/examples/stm32h5/src/bin/eth.rs @@ -12,14 +12,16 @@ use embassy_stm32::peripherals::ETH; use embassy_stm32::rcc::{AHBPrescaler, APBPrescaler, Hse, HseMode, Pll, PllSource, Sysclk, VoltageScale}; use embassy_stm32::rng::Rng; use embassy_stm32::time::Hertz; -use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; + bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; + RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; @@ -56,7 +58,7 @@ async fn main(spawner: Spawner) -> ! { info!("Hello World!"); // Generate random seed. - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; rng.fill_bytes(&mut seed); let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32h5/src/bin/rng.rs b/examples/stm32h5/src/bin/rng.rs index af9be0b6..7c8c50ec 100644 --- a/examples/stm32h5/src/bin/rng.rs +++ b/examples/stm32h5/src/bin/rng.rs @@ -5,14 +5,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rng::Rng; +use embassy_stm32::{bind_interrupts, peripherals, rng}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + RNG => rng::InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut buf = [0u8; 16]; unwrap!(rng.async_fill_bytes(&mut buf).await); diff --git a/examples/stm32h7/.cargo/config.toml b/examples/stm32h7/.cargo/config.toml index 5f680dbc..4160bf85 100644 --- a/examples/stm32h7/.cargo/config.toml +++ b/examples/stm32h7/.cargo/config.toml @@ -1,5 +1,5 @@ [target.thumbv7em-none-eabihf] -runner = 'probe-rs run --chip STM32H743ZITx' +runner = 'probe-rs run --chip STM32H7A3ZITxQ' [build] target = "thumbv7em-none-eabihf" # Cortex-M4F and Cortex-M7F (with FPU) diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 2d82c0d0..3c1232e6 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32h743bi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32h743bi", "time-driver-any", "exti", "memory-x", "unstable-pac", "unstable-traits"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "unstable-traits", "tick-hz-32_768"] } diff --git a/examples/stm32h7/memory.x b/examples/stm32h7/memory.x deleted file mode 100644 index 026b14b9..00000000 --- a/examples/stm32h7/memory.x +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - FLASH : ORIGIN = 0x8000000, LENGTH = 1024K - RAM : ORIGIN = 0x24000000, LENGTH = 384K -} diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs new file mode 100644 index 00000000..a9cb5d1e --- /dev/null +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -0,0 +1,140 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::dac::{DacChannel, ValueArray}; +use embassy_stm32::pac::timer::vals::{Mms, Opm}; +use embassy_stm32::peripherals::{TIM6, TIM7}; +use embassy_stm32::rcc::low_level::RccPeripheral; +use embassy_stm32::time::{mhz, Hertz}; +use embassy_stm32::timer::low_level::Basic16bitInstance; +use micromath::F32Ext; +use {defmt_rtt as _, panic_probe as _}; + +pub type Dac1Type = + embassy_stm32::dac::DacCh1<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH3>; + +pub type Dac2Type = + embassy_stm32::dac::DacCh2<'static, embassy_stm32::peripherals::DAC1, embassy_stm32::peripherals::DMA1_CH4>; + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let mut config = embassy_stm32::Config::default(); + config.rcc.sys_ck = Some(mhz(400)); + config.rcc.hclk = Some(mhz(100)); + config.rcc.pll1.q_ck = Some(mhz(100)); + + // Initialize the board and obtain a Peripherals instance + let p: embassy_stm32::Peripherals = embassy_stm32::init(config); + + // Obtain two independent channels (p.DAC1 can only be consumed once, though!) + let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); + + spawner.spawn(dac_task1(dac_ch1)).ok(); + spawner.spawn(dac_task2(dac_ch2)).ok(); +} + +#[embassy_executor::task] +async fn dac_task1(mut dac: Dac1Type) { + let data: &[u8; 256] = &calculate_array::<256>(); + + info!("TIM6 frequency is {}", TIM6::frequency()); + const FREQUENCY: Hertz = Hertz::hz(200); + + // Compute the reload value such that we obtain the FREQUENCY for the sine + let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; + + // Depends on your clock and on the specific chip used, you may need higher or lower values here + if reload < 10 { + error!("Reload value {} below threshold!", reload); + } + + dac.select_trigger(embassy_stm32::dac::Ch1Trigger::Tim6).unwrap(); + dac.enable_channel().unwrap(); + + TIM6::enable(); + TIM6::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM6::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM6::regs().cr1().modify(|w| { + w.set_opm(Opm::DISABLED); + w.set_cen(true); + }); + + debug!( + "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", + TIM6::frequency(), + FREQUENCY, + reload, + reload as u16, + data.len() + ); + + // Loop technically not necessary if DMA circular mode is enabled + loop { + info!("Loop DAC1"); + if let Err(e) = dac.write(ValueArray::Bit8(data), true).await { + error!("Could not write to dac: {}", e); + } + } +} + +#[embassy_executor::task] +async fn dac_task2(mut dac: Dac2Type) { + let data: &[u8; 256] = &calculate_array::<256>(); + + info!("TIM7 frequency is {}", TIM7::frequency()); + + const FREQUENCY: Hertz = Hertz::hz(600); + let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; + + if reload < 10 { + error!("Reload value {} below threshold!", reload); + } + + TIM7::enable(); + TIM7::regs().arr().modify(|w| w.set_arr(reload as u16 - 1)); + TIM7::regs().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + TIM7::regs().cr1().modify(|w| { + w.set_opm(Opm::DISABLED); + w.set_cen(true); + }); + + dac.select_trigger(embassy_stm32::dac::Ch2Trigger::Tim7).unwrap(); + + debug!( + "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", + TIM7::frequency(), + FREQUENCY, + reload, + reload as u16, + data.len() + ); + + if let Err(e) = dac.write(ValueArray::Bit8(data), true).await { + error!("Could not write to dac: {}", e); + } +} + +fn to_sine_wave(v: u8) -> u8 { + if v >= 128 { + // top half + let r = 3.14 * ((v - 128) as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } else { + // bottom half + let r = 3.14 + 3.14 * (v as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } +} + +fn calculate_array() -> [u8; N] { + let mut res = [0; N]; + let mut i = 0; + while i < N { + res[i] = to_sine_wave(i as u8); + i += 1; + } + res +} diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index cfafcaed..c93be9f0 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -11,14 +11,16 @@ use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::time::mhz; -use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use rand_core::RngCore; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; + bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; + RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; @@ -38,7 +40,7 @@ async fn main(spawner: Spawner) -> ! { info!("Hello World!"); // Generate random seed. - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; rng.fill_bytes(&mut seed); let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32h7/src/bin/eth_client.rs b/examples/stm32h7/src/bin/eth_client.rs index 4ed73757..78005e91 100644 --- a/examples/stm32h7/src/bin/eth_client.rs +++ b/examples/stm32h7/src/bin/eth_client.rs @@ -11,15 +11,17 @@ use embassy_stm32::eth::{Ethernet, PacketQueue}; use embassy_stm32::peripherals::ETH; use embassy_stm32::rng::Rng; use embassy_stm32::time::mhz; -use embassy_stm32::{bind_interrupts, eth, Config}; +use embassy_stm32::{bind_interrupts, eth, peripherals, rng, Config}; use embassy_time::{Duration, Timer}; use embedded_io::asynch::Write; use embedded_nal_async::{Ipv4Addr, SocketAddr, SocketAddrV4, TcpConnect}; use rand_core::RngCore; use static_cell::make_static; use {defmt_rtt as _, panic_probe as _}; + bind_interrupts!(struct Irqs { ETH => eth::InterruptHandler; + RNG => rng::InterruptHandler; }); type Device = Ethernet<'static, ETH, GenericSMI>; @@ -39,7 +41,7 @@ async fn main(spawner: Spawner) -> ! { info!("Hello World!"); // Generate random seed. - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut seed = [0; 8]; rng.fill_bytes(&mut seed); let seed = u64::from_le_bytes(seed); diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index d360df08..45b0872b 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -6,8 +6,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::gpio::low_level::AFType; use embassy_stm32::gpio::Speed; -use embassy_stm32::pwm::*; use embassy_stm32::time::{khz, mhz, Hertz}; +use embassy_stm32::timer::*; use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; diff --git a/examples/stm32h7/src/bin/pwm.rs b/examples/stm32h7/src/bin/pwm.rs index c5c0dd29..aa5ec1bc 100644 --- a/examples/stm32h7/src/bin/pwm.rs +++ b/examples/stm32h7/src/bin/pwm.rs @@ -4,9 +4,10 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::pwm::simple_pwm::{PwmPin, SimplePwm}; -use embassy_stm32::pwm::Channel; +use embassy_stm32::gpio::OutputType; use embassy_stm32::time::{khz, mhz}; +use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; +use embassy_stm32::timer::Channel; use embassy_stm32::Config; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -24,7 +25,7 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(config); info!("Hello World!"); - let ch1 = PwmPin::new_ch1(p.PA6); + let ch1 = PwmPin::new_ch1(p.PA6, OutputType::PushPull); let mut pwm = SimplePwm::new(p.TIM3, Some(ch1), None, None, None, khz(10)); let max = pwm.get_max_duty(); pwm.enable(Channel::Ch1); diff --git a/examples/stm32h7/src/bin/rng.rs b/examples/stm32h7/src/bin/rng.rs index af9be0b6..7c8c50ec 100644 --- a/examples/stm32h7/src/bin/rng.rs +++ b/examples/stm32h7/src/bin/rng.rs @@ -5,14 +5,19 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rng::Rng; +use embassy_stm32::{bind_interrupts, peripherals, rng}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + RNG => rng::InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut buf = [0u8; 16]; unwrap!(rng.async_fill_bytes(&mut buf).await); diff --git a/examples/stm32h7/src/bin/spi.rs b/examples/stm32h7/src/bin/spi.rs index 1f407f00..28bba2b8 100644 --- a/examples/stm32h7/src/bin/spi.rs +++ b/examples/stm32h7/src/bin/spi.rs @@ -43,16 +43,10 @@ fn main() -> ! { config.rcc.pll1.q_ck = Some(mhz(100)); let p = embassy_stm32::init(config); - let spi = spi::Spi::new( - p.SPI3, - p.PB3, - p.PB5, - p.PB4, - NoDma, - NoDma, - mhz(1), - spi::Config::default(), - ); + let mut spi_config = spi::Config::default(); + spi_config.frequency = mhz(1); + + let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, NoDma, NoDma, spi_config); let executor = EXECUTOR.init(Executor::new()); diff --git a/examples/stm32h7/src/bin/spi_dma.rs b/examples/stm32h7/src/bin/spi_dma.rs index 53004fc9..f6e30cfa 100644 --- a/examples/stm32h7/src/bin/spi_dma.rs +++ b/examples/stm32h7/src/bin/spi_dma.rs @@ -39,16 +39,10 @@ fn main() -> ! { config.rcc.pll1.q_ck = Some(mhz(100)); let p = embassy_stm32::init(config); - let spi = spi::Spi::new( - p.SPI3, - p.PB3, - p.PB5, - p.PB4, - p.DMA1_CH3, - p.DMA1_CH4, - mhz(1), - spi::Config::default(), - ); + let mut spi_config = spi::Config::default(); + spi_config.frequency = mhz(1); + + let spi = spi::Spi::new(p.SPI3, p.PB3, p.PB5, p.PB4, p.DMA1_CH3, p.DMA1_CH4, spi_config); let executor = EXECUTOR.init(Executor::new()); diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml index e6a5a4c1..c325751c 100644 --- a/examples/stm32l0/Cargo.toml +++ b/examples/stm32l0/Cargo.toml @@ -34,5 +34,5 @@ heapless = { version = "0.7.5", default-features = false } embedded-hal = "0.2.6" static_cell = "1.1" -[patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } +[profile.release] +debug = 2 diff --git a/examples/stm32l0/src/bin/lora_cad.rs b/examples/stm32l0/src/bin/lora_cad.rs index 588cea1e..7729b416 100644 --- a/examples/stm32l0/src/bin/lora_cad.rs +++ b/examples/stm32l0/src/bin/lora_cad.rs @@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) { config.rcc.enable_hsi48 = true; let p = embassy_stm32::init(config); + let mut spi_config = spi::Config::default(); + spi_config.frequency = khz(200); + // SPI for sx1276 - let spi = spi::Spi::new( - p.SPI1, - p.PB3, - p.PA7, - p.PA6, - p.DMA1_CH3, - p.DMA1_CH2, - khz(200), - spi::Config::default(), - ); + let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config); let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); diff --git a/examples/stm32l0/src/bin/lora_lorawan.rs b/examples/stm32l0/src/bin/lora_lorawan.rs index c397edd5..10608aeb 100644 --- a/examples/stm32l0/src/bin/lora_lorawan.rs +++ b/examples/stm32l0/src/bin/lora_lorawan.rs @@ -12,8 +12,8 @@ use embassy_lora::LoraTimer; use embassy_stm32::exti::{Channel, ExtiInput}; use embassy_stm32::gpio::{Input, Level, Output, Pin, Pull, Speed}; use embassy_stm32::rng::Rng; -use embassy_stm32::spi; use embassy_stm32::time::khz; +use embassy_stm32::{bind_interrupts, peripherals, rng, spi}; use embassy_time::Delay; use lora_phy::mod_params::*; use lora_phy::sx1276_7_8_9::SX1276_7_8_9; @@ -23,6 +23,10 @@ use lorawan_device::async_device::lora_radio::LoRaRadio; use lorawan_device::async_device::{region, Device, JoinMode}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + RNG_LPUART1 => rng::InterruptHandler; +}); + const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set this appropriately for the region #[embassy_executor::main] @@ -32,17 +36,11 @@ async fn main(_spawner: Spawner) { config.rcc.enable_hsi48 = true; let p = embassy_stm32::init(config); + let mut spi_config = spi::Config::default(); + spi_config.frequency = khz(200); + // SPI for sx1276 - let spi = spi::Spi::new( - p.SPI1, - p.PB3, - p.PA7, - p.PA6, - p.DMA1_CH3, - p.DMA1_CH2, - khz(200), - spi::Config::default(), - ); + let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config); let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); @@ -66,7 +64,7 @@ async fn main(_spawner: Spawner) { let radio = LoRaRadio::new(lora); let region: region::Configuration = region::Configuration::new(LORAWAN_REGION); - let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); + let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG, Irqs)); defmt::info!("Joining LoRaWAN network"); diff --git a/examples/stm32l0/src/bin/lora_p2p_receive.rs b/examples/stm32l0/src/bin/lora_p2p_receive.rs index bb750950..0f9f6095 100644 --- a/examples/stm32l0/src/bin/lora_p2p_receive.rs +++ b/examples/stm32l0/src/bin/lora_p2p_receive.rs @@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) { config.rcc.enable_hsi48 = true; let p = embassy_stm32::init(config); + let mut spi_config = spi::Config::default(); + spi_config.frequency = khz(200); + // SPI for sx1276 - let spi = spi::Spi::new( - p.SPI1, - p.PB3, - p.PA7, - p.PA6, - p.DMA1_CH3, - p.DMA1_CH2, - khz(200), - spi::Config::default(), - ); + let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config); let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); diff --git a/examples/stm32l0/src/bin/lora_p2p_send.rs b/examples/stm32l0/src/bin/lora_p2p_send.rs index e6fadc01..c85c3c2b 100644 --- a/examples/stm32l0/src/bin/lora_p2p_send.rs +++ b/examples/stm32l0/src/bin/lora_p2p_send.rs @@ -27,17 +27,11 @@ async fn main(_spawner: Spawner) { config.rcc.enable_hsi48 = true; let p = embassy_stm32::init(config); + let mut spi_config = spi::Config::default(); + spi_config.frequency = khz(200); + // SPI for sx1276 - let spi = spi::Spi::new( - p.SPI1, - p.PB3, - p.PA7, - p.PA6, - p.DMA1_CH3, - p.DMA1_CH2, - khz(200), - spi::Config::default(), - ); + let spi = spi::Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, p.DMA1_CH3, p.DMA1_CH2, spi_config); let nss = Output::new(p.PA15.degrade(), Level::High, Speed::Low); let reset = Output::new(p.PC0.degrade(), Level::High, Speed::Low); diff --git a/examples/stm32l0/src/bin/spi.rs b/examples/stm32l0/src/bin/spi.rs index 9b5b3e27..583e3d12 100644 --- a/examples/stm32l0/src/bin/spi.rs +++ b/examples/stm32l0/src/bin/spi.rs @@ -15,16 +15,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World, folks!"); - let mut spi = Spi::new( - p.SPI1, - p.PB3, - p.PA7, - p.PA6, - NoDma, - NoDma, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI1, p.PB3, p.PA7, p.PA6, NoDma, NoDma, spi_config); let mut cs = Output::new(p.PA15, Level::High, Speed::VeryHigh); diff --git a/examples/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml index dcca1cc3..329d44ca 100644 --- a/examples/stm32l1/Cargo.toml +++ b/examples/stm32l1/Cargo.toml @@ -20,3 +20,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } embedded-storage = "0.3.0" + +[profile.release] +debug = 2 diff --git a/examples/stm32l1/src/bin/spi.rs b/examples/stm32l1/src/bin/spi.rs index 0a532e8e..905b4d75 100644 --- a/examples/stm32l1/src/bin/spi.rs +++ b/examples/stm32l1/src/bin/spi.rs @@ -15,16 +15,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World, folks!"); - let mut spi = Spi::new( - p.SPI1, - p.PA5, - p.PA7, - p.PA6, - NoDma, - NoDma, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI1, p.PA5, p.PA7, p.PA6, NoDma, NoDma, spi_config); let mut cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml index 41c9869b..3b27d8e8 100644 --- a/examples/stm32l4/Cargo.toml +++ b/examples/stm32l4/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] # Change stm32l4s5vi to your chip name, if necessary. -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "time-driver-any", "exti", "unstable-traits", "chrono"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "unstable-pac", "stm32l4s5vi", "memory-x", "time-driver-any", "exti", "unstable-traits", "chrono"] } embassy-sync = { version = "0.2.0", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.2.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } embassy-time = { version = "0.1.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } @@ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false } chrono = { version = "^0.4", default-features = false } micromath = "2.0.0" + +[profile.release] +debug = 2 diff --git a/examples/stm32l4/build.rs b/examples/stm32l4/build.rs index 30691aa9..8cd32d7e 100644 --- a/examples/stm32l4/build.rs +++ b/examples/stm32l4/build.rs @@ -1,34 +1,4 @@ -//! This build script copies the `memory.x` file from the crate root into -//! a directory where the linker can always find it at build time. -//! For many projects this is optional, as the linker always searches the -//! project root directory -- wherever `Cargo.toml` is. However, if you -//! are using a workspace or have a more complicated build setup, this -//! build script becomes required. Additionally, by requesting that -//! Cargo re-run the build script whenever `memory.x` is changed, -//! updating `memory.x` ensures a rebuild of the application with the -//! new memory settings. - -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - fn main() { - // Put `memory.x` in our output directory and ensure it's - // on the linker search path. - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - File::create(out.join("memory.x")) - .unwrap() - .write_all(include_bytes!("memory.x")) - .unwrap(); - println!("cargo:rustc-link-search={}", out.display()); - - // By default, Cargo will re-run a build script whenever - // any file in the project changes. By specifying `memory.x` - // here, we ensure the build script is only re-run when - // `memory.x` is changed. - println!("cargo:rerun-if-changed=memory.x"); - println!("cargo:rustc-link-arg-bins=--nmagic"); println!("cargo:rustc-link-arg-bins=-Tlink.x"); println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); diff --git a/examples/stm32l4/memory.x b/examples/stm32l4/memory.x deleted file mode 100644 index eb87d1b5..00000000 --- a/examples/stm32l4/memory.x +++ /dev/null @@ -1,7 +0,0 @@ -MEMORY -{ - /* NOTE 1 K = 1 KiBi = 1024 bytes */ - /* These values correspond to the STM32L4S5 */ - FLASH : ORIGIN = 0x08000000, LENGTH = 1024K - RAM : ORIGIN = 0x20000000, LENGTH = 128K -} diff --git a/examples/stm32l4/src/bin/rng.rs b/examples/stm32l4/src/bin/rng.rs index c9302bb9..806e49f5 100644 --- a/examples/stm32l4/src/bin/rng.rs +++ b/examples/stm32l4/src/bin/rng.rs @@ -6,9 +6,13 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; use embassy_stm32::rng::Rng; -use embassy_stm32::Config; +use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + RNG => rng::InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); @@ -24,7 +28,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut buf = [0u8; 16]; unwrap!(rng.async_fill_bytes(&mut buf).await); diff --git a/examples/stm32l4/src/bin/spi.rs b/examples/stm32l4/src/bin/spi.rs index 76e316a2..54cf68f7 100644 --- a/examples/stm32l4/src/bin/spi.rs +++ b/examples/stm32l4/src/bin/spi.rs @@ -15,16 +15,10 @@ fn main() -> ! { let p = embassy_stm32::init(Default::default()); - let mut spi = Spi::new( - p.SPI3, - p.PC10, - p.PC12, - p.PC11, - NoDma, - NoDma, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config); let mut cs = Output::new(p.PE0, Level::High, Speed::VeryHigh); diff --git a/examples/stm32l4/src/bin/spi_blocking_async.rs b/examples/stm32l4/src/bin/spi_blocking_async.rs index 62ef0130..f1b80087 100644 --- a/examples/stm32l4/src/bin/spi_blocking_async.rs +++ b/examples/stm32l4/src/bin/spi_blocking_async.rs @@ -17,16 +17,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let spi = Spi::new( - p.SPI3, - p.PC10, - p.PC12, - p.PC11, - NoDma, - NoDma, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, NoDma, NoDma, spi_config); let mut spi = BlockingAsync::new(spi); diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs index 89471db5..ff9b5b43 100644 --- a/examples/stm32l4/src/bin/spi_dma.rs +++ b/examples/stm32l4/src/bin/spi_dma.rs @@ -14,16 +14,10 @@ async fn main(_spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hello World!"); - let mut spi = Spi::new( - p.SPI3, - p.PC10, - p.PC12, - p.PC11, - p.DMA1_CH1, - p.DMA1_CH2, - Hertz(1_000_000), - Config::default(), - ); + let mut spi_config = Config::default(); + spi_config.frequency = Hertz(1_000_000); + + let mut spi = Spi::new(p.SPI3, p.PC10, p.PC12, p.PC11, p.DMA1_CH1, p.DMA1_CH2, spi_config); // These are the pins for the Inventek eS-Wifi SPI Wifi Adapter. diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml index 5d66c59c..1afd0039 100644 --- a/examples/stm32l5/Cargo.toml +++ b/examples/stm32l5/Cargo.toml @@ -27,3 +27,6 @@ heapless = { version = "0.7.5", default-features = false } rand_core = { version = "0.6.3", default-features = false } embedded-io = { version = "0.4.0", features = ["async"] } static_cell = { version = "1.1", features = ["nightly"]} + +[profile.release] +debug = 2 diff --git a/examples/stm32l5/src/bin/rng.rs b/examples/stm32l5/src/bin/rng.rs index d359847e..9549d64d 100644 --- a/examples/stm32l5/src/bin/rng.rs +++ b/examples/stm32l5/src/bin/rng.rs @@ -6,9 +6,13 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::rcc::{ClockSrc, PLLClkDiv, PLLMul, PLLSource, PLLSrcDiv}; use embassy_stm32::rng::Rng; -use embassy_stm32::Config; +use embassy_stm32::{bind_interrupts, peripherals, rng, Config}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs { + RNG => rng::InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); @@ -23,7 +27,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut buf = [0u8; 16]; unwrap!(rng.async_fill_bytes(&mut buf).await); diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index 32eba427..5e75b21c 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -9,7 +9,7 @@ use embassy_net::{Stack, StackResources}; use embassy_stm32::rcc::*; use embassy_stm32::rng::Rng; use embassy_stm32::usb::Driver; -use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; +use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; @@ -24,6 +24,7 @@ const MTU: usize = 1514; bind_interrupts!(struct Irqs { USB_FS => usb::InterruptHandler; + RNG => rng::InterruptHandler; }); #[embassy_executor::task] @@ -99,7 +100,7 @@ async fn main(spawner: Spawner) { //}); // Generate random seed - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let seed = rng.next_u64(); // Init network stack diff --git a/examples/stm32u5/Cargo.toml b/examples/stm32u5/Cargo.toml index a43a5590..db251eaf 100644 --- a/examples/stm32u5/Cargo.toml +++ b/examples/stm32u5/Cargo.toml @@ -23,3 +23,6 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } micromath = "2.0.0" + +[profile.release] +debug = 2 diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml index 48e34026..1a5aff35 100644 --- a/examples/stm32wb/Cargo.toml +++ b/examples/stm32wb/Cargo.toml @@ -52,3 +52,6 @@ required-features = ["ble"] [[bin]] name = "gatt_server" required-features = ["ble"] + +[profile.release] +debug = 2 diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs index 451bd7d2..ea150c67 100644 --- a/examples/stm32wb/src/bin/eddystone_beacon.rs +++ b/examples/stm32wb/src/bin/eddystone_beacon.rs @@ -8,6 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::hci::host::uart::UartHci; use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; use embassy_stm32_wpan::hci::types::AdvertisingType; @@ -54,7 +55,9 @@ async fn main(_spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs index 0f6419d4..dd67249c 100644 --- a/examples/stm32wb/src/bin/gatt_server.rs +++ b/examples/stm32wb/src/bin/gatt_server.rs @@ -8,6 +8,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::hci::event::command::{CommandComplete, ReturnParameters}; use embassy_stm32_wpan::hci::host::uart::{Packet, UartHci}; use embassy_stm32_wpan::hci::host::{AdvertisingFilterPolicy, EncryptionKey, HostHci, OwnAddressType}; @@ -62,7 +63,9 @@ async fn main(_spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs index 1379ac6b..881dc488 100644 --- a/examples/stm32wb/src/bin/mac_ffd.rs +++ b/examples/stm32wb/src/bin/mac_ffd.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; use embassy_stm32_wpan::mac::event::MacEvent; use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; @@ -30,7 +31,7 @@ async fn main(spawner: Spawner) { - Obtain a NUCLEO-STM32WB55 from your preferred supplier. - Download and Install STM32CubeProgrammer. - - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x - Open STM32CubeProgrammer - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. @@ -39,7 +40,7 @@ async fn main(spawner: Spawner) { - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the - stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address. - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Select "Start Wireless Stack". - Disconnect from the device. @@ -49,7 +50,9 @@ async fn main(spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index bbcd0a70..f8c76b5a 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::mac::commands::{ResetRequest, SetRequest, StartRequest}; use embassy_stm32_wpan::mac::typedefs::{MacChannel, PanId, PibId}; use embassy_stm32_wpan::mac::{self, Runner}; @@ -36,7 +37,7 @@ async fn main(spawner: Spawner) { - Obtain a NUCLEO-STM32WB55 from your preferred supplier. - Download and Install STM32CubeProgrammer. - - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x - Open STM32CubeProgrammer - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. @@ -45,7 +46,7 @@ async fn main(spawner: Spawner) { - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the - stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address. - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Select "Start Wireless Stack". - Disconnect from the device. @@ -55,7 +56,9 @@ async fn main(spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs index 4d8b6601..000355de 100644 --- a/examples/stm32wb/src/bin/mac_rfd.rs +++ b/examples/stm32wb/src/bin/mac_rfd.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::mac::commands::{AssociateRequest, DataRequest, GetRequest, ResetRequest, SetRequest}; use embassy_stm32_wpan::mac::event::MacEvent; use embassy_stm32_wpan::mac::typedefs::{ @@ -32,7 +33,7 @@ async fn main(spawner: Spawner) { - Obtain a NUCLEO-STM32WB55 from your preferred supplier. - Download and Install STM32CubeProgrammer. - - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x - Open STM32CubeProgrammer - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. @@ -41,7 +42,7 @@ async fn main(spawner: Spawner) { - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the - stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address. - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Select "Start Wireless Stack". - Disconnect from the device. @@ -51,7 +52,9 @@ async fn main(spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs index 9fc4b8aa..fc49c3c4 100644 --- a/examples/stm32wb/src/bin/tl_mbox.rs +++ b/examples/stm32wb/src/bin/tl_mbox.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::TlMbox; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -41,7 +42,9 @@ async fn main(_spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs index 90349422..5745ebd0 100644 --- a/examples/stm32wb/src/bin/tl_mbox_ble.rs +++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -40,7 +41,9 @@ async fn main(_spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs index 5931c392..f32e07d9 100644 --- a/examples/stm32wb/src/bin/tl_mbox_mac.rs +++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs @@ -6,6 +6,7 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::rcc::WPAN_DEFAULT; use embassy_stm32_wpan::sub::mm; use embassy_stm32_wpan::TlMbox; use {defmt_rtt as _, panic_probe as _}; @@ -27,7 +28,7 @@ async fn main(spawner: Spawner) { - Obtain a NUCLEO-STM32WB55 from your preferred supplier. - Download and Install STM32CubeProgrammer. - - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Mac_802_15_4_fw.bin, and Release_Notes.html from gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x - Open STM32CubeProgrammer - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. @@ -36,7 +37,7 @@ async fn main(spawner: Spawner) { - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the - stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + stm32wb5x_BLE_Mac_802_15_4_fw.bin file. It should not be the same memory address. - Select that file, the memory address, "verify download", and then "Firmware Upgrade". - Select "Start Wireless Stack". - Disconnect from the device. @@ -46,7 +47,9 @@ async fn main(spawner: Spawner) { Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. */ - let p = embassy_stm32::init(Default::default()); + let mut config = embassy_stm32::Config::default(); + config.rcc = WPAN_DEFAULT; + let p = embassy_stm32::init(config); info!("Hello World!"); let config = Config::default(); diff --git a/examples/stm32wl/Cargo.toml b/examples/stm32wl/Cargo.toml index 6e6f269a..48b69c8d 100644 --- a/examples/stm32wl/Cargo.toml +++ b/examples/stm32wl/Cargo.toml @@ -28,5 +28,5 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } chrono = { version = "^0.4", default-features = false } -[patch.crates-io] -lora-phy = { git = "https://github.com/embassy-rs/lora-phy", rev = "ad289428fd44b02788e2fa2116445cc8f640a265" } +[profile.release] +debug = 2 diff --git a/examples/stm32wl/src/bin/lora_lorawan.rs b/examples/stm32wl/src/bin/lora_lorawan.rs index 805d2141..2c9c9886 100644 --- a/examples/stm32wl/src/bin/lora_lorawan.rs +++ b/examples/stm32wl/src/bin/lora_lorawan.rs @@ -10,9 +10,9 @@ use embassy_executor::Spawner; use embassy_lora::iv::{InterruptHandler, Stm32wlInterfaceVariant}; use embassy_lora::LoraTimer; use embassy_stm32::gpio::{Level, Output, Pin, Speed}; -use embassy_stm32::rng::Rng; +use embassy_stm32::rng::{self, Rng}; use embassy_stm32::spi::Spi; -use embassy_stm32::{bind_interrupts, pac}; +use embassy_stm32::{bind_interrupts, pac, peripherals}; use embassy_time::Delay; use lora_phy::mod_params::*; use lora_phy::sx1261_2::SX1261_2; @@ -26,6 +26,7 @@ const LORAWAN_REGION: region::Region = region::Region::EU868; // warning: set th bind_interrupts!(struct Irqs{ SUBGHZ_RADIO => InterruptHandler; + RNG => rng::InterruptHandler; }); #[embassy_executor::main] @@ -58,7 +59,7 @@ async fn main(_spawner: Spawner) { }; let radio = LoRaRadio::new(lora); let region: region::Configuration = region::Configuration::new(LORAWAN_REGION); - let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG)); + let mut device: Device<_, Crypto, _, _> = Device::new(region, radio, LoraTimer::new(), Rng::new(p.RNG, Irqs)); defmt::info!("Joining LoRaWAN network"); diff --git a/examples/stm32wl/src/bin/random.rs b/examples/stm32wl/src/bin/random.rs index d8562fca..592e65f4 100644 --- a/examples/stm32wl/src/bin/random.rs +++ b/examples/stm32wl/src/bin/random.rs @@ -4,10 +4,14 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::pac; -use embassy_stm32::rng::Rng; +use embassy_stm32::rng::{self, Rng}; +use embassy_stm32::{bind_interrupts, pac, peripherals}; use {defmt_rtt as _, panic_probe as _}; +bind_interrupts!(struct Irqs{ + RNG => rng::InterruptHandler; +}); + #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = embassy_stm32::Config::default(); @@ -21,7 +25,7 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); - let mut rng = Rng::new(p.RNG); + let mut rng = Rng::new(p.RNG, Irqs); let mut buf = [0u8; 16]; unwrap!(rng.async_fill_bytes(&mut buf).await); diff --git a/examples/wasm/Cargo.toml b/examples/wasm/Cargo.toml index 3679e385..2791cc34 100644 --- a/examples/wasm/Cargo.toml +++ b/examples/wasm/Cargo.toml @@ -17,3 +17,6 @@ wasm-bindgen = "0.2" web-sys = { version = "0.3", features = ["Document", "Element", "HtmlElement", "Node", "Window" ] } log = "0.4.11" critical-section = { version = "1.1", features = ["std"] } + +[profile.release] +debug = 2 diff --git a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs index 398ab9d2..e2adfe0b 100644 --- a/tests/nrf/src/bin/wifi_esp_hosted_perf.rs +++ b/tests/nrf/src/bin/wifi_esp_hosted_perf.rs @@ -118,9 +118,9 @@ const WIFI_NETWORK: &str = "EmbassyTest"; const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; const TEST_DURATION: usize = 10; -const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 150; -const TEST_EXPECTED_UPLOAD_KBPS: usize = 150; -const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 150; +const TEST_EXPECTED_DOWNLOAD_KBPS: usize = 50; +const TEST_EXPECTED_UPLOAD_KBPS: usize = 50; +const TEST_EXPECTED_UPLOAD_DOWNLOAD_KBPS: usize = 50; const RX_BUFFER_SIZE: usize = 4096; const TX_BUFFER_SIZE: usize = 4096; const SERVER_ADDRESS: Ipv4Address = Ipv4Address::new(192, 168, 2, 2); diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index bc127e2e..fffdabc9 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs @@ -48,9 +48,9 @@ async fn main(spawner: Spawner) { } // cyw43 firmware needs to be flashed manually: - // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101c0000 + // probe-rs download 43439A0.bin --format bin --chip RP2040 --base-address 0x101b0000 // probe-rs download 43439A0_clm.bin --format bin --chip RP2040 --base-address 0x101f8000 - let fw = unsafe { core::slice::from_raw_parts(0x101c0000 as *const u8, 224190) }; + let fw = unsafe { core::slice::from_raw_parts(0x101b0000 as *const u8, 230321) }; let clm = unsafe { core::slice::from_raw_parts(0x101f8000 as *const u8, 4752) }; let pwr = Output::new(p.PIN_23, Level::Low); diff --git a/tests/rp/src/bin/flash.rs b/tests/rp/src/bin/flash.rs index cf9b86df..c31d6dec 100644 --- a/tests/rp/src/bin/flash.rs +++ b/tests/rp/src/bin/flash.rs @@ -6,11 +6,11 @@ mod common; use defmt::*; use embassy_executor::Spawner; -use embassy_rp::flash::{ERASE_SIZE, FLASH_BASE}; +use embassy_rp::flash::{Async, ERASE_SIZE, FLASH_BASE}; use embassy_time::{Duration, Timer}; use {defmt_rtt as _, panic_probe as _}; -const ADDR_OFFSET: u32 = 0x4000; +const ADDR_OFFSET: u32 = 0x8000; #[embassy_executor::main] async fn main(_spawner: Spawner) { @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { // https://github.com/knurling-rs/defmt/pull/683 Timer::after(Duration::from_millis(10)).await; - let mut flash = embassy_rp::flash::Flash::<_, { 2 * 1024 * 1024 }>::new(p.FLASH); + let mut flash = embassy_rp::flash::Flash::<_, Async, { 2 * 1024 * 1024 }>::new(p.FLASH, p.DMA_CH0); // Get JEDEC id let jedec = defmt::unwrap!(flash.jedec_id()); @@ -60,6 +60,14 @@ async fn main(_spawner: Spawner) { defmt::panic!("unexpected"); } + let mut buf = [0u32; ERASE_SIZE / 4]; + + defmt::unwrap!(flash.background_read(ADDR_OFFSET, &mut buf)).await; + info!("Contents after write starts with {=u32:x}", buf[0]); + if buf.iter().any(|x| *x != 0xDADADADA) { + defmt::panic!("unexpected"); + } + info!("Test OK"); cortex_m::asm::bkpt(); } diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs index 45004424..bdea63ea 100644 --- a/tests/rp/src/bin/pio_irq.rs +++ b/tests/rp/src/bin/pio_irq.rs @@ -9,7 +9,6 @@ use embassy_executor::Spawner; use embassy_rp::bind_interrupts; use embassy_rp::peripherals::PIO0; use embassy_rp::pio::{Config, InterruptHandler, Pio}; -use embassy_rp::relocate::RelocatedProgram; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { @@ -35,9 +34,8 @@ async fn main(_spawner: Spawner) { "irq wait 1", ); - let relocated = RelocatedProgram::new(&prg.program); let mut cfg = Config::default(); - cfg.use_program(&common.load_program(&relocated), &[]); + cfg.use_program(&common.load_program(&prg.program), &[]); sm.set_config(&cfg); sm.set_enable(true); diff --git a/tests/rp/src/bin/pio_multi_load.rs b/tests/rp/src/bin/pio_multi_load.rs new file mode 100644 index 00000000..356f1679 --- /dev/null +++ b/tests/rp/src/bin/pio_multi_load.rs @@ -0,0 +1,126 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] +#[path = "../common.rs"] +mod common; + +use defmt::info; +use embassy_executor::Spawner; +use embassy_rp::bind_interrupts; +use embassy_rp::peripherals::PIO0; +use embassy_rp::pio::{Config, InterruptHandler, LoadError, Pio}; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + PIO0_IRQ_0 => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let pio = p.PIO0; + let Pio { + mut common, + mut sm0, + mut sm1, + mut sm2, + irq_flags, + .. + } = Pio::new(pio, Irqs); + + // load with explicit origin works + let prg1 = pio_proc::pio_asm!( + ".origin 4" + "nop", + "nop", + "nop", + "nop", + "nop", + "nop", + "nop", + "irq 0", + "nop", + "nop", + ); + let loaded1 = common.load_program(&prg1.program); + assert_eq!(loaded1.origin, 4); + assert_eq!(loaded1.wrap.source, 13); + assert_eq!(loaded1.wrap.target, 4); + + // load without origin chooses a free space + let prg2 = pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 1", "nop", "nop",); + let loaded2 = common.load_program(&prg2.program); + assert_eq!(loaded2.origin, 14); + assert_eq!(loaded2.wrap.source, 23); + assert_eq!(loaded2.wrap.target, 14); + + // wrapping around the end of program space automatically works + let prg3 = + pio_proc::pio_asm!("nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "nop", "irq 2",); + let loaded3 = common.load_program(&prg3.program); + assert_eq!(loaded3.origin, 24); + assert_eq!(loaded3.wrap.source, 3); + assert_eq!(loaded3.wrap.target, 24); + + // check that the programs actually work + { + let mut cfg = Config::default(); + cfg.use_program(&loaded1, &[]); + sm0.set_config(&cfg); + sm0.set_enable(true); + while !irq_flags.check(0) {} + sm0.set_enable(false); + } + { + let mut cfg = Config::default(); + cfg.use_program(&loaded2, &[]); + sm1.set_config(&cfg); + sm1.set_enable(true); + while !irq_flags.check(1) {} + sm1.set_enable(false); + } + { + let mut cfg = Config::default(); + cfg.use_program(&loaded3, &[]); + sm2.set_config(&cfg); + sm2.set_enable(true); + while !irq_flags.check(2) {} + sm2.set_enable(false); + } + + // instruction memory is full now. all loads should fail. + { + let prg = pio_proc::pio_asm!(".origin 0", "nop"); + match common.try_load_program(&prg.program) { + Err(LoadError::AddressInUse(0)) => (), + _ => panic!("program loaded when it shouldn't"), + }; + + let prg = pio_proc::pio_asm!("nop"); + match common.try_load_program(&prg.program) { + Err(LoadError::InsufficientSpace) => (), + _ => panic!("program loaded when it shouldn't"), + }; + } + + // freeing some memory should allow further loads though. + unsafe { + common.free_instr(loaded3.used_memory); + } + { + let prg = pio_proc::pio_asm!(".origin 0", "nop"); + match common.try_load_program(&prg.program) { + Ok(_) => (), + _ => panic!("program didn't loaded when it shouldn"), + }; + + let prg = pio_proc::pio_asm!("nop"); + match common.try_load_program(&prg.program) { + Ok(_) => (), + _ => panic!("program didn't loaded when it shouldn"), + }; + } + + info!("Test OK"); + cortex_m::asm::bkpt(); +} diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 3007cd1e..17320649 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml @@ -7,11 +7,11 @@ autobins = false [features] stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] # Blue Pill -stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma"] # Nucleo "sdmmc" -stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma"] # Nucleo +stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "can", "not-gpdma", "dac-adc-pin"] # Nucleo "sdmmc" +stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] # Nucleo stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] # Nucleo stm32g491re = ["embassy-stm32/stm32g491re", "not-gpdma"] # Nucleo -stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma"] # Nucleo +stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "not-gpdma", "dac-adc-pin"] # Nucleo stm32wb55rg = ["embassy-stm32/stm32wb55rg", "not-gpdma", "ble", "mac" ] # Nucleo stm32h563zi = ["embassy-stm32/stm32h563zi"] # Nucleo stm32u585ai = ["embassy-stm32/stm32u585ai"] # IoT board @@ -23,6 +23,7 @@ ble = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/ble"] mac = ["dep:embassy-stm32-wpan", "embassy-stm32-wpan/mac"] embassy-stm32-wpan = [] not-gpdma = [] +dac-adc-pin = [] [dependencies] teleprobe-meta = "1" @@ -42,6 +43,7 @@ cortex-m-rt = "0.7.0" embedded-hal = "0.2.6" embedded-hal-1 = { package = "embedded-hal", version = "=1.0.0-alpha.11" } embedded-hal-async = { version = "=0.2.0-alpha.2" } +micromath = "2.0.0" panic-probe = { version = "0.3.0", features = ["print-defmt"] } rand_core = { version = "0.6", default-features = false } rand_chacha = { version = "0.3", default-features = false } @@ -55,6 +57,11 @@ name = "can" path = "src/bin/can.rs" required-features = [ "can",] +[[bin]] +name = "dac" +path = "src/bin/dac.rs" +required-features = [ "dac-adc-pin",] + [[bin]] name = "gpio" path = "src/bin/gpio.rs" diff --git a/tests/stm32/src/bin/dac.rs b/tests/stm32/src/bin/dac.rs new file mode 100644 index 00000000..67a7d5b5 --- /dev/null +++ b/tests/stm32/src/bin/dac.rs @@ -0,0 +1,81 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +// required-features: dac-adc-pin + +#[path = "../common.rs"] +mod common; +use common::*; +use defmt::assert; +use embassy_executor::Spawner; +use embassy_stm32::adc::Adc; +use embassy_stm32::dac::{DacCh1, DacChannel, Value}; +use embassy_stm32::dma::NoDma; +use embassy_time::{Delay, Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + // Initialize the board and obtain a Peripherals instance + let p: embassy_stm32::Peripherals = embassy_stm32::init(config()); + + #[cfg(feature = "stm32f429zi")] + let dac_peripheral = p.DAC; + + #[cfg(any(feature = "stm32h755zi", feature = "stm32g071rb"))] + let dac_peripheral = p.DAC1; + + let mut dac: DacCh1<'_, _, NoDma> = DacCh1::new(dac_peripheral, NoDma, p.PA4); + unwrap!(dac.set_trigger_enable(false)); + + let mut adc = Adc::new(p.ADC1, &mut Delay); + + #[cfg(feature = "stm32h755zi")] + let normalization_factor = 256; + #[cfg(any(feature = "stm32f429zi", feature = "stm32g071rb"))] + let normalization_factor: i32 = 16; + + unwrap!(dac.set(Value::Bit8(0))); + // Now wait a little to obtain a stable value + Timer::after(Duration::from_millis(30)).await; + let offset = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); + + for v in 0..=255 { + // First set the DAC output value + let dac_output_val = to_sine_wave(v); + unwrap!(dac.set(Value::Bit8(dac_output_val))); + + // Now wait a little to obtain a stable value + Timer::after(Duration::from_millis(30)).await; + + // Need to steal the peripherals here because PA4 is obviously in use already + let measured = adc.read(&mut unsafe { embassy_stm32::Peripherals::steal() }.PA4); + // Calibrate and normalize the measurement to get close to the dac_output_val + let measured_normalized = ((measured as i32 - offset as i32) / normalization_factor) as i16; + + info!("value / measured: {} / {}", dac_output_val, measured_normalized); + + // The deviations are quite enormous but that does not matter since this is only a quick test + assert!((dac_output_val as i16 - measured_normalized).abs() < 15); + } + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +use core::f32::consts::PI; + +use micromath::F32Ext; + +fn to_sine_wave(v: u8) -> u8 { + if v >= 128 { + // top half + let r = PI * ((v - 128) as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } else { + // bottom half + let r = PI + PI * (v as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } +} diff --git a/tests/stm32/src/bin/spi.rs b/tests/stm32/src/bin/spi.rs index 819ecae3..e51dd5bf 100644 --- a/tests/stm32/src/bin/spi.rs +++ b/tests/stm32/src/bin/spi.rs @@ -35,15 +35,14 @@ async fn main(_spawner: Spawner) { #[cfg(feature = "stm32c031c6")] let (spi, sck, mosi, miso) = (p.SPI1, p.PA5, p.PA7, p.PA6); + let mut spi_config = spi::Config::default(); + spi_config.frequency = Hertz(1_000_000); + let mut spi = Spi::new( - spi, - sck, // Arduino D13 + spi, sck, // Arduino D13 mosi, // Arduino D11 miso, // Arduino D12 - NoDma, - NoDma, - Hertz(1_000_000), - spi::Config::default(), + NoDma, NoDma, spi_config, ); let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE]; diff --git a/tests/stm32/src/bin/spi_dma.rs b/tests/stm32/src/bin/spi_dma.rs index 78aad24e..d45cbe45 100644 --- a/tests/stm32/src/bin/spi_dma.rs +++ b/tests/stm32/src/bin/spi_dma.rs @@ -34,15 +34,14 @@ async fn main(_spawner: Spawner) { #[cfg(feature = "stm32c031c6")] let (spi, sck, mosi, miso, tx_dma, rx_dma) = (p.SPI1, p.PA5, p.PA7, p.PA6, p.DMA1_CH1, p.DMA1_CH2); + let mut spi_config = spi::Config::default(); + spi_config.frequency = Hertz(1_000_000); + let mut spi = Spi::new( - spi, - sck, // Arduino D13 + spi, sck, // Arduino D13 mosi, // Arduino D11 miso, // Arduino D12 - tx_dma, - rx_dma, - Hertz(1_000_000), - spi::Config::default(), + tx_dma, rx_dma, spi_config, ); let data: [u8; 9] = [0x00, 0xFF, 0xAA, 0x55, 0xC0, 0xFF, 0xEE, 0xC0, 0xDE]; diff --git a/tests/stm32/src/common.rs b/tests/stm32/src/common.rs index 3d2a9b8e..ca5cb43a 100644 --- a/tests/stm32/src/common.rs +++ b/tests/stm32/src/common.rs @@ -33,6 +33,7 @@ pub fn config() -> Config { { config.rcc.sys_ck = Some(Hertz(400_000_000)); config.rcc.pll1.q_ck = Some(Hertz(100_000_000)); + config.rcc.adc_clock_source = embassy_stm32::rcc::AdcClockSource::PerCk; } #[cfg(feature = "stm32u585ai")]