Merge branch 'main' into fix/ringbuffered-error-handling to resolve merge conflicts

This commit is contained in:
Tobias Naumann 2025-03-31 16:48:13 +02:00
commit c29fc3532b
338 changed files with 7794 additions and 4352 deletions

1
.github/ci/doc.sh vendored
View File

@ -25,6 +25,7 @@ docserver-builder -i ./embassy-executor -o webroot/crates/embassy-executor/git.z
docserver-builder -i ./embassy-futures -o webroot/crates/embassy-futures/git.zup
docserver-builder -i ./embassy-nrf -o webroot/crates/embassy-nrf/git.zup
docserver-builder -i ./embassy-rp -o webroot/crates/embassy-rp/git.zup
docserver-builder -i ./embassy-mspm0 -o webroot/crates/embassy-mspm0/git.zup
docserver-builder -i ./embassy-sync -o webroot/crates/embassy-sync/git.zup
docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup
docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup

View File

@ -28,6 +28,11 @@
// To work on the examples, comment the line above and all of the cargo.features lines,
// then uncomment ONE line below to select the chip you want to work on.
// This makes rust-analyzer work on the example crate and all its dependencies.
// "examples/mspm0c1104/Cargo.toml",
// "examples/mspm0g3507/Cargo.toml",
// "examples/mspm0g3519/Cargo.toml",
// "examples/mspm0l1306/Cargo.toml",
// "examples/mspm0l2228/Cargo.toml",
// "examples/nrf52840-rtic/Cargo.toml",
// "examples/nrf5340/Cargo.toml",
// "examples/nrf-rtos-trace/Cargo.toml",

View File

