Merge branch 'main' of https://github.com/embassy-rs/embassy into hrtim

This commit is contained in:
xoviat 2023-07-28 17:18:22 -05:00
commit c7c701b3e3
181 changed files with 2109 additions and 893 deletions

2
.github/ci/test.sh vendored
View file

@ -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

View file

@ -33,6 +33,7 @@ The <a href="https://docs.embassy.dev/embassy-net/">embassy-net</a> network stac
- **Bluetooth** -
The <a href="https://github.com/embassy-rs/nrf-softdevice">nrf-softdevice</a> crate provides Bluetooth Low Energy 4.x and 5.x support for nRF52 microcontrollers.
The <a href="https://github.com/embassy-rs/embassy/tree/main/embassy-stm32-wpan">embassy-stm32-wpan</a> crate provides Bluetooth Low Energy 5.x support for stm32wb microcontrollers.
- **LoRa** -
<a href="https://docs.embassy.dev/embassy-lora/">embassy-lora</a> supports LoRa networking.
@ -111,6 +112,12 @@ cargo install probe-rs --features cli
cd examples/nrf52840
```
- Ensure `Cargo.toml` sets the right feature for the name of the chip you are programming.
If this name is incorrect, the example may fail to run or immediately crash
after being programmed.
- Ensure `.cargo/config.toml` contains the name of the chip you are programming.
- Run the example
For example:
@ -119,6 +126,8 @@ For example:
cargo run --release --bin blinky
```
For more help getting started, see [Getting Started][1] and [Running the Examples][2].
## Developing Embassy with Rust Analyzer based editors
The [Rust Analyzer](https://rust-analyzer.github.io/) is used by [Visual Studio Code](https://code.visualstudio.com/)
@ -151,3 +160,5 @@ This work is licensed under either of
at your option.
[1]: https://github.com/embassy-rs/embassy/wiki/Getting-Started
[2]: https://github.com/embassy-rs/embassy/wiki/Running-the-Examples

2
ci.sh
View file

@ -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 \

Binary file not shown.

Binary file not shown.

View file

@ -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)
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

View file

@ -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<PIO> = 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,
}
}

View file

@ -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"

View file

@ -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
<http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.

View file

@ -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;

View file

@ -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 }

View file

@ -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);
}

View file

@ -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<D: Driver + 'static> Inner<D> {
#[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:");

View file

@ -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 }

View file

@ -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};

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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;

View file

@ -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 _;

View file

@ -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;

View file

@ -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;

View file

@ -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,
};

View file

@ -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;

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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};

View file

@ -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"]
@ -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"

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -1,6 +1,6 @@
use core::marker::PhantomData;
use embassy_hal_common::Peripheral;
use embassy_hal_internal::Peripheral;
use embedded_storage::nor_flash::{
check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind,
ReadNorFlash,

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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();
}

View file

@ -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<const SIZE: usize>(&mut self, prog: &RelocatedProgram<SIZE>) -> 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<const SIZE: usize>(&mut self, prog: &Program<SIZE>) -> 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<const SIZE: usize>(
&mut self,
prog: &RelocatedProgram<SIZE>,
prog: &Program<SIZE>,
) -> Result<LoadedProgram<'d, PIO>, 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<const SIZE: usize>(
&mut self,
prog: &Program<SIZE>,
origin: u8,
) -> Result<LoadedProgram<'d, PIO>, 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<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize>
fn try_write_instr<I>(&mut self, start: usize, instrs: I) -> Result<InstanceMemory<'d, PIO>, usize>
where
I: Iterator<Item = u16>,
{

View file

@ -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};

View file

@ -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<PROGRAM_SIZE>) -> RelocatedProgram<PROGRAM_SIZE> {
let origin = program.origin.unwrap_or(0);
RelocatedProgram { program, origin }
}
pub fn new_with_origin(program: &Program<PROGRAM_SIZE>, origin: u8) -> RelocatedProgram<PROGRAM_SIZE> {
RelocatedProgram { program, origin }
}

