1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
//! A hardware abstraction layer (HAL) for i.MX RT MCUs.
//!
//! `imxrt-hal` contains a collection of hardware drivers for various i.MX RT
//! MCUs. A default build of `imxrt-hal` provides drivers that are portable
//! across all i.MX RT chips. When your specific chip is known, `imxrt-hal`
//! provides additional, chip-specific APIs. Most drivers implement their
//! corresponding `embedded-hal` traits, or they can be adapted to use
//! `embedded-hal` traits in user code.
//!
//! # Building
//!
//! `imxrt-hal` requires that you, or something in your dependency graph, enable
//! a chip-specific feature from `imxrt-ral`, the i.MX RT _register access layer
//! (RAL)_. Without this, the HAL does not build. Since the HAL uses the RAL in
//! its public API, you're expected to depend on both packages.
//!
//! Here's an example of a project that builds the `imxrt-hal` for an i.MX RT
//! 1062 system.
//!
//! ```toml
//! [dependencies.imxrt-hal] # There's no required feature here...
//! version = # ...
//!
//! [dependencies.imxrt-ral]
//! version = # ...
//! features = ["imxrt1062"] # ...but this feature is required.
//! ```
//!
//! Once you've enabled a RAL feature, the HAL builds without any additional
//! features. All APIs exposed in this build are portable across all supported
//! i.MX RT chips.
//!
//! # Examples
//!
//! See each module's documentation for examples. Note that documentation
//! examples may assume a specific chip and chip family, so you may need to
//! adapt the example for your hardware.
//!
//! The `imxrt-hal` repository maintains examples that run on various i.MX RT
//! development boards. See the project documentation for more information.
//!
//! # Configuration
//!
//! Use these optional features to control the HAL build.
//!
//! | Feature | Description |
//! |-------------------|------------------------------------------------------------------|
//! | `"imxrt1010"` | Enable features for the 1010 chips. |
//! | `"imxrt1020"` | Enable features for the 1020 chips. |
//! | `"imxrt1060"` | Enable features for the 1060 chips. |
//! | `"imxrt1064"` | Enable features for the 1064 chips. |
//! | `"imxrt1170"` | Enable features for the 1170 chips. |
//! | `"eh02-unproven"` | Enable implementations for embedded-hal 0.2 `"unproven"` traits. |
//! | `"rand_core"` | Allows the TRNG to be used with the `rand` package. |
//!
//! The APIs exposed by the various `"imxrt[...]"` features are chip specific.
//! The HAL does not support building with more than one of these features at a
//! time.
//!
//! When enabling a HAL chip feature, make sure that it pairs properly with your
//! RAL chip selection. You are responsible for making sure that your RAL chip
//! feature is appropriate for the HAL chip feature. For instance, mixing the
//! RAL's `imxrt1062` feature with the HAL's `imxrt1010` feature is not
//! supported.
//!
//! ```toml
//! [dependencies.imxrt-hal]
//! version = # ...
//! #Bad: doesn't support RAL feature.
//! #features = ["imxrt1010"]
//!
//! #Good: supports RAL feature
//! features = ["imxrt1060"]
//!
//! [dependencies.imxrt-ral]
//! version = # ...
//! features = ["imxrt1062"] # Informs the HAL chip feature
//! ```
//!
//! The `"eh02-unproven"` feature will not build without the corresponding
//! `"unproven"` feature enabled in embedded-hal 0.2.
#![no_std]
#![warn(missing_docs, unsafe_op_in_unsafe_fn)]
use imxrt_ral as ral;
mod chip;
/// Modules that need no HAL conditional compilation.
///
/// These modules only depend on a RAL feature.
mod common {
pub use imxrt_dma as dma;
pub mod ccm;
pub mod flexpwm;
pub mod gpio;
pub mod gpt;
pub mod lpi2c;
pub mod lpspi;
pub mod lpuart;
pub mod pit;
pub mod snvs;
pub mod timer;
}
// These common drivers have no associated chip APIs, so
// export them directly.
pub use common::{flexpwm, gpio, gpt, lpi2c, lpspi, lpuart, pit, snvs, timer};
/// Clock control module.
///
/// Unlike other drivers in this package, this module only provides a
/// thin layer over the `imxrt-ral` APIs. It's fairly low level, but
/// more discoverable than the registers and reference manual.
///
/// # Overview
///
/// Use [`clock_gate`](crate::ccm::clock_gate) APIs to enable or disable the clock gates for
/// various peripherals. You'll need to enable clock gates before you
/// start using peripherals.
///
/// The remaining modules provide lower-level APIs for the CCM clock
/// tree. These APIs may not be portable across chip families.
///
/// # Visibility
///
/// If you see items in this module, it's because a chip family feature is
/// enabled in the HAL. These symbols may vary depending on the selected
/// feature.
pub mod ccm {
pub use crate::chip::ccm::*;
}
/// Direct memory access.
///
/// Use the `dma` APIs to perform memory operations without processor intervention.
/// The API supports the following transfers:
///
/// - peripheral to memory
/// - memory to peripheral
/// - memory to memory
///
/// Peripheral support depends on the peripheral. See your peripheral's API for details.
/// Methods that use DMA are typically prefixed with `dma`.
///
/// DMA transfers are modeled as futures. The examples below demonstrate a simple way
/// to start a transfer. Since these are futures, you may use these futures in `async` code.
///
/// # DMA channels
///
/// The API provides access to at least 16 DMA channels. If you've enabled an optional chip
/// family feature, this number may change. See [`CHANNEL_COUNT`](crate::dma::CHANNEL_COUNT)
/// for more information.
///
/// # Visibility
///
/// Select items become visible when a chip family feature is enabled.
///
/// # Example
///
/// Use [`channels()`](crate::dma::channels) to access all DMA channels for your processor.
///
/// ```no_run
/// use imxrt_hal as hal;
/// use imxrt_ral as ral;
///
/// # fn doc() -> Option<()> {
/// let mut ccm = unsafe { ral::ccm::CCM::instance() };
/// hal::ccm::clock_gate::dma().set(&mut ccm, hal::ccm::clock_gate::ON);
///
/// let mut channels = hal::dma::channels(
/// unsafe { ral::dma::DMA::instance() },
/// unsafe { ral::dmamux::DMAMUX::instance() },
/// );
///
/// // Selecting the 13th DMA channel for our examples...
/// let mut channel = channels[13].take()?;
/// # Some(()) }
/// ```
///
/// Construct and poll a [`Memcpy`](crate::dma::memcpy::Memcpy) to
/// perform a memory-to-memory transfer.
///
/// ```no_run
/// # async fn a() -> Option<()> {
/// # use imxrt_hal as hal;
/// # use imxrt_ral as ral;
/// # let mut channel = unsafe { hal::dma::DMA.channel(13) };
/// let source = [4u32, 5, 6, 7];
/// let mut destination = [0u32; 4];
///
/// let memcpy = hal::dma::memcpy::memcpy(&source, &mut destination, &mut channel);
/// memcpy.await.ok()?;
/// # Some(()) }
/// ```
///
/// For examples of using DMA with a peripheral, see the peripheral's documentation.
pub mod dma {
#[cfg_attr(family = "none", allow(unused_imports))] // Nothing to export in this build.
pub use crate::chip::dma::*;
pub use crate::common::dma::*;
}
/// USB device.
///
/// This module re-exports types from the `imxrt-usbd` package. The driver is compatible
/// with the [`usb-device`](https://docs.rs/usb-device/latest/usb_device/) ecosystem.
///
/// It also provides [`Instances`](crate::usbd::Instances), an implementation of `imxrt_usbd::Peripherals` over
/// `imxrt-ral` USB instances.
///
/// # Example
///
/// Construct a [`BusAdapter`](crate::usbd::BusAdapter) with USB peripheral instances. See the
/// [`BusAdapter`](crate::usbd::BusAdapter) documentation for more information on how to use the bus.
///
/// ```no_run
/// use imxrt_hal as hal;
/// use imxrt_ral as ral;
///
/// use hal::usbd;
///
/// # || -> Option<()> {
/// let mut usb_analog = unsafe { ral::usb_analog::USB_ANALOG::instance() };
/// let usb_instances = usbd::Instances {
/// usb: unsafe { ral::usb::USB1::instance() },
/// usbnc: unsafe { ral::usbnc::USBNC1::instance() },
/// usbphy: unsafe { ral::usbphy::USBPHY1::instance() },
/// };
///
/// // Prepare the USB clocks.
/// let mut ccm_analog = unsafe { ral::ccm_analog::CCM_ANALOG::instance() };
/// hal::ccm::analog::pll3::restart(&mut ccm_analog);
///
/// static ENDPOINT_MEMORY: usbd::EndpointMemory<2048> = usbd::EndpointMemory::new();
/// static ENDPOINT_STATE: usbd::EndpointState = usbd::EndpointState::max_endpoints();
///
/// let usbd = usbd::BusAdapter::new(usb_instances, &ENDPOINT_MEMORY, &ENDPOINT_STATE);
/// # Some(()) }().unwrap();
/// ```
#[cfg(feature = "imxrt-usbd")]
pub mod usbd {
pub use imxrt_usbd::*;
use crate::ral;
/// Aggregate of `imxrt-ral` USB peripheral instances.
///
/// This takes ownership of USB peripheral instances and implements
/// [`Peripherals`]. You can use this type to allocate a USB device
/// driver. See the [module-level documentation](crate::usbd) for an
/// example.
pub struct Instances<const N: u8> {
/// USB core registers.
pub usb: ral::usb::Instance<N>,
/// USB non-core registers.
pub usbnc: ral::usbnc::Instance<N>,
/// USBPHY registers.
pub usbphy: ral::usbphy::Instance<N>,
}
unsafe impl<const N: u8> Peripherals for Instances<N> {
fn usb(&self) -> *const () {
(&*self.usb as *const ral::usb::RegisterBlock).cast()
}
fn usbphy(&self) -> *const () {
(&*self.usbphy as *const ral::usbphy::RegisterBlock).cast()
}
}
}
/// Pad muxing and configurations.
///
/// This module re-exports select items from the `imxrt-iomuxc` crate. When a chip feature is enabled, the module also exports
/// chip-specific items, like `into_pads`. Use [`into_pads`](crate::iomuxc::into_pads) to transform the `imxrt-ral` instance(s)
/// into pad objects:
///
/// ```
/// use imxrt_hal as hal;
/// use imxrt_ral as ral;
///
/// let iomuxc = unsafe { ral::iomuxc::IOMUXC::instance() };
/// let pads = hal::iomuxc::into_pads(iomuxc);
/// ```
///
/// [`Pads`](crate::iomuxc::pads::Pads) exposes all pads as individual, owned objects. Use [`configure`](crate::iomuxc::configure)
/// to specify any pad configurations. Then use the pad object(s) to construct your driver.
pub mod iomuxc {
#[cfg_attr(family = "none", allow(unused_imports))] // Nothing to export in this build.
pub use crate::chip::iomuxc::*;
pub use imxrt_iomuxc::prelude::*;
}
#[cfg_attr(family = "none", allow(unused_imports))] // Nothing to export in this build.
pub use crate::chip::reexports::*;
/// Simply spin on the future.
fn spin_on<F: core::future::Future>(future: F) -> F::Output {
use core::task::{Context, Poll};
let waker = futures::task::noop_waker();
let mut context = Context::from_waker(&waker);
let mut future = core::pin::pin!(future);
loop {
if let Poll::Ready(result) = future.as_mut().poll(&mut context) {
return result;
}
}
}