@ -15,6 +15,7 @@ Rust's <a href="https://rust-lang.github.io/async-book/">async/await</a> allows
- <a href="https://docs.embassy.dev/embassy-stm32/">embassy-stm32</a>, for all STM32 microcontroller families.
- <a href="https://docs.embassy.dev/embassy-nrf/">embassy-nrf</a>, for the Nordic Semiconductor nRF52, nRF53, nRF54 and nRF91 series.
- <a href="https://docs.embassy.dev/embassy-rp/">embassy-rp</a>, for the Raspberry Pi RP2040 and RP23xx microcontrollers.
- <a href="https://docs.embassy.dev/embassy-mspm0/">embassy-mspm0</a>, for the Texas Instruments MSPM0 microcontrollers.
- <a href="https://github.com/esp-rs">esp-rs</a>, for the Espressif Systems ESP32 series of chips.
- Embassy HAL support for Espressif chips, as well as Async WiFi, Bluetooth and ESP-NOW, is being developed in the [esp-rs/esp-hal](https://github.com/esp-rs/esp-hal) repository.
- <a href="https://github.com/ch32-rs/ch32-hal">ch32-hal</a>, for the WCH 32-bit RISC-V(CH32V) series of chips.
@ -54,11 +55,11 @@ use defmt::info;
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pin, Pull};
use embassy_nrf::Peripherals;
use embassy_nrf::{Peri, Peripherals};
// Declare async tasks
#[embassy_executor::task]
async fn blink(pin: AnyPin) {
async fn blink(pin: Peri<'static, AnyPin>) {
let mut led = Output::new(pin, Level::Low, OutputDrive::Standard);
loop {
@ -76,7 +77,7 @@ async fn main(spawner: Spawner) {
let p = embassy_nrf::init(Default::default());
// Spawned tasks run in the background, concurrently.
spawner.spawn(blink(p.P0_13.degrade())).unwrap();
spawner.spawn(blink(p.P0_13.into())).unwrap();
let mut button = Input::new(p.P0_11, Pull::Up);
loop {

14
ci.sh
View File

@ -170,6 +170,11 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u073mb,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv6m-none-eabi --features stm32u083rc,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-nxp/Cargo.toml --target thumbv8m.main-none-eabihf \
--- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0c110x,defmt,time-driver-any \
--- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g350x,defmt,time-driver-any \
--- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0g351x,defmt,time-driver-any \
--- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l130x,defmt,time-driver-any \
--- build --release --manifest-path embassy-mspm0/Cargo.toml --target thumbv6m-none-eabi --features mspm0l222x,defmt,time-driver-any \
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features ''\
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'log' \
--- build --release --manifest-path cyw43/Cargo.toml --target thumbv6m-none-eabi --features 'defmt' \
@ -239,6 +244,10 @@ cargo batch \
--- build --release --manifest-path examples/stm32wba/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/stm32wba \
--- build --release --manifest-path examples/stm32wl/Cargo.toml --target thumbv7em-none-eabi --artifact-dir out/examples/stm32wl \
--- build --release --manifest-path examples/lpc55s69/Cargo.toml --target thumbv8m.main-none-eabihf --artifact-dir out/examples/lpc55s69 \
--- build --release --manifest-path examples/mspm0g3507/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3507 \
--- build --release --manifest-path examples/mspm0g3519/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0g3519 \
--- build --release --manifest-path examples/mspm0l1306/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l1306 \
--- build --release --manifest-path examples/mspm0l2228/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0l2228 \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv7em-none-eabi --features embassy-nrf/nrf52840,skip-include --artifact-dir out/examples/boot/nrf52840 \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9160-ns,skip-include --artifact-dir out/examples/boot/nrf9160 \
--- build --release --manifest-path examples/boot/application/nrf/Cargo.toml --target thumbv8m.main-none-eabihf --features embassy-nrf/nrf9120-ns,skip-include --artifact-dir out/examples/boot/nrf9120 \
@ -303,6 +312,11 @@ cargo batch \
$BUILD_EXTRA
# MSPM0C1104 must be built seperately since cargo batch does not consider env vars set in `.cargo/config.toml`.
# Since the target has 1KB of ram, we need to limit defmt's buffer size.
DEFMT_RTT_BUFFER_SIZE="72" cargo batch \
--- build --release --manifest-path examples/mspm0c1104/Cargo.toml --target thumbv6m-none-eabi --artifact-dir out/examples/mspm0c1104 \
# temporarily disabled, these boards are dead.
rm -rf out/tests/stm32f103c8
rm -rf out/tests/nrf52840-dk

View File

@ -10,16 +10,16 @@ use embassy_rp::dma::Channel;
use embassy_rp::gpio::{Drive, Level, Output, Pull, SlewRate};
use embassy_rp::pio::program::pio_asm;
use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine};
use embassy_rp::{Peripheral, PeripheralRef};
use embassy_rp::Peri;
use fixed::types::extra::U8;
use fixed::FixedU32;
/// SPI comms driven by PIO.
pub struct PioSpi<'d, PIO: Instance, const SM: usize, DMA> {
pub struct PioSpi<'d, PIO: Instance, const SM: usize, DMA: Channel> {
cs: Output<'d>,
sm: StateMachine<'d, PIO, SM>,
irq: Irq<'d, PIO, 0>,
dma: PeripheralRef<'d, DMA>,
dma: Peri<'d, DMA>,
wrap_target: u8,
}
@ -48,20 +48,16 @@ where
PIO: Instance,
{
/// Create a new instance of PioSpi.
pub fn new<DIO, CLK>(
pub fn new(
common: &mut Common<'d, PIO>,
mut sm: StateMachine<'d, PIO, SM>,
clock_divider: FixedU32<U8>,
irq: Irq<'d, PIO, 0>,
cs: Output<'d>,
dio: DIO,
clk: CLK,
dma: impl Peripheral<P = DMA> + 'd,
) -> Self
where
DIO: PioPin,
CLK: PioPin,
{
dio: Peri<'d, impl PioPin>,
clk: Peri<'d, impl PioPin>,
dma: Peri<'d, DMA>,
) -> Self {
let loaded_program = if clock_divider < DEFAULT_CLOCK_DIVIDER {
let overclock_program = pio_asm!(
".side_set 1"
@ -146,7 +142,7 @@ where
cs,
sm,
irq,
dma: dma.into_ref(),
dma: dma,
wrap_target: loaded_program.wrap.target,
}
}

View File

@ -29,6 +29,7 @@ The Embassy project maintains HALs for select hardware, but you can still use HA
* link:https://docs.embassy.dev/embassy-stm32/[embassy-stm32], for all STM32 microcontroller families.
* link:https://docs.embassy.dev/embassy-nrf/[embassy-nrf], for the Nordic Semiconductor nRF52, nRF53, nRF91 series.
* link:https://docs.embassy.dev/embassy-rp/[embassy-rp], for the Raspberry Pi RP2040 microcontroller.
* link:https://docs.embassy.dev/embassy-mspm0/[embassy-mspm0], for the Texas Instruments MSPM0 microcontrollers.
* link:https://github.com/esp-rs[esp-rs], for the Espressif Systems ESP32 series of chips.
* link:https://github.com/ch32-rs/ch32-hal[ch32-hal], for the WCH 32-bit RISC-V(CH32V) series of chips.
* link:https://github.com/AlexCharlton/mpfs-hal[mpfs-hal], for the Microchip PolarFire SoC.

View File

@ -9,7 +9,7 @@ pub use embassy_boot::{
};
use embassy_nrf::nvmc::PAGE_SIZE;
use embassy_nrf::peripherals::WDT;
use embassy_nrf::wdt;
use embassy_nrf::{wdt, Peri};
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
/// A bootloader for nRF devices.
@ -113,7 +113,7 @@ pub struct WatchdogFlash<FLASH> {
impl<FLASH> WatchdogFlash<FLASH> {
/// Start a new watchdog with a given flash and WDT peripheral and a timeout
pub fn start(flash: FLASH, wdt: WDT, config: wdt::Config) -> Self {
pub fn start(flash: FLASH, wdt: Peri<'static, WDT>, config: wdt::Config) -> Self {
let (_wdt, [wdt]) = match wdt::Watchdog::try_new(wdt, config) {
Ok(x) => x,
Err(_) => {

View File

@ -10,6 +10,7 @@ pub use embassy_boot::{
use embassy_rp::flash::{Blocking, Flash, ERASE_SIZE};
use embassy_rp::peripherals::{FLASH, WATCHDOG};
use embassy_rp::watchdog::Watchdog;
use embassy_rp::Peri;
use embassy_time::Duration;
use embedded_storage::nor_flash::{ErrorType, NorFlash, ReadNorFlash};
@ -68,7 +69,7 @@ pub struct WatchdogFlash<'d, const SIZE: usize> {
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 {
pub fn start(flash: Peri<'static, FLASH>, watchdog: Peri<'static, WATCHDOG>, timeout: Duration) -> Self {
let flash = Flash::<_, Blocking, SIZE>::new_blocking(flash);
let mut watchdog = Watchdog::new(watchdog);
watchdog.start(timeout);

View File

@ -145,9 +145,20 @@ pub fn run(args: TokenStream, item: TokenStream) -> TokenStream {
};
#[cfg(not(feature = "nightly"))]
let mut task_outer_body = quote! {
const fn __task_pool_get<F, Args, Fut>(_: F) -> &'static #embassy_executor::raw::TaskPool<Fut, POOL_SIZE>
where
F: #embassy_executor::_export::TaskFn<Args, Fut = Fut>,
Fut: ::core::future::Future + 'static,
{
unsafe { &*POOL.get().cast() }
}
const POOL_SIZE: usize = #pool_size;
static POOL: #embassy_executor::_export::TaskPoolRef = #embassy_executor::_export::TaskPoolRef::new();
unsafe { POOL.get::<_, POOL_SIZE>()._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) }
static POOL: #embassy_executor::_export::TaskPoolHolder<
{#embassy_executor::_export::task_pool_size::<_, _, _, POOL_SIZE>(#task_inner_ident)},
{#embassy_executor::_export::task_pool_align::<_, _, _, POOL_SIZE>(#task_inner_ident)},
> = unsafe { ::core::mem::transmute(#embassy_executor::_export::task_pool_new::<_, _, _, POOL_SIZE>(#task_inner_ident)) };
unsafe { __task_pool_get(#task_inner_ident)._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) }
};
let task_outer_attrs = task_inner.attrs.clone();

View File

@ -108,98 +108,3 @@ timer-item-payload-size-2 = ["_timer-item-payload"]
timer-item-payload-size-4 = ["_timer-item-payload"]
## 8 bytes
timer-item-payload-size-8 = ["_timer-item-payload"]
#! ### Task Arena Size
#! Sets the [task arena](#task-arena) size. Necessary if youre not using `nightly`.
#!
#! <details>
#! <summary>Preconfigured Task Arena Sizes:</summary>
#! <!-- rustdoc requires the following blank line for the feature list to render correctly! -->
#!
# BEGIN AUTOGENERATED CONFIG FEATURES
# Generated by gen_config.py. DO NOT EDIT.
## 64
task-arena-size-64 = []
## 128
task-arena-size-128 = []
## 192
task-arena-size-192 = []
## 256
task-arena-size-256 = []
## 320
task-arena-size-320 = []
## 384
task-arena-size-384 = []
## 512
task-arena-size-512 = []
## 640
task-arena-size-640 = []
## 768
task-arena-size-768 = []
## 1024
task-arena-size-1024 = []
## 1280
task-arena-size-1280 = []
## 1536
task-arena-size-1536 = []
## 2048
task-arena-size-2048 = []
## 2560
task-arena-size-2560 = []
## 3072
task-arena-size-3072 = []
## 4096 (default)
task-arena-size-4096 = [] # Default
## 5120
task-arena-size-5120 = []
## 6144
task-arena-size-6144 = []
## 8192
task-arena-size-8192 = []
## 10240
task-arena-size-10240 = []
## 12288
task-arena-size-12288 = []
## 16384
task-arena-size-16384 = []
## 20480
task-arena-size-20480 = []
## 24576
task-arena-size-24576 = []
## 32768
task-arena-size-32768 = []
## 40960
task-arena-size-40960 = []
## 49152
task-arena-size-49152 = []
## 65536
task-arena-size-65536 = []
## 81920
task-arena-size-81920 = []
## 98304
task-arena-size-98304 = []
## 131072
task-arena-size-131072 = []
## 163840
task-arena-size-163840 = []
## 196608
task-arena-size-196608 = []
## 262144
task-arena-size-262144 = []
## 327680
task-arena-size-327680 = []
## 393216
task-arena-size-393216 = []
## 524288
task-arena-size-524288 = []
## 655360
task-arena-size-655360 = []
## 786432
task-arena-size-786432 = []
## 1048576
task-arena-size-1048576 = []
# END AUTOGENERATED CONFIG FEATURES
#! </details>

View File

@ -3,35 +3,10 @@
An async/await executor designed for embedded usage.
- No `alloc`, no heap needed.
- With nightly Rust, task futures can be fully statically allocated.
- Tasks are statically allocated. Each task gets its own `static`, with the exact size to hold the task (or multiple instances of it, if using `pool_size`) calculated automatically at compile time. If tasks don't fit in RAM, this is detected at compile time by the linker. Runtime panics due to running out of memory are not possible.
- No "fixed capacity" data structures, executor works with 1 or 1000 tasks without needing config/tuning.
- Integrated timer queue: sleeping is easy, just do `Timer::after_secs(1).await;`.
- No busy-loop polling: CPU sleeps when there's no work to do, using interrupts or `WFE/SEV`.
- Efficient polling: a wake will only poll the woken task, not all of them.
- Fair: a task can't monopolize CPU time even if it's constantly being woken. All other tasks get a chance to run before a given task gets polled for the second time.
- Creating multiple executor instances is supported, to run tasks with multiple priority levels. This allows higher-priority tasks to preempt lower-priority tasks.
## Task arena
When the `nightly` Cargo feature is not enabled, `embassy-executor` allocates tasks out of an arena (a very simple bump allocator).
If the task arena gets full, the program will panic at runtime. To guarantee this doesn't happen, you must set the size to the sum of sizes of all tasks.
Tasks are allocated from the arena when spawned for the first time. If the task exits, the allocation is not released to the arena, but can be reused to spawn the task again. For multiple-instance tasks (like `#[embassy_executor::task(pool_size = 4)]`), the first spawn will allocate memory for all instances. This is done for performance and to increase predictability (for example, spawning at least 1 instance of every task at boot guarantees an immediate panic if the arena is too small, while allocating instances on-demand could delay the panic to only when the program is under load).
The arena size can be configured in two ways:
- Via Cargo features: enable a Cargo feature like `task-arena-size-8192`. Only a selection of values
is available, see [Task Area Sizes](#task-arena-size) for reference.
- Via environment variables at build time: set the variable named `EMBASSY_EXECUTOR_TASK_ARENA_SIZE`. For example
`EMBASSY_EXECUTOR_TASK_ARENA_SIZE=4321 cargo build`. You can also set them in the `[env]` section of `.cargo/config.toml`.
Any value can be set, unlike with Cargo features.
Environment variables take precedence over Cargo features. If two Cargo features are enabled for the same setting
with different values, compilation fails.
## Statically allocating tasks
When using nightly Rust, enable the `nightly` Cargo feature. This will make `embassy-executor` use the `type_alias_impl_trait` feature to allocate all tasks in `static`s. Each task gets its own `static`, with the exact size to hold the task (or multiple instances of it, if using `pool_size`) calculated automatically at compile time. If tasks don't fit in RAM, this is detected at compile time by the linker. Runtime panics due to running out of memory are not possible.
The configured arena size is ignored, no arena is used at all.

View File

@ -1,99 +1,7 @@
use std::collections::HashMap;
use std::fmt::Write;
use std::path::PathBuf;
use std::{env, fs};
#[path = "./build_common.rs"]
mod common;
static CONFIGS: &[(&str, usize)] = &[
// BEGIN AUTOGENERATED CONFIG FEATURES
// Generated by gen_config.py. DO NOT EDIT.
("TASK_ARENA_SIZE", 4096),
// END AUTOGENERATED CONFIG FEATURES
];
struct ConfigState {
value: usize,
seen_feature: bool,
seen_env: bool,
}
fn main() {
let crate_name = env::var("CARGO_PKG_NAME")
.unwrap()
.to_ascii_uppercase()
.replace('-', "_");
// only rebuild if build.rs changed. Otherwise Cargo will rebuild if any
// other file changed.
println!("cargo:rerun-if-changed=build.rs");
// Rebuild if config envvar changed.
for (name, _) in CONFIGS {
println!("cargo:rerun-if-env-changed={crate_name}_{name}");
}
let mut configs = HashMap::new();
for (name, default) in CONFIGS {
configs.insert(
*name,
ConfigState {
value: *default,
seen_env: false,
seen_feature: false,
},
);
}
let prefix = format!("{crate_name}_");
for (var, value) in env::vars() {
if let Some(name) = var.strip_prefix(&prefix) {
let Some(cfg) = configs.get_mut(name) else {
panic!("Unknown env var {name}")
};
let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for env var {name}: {value}")
};
cfg.value = value;
cfg.seen_env = true;
}
if let Some(feature) = var.strip_prefix("CARGO_FEATURE_") {
if let Some(i) = feature.rfind('_') {
let name = &feature[..i];
let value = &feature[i + 1..];
if let Some(cfg) = configs.get_mut(name) {
let Ok(value) = value.parse::<usize>() else {
panic!("Invalid value for feature {name}: {value}")
};
// envvars take priority.
if !cfg.seen_env {
if cfg.seen_feature {
panic!("multiple values set for feature {}: {} and {}", name, cfg.value, value);
}
cfg.value = value;
cfg.seen_feature = true;
}
}
}
}
}
let mut data = String::new();
for (name, cfg) in &configs {
writeln!(&mut data, "pub const {}: usize = {};", name, cfg.value).unwrap();
}
let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("config.rs").to_string_lossy().to_string();
fs::write(out_file, data).unwrap();
let mut rustc_cfgs = common::CfgSet::new();
common::set_target_cfgs(&mut rustc_cfgs);
}

View File

@ -50,101 +50,155 @@ pub mod raw;
mod spawner;
pub use spawner::*;
mod config {
#![allow(unused)]
include!(concat!(env!("OUT_DIR"), "/config.rs"));
}
/// Implementation details for embassy macros.
/// Do not use. Used for macros and HALs only. Not covered by semver guarantees.
#[doc(hidden)]
#[cfg(not(feature = "nightly"))]
pub mod _export {
use core::alloc::Layout;
use core::cell::{Cell, UnsafeCell};
use core::cell::UnsafeCell;
use core::future::Future;
use core::mem::MaybeUninit;
use core::ptr::null_mut;
use critical_section::{CriticalSection, Mutex};
use crate::raw::TaskPool;
struct Arena<const N: usize> {
buf: UnsafeCell<MaybeUninit<[u8; N]>>,
ptr: Mutex<Cell<*mut u8>>,
pub trait TaskFn<Args>: Copy {
type Fut: Future + 'static;
}
unsafe impl<const N: usize> Sync for Arena<N> {}
unsafe impl<const N: usize> Send for Arena<N> {}
impl<const N: usize> Arena<N> {
const fn new() -> Self {
Self {
buf: UnsafeCell::new(MaybeUninit::uninit()),
ptr: Mutex::new(Cell::new(null_mut())),
macro_rules! task_fn_impl {
($($Tn:ident),*) => {
impl<F, Fut, $($Tn,)*> TaskFn<($($Tn,)*)> for F
where
F: Copy + FnOnce($($Tn,)*) -> Fut,
Fut: Future + 'static,
{
type Fut = Fut;
}
}
};
}
fn alloc<T>(&'static self, cs: CriticalSection) -> &'static mut MaybeUninit<T> {
let layout = Layout::new::<T>();
task_fn_impl!();
task_fn_impl!(T0);
task_fn_impl!(T0, T1);
task_fn_impl!(T0, T1, T2);
task_fn_impl!(T0, T1, T2, T3);
task_fn_impl!(T0, T1, T2, T3, T4);
task_fn_impl!(T0, T1, T2, T3, T4, T5);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
task_fn_impl!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);
let start = self.buf.get().cast::<u8>();
let end = unsafe { start.add(N) };
#[allow(private_bounds)]
#[repr(C)]
pub struct TaskPoolHolder<const SIZE: usize, const ALIGN: usize>
where
Align<ALIGN>: Alignment,
{
data: UnsafeCell<[MaybeUninit<u8>; SIZE]>,
align: Align<ALIGN>,
}
let mut ptr = self.ptr.borrow(cs).get();
if ptr.is_null() {
ptr = self.buf.get().cast::<u8>();
}
unsafe impl<const SIZE: usize, const ALIGN: usize> Send for TaskPoolHolder<SIZE, ALIGN> where Align<ALIGN>: Alignment {}
unsafe impl<const SIZE: usize, const ALIGN: usize> Sync for TaskPoolHolder<SIZE, ALIGN> where Align<ALIGN>: Alignment {}
let bytes_left = (end as usize) - (ptr as usize);
let align_offset = (ptr as usize).next_multiple_of(layout.align()) - (ptr as usize);
if align_offset + layout.size() > bytes_left {
panic!("embassy-executor: task arena is full. You must increase the arena size, see the documentation for details: https://docs.embassy.dev/embassy-executor/");
}
let res = unsafe { ptr.add(align_offset) };
let ptr = unsafe { ptr.add(align_offset + layout.size()) };
self.ptr.borrow(cs).set(ptr);
unsafe { &mut *(res as *mut MaybeUninit<T>) }
#[allow(private_bounds)]
impl<const SIZE: usize, const ALIGN: usize> TaskPoolHolder<SIZE, ALIGN>
where
Align<ALIGN>: Alignment,
{
pub const fn get(&self) -> *const u8 {
self.data.get().cast()
}
}
static ARENA: Arena<{ crate::config::TASK_ARENA_SIZE }> = Arena::new();
pub struct TaskPoolRef {
// type-erased `&'static mut TaskPool<F, N>`
// Needed because statics can't have generics.
ptr: Mutex<Cell<*mut ()>>,
pub const fn task_pool_size<F, Args, Fut, const POOL_SIZE: usize>(_: F) -> usize
where
F: TaskFn<Args, Fut = Fut>,
Fut: Future + 'static,
{
size_of::<TaskPool<Fut, POOL_SIZE>>()
}
unsafe impl Sync for TaskPoolRef {}
unsafe impl Send for TaskPoolRef {}
impl TaskPoolRef {
pub const fn new() -> Self {
Self {
ptr: Mutex::new(Cell::new(null_mut())),
}
}
pub const fn task_pool_align<F, Args, Fut, const POOL_SIZE: usize>(_: F) -> usize
where
F: TaskFn<Args, Fut = Fut>,
Fut: Future + 'static,
{
align_of::<TaskPool<Fut, POOL_SIZE>>()
}
/// Get the pool for this ref, allocating it from the arena the first time.
///
/// safety: for a given TaskPoolRef instance, must always call with the exact
/// same generic params.
pub unsafe fn get<F: Future, const N: usize>(&'static self) -> &'static TaskPool<F, N> {
critical_section::with(|cs| {
let ptr = self.ptr.borrow(cs);
if ptr.get().is_null() {
let pool = ARENA.alloc::<TaskPool<F, N>>(cs);
pool.write(TaskPool::new());
ptr.set(pool as *mut _ as _);
pub const fn task_pool_new<F, Args, Fut, const POOL_SIZE: usize>(_: F) -> TaskPool<Fut, POOL_SIZE>
where
F: TaskFn<Args, Fut = Fut>,
Fut: Future + 'static,
{
TaskPool::new()
}
#[allow(private_bounds)]
#[repr(transparent)]
pub struct Align<const N: usize>([<Self as Alignment>::Archetype; 0])
where
Self: Alignment;
trait Alignment {
/// A zero-sized type of particular alignment.
type Archetype: Copy + Eq + PartialEq + Send + Sync + Unpin;
}
macro_rules! aligns {
($($AlignX:ident: $n:literal,)*) => {
$(
#[derive(Copy, Clone, Eq, PartialEq)]
#[repr(align($n))]
struct $AlignX {}
impl Alignment for Align<$n> {
type Archetype = $AlignX;
}
unsafe { &*(ptr.get() as *const _) }
})
}
)*
};
}
aligns!(
Align1: 1,
Align2: 2,
Align4: 4,
Align8: 8,
Align16: 16,
Align32: 32,
Align64: 64,
Align128: 128,
Align256: 256,
Align512: 512,
Align1024: 1024,
Align2048: 2048,
Align4096: 4096,
Align8192: 8192,
Align16384: 16384,
);
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
aligns!(
Align32768: 32768,
Align65536: 65536,
Align131072: 131072,
Align262144: 262144,
Align524288: 524288,
Align1048576: 1048576,
Align2097152: 2097152,
Align4194304: 4194304,
Align8388608: 8388608,
Align16777216: 16777216,
Align33554432: 33554432,
Align67108864: 67108864,
Align134217728: 134217728,
Align268435456: 268435456,
Align536870912: 536870912,
);
}

View File

@ -19,5 +19,6 @@ fn ui() {
t.compile_fail("tests/ui/not_async.rs");
t.compile_fail("tests/ui/self_ref.rs");
t.compile_fail("tests/ui/self.rs");
t.compile_fail("tests/ui/type_error.rs");
t.compile_fail("tests/ui/where_clause.rs");
}

View File

@ -0,0 +1,8 @@
#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))]
#[embassy_executor::task]
async fn task() {
5
}
fn main() {}

View File

@ -0,0 +1,7 @@
error[E0308]: mismatched types
--> tests/ui/type_error.rs:5:5
|
4 | async fn task() {
| - help: try adding a return type: `-> i32`
5 | 5
| ^ expected `()`, found integer

View File

@ -11,7 +11,7 @@ pub mod drop;
mod macros;
mod peripheral;
pub mod ratio;
pub use peripheral::{Peripheral, PeripheralRef};
pub use peripheral::{Peri, PeripheralType};
#[cfg(feature = "cortex-m")]
pub mod interrupt;

View File

@ -18,8 +18,8 @@ macro_rules! peripherals_definition {
///
/// You must ensure that you're only using one instance of this type at a time.
#[inline]
pub unsafe fn steal() -> Self {
Self{ _private: ()}
pub unsafe fn steal() -> $crate::Peri<'static, Self> {
$crate::Peri::new_unchecked(Self{ _private: ()})
}
}
@ -42,7 +42,7 @@ macro_rules! peripherals_struct {
$(
#[doc = concat!(stringify!($name), " peripheral")]
$(#[$cfg])?
pub $name: peripherals::$name,
pub $name: $crate::Peri<'static, peripherals::$name>,
)*
}
@ -108,28 +108,26 @@ macro_rules! peripherals {
};
}
/// Convenience converting into reference.
#[macro_export]
macro_rules! into_ref {
($($name:ident),*) => {
$(
let mut $name = $name.into_ref();
)*
}
}
/// Implement the peripheral trait.
#[macro_export]
macro_rules! impl_peripheral {
($type:ident) => {
impl $crate::Peripheral for $type {
type P = $type;
#[inline]
unsafe fn clone_unchecked(&self) -> Self::P {
#[allow(clippy::needless_update)]
$type { ..*self }
($type:ident<$($T:ident $(: $bound:tt $(+ $others:tt )*)?),*>) => {
impl<$($T: $($bound $(+$others)*)?),*> Copy for $type <$($T),*> {}
impl<$($T: $($bound $(+$others)*)?),*> Clone for $type <$($T),*> {
fn clone(&self) -> Self {
*self
}
}
impl<$($T: $($bound $(+$others)*)?),*> PeripheralType for $type <$($T),*> {}
};
($type:ident) => {
impl Copy for $type {}
impl Clone for $type {
fn clone(&self) -> Self {
*self
}
}
impl $crate::PeripheralType for $type {}
};
}

View File

@ -1,5 +1,5 @@
use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
use core::ops::Deref;
/// An exclusive reference to a peripheral.
///
@ -9,20 +9,26 @@ use core::ops::{Deref, DerefMut};
/// - Memory efficiency: Peripheral singletons are typically either zero-sized (for concrete
/// peripherals like `PA9` or `SPI4`) or very small (for example `AnyPin`, which is 1 byte).
/// However `&mut T` is always 4 bytes for 32-bit targets, even if T is zero-sized.
/// PeripheralRef stores a copy of `T` instead, so it's the same size.
/// Peripheral stores a copy of `T` instead, so it's the same size.
/// - Code size efficiency. If the user uses the same driver with both `SPI4` and `&mut SPI4`,
/// the driver code would be monomorphized two times. With PeripheralRef, the driver is generic
/// over a lifetime only. `SPI4` becomes `PeripheralRef<'static, SPI4>`, and `&mut SPI4` becomes
/// `PeripheralRef<'a, SPI4>`. Lifetimes don't cause monomorphization.
pub struct PeripheralRef<'a, T> {
/// the driver code would be monomorphized two times. With Peri, the driver is generic
/// over a lifetime only. `SPI4` becomes `Peri<'static, SPI4>`, and `&mut SPI4` becomes
/// `Peri<'a, SPI4>`. Lifetimes don't cause monomorphization.
pub struct Peri<'a, T: PeripheralType> {
inner: T,
_lifetime: PhantomData<&'a mut T>,
}
impl<'a, T> PeripheralRef<'a, T> {
/// Create a new reference to a peripheral.
impl<'a, T: PeripheralType> Peri<'a, T> {
/// Create a new owned a peripheral.
///
/// For use by HALs only.
///
/// If you're an end user you shouldn't use this, you should use `steal()`
/// on the actual peripheral types instead.
#[inline]
pub fn new(inner: T) -> Self {
#[doc(hidden)]
pub unsafe fn new_unchecked(inner: T) -> Self {
Self {
inner,
_lifetime: PhantomData,
@ -38,46 +44,38 @@ impl<'a, T> PeripheralRef<'a, T> {
/// create two SPI drivers on `SPI1`, because they will "fight" each other.
///
/// You should strongly prefer using `reborrow()` instead. It returns a
/// `PeripheralRef` that borrows `self`, which allows the borrow checker
/// `Peri` that borrows `self`, which allows the borrow checker
/// to enforce this at compile time.
pub unsafe fn clone_unchecked(&self) -> PeripheralRef<'a, T>
where
T: Peripheral<P = T>,
{
PeripheralRef::new(self.inner.clone_unchecked())
pub unsafe fn clone_unchecked(&self) -> Peri<'a, T> {
Peri::new_unchecked(self.inner)
}
/// Reborrow into a "child" PeripheralRef.
/// Reborrow into a "child" Peri.
///
/// `self` will stay borrowed until the child PeripheralRef is dropped.
pub fn reborrow(&mut self) -> PeripheralRef<'_, T>
where
T: Peripheral<P = T>,
{
// safety: we're returning the clone inside a new PeripheralRef that borrows
/// `self` will stay borrowed until the child Peripheral is dropped.
pub fn reborrow(&mut self) -> Peri<'_, T> {
// safety: we're returning the clone inside a new Peripheral that borrows
// self, so user code can't use both at the same time.
PeripheralRef::new(unsafe { self.inner.clone_unchecked() })
unsafe { self.clone_unchecked() }
}
/// Map the inner peripheral using `Into`.
///
/// This converts from `PeripheralRef<'a, T>` to `PeripheralRef<'a, U>`, using an
/// This converts from `Peri<'a, T>` to `Peri<'a, U>`, using an
/// `Into` impl to convert from `T` to `U`.
///
/// For example, this can be useful to degrade GPIO pins: converting from PeripheralRef<'a, PB11>` to `PeripheralRef<'a, AnyPin>`.
/// For example, this can be useful to.into() GPIO pins: converting from Peri<'a, PB11>` to `Peri<'a, AnyPin>`.
#[inline]
pub fn map_into<U>(self) -> PeripheralRef<'a, U>
pub fn into<U>(self) -> Peri<'a, U>
where
T: Into<U>,
U: PeripheralType,
{
PeripheralRef {
inner: self.inner.into(),
_lifetime: PhantomData,
}
unsafe { Peri::new_unchecked(self.inner.into()) }
}
}
impl<'a, T> Deref for PeripheralRef<'a, T> {
impl<'a, T: PeripheralType> Deref for Peri<'a, T> {
type Target = T;
#[inline]
@ -86,92 +84,5 @@ impl<'a, T> Deref for PeripheralRef<'a, T> {
}
}
/// Trait for any type that can be used as a peripheral of type `P`.
///
/// This is used in driver constructors, to allow passing either owned peripherals (e.g. `TWISPI0`),
/// or borrowed peripherals (e.g. `&mut TWISPI0`).
///
/// For example, if you have a driver with a constructor like this:
///
/// ```ignore
/// impl<'d, T: Instance> Twim<'d, T> {
/// pub fn new(
/// twim: impl Peripheral<P = T> + 'd,
/// irq: impl Peripheral<P = T::Interrupt> + 'd,
/// sda: impl Peripheral<P = impl GpioPin> + 'd,
/// scl: impl Peripheral<P = impl GpioPin> + 'd,
/// config: Config,
/// ) -> Self { .. }
/// }
/// ```
///
/// You may call it with owned peripherals, which yields an instance that can live forever (`'static`):
///
/// ```ignore
/// let mut twi: Twim<'static, ...> = Twim::new(p.TWISPI0, irq, p.P0_03, p.P0_04, config);
/// ```
///
/// Or you may call it with borrowed peripherals, which yields an instance that can only live for as long
/// as the borrows last:
///
/// ```ignore
/// let mut twi: Twim<'_, ...> = Twim::new(&mut p.TWISPI0, &mut irq, &mut p.P0_03, &mut p.P0_04, config);
/// ```
///
/// # Implementation details, for HAL authors
///
/// When writing a HAL, the intended way to use this trait is to take `impl Peripheral<P = ..>` in
/// the HAL's public API (such as driver constructors), calling `.into_ref()` to obtain a `PeripheralRef`,
/// and storing that in the driver struct.
///
/// `.into_ref()` on an owned `T` yields a `PeripheralRef<'static, T>`.
/// `.into_ref()` on an `&'a mut T` yields a `PeripheralRef<'a, T>`.
pub trait Peripheral: Sized {
/// Peripheral singleton type
type P;
/// Unsafely clone (duplicate) a peripheral singleton.
///
/// # Safety
///
/// This returns an owned clone of the peripheral. You must manually ensure
/// only one copy of the peripheral is in use at a time. For example, don't
/// create two SPI drivers on `SPI1`, because they will "fight" each other.
///
/// You should strongly prefer using `into_ref()` instead. It returns a
/// `PeripheralRef`, which allows the borrow checker to enforce this at compile time.
unsafe fn clone_unchecked(&self) -> Self::P;
/// Convert a value into a `PeripheralRef`.
///
/// When called on an owned `T`, yields a `PeripheralRef<'static, T>`.
/// When called on an `&'a mut T`, yields a `PeripheralRef<'a, T>`.
#[inline]
fn into_ref<'a>(self) -> PeripheralRef<'a, Self::P>
where
Self: 'a,
{
PeripheralRef::new(unsafe { self.clone_unchecked() })
}
}
impl<'b, T: DerefMut> Peripheral for T
where
T::Target: Peripheral,
{
type P = <T::Target as Peripheral>::P;
#[inline]
unsafe fn clone_unchecked(&self) -> Self::P {
T::Target::clone_unchecked(self)
}
}
impl<'b, T: Peripheral> Peripheral for PeripheralRef<'_, T> {
type P = T::P;
#[inline]
unsafe fn clone_unchecked(&self) -> Self::P {
T::clone_unchecked(self)
}
}
/// Marker trait for peripheral types.
pub trait PeripheralType: Copy + Sized {}

132
embassy-mspm0/Cargo.toml Normal file
View File

@ -0,0 +1,132 @@
[package]
name = "embassy-mspm0"
version = "0.1.0"
edition = "2021"
license = "MIT OR Apache-2.0"
description = "Embassy Hardware Abstraction Layer (HAL) for Texas Instruments MSPM0 series microcontrollers"
keywords = ["embedded", "async", "mspm0", "hal", "embedded-hal"]
categories = ["embedded", "hardware-support", "no-std", "asynchronous"]
repository = "https://github.com/embassy-rs/embassy"
documentation = "https://docs.embassy.dev/embassy-mspm0"
[package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-mspm0-v$VERSION/embassy-mspm0/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-mspm0/src/"
features = ["defmt", "unstable-pac", "time-driver-any"]
flavors = [
{ regex_feature = "mspm0c.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "mspm0l.*", target = "thumbv6m-none-eabi" },
{ regex_feature = "mspm0g.*", target = "thumbv6m-none-eabi" },
]
[package.metadata.docs.rs]
features = ["defmt", "unstable-pac", "time-driver-any", "time", "mspm0g3507"]
rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
embassy-sync = { version = "0.6.2", path = "../embassy-sync" }
embassy-time = { version = "0.4.0", path = "../embassy-time", optional = true }
# TODO: Support other tick rates
embassy-time-driver = { version = "0.2", path = "../embassy-time-driver", optional = true, features = ["tick-hz-32_768"] }
embassy-time-queue-utils = { version = "0.1", path = "../embassy-time-queue-utils", optional = true }
embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
embassy-hal-internal = { version = "0.2.0", path = "../embassy-hal-internal", features = ["cortex-m", "prio-bits-2"] }
embassy-embedded-hal = { version = "0.3.0", path = "../embassy-embedded-hal", default-features = false }
embassy-executor = { version = "0.7.0", path = "../embassy-executor", optional = true }
embedded-hal = { version = "1.0" }
embedded-hal-async = { version = "1.0" }
defmt = { version = "0.3", optional = true }
log = { version = "0.4.14", optional = true }
cortex-m-rt = ">=0.6.15,<0.8"
cortex-m = "0.7.6"
critical-section = "1.2.0"
# mspm0-metapac = { version = "" }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a" }
[build-dependencies]
proc-macro2 = "1.0.94"
quote = "1.0.40"
# mspm0-metapac = { version = "", default-features = false, features = ["metadata"] }
mspm0-metapac = { git = "https://github.com/mspm0-rs/mspm0-data-generated/", tag = "mspm0-data-119240dd23ef5748d2a7bef219ca298d37ba604a", default-features = false, features = ["metadata"] }
[features]
default = ["rt"]
## Enable `mspm0-metapac`'s `rt` feature
rt = ["mspm0-metapac/rt"]
## Use [`defmt`](https://docs.rs/defmt/latest/defmt/) for logging
defmt = [
"dep:defmt",
"embassy-sync/defmt",
"embassy-embedded-hal/defmt",
"embassy-hal-internal/defmt",
"embassy-time?/defmt",
]
## Re-export mspm0-metapac at `mspm0::pac`.
## This is unstable because semver-minor (non-breaking) releases of embassy-mspm0 may major-bump (breaking) the mspm0-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 = []
#! ## 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 = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"]
# Use any time driver
time-driver-any = ["_time-driver"]
## Use TIMG0 as time driver
time-driver-timg0 = ["_time-driver"]
## Use TIMG1 as time driver
time-driver-timg1 = ["_time-driver"]
## Use TIMG2 as time driver
time-driver-timg2 = ["_time-driver"]
## Use TIMG3 as time driver
time-driver-timg3 = ["_time-driver"]
## Use TIMG4 as time driver
time-driver-timg4 = ["_time-driver"]
## Use TIMG5 as time driver
time-driver-timg5 = ["_time-driver"]
## Use TIMG6 as time driver
time-driver-timg6 = ["_time-driver"]
## Use TIMG7 as time driver
time-driver-timg7 = ["_time-driver"]
## Use TIMG8 as time driver
time-driver-timg8 = ["_time-driver"]
## Use TIMG9 as time driver
time-driver-timg9 = ["_time-driver"]
## Use TIMG10 as time driver
time-driver-timg10 = ["_time-driver"]
## Use TIMG11 as time driver
time-driver-timg11 = ["_time-driver"]
## Use TIMG12 as time driver
time-driver-timg12 = ["_time-driver"]
## Use TIMG13 as time driver
time-driver-timg13 = ["_time-driver"]
## Use TIMG14 as time driver
time-driver-timg14 = ["_time-driver"]
## Use TIMA0 as time driver
time-driver-tima0 = ["_time-driver"]
## Use TIMA1 as time driver
time-driver-tima1 = ["_time-driver"]
#! ## Chip-selection features
#! Select your chip by specifying the model as a feature, e.g. `mspm0g350x`.
#! 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`.
mspm0c110x = [ "mspm0-metapac/mspm0c110x" ]
mspm0g350x = [ "mspm0-metapac/mspm0g350x" ]
mspm0g351x = [ "mspm0-metapac/mspm0g351x" ]
mspm0l130x = [ "mspm0-metapac/mspm0l130x" ]
mspm0l222x = [ "mspm0-metapac/mspm0l222x" ]

802
embassy-mspm0/build.rs Normal file
View File

@ -0,0 +1,802 @@
use std::cmp::Ordering;
use std::collections::{BTreeSet, HashMap};
use std::io::Write;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::sync::LazyLock;
use std::{env, fs};
use common::CfgSet;
use mspm0_metapac::metadata::METADATA;
use proc_macro2::{Ident, Literal, Span, TokenStream};
use quote::{format_ident, quote};
#[path = "./build_common.rs"]
mod common;
fn main() {
generate_code();
}
fn generate_code() {
let mut cfgs = common::CfgSet::new();
common::set_target_cfgs(&mut cfgs);
cfgs.declare_all(&["gpio_pb", "gpio_pc", "int_group1"]);
let mut singletons = get_singletons(&mut cfgs);
time_driver(&mut singletons, &mut cfgs);
let mut g = TokenStream::new();
g.extend(generate_singletons(&singletons));
g.extend(generate_pincm_mapping());
g.extend(generate_pin());
g.extend(generate_timers());
g.extend(generate_interrupts());
g.extend(generate_peripheral_instances());
g.extend(generate_pin_trait_impls());
let out_dir = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
let out_file = out_dir.join("_generated.rs").to_string_lossy().to_string();
fs::write(&out_file, g.to_string()).unwrap();
rustfmt(&out_file);
}
#[derive(Debug, Clone)]
struct Singleton {
name: String,
cfg: Option<TokenStream>,
}
impl PartialEq for Singleton {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
impl Eq for Singleton {}
impl PartialOrd for Singleton {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Singleton {
fn cmp(&self, other: &Self) -> Ordering {
self.name.cmp(&other.name)
}
}
fn get_singletons(cfgs: &mut common::CfgSet) -> Vec<Singleton> {
let mut singletons = Vec::<Singleton>::new();
for peripheral in METADATA.peripherals {
// Some peripherals do not generate a singleton, but generate a singleton for each pin.
let skip_peripheral_singleton = match peripheral.kind {
"gpio" => {
// Also enable ports that are present.
match peripheral.name {
"GPIOB" => cfgs.enable("gpio_pb"),
"GPIOC" => cfgs.enable("gpio_pc"),
_ => (),
}
true
}
// Each channel gets a singleton, handled separately.
"dma" => true,
// These peripherals do not exist as singletons, and have no signals but are managed
// by the HAL.
"iomux" | "cpuss" => true,
_ => false,
};
if !skip_peripheral_singleton {
singletons.push(Singleton {
name: peripheral.name.to_string(),
cfg: None,
});
}
let mut signals = BTreeSet::new();
// Pick out each unique signal. There may be multiple instances of each signal due to
// iomux mappings.
for pin in peripheral.pins {
let signal = if peripheral.name.starts_with("GPIO")
|| peripheral.name.starts_with("VREF")
|| peripheral.name.starts_with("RTC")
{
pin.signal.to_string()
} else {
format!("{}_{}", peripheral.name, pin.signal)
};
// We need to rename some signals to become valid Rust identifiers.
let signal = make_valid_identifier(&signal);
signals.insert(signal);
}
singletons.extend(signals);
}
// DMA channels get their own singletons
for dma_channel in METADATA.dma_channels.iter() {
singletons.push(Singleton {
name: format!("DMA_CH{}", dma_channel.number),
cfg: None,
});
}
singletons.sort_by(|a, b| a.name.cmp(&b.name));
singletons
}
fn make_valid_identifier(s: &str) -> Singleton {
let name = s.replace('+', "_P").replace("-", "_N");
Singleton { name, cfg: None }
}
fn generate_pincm_mapping() -> TokenStream {
let pincms = METADATA.pincm_mappings.iter().map(|mapping| {
let port_letter = mapping.pin.strip_prefix("P").unwrap();
let port_base = (port_letter.chars().next().unwrap() as u8 - b'A') * 32;
// This assumes all ports are single letter length.
// This is fine unless TI releases a part with 833+ GPIO pins.
let pin_number = mapping.pin[2..].parse::<u8>().unwrap();
let num = port_base + pin_number;
// But subtract 1 since pincm indices start from 0, not 1.
let pincm = Literal::u8_unsuffixed(mapping.pincm - 1);
quote! {
#num => #pincm
}
});
quote! {
#[doc = "Get the mapping from GPIO pin port to IOMUX PINCM index. This is required since the mapping from IO to PINCM index is not consistent across parts."]
pub(crate) fn gpio_pincm(pin_port: u8) -> u8 {
match pin_port {
#(#pincms),*,
_ => unreachable!(),
}
}
}
}
fn generate_pin() -> TokenStream {
let pin_impls = METADATA.pincm_mappings.iter().map(|pincm_mapping| {
let name = Ident::new(&pincm_mapping.pin, Span::call_site());
let port_letter = pincm_mapping.pin.strip_prefix("P").unwrap();
let port_letter = port_letter.chars().next().unwrap();
let pin_number = Literal::u8_unsuffixed(pincm_mapping.pin[2..].parse::<u8>().unwrap());
let port = Ident::new(&format!("Port{}", port_letter), Span::call_site());
// TODO: Feature gate pins that can be used as NRST
quote! {
impl_pin!(#name, crate::gpio::Port::#port, #pin_number);
}
});
quote! {
#(#pin_impls)*
}
}
fn time_driver(singletons: &mut Vec<Singleton>, cfgs: &mut CfgSet) {
// Timer features
for (timer, _) in TIMERS.iter() {
let name = timer.to_lowercase();
cfgs.declare(&format!("time_driver_{}", name));
}
let time_driver = match env::vars()
.map(|(a, _)| a)
.filter(|x| x.starts_with("CARGO_FEATURE_TIME_DRIVER_"))
.get_one()
{
Ok(x) => Some(
x.strip_prefix("CARGO_FEATURE_TIME_DRIVER_")
.unwrap()
.to_ascii_lowercase(),
),
Err(GetOneError::None) => None,
Err(GetOneError::Multiple) => panic!("Multiple time-driver-xxx Cargo features enabled"),
};
// Verify the selected timer is available
let selected_timer = match time_driver.as_ref().map(|x| x.as_ref()) {
None => "",
Some("timg0") => "TIMG0",
Some("timg1") => "TIMG1",
Some("timg2") => "TIMG2",
Some("timg3") => "TIMG3",
Some("timg4") => "TIMG4",
Some("timg5") => "TIMG5",
Some("timg6") => "TIMG6",
Some("timg7") => "TIMG7",
Some("timg8") => "TIMG8",
Some("timg9") => "TIMG9",
Some("timg10") => "TIMG10",
Some("timg11") => "TIMG11",
Some("timg14") => "TIMG14",
Some("tima0") => "TIMA0",
Some("tima1") => "TIMA1",
Some("any") => {
// Order of timer candidates:
// 1. 16-bit, 2 channel
// 2. 16-bit, 2 channel with shadow registers
// 3. 16-bit, 4 channel
// 4. 16-bit with QEI
// 5. Advanced timers
//
// TODO: Select RTC first if available
// TODO: 32-bit timers are not considered yet
[
// 16-bit, 2 channel
"TIMG0", "TIMG1", "TIMG2", "TIMG3", // 16-bit, 2 channel with shadow registers
"TIMG4", "TIMG5", "TIMG6", "TIMG7", // 16-bit, 4 channel
"TIMG14", // 16-bit with QEI
"TIMG8", "TIMG9", "TIMG10", "TIMG11", // Advanced timers
"TIMA0", "TIMA1",
]
.iter()
.find(|tim| singletons.iter().any(|s| s.name == **tim))
.expect("Could not find any timer")
}
_ => panic!("unknown time_driver {:?}", time_driver),
};
if !selected_timer.is_empty() {
cfgs.enable(format!("time_driver_{}", selected_timer.to_lowercase()));
}
// Apply cfgs to each timer and it's pins
for singleton in singletons.iter_mut() {
if singleton.name.starts_with("TIM") {
// Remove suffixes for pin singletons.
let name = if singleton.name.contains("_CCP") {
singleton.name.split_once("_CCP").unwrap().0
} else if singleton.name.contains("_FAULT") {
singleton.name.split_once("_FAULT").unwrap().0
} else if singleton.name.contains("_IDX") {
singleton.name.split_once("_IDX").unwrap().0
} else {
&singleton.name
};
let feature = format!("time-driver-{}", name.to_lowercase());
if singleton.name.contains(selected_timer) {
singleton.cfg = Some(quote! { #[cfg(not(all(feature = "time-driver-any", feature = #feature)))] });
} else {
singleton.cfg = Some(quote! { #[cfg(not(feature = #feature))] });
}
}
}
}
fn generate_singletons(singletons: &[Singleton]) -> TokenStream {
let singletons = singletons
.iter()
.map(|s| {
let cfg = s.cfg.clone().unwrap_or_default();
let ident = format_ident!("{}", s.name);
quote! {
#cfg
#ident
}
})
.collect::<Vec<_>>();
quote! {
embassy_hal_internal::peripherals_definition!(#(#singletons),*);
embassy_hal_internal::peripherals_struct!(#(#singletons),*);
}
}
fn generate_timers() -> TokenStream {
// Generate timers
let timer_impls = METADATA
.peripherals
.iter()
.filter(|p| p.name.starts_with("TIM"))
.map(|peripheral| {
let name = Ident::new(&peripheral.name, Span::call_site());
let timers = &*TIMERS;
let timer = timers.get(peripheral.name).expect("Timer does not exist");
assert!(timer.bits == 16 || timer.bits == 32);
let bits = if timer.bits == 16 {
quote! { Bits16 }
} else {
quote! { Bits32 }
};
quote! {
impl_timer!(#name, #bits);
}
});
quote! {
#(#timer_impls)*
}
}
fn generate_interrupts() -> TokenStream {
// Generate interrupt module
let interrupts: Vec<Ident> = METADATA
.interrupts
.iter()
.map(|interrupt| Ident::new(interrupt.name, Span::call_site()))
.collect();
let group_interrupt_enables = METADATA
.interrupts
.iter()
.filter(|interrupt| interrupt.name.contains("GROUP"))
.map(|interrupt| {
let name = Ident::new(interrupt.name, Span::call_site());
quote! {
crate::interrupt::typelevel::#name::enable();
}
});
// Generate interrupt enables for groups
quote! {
embassy_hal_internal::interrupt_mod! {
#(#interrupts),*
}
pub fn enable_group_interrupts(_cs: critical_section::CriticalSection) {
use crate::interrupt::typelevel::Interrupt;
unsafe {
#(#group_interrupt_enables)*
}
}
}
}
fn generate_peripheral_instances() -> TokenStream {
let mut impls = Vec::<TokenStream>::new();
for peripheral in METADATA.peripherals {
let peri = format_ident!("{}", peripheral.name);
// Will be filled in when uart implementation is finished
let _ = peri;
let tokens = match peripheral.kind {
// "uart" => Some(quote! { impl_uart_instance!(#peri); }),
_ => None,
};
if let Some(tokens) = tokens {
impls.push(tokens);
}
}
quote! {
#(#impls)*
}
}
fn generate_pin_trait_impls() -> TokenStream {
let mut impls = Vec::<TokenStream>::new();
for peripheral in METADATA.peripherals {
for pin in peripheral.pins {
let key = (peripheral.kind, pin.signal);
let pin_name = format_ident!("{}", pin.pin);
let peri = format_ident!("{}", peripheral.name);
let pf = pin.pf;
// Will be filled in when uart implementation is finished
let _ = pin_name;
let _ = peri;
let _ = pf;
let tokens = match key {
// ("uart", "TX") => Some(quote! { impl_uart_tx_pin!(#peri, #pin_name, #pf); }),
// ("uart", "RX") => Some(quote! { impl_uart_rx_pin!(#peri, #pin_name, #pf); }),
// ("uart", "CTS") => Some(quote! { impl_uart_cts_pin!(#peri, #pin_name, #pf); }),
// ("uart", "RTS") => Some(quote! { impl_uart_rts_pin!(#peri, #pin_name, #pf); }),
_ => None,
};
if let Some(tokens) = tokens {
impls.push(tokens);
}
}
}
quote! {
#(#impls)*
}
}
/// rustfmt a given path.
/// Failures are logged to stderr and ignored.
fn rustfmt(path: impl AsRef<Path>) {
let path = path.as_ref();
match Command::new("rustfmt").args([path]).output() {
Err(e) => {
eprintln!("failed to exec rustfmt {:?}: {:?}", path, e);
}
Ok(out) => {
if !out.status.success() {
eprintln!("rustfmt {:?} failed:", path);
eprintln!("=== STDOUT:");
std::io::stderr().write_all(&out.stdout).unwrap();
eprintln!("=== STDERR:");
std::io::stderr().write_all(&out.stderr).unwrap();
}
}
}
}
#[allow(dead_code)]
struct TimerDesc {
bits: u8,
/// Is there an 8-bit prescaler
prescaler: bool,
/// Is there a repeat counter
repeat_counter: bool,
ccp_channels_internal: u8,
ccp_channels_external: u8,
external_pwm_channels: u8,
phase_load: bool,
shadow_load: bool,
shadow_ccs: bool,
deadband: bool,
fault_handler: bool,
qei_hall: bool,
}
/// Description of all timer instances.
const TIMERS: LazyLock<HashMap<String, TimerDesc>> = LazyLock::new(|| {
let mut map = HashMap::new();
map.insert(
"TIMG0".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG1".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG2".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG3".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG4".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: true,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG5".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: true,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG6".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: true,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG7".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: true,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG8".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: true,
},
);
map.insert(
"TIMG9".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: true,
},
);
map.insert(
"TIMG10".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: true,
},
);
map.insert(
"TIMG11".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: true,
},
);
map.insert(
"TIMG12".into(),
TimerDesc {
bits: 32,
prescaler: false,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG13".into(),
TimerDesc {
bits: 32,
prescaler: false,
repeat_counter: false,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 2,
phase_load: false,
shadow_load: false,
shadow_ccs: true,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMG14".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: false,
ccp_channels_internal: 4,
ccp_channels_external: 4,
external_pwm_channels: 4,
phase_load: false,
shadow_load: false,
shadow_ccs: false,
deadband: false,
fault_handler: false,
qei_hall: false,
},
);
map.insert(
"TIMA0".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: true,
ccp_channels_internal: 4,
ccp_channels_external: 2,
external_pwm_channels: 8,
phase_load: true,
shadow_load: true,
shadow_ccs: true,
deadband: true,
fault_handler: true,
qei_hall: false,
},
);
map.insert(
"TIMA1".into(),
TimerDesc {
bits: 16,
prescaler: true,
repeat_counter: true,
ccp_channels_internal: 2,
ccp_channels_external: 2,
external_pwm_channels: 4,
phase_load: true,
shadow_load: true,
shadow_ccs: true,
deadband: true,
fault_handler: true,
qei_hall: false,
},
);
map
});
enum GetOneError {
None,
Multiple,
}
trait IteratorExt: Iterator {
fn get_one(self) -> Result<Self::Item, GetOneError>;
}
impl<T: Iterator> IteratorExt for T {
fn get_one(mut self) -> Result<Self::Item, GetOneError> {
match self.next() {
None => Err(GetOneError::None),
Some(res) => match self.next() {
Some(_) => Err(GetOneError::Multiple),
None => Ok(res),
},
}
}
}

View File

@ -0,0 +1,94 @@
// NOTE: this file is copy-pasted between several Embassy crates, because there is no
// straightforward way to share this code:
// - it cannot be placed into the root of the repo and linked from each build.rs using `#[path =
// "../build_common.rs"]`, because `cargo publish` requires that all files published with a crate
// reside in the crate's directory,
// - it cannot be symlinked from `embassy-xxx/build_common.rs` to `../build_common.rs`, because
// symlinks don't work on Windows.
use std::collections::HashSet;
use std::env;
/// Helper for emitting cargo instruction for enabling configs (`cargo:rustc-cfg=X`) and declaring
/// them (`cargo:rust-check-cfg=cfg(X)`).
#[derive(Debug)]
pub struct CfgSet {
enabled: HashSet<String>,
declared: HashSet<String>,
}
impl CfgSet {
pub fn new() -> Self {
Self {
enabled: HashSet::new(),
declared: HashSet::new(),
}
}
/// Enable a config, which can then be used in `#[cfg(...)]` for conditional compilation.
///
/// All configs that can potentially be enabled should be unconditionally declared using
/// [`Self::declare()`].
pub fn enable(&mut self, cfg: impl AsRef<str>) {
if self.enabled.insert(cfg.as_ref().to_owned()) {
println!("cargo:rustc-cfg={}", cfg.as_ref());
}
}
pub fn enable_all(&mut self, cfgs: &[impl AsRef<str>]) {
for cfg in cfgs.iter() {
self.enable(cfg.as_ref());
}
}
/// Declare a valid config for conditional compilation, without enabling it.
///
/// This enables rustc to check that the configs in `#[cfg(...)]` attributes are valid.
pub fn declare(&mut self, cfg: impl AsRef<str>) {
if self.declared.insert(cfg.as_ref().to_owned()) {
println!("cargo:rustc-check-cfg=cfg({})", cfg.as_ref());
}
}
pub fn declare_all(&mut self, cfgs: &[impl AsRef<str>]) {
for cfg in cfgs.iter() {
self.declare(cfg.as_ref());
}
}
pub fn set(&mut self, cfg: impl Into<String>, enable: bool) {
let cfg = cfg.into();
if enable {
self.enable(cfg.clone());
}
self.declare(cfg);
}
}
/// Sets configs that describe the target platform.
pub fn set_target_cfgs(cfgs: &mut CfgSet) {
let target = env::var("TARGET").unwrap();
if target.starts_with("thumbv6m-") {
cfgs.enable_all(&["cortex_m", "armv6m"]);
} else if target.starts_with("thumbv7m-") {
cfgs.enable_all(&["cortex_m", "armv7m"]);
} else if target.starts_with("thumbv7em-") {
cfgs.enable_all(&["cortex_m", "armv7m", "armv7em"]);
} else if target.starts_with("thumbv8m.base") {
cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_base"]);
} else if target.starts_with("thumbv8m.main") {
cfgs.enable_all(&["cortex_m", "armv8m", "armv8m_main"]);
}
cfgs.declare_all(&[
"cortex_m",
"armv6m",
"armv7m",
"armv7em",
"armv8m",
"armv8m_base",
"armv8m_main",
]);
cfgs.set("has_fpu", target.ends_with("-eabihf"));
}

270
embassy-mspm0/src/fmt.rs Normal file
View File

@ -0,0 +1,270 @@
#![macro_use]
#![allow(unused)]
use core::fmt::{Debug, Display, LowerHex};
#[cfg(all(feature = "defmt", feature = "log"))]
compile_error!("You may not enable both `defmt` and `log` features.");
#[collapse_debuginfo(yes)]
macro_rules! assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_eq!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::assert_ne!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! debug_assert {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! debug_assert_eq {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_eq!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_eq!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! debug_assert_ne {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::debug_assert_ne!($($x)*);
#[cfg(feature = "defmt")]
::defmt::debug_assert_ne!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! todo {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::todo!($($x)*);
#[cfg(feature = "defmt")]
::defmt::todo!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! unreachable {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::unreachable!($($x)*);
#[cfg(feature = "defmt")]
::defmt::unreachable!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! panic {
($($x:tt)*) => {
{
#[cfg(not(feature = "defmt"))]
::core::panic!($($x)*);
#[cfg(feature = "defmt")]
::defmt::panic!($($x)*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! trace {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::trace!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::trace!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! debug {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::debug!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::debug!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! info {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::info!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::info!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! warn {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::warn!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::warn!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[collapse_debuginfo(yes)]
macro_rules! error {
($s:literal $(, $x:expr)* $(,)?) => {
{
#[cfg(feature = "log")]
::log::error!($s $(, $x)*);
#[cfg(feature = "defmt")]
::defmt::error!($s $(, $x)*);
#[cfg(not(any(feature = "log", feature="defmt")))]
let _ = ($( & $x ),*);
}
};
}
#[cfg(feature = "defmt")]
#[collapse_debuginfo(yes)]
macro_rules! unwrap {
($($x:tt)*) => {
::defmt::unwrap!($($x)*)
};
}
#[cfg(not(feature = "defmt"))]
#[collapse_debuginfo(yes)]
macro_rules! unwrap {
($arg:expr) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
}
}
};
($arg:expr, $($msg:expr),+ $(,)? ) => {
match $crate::fmt::Try::into_result($arg) {
::core::result::Result::Ok(t) => t,
::core::result::Result::Err(e) => {
::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
}
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct NoneError;
pub trait Try {
type Ok;
type Error;
fn into_result(self) -> Result<Self::Ok, Self::Error>;
}
impl<T> Try for Option<T> {
type Ok = T;
type Error = NoneError;
#[inline]
fn into_result(self) -> Result<T, NoneError> {
self.ok_or(NoneError)
}
}
impl<T, E> Try for Result<T, E> {
type Ok = T;
type Error = E;
#[inline]
fn into_result(self) -> Self {
self
}
}
pub(crate) struct Bytes<'a>(pub &'a [u8]);
impl<'a> Debug for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> Display for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
impl<'a> LowerHex for Bytes<'a> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{:#02x?}", self.0)
}
}
#[cfg(feature = "defmt")]
impl<'a> defmt::Format for Bytes<'a> {
fn format(&self, fmt: defmt::Formatter) {
defmt::write!(fmt, "{:02x}", self.0)
}
}

1071
embassy-mspm0/src/gpio.rs Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
use crate::pac;
use crate::pac::interrupt;
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP0() {
use mspm0_metapac::Group0;
let group = pac::CPUSS.int_group(0);
// TODO: Decompose to direct u8
let iidx = group.iidx().read().stat().to_bits();
let Ok(group) = pac::Group0::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 0: {}", iidx);
return;
};
match group {
Group0::WWDT0 => todo!("implement WWDT0"),
Group0::DEBUGSS => todo!("implement DEBUGSS"),
Group0::FLASHCTL => todo!("implement FLASHCTL"),
Group0::SYSCTL => todo!("implement SYSCTL"),
}
}

View File

@ -0,0 +1,51 @@
use crate::pac;
use crate::pac::interrupt;
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP0() {
use mspm0_metapac::Group0;
let group = pac::CPUSS.int_group(0);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group0::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 0: {}", iidx);
return;
};
match group {
Group0::WWDT0 => todo!("implement WWDT0"),
Group0::WWDT1 => todo!("implement WWDT1"),
Group0::DEBUGSS => todo!("implement DEBUGSS"),
Group0::FLASHCTL => todo!("implement FLASHCTL"),
Group0::SYSCTL => todo!("implement SYSCTL"),
}
}
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP1() {
use mspm0_metapac::Group1;
let group = pac::CPUSS.int_group(1);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group1::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 1: {}", iidx);
return;
};
match group {
Group1::GPIOA => crate::gpio::gpioa_interrupt(),
Group1::GPIOB => crate::gpio::gpiob_interrupt(),
Group1::COMP0 => todo!("implement COMP0"),
Group1::COMP1 => todo!("implement COMP1"),
Group1::COMP2 => todo!("implement COMP2"),
Group1::TRNG => todo!("implement TRNG"),
}
}

View File

@ -0,0 +1,52 @@
use crate::pac;
use crate::pac::interrupt;
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP0() {
use mspm0_metapac::Group0;
let group = pac::CPUSS.int_group(0);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group0::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 0: {}", iidx);
return;
};
match group {
Group0::WWDT0 => todo!("implement WWDT0"),
Group0::WWDT1 => todo!("implement WWDT1"),
Group0::DEBUGSS => todo!("implement DEBUGSS"),
Group0::FLASHCTL => todo!("implement FLASHCTL"),
Group0::SYSCTL => todo!("implement SYSCTL"),
}
}
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP1() {
use mspm0_metapac::Group1;
let group = pac::CPUSS.int_group(1);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group1::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 1: {}", iidx);
return;
};
match group {
Group1::GPIOA => crate::gpio::gpioa_interrupt(),
Group1::GPIOB => crate::gpio::gpiob_interrupt(),
Group1::COMP0 => todo!("implement COMP0"),
Group1::COMP1 => todo!("implement COMP1"),
Group1::COMP2 => todo!("implement COMP2"),
Group1::TRNG => todo!("implement TRNG"),
Group1::GPIOC => crate::gpio::gpioc_interrupt(),
}
}

View File

@ -0,0 +1,46 @@
use crate::pac;
use crate::pac::interrupt;
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP0() {
use mspm0_metapac::Group0;
let group = pac::CPUSS.int_group(0);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group0::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 0: {}", iidx);
return;
};
match group {
Group0::WWDT0 => todo!("implement WWDT0"),
Group0::DEBUGSS => todo!("implement DEBUGSS"),
Group0::FLASHCTL => todo!("implement FLASHCTL"),
Group0::SYSCTL => todo!("implement SYSCTL"),
}
}
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP1() {
use mspm0_metapac::Group1;
let group = pac::CPUSS.int_group(1);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group1::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 1: {}", iidx);
return;
};
match group {
Group1::GPIOA => crate::gpio::gpioa_interrupt(),
Group1::COMP0 => todo!("implement COMP0"),
}
}

View File

@ -0,0 +1,49 @@
use crate::pac;
use crate::pac::interrupt;
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP0() {
use mspm0_metapac::Group0;
let group = pac::CPUSS.int_group(0);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group0::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 0: {}", iidx);
return;
};
match group {
Group0::WWDT0 => todo!("implement WWDT0"),
Group0::DEBUGSS => todo!("implement DEBUGSS"),
Group0::FLASHCTL => todo!("implement FLASHCTL"),
Group0::SYSCTL => todo!("implement SYSCTL"),
}
}
#[cfg(feature = "rt")]
#[interrupt]
fn GROUP1() {
use mspm0_metapac::Group1;
let group = pac::CPUSS.int_group(1);
// Must subtract by 1 since NO_INTR is value 0
let iidx = group.iidx().read().stat().to_bits() - 1;
let Ok(group) = pac::Group1::try_from(iidx as u8) else {
debug!("Invalid IIDX for group 1: {}", iidx);
return;
};
match group {
Group1::GPIOA => crate::gpio::gpioa_interrupt(),
Group1::GPIOB => crate::gpio::gpiob_interrupt(),
Group1::COMP0 => todo!("implement COMP0"),
Group1::TRNG => todo!("implement TRNG"),
Group1::GPIOC => crate::gpio::gpioc_interrupt(),
}
}

119
embassy-mspm0/src/lib.rs Normal file
View File

@ -0,0 +1,119 @@
#![no_std]
// Doc feature labels can be tested locally by running RUSTDOCFLAGS="--cfg=docsrs" cargo +nightly doc
#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg_hide), doc(cfg_hide(doc, docsrs)))]
// This mod MUST go first, so that the others see its macros.
pub(crate) mod fmt;
pub mod gpio;
pub mod timer;
/// Operating modes for peripherals.
pub mod mode {
trait SealedMode {}
/// Operating mode for a peripheral.
#[allow(private_bounds)]
pub trait Mode: SealedMode {}
/// Blocking mode.
pub struct Blocking;
impl SealedMode for Blocking {}
impl Mode for Blocking {}
/// Async mode.
pub struct Async;
impl SealedMode for Async {}
impl Mode for Async {}
}
#[cfg(feature = "_time-driver")]
mod time_driver;
// Interrupt group handlers.
#[cfg_attr(feature = "mspm0c110x", path = "int_group/c110x.rs")]
#[cfg_attr(feature = "mspm0g350x", path = "int_group/g350x.rs")]
#[cfg_attr(feature = "mspm0g351x", path = "int_group/g351x.rs")]
#[cfg_attr(feature = "mspm0l130x", path = "int_group/l130x.rs")]
#[cfg_attr(feature = "mspm0l222x", path = "int_group/l222x.rs")]
mod int_group;
pub(crate) mod _generated {
#![allow(dead_code)]
#![allow(unused_imports)]
#![allow(non_snake_case)]
#![allow(missing_docs)]
include!(concat!(env!("OUT_DIR"), "/_generated.rs"));
}
// Reexports
pub(crate) use _generated::gpio_pincm;
pub use _generated::{peripherals, Peripherals};
pub use embassy_hal_internal::Peri;
#[cfg(feature = "unstable-pac")]
pub use mspm0_metapac as pac;
#[cfg(not(feature = "unstable-pac"))]
pub(crate) use mspm0_metapac as pac;
pub use crate::_generated::interrupt;
/// `embassy-mspm0` global configuration.
#[non_exhaustive]
#[derive(Clone, Copy)]
pub struct Config {
// TODO
}
impl Default for Config {
fn default() -> Self {
Self {
// TODO
}
}
}
pub fn init(_config: Config) -> Peripherals {
critical_section::with(|cs| {
let peripherals = Peripherals::take_with_cs(cs);
// TODO: Further clock configuration
pac::SYSCTL.mclkcfg().modify(|w| {
// Enable MFCLK
w.set_usemftick(true);
// MDIV must be disabled if MFCLK is enabled.
w.set_mdiv(0);
});
// Enable MFCLK for peripheral use
//
// TODO: Optional?
pac::SYSCTL.genclken().modify(|w| {
w.set_mfpclken(true);
});
pac::SYSCTL.borthreshold().modify(|w| {
w.set_level(0);
});
gpio::init(pac::GPIOA);
#[cfg(gpio_pb)]
gpio::init(pac::GPIOB);
#[cfg(gpio_pc)]
gpio::init(pac::GPIOC);
_generated::enable_group_interrupts(cs);
#[cfg(feature = "mspm0c110x")]
unsafe {
use crate::_generated::interrupt::typelevel::Interrupt;
crate::interrupt::typelevel::GPIOA::enable();
}
#[cfg(feature = "_time-driver")]
time_driver::init(cs);
peripherals
})
}

View File

@ -0,0 +1,426 @@
use core::cell::{Cell, RefCell};
use core::sync::atomic::{compiler_fence, AtomicU32, Ordering};
use core::task::Waker;
use critical_section::{CriticalSection, Mutex};
use embassy_time_driver::Driver;
use embassy_time_queue_utils::Queue;
use mspm0_metapac::interrupt;
use mspm0_metapac::tim::vals::{Cm, Cvae, CxC, EvtCfg, PwrenKey, Ratio, Repeat, ResetKey};
use mspm0_metapac::tim::{Counterregs16, Tim};
use crate::peripherals;
use crate::timer::SealedTimer;
#[cfg(any(time_driver_timg12, time_driver_timg13))]
compile_error!("TIMG12 and TIMG13 are not supported by the time driver yet");
// Currently TIMG12 and TIMG13 are excluded because those are 32-bit timers.
#[cfg(time_driver_timg0)]
type T = peripherals::TIMG0;
#[cfg(time_driver_timg1)]
type T = peripherals::TIMG1;
#[cfg(time_driver_timg2)]
type T = peripherals::TIMG2;
#[cfg(time_driver_timg3)]
type T = peripherals::TIMG3;
#[cfg(time_driver_timg4)]
type T = peripherals::TIMG4;
#[cfg(time_driver_timg5)]
type T = peripherals::TIMG5;
#[cfg(time_driver_timg6)]
type T = peripherals::TIMG6;
#[cfg(time_driver_timg7)]
type T = peripherals::TIMG7;
#[cfg(time_driver_timg8)]
type T = peripherals::TIMG8;
#[cfg(time_driver_timg9)]
type T = peripherals::TIMG9;
#[cfg(time_driver_timg10)]
type T = peripherals::TIMG10;
#[cfg(time_driver_timg11)]
type T = peripherals::TIMG11;
#[cfg(time_driver_timg14)]
type T = peripherals::TIMG14;
#[cfg(time_driver_tima0)]
type T = peripherals::TIMA0;
#[cfg(time_driver_tima1)]
type T = peripherals::TIMA1;
// TODO: RTC
fn regs() -> Tim {
unsafe { Tim::from_ptr(T::regs()) }
}
fn regs_counter(tim: Tim) -> Counterregs16 {
unsafe { Counterregs16::from_ptr(tim.counterregs(0).as_ptr()) }
}
/// Clock timekeeping works with something we call "periods", which are time intervals
/// of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods.
fn calc_now(period: u32, counter: u16) -> u64 {
((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64)
}
/// The TIMx driver uses one of the `TIMG` or `TIMA` timer instances to implement a timer with a 32.768 kHz
/// tick rate. (TODO: Allow setting the tick rate)
///
/// This driver defines a period to be 2^15 ticks. 16-bit timers of course count to 2^16 ticks.
///
/// To generate a period every 2^15 ticks, the CC0 value is set to 2^15 and the load value set to 2^16.
/// Incrementing the period on a CCU0 and load results in the a period of 2^15 ticks.
///
/// For a specific timestamp, load the lower 16 bits into the CC1 value. When the period where the timestamp
/// should be enabled is reached, then the CCU1 (CC1 up) interrupt runs to actually wake the timer.
///
/// TODO: Compensate for per part variance. This can supposedly be done with the FCC system.
/// TODO: Allow using 32-bit timers (TIMG12 and TIMG13).
struct TimxDriver {
/// Number of 2^15 periods elapsed since boot.
period: AtomicU32,
/// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled.
alarm: Mutex<Cell<u64>>,
queue: Mutex<RefCell<Queue>>,
}
impl TimxDriver {
#[inline(never)]
fn init(&'static self, _cs: CriticalSection) {
// Clock config
// TODO: Configurable tick rate up to 4 MHz (32 kHz for now)
let regs = regs();
// Reset timer
regs.gprcm(0).rstctl().write(|w| {
w.set_resetassert(true);
w.set_key(ResetKey::KEY);
w.set_resetstkyclr(true);
});
// Power up timer
regs.gprcm(0).pwren().write(|w| {
w.set_enable(true);
w.set_key(PwrenKey::KEY);
});
// Following the instructions according to SLAU847D 23.2.1: TIMCLK Configuration
// 1. Select TIMCLK source
regs.clksel().modify(|w| {
// Use LFCLK for a 32.768kHz tick rate
w.set_lfclk_sel(true);
// TODO: Allow MFCLK for configurable tick rate up to 4 MHz
// w.set_mfclk_sel(ClkSel::ENABLE);
});
// 2. Divide by TIMCLK, we don't need to divide further for the 32kHz tick rate
regs.clkdiv().modify(|w| {
w.set_ratio(Ratio::DIV_BY_1);
});
// 3. To be generic across timer instances, we do not use the prescaler.
// TODO: mspm0-sdk always sets this, regardless of timer width?
regs.commonregs(0).cps().modify(|w| {
w.set_pcnt(0);
});
regs.pdbgctl().modify(|w| {
w.set_free(true);
});
// 4. Enable the TIMCLK.
regs.commonregs(0).cclkctl().modify(|w| {
w.set_clken(true);
});
regs.counterregs(0).ctrctl().modify(|w| {
// allow counting during debug
w.set_repeat(Repeat::REPEAT_3);
w.set_cvae(Cvae::ZEROVAL);
w.set_cm(Cm::UP);
// Must explicitly set CZC, CAC and CLC to 0 in order for all the timers to count.
//
// The reset value of these registers is 0x07, which is a reserved value.
//
// Looking at a bit representation of the reset value, this appears to be an AND
// of 2-input QEI mode and CCCTL_3 ACOND. Given that TIMG14 and TIMA0 have no QEI
// and 4 capture and compare channels, this works by accident for those timer units.
w.set_czc(CxC::CCTL0);
w.set_cac(CxC::CCTL0);
w.set_clc(CxC::CCTL0);
});
// Setup the period
let ctr = regs_counter(regs);
// Middle
ctr.cc(0).modify(|w| {
w.set_ccval(0x7FFF);
});
ctr.load().modify(|w| {
w.set_ld(u16::MAX);
});
// Enable the period interrupts
//
// This does not appear to ever be set for CPU_INT in the TI SDK and is not technically needed.
regs.evt_mode().modify(|w| {
w.set_evt_cfg(0, EvtCfg::SOFTWARE);
});
regs.int_event(0).imask().modify(|w| {
w.set_l(true);
w.set_ccu0(true);
});
unsafe { T::enable_interrupt() };
// Allow the counter to start counting.
regs.counterregs(0).ctrctl().modify(|w| {
w.set_en(true);
});
}
#[inline(never)]
fn next_period(&self) {
let r = regs();
// We only modify the period from the timer interrupt, so we know this can't race.
let period = self.period.load(Ordering::Relaxed) + 1;
self.period.store(period, Ordering::Relaxed);
let t = (period as u64) << 15;
critical_section::with(move |cs| {
r.int_event(0).imask().modify(move |w| {
let alarm = self.alarm.borrow(cs);
let at = alarm.get();
if at < t + 0xC000 {
// just enable it. `set_alarm` has already set the correct CC1 val.
w.set_ccu1(true);
}
})
});
}
#[inline(never)]
fn on_interrupt(&self) {
let r = regs();
critical_section::with(|cs| {
let mis = r.int_event(0).mis().read();
// Advance to next period if overflowed
if mis.l() {
self.next_period();
r.int_event(0).iclr().write(|w| {
w.set_l(true);
});
}
if mis.ccu0() {
self.next_period();
r.int_event(0).iclr().write(|w| {
w.set_ccu0(true);
});
}
if mis.ccu1() {
r.int_event(0).iclr().write(|w| {
w.set_ccu1(true);
});
self.trigger_alarm(cs);
}
});
}
fn trigger_alarm(&self, cs: CriticalSection) {
let mut next = self.queue.borrow(cs).borrow_mut().next_expiration(self.now());
while !self.set_alarm(cs, next) {
next = self.queue.borrow(cs).borrow_mut().next_expiration(self.now());
}
}
fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool {
let r = regs();
let ctr = regs_counter(r);
self.alarm.borrow(cs).set(timestamp);
let t = self.now();
if timestamp <= t {
// If alarm timestamp has passed the alarm will not fire.
// Disarm the alarm and return `false` to indicate that.
r.int_event(0).imask().modify(|w| w.set_ccu1(false));
self.alarm.borrow(cs).set(u64::MAX);
return false;
}
// Write the CC1 value regardless of whether we're going to enable it now or not.
// This way, when we enable it later, the right value is already set.
ctr.cc(1).write(|w| {
w.set_ccval(timestamp as u16);
});
// Enable it if it'll happen soon. Otherwise, `next_period` will enable it.
let diff = timestamp - t;
r.int_event(0).imask().modify(|w| w.set_ccu1(diff < 0xC000));
// Reevaluate if the alarm timestamp is still in the future
let t = self.now();
if timestamp <= t {
// If alarm timestamp has passed since we set it, we have a race condition and
// the alarm may or may not have fired.
// Disarm the alarm and return `false` to indicate that.
// It is the caller's responsibility to handle this ambiguity.
r.int_event(0).imask().modify(|w| w.set_ccu1(false));
self.alarm.borrow(cs).set(u64::MAX);
return false;
}
// We're confident the alarm will ring in the future.
true
}
}
impl Driver for TimxDriver {
fn now(&self) -> u64 {
let regs = regs();
let period = self.period.load(Ordering::Relaxed);
// Ensure the compiler does not read the counter before the period.
compiler_fence(Ordering::Acquire);
let counter = regs_counter(regs).ctr().read().cctr() as u16;
calc_now(period, counter)
}
fn schedule_wake(&self, at: u64, waker: &Waker) {
critical_section::with(|cs| {
let mut queue = self.queue.borrow(cs).borrow_mut();
if queue.schedule_wake(at, waker) {
let mut next = queue.next_expiration(self.now());
while !self.set_alarm(cs, next) {
next = queue.next_expiration(self.now());
}
}
});
}
}
embassy_time_driver::time_driver_impl!(static DRIVER: TimxDriver = TimxDriver {
period: AtomicU32::new(0),
alarm: Mutex::new(Cell::new(u64::MAX)),
queue: Mutex::new(RefCell::new(Queue::new()))
});
pub(crate) fn init(cs: CriticalSection) {
DRIVER.init(cs);
}
#[cfg(time_driver_timg0)]
#[interrupt]
fn TIMG0() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg1)]
#[interrupt]
fn TIMG1() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg2)]
#[interrupt]
fn TIMG2() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg3)]
#[interrupt]
fn TIMG3() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg4)]
#[interrupt]
fn TIMG4() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg5)]
#[interrupt]
fn TIMG5() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg6)]
#[interrupt]
fn TIMG6() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg7)]
#[interrupt]
fn TIMG7() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg8)]
#[interrupt]
fn TIMG8() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg9)]
#[interrupt]
fn TIMG9() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg10)]
#[interrupt]
fn TIMG10() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_timg11)]
#[interrupt]
fn TIMG11() {
DRIVER.on_interrupt();
}
// TODO: TIMG12 and TIMG13
#[cfg(time_driver_timg14)]
#[interrupt]
fn TIMG14() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_tima0)]
#[interrupt]
fn TIMA0() {
DRIVER.on_interrupt();
}
#[cfg(time_driver_tima1)]
#[interrupt]
fn TIMA1() {
DRIVER.on_interrupt();
}

View File

@ -0,0 +1,48 @@
#![macro_use]
/// Amount of bits of a timer.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TimerBits {
/// 16 bits.
Bits16,
/// 32 bits.
Bits32,
}
#[allow(private_bounds)]
pub trait Timer: SealedTimer + 'static {
/// Amount of bits this timer has.
const BITS: TimerBits;
}
pub(crate) trait SealedTimer {
/// Registers for this timer.
///
/// This is a raw pointer to the register block. The actual register block layout varies depending on the
/// timer type.
fn regs() -> *mut ();
/// Enable the interrupt corresponding to this timer.
unsafe fn enable_interrupt();
}
macro_rules! impl_timer {
($name: ident, $bits: ident) => {
impl crate::timer::SealedTimer for crate::peripherals::$name {
fn regs() -> *mut () {
crate::pac::$name.as_ptr()
}
unsafe fn enable_interrupt() {
use embassy_hal_internal::interrupt::InterruptExt;
crate::interrupt::$name.unpend();
crate::interrupt::$name.enable();
}
}
impl crate::timer::Timer for crate::peripherals::$name {
const BITS: crate::timer::TimerBits = crate::timer::TimerBits::$bits;
}
};
}

View File

@ -16,7 +16,7 @@ use core::sync::atomic::{compiler_fence, AtomicBool, AtomicU8, AtomicUsize, Orde
use core::task::Poll;
use embassy_hal_internal::atomic_ring_buffer::RingBuffer;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::Peri;
use pac::uarte::vals;
// Re-export SVD variants to allow user to directly set values
pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity};
@ -28,7 +28,7 @@ use crate::ppi::{
};
use crate::timer::{Instance as TimerInstance, Timer};
use crate::uarte::{configure, configure_rx_pins, configure_tx_pins, drop_tx_rx, Config, Instance as UarteInstance};
use crate::{interrupt, pac, Peripheral, EASY_DMA_SIZE};
use crate::{interrupt, pac, EASY_DMA_SIZE};
pub(crate) struct State {
tx_buf: RingBuffer,
@ -222,27 +222,26 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
/// Panics if `rx_buffer.len()` is odd.
#[allow(clippy::too_many_arguments)]
pub fn new(
uarte: impl Peripheral<P = U> + 'd,
timer: impl Peripheral<P = T> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_group: impl Peripheral<P = impl Group> + 'd,
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, timer, rxd, txd, ppi_ch1, ppi_ch2, ppi_group);
Self::new_inner(
uarte,
timer,
ppi_ch1.map_into(),
ppi_ch2.map_into(),
ppi_group.map_into(),
rxd.map_into(),
txd.map_into(),
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
txd.into(),
None,
None,
config,
@ -258,31 +257,30 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
/// Panics if `rx_buffer.len()` is odd.
#[allow(clippy::too_many_arguments)]
pub fn new_with_rtscts(
uarte: impl Peripheral<P = U> + 'd,
timer: impl Peripheral<P = T> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_group: impl Peripheral<P = impl Group> + 'd,
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
cts: impl Peripheral<P = impl GpioPin> + 'd,
rts: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, timer, rxd, txd, cts, rts, ppi_ch1, ppi_ch2, ppi_group);
Self::new_inner(
uarte,
timer,
ppi_ch1.map_into(),
ppi_ch2.map_into(),
ppi_group.map_into(),
rxd.map_into(),
txd.map_into(),
Some(cts.map_into()),
Some(rts.map_into()),
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
txd.into(),
Some(cts.into()),
Some(rts.into()),
config,
rx_buffer,
tx_buffer,
@ -291,15 +289,15 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
#[allow(clippy::too_many_arguments)]
fn new_inner(
peri: PeripheralRef<'d, U>,
timer: PeripheralRef<'d, T>,
ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_group: PeripheralRef<'d, AnyGroup>,
rxd: PeripheralRef<'d, AnyPin>,
txd: PeripheralRef<'d, AnyPin>,
cts: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
rts: Option<Peri<'d, AnyPin>>,
config: Config,
rx_buffer: &'d mut [u8],
tx_buffer: &'d mut [u8],
@ -372,20 +370,19 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarte<'d, U, T> {
/// Reader part of the buffered UARTE driver.
pub struct BufferedUarteTx<'d, U: UarteInstance> {
_peri: PeripheralRef<'d, U>,
_peri: Peri<'d, U>,
}
impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
/// Create a new BufferedUarteTx without hardware flow control.
pub fn new(
uarte: impl Peripheral<P = U> + 'd,
uarte: Peri<'d, U>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
txd: Peri<'d, impl GpioPin>,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, txd);
Self::new_inner(uarte, txd.map_into(), None, config, tx_buffer)
Self::new_inner(uarte, txd.into(), None, config, tx_buffer)
}
/// Create a new BufferedUarte with hardware flow control (RTS/CTS)
@ -394,21 +391,20 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
///
/// Panics if `rx_buffer.len()` is odd.
pub fn new_with_cts(
uarte: impl Peripheral<P = U> + 'd,
uarte: Peri<'d, U>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
cts: impl Peripheral<P = impl GpioPin> + 'd,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, txd, cts);
Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config, tx_buffer)
Self::new_inner(uarte, txd.into(), Some(cts.into()), config, tx_buffer)
}
fn new_inner(
peri: PeripheralRef<'d, U>,
txd: PeripheralRef<'d, AnyPin>,
cts: Option<PeripheralRef<'d, AnyPin>>,
peri: Peri<'d, U>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
config: Config,
tx_buffer: &'d mut [u8],
) -> Self {
@ -426,9 +422,9 @@ impl<'d, U: UarteInstance> BufferedUarteTx<'d, U> {
}
fn new_innerer(
peri: PeripheralRef<'d, U>,
txd: PeripheralRef<'d, AnyPin>,
cts: Option<PeripheralRef<'d, AnyPin>>,
peri: Peri<'d, U>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
tx_buffer: &'d mut [u8],
) -> Self {
let r = U::regs();
@ -542,7 +538,7 @@ impl<'a, U: UarteInstance> Drop for BufferedUarteTx<'a, U> {
/// Reader part of the buffered UARTE driver.
pub struct BufferedUarteRx<'d, U: UarteInstance, T: TimerInstance> {
_peri: PeripheralRef<'d, U>,
_peri: Peri<'d, U>,
timer: Timer<'d, T>,
_ppi_ch1: Ppi<'d, AnyConfigurableChannel, 1, 1>,
_ppi_ch2: Ppi<'d, AnyConfigurableChannel, 1, 2>,
@ -557,24 +553,23 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
/// Panics if `rx_buffer.len()` is odd.
#[allow(clippy::too_many_arguments)]
pub fn new(
uarte: impl Peripheral<P = U> + 'd,
timer: impl Peripheral<P = T> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_group: impl Peripheral<P = impl Group> + 'd,
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, timer, rxd, ppi_ch1, ppi_ch2, ppi_group);
Self::new_inner(
uarte,
timer,
ppi_ch1.map_into(),
ppi_ch2.map_into(),
ppi_group.map_into(),
rxd.map_into(),
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
None,
config,
rx_buffer,
@ -588,26 +583,25 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
/// Panics if `rx_buffer.len()` is odd.
#[allow(clippy::too_many_arguments)]
pub fn new_with_rts(
uarte: impl Peripheral<P = U> + 'd,
timer: impl Peripheral<P = T> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel> + 'd,
ppi_group: impl Peripheral<P = impl Group> + 'd,
uarte: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, impl ConfigurableChannel>,
ppi_ch2: Peri<'d, impl ConfigurableChannel>,
ppi_group: Peri<'d, impl Group>,
_irq: impl interrupt::typelevel::Binding<U::Interrupt, InterruptHandler<U>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
rts: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
into_ref!(uarte, timer, rxd, rts, ppi_ch1, ppi_ch2, ppi_group);
Self::new_inner(
uarte,
timer,
ppi_ch1.map_into(),
ppi_ch2.map_into(),
ppi_group.map_into(),
rxd.map_into(),
Some(rts.map_into()),
ppi_ch1.into(),
ppi_ch2.into(),
ppi_group.into(),
rxd.into(),
Some(rts.into()),
config,
rx_buffer,
)
@ -615,13 +609,13 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
#[allow(clippy::too_many_arguments)]
fn new_inner(
peri: PeripheralRef<'d, U>,
timer: PeripheralRef<'d, T>,
ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_group: PeripheralRef<'d, AnyGroup>,
rxd: PeripheralRef<'d, AnyPin>,
rts: Option<PeripheralRef<'d, AnyPin>>,
peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
rts: Option<Peri<'d, AnyPin>>,
config: Config,
rx_buffer: &'d mut [u8],
) -> Self {
@ -640,13 +634,13 @@ impl<'d, U: UarteInstance, T: TimerInstance> BufferedUarteRx<'d, U, T> {
#[allow(clippy::too_many_arguments)]
fn new_innerer(
peri: PeripheralRef<'d, U>,
timer: PeripheralRef<'d, T>,
ppi_ch1: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_ch2: PeripheralRef<'d, AnyConfigurableChannel>,
ppi_group: PeripheralRef<'d, AnyGroup>,
rxd: PeripheralRef<'d, AnyPin>,
rts: Option<PeripheralRef<'d, AnyPin>>,
peri: Peri<'d, U>,
timer: Peri<'d, T>,
ppi_ch1: Peri<'d, AnyConfigurableChannel>,
ppi_ch2: Peri<'d, AnyConfigurableChannel>,
ppi_group: Peri<'d, AnyGroup>,
rxd: Peri<'d, AnyPin>,
rts: Option<Peri<'d, AnyPin>>,
rx_buffer: &'d mut [u8],
) -> Self {
assert!(rx_buffer.len() % 2 == 0);

View File

@ -7,20 +7,19 @@
use core::marker::PhantomData;
use embassy_hal_internal::into_ref;
use embassy_hal_internal::PeripheralType;
use crate::ppi::{Event, Task};
use crate::{interrupt, pac, Peripheral, PeripheralRef};
use crate::{interrupt, pac, Peri};
/// An instance of the EGU.
pub struct Egu<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Egu<'d, T> {
/// Create a new EGU instance.
pub fn new(_p: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(_p);
pub fn new(_p: Peri<'d, T>) -> Self {
Self { _p }
}
@ -39,7 +38,7 @@ pub(crate) trait SealedInstance {
/// Basic Egu instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -5,14 +5,14 @@ use core::convert::Infallible;
use core::hint::unreachable_unchecked;
use cfg_if::cfg_if;
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use crate::pac;
use crate::pac::common::{Reg, RW};
use crate::pac::gpio;
use crate::pac::gpio::vals;
#[cfg(not(feature = "_nrf51"))]
use crate::pac::shared::{regs::Psel, vals::Connect};
use crate::{pac, Peripheral};
/// A GPIO port with up to 32 pins.
#[derive(Debug, Eq, PartialEq)]
@ -49,7 +49,7 @@ pub struct Input<'d> {
impl<'d> Input<'d> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, pull: Pull) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input(pull);
@ -210,7 +210,7 @@ pub struct Output<'d> {
impl<'d> Output<'d> {
/// Create GPIO output driver for a [Pin] with the provided [Level] and [OutputDriver] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level, drive: OutputDrive) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level, drive: OutputDrive) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
@ -310,7 +310,7 @@ fn convert_pull(pull: Pull) -> vals::Pull {
/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
/// mode.
pub struct Flex<'d> {
pub(crate) pin: PeripheralRef<'d, AnyPin>,
pub(crate) pin: Peri<'d, AnyPin>,
}
impl<'d> Flex<'d> {
@ -319,10 +319,9 @@ impl<'d> Flex<'d> {
/// The pin remains disconnected. The initial output level is unspecified, but can be changed
/// before the pin is put into output mode.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd) -> Self {
into_ref!(pin);
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
// Pin will be in disconnected state.
Self { pin: pin.map_into() }
Self { pin: pin.into() }
}
/// Put the pin into input mode.
@ -503,7 +502,7 @@ pub(crate) trait SealedPin {
/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
#[allow(private_bounds)]
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static {
pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
/// Number of the pin within the port (0..31)
#[inline]
fn pin(&self) -> u8 {
@ -529,19 +528,11 @@ pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static
fn psel_bits(&self) -> pac::shared::regs::Psel {
pac::shared::regs::Psel(self.pin_port() as u32)
}
/// Convert from concrete pin type PX_XX to type erased `AnyPin`.
#[inline]
fn degrade(self) -> AnyPin {
AnyPin {
pin_port: self.pin_port(),
}
}
}
/// Type-erased GPIO pin
pub struct AnyPin {
pin_port: u8,
pub(crate) pin_port: u8,
}
impl AnyPin {
@ -550,8 +541,8 @@ impl AnyPin {
/// # Safety
/// - `pin_port` should not in use by another driver.
#[inline]
pub unsafe fn steal(pin_port: u8) -> Self {
Self { pin_port }
pub unsafe fn steal(pin_port: u8) -> Peri<'static, Self> {
Peri::new_unchecked(Self { pin_port })
}
}
@ -573,7 +564,7 @@ pub(crate) trait PselBits {
}
#[cfg(not(feature = "_nrf51"))]
impl<'a, P: Pin> PselBits for Option<PeripheralRef<'a, P>> {
impl<'a, P: Pin> PselBits for Option<Peri<'a, P>> {
#[inline]
fn psel_bits(&self) -> pac::shared::regs::Psel {
match self {
@ -611,8 +602,10 @@ macro_rules! impl_pin {
}
impl From<peripherals::$type> for crate::gpio::AnyPin {
fn from(val: peripherals::$type) -> Self {
crate::gpio::Pin::degrade(val)
fn from(_val: peripherals::$type) -> Self {
Self {
pin_port: $port_num * 32 + $pin_num,
}
}
}
};

View File

@ -4,7 +4,7 @@ use core::convert::Infallible;
use core::future::{poll_fn, Future};
use core::task::{Context, Poll};
use embassy_hal_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Flex, Input, Output, Pin as GpioPin, SealedPin as _};
@ -189,7 +189,7 @@ impl Iterator for BitIter {
/// GPIOTE channel driver in input mode
pub struct InputChannel<'d> {
ch: PeripheralRef<'d, AnyChannel>,
ch: Peri<'d, AnyChannel>,
pin: Input<'d>,
}
@ -204,9 +204,7 @@ impl<'d> Drop for InputChannel<'d> {
impl<'d> InputChannel<'d> {
/// Create a new GPIOTE input channel driver.
pub fn new(ch: impl Peripheral<P = impl Channel> + 'd, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
into_ref!(ch);
pub fn new(ch: Peri<'d, impl Channel>, pin: Input<'d>, polarity: InputChannelPolarity) -> Self {
let g = regs();
let num = ch.number();
@ -228,7 +226,7 @@ impl<'d> InputChannel<'d> {
g.events_in(num).write_value(0);
InputChannel { ch: ch.map_into(), pin }
InputChannel { ch: ch.into(), pin }
}
/// Asynchronously wait for an event in this channel.
@ -261,7 +259,7 @@ impl<'d> InputChannel<'d> {
/// GPIOTE channel driver in output mode
pub struct OutputChannel<'d> {
ch: PeripheralRef<'d, AnyChannel>,
ch: Peri<'d, AnyChannel>,
_pin: Output<'d>,
}
@ -276,8 +274,7 @@ impl<'d> Drop for OutputChannel<'d> {
impl<'d> OutputChannel<'d> {
/// Create a new GPIOTE output channel driver.
pub fn new(ch: impl Peripheral<P = impl Channel> + 'd, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
into_ref!(ch);
pub fn new(ch: Peri<'d, impl Channel>, pin: Output<'d>, polarity: OutputChannelPolarity) -> Self {
let g = regs();
let num = ch.number();
@ -301,7 +298,7 @@ impl<'d> OutputChannel<'d> {
});
OutputChannel {
ch: ch.map_into(),
ch: ch.into(),
_pin: pin,
}
}
@ -351,14 +348,12 @@ impl<'d> OutputChannel<'d> {
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub(crate) struct PortInputFuture<'a> {
pin: PeripheralRef<'a, AnyPin>,
pin: Peri<'a, AnyPin>,
}
impl<'a> PortInputFuture<'a> {
fn new(pin: impl Peripheral<P = impl GpioPin> + 'a) -> Self {
Self {
pin: pin.into_ref().map_into(),
}
fn new(pin: Peri<'a, impl GpioPin>) -> Self {
Self { pin: pin.into() }
}
}
@ -415,13 +410,13 @@ impl<'d> Flex<'d> {
/// Wait until the pin is high. If it is already high, return immediately.
pub async fn wait_for_high(&mut self) {
self.pin.conf().modify(|w| w.set_sense(Sense::HIGH));
PortInputFuture::new(&mut self.pin).await
PortInputFuture::new(self.pin.reborrow()).await
}
/// Wait until the pin is low. If it is already low, return immediately.
pub async fn wait_for_low(&mut self) {
self.pin.conf().modify(|w| w.set_sense(Sense::LOW));
PortInputFuture::new(&mut self.pin).await
PortInputFuture::new(self.pin.reborrow()).await
}
/// Wait for the pin to undergo a transition from low to high.
@ -443,7 +438,7 @@ impl<'d> Flex<'d> {
} else {
self.pin.conf().modify(|w| w.set_sense(Sense::HIGH));
}
PortInputFuture::new(&mut self.pin).await
PortInputFuture::new(self.pin.reborrow()).await
}
}
@ -455,24 +450,14 @@ trait SealedChannel {}
///
/// Implemented by all GPIOTE channels.
#[allow(private_bounds)]
pub trait Channel: SealedChannel + Into<AnyChannel> + Sized + 'static {
pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static {
/// Get the channel number.
fn number(&self) -> usize;
/// Convert this channel to a type-erased `AnyChannel`.
///
/// This allows using several channels in situations that might require
/// them to be the same type, like putting them in an array.
fn degrade(self) -> AnyChannel {
AnyChannel {
number: self.number() as u8,
}
}
}
/// Type-erased channel.
///
/// Obtained by calling `Channel::degrade`.
/// Obtained by calling `Channel::into()`.
///
/// This allows using several channels in situations that might require
/// them to be the same type, like putting them in an array.
@ -498,7 +483,9 @@ macro_rules! impl_channel {
impl From<peripherals::$type> for AnyChannel {
fn from(val: peripherals::$type) -> Self {
Channel::degrade(val)
Self {
number: val.number() as u8,
}
}
}
};

View File

@ -10,14 +10,14 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Pin as GpioPin, PselBits};
use crate::interrupt::typelevel::Interrupt;
use crate::pac::i2s::vals;
use crate::util::slice_in_ram_or;
use crate::{interrupt, pac, Peripheral, EASY_DMA_SIZE};
use crate::{interrupt, pac, EASY_DMA_SIZE};
/// Type alias for `MultiBuffering` with 2 buffers.
pub type DoubleBuffering<S, const NS: usize> = MultiBuffering<S, 2, NS>;
@ -406,12 +406,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// I2S driver.
pub struct I2S<'d, T: Instance> {
i2s: PeripheralRef<'d, T>,
mck: Option<PeripheralRef<'d, AnyPin>>,
sck: PeripheralRef<'d, AnyPin>,
lrck: PeripheralRef<'d, AnyPin>,
sdin: Option<PeripheralRef<'d, AnyPin>>,
sdout: Option<PeripheralRef<'d, AnyPin>>,
i2s: Peri<'d, T>,
mck: Option<Peri<'d, AnyPin>>,
sck: Peri<'d, AnyPin>,
lrck: Peri<'d, AnyPin>,
sdin: Option<Peri<'d, AnyPin>>,
sdout: Option<Peri<'d, AnyPin>>,
master_clock: Option<MasterClock>,
config: Config,
}
@ -419,20 +419,19 @@ pub struct I2S<'d, T: Instance> {
impl<'d, T: Instance> I2S<'d, T> {
/// Create a new I2S in master mode
pub fn new_master(
i2s: impl Peripheral<P = T> + 'd,
i2s: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
mck: impl Peripheral<P = impl GpioPin> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
lrck: impl Peripheral<P = impl GpioPin> + 'd,
mck: Peri<'d, impl GpioPin>,
sck: Peri<'d, impl GpioPin>,
lrck: Peri<'d, impl GpioPin>,
master_clock: MasterClock,
config: Config,
) -> Self {
into_ref!(i2s, mck, sck, lrck);
Self {
i2s,
mck: Some(mck.map_into()),
sck: sck.map_into(),
lrck: lrck.map_into(),
mck: Some(mck.into()),
sck: sck.into(),
lrck: lrck.into(),
sdin: None,
sdout: None,
master_clock: Some(master_clock),
@ -442,18 +441,17 @@ impl<'d, T: Instance> I2S<'d, T> {
/// Create a new I2S in slave mode
pub fn new_slave(
i2s: impl Peripheral<P = T> + 'd,
i2s: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
lrck: impl Peripheral<P = impl GpioPin> + 'd,
sck: Peri<'d, impl GpioPin>,
lrck: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(i2s, sck, lrck);
Self {
i2s,
mck: None,
sck: sck.map_into(),
lrck: lrck.map_into(),
sck: sck.into(),
lrck: lrck.into(),
sdin: None,
sdout: None,
master_clock: None,
@ -464,10 +462,10 @@ impl<'d, T: Instance> I2S<'d, T> {
/// I2S output only
pub fn output<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdout: impl Peripheral<P = impl GpioPin> + 'd,
sdout: Peri<'d, impl GpioPin>,
buffers: MultiBuffering<S, NB, NS>,
) -> OutputStream<'d, T, S, NB, NS> {
self.sdout = Some(sdout.into_ref().map_into());
self.sdout = Some(sdout.into());
OutputStream {
_p: self.build(),
buffers,
@ -477,10 +475,10 @@ impl<'d, T: Instance> I2S<'d, T> {
/// I2S input only
pub fn input<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdin: impl Peripheral<P = impl GpioPin> + 'd,
sdin: Peri<'d, impl GpioPin>,
buffers: MultiBuffering<S, NB, NS>,
) -> InputStream<'d, T, S, NB, NS> {
self.sdin = Some(sdin.into_ref().map_into());
self.sdin = Some(sdin.into());
InputStream {
_p: self.build(),
buffers,
@ -490,13 +488,13 @@ impl<'d, T: Instance> I2S<'d, T> {
/// I2S full duplex (input and output)
pub fn full_duplex<S: Sample, const NB: usize, const NS: usize>(
mut self,
sdin: impl Peripheral<P = impl GpioPin> + 'd,
sdout: impl Peripheral<P = impl GpioPin> + 'd,
sdin: Peri<'d, impl GpioPin>,
sdout: Peri<'d, impl GpioPin>,
buffers_out: MultiBuffering<S, NB, NS>,
buffers_in: MultiBuffering<S, NB, NS>,
) -> FullDuplexStream<'d, T, S, NB, NS> {
self.sdout = Some(sdout.into_ref().map_into());
self.sdin = Some(sdin.into_ref().map_into());
self.sdout = Some(sdout.into());
self.sdin = Some(sdin.into());
FullDuplexStream {
_p: self.build(),
@ -505,7 +503,7 @@ impl<'d, T: Instance> I2S<'d, T> {
}
}
fn build(self) -> PeripheralRef<'d, T> {
fn build(self) -> Peri<'d, T> {
self.apply_config();
self.select_pins();
self.setup_interrupt();
@ -702,7 +700,7 @@ impl<'d, T: Instance> I2S<'d, T> {
/// I2S output
pub struct OutputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
buffers: MultiBuffering<S, NB, NS>,
}
@ -756,7 +754,7 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> OutputStream<
/// I2S input
pub struct InputStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
buffers: MultiBuffering<S, NB, NS>,
}
@ -811,7 +809,7 @@ impl<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> InputStream<'
/// I2S full duplex stream (input & output)
pub struct FullDuplexStream<'d, T: Instance, S: Sample, const NB: usize, const NS: usize> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
buffers_out: MultiBuffering<S, NB, NS>,
buffers_in: MultiBuffering<S, NB, NS>,
}
@ -1148,7 +1146,7 @@ pub(crate) trait SealedInstance {
/// I2S peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -263,7 +263,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_internal::{into_ref, Peripheral, PeripheralRef};
pub use embassy_hal_internal::{Peri, PeripheralType};
pub use crate::chip::interrupt;
#[cfg(feature = "rt")]

View File

@ -13,7 +13,6 @@ use core::future::poll_fn;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
pub use vals::{Bitframesdd as SddPat, Discardmode as DiscardMode};
@ -22,7 +21,7 @@ use crate::pac::nfct::vals;
use crate::pac::NFCT;
use crate::peripherals::NFCT;
use crate::util::slice_in_ram;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac, Peri};
/// NFCID1 (aka UID) of different sizes.
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
@ -96,7 +95,7 @@ pub enum Error {
/// NFC tag emulator driver.
pub struct NfcT<'d> {
_p: PeripheralRef<'d, NFCT>,
_p: Peri<'d, NFCT>,
rx_buf: [u8; 256],
tx_buf: [u8; 256],
}
@ -104,12 +103,10 @@ pub struct NfcT<'d> {
impl<'d> NfcT<'d> {
/// Create an Nfc Tag driver
pub fn new(
_p: impl Peripheral<P = NFCT> + 'd,
_p: Peri<'d, NFCT>,
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::NFCT, InterruptHandler> + 'd,
config: &Config,
) -> Self {
into_ref!(_p);
let r = pac::NFCT;
unsafe {

View File

@ -2,14 +2,13 @@
use core::{ptr, slice};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embedded_storage::nor_flash::{
ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash,
};
use crate::pac::nvmc::vals;
use crate::peripherals::NVMC;
use crate::{pac, Peripheral};
use crate::{pac, Peri};
#[cfg(not(feature = "_nrf5340-net"))]
/// Erase size of NVMC flash in bytes.
@ -42,13 +41,12 @@ impl NorFlashError for Error {
/// Non-Volatile Memory Controller (NVMC) that implements the `embedded-storage` traits.
pub struct Nvmc<'d> {
_p: PeripheralRef<'d, NVMC>,
_p: Peri<'d, NVMC>,
}
impl<'d> Nvmc<'d> {
/// Create Nvmc driver.
pub fn new(_p: impl Peripheral<P = NVMC> + 'd) -> Self {
into_ref!(_p);
pub fn new(_p: Peri<'d, NVMC>) -> Self {
Self { _p }
}

View File

@ -8,7 +8,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use fixed::types::I7F1;
@ -25,7 +25,7 @@ pub use crate::pac::pdm::vals::Freq as Frequency;
feature = "_nrf91",
))]
pub use crate::pac::pdm::vals::Ratio;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// Interrupt handler
pub struct InterruptHandler<T: Instance> {
@ -54,7 +54,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// PDM microphone interface
pub struct Pdm<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
_peri: Peri<'d, T>,
}
/// PDM error
@ -89,24 +89,16 @@ pub enum SamplerState {
impl<'d, T: Instance> Pdm<'d, T> {
/// Create PDM driver
pub fn new(
pdm: impl Peripheral<P = T> + 'd,
pdm: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
clk: impl Peripheral<P = impl GpioPin> + 'd,
din: impl Peripheral<P = impl GpioPin> + 'd,
clk: Peri<'d, impl GpioPin>,
din: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(pdm, clk, din);
Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
Self::new_inner(pdm, clk.into(), din.into(), config)
}
fn new_inner(
pdm: PeripheralRef<'d, T>,
clk: PeripheralRef<'d, AnyPin>,
din: PeripheralRef<'d, AnyPin>,
config: Config,
) -> Self {
into_ref!(pdm);
fn new_inner(pdm: Peri<'d, T>, clk: Peri<'d, AnyPin>, din: Peri<'d, AnyPin>, config: Config) -> Self {
let r = T::regs();
// setup gpio pins
@ -452,7 +444,7 @@ pub(crate) trait SealedInstance {
/// PDM peripheral instance
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -1,7 +1,5 @@
use embassy_hal_internal::into_ref;
use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
use crate::{pac, Peripheral};
use crate::{pac, Peri};
const DPPI_ENABLE_BIT: u32 = 0x8000_0000;
const DPPI_CHANNEL_MASK: u32 = 0x0000_00FF;
@ -12,14 +10,14 @@ pub(crate) fn regs() -> pac::dppic::Dppic {
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
/// Configure PPI channel to trigger `task` on `event`.
pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
pub fn new_one_to_one(ch: Peri<'d, C>, event: Event<'d>, task: Task<'d>) -> Self {
Ppi::new_many_to_many(ch, [event], [task])
}
}
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
/// Configure PPI channel to trigger both `task1` and `task2` on `event`.
pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
pub fn new_one_to_two(ch: Peri<'d, C>, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
Ppi::new_many_to_many(ch, [event], [task1, task2])
}
}
@ -28,13 +26,7 @@ impl<'d, C: ConfigurableChannel, const EVENT_COUNT: usize, const TASK_COUNT: usi
Ppi<'d, C, EVENT_COUNT, TASK_COUNT>
{
/// Configure a DPPI channel to trigger all `tasks` when any of the `events` fires.
pub fn new_many_to_many(
ch: impl Peripheral<P = C> + 'd,
events: [Event<'d>; EVENT_COUNT],
tasks: [Task<'d>; TASK_COUNT],
) -> Self {
into_ref!(ch);
pub fn new_many_to_many(ch: Peri<'d, C>, events: [Event<'d>; EVENT_COUNT], tasks: [Task<'d>; TASK_COUNT]) -> Self {
let val = DPPI_ENABLE_BIT | (ch.number() as u32 & DPPI_CHANNEL_MASK);
for task in tasks {
if unsafe { task.subscribe_reg().read_volatile() } != 0 {

View File

@ -18,10 +18,10 @@
use core::marker::PhantomData;
use core::ptr::NonNull;
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use crate::pac::common::{Reg, RW, W};
use crate::{peripherals, Peripheral};
use crate::peripherals;
#[cfg_attr(feature = "_dppi", path = "dppi.rs")]
#[cfg_attr(feature = "_ppi", path = "ppi.rs")]
@ -30,7 +30,7 @@ pub(crate) use _version::*;
/// PPI channel driver.
pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize> {
ch: PeripheralRef<'d, C>,
ch: Peri<'d, C>,
#[cfg(feature = "_dppi")]
events: [Event<'d>; EVENT_COUNT],
#[cfg(feature = "_dppi")]
@ -39,16 +39,14 @@ pub struct Ppi<'d, C: Channel, const EVENT_COUNT: usize, const TASK_COUNT: usize
/// PPI channel group driver.
pub struct PpiGroup<'d, G: Group> {
g: PeripheralRef<'d, G>,
g: Peri<'d, G>,
}
impl<'d, G: Group> PpiGroup<'d, G> {
/// Create a new PPI group driver.
///
/// The group is initialized as containing no channels.
pub fn new(g: impl Peripheral<P = G> + 'd) -> Self {
into_ref!(g);
pub fn new(g: Peri<'d, G>) -> Self {
let r = regs();
let n = g.number();
r.chg(n).write(|_| ());
@ -210,34 +208,22 @@ pub(crate) trait SealedGroup {}
/// Interface for PPI channels.
#[allow(private_bounds)]
pub trait Channel: SealedChannel + Peripheral<P = Self> + Sized + 'static {
pub trait Channel: SealedChannel + PeripheralType + Sized + 'static {
/// Returns the number of the channel
fn number(&self) -> usize;
}
/// Interface for PPI channels that can be configured.
pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> {
/// Convert into a type erased configurable channel.
fn degrade(self) -> AnyConfigurableChannel;
}
pub trait ConfigurableChannel: Channel + Into<AnyConfigurableChannel> {}
/// Interface for PPI channels that cannot be configured.
pub trait StaticChannel: Channel + Into<AnyStaticChannel> {
/// Convert into a type erased static channel.
fn degrade(self) -> AnyStaticChannel;
}
pub trait StaticChannel: Channel + Into<AnyStaticChannel> {}
/// Interface for a group of PPI channels.
#[allow(private_bounds)]
pub trait Group: SealedGroup + Peripheral<P = Self> + Into<AnyGroup> + Sized + 'static {
pub trait Group: SealedGroup + PeripheralType + Into<AnyGroup> + Sized + 'static {
/// Returns the number of the group.
fn number(&self) -> usize;
/// Convert into a type erased group.
fn degrade(self) -> AnyGroup {
AnyGroup {
number: self.number() as u8,
}
}
}
// ======================
@ -255,11 +241,7 @@ impl Channel for AnyStaticChannel {
self.number as usize
}
}
impl StaticChannel for AnyStaticChannel {
fn degrade(self) -> AnyStaticChannel {
self
}
}
impl StaticChannel for AnyStaticChannel {}
/// The any configurable channel can represent any configurable channel at runtime.
/// This can be used to have fewer generic parameters in some places.
@ -273,11 +255,7 @@ impl Channel for AnyConfigurableChannel {
self.number as usize
}
}
impl ConfigurableChannel for AnyConfigurableChannel {
fn degrade(self) -> AnyConfigurableChannel {
self
}
}
impl ConfigurableChannel for AnyConfigurableChannel {}
#[cfg(not(feature = "_nrf51"))]
macro_rules! impl_ppi_channel {
@ -291,35 +269,23 @@ macro_rules! impl_ppi_channel {
};
($type:ident, $number:expr => static) => {
impl_ppi_channel!($type, $number);
impl crate::ppi::StaticChannel for peripherals::$type {
fn degrade(self) -> crate::ppi::AnyStaticChannel {
use crate::ppi::Channel;
crate::ppi::AnyStaticChannel {
number: self.number() as u8,
}
}
}
impl crate::ppi::StaticChannel for peripherals::$type {}
impl From<peripherals::$type> for crate::ppi::AnyStaticChannel {
fn from(val: peripherals::$type) -> Self {
crate::ppi::StaticChannel::degrade(val)
Self {
number: crate::ppi::Channel::number(&val) as u8,
}
}
}
};
($type:ident, $number:expr => configurable) => {
impl_ppi_channel!($type, $number);
impl crate::ppi::ConfigurableChannel for peripherals::$type {
fn degrade(self) -> crate::ppi::AnyConfigurableChannel {
use crate::ppi::Channel;
crate::ppi::AnyConfigurableChannel {
number: self.number() as u8,
}
}
}
impl crate::ppi::ConfigurableChannel for peripherals::$type {}
impl From<peripherals::$type> for crate::ppi::AnyConfigurableChannel {
fn from(val: peripherals::$type) -> Self {
crate::ppi::ConfigurableChannel::degrade(val)
Self {
number: crate::ppi::Channel::number(&val) as u8,
}
}
}
};
@ -351,7 +317,9 @@ macro_rules! impl_group {
impl From<peripherals::$type> for crate::ppi::AnyGroup {
fn from(val: peripherals::$type) -> Self {
crate::ppi::Group::degrade(val)
Self {
number: crate::ppi::Group::number(&val) as u8,
}
}
}
};

View File

@ -1,7 +1,5 @@
use embassy_hal_internal::into_ref;
use super::{Channel, ConfigurableChannel, Event, Ppi, Task};
use crate::{pac, Peripheral};
use crate::{pac, Peri};
impl<'d> Task<'d> {
fn reg_val(&self) -> u32 {
@ -21,9 +19,7 @@ pub(crate) fn regs() -> pac::ppi::Ppi {
#[cfg(not(feature = "_nrf51"))] // Not for nrf51 because of the fork task
impl<'d, C: super::StaticChannel> Ppi<'d, C, 0, 1> {
/// Configure PPI channel to trigger `task`.
pub fn new_zero_to_one(ch: impl Peripheral<P = C> + 'd, task: Task) -> Self {
into_ref!(ch);
pub fn new_zero_to_one(ch: Peri<'d, C>, task: Task) -> Self {
let r = regs();
let n = ch.number();
r.fork(n).tep().write_value(task.reg_val());
@ -34,9 +30,7 @@ impl<'d, C: super::StaticChannel> Ppi<'d, C, 0, 1> {
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
/// Configure PPI channel to trigger `task` on `event`.
pub fn new_one_to_one(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task: Task<'d>) -> Self {
into_ref!(ch);
pub fn new_one_to_one(ch: Peri<'d, C>, event: Event<'d>, task: Task<'d>) -> Self {
let r = regs();
let n = ch.number();
r.ch(n).eep().write_value(event.reg_val());
@ -49,9 +43,7 @@ impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 1> {
#[cfg(not(feature = "_nrf51"))] // Not for nrf51 because of the fork task
impl<'d, C: ConfigurableChannel> Ppi<'d, C, 1, 2> {
/// Configure PPI channel to trigger both `task1` and `task2` on `event`.
pub fn new_one_to_two(ch: impl Peripheral<P = C> + 'd, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
into_ref!(ch);
pub fn new_one_to_two(ch: Peri<'d, C>, event: Event<'d>, task1: Task<'d>, task2: Task<'d>) -> Self {
let r = regs();
let n = ch.number();
r.ch(n).eep().write_value(event.reg_val());

View File

@ -4,34 +4,34 @@
use core::sync::atomic::{compiler_fence, Ordering};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use crate::gpio::{convert_drive, AnyPin, OutputDrive, Pin as GpioPin, PselBits, SealedPin as _, DISCONNECTED};
use crate::pac::gpio::vals as gpiovals;
use crate::pac::pwm::vals;
use crate::ppi::{Event, Task};
use crate::util::slice_in_ram_or;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// SimplePwm is the traditional pwm interface you're probably used to, allowing
/// to simply set a duty cycle across up to four channels.
pub struct SimplePwm<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
_peri: Peri<'d, T>,
duty: [u16; 4],
ch0: Option<PeripheralRef<'d, AnyPin>>,
ch1: Option<PeripheralRef<'d, AnyPin>>,
ch2: Option<PeripheralRef<'d, AnyPin>>,
ch3: Option<PeripheralRef<'d, AnyPin>>,
ch0: Option<Peri<'d, AnyPin>>,
ch1: Option<Peri<'d, AnyPin>>,
ch2: Option<Peri<'d, AnyPin>>,
ch3: Option<Peri<'d, AnyPin>>,
}
/// SequencePwm allows you to offload the updating of a sequence of duty cycles
/// to up to four channels, as well as repeat that sequence n times.
pub struct SequencePwm<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
ch0: Option<PeripheralRef<'d, AnyPin>>,
ch1: Option<PeripheralRef<'d, AnyPin>>,
ch2: Option<PeripheralRef<'d, AnyPin>>,
ch3: Option<PeripheralRef<'d, AnyPin>>,
_peri: Peri<'d, T>,
ch0: Option<Peri<'d, AnyPin>>,
ch1: Option<Peri<'d, AnyPin>>,
ch2: Option<Peri<'d, AnyPin>>,
ch3: Option<Peri<'d, AnyPin>>,
}
/// PWM error
@ -54,78 +54,61 @@ pub const PWM_CLK_HZ: u32 = 16_000_000;
impl<'d, T: Instance> SequencePwm<'d, T> {
/// Create a new 1-channel PWM
#[allow(unused_unsafe)]
pub fn new_1ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
config: Config,
) -> Result<Self, Error> {
into_ref!(ch0);
Self::new_inner(pwm, Some(ch0.map_into()), None, None, None, config)
pub fn new_1ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, config: Config) -> Result<Self, Error> {
Self::new_inner(pwm, Some(ch0.into()), None, None, None, config)
}
/// Create a new 2-channel PWM
#[allow(unused_unsafe)]
pub fn new_2ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
pwm: Peri<'d, T>,
ch0: Peri<'d, impl GpioPin>,
ch1: Peri<'d, impl GpioPin>,
config: Config,
) -> Result<Self, Error> {
into_ref!(ch0, ch1);
Self::new_inner(pwm, Some(ch0.map_into()), Some(ch1.map_into()), None, None, config)
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None, config)
}
/// Create a new 3-channel PWM
#[allow(unused_unsafe)]
pub fn new_3ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
ch2: impl Peripheral<P = impl GpioPin> + 'd,
pwm: Peri<'d, T>,
ch0: Peri<'d, impl GpioPin>,
ch1: Peri<'d, impl GpioPin>,
ch2: Peri<'d, impl GpioPin>,
config: Config,
) -> Result<Self, Error> {
into_ref!(ch0, ch1, ch2);
Self::new_inner(
pwm,
Some(ch0.map_into()),
Some(ch1.map_into()),
Some(ch2.map_into()),
None,
config,
)
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None, config)
}
/// Create a new 4-channel PWM
#[allow(unused_unsafe)]
pub fn new_4ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
ch2: impl Peripheral<P = impl GpioPin> + 'd,
ch3: impl Peripheral<P = impl GpioPin> + 'd,
pwm: Peri<'d, T>,
ch0: Peri<'d, impl GpioPin>,
ch1: Peri<'d, impl GpioPin>,
ch2: Peri<'d, impl GpioPin>,
ch3: Peri<'d, impl GpioPin>,
config: Config,
) -> Result<Self, Error> {
into_ref!(ch0, ch1, ch2, ch3);
Self::new_inner(
pwm,
Some(ch0.map_into()),
Some(ch1.map_into()),
Some(ch2.map_into()),
Some(ch3.map_into()),
Some(ch0.into()),
Some(ch1.into()),
Some(ch2.into()),
Some(ch3.into()),
config,
)
}
fn new_inner(
_pwm: impl Peripheral<P = T> + 'd,
ch0: Option<PeripheralRef<'d, AnyPin>>,
ch1: Option<PeripheralRef<'d, AnyPin>>,
ch2: Option<PeripheralRef<'d, AnyPin>>,
ch3: Option<PeripheralRef<'d, AnyPin>>,
_pwm: Peri<'d, T>,
ch0: Option<Peri<'d, AnyPin>>,
ch1: Option<Peri<'d, AnyPin>>,
ch2: Option<Peri<'d, AnyPin>>,
ch3: Option<Peri<'d, AnyPin>>,
config: Config,
) -> Result<Self, Error> {
into_ref!(_pwm);
let r = T::regs();
if let Some(pin) = &ch0 {
@ -610,74 +593,54 @@ pub enum CounterMode {
impl<'d, T: Instance> SimplePwm<'d, T> {
/// Create a new 1-channel PWM
#[allow(unused_unsafe)]
pub fn new_1ch(pwm: impl Peripheral<P = T> + 'd, ch0: impl Peripheral<P = impl GpioPin> + 'd) -> Self {
unsafe {
into_ref!(ch0);
Self::new_inner(pwm, Some(ch0.map_into()), None, None, None)
}
pub fn new_1ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>) -> Self {
unsafe { Self::new_inner(pwm, Some(ch0.into()), None, None, None) }
}
/// Create a new 2-channel PWM
#[allow(unused_unsafe)]
pub fn new_2ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
) -> Self {
into_ref!(ch0, ch1);
Self::new_inner(pwm, Some(ch0.map_into()), Some(ch1.map_into()), None, None)
pub fn new_2ch(pwm: Peri<'d, T>, ch0: Peri<'d, impl GpioPin>, ch1: Peri<'d, impl GpioPin>) -> Self {
Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), None, None)
}
/// Create a new 3-channel PWM
#[allow(unused_unsafe)]
pub fn new_3ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
ch2: impl Peripheral<P = impl GpioPin> + 'd,
pwm: Peri<'d, T>,
ch0: Peri<'d, impl GpioPin>,
ch1: Peri<'d, impl GpioPin>,
ch2: Peri<'d, impl GpioPin>,
) -> Self {
unsafe {
into_ref!(ch0, ch1, ch2);
Self::new_inner(
pwm,
Some(ch0.map_into()),
Some(ch1.map_into()),
Some(ch2.map_into()),
None,
)
}
unsafe { Self::new_inner(pwm, Some(ch0.into()), Some(ch1.into()), Some(ch2.into()), None) }
}
/// Create a new 4-channel PWM
#[allow(unused_unsafe)]
pub fn new_4ch(
pwm: impl Peripheral<P = T> + 'd,
ch0: impl Peripheral<P = impl GpioPin> + 'd,
ch1: impl Peripheral<P = impl GpioPin> + 'd,
ch2: impl Peripheral<P = impl GpioPin> + 'd,
ch3: impl Peripheral<P = impl GpioPin> + 'd,
pwm: Peri<'d, T>,
ch0: Peri<'d, impl GpioPin>,
ch1: Peri<'d, impl GpioPin>,
ch2: Peri<'d, impl GpioPin>,
ch3: Peri<'d, impl GpioPin>,
) -> Self {
unsafe {
into_ref!(ch0, ch1, ch2, ch3);
Self::new_inner(
pwm,
Some(ch0.map_into()),
Some(ch1.map_into()),
Some(ch2.map_into()),
Some(ch3.map_into()),
Some(ch0.into()),
Some(ch1.into()),
Some(ch2.into()),
Some(ch3.into()),
)
}
}
fn new_inner(
_pwm: impl Peripheral<P = T> + 'd,
ch0: Option<PeripheralRef<'d, AnyPin>>,
ch1: Option<PeripheralRef<'d, AnyPin>>,
ch2: Option<PeripheralRef<'d, AnyPin>>,
ch3: Option<PeripheralRef<'d, AnyPin>>,
_pwm: Peri<'d, T>,
ch0: Option<Peri<'d, AnyPin>>,
ch1: Option<Peri<'d, AnyPin>>,
ch2: Option<Peri<'d, AnyPin>>,
ch3: Option<Peri<'d, AnyPin>>,
) -> Self {
into_ref!(_pwm);
let r = T::regs();
for (i, ch) in [&ch0, &ch1, &ch2, &ch3].into_iter().enumerate() {
@ -896,7 +859,7 @@ pub(crate) trait SealedInstance {
/// PWM peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -6,18 +6,18 @@ use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{AnyPin, Pin as GpioPin, SealedPin as _};
use crate::interrupt::typelevel::Interrupt;
use crate::pac::gpio::vals as gpiovals;
use crate::pac::qdec::vals;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// Quadrature decoder driver.
pub struct Qdec<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
/// QDEC config
@ -62,34 +62,32 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
impl<'d, T: Instance> Qdec<'d, T> {
/// Create a new QDEC.
pub fn new(
qdec: impl Peripheral<P = T> + 'd,
qdec: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
a: impl Peripheral<P = impl GpioPin> + 'd,
b: impl Peripheral<P = impl GpioPin> + 'd,
a: Peri<'d, impl GpioPin>,
b: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(qdec, a, b);
Self::new_inner(qdec, a.map_into(), b.map_into(), None, config)
Self::new_inner(qdec, a.into(), b.into(), None, config)
}
/// Create a new QDEC, with a pin for LED output.
pub fn new_with_led(
qdec: impl Peripheral<P = T> + 'd,
qdec: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
a: impl Peripheral<P = impl GpioPin> + 'd,
b: impl Peripheral<P = impl GpioPin> + 'd,
led: impl Peripheral<P = impl GpioPin> + 'd,
a: Peri<'d, impl GpioPin>,
b: Peri<'d, impl GpioPin>,
led: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(qdec, a, b, led);
Self::new_inner(qdec, a.map_into(), b.map_into(), Some(led.map_into()), config)
Self::new_inner(qdec, a.into(), b.into(), Some(led.into()), config)
}
fn new_inner(
p: PeripheralRef<'d, T>,
a: PeripheralRef<'d, AnyPin>,
b: PeripheralRef<'d, AnyPin>,
led: Option<PeripheralRef<'d, AnyPin>>,
p: Peri<'d, T>,
a: Peri<'d, AnyPin>,
b: Peri<'d, AnyPin>,
led: Option<Peri<'d, AnyPin>>,
config: Config,
) -> Self {
let r = T::regs();
@ -272,7 +270,7 @@ pub(crate) trait SealedInstance {
/// qdec peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -8,7 +8,7 @@ use core::ptr;
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash};
@ -19,7 +19,7 @@ use crate::pac::qspi::vals;
pub use crate::pac::qspi::vals::{
Addrmode as AddressMode, Ppsize as WritePageSize, Readoc as ReadOpcode, Spimode as SpiMode, Writeoc as WriteOpcode,
};
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// Deep power-down config.
pub struct DeepPowerDownConfig {
@ -139,7 +139,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// QSPI flash driver.
pub struct Qspi<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
_peri: Peri<'d, T>,
dpm_enabled: bool,
capacity: u32,
}
@ -147,18 +147,16 @@ pub struct Qspi<'d, T: Instance> {
impl<'d, T: Instance> Qspi<'d, T> {
/// Create a new QSPI driver.
pub fn new(
qspi: impl Peripheral<P = T> + 'd,
qspi: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
csn: impl Peripheral<P = impl GpioPin> + 'd,
io0: impl Peripheral<P = impl GpioPin> + 'd,
io1: impl Peripheral<P = impl GpioPin> + 'd,
io2: impl Peripheral<P = impl GpioPin> + 'd,
io3: impl Peripheral<P = impl GpioPin> + 'd,
sck: Peri<'d, impl GpioPin>,
csn: Peri<'d, impl GpioPin>,
io0: Peri<'d, impl GpioPin>,
io1: Peri<'d, impl GpioPin>,
io2: Peri<'d, impl GpioPin>,
io3: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(qspi, sck, csn, io0, io1, io2, io3);
let r = T::regs();
macro_rules! config_pin {
@ -664,7 +662,7 @@ pub(crate) trait SealedInstance {
/// QSPI peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -5,7 +5,6 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
pub use pac::radio::vals::Mode;
#[cfg(not(feature = "_nrf51"))]
use pac::radio::vals::Plen as PreambleLength;
@ -15,20 +14,19 @@ use crate::pac::radio::vals;
use crate::radio::*;
pub use crate::radio::{Error, TxPower};
use crate::util::slice_in_ram_or;
use crate::Peri;
/// Radio driver.
pub struct Radio<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Radio<'d, T> {
/// Create a new radio driver.
pub fn new(
radio: impl Peripheral<P = T> + 'd,
radio: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
into_ref!(radio);
let r = T::regs();
r.pcnf1().write(|w| {

View File

@ -4,13 +4,12 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use super::{state, Error, Instance, InterruptHandler, RadioState, TxPower};
use crate::interrupt::typelevel::Interrupt;
use crate::interrupt::{self};
use crate::pac::radio::vals;
use crate::Peripheral;
use crate::Peri;
/// Default (IEEE compliant) Start of Frame Delimiter
pub const DEFAULT_SFD: u8 = 0xA7;
@ -33,18 +32,16 @@ pub enum Cca {
/// IEEE 802.15.4 radio driver.
pub struct Radio<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
needs_enable: bool,
}
impl<'d, T: Instance> Radio<'d, T> {
/// Create a new IEEE 802.15.4 radio driver.
pub fn new(
radio: impl Peripheral<P = T> + 'd,
radio: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
into_ref!(radio);
let r = T::regs();
// Disable and enable to reset peripheral

View File

@ -19,11 +19,12 @@ pub mod ieee802154;
use core::marker::PhantomData;
use embassy_hal_internal::PeripheralType;
use embassy_sync::waitqueue::AtomicWaker;
use pac::radio::vals::State as RadioState;
pub use pac::radio::vals::Txpower as TxPower;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// RADIO error.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -94,7 +95,7 @@ macro_rules! impl_radio {
/// Radio peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -10,11 +10,11 @@ use core::task::Poll;
use critical_section::{CriticalSection, Mutex};
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::WakerRegistration;
use crate::interrupt::typelevel::Interrupt;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// Interrupt handler.
pub struct InterruptHandler<T: Instance> {
@ -56,7 +56,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
///
/// It has a non-blocking API, and a blocking api through `rand`.
pub struct Rng<'d, T: Instance> {
_peri: PeripheralRef<'d, T>,
_peri: Peri<'d, T>,
}
impl<'d, T: Instance> Rng<'d, T> {
@ -67,11 +67,9 @@ impl<'d, T: Instance> Rng<'d, T> {
///
/// The synchronous API is safe.
pub fn new(
rng: impl Peripheral<P = T> + 'd,
rng: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
into_ref!(rng);
let this = Self { _peri: rng };
this.stop();
@ -250,7 +248,7 @@ pub(crate) trait SealedInstance {
/// RNG peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -3,11 +3,12 @@
#![macro_use]
use core::future::poll_fn;
use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri};
use embassy_sync::waitqueue::AtomicWaker;
pub(crate) use vals::Psel as InputChannel;
@ -15,7 +16,7 @@ use crate::interrupt::InterruptExt;
use crate::pac::saadc::vals;
use crate::ppi::{ConfigurableChannel, Event, Ppi, Task};
use crate::timer::{Frequency, Instance as TimerInstance, Timer};
use crate::{interrupt, pac, peripherals, Peripheral};
use crate::{interrupt, pac, peripherals};
/// SAADC error
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -87,37 +88,32 @@ pub struct ChannelConfig<'d> {
/// Acquisition time in microseconds.
pub time: Time,
/// Positive channel to sample
p_channel: PeripheralRef<'d, AnyInput>,
p_channel: AnyInput<'d>,
/// An optional negative channel to sample
n_channel: Option<PeripheralRef<'d, AnyInput>>,
n_channel: Option<AnyInput<'d>>,
}
impl<'d> ChannelConfig<'d> {
/// Default configuration for single ended channel sampling.
pub fn single_ended(input: impl Peripheral<P = impl Input> + 'd) -> Self {
into_ref!(input);
pub fn single_ended(input: impl Input + 'd) -> Self {
Self {
reference: Reference::INTERNAL,
gain: Gain::GAIN1_6,
resistor: Resistor::BYPASS,
time: Time::_10US,
p_channel: input.map_into(),
p_channel: input.degrade_saadc(),
n_channel: None,
}
}
/// Default configuration for differential channel sampling.
pub fn differential(
p_input: impl Peripheral<P = impl Input> + 'd,
n_input: impl Peripheral<P = impl Input> + 'd,
) -> Self {
into_ref!(p_input, n_input);
pub fn differential(p_input: impl Input + 'd, n_input: impl Input + 'd) -> Self {
Self {
reference: Reference::INTERNAL,
gain: Gain::GAIN1_6,
resistor: Resistor::BYPASS,
time: Time::_10US,
p_channel: p_input.map_into(),
n_channel: Some(n_input.map_into()),
p_channel: p_input.degrade_saadc(),
n_channel: Some(n_input.degrade_saadc()),
}
}
}
@ -133,19 +129,17 @@ pub enum CallbackResult {
/// One-shot and continuous SAADC.
pub struct Saadc<'d, const N: usize> {
_p: PeripheralRef<'d, peripherals::SAADC>,
_p: Peri<'d, peripherals::SAADC>,
}
impl<'d, const N: usize> Saadc<'d, N> {
/// Create a new SAADC driver.
pub fn new(
saadc: impl Peripheral<P = peripherals::SAADC> + 'd,
saadc: Peri<'d, peripherals::SAADC>,
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::SAADC, InterruptHandler> + 'd,
config: Config,
channel_configs: [ChannelConfig; N],
) -> Self {
into_ref!(saadc);
let r = pac::SAADC;
let Config { resolution, oversample } = config;
@ -284,9 +278,9 @@ impl<'d, const N: usize> Saadc<'d, N> {
pub async fn run_task_sampler<F, T: TimerInstance, const N0: usize>(
&mut self,
timer: &mut T,
ppi_ch1: &mut impl ConfigurableChannel,
ppi_ch2: &mut impl ConfigurableChannel,
timer: Peri<'_, T>,
ppi_ch1: Peri<'_, impl ConfigurableChannel>,
ppi_ch2: Peri<'_, impl ConfigurableChannel>,
frequency: Frequency,
sample_counter: u32,
bufs: &mut [[[i16; N]; N0]; 2],
@ -465,6 +459,10 @@ impl<'d, const N: usize> Drop for Saadc<'d, N> {
fn drop(&mut self) {
let r = Self::regs();
r.enable().write(|w| w.set_enable(false));
for i in 0..N {
r.ch(i).pselp().write(|w| w.set_pselp(InputChannel::NC));
r.ch(i).pseln().write(|w| w.set_pseln(InputChannel::NC));
}
}
}
@ -651,14 +649,18 @@ pub(crate) trait SealedInput {
/// An input that can be used as either or negative end of a ADC differential in the SAADC periperhal.
#[allow(private_bounds)]
pub trait Input: SealedInput + Into<AnyInput> + Peripheral<P = Self> + Sized + 'static {
pub trait Input: SealedInput + Sized {
/// Convert this SAADC input to a type-erased `AnyInput`.
///
/// This allows using several inputs in situations that might require
/// them to be the same type, like putting them in an array.
fn degrade_saadc(self) -> AnyInput {
fn degrade_saadc<'a>(self) -> AnyInput<'a>
where
Self: 'a,
{
AnyInput {
channel: self.channel(),
_phantom: core::marker::PhantomData,
}
}
}
@ -667,23 +669,36 @@ pub trait Input: SealedInput + Into<AnyInput> + Peripheral<P = Self> + Sized + '
///
/// This allows using several inputs in situations that might require
/// them to be the same type, like putting them in an array.
pub struct AnyInput {
pub struct AnyInput<'a> {
channel: InputChannel,
_phantom: PhantomData<&'a ()>,
}
impl_peripheral!(AnyInput);
impl<'a> AnyInput<'a> {
/// Reborrow into a "child" AnyInput.
///
/// `self` will stay borrowed until the child AnyInput is dropped.
pub fn reborrow(&mut self) -> AnyInput<'_> {
// safety: we're returning the clone inside a new Peripheral that borrows
// self, so user code can't use both at the same time.
Self {
channel: self.channel,
_phantom: PhantomData,
}
}
}
impl SealedInput for AnyInput {
impl SealedInput for AnyInput<'_> {
fn channel(&self) -> InputChannel {
self.channel
}
}
impl Input for AnyInput {}
impl Input for AnyInput<'_> {}
macro_rules! impl_saadc_input {
($pin:ident, $ch:ident) => {
impl_saadc_input!(@local, crate::peripherals::$pin, $ch);
impl_saadc_input!(@local, crate::Peri<'_, crate::peripherals::$pin>, $ch);
};
(@local, $pin:ty, $ch:ident) => {
impl crate::saadc::SealedInput for $pin {
@ -692,12 +707,6 @@ macro_rules! impl_saadc_input {
}
}
impl crate::saadc::Input for $pin {}
impl From<$pin> for crate::saadc::AnyInput {
fn from(val: $pin) -> Self {
crate::saadc::Input::degrade_saadc(val)
}
}
};
}

View File

@ -10,7 +10,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_embedded_hal::SetConfig;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
pub use pac::spim::vals::{Frequency, Order as BitOrder};
@ -21,7 +21,7 @@ use crate::interrupt::typelevel::Interrupt;
use crate::pac::gpio::vals as gpiovals;
use crate::pac::spim::vals;
use crate::util::slice_in_ram_or;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// SPIM error
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -100,73 +100,61 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// SPIM driver.
pub struct Spim<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Spim<'d, T> {
/// Create a new SPIM driver.
pub fn new(
spim: impl Peripheral<P = T> + 'd,
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
miso: impl Peripheral<P = impl GpioPin> + 'd,
mosi: impl Peripheral<P = impl GpioPin> + 'd,
sck: Peri<'d, impl GpioPin>,
miso: Peri<'d, impl GpioPin>,
mosi: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(sck, miso, mosi);
Self::new_inner(
spim,
Some(sck.map_into()),
Some(miso.map_into()),
Some(mosi.map_into()),
config,
)
Self::new_inner(spim, Some(sck.into()), Some(miso.into()), Some(mosi.into()), config)
}
/// Create a new SPIM driver, capable of TX only (MOSI only).
pub fn new_txonly(
spim: impl Peripheral<P = T> + 'd,
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
mosi: impl Peripheral<P = impl GpioPin> + 'd,
sck: Peri<'d, impl GpioPin>,
mosi: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(sck, mosi);
Self::new_inner(spim, Some(sck.map_into()), None, Some(mosi.map_into()), config)
Self::new_inner(spim, Some(sck.into()), None, Some(mosi.into()), config)
}
/// Create a new SPIM driver, capable of RX only (MISO only).
pub fn new_rxonly(
spim: impl Peripheral<P = T> + 'd,
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
miso: impl Peripheral<P = impl GpioPin> + 'd,
sck: Peri<'d, impl GpioPin>,
miso: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(sck, miso);
Self::new_inner(spim, Some(sck.map_into()), Some(miso.map_into()), None, config)
Self::new_inner(spim, Some(sck.into()), Some(miso.into()), None, config)
}
/// Create a new SPIM driver, capable of TX only (MOSI only), without SCK pin.
pub fn new_txonly_nosck(
spim: impl Peripheral<P = T> + 'd,
spim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
mosi: impl Peripheral<P = impl GpioPin> + 'd,
mosi: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(mosi);
Self::new_inner(spim, None, None, Some(mosi.map_into()), config)
Self::new_inner(spim, None, None, Some(mosi.into()), config)
}
fn new_inner(
spim: impl Peripheral<P = T> + 'd,
sck: Option<PeripheralRef<'d, AnyPin>>,
miso: Option<PeripheralRef<'d, AnyPin>>,
mosi: Option<PeripheralRef<'d, AnyPin>>,
spim: Peri<'d, T>,
sck: Option<Peri<'d, AnyPin>>,
miso: Option<Peri<'d, AnyPin>>,
mosi: Option<Peri<'d, AnyPin>>,
config: Config,
) -> Self {
into_ref!(spim);
let r = T::regs();
// Configure pins
@ -511,7 +499,7 @@ pub(crate) trait SealedInstance {
/// SPIM peripheral instance
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

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_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
pub use pac::spis::vals::Order as BitOrder;
@ -18,7 +18,7 @@ use crate::interrupt::typelevel::Interrupt;
use crate::pac::gpio::vals as gpiovals;
use crate::pac::spis::vals;
use crate::util::slice_in_ram_or;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// SPIS error
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -98,95 +98,75 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// SPIS driver.
pub struct Spis<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Spis<'d, T> {
/// Create a new SPIS driver.
pub fn new(
spis: impl Peripheral<P = T> + 'd,
spis: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
cs: impl Peripheral<P = impl GpioPin> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
miso: impl Peripheral<P = impl GpioPin> + 'd,
mosi: impl Peripheral<P = impl GpioPin> + 'd,
cs: Peri<'d, impl GpioPin>,
sck: Peri<'d, impl GpioPin>,
miso: Peri<'d, impl GpioPin>,
mosi: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(cs, sck, miso, mosi);
Self::new_inner(
spis,
cs.map_into(),
Some(sck.map_into()),
Some(miso.map_into()),
Some(mosi.map_into()),
cs.into(),
Some(sck.into()),
Some(miso.into()),
Some(mosi.into()),
config,
)
}
/// Create a new SPIS driver, capable of TX only (MISO only).
pub fn new_txonly(
spis: impl Peripheral<P = T> + 'd,
spis: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
cs: impl Peripheral<P = impl GpioPin> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
miso: impl Peripheral<P = impl GpioPin> + 'd,
cs: Peri<'d, impl GpioPin>,
sck: Peri<'d, impl GpioPin>,
miso: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(cs, sck, miso);
Self::new_inner(
spis,
cs.map_into(),
Some(sck.map_into()),
Some(miso.map_into()),
None,
config,
)
Self::new_inner(spis, cs.into(), Some(sck.into()), Some(miso.into()), None, config)
}
/// Create a new SPIS driver, capable of RX only (MOSI only).
pub fn new_rxonly(
spis: impl Peripheral<P = T> + 'd,
spis: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
cs: impl Peripheral<P = impl GpioPin> + 'd,
sck: impl Peripheral<P = impl GpioPin> + 'd,
mosi: impl Peripheral<P = impl GpioPin> + 'd,
cs: Peri<'d, impl GpioPin>,
sck: Peri<'d, impl GpioPin>,
mosi: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(cs, sck, mosi);
Self::new_inner(
spis,
cs.map_into(),
Some(sck.map_into()),
None,
Some(mosi.map_into()),
config,
)
Self::new_inner(spis, cs.into(), Some(sck.into()), None, Some(mosi.into()), config)
}
/// Create a new SPIS driver, capable of TX only (MISO only) without SCK pin.
pub fn new_txonly_nosck(
spis: impl Peripheral<P = T> + 'd,
spis: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
cs: impl Peripheral<P = impl GpioPin> + 'd,
miso: impl Peripheral<P = impl GpioPin> + 'd,
cs: Peri<'d, impl GpioPin>,
miso: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(cs, miso);
Self::new_inner(spis, cs.map_into(), None, Some(miso.map_into()), None, config)
Self::new_inner(spis, cs.into(), None, Some(miso.into()), None, config)
}
fn new_inner(
spis: impl Peripheral<P = T> + 'd,
cs: PeripheralRef<'d, AnyPin>,
sck: Option<PeripheralRef<'d, AnyPin>>,
miso: Option<PeripheralRef<'d, AnyPin>>,
mosi: Option<PeripheralRef<'d, AnyPin>>,
spis: Peri<'d, T>,
cs: Peri<'d, AnyPin>,
sck: Option<Peri<'d, AnyPin>>,
miso: Option<Peri<'d, AnyPin>>,
mosi: Option<Peri<'d, AnyPin>>,
config: Config,
) -> Self {
compiler_fence(Ordering::SeqCst);
into_ref!(spis, cs);
let r = T::regs();
// Configure pins.
@ -485,7 +465,7 @@ pub(crate) trait SealedInstance {
/// SPIS peripheral instance
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -4,13 +4,12 @@ use core::future::poll_fn;
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use fixed::types::I30F2;
use crate::interrupt::InterruptExt;
use crate::peripherals::TEMP;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac, Peri};
/// Interrupt handler.
pub struct InterruptHandler {
@ -27,7 +26,7 @@ impl interrupt::typelevel::Handler<interrupt::typelevel::TEMP> for InterruptHand
/// Builtin temperature sensor driver.
pub struct Temp<'d> {
_peri: PeripheralRef<'d, TEMP>,
_peri: Peri<'d, TEMP>,
}
static WAKER: AtomicWaker = AtomicWaker::new();
@ -35,11 +34,9 @@ static WAKER: AtomicWaker = AtomicWaker::new();
impl<'d> Temp<'d> {
/// Create a new temperature sensor driver.
pub fn new(
_peri: impl Peripheral<P = TEMP> + 'd,
_peri: Peri<'d, TEMP>,
_irq: impl interrupt::typelevel::Binding<interrupt::typelevel::TEMP, InterruptHandler> + 'd,
) -> Self {
into_ref!(_peri);
// Enable interrupt that signals temperature values
interrupt::TEMP.unpend();
unsafe { interrupt::TEMP.enable() };

View File

@ -6,11 +6,11 @@
#![macro_use]
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use crate::pac;
use crate::pac::timer::vals;
use crate::ppi::{Event, Task};
use crate::{pac, Peripheral};
pub(crate) trait SealedInstance {
/// The number of CC registers this instance has.
@ -20,7 +20,7 @@ pub(crate) trait SealedInstance {
/// Basic Timer instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: crate::interrupt::typelevel::Interrupt;
}
@ -84,7 +84,7 @@ pub enum Frequency {
/// Timer driver.
pub struct Timer<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Timer<'d, T> {
@ -92,7 +92,7 @@ impl<'d, T: Instance> Timer<'d, T> {
///
/// This can be useful for triggering tasks via PPI
/// `Uarte` uses this internally.
pub fn new(timer: impl Peripheral<P = T> + 'd) -> Self {
pub fn new(timer: Peri<'d, T>) -> Self {
Self::new_inner(timer, false)
}
@ -100,13 +100,11 @@ impl<'d, T: Instance> Timer<'d, T> {
///
/// This can be useful for triggering tasks via PPI
/// `Uarte` uses this internally.
pub fn new_counter(timer: impl Peripheral<P = T> + 'd) -> Self {
pub fn new_counter(timer: Peri<'d, T>) -> Self {
Self::new_inner(timer, true)
}
fn new_inner(timer: impl Peripheral<P = T> + 'd, _is_counter: bool) -> Self {
into_ref!(timer);
fn new_inner(timer: Peri<'d, T>, _is_counter: bool) -> Self {
let regs = T::regs();
let this = Self { _p: timer };
@ -229,7 +227,7 @@ impl<'d, T: Instance> Timer<'d, T> {
/// When the register's CAPTURE task is triggered, the timer will store the current value of its counter in the register
pub struct Cc<'d, T: Instance> {
n: usize,
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Cc<'d, T> {

View File

@ -10,7 +10,7 @@ use core::sync::atomic::Ordering::SeqCst;
use core::task::Poll;
use embassy_embedded_hal::SetConfig;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")]
use embassy_time::{Duration, Instant};
@ -23,7 +23,7 @@ use crate::interrupt::typelevel::Interrupt;
use crate::pac::gpio::vals as gpiovals;
use crate::pac::twim::vals;
use crate::util::slice_in_ram;
use crate::{gpio, interrupt, pac, Peripheral};
use crate::{gpio, interrupt, pac};
/// TWIM config.
#[non_exhaustive]
@ -114,20 +114,18 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// TWI driver.
pub struct Twim<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Twim<'d, T> {
/// Create a new TWI driver.
pub fn new(
twim: impl Peripheral<P = T> + 'd,
twim: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sda: impl Peripheral<P = impl GpioPin> + 'd,
scl: impl Peripheral<P = impl GpioPin> + 'd,
sda: Peri<'d, impl GpioPin>,
scl: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(twim, sda, scl);
let r = T::regs();
// Configure pins
@ -847,7 +845,7 @@ pub(crate) trait SealedInstance {
/// TWIM peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

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_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
#[cfg(feature = "time")]
use embassy_time::{Duration, Instant};
@ -19,7 +19,7 @@ use crate::interrupt::typelevel::Interrupt;
use crate::pac::gpio::vals as gpiovals;
use crate::pac::twis::vals;
use crate::util::slice_in_ram_or;
use crate::{gpio, interrupt, pac, Peripheral};
use crate::{gpio, interrupt, pac};
/// TWIS config.
#[non_exhaustive]
@ -141,20 +141,18 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// TWIS driver.
pub struct Twis<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Twis<'d, T> {
/// Create a new TWIS driver.
pub fn new(
twis: impl Peripheral<P = T> + 'd,
twis: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
sda: impl Peripheral<P = impl GpioPin> + 'd,
scl: impl Peripheral<P = impl GpioPin> + 'd,
sda: Peri<'d, impl GpioPin>,
scl: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(twis, sda, scl);
let r = T::regs();
// Configure pins
@ -791,7 +789,7 @@ pub(crate) trait SealedInstance {
/// TWIS peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -19,7 +19,7 @@ use core::sync::atomic::{compiler_fence, AtomicU8, Ordering};
use core::task::Poll;
use embassy_hal_internal::drop::OnDrop;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
// Re-export SVD variants to allow user to directly set values.
pub use pac::uarte::vals::{Baudrate, ConfigParity as Parity};
@ -32,7 +32,7 @@ use crate::pac::uarte::vals;
use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task};
use crate::timer::{Frequency, Instance as TimerInstance, Timer};
use crate::util::slice_in_ram_or;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
/// UARTE config.
#[derive(Clone)]
@ -141,56 +141,54 @@ pub struct Uarte<'d, T: Instance> {
///
/// This can be obtained via [`Uarte::split`], or created directly.
pub struct UarteTx<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
/// Receiver part of the UARTE driver.
///
/// This can be obtained via [`Uarte::split`], or created directly.
pub struct UarteRx<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
}
impl<'d, T: Instance> Uarte<'d, T> {
/// Create a new UARTE without hardware flow control
pub fn new(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, rxd, txd);
Self::new_inner(uarte, rxd.map_into(), txd.map_into(), None, None, config)
Self::new_inner(uarte, rxd.into(), txd.into(), None, None, config)
}
/// Create a new UARTE with hardware flow control (RTS/CTS)
pub fn new_with_rtscts(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
cts: impl Peripheral<P = impl GpioPin> + 'd,
rts: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, rxd, txd, cts, rts);
Self::new_inner(
uarte,
rxd.map_into(),
txd.map_into(),
Some(cts.map_into()),
Some(rts.map_into()),
rxd.into(),
txd.into(),
Some(cts.into()),
Some(rts.into()),
config,
)
}
fn new_inner(
uarte: PeripheralRef<'d, T>,
rxd: PeripheralRef<'d, AnyPin>,
txd: PeripheralRef<'d, AnyPin>,
cts: Option<PeripheralRef<'d, AnyPin>>,
rts: Option<PeripheralRef<'d, AnyPin>>,
uarte: Peri<'d, T>,
rxd: Peri<'d, AnyPin>,
txd: Peri<'d, AnyPin>,
cts: Option<Peri<'d, AnyPin>>,
rts: Option<Peri<'d, AnyPin>>,
config: Config,
) -> Self {
let r = T::regs();
@ -239,9 +237,9 @@ impl<'d, T: Instance> Uarte<'d, T> {
/// This is useful to concurrently transmit and receive from independent tasks.
pub fn split_with_idle<U: TimerInstance>(
self,
timer: impl Peripheral<P = U> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
timer: Peri<'d, U>,
ppi_ch1: Peri<'d, impl ConfigurableChannel + 'd>,
ppi_ch2: Peri<'d, impl ConfigurableChannel + 'd>,
) -> (UarteTx<'d, T>, UarteRxWithIdle<'d, T, U>) {
(self.tx, self.rx.with_idle(timer, ppi_ch1, ppi_ch2))
}
@ -283,11 +281,7 @@ impl<'d, T: Instance> Uarte<'d, T> {
}
}
pub(crate) fn configure_tx_pins(
r: pac::uarte::Uarte,
txd: PeripheralRef<'_, AnyPin>,
cts: Option<PeripheralRef<'_, AnyPin>>,
) {
pub(crate) fn configure_tx_pins(r: pac::uarte::Uarte, txd: Peri<'_, AnyPin>, cts: Option<Peri<'_, AnyPin>>) {
txd.set_high();
txd.conf().write(|w| {
w.set_dir(gpiovals::Dir::OUTPUT);
@ -306,11 +300,7 @@ pub(crate) fn configure_tx_pins(
r.psel().cts().write_value(cts.psel_bits());
}
pub(crate) fn configure_rx_pins(
r: pac::uarte::Uarte,
rxd: PeripheralRef<'_, AnyPin>,
rts: Option<PeripheralRef<'_, AnyPin>>,
) {
pub(crate) fn configure_rx_pins(r: pac::uarte::Uarte, rxd: Peri<'_, AnyPin>, rts: Option<Peri<'_, AnyPin>>) {
rxd.conf().write(|w| {
w.set_dir(gpiovals::Dir::INPUT);
w.set_input(gpiovals::Input::CONNECT);
@ -356,33 +346,26 @@ pub(crate) fn configure(r: pac::uarte::Uarte, config: Config, hardware_flow_cont
impl<'d, T: Instance> UarteTx<'d, T> {
/// Create a new tx-only UARTE without hardware flow control
pub fn new(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
txd: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, txd);
Self::new_inner(uarte, txd.map_into(), None, config)
Self::new_inner(uarte, txd.into(), None, config)
}
/// Create a new tx-only UARTE with hardware flow control (RTS/CTS)
pub fn new_with_rtscts(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
txd: impl Peripheral<P = impl GpioPin> + 'd,
cts: impl Peripheral<P = impl GpioPin> + 'd,
txd: Peri<'d, impl GpioPin>,
cts: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, txd, cts);
Self::new_inner(uarte, txd.map_into(), Some(cts.map_into()), config)
Self::new_inner(uarte, txd.into(), Some(cts.into()), config)
}
fn new_inner(
uarte: PeripheralRef<'d, T>,
txd: PeripheralRef<'d, AnyPin>,
cts: Option<PeripheralRef<'d, AnyPin>>,
config: Config,
) -> Self {
fn new_inner(uarte: Peri<'d, T>, txd: Peri<'d, AnyPin>, cts: Option<Peri<'d, AnyPin>>, config: Config) -> Self {
let r = T::regs();
configure(r, config, cts.is_some());
@ -539,25 +522,23 @@ impl<'a, T: Instance> Drop for UarteTx<'a, T> {
impl<'d, T: Instance> UarteRx<'d, T> {
/// Create a new rx-only UARTE without hardware flow control
pub fn new(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, rxd);
Self::new_inner(uarte, rxd.map_into(), None, config)
Self::new_inner(uarte, rxd.into(), None, config)
}
/// Create a new rx-only UARTE with hardware flow control (RTS/CTS)
pub fn new_with_rtscts(
uarte: impl Peripheral<P = T> + 'd,
uarte: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
rxd: impl Peripheral<P = impl GpioPin> + 'd,
rts: impl Peripheral<P = impl GpioPin> + 'd,
rxd: Peri<'d, impl GpioPin>,
rts: Peri<'d, impl GpioPin>,
config: Config,
) -> Self {
into_ref!(uarte, rxd, rts);
Self::new_inner(uarte, rxd.map_into(), Some(rts.map_into()), config)
Self::new_inner(uarte, rxd.into(), Some(rts.into()), config)
}
/// Check for errors and clear the error register if an error occured.
@ -568,12 +549,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
ErrorSource::from_bits_truncate(err_bits.0).check()
}
fn new_inner(
uarte: PeripheralRef<'d, T>,
rxd: PeripheralRef<'d, AnyPin>,
rts: Option<PeripheralRef<'d, AnyPin>>,
config: Config,
) -> Self {
fn new_inner(uarte: Peri<'d, T>, rxd: Peri<'d, AnyPin>, rts: Option<Peri<'d, AnyPin>>, config: Config) -> Self {
let r = T::regs();
configure(r, config, rts.is_some());
@ -592,14 +568,12 @@ impl<'d, T: Instance> UarteRx<'d, T> {
/// Upgrade to an instance that supports idle line detection.
pub fn with_idle<U: TimerInstance>(
self,
timer: impl Peripheral<P = U> + 'd,
ppi_ch1: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
ppi_ch2: impl Peripheral<P = impl ConfigurableChannel + 'd> + 'd,
timer: Peri<'d, U>,
ppi_ch1: Peri<'d, impl ConfigurableChannel + 'd>,
ppi_ch2: Peri<'d, impl ConfigurableChannel + 'd>,
) -> UarteRxWithIdle<'d, T, U> {
let timer = Timer::new(timer);
into_ref!(ppi_ch1, ppi_ch2);
let r = T::regs();
// BAUDRATE register values are `baudrate * 2^32 / 16000000`
@ -617,7 +591,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
timer.cc(0).short_compare_stop();
let mut ppi_ch1 = Ppi::new_one_to_two(
ppi_ch1.map_into(),
ppi_ch1.into(),
Event::from_reg(r.events_rxdrdy()),
timer.task_clear(),
timer.task_start(),
@ -625,7 +599,7 @@ impl<'d, T: Instance> UarteRx<'d, T> {
ppi_ch1.enable();
let mut ppi_ch2 = Ppi::new_one_to_one(
ppi_ch2.map_into(),
ppi_ch2.into(),
timer.cc(0).event_compare(),
Task::from_reg(r.tasks_stoprx()),
);
@ -992,7 +966,7 @@ pub(crate) trait SealedInstance {
/// UARTE peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

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_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver as driver;
use embassy_usb_driver::{Direction, EndpointAddress, EndpointError, EndpointInfo, EndpointType, Event, Unsupported};
@ -20,7 +20,7 @@ use self::vbus_detect::VbusDetect;
use crate::interrupt::typelevel::Interrupt;
use crate::pac::usbd::vals;
use crate::util::slice_in_ram;
use crate::{interrupt, pac, Peripheral};
use crate::{interrupt, pac};
static BUS_WAKER: AtomicWaker = AtomicWaker::new();
static EP0_WAKER: AtomicWaker = AtomicWaker::new();
@ -87,7 +87,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
/// USB driver.
pub struct Driver<'d, T: Instance, V: VbusDetect> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
alloc_in: Allocator,
alloc_out: Allocator,
vbus_detect: V,
@ -96,12 +96,10 @@ pub struct Driver<'d, T: Instance, V: VbusDetect> {
impl<'d, T: Instance, V: VbusDetect> Driver<'d, T, V> {
/// Create a new USB driver.
pub fn new(
usb: impl Peripheral<P = T> + 'd,
usb: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
vbus_detect: V,
) -> Self {
into_ref!(usb);
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };
@ -169,7 +167,7 @@ impl<'d, T: Instance, V: VbusDetect + 'd> driver::Driver<'d> for Driver<'d, T, V
/// USB bus.
pub struct Bus<'d, T: Instance, V: VbusDetect> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
power_available: bool,
vbus_detect: V,
}
@ -592,7 +590,7 @@ impl<'d, T: Instance> driver::EndpointIn for Endpoint<'d, T, In> {
/// USB control pipe.
pub struct ControlPipe<'d, T: Instance> {
_p: PeripheralRef<'d, T>,
_p: Peri<'d, T>,
max_packet_size: u16,
}
@ -779,7 +777,7 @@ pub(crate) trait SealedInstance {
/// USB peripheral instance.
#[allow(private_bounds)]
pub trait Instance: Peripheral<P = Self> + SealedInstance + 'static + Send {
pub trait Instance: SealedInstance + PeripheralType + 'static + Send {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -3,9 +3,11 @@
//! This HAL implements a basic watchdog timer with 1..=8 handles.
//! Once the watchdog has been started, it cannot be stopped.
use core::marker::PhantomData;
use crate::pac::wdt::vals;
pub use crate::pac::wdt::vals::{Halt as HaltConfig, Sleep as SleepConfig};
use crate::peripherals;
use crate::{peripherals, Peri};
const MIN_TICKS: u32 = 15;
@ -61,7 +63,7 @@ impl Default for Config {
/// Watchdog driver.
pub struct Watchdog {
_private: (),
_wdt: Peri<'static, peripherals::WDT>,
}
impl Watchdog {
@ -74,9 +76,9 @@ impl Watchdog {
/// `N` must be between 1 and 8, inclusive.
#[inline]
pub fn try_new<const N: usize>(
wdt: peripherals::WDT,
wdt: Peri<'static, peripherals::WDT>,
config: Config,
) -> Result<(Self, [WatchdogHandle; N]), peripherals::WDT> {
) -> Result<(Self, [WatchdogHandle; N]), Peri<'static, peripherals::WDT>> {
assert!(N >= 1 && N <= 8);
let r = crate::pac::WDT;
@ -110,11 +112,19 @@ impl Watchdog {
r.tasks_start().write_value(1);
}
let this = Self { _private: () };
let this = Self { _wdt: wdt };
let mut handles = [const { WatchdogHandle { index: 0 } }; N];
let mut handles = [const {
WatchdogHandle {
_wdt: PhantomData,
index: 0,
}
}; N];
for i in 0..N {
handles[i] = WatchdogHandle { index: i as u8 };
handles[i] = WatchdogHandle {
_wdt: PhantomData,
index: i as u8,
};
handles[i].pet();
}
@ -155,6 +165,7 @@ impl Watchdog {
/// Watchdog handle.
pub struct WatchdogHandle {
_wdt: PhantomData<Peri<'static, peripherals::WDT>>,
index: u8,
}
@ -183,6 +194,9 @@ impl WatchdogHandle {
/// Watchdog must be initialized and `index` must be between `0` and `N-1`
/// where `N` is the handle count when initializing.
pub unsafe fn steal(index: u8) -> Self {
Self { index }
Self {
_wdt: PhantomData,
index,
}
}
}

View File

@ -1,7 +1,7 @@
use embassy_hal_internal::impl_peripheral;
use embassy_hal_internal::{impl_peripheral, PeripheralType};
use crate::pac_utils::*;
use crate::{peripherals, Peripheral, PeripheralRef};
use crate::{peripherals, Peri};
pub(crate) fn init() {
// Enable clocks for GPIO, PINT, and IOCON
@ -45,7 +45,7 @@ pub struct Output<'d> {
impl<'d> Output<'d> {
/// Create GPIO output driver for a [Pin] with the provided [initial output](Level).
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_output();
let mut result = Self { pin };
@ -90,7 +90,7 @@ pub struct Input<'d> {
impl<'d> Input<'d> {
/// Create GPIO output driver for a [Pin] with the provided [Pull].
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, pull: Pull) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input();
let mut result = Self { pin };
@ -124,7 +124,7 @@ impl<'d> Input<'d> {
/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a
/// reference to a type-erased pin called ["AnyPin"](AnyPin).
pub struct Flex<'d> {
pub(crate) pin: PeripheralRef<'d, AnyPin>,
pub(crate) pin: Peri<'d, AnyPin>,
}
impl<'d> Flex<'d> {
@ -132,10 +132,8 @@ impl<'d> Flex<'d> {
///
/// Note: you cannot assume that the pin will be in Digital mode after this call.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd) -> Self {
Self {
pin: pin.into_ref().map_into(),
}
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
Self { pin: pin.into() }
}
/// Get the bank of this pin. See also [Bank].
@ -218,15 +216,7 @@ pub(crate) trait SealedPin: Sized {
/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the
/// `embassy-nxp` crate due to the [SealedPin] trait.
#[allow(private_bounds)]
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static {
/// Degrade to a generic pin struct
fn degrade(self) -> AnyPin {
AnyPin {
pin_bank: self.pin_bank(),
pin_number: self.pin_number(),
}
}
pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
/// Returns the pin number within a bank
#[inline]
fn pin(&self) -> u8 {
@ -252,8 +242,8 @@ impl AnyPin {
/// # Safety
///
/// You must ensure that youre only using one instance of this type at a time.
pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Self {
Self { pin_bank, pin_number }
pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> {
Peri::new_unchecked(Self { pin_bank, pin_number })
}
}
@ -289,7 +279,10 @@ macro_rules! impl_pin {
impl From<peripherals::$name> for crate::gpio::AnyPin {
fn from(val: peripherals::$name) -> Self {
crate::gpio::Pin::degrade(val)
Self {
pin_bank: val.pin_bank(),
pin_number: val.pin_number(),
}
}
}
};

View File

@ -4,7 +4,7 @@ pub mod gpio;
mod pac_utils;
pub mod pint;
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
pub use embassy_hal_internal::Peri;
pub use lpc55_pac as pac;
/// Initialize the `embassy-nxp` HAL with the provided configuration.

View File

@ -5,12 +5,12 @@ use core::pin::Pin as FuturePin;
use core::task::{Context, Poll};
use critical_section::Mutex;
use embassy_hal_internal::{Peripheral, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{self, AnyPin, Level, SealedPin};
use crate::pac::interrupt;
use crate::pac_utils::*;
use crate::Peri;
struct PinInterrupt {
assigned: bool,
@ -107,14 +107,14 @@ pub(crate) fn init() {
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct InputFuture<'d> {
#[allow(dead_code)]
pin: PeripheralRef<'d, AnyPin>,
pin: Peri<'d, AnyPin>,
interrupt_number: usize,
}
impl<'d> InputFuture<'d> {
/// Create a new input future. Returns None if all interrupts are in use.
fn new(pin: impl Peripheral<P = impl gpio::Pin> + 'd, interrupt_on: InterruptOn) -> Option<Self> {
let pin = pin.into_ref().map_into();
fn new(pin: Peri<'d, impl gpio::Pin>, interrupt_on: InterruptOn) -> Option<Self> {
let pin = pin.into();
let interrupt_number = next_available_interrupt()?;
// Clear interrupt, just in case
@ -344,35 +344,35 @@ impl gpio::Flex<'_> {
/// Wait for a falling or rising edge on the pin. You can have at most 8 pins waiting. If you
/// try to wait for more than 8 pins, this function will return `None`.
pub async fn wait_for_any_edge(&mut self) -> Option<()> {
InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Both))?.await;
InputFuture::new(self.pin.reborrow(), InterruptOn::Edge(Edge::Both))?.await;
Some(())
}
/// Wait for a falling edge on the pin. You can have at most 8 pins waiting. If you try to wait
/// for more than 8 pins, this function will return `None`.
pub async fn wait_for_falling_edge(&mut self) -> Option<()> {
InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Falling))?.await;
InputFuture::new(self.pin.reborrow(), InterruptOn::Edge(Edge::Falling))?.await;
Some(())
}
/// Wait for a rising edge on the pin. You can have at most 8 pins waiting. If you try to wait
/// for more than 8 pins, this function will return `None`.
pub async fn wait_for_rising_edge(&mut self) -> Option<()> {
InputFuture::new(&mut self.pin, InterruptOn::Edge(Edge::Rising))?.await;
InputFuture::new(self.pin.reborrow(), InterruptOn::Edge(Edge::Rising))?.await;
Some(())
}
/// Wait for a low level on the pin. You can have at most 8 pins waiting. If you try to wait for
/// more than 8 pins, this function will return `None`.
pub async fn wait_for_low(&mut self) -> Option<()> {
InputFuture::new(&mut self.pin, InterruptOn::Level(Level::Low))?.await;
InputFuture::new(self.pin.reborrow(), InterruptOn::Level(Level::Low))?.await;
Some(())
}
/// Wait for a high level on the pin. You can have at most 8 pins waiting. If you try to wait for
/// more than 8 pins, this function will return `None`.
pub async fn wait_for_high(&mut self) -> Option<()> {
InputFuture::new(&mut self.pin, InterruptOn::Level(Level::High))?.await;
InputFuture::new(self.pin.reborrow(), InterruptOn::Level(Level::High))?.await;
Some(())
}
}

View File

@ -5,7 +5,6 @@ use core::mem;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
use crate::gpio::{self, AnyPin, Pull, SealedPin as GpioPin};
@ -13,7 +12,7 @@ use crate::interrupt::typelevel::Binding;
use crate::interrupt::InterruptExt;
use crate::pac::dma::vals::TreqSel;
use crate::peripherals::{ADC, ADC_TEMP_SENSOR};
use crate::{dma, interrupt, pac, peripherals, Peripheral, RegExt};
use crate::{dma, interrupt, pac, peripherals, Peri, RegExt};
static WAKER: AtomicWaker = AtomicWaker::new();
@ -23,8 +22,8 @@ static WAKER: AtomicWaker = AtomicWaker::new();
pub struct Config {}
enum Source<'p> {
Pin(PeripheralRef<'p, AnyPin>),
TempSensor(PeripheralRef<'p, ADC_TEMP_SENSOR>),
Pin(Peri<'p, AnyPin>),
TempSensor(Peri<'p, ADC_TEMP_SENSOR>),
}
/// ADC channel.
@ -32,8 +31,7 @@ pub struct Channel<'p>(Source<'p>);
impl<'p> Channel<'p> {
/// Create a new ADC channel from pin with the provided [Pull] configuration.
pub fn new_pin(pin: impl Peripheral<P = impl AdcPin + 'p> + 'p, pull: Pull) -> Self {
into_ref!(pin);
pub fn new_pin(pin: Peri<'p, impl AdcPin + 'p>, pull: Pull) -> Self {
pin.pad_ctrl().modify(|w| {
#[cfg(feature = "_rp235x")]
w.set_iso(false);
@ -47,14 +45,14 @@ impl<'p> Channel<'p> {
w.set_pue(pull == Pull::Up);
w.set_pde(pull == Pull::Down);
});
Self(Source::Pin(pin.map_into()))
Self(Source::Pin(pin.into()))
}
/// Create a new ADC channel for the internal temperature sensor.
pub fn new_temp_sensor(s: impl Peripheral<P = ADC_TEMP_SENSOR> + 'p) -> Self {
pub fn new_temp_sensor(s: Peri<'p, ADC_TEMP_SENSOR>) -> Self {
let r = pac::ADC;
r.cs().write_set(|w| w.set_ts_en(true));
Self(Source::TempSensor(s.into_ref()))
Self(Source::TempSensor(s))
}
fn channel(&self) -> u8 {
@ -190,7 +188,7 @@ impl<'d, M: Mode> Adc<'d, M> {
impl<'d> Adc<'d, Async> {
/// Create ADC driver in async mode.
pub fn new(
_inner: impl Peripheral<P = ADC> + 'd,
_inner: Peri<'d, ADC>,
_irq: impl Binding<interrupt::typelevel::ADC_IRQ_FIFO, InterruptHandler>,
_config: Config,
) -> Self {
@ -205,11 +203,13 @@ impl<'d> Adc<'d, Async> {
fn wait_for_ready() -> impl Future<Output = ()> {
let r = Self::regs();
r.inte().write(|w| w.set_fifo(true));
compiler_fence(Ordering::SeqCst);
poll_fn(move |cx| {
WAKER.register(cx.waker());
r.inte().write(|w| w.set_fifo(true));
compiler_fence(Ordering::SeqCst);
if r.cs().read().ready() {
return Poll::Ready(());
}
@ -240,7 +240,7 @@ impl<'d> Adc<'d, Async> {
buf: &mut [W],
fcs_err: bool,
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
dma: Peri<'_, impl dma::Channel>,
) -> Result<(), Error> {
#[cfg(feature = "rp2040")]
let mut rrobin = 0_u8;
@ -321,7 +321,7 @@ impl<'d> Adc<'d, Async> {
ch: &mut [Channel<'_>],
buf: &mut [S],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
dma: Peri<'_, impl dma::Channel>,
) -> Result<(), Error> {
self.read_many_inner(ch.iter().map(|c| c.channel()), buf, false, div, dma)
.await
@ -337,7 +337,7 @@ impl<'d> Adc<'d, Async> {
ch: &mut [Channel<'_>],
buf: &mut [Sample],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
dma: Peri<'_, impl dma::Channel>,
) {
// errors are reported in individual samples
let _ = self
@ -360,7 +360,7 @@ impl<'d> Adc<'d, Async> {
ch: &mut Channel<'_>,
buf: &mut [S],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
dma: Peri<'_, impl dma::Channel>,
) -> Result<(), Error> {
self.read_many_inner([ch.channel()].into_iter(), buf, false, div, dma)
.await
@ -375,7 +375,7 @@ impl<'d> Adc<'d, Async> {
ch: &mut Channel<'_>,
buf: &mut [Sample],
div: u16,
dma: impl Peripheral<P = impl dma::Channel>,
dma: Peri<'_, impl dma::Channel>,
) {
// errors are reported in individual samples
let _ = self
@ -392,7 +392,7 @@ impl<'d> Adc<'d, Async> {
impl<'d> Adc<'d, Blocking> {
/// Create ADC driver in blocking mode.
pub fn new_blocking(_inner: impl Peripheral<P = ADC> + 'd, _config: Config) -> Self {
pub fn new_blocking(_inner: Peri<'d, ADC>, _config: Config) -> Self {
Self::setup();
Self { phantom: PhantomData }

View File

@ -8,20 +8,19 @@
//! This module provides functionality to poll BOOTSEL from an embassy application.
use crate::flash::in_ram;
use crate::Peri;
impl crate::peripherals::BOOTSEL {
/// Polls the BOOTSEL button. Returns true if the button is pressed.
///
/// Polling isn't cheap, as this function waits for core 1 to finish it's current
/// task and for any DMAs from flash to complete
pub fn is_pressed(&mut self) -> bool {
let mut cs_status = Default::default();
/// Reads the BOOTSEL button. Returns true if the button is pressed.
///
/// Reading isn't cheap, as this function waits for core 1 to finish it's current
/// task and for any DMAs from flash to complete
pub fn is_bootsel_pressed(_p: Peri<'_, crate::peripherals::BOOTSEL>) -> bool {
let mut cs_status = Default::default();
unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0");
unsafe { in_ram(|| cs_status = ram_helpers::read_cs_status()) }.expect("Must be called from Core 0");
// bootsel is active low, so invert
!cs_status.infrompad()
}
// bootsel is active low, so invert
!cs_status.infrompad()
}
mod ram_helpers {

View File

@ -7,13 +7,12 @@ use core::marker::PhantomData;
use core::sync::atomic::AtomicU16;
use core::sync::atomic::{AtomicU32, Ordering};
use embassy_hal_internal::{into_ref, PeripheralRef};
use pac::clocks::vals::*;
use crate::gpio::{AnyPin, SealedPin};
#[cfg(feature = "rp2040")]
use crate::pac::common::{Reg, RW};
use crate::{pac, reset, Peripheral};
use crate::{pac, reset, Peri};
// NOTE: all gpin handling is commented out for future reference.
// gpin is not usually safe to use during the boot init() call, so it won't
@ -200,8 +199,8 @@ impl ClockConfig {
// pub fn bind_gpin<P: GpinPin>(&mut self, gpin: Gpin<'static, P>, hz: u32) {
// match P::NR {
// 0 => self.gpin0 = Some((hz, gpin.map_into())),
// 1 => self.gpin1 = Some((hz, gpin.map_into())),
// 0 => self.gpin0 = Some((hz, gpin.into())),
// 1 => self.gpin1 = Some((hz, gpin.into())),
// _ => unreachable!(),
// }
// // pin is now provisionally bound. if the config is applied it must be forgotten,
@ -845,15 +844,13 @@ impl_gpinpin!(PIN_22, 22, 1);
/// General purpose clock input driver.
pub struct Gpin<'d, T: GpinPin> {
gpin: PeripheralRef<'d, AnyPin>,
gpin: Peri<'d, AnyPin>,
_phantom: PhantomData<T>,
}
impl<'d, T: GpinPin> Gpin<'d, T> {
/// Create new gpin driver.
pub fn new(gpin: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(gpin);
pub fn new(gpin: Peri<'d, T>) -> Self {
#[cfg(feature = "rp2040")]
gpin.gpio().ctrl().write(|w| w.set_funcsel(0x08));
@ -867,14 +864,10 @@ impl<'d, T: GpinPin> Gpin<'d, T> {
});
Gpin {
gpin: gpin.map_into(),
gpin: gpin.into(),
_phantom: PhantomData,
}
}
// fn map_into(self) -> Gpin<'d, AnyPin> {
// unsafe { core::mem::transmute(self) }
// }
}
impl<'d, T: GpinPin> Drop for Gpin<'d, T> {
@ -936,14 +929,12 @@ pub enum GpoutSrc {
/// General purpose clock output driver.
pub struct Gpout<'d, T: GpoutPin> {
gpout: PeripheralRef<'d, T>,
gpout: Peri<'d, T>,
}
impl<'d, T: GpoutPin> Gpout<'d, T> {
/// Create new general purpose clock output.
pub fn new(gpout: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(gpout);
pub fn new(gpout: Peri<'d, T>) -> Self {
#[cfg(feature = "rp2040")]
gpout.gpio().ctrl().write(|w| w.set_funcsel(0x08));

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_internal::{impl_peripheral, into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use pac::dma::vals::DataSize;
@ -42,7 +42,7 @@ pub(crate) unsafe fn init() {
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn read<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a,
ch: Peri<'a, C>,
from: *const W,
to: *mut [W],
dreq: vals::TreqSel,
@ -63,7 +63,7 @@ pub unsafe fn read<'a, C: Channel, W: Word>(
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn write<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a,
ch: Peri<'a, C>,
from: *const [W],
to: *mut W,
dreq: vals::TreqSel,
@ -87,7 +87,7 @@ static mut DUMMY: u32 = 0;
///
/// SAFETY: Slice must point to a valid location reachable by DMA.
pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a,
ch: Peri<'a, C>,
to: *mut W,
len: usize,
dreq: vals::TreqSel,
@ -107,11 +107,7 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>(
/// DMA copy between slices.
///
/// SAFETY: Slices must point to locations reachable by DMA.
pub unsafe fn copy<'a, C: Channel, W: Word>(
ch: impl Peripheral<P = C> + 'a,
from: &[W],
to: &mut [W],
) -> Transfer<'a, C> {
pub unsafe fn copy<'a, C: Channel, W: Word>(ch: Peri<'a, C>, from: &[W], to: &mut [W]) -> Transfer<'a, C> {
let from_len = from.len();
let to_len = to.len();
assert_eq!(from_len, to_len);
@ -128,7 +124,7 @@ pub unsafe fn copy<'a, C: Channel, W: Word>(
}
fn copy_inner<'a, C: Channel>(
ch: impl Peripheral<P = C> + 'a,
ch: Peri<'a, C>,
from: *const u32,
to: *mut u32,
len: usize,
@ -137,8 +133,6 @@ fn copy_inner<'a, C: Channel>(
incr_write: bool,
dreq: vals::TreqSel,
) -> Transfer<'a, C> {
into_ref!(ch);
let p = ch.regs();
p.read_addr().write_value(from as u32);
@ -171,13 +165,11 @@ fn copy_inner<'a, C: Channel>(
/// DMA transfer driver.
#[must_use = "futures do nothing unless you `.await` or poll them"]
pub struct Transfer<'a, C: Channel> {
channel: PeripheralRef<'a, C>,
channel: Peri<'a, C>,
}
impl<'a, C: Channel> Transfer<'a, C> {
pub(crate) fn new(channel: impl Peripheral<P = C> + 'a) -> Self {
into_ref!(channel);
pub(crate) fn new(channel: Peri<'a, C>) -> Self {
Self { channel }
}
}
@ -219,7 +211,7 @@ trait SealedWord {}
/// DMA channel interface.
#[allow(private_bounds)]
pub trait Channel: Peripheral<P = Self> + SealedChannel + Into<AnyChannel> + Sized + 'static {
pub trait Channel: PeripheralType + SealedChannel + Into<AnyChannel> + Sized + 'static {
/// Channel number.
fn number(&self) -> u8;
@ -227,11 +219,6 @@ pub trait Channel: Peripheral<P = Self> + SealedChannel + Into<AnyChannel> + Siz
fn regs(&self) -> pac::dma::Channel {
pac::DMA.ch(self.number() as _)
}
/// Convert into type-erased [AnyChannel].
fn degrade(self) -> AnyChannel {
AnyChannel { number: self.number() }
}
}
/// DMA word.
@ -287,7 +274,7 @@ macro_rules! channel {
impl From<peripherals::$name> for crate::dma::AnyChannel {
fn from(val: peripherals::$name) -> Self {
crate::dma::Channel::degrade(val)
Self { number: val.number() }
}
}
};

View File

@ -4,7 +4,7 @@ use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embedded_storage::nor_flash::{
check_erase, check_read, check_write, ErrorType, MultiwriteNorFlash, NorFlash, NorFlashError, NorFlashErrorKind,
ReadNorFlash,
@ -19,7 +19,7 @@ pub const FLASH_BASE: *const u32 = 0x10000000 as _;
/// Address for xip setup function set up by the 235x bootrom.
#[cfg(feature = "_rp235x")]
pub const BOOTROM_BASE: *const u32 = 0x400e0000 as _;
pub const BOOTRAM_BASE: *const u32 = 0x400e0000 as _;
/// If running from RAM, we might have no boot2. Use bootrom `flash_enter_cmd_xip` instead.
// TODO: when run-from-ram is set, completely skip the "pause cores and jumpp to RAM" dance.
@ -114,7 +114,7 @@ impl<'a, 'd, T: Instance, const FLASH_SIZE: usize> Drop for BackgroundRead<'a, '
/// Flash driver.
pub struct Flash<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> {
dma: Option<PeripheralRef<'d, AnyChannel>>,
dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
}
@ -253,7 +253,7 @@ impl<'d, T: Instance, M: Mode, const FLASH_SIZE: usize> Flash<'d, T, M, FLASH_SI
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE> {
/// Create a new flash driver in blocking mode.
pub fn new_blocking(_flash: impl Peripheral<P = T> + 'd) -> Self {
pub fn new_blocking(_flash: Peri<'d, T>) -> Self {
Self {
dma: None,
phantom: PhantomData,
@ -263,10 +263,9 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Blocking, FLASH_SIZE
impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
/// Create a new flash driver in async mode.
pub fn new(_flash: impl Peripheral<P = T> + 'd, dma: impl Peripheral<P = impl Channel> + 'd) -> Self {
into_ref!(dma);
pub fn new(_flash: Peri<'d, T>, dma: Peri<'d, impl Channel>) -> Self {
Self {
dma: Some(dma.map_into()),
dma: Some(dma.into()),
phantom: PhantomData,
}
}
@ -316,7 +315,7 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> Flash<'d, T, Async, FLASH_SIZE> {
const XIP_AUX_BASE: *const u32 = 0x50500000 as *const _;
let transfer = unsafe {
crate::dma::read(
self.dma.as_mut().unwrap(),
self.dma.as_mut().unwrap().reborrow(),
XIP_AUX_BASE,
data,
pac::dma::vals::TreqSel::XIP_STREAM,
@ -527,7 +526,7 @@ mod ram_helpers {
#[cfg(feature = "rp2040")]
rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256);
#[cfg(feature = "_rp235x")]
core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256);
core::ptr::copy_nonoverlapping(BOOTRAM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256);
flash_function_pointers_with_boot2(true, false, &boot2)
} else {
flash_function_pointers(true, false)
@ -560,7 +559,7 @@ mod ram_helpers {
#[cfg(feature = "rp2040")]
rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256);
#[cfg(feature = "_rp235x")]
core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, (boot2).as_mut_ptr() as *mut u8, 256);
core::ptr::copy_nonoverlapping(BOOTRAM_BASE as *const u8, (boot2).as_mut_ptr() as *mut u8, 256);
flash_function_pointers_with_boot2(true, true, &boot2)
} else {
flash_function_pointers(true, true)
@ -598,7 +597,7 @@ mod ram_helpers {
#[cfg(feature = "rp2040")]
rom_data::memcpy44(&mut boot2 as *mut _, FLASH_BASE, 256);
#[cfg(feature = "_rp235x")]
core::ptr::copy_nonoverlapping(BOOTROM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256);
core::ptr::copy_nonoverlapping(BOOTRAM_BASE as *const u8, boot2.as_mut_ptr() as *mut u8, 256);
flash_function_pointers_with_boot2(false, true, &boot2)
} else {
flash_function_pointers(false, true)
@ -965,7 +964,7 @@ trait SealedMode {}
/// Flash instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {}
pub trait Instance: SealedInstance + PeripheralType {}
/// Flash mode.
#[allow(private_bounds)]
pub trait Mode: SealedMode {}

View File

@ -5,13 +5,13 @@ use core::future::Future;
use core::pin::Pin as FuturePin;
use core::task::{Context, Poll};
use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef};
use embassy_hal_internal::{impl_peripheral, Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use crate::interrupt::InterruptExt;
use crate::pac::common::{Reg, RW};
use crate::pac::SIO;
use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
use crate::{interrupt, pac, peripherals, RegExt};
#[cfg(any(feature = "rp2040", feature = "rp235xa"))]
pub(crate) const BANK0_PIN_COUNT: usize = 30;
@ -115,7 +115,7 @@ pub struct Input<'d> {
impl<'d> Input<'d> {
/// Create GPIO input driver for a [Pin] with the provided [Pull] configuration.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, pull: Pull) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
let mut pin = Flex::new(pin);
pin.set_as_input();
pin.set_pull(pull);
@ -266,11 +266,11 @@ fn IO_IRQ_QSPI() {
#[must_use = "futures do nothing unless you `.await` or poll them"]
struct InputFuture<'d> {
pin: PeripheralRef<'d, AnyPin>,
pin: Peri<'d, AnyPin>,
}
impl<'d> InputFuture<'d> {
fn new(pin: PeripheralRef<'d, AnyPin>, level: InterruptTrigger) -> Self {
fn new(pin: Peri<'d, AnyPin>, level: InterruptTrigger) -> Self {
let pin_group = (pin.pin() % 8) as usize;
// first, clear the INTR register bits. without this INTR will still
// contain reports of previous edges, causing the IRQ to fire early
@ -359,7 +359,7 @@ pub struct Output<'d> {
impl<'d> Output<'d> {
/// Create GPIO output driver for a [Pin] with the provided [Level].
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
match initial_output {
Level::High => pin.set_high(),
@ -440,7 +440,7 @@ pub struct OutputOpenDrain<'d> {
impl<'d> OutputOpenDrain<'d> {
/// Create GPIO output driver for a [Pin] in open drain mode with the provided [Level].
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd, initial_output: Level) -> Self {
pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
let mut pin = Flex::new(pin);
pin.set_low();
match initial_output {
@ -581,7 +581,7 @@ impl<'d> OutputOpenDrain<'d> {
/// set while not in output mode, so the pin's level will be 'remembered' when it is not in output
/// mode.
pub struct Flex<'d> {
pin: PeripheralRef<'d, AnyPin>,
pin: Peri<'d, AnyPin>,
}
impl<'d> Flex<'d> {
@ -590,9 +590,7 @@ impl<'d> Flex<'d> {
/// The pin remains disconnected. The initial output level is unspecified, but can be changed
/// before the pin is put into output mode.
#[inline]
pub fn new(pin: impl Peripheral<P = impl Pin> + 'd) -> Self {
into_ref!(pin);
pub fn new(pin: Peri<'d, impl Pin>) -> Self {
pin.pad_ctrl().write(|w| {
#[cfg(feature = "_rp235x")]
w.set_iso(false);
@ -606,7 +604,7 @@ impl<'d> Flex<'d> {
w.set_funcsel(pac::io::vals::Gpio0ctrlFuncsel::SIOB_PROC_0 as _);
});
Self { pin: pin.map_into() }
Self { pin: pin.into() }
}
#[inline]
@ -829,7 +827,7 @@ impl<'d> Drop for Flex<'d> {
/// Dormant wake driver.
pub struct DormantWake<'w> {
pin: PeripheralRef<'w, AnyPin>,
pin: Peri<'w, AnyPin>,
cfg: DormantWakeConfig,
}
@ -919,14 +917,7 @@ pub(crate) trait SealedPin: Sized {
/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an [AnyPin].
#[allow(private_bounds)]
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + SealedPin + Sized + 'static {
/// Degrade to a generic pin struct
fn degrade(self) -> AnyPin {
AnyPin {
pin_bank: self.pin_bank(),
}
}
pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
/// Returns the pin number within a bank
#[inline]
fn pin(&self) -> u8 {
@ -951,8 +942,8 @@ impl AnyPin {
/// # Safety
///
/// You must ensure that youre only using one instance of this type at a time.
pub unsafe fn steal(pin_bank: u8) -> Self {
Self { pin_bank }
pub unsafe fn steal(pin_bank: u8) -> Peri<'static, Self> {
Peri::new_unchecked(Self { pin_bank })
}
}
@ -979,7 +970,9 @@ macro_rules! impl_pin {
impl From<peripherals::$name> for crate::gpio::AnyPin {
fn from(val: peripherals::$name) -> Self {
crate::gpio::Pin::degrade(val)
Self {
pin_bank: val.pin_bank(),
}
}
}
};

View File

@ -5,13 +5,13 @@ use core::future;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use pac::i2c;
use crate::gpio::AnyPin;
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::{interrupt, pac, peripherals, Peripheral};
use crate::{interrupt, pac, peripherals};
/// I2C error abort reason
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -83,28 +83,25 @@ pub struct I2c<'d, T: Instance, M: Mode> {
impl<'d, T: Instance> I2c<'d, T, Blocking> {
/// Create a new driver instance in blocking mode.
pub fn new_blocking(
peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
peri: Peri<'d, T>,
scl: Peri<'d, impl SclPin<T>>,
sda: Peri<'d, impl SdaPin<T>>,
config: Config,
) -> Self {
into_ref!(scl, sda);
Self::new_inner(peri, scl.map_into(), sda.map_into(), config)
Self::new_inner(peri, scl.into(), sda.into(), config)
}
}
impl<'d, T: Instance> I2c<'d, T, Async> {
/// Create a new driver instance in async mode.
pub fn new_async(
peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
peri: Peri<'d, T>,
scl: Peri<'d, impl SclPin<T>>,
sda: Peri<'d, impl SdaPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
config: Config,
) -> Self {
into_ref!(scl, sda);
let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config);
let i2c = Self::new_inner(peri, scl.into(), sda.into(), config);
let r = T::regs();
@ -378,14 +375,7 @@ where
}
impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
fn new_inner(
_peri: impl Peripheral<P = T> + 'd,
scl: PeripheralRef<'d, AnyPin>,
sda: PeripheralRef<'d, AnyPin>,
config: Config,
) -> Self {
into_ref!(_peri);
fn new_inner(_peri: Peri<'d, T>, scl: Peri<'d, AnyPin>, sda: Peri<'d, AnyPin>, config: Config) -> Self {
let reset = T::reset();
crate::reset::reset(reset);
crate::reset::unreset_wait(reset);
@ -804,7 +794,7 @@ impl_mode!(Async);
/// I2C instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {
pub trait Instance: SealedInstance + PeripheralType {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -3,12 +3,11 @@ use core::future;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::into_ref;
use pac::i2c;
use crate::i2c::{set_up_i2c_pin, AbortReason, Instance, InterruptHandler, SclPin, SdaPin, FIFO_SIZE};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::{pac, Peripheral};
use crate::{pac, Peri};
/// I2C error
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
@ -87,14 +86,12 @@ pub struct I2cSlave<'d, T: Instance> {
impl<'d, T: Instance> I2cSlave<'d, T> {
/// Create a new instance.
pub fn new(
_peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
_peri: Peri<'d, T>,
scl: Peri<'d, impl SclPin<T>>,
sda: Peri<'d, impl SdaPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
config: Config,
) -> Self {
into_ref!(_peri, scl, sda);
assert!(config.addr != 0);
// Configure SCL & SDA pins

View File

@ -54,7 +54,7 @@ pub mod pio;
pub(crate) mod relocate;
// Reexports
pub use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
pub use embassy_hal_internal::{Peri, PeripheralType};
#[cfg(feature = "unstable-pac")]
pub use rp_pac as pac;
#[cfg(not(feature = "unstable-pac"))]

View File

@ -51,7 +51,7 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
use crate::interrupt::InterruptExt;
use crate::peripherals::CORE1;
use crate::{gpio, install_stack_guard, interrupt, pac};
use crate::{gpio, install_stack_guard, interrupt, pac, Peri};
const PAUSE_TOKEN: u32 = 0xDEADBEEF;
const RESUME_TOKEN: u32 = !0xDEADBEEF;
@ -139,7 +139,7 @@ unsafe fn SIO_IRQ_FIFO() {
}
/// Spawn a function on this core
pub fn spawn_core1<F, const SIZE: usize>(_core1: CORE1, stack: &'static mut Stack<SIZE>, entry: F)
pub fn spawn_core1<F, const SIZE: usize>(_core1: Peri<'static, CORE1>, stack: &'static mut Stack<SIZE>, entry: F)
where
F: FnOnce() -> bad::Never + Send + 'static,
{

View File

@ -6,7 +6,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use core::task::{Context, Poll};
use atomic_polyfill::{AtomicU64, AtomicU8};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use fixed::types::extra::U8;
use fixed::FixedU32;
@ -235,7 +235,7 @@ impl<'a, 'd, PIO: Instance> Drop for IrqFuture<'a, 'd, PIO> {
/// Type representing a PIO pin.
pub struct Pin<'l, PIO: Instance> {
pin: PeripheralRef<'l, AnyPin>,
pin: Peri<'l, AnyPin>,
pio: PhantomData<PIO>,
}
@ -360,7 +360,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineRx<'d, PIO, SM> {
/// Prepare DMA transfer from RX FIFO.
pub fn dma_pull<'a, C: Channel, W: Word>(
&'a mut self,
ch: PeripheralRef<'a, C>,
ch: Peri<'a, C>,
data: &'a mut [W],
bswap: bool,
) -> Transfer<'a, C> {
@ -451,7 +451,7 @@ impl<'d, PIO: Instance, const SM: usize> StateMachineTx<'d, PIO, SM> {
/// Prepare a DMA transfer to TX FIFO.
pub fn dma_push<'a, C: Channel, W: Word>(
&'a mut self,
ch: PeripheralRef<'a, C>,
ch: Peri<'a, C>,
data: &'a [W],
bswap: bool,
) -> Transfer<'a, C> {
@ -1147,9 +1147,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
/// (i.e., have their `FUNCSEL` reset to `NULL`) when the [`Common`] *and*
/// all [`StateMachine`]s for this block have been dropped. **Other members
/// of [`Pio`] do not keep pin registrations alive.**
pub fn make_pio_pin(&mut self, pin: impl Peripheral<P = impl PioPin + 'd> + 'd) -> Pin<'d, PIO> {
into_ref!(pin);
pub fn make_pio_pin(&mut self, pin: Peri<'d, impl PioPin + 'd>) -> Pin<'d, PIO> {
// enable the outputs
pin.pad_ctrl().write(|w| w.set_od(false));
// especially important on the 235x, where IE defaults to 0
@ -1171,7 +1169,7 @@ impl<'d, PIO: Instance> Common<'d, PIO> {
// we can be relaxed about this because we're &mut here and nothing is cached
PIO::state().used_pins.fetch_or(1 << pin.pin_bank(), Ordering::Relaxed);
Pin {
pin: pin.into_ref().map_into(),
pin: pin.into(),
pio: PhantomData::default(),
}
}
@ -1304,7 +1302,7 @@ pub struct Pio<'d, PIO: Instance> {
impl<'d, PIO: Instance> Pio<'d, PIO> {
/// Create a new instance of a PIO peripheral.
pub fn new(_pio: impl Peripheral<P = PIO> + 'd, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self {
pub fn new(_pio: Peri<'d, PIO>, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self {
PIO::state().users.store(5, Ordering::Release);
PIO::state().used_pins.store(0, Ordering::Release);
PIO::Interrupt::unpend();
@ -1389,7 +1387,7 @@ trait SealedInstance {
/// PIO instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance + Sized + Unpin {
pub trait Instance: SealedInstance + PeripheralType + Sized + Unpin {
/// Interrupt for this peripheral.
type Interrupt: crate::interrupt::typelevel::Interrupt;
}

View File

@ -5,7 +5,7 @@ use crate::pio::{
Common, Config, Direction, FifoJoin, Instance, Irq, LoadedProgram, PioPin, ShiftConfig, ShiftDirection,
StateMachine,
};
use crate::{into_ref, Peripheral, PeripheralRef};
use crate::Peri;
/// This struct represents a HD44780 program that takes command words (<wait:24> <command:4> <0:4>)
pub struct PioHD44780CommandWordProgram<'a, PIO: Instance> {
@ -99,7 +99,7 @@ impl<'a, PIO: Instance> PioHD44780CommandSequenceProgram<'a, PIO> {
/// Pio backed HD44780 driver
pub struct PioHD44780<'l, P: Instance, const S: usize> {
dma: PeripheralRef<'l, AnyChannel>,
dma: Peri<'l, AnyChannel>,
sm: StateMachine<'l, P, S>,
buf: [u8; 40],
@ -111,19 +111,17 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
common: &mut Common<'l, P>,
mut sm: StateMachine<'l, P, S>,
mut irq: Irq<'l, P, S>,
dma: impl Peripheral<P = impl Channel> + 'l,
rs: impl PioPin,
rw: impl PioPin,
e: impl PioPin,
db4: impl PioPin,
db5: impl PioPin,
db6: impl PioPin,
db7: impl PioPin,
mut dma: Peri<'l, impl Channel>,
rs: Peri<'l, impl PioPin>,
rw: Peri<'l, impl PioPin>,
e: Peri<'l, impl PioPin>,
db4: Peri<'l, impl PioPin>,
db5: Peri<'l, impl PioPin>,
db6: Peri<'l, impl PioPin>,
db7: Peri<'l, impl PioPin>,
word_prg: &PioHD44780CommandWordProgram<'l, P>,
seq_prg: &PioHD44780CommandSequenceProgram<'l, P>,
) -> PioHD44780<'l, P, S> {
into_ref!(dma);
let rs = common.make_pio_pin(rs);
let rw = common.make_pio_pin(rw);
let e = common.make_pio_pin(e);
@ -176,7 +174,7 @@ impl<'l, P: Instance, const S: usize> PioHD44780<'l, P, S> {
sm.tx().dma_push(dma.reborrow(), &[0x81u8, 0x0f, 1], false).await;
Self {
dma: dma.map_into(),
dma: dma.into(),
sm,
buf: [0x20; 40],
}

View File

@ -6,16 +6,16 @@ use crate::dma::{AnyChannel, Channel, Transfer};
use crate::pio::{
Common, Config, Direction, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
};
use crate::{into_ref, Peripheral, PeripheralRef};
use crate::Peri;
/// This struct represents an i2s output driver program
pub struct PioI2sOutProgram<'a, PIO: Instance> {
prg: LoadedProgram<'a, PIO>,
pub struct PioI2sOutProgram<'d, PIO: Instance> {
prg: LoadedProgram<'d, PIO>,
}
impl<'a, PIO: Instance> PioI2sOutProgram<'a, PIO> {
impl<'d, PIO: Instance> PioI2sOutProgram<'d, PIO> {
/// Load the program into the given pio
pub fn new(common: &mut Common<'a, PIO>) -> Self {
pub fn new(common: &mut Common<'d, PIO>) -> Self {
let prg = pio::pio_asm!(
".side_set 2",
" set x, 14 side 0b01", // side 0bWB - W = Word Clock, B = Bit Clock
@ -37,27 +37,25 @@ impl<'a, PIO: Instance> PioI2sOutProgram<'a, PIO> {
}
/// Pio backed I2s output driver
pub struct PioI2sOut<'a, P: Instance, const S: usize> {
dma: PeripheralRef<'a, AnyChannel>,
sm: StateMachine<'a, P, S>,
pub struct PioI2sOut<'d, P: Instance, const S: usize> {
dma: Peri<'d, AnyChannel>,
sm: StateMachine<'d, P, S>,
}
impl<'a, P: Instance, const S: usize> PioI2sOut<'a, P, S> {
impl<'d, P: Instance, const S: usize> PioI2sOut<'d, P, S> {
/// Configure a state machine to output I2s
pub fn new(
common: &mut Common<'a, P>,
mut sm: StateMachine<'a, P, S>,
dma: impl Peripheral<P = impl Channel> + 'a,
data_pin: impl PioPin,
bit_clock_pin: impl PioPin,
lr_clock_pin: impl PioPin,
common: &mut Common<'d, P>,
mut sm: StateMachine<'d, P, S>,
dma: Peri<'d, impl Channel>,
data_pin: Peri<'d, impl PioPin>,
bit_clock_pin: Peri<'d, impl PioPin>,
lr_clock_pin: Peri<'d, impl PioPin>,
sample_rate: u32,
bit_depth: u32,
channels: u32,
program: &PioI2sOutProgram<'a, P>,
program: &PioI2sOutProgram<'d, P>,
) -> Self {
into_ref!(dma);
let data_pin = common.make_pio_pin(data_pin);
let bit_clock_pin = common.make_pio_pin(bit_clock_pin);
let left_right_clock_pin = common.make_pio_pin(lr_clock_pin);
@ -82,10 +80,7 @@ impl<'a, P: Instance, const S: usize> PioI2sOut<'a, P, S> {
sm.set_enable(true);
Self {
dma: dma.map_into(),
sm,
}
Self { dma: dma.into(), sm }
}
/// Return an in-prograss dma transfer future. Awaiting it will guarentee a complete transfer.

View File

@ -1,6 +1,7 @@
//! OneWire pio driver
use crate::pio::{Common, Config, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine};
use crate::Peri;
/// This struct represents an onewire driver program
pub struct PioOneWireProgram<'a, PIO: Instance> {
@ -69,7 +70,7 @@ impl<'d, PIO: Instance, const SM: usize> PioOneWire<'d, PIO, SM> {
pub fn new(
common: &mut Common<'d, PIO>,
mut sm: StateMachine<'d, PIO, SM>,
pin: impl PioPin,
pin: Peri<'d, impl PioPin>,
program: &PioOneWireProgram<'d, PIO>,
) -> Self {
let pin = common.make_pio_pin(pin);

View File

@ -4,9 +4,9 @@ use core::time::Duration;
use pio::InstructionOperands;
use crate::clocks;
use crate::gpio::Level;
use crate::pio::{Common, Config, Direction, Instance, LoadedProgram, Pin, PioPin, StateMachine};
use crate::{clocks, Peri};
/// This converts the duration provided into the number of cycles the PIO needs to run to make it take the same time
fn to_pio_cycles(duration: Duration) -> u32 {
@ -52,7 +52,7 @@ impl<'d, T: Instance, const SM: usize> PioPwm<'d, T, SM> {
pub fn new(
pio: &mut Common<'d, T>,
mut sm: StateMachine<'d, T, SM>,
pin: impl PioPin,
pin: Peri<'d, impl PioPin>,
program: &PioPwmProgram<'d, T>,
) -> Self {
let pin = pio.make_pio_pin(pin);

View File

@ -6,6 +6,7 @@ use crate::gpio::Pull;
use crate::pio::{
Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
};
use crate::Peri;
/// This struct represents an Encoder program loaded into pio instruction memory.
pub struct PioEncoderProgram<'a, PIO: Instance> {
@ -33,8 +34,8 @@ impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
pub fn new(
pio: &mut Common<'d, T>,
mut sm: StateMachine<'d, T, SM>,
pin_a: impl PioPin,
pin_b: impl PioPin,
pin_a: Peri<'d, impl PioPin>,
pin_b: Peri<'d, impl PioPin>,
program: &PioEncoderProgram<'d, T>,
) -> Self {
let mut pin_a = pio.make_pio_pin(pin_a);

View File

@ -7,6 +7,7 @@ use fixed::types::extra::U8;
use fixed::FixedU32;
use crate::pio::{Common, Config, Direction, Instance, Irq, LoadedProgram, PioPin, StateMachine};
use crate::Peri;
/// This struct represents a Stepper driver program loaded into pio instruction memory.
pub struct PioStepperProgram<'a, PIO: Instance> {
@ -50,10 +51,10 @@ impl<'d, T: Instance, const SM: usize> PioStepper<'d, T, SM> {
pio: &mut Common<'d, T>,
mut sm: StateMachine<'d, T, SM>,
irq: Irq<'d, T, SM>,
pin0: impl PioPin,
pin1: impl PioPin,
pin2: impl PioPin,
pin3: impl PioPin,
pin0: Peri<'d, impl PioPin>,
pin1: Peri<'d, impl PioPin>,
pin2: Peri<'d, impl PioPin>,
pin3: Peri<'d, impl PioPin>,
program: &PioStepperProgram<'d, T>,
) -> Self {
let pin0 = pio.make_pio_pin(pin0);

View File

@ -10,15 +10,16 @@ use crate::gpio::Level;
use crate::pio::{
Common, Config, Direction as PioDirection, FifoJoin, Instance, LoadedProgram, PioPin, ShiftDirection, StateMachine,
};
use crate::Peri;
/// This struct represents a uart tx program loaded into pio instruction memory.
pub struct PioUartTxProgram<'a, PIO: Instance> {
prg: LoadedProgram<'a, PIO>,
pub struct PioUartTxProgram<'d, PIO: Instance> {
prg: LoadedProgram<'d, PIO>,
}
impl<'a, PIO: Instance> PioUartTxProgram<'a, PIO> {
impl<'d, PIO: Instance> PioUartTxProgram<'d, PIO> {
/// Load the uart tx program into the given pio
pub fn new(common: &mut Common<'a, PIO>) -> Self {
pub fn new(common: &mut Common<'d, PIO>) -> Self {
let prg = pio::pio_asm!(
r#"
.side_set 1 opt
@ -41,18 +42,18 @@ impl<'a, PIO: Instance> PioUartTxProgram<'a, PIO> {
}
/// PIO backed Uart transmitter
pub struct PioUartTx<'a, PIO: Instance, const SM: usize> {
sm_tx: StateMachine<'a, PIO, SM>,
pub struct PioUartTx<'d, PIO: Instance, const SM: usize> {
sm_tx: StateMachine<'d, PIO, SM>,
}
impl<'a, PIO: Instance, const SM: usize> PioUartTx<'a, PIO, SM> {
impl<'d, PIO: Instance, const SM: usize> PioUartTx<'d, PIO, SM> {
/// Configure a pio state machine to use the loaded tx program.
pub fn new(
baud: u32,
common: &mut Common<'a, PIO>,
mut sm_tx: StateMachine<'a, PIO, SM>,
tx_pin: impl PioPin,
program: &PioUartTxProgram<'a, PIO>,
common: &mut Common<'d, PIO>,
mut sm_tx: StateMachine<'d, PIO, SM>,
tx_pin: Peri<'d, impl PioPin>,
program: &PioUartTxProgram<'d, PIO>,
) -> Self {
let tx_pin = common.make_pio_pin(tx_pin);
sm_tx.set_pins(Level::High, &[&tx_pin]);
@ -92,13 +93,13 @@ impl<PIO: Instance, const SM: usize> Write for PioUartTx<'_, PIO, SM> {
}
/// This struct represents a Uart Rx program loaded into pio instruction memory.
pub struct PioUartRxProgram<'a, PIO: Instance> {
prg: LoadedProgram<'a, PIO>,
pub struct PioUartRxProgram<'d, PIO: Instance> {
prg: LoadedProgram<'d, PIO>,
}
impl<'a, PIO: Instance> PioUartRxProgram<'a, PIO> {
impl<'d, PIO: Instance> PioUartRxProgram<'d, PIO> {
/// Load the uart rx program into the given pio
pub fn new(common: &mut Common<'a, PIO>) -> Self {
pub fn new(common: &mut Common<'d, PIO>) -> Self {
let prg = pio::pio_asm!(
r#"
; Slightly more fleshed-out 8n1 UART receiver which handles framing errors and
@ -130,18 +131,18 @@ impl<'a, PIO: Instance> PioUartRxProgram<'a, PIO> {
}
/// PIO backed Uart reciever
pub struct PioUartRx<'a, PIO: Instance, const SM: usize> {
sm_rx: StateMachine<'a, PIO, SM>,
pub struct PioUartRx<'d, PIO: Instance, const SM: usize> {
sm_rx: StateMachine<'d, PIO, SM>,
}
impl<'a, PIO: Instance, const SM: usize> PioUartRx<'a, PIO, SM> {
impl<'d, PIO: Instance, const SM: usize> PioUartRx<'d, PIO, SM> {
/// Configure a pio state machine to use the loaded rx program.
pub fn new(
baud: u32,
common: &mut Common<'a, PIO>,
mut sm_rx: StateMachine<'a, PIO, SM>,
rx_pin: impl PioPin,
program: &PioUartRxProgram<'a, PIO>,
common: &mut Common<'d, PIO>,
mut sm_rx: StateMachine<'d, PIO, SM>,
rx_pin: Peri<'d, impl PioPin>,
program: &PioUartRxProgram<'d, PIO>,
) -> Self {
let mut cfg = Config::default();
cfg.use_program(&program.prg, &[]);

View File

@ -9,7 +9,7 @@ use crate::dma::{AnyChannel, Channel};
use crate::pio::{
Common, Config, FifoJoin, Instance, LoadedProgram, PioPin, ShiftConfig, ShiftDirection, StateMachine,
};
use crate::{into_ref, Peripheral, PeripheralRef};
use crate::Peri;
const T1: u8 = 2; // start bit
const T2: u8 = 5; // data bit
@ -53,7 +53,7 @@ impl<'a, PIO: Instance> PioWs2812Program<'a, PIO> {
/// Pio backed ws2812 driver
/// Const N is the number of ws2812 leds attached to this pin
pub struct PioWs2812<'d, P: Instance, const S: usize, const N: usize> {
dma: PeripheralRef<'d, AnyChannel>,
dma: Peri<'d, AnyChannel>,
sm: StateMachine<'d, P, S>,
}
@ -62,12 +62,10 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
pub fn new(
pio: &mut Common<'d, P>,
mut sm: StateMachine<'d, P, S>,
dma: impl Peripheral<P = impl Channel> + 'd,
pin: impl PioPin,
dma: Peri<'d, impl Channel>,
pin: Peri<'d, impl PioPin>,
program: &PioWs2812Program<'d, P>,
) -> Self {
into_ref!(dma);
// Setup sm0
let mut cfg = Config::default();
@ -95,10 +93,7 @@ impl<'d, P: Instance, const S: usize, const N: usize> PioWs2812<'d, P, S, N> {
sm.set_config(&cfg);
sm.set_enable(true);
Self {
dma: dma.map_into(),
sm,
}
Self { dma: dma.into(), sm }
}
/// Write a buffer of [smart_leds::RGB8] to the ws2812 string

View File

@ -1,6 +1,6 @@
//! Pulse Width Modulation (PWM)
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
pub use embedded_hal_1::pwm::SetDutyCycle;
use embedded_hal_1::pwm::{Error, ErrorKind, ErrorType};
use fixed::traits::ToFixed;
@ -99,8 +99,8 @@ impl Error for PwmError {
/// PWM driver.
pub struct Pwm<'d> {
pin_a: Option<PeripheralRef<'d, AnyPin>>,
pin_b: Option<PeripheralRef<'d, AnyPin>>,
pin_a: Option<Peri<'d, AnyPin>>,
pin_b: Option<Peri<'d, AnyPin>>,
slice: usize,
}
@ -131,8 +131,8 @@ impl<'d> SetDutyCycle for Pwm<'d> {
impl<'d> Pwm<'d> {
fn new_inner(
slice: usize,
a: Option<PeripheralRef<'d, AnyPin>>,
b: Option<PeripheralRef<'d, AnyPin>>,
a: Option<Peri<'d, AnyPin>>,
b: Option<Peri<'d, AnyPin>>,
b_pull: Pull,
config: Config,
divmode: Divmode,
@ -171,60 +171,34 @@ impl<'d> Pwm<'d> {
/// Create PWM driver without any configured pins.
#[inline]
pub fn new_free<T: Slice>(slice: impl Peripheral<P = T> + 'd, config: Config) -> Self {
into_ref!(slice);
pub fn new_free<T: Slice>(slice: Peri<'d, T>, config: Config) -> Self {
Self::new_inner(slice.number(), None, None, Pull::None, config, Divmode::DIV)
}
/// Create PWM driver with a single 'a' pin as output.
#[inline]
pub fn new_output_a<T: Slice>(
slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
config: Config,
) -> Self {
into_ref!(slice, a);
Self::new_inner(
slice.number(),
Some(a.map_into()),
None,
Pull::None,
config,
Divmode::DIV,
)
pub fn new_output_a<T: Slice>(slice: Peri<'d, T>, a: Peri<'d, impl ChannelAPin<T>>, config: Config) -> Self {
Self::new_inner(slice.number(), Some(a.into()), None, Pull::None, config, Divmode::DIV)
}
/// Create PWM driver with a single 'b' pin as output.
#[inline]
pub fn new_output_b<T: Slice>(
slice: impl Peripheral<P = T> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
config: Config,
) -> Self {
into_ref!(slice, b);
Self::new_inner(
slice.number(),
None,
Some(b.map_into()),
Pull::None,
config,
Divmode::DIV,
)
pub fn new_output_b<T: Slice>(slice: Peri<'d, T>, b: Peri<'d, impl ChannelBPin<T>>, config: Config) -> Self {
Self::new_inner(slice.number(), None, Some(b.into()), Pull::None, config, Divmode::DIV)
}
/// Create PWM driver with a 'a' and 'b' pins as output.
#[inline]
pub fn new_output_ab<T: Slice>(
slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
slice: Peri<'d, T>,
a: Peri<'d, impl ChannelAPin<T>>,
b: Peri<'d, impl ChannelBPin<T>>,
config: Config,
) -> Self {
into_ref!(slice, a, b);
Self::new_inner(
slice.number(),
Some(a.map_into()),
Some(b.map_into()),
Some(a.into()),
Some(b.into()),
Pull::None,
config,
Divmode::DIV,
@ -234,31 +208,29 @@ impl<'d> Pwm<'d> {
/// Create PWM driver with a single 'b' as input pin.
#[inline]
pub fn new_input<T: Slice>(
slice: impl Peripheral<P = T> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
slice: Peri<'d, T>,
b: Peri<'d, impl ChannelBPin<T>>,
b_pull: Pull,
mode: InputMode,
config: Config,
) -> Self {
into_ref!(slice, b);
Self::new_inner(slice.number(), None, Some(b.map_into()), b_pull, config, mode.into())
Self::new_inner(slice.number(), None, Some(b.into()), b_pull, config, mode.into())
}
/// Create PWM driver with a 'a' and 'b' pins in the desired input mode.
#[inline]
pub fn new_output_input<T: Slice>(
slice: impl Peripheral<P = T> + 'd,
a: impl Peripheral<P = impl ChannelAPin<T>> + 'd,
b: impl Peripheral<P = impl ChannelBPin<T>> + 'd,
slice: Peri<'d, T>,
a: Peri<'d, impl ChannelAPin<T>>,
b: Peri<'d, impl ChannelBPin<T>>,
b_pull: Pull,
mode: InputMode,
config: Config,
) -> Self {
into_ref!(slice, a, b);
Self::new_inner(
slice.number(),
Some(a.map_into()),
Some(b.map_into()),
Some(a.into()),
Some(b.into()),
b_pull,
config,
mode.into(),
@ -373,8 +345,8 @@ impl<'d> Pwm<'d> {
}
enum PwmChannelPin<'d> {
A(PeripheralRef<'d, AnyPin>),
B(PeripheralRef<'d, AnyPin>),
A(Peri<'d, AnyPin>),
B(Peri<'d, AnyPin>),
}
/// Single channel of Pwm driver.
@ -498,7 +470,7 @@ trait SealedSlice {}
/// PWM Slice.
#[allow(private_bounds)]
pub trait Slice: Peripheral<P = Self> + SealedSlice + Sized + 'static {
pub trait Slice: PeripheralType + SealedSlice + Sized + 'static {
/// Slice number.
fn number(&self) -> usize;
}

View File

@ -1,7 +1,7 @@
//! RTC driver.
mod filter;
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
pub use self::filter::DateTimeFilter;
@ -14,7 +14,7 @@ use crate::clocks::clk_rtc_freq;
/// A reference to the real time clock of the system
pub struct Rtc<'d, T: Instance> {
inner: PeripheralRef<'d, T>,
inner: Peri<'d, T>,
}
impl<'d, T: Instance> Rtc<'d, T> {
@ -23,9 +23,7 @@ impl<'d, T: Instance> Rtc<'d, T> {
/// # Errors
///
/// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range.
pub fn new(inner: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(inner);
pub fn new(inner: Peri<'d, T>) -> Self {
// Set the RTC divider
inner.regs().clkdiv_m1().write(|w| w.set_clkdiv_m1(clk_rtc_freq() - 1));
@ -194,7 +192,7 @@ trait SealedInstance {
/// RTC peripheral instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {}
pub trait Instance: SealedInstance + PeripheralType {}
impl SealedInstance for crate::peripherals::RTC {
fn regs(&self) -> crate::pac::rtc::Rtc {

View File

@ -3,12 +3,12 @@ use core::marker::PhantomData;
use embassy_embedded_hal::SetConfig;
use embassy_futures::join::join;
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
pub use embedded_hal_02::spi::{Phase, Polarity};
use crate::dma::{AnyChannel, Channel};
use crate::gpio::{AnyPin, Pin as GpioPin, SealedPin as _};
use crate::{pac, peripherals, Peripheral};
use crate::{pac, peripherals};
/// SPI errors.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -42,9 +42,9 @@ impl Default for Config {
/// SPI driver.
pub struct Spi<'d, T: Instance, M: Mode> {
inner: PeripheralRef<'d, T>,
tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
inner: Peri<'d, T>,
tx_dma: Option<Peri<'d, AnyChannel>>,
rx_dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
}
@ -73,17 +73,15 @@ fn calc_prescs(freq: u32) -> (u8, u8) {
impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
fn new_inner(
inner: impl Peripheral<P = T> + 'd,
clk: Option<PeripheralRef<'d, AnyPin>>,
mosi: Option<PeripheralRef<'d, AnyPin>>,
miso: Option<PeripheralRef<'d, AnyPin>>,
cs: Option<PeripheralRef<'d, AnyPin>>,
tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
inner: Peri<'d, T>,
clk: Option<Peri<'d, AnyPin>>,
mosi: Option<Peri<'d, AnyPin>>,
miso: Option<Peri<'d, AnyPin>>,
cs: Option<Peri<'d, AnyPin>>,
tx_dma: Option<Peri<'d, AnyChannel>>,
rx_dma: Option<Peri<'d, AnyChannel>>,
config: Config,
) -> Self {
into_ref!(inner);
Self::apply_config(&inner, &config);
let p = inner.regs();
@ -161,7 +159,7 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
///
/// Driver should be disabled before making changes and reenabled after the modifications
/// are applied.
fn apply_config(inner: &PeripheralRef<'d, T>, config: &Config) {
fn apply_config(inner: &Peri<'d, T>, config: &Config) {
let p = inner.regs();
let (presc, postdiv) = calc_prescs(config.frequency);
@ -273,18 +271,17 @@ impl<'d, T: Instance, M: Mode> Spi<'d, T, M> {
impl<'d, T: Instance> Spi<'d, T, Blocking> {
/// Create an SPI driver in blocking mode.
pub fn new_blocking(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
mosi: Peri<'d, impl MosiPin<T> + 'd>,
miso: Peri<'d, impl MisoPin<T> + 'd>,
config: Config,
) -> Self {
into_ref!(clk, mosi, miso);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(mosi.map_into()),
Some(miso.map_into()),
Some(clk.into()),
Some(mosi.into()),
Some(miso.into()),
None,
None,
None,
@ -294,16 +291,15 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
/// Create an SPI driver in blocking mode supporting writes only.
pub fn new_blocking_txonly(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
mosi: Peri<'d, impl MosiPin<T> + 'd>,
config: Config,
) -> Self {
into_ref!(clk, mosi);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(mosi.map_into()),
Some(clk.into()),
Some(mosi.into()),
None,
None,
None,
@ -314,17 +310,16 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
/// Create an SPI driver in blocking mode supporting reads only.
pub fn new_blocking_rxonly(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
miso: Peri<'d, impl MisoPin<T> + 'd>,
config: Config,
) -> Self {
into_ref!(clk, miso);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(clk.into()),
None,
Some(miso.map_into()),
Some(miso.into()),
None,
None,
None,
@ -336,43 +331,41 @@ impl<'d, T: Instance> Spi<'d, T, Blocking> {
impl<'d, T: Instance> Spi<'d, T, Async> {
/// Create an SPI driver in async mode supporting DMA operations.
pub fn new(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
mosi: Peri<'d, impl MosiPin<T> + 'd>,
miso: Peri<'d, impl MisoPin<T> + 'd>,
tx_dma: Peri<'d, impl Channel>,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx_dma, rx_dma, clk, mosi, miso);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(mosi.map_into()),
Some(miso.map_into()),
Some(clk.into()),
Some(mosi.into()),
Some(miso.into()),
None,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
Some(tx_dma.into()),
Some(rx_dma.into()),
config,
)
}
/// Create an SPI driver in async mode supporting DMA write operations only.
pub fn new_txonly(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
mosi: impl Peripheral<P = impl MosiPin<T> + 'd> + 'd,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
mosi: Peri<'d, impl MosiPin<T> + 'd>,
tx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx_dma, clk, mosi);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(mosi.map_into()),
Some(clk.into()),
Some(mosi.into()),
None,
None,
Some(tx_dma.map_into()),
Some(tx_dma.into()),
None,
config,
)
@ -380,29 +373,28 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
/// Create an SPI driver in async mode supporting DMA read operations only.
pub fn new_rxonly(
inner: impl Peripheral<P = T> + 'd,
clk: impl Peripheral<P = impl ClkPin<T> + 'd> + 'd,
miso: impl Peripheral<P = impl MisoPin<T> + 'd> + 'd,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
inner: Peri<'d, T>,
clk: Peri<'d, impl ClkPin<T> + 'd>,
miso: Peri<'d, impl MisoPin<T> + 'd>,
tx_dma: Peri<'d, impl Channel>,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx_dma, rx_dma, clk, miso);
Self::new_inner(
inner,
Some(clk.map_into()),
Some(clk.into()),
None,
Some(miso.map_into()),
Some(miso.into()),
None,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
Some(tx_dma.into()),
Some(rx_dma.into()),
config,
)
}
/// Write data to SPI using DMA.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let tx_ch = self.tx_dma.as_mut().unwrap();
let tx_ch = self.tx_dma.as_mut().unwrap().reborrow();
let tx_transfer = unsafe {
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
@ -427,14 +419,14 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
pub async fn read(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
// Start RX first. Transfer starts when TX starts, if RX
// is not started yet we might lose bytes.
let rx_ch = self.rx_dma.as_mut().unwrap();
let rx_ch = self.rx_dma.as_mut().unwrap().reborrow();
let rx_transfer = unsafe {
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, buffer, T::RX_DREQ)
};
let tx_ch = self.tx_dma.as_mut().unwrap();
let tx_ch = self.tx_dma.as_mut().unwrap().reborrow();
let tx_transfer = unsafe {
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
@ -462,20 +454,20 @@ impl<'d, T: Instance> Spi<'d, T, Async> {
async fn transfer_inner(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> {
// Start RX first. Transfer starts when TX starts, if RX
// is not started yet we might lose bytes.
let rx_ch = self.rx_dma.as_mut().unwrap();
let rx_ch = self.rx_dma.as_mut().unwrap().reborrow();
let rx_transfer = unsafe {
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::read(rx_ch, self.inner.regs().dr().as_ptr() as *const _, rx, T::RX_DREQ)
};
let mut tx_ch = self.tx_dma.as_mut().unwrap();
let mut tx_ch = self.tx_dma.as_mut().unwrap().reborrow();
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
let tx_transfer = async {
let p = self.inner.regs();
unsafe {
crate::dma::write(&mut tx_ch, tx, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
crate::dma::write(tx_ch.reborrow(), tx, p.dr().as_ptr() as *mut _, T::TX_DREQ).await;
if rx.len() > tx.len() {
let write_bytes_len = rx.len() - tx.len();
@ -519,7 +511,7 @@ pub trait Mode: SealedMode {}
/// SPI instance trait.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {}
pub trait Instance: SealedInstance + PeripheralType {}
macro_rules! impl_instance {
($type:ident, $irq:ident, $tx_dreq:expr, $rx_dreq:expr) => {

View File

@ -5,7 +5,7 @@ use core::marker::PhantomData;
use core::ops::Not;
use core::task::Poll;
use embassy_hal_internal::Peripheral;
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use rand_core::Error;
@ -20,7 +20,7 @@ trait SealedInstance {
/// TRNG peripheral instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {
pub trait Instance: SealedInstance + PeripheralType {
/// Interrupt for this peripheral.
type Interrupt: Interrupt;
}
@ -158,11 +158,7 @@ const TRNG_BLOCK_SIZE_BYTES: usize = TRNG_BLOCK_SIZE_BITS / 8;
impl<'d, T: Instance> Trng<'d, T> {
/// Create a new TRNG driver.
pub fn new(
_trng: impl Peripheral<P = T> + 'd,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd,
config: Config,
) -> Self {
pub fn new(_trng: Peri<'d, T>, _irq: impl Binding<T::Interrupt, InterruptHandler<T>> + 'd, config: Config) -> Self {
let regs = T::regs();
regs.rng_imr().write(|w| w.set_ehr_valid_int_mask(false));

View File

@ -90,17 +90,15 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
impl<'d, T: Instance> BufferedUart<'d, T> {
/// Create a buffered UART instance.
pub fn new(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx, rx);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config);
super::Uart::<'d, T, Async>::init(Some(tx.into()), Some(rx.into()), None, None, config);
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
Self {
@ -111,23 +109,21 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
/// Create a buffered UART instance with flow control.
pub fn new_with_rtscts(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx, rx, cts, rts);
super::Uart::<'d, T, Async>::init(
Some(tx.map_into()),
Some(rx.map_into()),
Some(rts.map_into()),
Some(cts.map_into()),
Some(tx.into()),
Some(rx.into()),
Some(rts.into()),
Some(cts.into()),
config,
);
init_buffers::<T>(irq, Some(tx_buffer), Some(rx_buffer));
@ -184,15 +180,13 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
impl<'d, T: Instance> BufferedUartRx<'d, T> {
/// Create a new buffered UART RX.
pub fn new(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rx: Peri<'d, impl RxPin<T>>,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(rx);
super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config);
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), None, None, config);
init_buffers::<T>(irq, None, Some(rx_buffer));
Self { phantom: PhantomData }
@ -200,16 +194,14 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
/// Create a new buffered UART RX with flow control.
pub fn new_with_rts(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(rx, rts);
super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config);
super::Uart::<'d, T, Async>::init(None, Some(rx.into()), Some(rts.into()), None, config);
init_buffers::<T>(irq, None, Some(rx_buffer));
Self { phantom: PhantomData }
@ -338,15 +330,13 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
impl<'d, T: Instance> BufferedUartTx<'d, T> {
/// Create a new buffered UART TX.
pub fn new(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
tx: Peri<'d, impl TxPin<T>>,
tx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config);
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, None, config);
init_buffers::<T>(irq, Some(tx_buffer), None);
Self { phantom: PhantomData }
@ -354,16 +344,14 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
/// Create a new buffered UART TX with flow control.
pub fn new_with_cts(
_uart: impl Peripheral<P = T> + 'd,
_uart: Peri<'d, T>,
irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
tx: Peri<'d, impl TxPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
tx_buffer: &'d mut [u8],
config: Config,
) -> Self {
into_ref!(tx, cts);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config);
super::Uart::<'d, T, Async>::init(Some(tx.into()), None, None, Some(cts.into()), config);
init_buffers::<T>(irq, Some(tx_buffer), None);
Self { phantom: PhantomData }

View File

@ -5,7 +5,7 @@ use core::task::Poll;
use atomic_polyfill::{AtomicU16, Ordering};
use embassy_futures::select::{select, Either};
use embassy_hal_internal::{into_ref, PeripheralRef};
use embassy_hal_internal::{Peri, PeripheralType};
use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{Delay, Timer};
use pac::uart::regs::Uartris;
@ -15,7 +15,7 @@ use crate::dma::{AnyChannel, Channel};
use crate::gpio::{AnyPin, SealedPin};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::pac::io::vals::{Inover, Outover};
use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
use crate::{interrupt, pac, peripherals, RegExt};
mod buffered;
pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx};
@ -142,30 +142,29 @@ pub struct Uart<'d, T: Instance, M: Mode> {
/// UART TX driver.
pub struct UartTx<'d, T: Instance, M: Mode> {
tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
tx_dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
}
/// UART RX driver.
pub struct UartRx<'d, T: Instance, M: Mode> {
rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<Peri<'d, AnyChannel>>,
phantom: PhantomData<(&'d mut T, M)>,
}
impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
/// Create a new DMA-enabled UART which can only send data
pub fn new(
_uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
_uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
tx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx, tx_dma);
Uart::<T, M>::init(Some(tx.map_into()), None, None, None, config);
Self::new_inner(Some(tx_dma.map_into()))
Uart::<T, M>::init(Some(tx.into()), None, None, None, config);
Self::new_inner(Some(tx_dma.into()))
}
fn new_inner(tx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
fn new_inner(tx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
Self {
tx_dma,
phantom: PhantomData,
@ -225,13 +224,8 @@ impl<'d, T: Instance, M: Mode> UartTx<'d, T, M> {
impl<'d, T: Instance> UartTx<'d, T, Blocking> {
/// Create a new UART TX instance for blocking mode operations.
pub fn new_blocking(
_uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
config: Config,
) -> Self {
into_ref!(tx);
Uart::<T, Blocking>::init(Some(tx.map_into()), None, None, None, config);
pub fn new_blocking(_uart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self {
Uart::<T, Blocking>::init(Some(tx.into()), None, None, None, config);
Self::new_inner(None)
}
@ -251,7 +245,7 @@ impl<'d, T: Instance> UartTx<'d, T, Blocking> {
impl<'d, T: Instance> UartTx<'d, T, Async> {
/// Write to UART TX from the provided buffer using DMA.
pub async fn write(&mut self, buffer: &[u8]) -> Result<(), Error> {
let ch = self.tx_dma.as_mut().unwrap();
let ch = self.tx_dma.as_mut().unwrap().reborrow();
let transfer = unsafe {
T::regs().uartdmacr().write_set(|reg| {
reg.set_txdmae(true);
@ -268,18 +262,17 @@ impl<'d, T: Instance> UartTx<'d, T, Async> {
impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
/// Create a new DMA-enabled UART which can only receive data
pub fn new(
_uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
_uart: Peri<'d, T>,
rx: Peri<'d, impl RxPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(rx, rx_dma);
Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
Self::new_inner(true, Some(rx_dma.map_into()))
Uart::<T, M>::init(None, Some(rx.into()), None, None, config);
Self::new_inner(true, Some(rx_dma.into()))
}
fn new_inner(has_irq: bool, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
fn new_inner(has_irq: bool, rx_dma: Option<Peri<'d, AnyChannel>>) -> Self {
debug_assert_eq!(has_irq, rx_dma.is_some());
if has_irq {
// disable all error interrupts initially
@ -346,13 +339,8 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
impl<'d, T: Instance> UartRx<'d, T, Blocking> {
/// Create a new UART RX instance for blocking mode operations.
pub fn new_blocking(
_uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
config: Config,
) -> Self {
into_ref!(rx);
Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config);
pub fn new_blocking(_uart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self {
Uart::<T, Blocking>::init(None, Some(rx.into()), None, None, config);
Self::new_inner(false, None)
}
@ -419,7 +407,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// start a dma transfer. if errors have happened in the interim some error
// interrupt flags will have been raised, and those will be picked up immediately
// by the interrupt handler.
let ch = self.rx_dma.as_mut().unwrap();
let ch = self.rx_dma.as_mut().unwrap().reborrow();
T::regs().uartimsc().write_set(|w| {
w.set_oeim(true);
w.set_beim(true);
@ -566,7 +554,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// start a dma transfer. if errors have happened in the interim some error
// interrupt flags will have been raised, and those will be picked up immediately
// by the interrupt handler.
let mut ch = self.rx_dma.as_mut().unwrap();
let ch = self.rx_dma.as_mut().unwrap();
T::regs().uartimsc().write_set(|w| {
w.set_oeim(true);
w.set_beim(true);
@ -583,7 +571,7 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
// If we don't assign future to a variable, the data register pointer
// is held across an await and makes the future non-Send.
crate::dma::read(
&mut ch,
ch.reborrow(),
T::regs().uartdr().as_ptr() as *const _,
sbuffer,
T::RX_DREQ.into(),
@ -700,41 +688,29 @@ impl<'d, T: Instance> UartRx<'d, T, Async> {
impl<'d, T: Instance> Uart<'d, T, Blocking> {
/// Create a new UART without hardware flow control
pub fn new_blocking(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
config: Config,
) -> Self {
into_ref!(tx, rx);
Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
None,
None,
false,
None,
None,
config,
)
Self::new_inner(uart, tx.into(), rx.into(), None, None, false, None, None, config)
}
/// Create a new UART with hardware flow control (RTS/CTS)
pub fn new_with_rtscts_blocking(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
config: Config,
) -> Self {
into_ref!(tx, rx, cts, rts);
Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
Some(rts.map_into()),
Some(cts.map_into()),
tx.into(),
rx.into(),
Some(rts.into()),
Some(cts.into()),
false,
None,
None,
@ -762,50 +738,48 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
impl<'d, T: Instance> Uart<'d, T, Async> {
/// Create a new DMA enabled UART without hardware flow control
pub fn new(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
tx_dma: Peri<'d, impl Channel>,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx, rx, tx_dma, rx_dma);
Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
tx.into(),
rx.into(),
None,
None,
true,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
Some(tx_dma.into()),
Some(rx_dma.into()),
config,
)
}
/// Create a new DMA enabled UART with hardware flow control (RTS/CTS)
pub fn new_with_rtscts(
uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
uart: Peri<'d, T>,
tx: Peri<'d, impl TxPin<T>>,
rx: Peri<'d, impl RxPin<T>>,
rts: Peri<'d, impl RtsPin<T>>,
cts: Peri<'d, impl CtsPin<T>>,
_irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd,
tx_dma: Peri<'d, impl Channel>,
rx_dma: Peri<'d, impl Channel>,
config: Config,
) -> Self {
into_ref!(tx, rx, cts, rts, tx_dma, rx_dma);
Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
Some(rts.map_into()),
Some(cts.map_into()),
tx.into(),
rx.into(),
Some(rts.into()),
Some(cts.into()),
true,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
Some(tx_dma.into()),
Some(rx_dma.into()),
config,
)
}
@ -813,14 +787,14 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
fn new_inner(
_uart: impl Peripheral<P = T> + 'd,
mut tx: PeripheralRef<'d, AnyPin>,
mut rx: PeripheralRef<'d, AnyPin>,
mut rts: Option<PeripheralRef<'d, AnyPin>>,
mut cts: Option<PeripheralRef<'d, AnyPin>>,
_uart: Peri<'d, T>,
mut tx: Peri<'d, AnyPin>,
mut rx: Peri<'d, AnyPin>,
mut rts: Option<Peri<'d, AnyPin>>,
mut cts: Option<Peri<'d, AnyPin>>,
has_irq: bool,
tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
tx_dma: Option<Peri<'d, AnyChannel>>,
rx_dma: Option<Peri<'d, AnyChannel>>,
config: Config,
) -> Self {
Self::init(
@ -838,10 +812,10 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
}
fn init(
tx: Option<PeripheralRef<'_, AnyPin>>,
rx: Option<PeripheralRef<'_, AnyPin>>,
rts: Option<PeripheralRef<'_, AnyPin>>,
cts: Option<PeripheralRef<'_, AnyPin>>,
tx: Option<Peri<'_, AnyPin>>,
rx: Option<Peri<'_, AnyPin>>,
rts: Option<Peri<'_, AnyPin>>,
cts: Option<Peri<'_, AnyPin>>,
config: Config,
) {
let r = T::regs();
@ -1326,7 +1300,7 @@ impl_mode!(Async);
/// UART instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance {
pub trait Instance: SealedInstance + PeripheralType {
/// Interrupt for this instance.
type Interrupt: interrupt::typelevel::Interrupt;
}

View File

@ -5,6 +5,7 @@ use core::slice;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
use embassy_hal_internal::PeripheralType;
use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver as driver;
use embassy_usb_driver::{
@ -12,7 +13,7 @@ use embassy_usb_driver::{
};
use crate::interrupt::typelevel::{Binding, Interrupt};
use crate::{interrupt, pac, peripherals, Peripheral, RegExt};
use crate::{interrupt, pac, peripherals, Peri, RegExt};
trait SealedInstance {
fn regs() -> crate::pac::usb::Usb;
@ -21,7 +22,7 @@ trait SealedInstance {
/// USB peripheral instance.
#[allow(private_bounds)]
pub trait Instance: SealedInstance + 'static {
pub trait Instance: SealedInstance + PeripheralType + 'static {
/// Interrupt for this peripheral.
type Interrupt: interrupt::typelevel::Interrupt;
}
@ -107,7 +108,7 @@ pub struct Driver<'d, T: Instance> {
impl<'d, T: Instance> Driver<'d, T> {
/// Create a new USB driver.
pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self {
pub fn new(_usb: Peri<'d, T>, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self {
T::Interrupt::unpend();
unsafe { T::Interrupt::enable() };

View File

@ -10,8 +10,8 @@ use core::marker::PhantomData;
use embassy_time::Duration;
use crate::pac;
use crate::peripherals::WATCHDOG;
use crate::{pac, Peri};
/// The reason for a system reset from the watchdog.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
@ -30,7 +30,7 @@ pub struct Watchdog {
impl Watchdog {
/// Create a new `Watchdog`
pub fn new(_watchdog: WATCHDOG) -> Self {
pub fn new(_watchdog: Peri<'static, WATCHDOG>) -> Self {
Self {
phantom: PhantomData,
load_value: 0,
@ -89,17 +89,25 @@ impl Watchdog {
/// Start the watchdog timer
pub fn start(&mut self, period: Duration) {
#[cfg(feature = "rp2040")]
const MAX_PERIOD: u32 = 0xFFFFFF / 2;
#[cfg(feature = "_rp235x")]
const MAX_PERIOD: u32 = 0xFFFFFF;
let delay_us = period.as_micros();
if delay_us > (MAX_PERIOD / 2) as u64 {
panic!("Period cannot exceed {} microseconds", MAX_PERIOD / 2);
if delay_us > (MAX_PERIOD) as u64 {
panic!("Period cannot exceed {} microseconds", MAX_PERIOD);
}
let delay_us = delay_us as u32;
// Due to a logic error, the watchdog decrements by 2 and
// the load value must be compensated; see RP2040-E1
self.load_value = delay_us * 2;
// This errata is fixed in the RP235x
if cfg!(feature = "rp2040") {
self.load_value = delay_us * 2;
} else {
self.load_value = delay_us;
}
self.enable(false);
self.configure_wdog_reset_triggers();

View File

@ -23,7 +23,7 @@ mod fmt;
use core::mem::MaybeUninit;
use core::sync::atomic::{compiler_fence, Ordering};
use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef};
use embassy_hal_internal::Peri;
use embassy_stm32::interrupt;
use embassy_stm32::ipcc::{Config, Ipcc, ReceiveInterruptHandler, TransmitInterruptHandler};
use embassy_stm32::peripherals::IPCC;
@ -52,7 +52,7 @@ type PacketHeader = LinkedListNode;
/// Transport Layer for the Mailbox interface
pub struct TlMbox<'d> {
_ipcc: PeripheralRef<'d, IPCC>,
_ipcc: Peri<'d, IPCC>,
pub sys_subsystem: Sys,
pub mm_subsystem: MemoryManager,
@ -92,13 +92,11 @@ impl<'d> TlMbox<'d> {
/// Figure 66.
// TODO: document what the user should do after calling init to use the mac_802_15_4 subsystem
pub fn init(
ipcc: impl Peripheral<P = IPCC> + 'd,
ipcc: Peri<'d, IPCC>,
_irqs: impl interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_RX, ReceiveInterruptHandler>
+ interrupt::typelevel::Binding<interrupt::typelevel::IPCC_C1_TX, TransmitInterruptHandler>,
config: Config,
) -> Self {
into_ref!(ipcc);
// this is an inlined version of TL_Init from the STM32WB firmware as requested by AN5289.
// HW_IPCC_Init is not called, and its purpose is (presumably?) covered by this
// implementation

View File

@ -324,7 +324,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_internal::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::Peri<'d, crate::peripherals::FLASH>, pub(crate) core::marker::PhantomData<MODE>);
});
}
@ -356,7 +356,7 @@ fn main() {
#[cfg(flash)]
impl<'d, MODE> FlashLayout<'d, MODE> {
pub(crate) fn new(p: embassy_hal_internal::PeripheralRef<'d, crate::peripherals::FLASH>) -> Self {
pub(crate) fn new(p: embassy_hal_internal::Peri<'d, crate::peripherals::FLASH>) -> Self {
Self {
#(#inits),*,
_mode: core::marker::PhantomData,
@ -1151,6 +1151,8 @@ fn main() {
(("tsc", "G8_IO2"), quote!(crate::tsc::G8IO2Pin)),
(("tsc", "G8_IO3"), quote!(crate::tsc::G8IO3Pin)),
(("tsc", "G8_IO4"), quote!(crate::tsc::G8IO4Pin)),
(("dac", "OUT1"), quote!(crate::dac::DacPin<Ch1>)),
(("dac", "OUT2"), quote!(crate::dac::DacPin<Ch2>)),
].into();
for p in METADATA.peripherals {
@ -1250,17 +1252,6 @@ fn main() {
}
}
// DAC is special
if regs.kind == "dac" {
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
let ch: u8 = pin.signal.strip_prefix("OUT").unwrap().parse().unwrap();
g.extend(quote! {
impl_dac_pin!( #peri, #pin_name, #ch);
})
}
if regs.kind == "spdifrx" {
let peri = format_ident!("{}", p.name);
let pin_name = format_ident!("{}", pin.pin);
@ -1304,8 +1295,8 @@ fn main() {
(("quadspi", "QUADSPI"), quote!(crate::qspi::QuadDma)),
(("octospi", "OCTOSPI1"), quote!(crate::ospi::OctoDma)),
(("hspi", "HSPI1"), quote!(crate::hspi::HspiDma)),
(("dac", "CH1"), quote!(crate::dac::DacDma1)),
(("dac", "CH2"), quote!(crate::dac::DacDma2)),
(("dac", "CH1"), quote!(crate::dac::Dma<Ch1>)),
(("dac", "CH2"), quote!(crate::dac::Dma<Ch2>)),
(("timer", "UP"), quote!(crate::timer::UpDma)),
(("hash", "IN"), quote!(crate::hash::Dma)),
(("cryp", "IN"), quote!(crate::cryp::DmaIn)),

View File

@ -8,7 +8,7 @@ use super::{
};
use crate::dma::Transfer;
use crate::time::Hertz;
use crate::{pac, rcc, Peripheral};
use crate::{pac, rcc, Peri};
/// Default VREF voltage used for sample conversion to millivolts.
pub const VREF_DEFAULT_MV: u32 = 3300;
@ -154,8 +154,7 @@ pub enum Averaging {
impl<'d, T: Instance> Adc<'d, T> {
/// Create a new ADC driver.
pub fn new(adc: impl Peripheral<P = T> + 'd, sample_time: SampleTime, resolution: Resolution) -> Self {
embassy_hal_internal::into_ref!(adc);
pub fn new(adc: Peri<'d, T>, sample_time: SampleTime, resolution: Resolution) -> Self {
rcc::enable_and_reset::<T>();
T::regs().cfgr2().modify(|w| w.set_ckmode(Ckmode::SYSCLK));
@ -319,7 +318,7 @@ impl<'d, T: Instance> Adc<'d, T> {
Self::apply_channel_conf()
}
async fn dma_convert(&mut self, rx_dma: &mut impl RxDma<T>, readings: &mut [u16]) {
async fn dma_convert(&mut self, rx_dma: Peri<'_, impl RxDma<T>>, readings: &mut [u16]) {
// Enable overrun control, so no new DMA requests will be generated until
// previous DR values is read.
T::regs().isr().modify(|reg| {
@ -374,7 +373,7 @@ impl<'d, T: Instance> Adc<'d, T> {
/// TODO(chudsaviet): externalize generic code and merge with read().
pub async fn read_in_hw_order(
&mut self,
rx_dma: &mut impl RxDma<T>,
rx_dma: Peri<'_, impl RxDma<T>>,
hw_channel_selection: u32,
scandir: Scandir,
readings: &mut [u16],
@ -415,7 +414,7 @@ impl<'d, T: Instance> Adc<'d, T> {
// For other channels, use `read_in_hw_order()` or blocking read.
pub async fn read(
&mut self,
rx_dma: &mut impl RxDma<T>,
rx_dma: Peri<'_, impl RxDma<T>>,
channel_sequence: impl ExactSizeIterator<Item = &mut AnyAdcChannel<T>>,
readings: &mut [u16],
) {

View File

@ -2,12 +2,10 @@ use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::into_ref;
use super::blocking_delay_us;
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
use crate::time::Hertz;
use crate::{interrupt, rcc, Peripheral};
use crate::{interrupt, rcc, Peri};
pub const VDDA_CALIB_MV: u32 = 3300;
pub const ADC_MAX: u32 = (1 << 12) - 1;
@ -48,8 +46,7 @@ impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
}
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
into_ref!(adc);
pub fn new(adc: Peri<'d, T>) -> Self {
rcc::enable_and_reset::<T>();
T::regs().cr2().modify(|reg| reg.set_adon(true));

View File

@ -2,13 +2,11 @@ use core::future::poll_fn;
use core::marker::PhantomData;
use core::task::Poll;
use embassy_hal_internal::into_ref;
use super::blocking_delay_us;
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
use crate::interrupt::typelevel::Interrupt;
use crate::time::Hertz;
use crate::{interrupt, rcc, Peripheral};
use crate::{interrupt, rcc, Peri};
pub const VDDA_CALIB_MV: u32 = 3300;
pub const ADC_MAX: u32 = (1 << 12) - 1;
@ -56,13 +54,11 @@ impl<T: Instance> super::SealedAdcChannel<T> for Temperature {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(
adc: impl Peripheral<P = T> + 'd,
adc: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
use crate::pac::adc::vals;
into_ref!(adc);
rcc::enable_and_reset::<T>();
// Enable the adc regulator

View File

@ -3,14 +3,13 @@ use core::marker::PhantomData;
use core::task::Poll;
use embassy_futures::yield_now;
use embassy_hal_internal::into_ref;
use embassy_time::Instant;
use super::Resolution;
use crate::adc::{Adc, AdcChannel, Instance, SampleTime};
use crate::interrupt::typelevel::Interrupt;
use crate::time::Hertz;
use crate::{interrupt, rcc, Peripheral};
use crate::{interrupt, rcc, Peri};
const ADC_FREQ: Hertz = crate::rcc::HSI_FREQ;
@ -138,11 +137,9 @@ impl<T: Instance> Drop for Temperature<T> {
impl<'d, T: Instance> Adc<'d, T> {
pub fn new(
adc: impl Peripheral<P = T> + 'd,
adc: Peri<'d, T>,
_irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
) -> Self {
into_ref!(adc);
rcc::enable_and_reset::<T>();
//let r = T::regs();

View File

@ -11,7 +11,7 @@ use super::{blocking_delay_us, Adc, AdcChannel, AnyAdcChannel, Instance, Resolut
use crate::adc::SealedAdcChannel;
use crate::dma::Transfer;
use crate::time::Hertz;
use crate::{pac, rcc, Peripheral};
use crate::{pac, rcc, Peri};
/// Default VREF voltage used for sample conversion to millivolts.
pub const VREF_DEFAULT_MV: u32 = 3300;
@ -135,8 +135,7 @@ impl Prescaler {
impl<'d, T: Instance> Adc<'d, T> {
/// Create a new ADC driver.
pub fn new(adc: impl Peripheral<P = T> + 'd) -> Self {
embassy_hal_internal::into_ref!(adc);
pub fn new(adc: Peri<'d, T>) -> Self {
rcc::enable_and_reset::<T>();
let prescaler = Prescaler::from_ker_ck(T::frequency());
@ -172,7 +171,7 @@ impl<'d, T: Instance> Adc<'d, T> {
reg.set_advregen(true);
});
blocking_delay_us(10);
blocking_delay_us(20);
}
fn configure_differential_inputs(&mut self) {
@ -192,6 +191,8 @@ impl<'d, T: Instance> Adc<'d, T> {
while T::regs().cr().read().adcal() {}
blocking_delay_us(20);
T::regs().cr().modify(|w| {
w.set_adcaldif(Adcaldif::DIFFERENTIAL);
});
@ -199,6 +200,8 @@ impl<'d, T: Instance> Adc<'d, T> {
T::regs().cr().modify(|w| w.set_adcal(true));
while T::regs().cr().read().adcal() {}
blocking_delay_us(20);
}
fn enable(&mut self) {
@ -364,8 +367,8 @@ impl<'d, T: Instance> Adc<'d, T> {
/// use embassy_stm32::adc::{Adc, AdcChannel}
///
/// let mut adc = Adc::new(p.ADC1);
/// let mut adc_pin0 = p.PA0.degrade_adc();
/// let mut adc_pin1 = p.PA1.degrade_adc();
/// let mut adc_pin0 = p.PA0.into();
/// let mut adc_pin1 = p.PA1.into();
/// let mut measurements = [0u16; 2];
///
/// adc.read_async(
@ -382,7 +385,7 @@ impl<'d, T: Instance> Adc<'d, T> {
/// ```
pub async fn read(
&mut self,
rx_dma: &mut impl RxDma<T>,
rx_dma: Peri<'_, impl RxDma<T>>,
sequence: impl ExactSizeIterator<Item = (&mut AnyAdcChannel<T>, SampleTime)>,
readings: &mut [u16],
) {

View File

@ -22,6 +22,7 @@ use core::marker::PhantomData;
#[allow(unused)]
#[cfg(not(any(adc_f3_v2)))]
pub use _version::*;
use embassy_hal_internal::{impl_peripheral, PeripheralType};
#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
use embassy_sync::waitqueue::AtomicWaker;
@ -42,7 +43,7 @@ dma_trait!(RxDma4, adc4::Instance);
/// Analog to Digital driver.
pub struct Adc<'d, T: Instance> {
#[allow(unused)]
adc: crate::PeripheralRef<'d, T>,
adc: crate::Peri<'d, T>,
#[cfg(not(any(adc_f3_v2, adc_f3_v1_1)))]
sample_time: SampleTime,
}
@ -111,7 +112,7 @@ pub(crate) fn blocking_delay_us(us: u32) {
adc_c0
)))]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
pub trait Instance: SealedInstance + crate::PeripheralType {
type Interrupt: crate::interrupt::typelevel::Interrupt;
}
/// ADC instance.
@ -132,7 +133,7 @@ pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
adc_c0
))]
#[allow(private_bounds)]
pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {
pub trait Instance: SealedInstance + crate::PeripheralType + crate::rcc::RccPeripheral {
type Interrupt: crate::interrupt::typelevel::Interrupt;
}
@ -159,7 +160,7 @@ pub struct AnyAdcChannel<T> {
channel: u8,
_phantom: PhantomData<T>,
}
impl_peripheral!(AnyAdcChannel<T: Instance>);
impl<T: Instance> AdcChannel<T> for AnyAdcChannel<T> {}
impl<T: Instance> SealedAdcChannel<T> for AnyAdcChannel<T> {
fn channel(&self) -> u8 {
@ -233,11 +234,11 @@ foreach_adc!(
macro_rules! impl_adc_pin {
($inst:ident, $pin:ident, $ch:expr) => {
impl crate::adc::AdcChannel<peripherals::$inst> for crate::peripherals::$pin {}
impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::peripherals::$pin {
impl crate::adc::AdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {}
impl crate::adc::SealedAdcChannel<peripherals::$inst> for crate::Peri<'_, crate::peripherals::$pin> {
#[cfg(any(adc_v1, adc_c0, adc_l0, adc_v2, adc_g4, adc_v4, adc_u5))]
fn setup(&mut self) {
<Self as crate::gpio::SealedPin>::set_as_analog(self);
<crate::peripherals::$pin as crate::gpio::SealedPin>::set_as_analog(self);
}
fn channel(&self) -> u8 {

View File

@ -2,13 +2,12 @@ use core::marker::PhantomData;
use core::mem;
use core::sync::atomic::{compiler_fence, Ordering};
use embassy_hal_internal::{into_ref, Peripheral};
use stm32_metapac::adc::vals::SampleTime;
use crate::adc::{Adc, AdcChannel, Instance, RxDma};
use crate::dma::{Priority, ReadableRingBuffer, TransferOptions};
use crate::pac::adc::vals;
use crate::rcc;
use crate::{rcc, Peri};
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct OverrunError;
@ -103,13 +102,8 @@ impl<'d, T: Instance> Adc<'d, T> {
/// It is critical to call `read` frequently to prevent DMA buffer overrun.
///
/// [`read`]: #method.read
pub fn into_ring_buffered(
self,
dma: impl Peripheral<P = impl RxDma<T>> + 'd,
dma_buf: &'d mut [u16],
) -> RingBufferedAdc<'d, T> {
pub fn into_ring_buffered(self, dma: Peri<'d, impl RxDma<T>>, dma_buf: &'d mut [u16]) -> RingBufferedAdc<'d, T> {
assert!(!dma_buf.is_empty() && dma_buf.len() <= 0xFFFF);
into_ref!(dma);
let opts: crate::dma::TransferOptions = TransferOptions {
half_transfer_ir: true,

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