View file

@ -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;

View file

@ -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};

View file

@ -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};

View file

@ -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;

View file

@ -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" ]

View file

@ -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;

View file

@ -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 }
@ -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"] }
@ -78,40 +79,63 @@ stm32-metapac = { version = "13", default-features = false, features = ["metadat
[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"]
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"]
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" ]
@ -1445,4 +1469,4 @@ stm32wle5cb = [ "stm32-metapac/stm32wle5cb" ]
stm32wle5cc = [ "stm32-metapac/stm32wle5cc" ]
stm32wle5j8 = [ "stm32-metapac/stm32wle5j8" ]
stm32wle5jb = [ "stm32-metapac/stm32wle5jb" ]
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]
stm32wle5jc = [ "stm32-metapac/stm32wle5jc" ]

View file

@ -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<MODE>);
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<MODE>);
});
}
@ -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,21 @@ 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)),

View file

@ -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};

View file

@ -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};

View file

@ -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;

View file

@ -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};

View file

@ -226,7 +226,7 @@ impl Prescaler {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u16>) -> Self {
embassy_hal_common::into_ref!(adc);
embassy_hal_internal::into_ref!(adc);
T::enable();
T::reset();

View file

@ -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;
@ -77,6 +77,7 @@ pub struct Can<'d, T: Instance> {
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BusError {
Stuff,
Form,
@ -90,6 +91,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.
@ -161,58 +178,60 @@ impl<'d, T: Instance> Can<'d, T> {
.leave_disabled();
}
/// 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
/// Enables the peripheral and synchronizes with the bus.
///
/// This will wait for 11 consecutive recessive bits (bus idle state).
/// Contrary to enable method from bxcan library, this will not freeze the executor while waiting.
pub async fn enable(&mut self) {
while self.borrow_mut().enable_non_blocking().is_err() {
// SCE interrupt is only generated for entering sleep mode, but not leaving.
// Yield to allow other tasks to execute while can bus is initializing.
embassy_futures::yield_now().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(());
}
/// Queues the message to be sent but exerts backpressure
pub async fn write(&mut self, frame: &Frame) -> bxcan::TransmitStatus {
CanTx { can: &self.can }.write(frame).await
}
Poll::Pending
})
.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<bxcan::TransmitStatus, TryWriteError> {
CanTx { can: &self.can }.try_write(frame)
}
/// 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<(u16, bxcan::Frame), BusError> {
poll_fn(|cx| {
T::state().err_waker.register(cx.waker());
if let Poll::Ready((time, frame)) = T::state().rx_queue.recv().poll_unpin(cx) {
return Poll::Ready(Ok((time, frame)));
} 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<BusError> {
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<(u16, bxcan::Frame), TryReadError> {
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) {
@ -374,6 +393,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<bxcan::TransmitStatus, TryWriteError> {
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());
@ -385,6 +412,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)]
@ -407,6 +470,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<(u16, bxcan::Frame), TryReadError> {
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<BusError> {
let err = { T::regs().esr().read() };
if err.boff() {

View file

@ -1,5 +1,5 @@
pub use bxcan;
use embassy_hal_common::PeripheralRef;
use embassy_hal_internal::PeripheralRef;
use crate::peripherals;

View file

@ -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;

View file

@ -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;

View file

@ -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;
@ -38,11 +38,30 @@ impl Channel {
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
/// Trigger sources for CH1
pub enum Ch1Trigger {
Tim6,
Tim3,
Tim7,
Tim15,
#[cfg(dac_v3)]
Tim1,
Tim2,
#[cfg(not(dac_v3))]
Tim3,
#[cfg(dac_v3)]
Tim4,
#[cfg(dac_v3)]
Tim5,
Tim6,
Tim7,
#[cfg(dac_v3)]
Tim8,
Tim15,
#[cfg(dac_v3)]
Hrtim1Dactrg1,
#[cfg(dac_v3)]
Hrtim1Dactrg2,
#[cfg(dac_v3)]
Lptim1,
#[cfg(dac_v3)]
Lptim2,
#[cfg(dac_v3)]
Lptim3,
Exti9,
Software,
}
@ -50,14 +69,30 @@ pub enum Ch1Trigger {
impl Ch1Trigger {
fn tsel(&self) -> dac::vals::Tsel1 {
match self {
Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim1 => dac::vals::Tsel1::TIM1_TRGO,
Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO,
#[cfg(not(dac_v3))]
Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM3_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim3 => dac::vals::Tsel1::TIM1_TRGO,
Ch1Trigger::Tim4 => dac::vals::Tsel1::TIM4_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim5 => dac::vals::Tsel1::TIM5_TRGO,
Ch1Trigger::Tim6 => dac::vals::Tsel1::TIM6_TRGO,
Ch1Trigger::Tim7 => dac::vals::Tsel1::TIM7_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Tim8 => dac::vals::Tsel1::TIM8_TRGO,
Ch1Trigger::Tim15 => dac::vals::Tsel1::TIM15_TRGO,
Ch1Trigger::Tim2 => dac::vals::Tsel1::TIM2_TRGO,
#[cfg(dac_v3)]
Ch1Trigger::Hrtim1Dactrg1 => dac::vals::Tsel1::HRTIM1_DACTRG1,
#[cfg(dac_v3)]
Ch1Trigger::Hrtim1Dactrg2 => dac::vals::Tsel1::HRTIM1_DACTRG2,
#[cfg(dac_v3)]
Ch1Trigger::Lptim1 => dac::vals::Tsel1::LPTIM1_OUT,
#[cfg(dac_v3)]
Ch1Trigger::Lptim2 => dac::vals::Tsel1::LPTIM2_OUT,
#[cfg(dac_v3)]
Ch1Trigger::Lptim3 => dac::vals::Tsel1::LPTIM3_OUT,
Ch1Trigger::Exti9 => dac::vals::Tsel1::EXTI9,
Ch1Trigger::Software => dac::vals::Tsel1::SOFTWARE,
}
@ -129,7 +164,7 @@ pub trait DacChannel<T: Instance, Tx> {
}
/// Set mode register of the given channel
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
fn set_channel_mode(&mut self, val: u8) -> Result<(), Error> {
T::regs().mcr().modify(|reg| {
reg.set_mode(Self::CHANNEL.index(), val);
@ -216,8 +251,9 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
pub fn new(
peri: impl Peripheral<P = T> + 'd,
dma: impl Peripheral<P = Tx> + 'd,
_pin: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
pin: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin.set_as_analog();
into_ref!(peri, dma);
T::enable();
T::reset();
@ -226,7 +262,7 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac.set_channel_mode(0).unwrap();
dac.enable_channel().unwrap();
dac.set_trigger_enable(true).unwrap();
@ -252,7 +288,6 @@ impl<'d, T: Instance, Tx> DacCh1<'d, T, Tx> {
/// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
///
/// **Important:** Channel 1 has to be configured for the DAC instance!
#[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error>
where
Tx: DmaCh1<T>,
@ -327,8 +362,9 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
pub fn new(
_peri: impl Peripheral<P = T> + 'd,
dma: impl Peripheral<P = Tx> + 'd,
_pin: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
pin: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin.set_as_analog();
into_ref!(_peri, dma);
T::enable();
T::reset();
@ -340,7 +376,7 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac.set_channel_mode(0).unwrap();
dac.enable_channel().unwrap();
dac.set_trigger_enable(true).unwrap();
@ -364,7 +400,6 @@ impl<'d, T: Instance, Tx> DacCh2<'d, T, Tx> {
/// Note that for performance reasons in circular mode the transfer complete interrupt is disabled.
///
/// **Important:** Channel 2 has to be configured for the DAC instance!
#[cfg(all(bdma, not(dma)))] // It currently only works with BDMA-only chips (DMA should theoretically work though)
pub async fn write(&mut self, data: ValueArray<'_>, circular: bool) -> Result<(), Error>
where
Tx: DmaCh2<T>,
@ -442,9 +477,11 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
peri: impl Peripheral<P = T> + 'd,
dma_ch1: impl Peripheral<P = TxCh1> + 'd,
dma_ch2: impl Peripheral<P = TxCh2> + 'd,
_pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd,
_pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + 'd,
pin_ch1: impl Peripheral<P = impl DacPin<T, 1>> + crate::gpio::sealed::Pin + 'd,
pin_ch2: impl Peripheral<P = impl DacPin<T, 2>> + crate::gpio::sealed::Pin + 'd,
) -> Self {
pin_ch1.set_as_analog();
pin_ch2.set_as_analog();
into_ref!(peri, dma_ch1, dma_ch2);
T::enable();
T::reset();
@ -461,12 +498,12 @@ impl<'d, T: Instance, TxCh1, TxCh2> Dac<'d, T, TxCh1, TxCh2> {
// Configure each activated channel. All results can be `unwrap`ed since they
// will only error if the channel is not configured (i.e. ch1, ch2 are false)
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac_ch1.set_channel_mode(0).unwrap();
dac_ch1.enable_channel().unwrap();
dac_ch1.set_trigger_enable(true).unwrap();
#[cfg(dac_v2)]
#[cfg(any(dac_v2, dac_v3))]
dac_ch2.set_channel_mode(0).unwrap();
dac_ch2.enable_channel().unwrap();
dac_ch2.set_trigger_enable(true).unwrap();

View file

@ -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;

View file

@ -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<usize, OverrunError> {
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()

View file

@ -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};
@ -28,6 +28,12 @@ pub struct TransferOptions {
pub flow_ctrl: FlowControl,
/// FIFO threshold for DMA FIFO mode. If none, direct mode is used.
pub fifo_threshold: Option<FifoThreshold>,
/// Enable circular DMA
pub circular: bool,
/// Enable half transfer interrupt
pub half_transfer_ir: bool,
/// Enable transfer complete interrupt
pub complete_transfer_ir: bool,
}
impl Default for TransferOptions {
@ -37,6 +43,9 @@ impl Default for TransferOptions {
mburst: Burst::Single,
flow_ctrl: FlowControl::Dma,
fifo_threshold: None,
circular: false,
half_transfer_ir: false,
complete_transfer_ir: true,
}
}
}
@ -365,7 +374,13 @@ impl<'a, C: Channel> Transfer<'a, C> {
});
w.set_pinc(vals::Inc::FIXED);
w.set_teie(true);
w.set_tcie(true);
w.set_tcie(options.complete_transfer_ir);
if options.circular {
w.set_circ(vals::Circ::ENABLED);
debug!("Setting circular mode");
} else {
w.set_circ(vals::Circ::DISABLED);
}
#[cfg(dma_v1)]
w.set_trbuff(true);
@ -646,7 +661,7 @@ impl<'a, C: Channel, W: Word> RingBuffer<'a, C, W> {
w.set_minc(vals::Inc::INCREMENTED);
w.set_pinc(vals::Inc::FIXED);
w.set_teie(true);
w.set_htie(true);
w.set_htie(options.half_transfer_ir);
w.set_tcie(true);
w.set_circ(vals::Circ::ENABLED);
#[cfg(dma_v1)]
@ -696,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<usize, OverrunError> {
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()

View file

@ -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};

View file

@ -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::*;

View file

@ -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>) -> 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

View file

@ -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};

View file

@ -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::*;

View file

@ -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};

View file

@ -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;

View file

@ -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::{

View file

@ -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};

View file

@ -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};

View file

@ -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};

Some files were not shown because too many files have changed in this diff Show more