mirror of
https://github.com/esp-rs/esp-hal.git
synced 2025-09-27 12:20:56 +00:00
Get rid of missing docs
in a number of modules (#1967)
* Get rid of missing docs in a number of modules * address reviews * Address the rest of reviews * remove all remaining `allows` * are you serious?
This commit is contained in:
parent
f829c8f2ac
commit
19db509403
@ -12,45 +12,93 @@ pub(super) const RA_OFFSET: usize = 4;
|
||||
|
||||
/// Registers saved in trap handler
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(C)]
|
||||
pub(crate) struct TrapFrame {
|
||||
/// Return address, stores the address to return to after a function call or
|
||||
/// interrupt.
|
||||
pub ra: usize,
|
||||
/// Temporary register t0, used for intermediate values.
|
||||
pub t0: usize,
|
||||
/// Temporary register t1, used for intermediate values.
|
||||
pub t1: usize,
|
||||
/// Temporary register t2, used for intermediate values.
|
||||
pub t2: usize,
|
||||
/// Temporary register t3, used for intermediate values.
|
||||
pub t3: usize,
|
||||
/// Temporary register t4, used for intermediate values.
|
||||
pub t4: usize,
|
||||
/// Temporary register t5, used for intermediate values.
|
||||
pub t5: usize,
|
||||
/// Temporary register t6, used for intermediate values.
|
||||
pub t6: usize,
|
||||
/// Argument register a0, typically used to pass the first argument to a
|
||||
/// function.
|
||||
pub a0: usize,
|
||||
/// Argument register a1, typically used to pass the second argument to a
|
||||
/// function.
|
||||
pub a1: usize,
|
||||
/// Argument register a2, typically used to pass the third argument to a
|
||||
/// function.
|
||||
pub a2: usize,
|
||||
/// Argument register a3, typically used to pass the fourth argument to a
|
||||
/// function.
|
||||
pub a3: usize,
|
||||
/// Argument register a4, typically used to pass the fifth argument to a
|
||||
/// function.
|
||||
pub a4: usize,
|
||||
/// Argument register a5, typically used to pass the sixth argument to a
|
||||
/// function.
|
||||
pub a5: usize,
|
||||
/// Argument register a6, typically used to pass the seventh argument to a
|
||||
/// function.
|
||||
pub a6: usize,
|
||||
/// Argument register a7, typically used to pass the eighth argument to a
|
||||
/// function.
|
||||
pub a7: usize,
|
||||
/// Saved register s0, used to hold values across function calls.
|
||||
pub s0: usize,
|
||||
/// Saved register s1, used to hold values across function calls.
|
||||
pub s1: usize,
|
||||
/// Saved register s2, used to hold values across function calls.
|
||||
pub s2: usize,
|
||||
/// Saved register s3, used to hold values across function calls.
|
||||
pub s3: usize,
|
||||
/// Saved register s4, used to hold values across function calls.
|
||||
pub s4: usize,
|
||||
/// Saved register s5, used to hold values across function calls.
|
||||
pub s5: usize,
|
||||
/// Saved register s6, used to hold values across function calls.
|
||||
pub s6: usize,
|
||||
/// Saved register s7, used to hold values across function calls.
|
||||
pub s7: usize,
|
||||
/// Saved register s8, used to hold values across function calls.
|
||||
pub s8: usize,
|
||||
/// Saved register s9, used to hold values across function calls.
|
||||
pub s9: usize,
|
||||
/// Saved register s10, used to hold values across function calls.
|
||||
pub s10: usize,
|
||||
/// Saved register s11, used to hold values across function calls.
|
||||
pub s11: usize,
|
||||
/// Global pointer register, holds the address of the global data area.
|
||||
pub gp: usize,
|
||||
/// Thread pointer register, holds the address of the thread-local storage
|
||||
/// area.
|
||||
pub tp: usize,
|
||||
/// Stack pointer register, holds the address of the top of the stack.
|
||||
pub sp: usize,
|
||||
/// Program counter, stores the address of the next instruction to be
|
||||
/// executed.
|
||||
pub pc: usize,
|
||||
/// Machine status register, holds the current status of the processor,
|
||||
/// including interrupt enable bits and privilege mode.
|
||||
pub mstatus: usize,
|
||||
/// Machine cause register, contains the reason for the trap (e.g.,
|
||||
/// exception or interrupt number).
|
||||
pub mcause: usize,
|
||||
/// Machine trap value register, contains additional information about the
|
||||
/// trap (e.g., faulting address).
|
||||
pub mtval: usize,
|
||||
}
|
||||
|
||||
|
@ -9,8 +9,8 @@ use crate::MAX_BACKTRACE_ADDRESSES;
|
||||
#[cfg(feature = "panic-handler")]
|
||||
pub(super) const RA_OFFSET: usize = 3;
|
||||
|
||||
/// Exception Cause
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(C)]
|
||||
@ -95,89 +95,165 @@ pub enum ExceptionCause {
|
||||
Cp6Disabled = 38,
|
||||
/// Access To Coprocessor 7 When Disabled
|
||||
Cp7Disabled = 39,
|
||||
|
||||
/// None
|
||||
None = 255,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_docs, non_snake_case)]
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(C)]
|
||||
pub struct Context {
|
||||
/// Program counter, stores the address of the next instruction to be
|
||||
/// executed.
|
||||
pub PC: u32,
|
||||
/// Processor status, holds various status flags for the CPU.
|
||||
pub PS: u32,
|
||||
/// General-purpose register A0 used for data storage and manipulation.
|
||||
pub A0: u32,
|
||||
/// General-purpose register A1 used for data storage and manipulation.
|
||||
pub A1: u32,
|
||||
/// General-purpose register A2 used for data storage and manipulation.
|
||||
pub A2: u32,
|
||||
/// General-purpose register A3 used for data storage and manipulation.
|
||||
pub A3: u32,
|
||||
/// General-purpose register A4 used for data storage and manipulation.
|
||||
pub A4: u32,
|
||||
/// General-purpose register A5 used for data storage and manipulation.
|
||||
pub A5: u32,
|
||||
/// General-purpose register A6 used for data storage and manipulation.
|
||||
pub A6: u32,
|
||||
/// General-purpose register A7 used for data storage and manipulation.
|
||||
pub A7: u32,
|
||||
/// General-purpose register A8 used for data storage and manipulation.
|
||||
pub A8: u32,
|
||||
/// General-purpose register A9 used for data storage and manipulation.
|
||||
pub A9: u32,
|
||||
/// General-purpose register A10 used for data storage and manipulation.
|
||||
pub A10: u32,
|
||||
/// General-purpose register A11 used for data storage and manipulation.
|
||||
pub A11: u32,
|
||||
/// General-purpose register A12 used for data storage and manipulation.
|
||||
pub A12: u32,
|
||||
/// General-purpose register A13 used for data storage and manipulation.
|
||||
pub A13: u32,
|
||||
/// General-purpose register A14 used for data storage and manipulation.
|
||||
pub A14: u32,
|
||||
/// General-purpose register A15 used for data storage and manipulation.
|
||||
pub A15: u32,
|
||||
/// Shift amount register, used for shift and rotate instructions.
|
||||
pub SAR: u32,
|
||||
/// Exception cause, indicates the reason for the last exception.
|
||||
pub EXCCAUSE: u32,
|
||||
/// Exception address, holds the address related to the exception.
|
||||
pub EXCVADDR: u32,
|
||||
/// Loop start address, used in loop instructions.
|
||||
pub LBEG: u32,
|
||||
/// Loop end address, used in loop instructions.
|
||||
pub LEND: u32,
|
||||
/// Loop counter, used to count iterations in loop instructions.
|
||||
pub LCOUNT: u32,
|
||||
/// Thread pointer, used for thread-local storage.
|
||||
pub THREADPTR: u32,
|
||||
/// Compare register, used for certain compare instructions.
|
||||
pub SCOMPARE1: u32,
|
||||
/// Break register, used for breakpoint-related operations.
|
||||
pub BR: u32,
|
||||
/// Accumulator low register, used for extended arithmetic operations.
|
||||
pub ACCLO: u32,
|
||||
/// Accumulator high register, used for extended arithmetic operations.
|
||||
pub ACCHI: u32,
|
||||
/// Additional register M0 used for special operations.
|
||||
pub M0: u32,
|
||||
/// Additional register M1 used for special operations.
|
||||
pub M1: u32,
|
||||
/// Additional register M2 used for special operations.
|
||||
pub M2: u32,
|
||||
/// Additional register M3 used for special operations.
|
||||
pub M3: u32,
|
||||
/// 64-bit floating-point register (low part), available if the
|
||||
/// `print-float-registers` feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F64R_LO: u32,
|
||||
/// 64-bit floating-point register (high part), available if the
|
||||
/// `print-float-registers` feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F64R_HI: u32,
|
||||
/// Floating-point status register, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F64S: u32,
|
||||
/// Floating-point control register, available if the
|
||||
/// `print-float-registers` feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub FCR: u32,
|
||||
/// Floating-point status register, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub FSR: u32,
|
||||
/// Floating-point register F0, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F0: u32,
|
||||
/// Floating-point register F1, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F1: u32,
|
||||
/// Floating-point register F2, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F2: u32,
|
||||
/// Floating-point register F3, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F3: u32,
|
||||
/// Floating-point register F4, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F4: u32,
|
||||
/// Floating-point register F5, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F5: u32,
|
||||
/// Floating-point register F6, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F6: u32,
|
||||
/// Floating-point register F7, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F7: u32,
|
||||
/// Floating-point register F8, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F8: u32,
|
||||
/// Floating-point register F9, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F9: u32,
|
||||
/// Floating-point register F10, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F10: u32,
|
||||
/// Floating-point register F11, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F11: u32,
|
||||
/// Floating-point register F12, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F12: u32,
|
||||
/// Floating-point register F13, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F13: u32,
|
||||
/// Floating-point register F14, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F14: u32,
|
||||
/// Floating-point register F15, available if the `print-float-registers`
|
||||
/// feature is enabled.
|
||||
#[cfg(feature = "print-float-registers")]
|
||||
pub F15: u32,
|
||||
}
|
||||
|
@ -523,17 +523,26 @@ pub enum DmaError {
|
||||
#[cfg(gdma)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum DmaPriority {
|
||||
/// The lowest priority level (Priority 0).
|
||||
Priority0 = 0,
|
||||
/// Priority level 1.
|
||||
Priority1 = 1,
|
||||
/// Priority level 2.
|
||||
Priority2 = 2,
|
||||
/// Priority level 3.
|
||||
Priority3 = 3,
|
||||
/// Priority level 4.
|
||||
Priority4 = 4,
|
||||
/// Priority level 5.
|
||||
Priority5 = 5,
|
||||
/// Priority level 6.
|
||||
Priority6 = 6,
|
||||
/// Priority level 7.
|
||||
Priority7 = 7,
|
||||
/// Priority level 8.
|
||||
Priority8 = 8,
|
||||
/// The highest priority level (Priority 9).
|
||||
Priority9 = 9,
|
||||
}
|
||||
|
||||
@ -542,8 +551,8 @@ pub enum DmaPriority {
|
||||
#[cfg(pdma)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum DmaPriority {
|
||||
/// The lowest priority level (Priority 0).
|
||||
Priority0 = 0,
|
||||
}
|
||||
|
||||
@ -860,10 +869,12 @@ impl DescriptorChain {
|
||||
|
||||
/// Block size for transfers to/from psram
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum DmaExtMemBKSize {
|
||||
/// External memory block size of 16 bytes.
|
||||
Size16 = 0,
|
||||
/// External memory block size of 32 bytes.
|
||||
Size32 = 1,
|
||||
/// External memory block size of 64 bytes.
|
||||
Size64 = 2,
|
||||
}
|
||||
|
||||
|
@ -25,8 +25,6 @@
|
||||
//!
|
||||
//! [ECC]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/ecc.rs
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::{
|
||||
@ -55,30 +53,47 @@ pub enum Error {
|
||||
PointNotOnSelectedCurve,
|
||||
}
|
||||
|
||||
/// Represents supported elliptic curves for cryptographic operations.
|
||||
pub enum EllipticCurve {
|
||||
/// The P-192 elliptic curve, a 192-bit curve.
|
||||
P192 = 0,
|
||||
/// The P-256 elliptic curve. a 256-bit curve.
|
||||
P256 = 1,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
/// Represents the operational modes for elliptic curve or modular arithmetic
|
||||
/// computations.
|
||||
pub enum WorkMode {
|
||||
/// Point multiplication mode.
|
||||
PointMultiMode = 0,
|
||||
#[cfg(esp32c2)]
|
||||
/// Division mode.
|
||||
DivisionMode = 1,
|
||||
/// Point verification mode.
|
||||
PointVerif = 2,
|
||||
/// Point verification and multiplication mode.
|
||||
PointVerifMulti = 3,
|
||||
/// Jacobian point multiplication mode.
|
||||
JacobianPointMulti = 4,
|
||||
#[cfg(esp32h2)]
|
||||
/// Point addition mode.
|
||||
PointAdd = 5,
|
||||
/// Jacobian point verification mode.
|
||||
JacobianPointVerif = 6,
|
||||
/// Point verification and multiplication in Jacobian coordinates.
|
||||
PointVerifJacobianMulti = 7,
|
||||
#[cfg(esp32h2)]
|
||||
/// Modular addition mode.
|
||||
ModAdd = 8,
|
||||
#[cfg(esp32h2)]
|
||||
/// Modular subtraction mode.
|
||||
ModSub = 9,
|
||||
#[cfg(esp32h2)]
|
||||
/// Modular multiplication mode.
|
||||
ModMulti = 10,
|
||||
#[cfg(esp32h2)]
|
||||
/// Modular division mode.
|
||||
ModDiv = 11,
|
||||
}
|
||||
|
||||
@ -111,6 +126,7 @@ impl<'d> InterruptConfigurable for Ecc<'d, crate::Blocking> {
|
||||
}
|
||||
|
||||
impl<'d, DM: crate::Mode> Ecc<'d, DM> {
|
||||
/// Resets the ECC peripheral.
|
||||
pub fn reset(&mut self) {
|
||||
self.ecc.mult_conf().reset()
|
||||
}
|
||||
|
@ -61,8 +61,6 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use crate::{
|
||||
peripheral::{Peripheral, PeripheralRef},
|
||||
system::PeripheralClockControl,
|
||||
@ -144,10 +142,14 @@ macro_rules! create_etm {
|
||||
/// Provides access to all the [EtmChannel]
|
||||
pub struct Etm<'d> {
|
||||
_peripheral: PeripheralRef<'d, crate::peripherals::SOC_ETM>,
|
||||
$(pub [< channel $num >]: EtmChannel<$num>,)+
|
||||
$(
|
||||
/// An individual ETM channel, identified by its index number.
|
||||
pub [< channel $num >]: EtmChannel<$num>,
|
||||
)+
|
||||
}
|
||||
|
||||
impl<'d> Etm<'d> {
|
||||
/// Creates a new `Etm` instance.
|
||||
pub fn new(peripheral: impl Peripheral<P = crate::peripherals::SOC_ETM> + 'd) -> Self {
|
||||
crate::into_ref!(peripheral);
|
||||
|
||||
|
@ -60,24 +60,39 @@ use crate::{
|
||||
|
||||
/// All the GPIO ETM channels
|
||||
#[non_exhaustive]
|
||||
#[allow(missing_docs)]
|
||||
pub struct GpioEtmChannels<'d> {
|
||||
_gpio_sd: PeripheralRef<'d, crate::peripherals::GPIO_SD>,
|
||||
/// Task channel 0 for triggering GPIO tasks.
|
||||
pub channel0_task: GpioEtmTaskChannel<0>,
|
||||
/// Event channel 0 for handling GPIO events.
|
||||
pub channel0_event: GpioEtmEventChannel<0>,
|
||||
/// Task channel 1 for triggering GPIO tasks.
|
||||
pub channel1_task: GpioEtmTaskChannel<1>,
|
||||
/// Event channel 1 for handling GPIO events.
|
||||
pub channel1_event: GpioEtmEventChannel<1>,
|
||||
/// Task channel 2 for triggering GPIO tasks.
|
||||
pub channel2_task: GpioEtmTaskChannel<2>,
|
||||
/// Event channel 2 for handling GPIO events.
|
||||
pub channel2_event: GpioEtmEventChannel<2>,
|
||||
/// Task channel 3 for triggering GPIO tasks.
|
||||
pub channel3_task: GpioEtmTaskChannel<3>,
|
||||
/// Event channel 3 for handling GPIO events.
|
||||
pub channel3_event: GpioEtmEventChannel<3>,
|
||||
/// Task channel 4 for triggering GPIO tasks.
|
||||
pub channel4_task: GpioEtmTaskChannel<4>,
|
||||
/// Event channel 4 for handling GPIO events.
|
||||
pub channel4_event: GpioEtmEventChannel<4>,
|
||||
/// Task channel 5 for triggering GPIO tasks.
|
||||
pub channel5_task: GpioEtmTaskChannel<5>,
|
||||
/// Event channel 5 for handling GPIO events.
|
||||
pub channel5_event: GpioEtmEventChannel<5>,
|
||||
/// Task channel 6 for triggering GPIO tasks.
|
||||
pub channel6_task: GpioEtmTaskChannel<6>,
|
||||
/// Event channel 6 for handling GPIO events.
|
||||
pub channel6_event: GpioEtmEventChannel<6>,
|
||||
/// Task channel 7 for triggering GPIO tasks.
|
||||
pub channel7_task: GpioEtmTaskChannel<7>,
|
||||
/// Event channel 7 for handling GPIO events.
|
||||
pub channel7_event: GpioEtmEventChannel<7>,
|
||||
}
|
||||
|
||||
|
@ -170,31 +170,46 @@ pub struct RtcOutput;
|
||||
pub struct Analog;
|
||||
|
||||
/// Drive strength (values are approximates)
|
||||
#[allow(missing_docs)]
|
||||
pub enum DriveStrength {
|
||||
/// Drive strength of approximately 5mA.
|
||||
I5mA = 0,
|
||||
/// Drive strength of approximately 10mA.
|
||||
I10mA = 1,
|
||||
/// Drive strength of approximately 20mA.
|
||||
I20mA = 2,
|
||||
/// Drive strength of approximately 40mA.
|
||||
I40mA = 3,
|
||||
}
|
||||
|
||||
/// Alternate functions
|
||||
///
|
||||
/// GPIO pins can be configured for various functions, such as GPIO
|
||||
/// or being directly connected to a peripheral's signal like UART, SPI, etc.
|
||||
/// The `AlternateFunction` enum allows to select one of several functions that
|
||||
/// a pin can perform, rather than using it as a general-purpose input or
|
||||
/// output.
|
||||
#[derive(PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum AlternateFunction {
|
||||
/// Alternate function 0.
|
||||
Function0 = 0,
|
||||
/// Alternate function 1.
|
||||
Function1 = 1,
|
||||
/// Alternate function 2.
|
||||
Function2 = 2,
|
||||
/// Alternate function 3.
|
||||
Function3 = 3,
|
||||
/// Alternate function 4.
|
||||
Function4 = 4,
|
||||
/// Alternate function 5.
|
||||
Function5 = 5,
|
||||
}
|
||||
|
||||
/// RTC function
|
||||
#[derive(PartialEq)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum RtcFunction {
|
||||
/// RTC mode.
|
||||
Rtc = 0,
|
||||
/// Digital mode.
|
||||
Digital = 1,
|
||||
}
|
||||
|
||||
@ -1390,9 +1405,9 @@ macro_rules! gpio {
|
||||
)+
|
||||
|
||||
/// Pins available on this chip
|
||||
#[allow(missing_docs)]
|
||||
pub struct Pins {
|
||||
$(
|
||||
/// GPIO pin number `$gpionum`.
|
||||
pub [< gpio $gpionum >] : GpioPin<$gpionum>,
|
||||
)+
|
||||
}
|
||||
|
@ -34,8 +34,6 @@
|
||||
//!
|
||||
//! [HMAC]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/hmac.rs
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::convert::Infallible;
|
||||
|
||||
use crate::{
|
||||
@ -45,6 +43,9 @@ use crate::{
|
||||
system::{Peripheral as PeripheralEnable, PeripheralClockControl},
|
||||
};
|
||||
|
||||
/// Provides an interface for interacting with the HMAC hardware peripheral.
|
||||
/// It allows users to compute HMACs for cryptographic purposes, ensuring data
|
||||
/// integrity and authenticity.
|
||||
pub struct Hmac<'d> {
|
||||
hmac: PeripheralRef<'d, HMAC>,
|
||||
alignment_helper: AlignmentHelper<SocDependentEndianess>,
|
||||
@ -79,12 +80,19 @@ pub enum HmacPurpose {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Represents the key identifiers for the HMAC peripheral.
|
||||
pub enum KeyId {
|
||||
/// Key 0.
|
||||
Key0 = 0,
|
||||
/// Key 1.
|
||||
Key1 = 1,
|
||||
/// Key 2.
|
||||
Key2 = 2,
|
||||
/// Key 3.
|
||||
Key3 = 3,
|
||||
/// Key 4.
|
||||
Key4 = 4,
|
||||
/// Key 5.
|
||||
Key5 = 5,
|
||||
}
|
||||
|
||||
@ -95,6 +103,7 @@ enum NextCommand {
|
||||
}
|
||||
|
||||
impl<'d> Hmac<'d> {
|
||||
/// Creates a new instance of the HMAC peripheral.
|
||||
pub fn new(hmac: impl Peripheral<P = HMAC> + 'd) -> Self {
|
||||
crate::into_ref!(hmac);
|
||||
|
||||
@ -155,6 +164,7 @@ impl<'d> Hmac<'d> {
|
||||
Ok(remaining)
|
||||
}
|
||||
|
||||
/// Finalizes the HMAC computation and retrieves the resulting hash output.
|
||||
pub fn finalize(&mut self, output: &mut [u8]) -> nb::Result<(), Infallible> {
|
||||
if self.is_busy() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
|
@ -69,8 +69,6 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use fugit::HertzU32;
|
||||
@ -100,11 +98,17 @@ const MAX_ITERATIONS: u32 = 1_000_000;
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// The transmission exceeded the FIFO size.
|
||||
ExceedingFifo,
|
||||
/// The acknowledgment check failed.
|
||||
AckCheckFailed,
|
||||
/// A timeout occurred during transmission.
|
||||
TimeOut,
|
||||
/// The arbitration for the bus was lost.
|
||||
ArbitrationLost,
|
||||
/// The execution of the I2C command was incomplete.
|
||||
ExecIncomplete,
|
||||
/// The number of commands issued exceeded the limit.
|
||||
CommandNrExceeded,
|
||||
}
|
||||
|
||||
@ -1010,19 +1014,29 @@ mod asynch {
|
||||
|
||||
/// I2C Peripheral Instance
|
||||
pub trait Instance: crate::private::Sealed {
|
||||
/// The identifier number for this I2C instance.
|
||||
const I2C_NUMBER: usize;
|
||||
|
||||
/// Returns the interrupt associated with this I2C peripheral.
|
||||
fn interrupt() -> crate::peripherals::Interrupt;
|
||||
|
||||
/// Returns the SCL output signal for this I2C peripheral.
|
||||
fn scl_output_signal(&self) -> OutputSignal;
|
||||
/// Returns the SCL input signal for this I2C peripheral.
|
||||
fn scl_input_signal(&self) -> InputSignal;
|
||||
/// Returns the SDA output signal for this I2C peripheral.
|
||||
fn sda_output_signal(&self) -> OutputSignal;
|
||||
/// Returns the SDA input signal for this I2C peripheral.
|
||||
fn sda_input_signal(&self) -> InputSignal;
|
||||
|
||||
/// Returns a reference to the register block of the I2C peripheral.
|
||||
fn register_block(&self) -> &RegisterBlock;
|
||||
|
||||
/// Returns the I2C peripheral's index number.
|
||||
fn i2c_number(&self) -> usize;
|
||||
|
||||
/// Configures the I2C peripheral with the specified frequency, clocks, and
|
||||
/// optional timeout.
|
||||
fn setup(&mut self, frequency: HertzU32, clocks: &Clocks<'_>, timeout: Option<u32>) {
|
||||
self.register_block().ctr().modify(|_, w| unsafe {
|
||||
// Clear register
|
||||
@ -1339,6 +1353,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments, unused)]
|
||||
/// Configures the clock and timing parameters for the I2C peripheral.
|
||||
fn configure_clock(
|
||||
&mut self,
|
||||
sclk_div: u32,
|
||||
@ -1445,6 +1460,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configures the I2C peripheral for a write operation.
|
||||
fn setup_write<'a, I>(&self, addr: u8, bytes: &[u8], cmd_iterator: &mut I) -> Result<(), Error>
|
||||
where
|
||||
I: Iterator<Item = &'a COMD>,
|
||||
@ -1475,6 +1491,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Configures the I2C peripheral for a read operation.
|
||||
fn setup_read<'a, I>(
|
||||
&self,
|
||||
addr: u8,
|
||||
@ -1528,6 +1545,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
/// Reads all bytes from the RX FIFO.
|
||||
fn read_all_from_fifo(&self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
// Read bytes from FIFO
|
||||
// FIXME: Handle case where less data has been provided by the slave than
|
||||
@ -1549,6 +1567,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
/// Reads all bytes from the RX FIFO.
|
||||
fn read_all_from_fifo(&self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||
// on ESP32/ESP32-S2 we currently don't support I2C transactions larger than the
|
||||
// FIFO apparently it would be possible by using non-fifo mode
|
||||
@ -1573,12 +1592,14 @@ pub trait Instance: crate::private::Sealed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Clears all pending interrupts for the I2C peripheral.
|
||||
fn clear_all_interrupts(&self) {
|
||||
self.register_block()
|
||||
.int_clr()
|
||||
.write(|w| unsafe { w.bits(I2C_LL_INTR_MASK) });
|
||||
}
|
||||
|
||||
/// Waits for the completion of an I2C transaction.
|
||||
fn wait_for_completion(&self, end_only: bool) -> Result<(), Error> {
|
||||
let mut tout = MAX_ITERATIONS;
|
||||
loop {
|
||||
@ -1604,6 +1625,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks whether all I2C commands have completed execution.
|
||||
fn check_all_commands_done(&self) -> Result<(), Error> {
|
||||
// NOTE: on esp32 executing the end command generates the end_detect interrupt
|
||||
// but does not seem to clear the done bit! So we don't check the done
|
||||
@ -1618,6 +1640,14 @@ pub trait Instance: crate::private::Sealed {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Checks for I2C transmission errors and handles them.
|
||||
///
|
||||
/// This function inspects specific I2C-related interrupts to detect errors
|
||||
/// during communication, such as timeouts, failed acknowledgments, or
|
||||
/// arbitration loss. If an error is detected, the function handles it
|
||||
/// by resetting the I2C peripheral to clear the error condition and then
|
||||
/// returns an appropriate error.
|
||||
fn check_errors(&self) -> Result<(), Error> {
|
||||
let interrupts = self.register_block().int_raw().read();
|
||||
|
||||
@ -1658,6 +1688,15 @@ pub trait Instance: crate::private::Sealed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Updates the configuration of the I2C peripheral.
|
||||
///
|
||||
/// This function ensures that the configuration values, such as clock
|
||||
/// settings, SDA/SCL filtering, timeouts, and other operational
|
||||
/// parameters, which are configured in other functions, are properly
|
||||
/// propagated to the I2C hardware. This step is necessary to synchronize
|
||||
/// the software-configured settings with the peripheral's internal
|
||||
/// registers, ensuring that the hardware behaves according to the
|
||||
/// current configuration.
|
||||
fn update_config(&self) {
|
||||
// Ensure that the configuration of the peripheral is correctly propagated
|
||||
// (only necessary for C2, C3, C6, H2 and S3 variant)
|
||||
@ -1667,6 +1706,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
.modify(|_, w| w.conf_upgate().set_bit());
|
||||
}
|
||||
|
||||
/// Starts an I2C transmission.
|
||||
fn start_transmission(&self) {
|
||||
// Start transmission
|
||||
self.register_block()
|
||||
@ -1675,6 +1715,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
/// Fills the TX FIFO with data from the provided slice.
|
||||
fn fill_tx_fifo(&self, bytes: &[u8]) -> usize {
|
||||
let mut index = 0;
|
||||
while index < bytes.len()
|
||||
@ -1704,6 +1745,8 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
/// Writes remaining data from byte slice to the TX FIFO from the specified
|
||||
/// index.
|
||||
fn write_remaining_tx_fifo(&self, start_index: usize, bytes: &[u8]) -> Result<(), Error> {
|
||||
let mut index = start_index;
|
||||
loop {
|
||||
@ -1743,6 +1786,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
/// Fills the TX FIFO with data from the provided slice.
|
||||
fn fill_tx_fifo(&self, bytes: &[u8]) -> usize {
|
||||
// on ESP32/ESP32-S2 we currently don't support I2C transactions larger than the
|
||||
// FIFO apparently it would be possible by using non-fifo mode
|
||||
@ -1760,6 +1804,8 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
/// Writes remaining data from byte slice to the TX FIFO from the specified
|
||||
/// index.
|
||||
fn write_remaining_tx_fifo(&self, start_index: usize, bytes: &[u8]) -> Result<(), Error> {
|
||||
// on ESP32/ESP32-S2 we currently don't support I2C transactions larger than the
|
||||
// FIFO apparently it would be possible by using non-fifo mode
|
||||
@ -1838,6 +1884,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
.write(|w| w.rxfifo_full().clear_bit_by_one());
|
||||
}
|
||||
|
||||
/// Executes an I2C write operation.
|
||||
fn write_operation<'a, I>(
|
||||
&self,
|
||||
address: u8,
|
||||
@ -1870,6 +1917,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Executes an I2C read operation.
|
||||
fn read_operation<'a, I>(
|
||||
&self,
|
||||
address: u8,
|
||||
@ -1964,6 +2012,7 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds a command to the I2C command sequence.
|
||||
fn add_cmd<'a, I>(cmd_iterator: &mut I, command: Command) -> Result<(), Error>
|
||||
where
|
||||
I: Iterator<Item = &'a COMD>,
|
||||
@ -2139,12 +2188,19 @@ pub mod lp_i2c {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// The transmission exceeded the FIFO size.
|
||||
ExceedingFifo,
|
||||
/// The acknowledgment check failed.
|
||||
AckCheckFailed,
|
||||
/// A timeout occurred during transmission.
|
||||
TimeOut,
|
||||
/// The arbitration for the bus was lost.
|
||||
ArbitrationLost,
|
||||
/// The execution of the I2C command was incomplete.
|
||||
ExecIncomplete,
|
||||
/// The number of commands issued exceeded the limit.
|
||||
CommandNrExceeded,
|
||||
/// The response received from the I2C device was invalid.
|
||||
InvalidResponse,
|
||||
}
|
||||
|
||||
@ -2197,11 +2253,13 @@ pub mod lp_i2c {
|
||||
// Configure LP_EXT_I2C_CK_EN high to enable the clock source of I2C_SCLK.
|
||||
// Adjust the timing registers accordingly when the clock frequency changes.
|
||||
|
||||
/// Represents a Low-Power I2C peripheral.
|
||||
pub struct LpI2c {
|
||||
i2c: LP_I2C0,
|
||||
}
|
||||
|
||||
impl LpI2c {
|
||||
/// Creates a new instance of the `LpI2c` peripheral.
|
||||
pub fn new(
|
||||
i2c: LP_I2C0,
|
||||
_sda: LowPowerOutputOpenDrain<'_, 6>,
|
||||
@ -2444,6 +2502,7 @@ pub mod lp_i2c {
|
||||
self.i2c.ctr().modify(|_, w| w.conf_upgate().set_bit());
|
||||
}
|
||||
|
||||
/// Resets the transmit and receive FIFO buffers.
|
||||
fn reset_fifo(&self) {
|
||||
self.i2c
|
||||
.fifo_conf()
|
||||
|
@ -80,8 +80,6 @@
|
||||
//! - Only master mode is supported.
|
||||
//! - Only TDM Philips standard is supported.
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use enumset::{EnumSet, EnumSetType};
|
||||
@ -121,12 +119,17 @@ use crate::{
|
||||
};
|
||||
|
||||
#[derive(EnumSetType)]
|
||||
/// Represents the various interrupt types for the I2S peripheral.
|
||||
pub enum I2sInterrupt {
|
||||
/// Transmit buffer hung, indicating a stall in data transmission.
|
||||
TxHung,
|
||||
/// Receive buffer hung, indicating a stall in data reception.
|
||||
RxHung,
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
/// Transmission of data is complete.
|
||||
TxDone,
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
/// Reception of data is complete.
|
||||
RxDone,
|
||||
}
|
||||
|
||||
@ -150,8 +153,11 @@ impl AcceptedWord for i32 {}
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// An unspecified or unknown error occurred during an I2S operation.
|
||||
Unknown,
|
||||
/// A DMA-related error occurred during I2S operations.
|
||||
DmaError(DmaError),
|
||||
/// An illegal or invalid argument was passed to an I2S function or method.
|
||||
IllegalArgument,
|
||||
}
|
||||
|
||||
@ -165,6 +171,7 @@ impl From<DmaError> for Error {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Standard {
|
||||
/// The Philips I2S standard.
|
||||
Philips,
|
||||
// Tdm,
|
||||
// Pdm,
|
||||
@ -175,12 +182,19 @@ pub enum Standard {
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
pub enum DataFormat {
|
||||
/// 32-bit data width and 32-bit channel width.
|
||||
Data32Channel32,
|
||||
/// 32-bit data width and 24-bit channel width.
|
||||
Data32Channel24,
|
||||
/// 32-bit data width and 16-bit channel width.
|
||||
Data32Channel16,
|
||||
/// 32-bit data width and 8-bit channel width.
|
||||
Data32Channel8,
|
||||
/// 16-bit data width and 16-bit channel width.
|
||||
Data16Channel16,
|
||||
/// 16-bit data width and 8-bit channel width.
|
||||
Data16Channel8,
|
||||
/// 8-bit data width and 8-bit channel width.
|
||||
Data8Channel8,
|
||||
}
|
||||
|
||||
@ -189,12 +203,15 @@ pub enum DataFormat {
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
pub enum DataFormat {
|
||||
/// 32-bit data width and 32-bit channel width.
|
||||
Data32Channel32,
|
||||
/// 16-bit data width and 16-bit channel width.
|
||||
Data16Channel16,
|
||||
}
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
impl DataFormat {
|
||||
/// Returns the number of data bits for the selected data format.
|
||||
pub fn data_bits(&self) -> u8 {
|
||||
match self {
|
||||
DataFormat::Data32Channel32 => 32,
|
||||
@ -207,6 +224,7 @@ impl DataFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of channel bits for the selected data format.
|
||||
pub fn channel_bits(&self) -> u8 {
|
||||
match self {
|
||||
DataFormat::Data32Channel32 => 32,
|
||||
@ -222,6 +240,7 @@ impl DataFormat {
|
||||
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
impl DataFormat {
|
||||
/// Returns the number of data bits for the selected data format.
|
||||
pub fn data_bits(&self) -> u8 {
|
||||
match self {
|
||||
DataFormat::Data32Channel32 => 32,
|
||||
@ -229,6 +248,7 @@ impl DataFormat {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of channel bits for the selected data format.
|
||||
pub fn channel_bits(&self) -> u8 {
|
||||
match self {
|
||||
DataFormat::Data32Channel32 => 32,
|
||||
@ -239,6 +259,7 @@ impl DataFormat {
|
||||
|
||||
/// Blocking I2s Write
|
||||
pub trait I2sWrite<W> {
|
||||
/// Writes a slice of data to the I2S peripheral.
|
||||
fn write(&mut self, words: &[W]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
@ -269,6 +290,8 @@ where
|
||||
|
||||
/// Blocking I2S Read
|
||||
pub trait I2sRead<W> {
|
||||
/// Reads a slice of data from the I2S peripheral and stores it in the
|
||||
/// provided buffer.
|
||||
fn read(&mut self, words: &mut [W]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
@ -305,7 +328,9 @@ where
|
||||
CH: DmaChannel,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Handles the transmission (TX) side of the I2S peripheral.
|
||||
pub i2s_tx: TxCreator<'d, I, CH, DmaMode>,
|
||||
/// Handles the reception (RX) side of the I2S peripheral.
|
||||
pub i2s_rx: RxCreator<'d, I, CH, DmaMode>,
|
||||
phantom: PhantomData<DmaMode>,
|
||||
}
|
||||
@ -481,6 +506,7 @@ where
|
||||
)
|
||||
}
|
||||
|
||||
/// Configures the I2S peripheral to use a master clock (MCLK) output pin.
|
||||
pub fn with_mclk<P: OutputPin>(self, pin: impl Peripheral<P = P> + 'd) -> Self {
|
||||
into_ref!(pin);
|
||||
pin.set_to_push_pull_output(crate::private::Internal);
|
||||
@ -850,6 +876,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Provides an abstraction for accessing the I2S peripheral registers.
|
||||
pub trait RegisterAccess: RegisterAccessPrivate {}
|
||||
|
||||
mod private {
|
||||
@ -2153,6 +2180,7 @@ mod private {
|
||||
}
|
||||
}
|
||||
|
||||
/// Async functionality
|
||||
#[cfg(feature = "async")]
|
||||
pub mod asynch {
|
||||
use super::{Error, I2sRx, I2sTx, RegisterAccess};
|
||||
|
@ -53,38 +53,68 @@ pub enum InterruptKind {
|
||||
#[repr(u32)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[allow(missing_docs)]
|
||||
pub enum CpuInterrupt {
|
||||
/// Interrupt number 1.
|
||||
Interrupt1 = 1,
|
||||
/// Interrupt number 2.
|
||||
Interrupt2,
|
||||
/// Interrupt number 3.
|
||||
Interrupt3,
|
||||
/// Interrupt number 4.
|
||||
Interrupt4,
|
||||
/// Interrupt number 5.
|
||||
Interrupt5,
|
||||
/// Interrupt number 6.
|
||||
Interrupt6,
|
||||
/// Interrupt number 7.
|
||||
Interrupt7,
|
||||
/// Interrupt number 8.
|
||||
Interrupt8,
|
||||
/// Interrupt number 9.
|
||||
Interrupt9,
|
||||
/// Interrupt number 10.
|
||||
Interrupt10,
|
||||
/// Interrupt number 11.
|
||||
Interrupt11,
|
||||
/// Interrupt number 12.
|
||||
Interrupt12,
|
||||
/// Interrupt number 13.
|
||||
Interrupt13,
|
||||
/// Interrupt number 14.
|
||||
Interrupt14,
|
||||
/// Interrupt number 15.
|
||||
Interrupt15,
|
||||
/// Interrupt number 16.
|
||||
Interrupt16,
|
||||
/// Interrupt number 17.
|
||||
Interrupt17,
|
||||
/// Interrupt number 18.
|
||||
Interrupt18,
|
||||
/// Interrupt number 19.
|
||||
Interrupt19,
|
||||
/// Interrupt number 20.
|
||||
Interrupt20,
|
||||
/// Interrupt number 21.
|
||||
Interrupt21,
|
||||
/// Interrupt number 22.
|
||||
Interrupt22,
|
||||
/// Interrupt number 23.
|
||||
Interrupt23,
|
||||
/// Interrupt number 24.
|
||||
Interrupt24,
|
||||
/// Interrupt number 25.
|
||||
Interrupt25,
|
||||
/// Interrupt number 26.
|
||||
Interrupt26,
|
||||
/// Interrupt number 27.
|
||||
Interrupt27,
|
||||
/// Interrupt number 28.
|
||||
Interrupt28,
|
||||
/// Interrupt number 29.
|
||||
Interrupt29,
|
||||
/// Interrupt number 30.
|
||||
Interrupt30,
|
||||
/// Interrupt number 31.
|
||||
Interrupt31,
|
||||
}
|
||||
|
||||
@ -92,30 +122,45 @@ pub enum CpuInterrupt {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Priority {
|
||||
/// No priority.
|
||||
None = 0,
|
||||
/// Priority level 1.
|
||||
Priority1,
|
||||
/// Priority level 2.
|
||||
Priority2,
|
||||
/// Priority level 3.
|
||||
Priority3,
|
||||
/// Priority level 4.
|
||||
Priority4,
|
||||
/// Priority level 5.
|
||||
Priority5,
|
||||
/// Priority level 6.
|
||||
Priority6,
|
||||
/// Priority level 7.
|
||||
Priority7,
|
||||
/// Priority level 8.
|
||||
#[cfg(not(clic))]
|
||||
Priority8,
|
||||
/// Priority level 9.
|
||||
#[cfg(not(clic))]
|
||||
Priority9,
|
||||
/// Priority level 10.
|
||||
#[cfg(not(clic))]
|
||||
Priority10,
|
||||
/// Priority level 11.
|
||||
#[cfg(not(clic))]
|
||||
Priority11,
|
||||
/// Priority level 12.
|
||||
#[cfg(not(clic))]
|
||||
Priority12,
|
||||
/// Priority level 13.
|
||||
#[cfg(not(clic))]
|
||||
Priority13,
|
||||
/// Priority level 14.
|
||||
#[cfg(not(clic))]
|
||||
Priority14,
|
||||
/// Priority level 15.
|
||||
#[cfg(not(clic))]
|
||||
Priority15,
|
||||
}
|
||||
|
@ -27,39 +27,70 @@ pub enum Error {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(u32)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum CpuInterrupt {
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt0LevelPriority1 = 0,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt1LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt2LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt3LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt4LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt5LevelPriority1,
|
||||
/// Timer 0 interrupt with priority 1.
|
||||
Interrupt6Timer0Priority1,
|
||||
/// Software-triggered interrupt with priority 1.
|
||||
Interrupt7SoftwarePriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt8LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt9LevelPriority1,
|
||||
/// Edge-triggered interrupt with priority 1.
|
||||
Interrupt10EdgePriority1,
|
||||
/// Profiling-related interrupt with priority 3.
|
||||
Interrupt11ProfilingPriority3,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt12LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt13LevelPriority1,
|
||||
/// Non-maskable interrupt (NMI) with priority 7.
|
||||
Interrupt14NmiPriority7,
|
||||
/// Timer 1 interrupt with priority 3.
|
||||
Interrupt15Timer1Priority3,
|
||||
/// Timer 2 interrupt with priority 5.
|
||||
Interrupt16Timer2Priority5,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt17LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 1.
|
||||
Interrupt18LevelPriority1,
|
||||
/// Level-triggered interrupt with priority 2.
|
||||
Interrupt19LevelPriority2,
|
||||
/// Level-triggered interrupt with priority 2.
|
||||
Interrupt20LevelPriority2,
|
||||
/// Level-triggered interrupt with priority 2.
|
||||
Interrupt21LevelPriority2,
|
||||
/// Edge-triggered interrupt with priority 3.
|
||||
Interrupt22EdgePriority3,
|
||||
/// Level-triggered interrupt with priority 3.
|
||||
Interrupt23LevelPriority3,
|
||||
/// Level-triggered interrupt with priority 4.
|
||||
Interrupt24LevelPriority4,
|
||||
/// Level-triggered interrupt with priority 4.
|
||||
Interrupt25LevelPriority4,
|
||||
/// Level-triggered interrupt with priority 5.
|
||||
Interrupt26LevelPriority5,
|
||||
/// Level-triggered interrupt with priority 3.
|
||||
Interrupt27LevelPriority3,
|
||||
/// Edge-triggered interrupt with priority 4.
|
||||
Interrupt28EdgePriority4,
|
||||
/// Software-triggered interrupt with priority 3.
|
||||
Interrupt29SoftwarePriority3,
|
||||
/// Edge-triggered interrupt with priority 4.
|
||||
Interrupt30EdgePriority4,
|
||||
/// Edge-triggered interrupt with priority 5.
|
||||
Interrupt31EdgePriority5,
|
||||
}
|
||||
|
||||
@ -267,11 +298,14 @@ mod vectored {
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum Priority {
|
||||
/// No priority.
|
||||
None = 0,
|
||||
/// Priority level 1.
|
||||
Priority1,
|
||||
/// Priority level 2.
|
||||
Priority2,
|
||||
/// Priority level 3.
|
||||
Priority3,
|
||||
}
|
||||
|
||||
|
@ -102,20 +102,31 @@ pub enum EofMode {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum VsyncFilterThreshold {
|
||||
/// Requires 1 valid VSYNC pulse to trigger synchronization.
|
||||
One,
|
||||
/// Requires 2 valid VSYNC pulse to trigger synchronization.
|
||||
Two,
|
||||
/// Requires 3 valid VSYNC pulse to trigger synchronization.
|
||||
Three,
|
||||
/// Requires 4 valid VSYNC pulse to trigger synchronization.
|
||||
Four,
|
||||
/// Requires 5 valid VSYNC pulse to trigger synchronization.
|
||||
Five,
|
||||
/// Requires 6 valid VSYNC pulse to trigger synchronization.
|
||||
Six,
|
||||
/// Requires 7 valid VSYNC pulse to trigger synchronization.
|
||||
Seven,
|
||||
/// Requires 8 valid VSYNC pulse to trigger synchronization.
|
||||
Eight,
|
||||
}
|
||||
|
||||
/// Represents the camera interface.
|
||||
pub struct Cam<'d> {
|
||||
/// The LCD_CAM peripheral reference for managing the camera functionality.
|
||||
pub(crate) lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||
}
|
||||
|
||||
/// Represents the camera interface with DMA support.
|
||||
pub struct Camera<'d, CH: DmaChannel> {
|
||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||
rx_channel: ChannelRx<'d, CH>,
|
||||
@ -128,6 +139,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH>
|
||||
where
|
||||
CH::P: LcdCamPeripheral,
|
||||
{
|
||||
/// Creates a new `Camera` instance with DMA support.
|
||||
pub fn new<P: RxPins>(
|
||||
cam: Cam<'d>,
|
||||
mut channel: ChannelRx<'d, CH>,
|
||||
@ -244,6 +256,7 @@ impl<'d, CH: DmaChannel> DmaSupportRx for Camera<'d, CH> {
|
||||
}
|
||||
|
||||
impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
/// Configures the byte order for the camera data.
|
||||
pub fn set_byte_order(&mut self, byte_order: ByteOrder) -> &mut Self {
|
||||
self.lcd_cam
|
||||
.cam_ctrl()
|
||||
@ -251,6 +264,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the bit order for the camera data.
|
||||
pub fn set_bit_order(&mut self, bit_order: BitOrder) -> &mut Self {
|
||||
self.lcd_cam
|
||||
.cam_ctrl()
|
||||
@ -258,6 +272,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the VSYNC filter threshold.
|
||||
pub fn set_vsync_filter(&mut self, threshold: Option<VsyncFilterThreshold>) -> &mut Self {
|
||||
if let Some(threshold) = threshold {
|
||||
let value = match threshold {
|
||||
@ -285,6 +300,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the master clock (MCLK) pin for the camera interface.
|
||||
pub fn with_master_clock<MCLK: OutputPin>(self, mclk: impl Peripheral<P = MCLK> + 'd) -> Self {
|
||||
crate::into_ref!(mclk);
|
||||
mclk.set_to_push_pull_output(crate::private::Internal);
|
||||
@ -292,6 +308,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the pixel clock (PCLK) pin for the camera interface.
|
||||
pub fn with_pixel_clock<PCLK: InputPin>(self, pclk: impl Peripheral<P = PCLK> + 'd) -> Self {
|
||||
crate::into_ref!(pclk);
|
||||
|
||||
@ -301,6 +318,8 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the control pins for the camera interface (VSYNC and
|
||||
/// HENABLE).
|
||||
pub fn with_ctrl_pins<VSYNC: InputPin, HENABLE: InputPin>(
|
||||
self,
|
||||
vsync: impl Peripheral<P = VSYNC> + 'd,
|
||||
@ -321,6 +340,8 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the control pins for the camera interface (VSYNC, HSYNC, and
|
||||
/// HENABLE) with DE (data enable).
|
||||
pub fn with_ctrl_pins_and_de<VSYNC: InputPin, HSYNC: InputPin, HENABLE: InputPin>(
|
||||
self,
|
||||
vsync: impl Peripheral<P = VSYNC> + 'd,
|
||||
@ -388,6 +409,7 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
self.rx_channel.start_transfer()
|
||||
}
|
||||
|
||||
/// Starts a DMA transfer to receive data from the camera peripheral.
|
||||
pub fn read_dma<'t, RXBUF: WriteBuffer>(
|
||||
&'t mut self,
|
||||
buf: &'t mut RXBUF,
|
||||
@ -400,6 +422,8 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
Ok(DmaTransferRx::new(self))
|
||||
}
|
||||
|
||||
/// Starts a circular DMA transfer to receive data from the camera
|
||||
/// peripheral.
|
||||
pub fn read_dma_circular<'t, RXBUF: WriteBuffer>(
|
||||
&'t mut self,
|
||||
buf: &'t mut RXBUF,
|
||||
@ -413,12 +437,16 @@ impl<'d, CH: DmaChannel> Camera<'d, CH> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents an 8-bit wide camera data bus.
|
||||
/// Is used to configure the camera interface to receive 8-bit data.
|
||||
pub struct RxEightBits {
|
||||
_pins: (),
|
||||
}
|
||||
|
||||
impl RxEightBits {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
/// Creates a new instance of `RxEightBits`, configuring the specified pins
|
||||
/// as the 8-bit data bus.
|
||||
pub fn new<'d, P0, P1, P2, P3, P4, P5, P6, P7>(
|
||||
pin_0: impl Peripheral<P = P0> + 'd,
|
||||
pin_1: impl Peripheral<P = P1> + 'd,
|
||||
@ -473,12 +501,16 @@ impl RxPins for RxEightBits {
|
||||
const BUS_WIDTH: usize = 1;
|
||||
}
|
||||
|
||||
/// Represents a 16-bit wide camera data bus.
|
||||
/// Is used to configure the camera interface to receive 16-bit data.
|
||||
pub struct RxSixteenBits {
|
||||
_pins: (),
|
||||
}
|
||||
|
||||
impl RxSixteenBits {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
/// Creates a new instance of `RxSixteenBits`, configuring the specified
|
||||
/// pins as the 16-bit data bus.
|
||||
pub fn new<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15>(
|
||||
pin_0: impl Peripheral<P = P0> + 'd,
|
||||
pin_1: impl Peripheral<P = P1> + 'd,
|
||||
|
@ -91,6 +91,7 @@ use crate::{
|
||||
Mode,
|
||||
};
|
||||
|
||||
/// Represents the I8080 LCD interface.
|
||||
pub struct I8080<'d, CH: DmaChannel, P, DM: Mode> {
|
||||
lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||
tx_channel: ChannelTx<'d, CH>,
|
||||
@ -104,6 +105,7 @@ where
|
||||
CH::P: LcdCamPeripheral,
|
||||
P::Word: Into<u16>,
|
||||
{
|
||||
/// Creates a new instance of the I8080 LCD interface.
|
||||
pub fn new(
|
||||
lcd: Lcd<'d, DM>,
|
||||
mut channel: ChannelTx<'d, CH>,
|
||||
@ -287,6 +289,7 @@ impl<'d, CH: DmaChannel, P: TxPins, DM: Mode> I8080<'d, CH, P, DM>
|
||||
where
|
||||
P::Word: Into<u16>,
|
||||
{
|
||||
/// Configures the byte order for data transmission.
|
||||
pub fn set_byte_order(&mut self, byte_order: ByteOrder) -> &mut Self {
|
||||
let is_inverted = byte_order != ByteOrder::default();
|
||||
self.lcd_cam.lcd_user().modify(|_, w| {
|
||||
@ -299,6 +302,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the bit order for data transmission.
|
||||
pub fn set_bit_order(&mut self, bit_order: BitOrder) -> &mut Self {
|
||||
self.lcd_cam
|
||||
.lcd_user()
|
||||
@ -306,6 +310,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Associates a CS pin with the I8080 interface.
|
||||
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
||||
crate::into_ref!(cs);
|
||||
cs.set_to_push_pull_output(crate::private::Internal);
|
||||
@ -314,6 +319,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the control pins for the I8080 interface.
|
||||
pub fn with_ctrl_pins<DC: OutputPin, WRX: OutputPin>(
|
||||
self,
|
||||
dc: impl Peripheral<P = DC> + 'd,
|
||||
@ -331,6 +337,7 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Sends a command and data to the LCD using the I8080 interface.
|
||||
pub fn send(
|
||||
&mut self,
|
||||
cmd: impl Into<Command<P::Word>>,
|
||||
@ -350,6 +357,7 @@ where
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sends a command and data to the LCD using DMA.
|
||||
pub fn send_dma<'t, TXBUF>(
|
||||
&'t mut self,
|
||||
cmd: impl Into<Command<P::Word>>,
|
||||
@ -374,6 +382,7 @@ impl<'d, CH: DmaChannel, P: TxPins> I8080<'d, CH, P, crate::Async>
|
||||
where
|
||||
P::Word: Into<u16>,
|
||||
{
|
||||
/// Asynchronously sends a command and data to the LCD using DMA.
|
||||
pub async fn send_dma_async<'t, TXBUF>(
|
||||
&'t mut self,
|
||||
cmd: impl Into<Command<P::Word>>,
|
||||
@ -517,7 +526,9 @@ impl<'d, CH: DmaChannel, P, DM: Mode> core::fmt::Debug for I8080<'d, CH, P, DM>
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Configuration settings for the I8080 interface.
|
||||
pub struct Config {
|
||||
/// Specifies the clock mode, including polarity and phase settings.
|
||||
pub clock_mode: ClockMode,
|
||||
|
||||
/// Setup cycles expected, must be at least 1. (6 bits)
|
||||
@ -563,8 +574,11 @@ impl Default for Config {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Command<T> {
|
||||
/// Suppresses the command phase. No command is sent.
|
||||
None,
|
||||
/// Sends a single-word command.
|
||||
One(T),
|
||||
/// Sends a two-word command.
|
||||
Two(T, T),
|
||||
}
|
||||
|
||||
@ -574,6 +588,8 @@ impl<T> From<T> for Command<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a group of 8 output pins configured for 8-bit parallel data
|
||||
/// transmission.
|
||||
pub struct TxEightBits<'d, P0, P1, P2, P3, P4, P5, P6, P7> {
|
||||
pin_0: PeripheralRef<'d, P0>,
|
||||
pin_1: PeripheralRef<'d, P1>,
|
||||
@ -597,6 +613,7 @@ where
|
||||
P7: OutputPin,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
/// Creates a new `TxEightBits` instance with the provided output pins.
|
||||
pub fn new(
|
||||
pin_0: impl Peripheral<P = P0> + 'd,
|
||||
pin_1: impl Peripheral<P = P1> + 'd,
|
||||
@ -670,6 +687,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a group of 16 output pins configured for 16-bit parallel data
|
||||
/// transmission.
|
||||
pub struct TxSixteenBits<'d, P0, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10, P11, P12, P13, P14, P15> {
|
||||
pin_0: PeripheralRef<'d, P0>,
|
||||
pin_1: PeripheralRef<'d, P1>,
|
||||
@ -710,6 +729,7 @@ where
|
||||
P15: OutputPin,
|
||||
{
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
/// Creates a new `TxSixteenBits` instance with the provided output pins.
|
||||
pub fn new(
|
||||
pin_0: impl Peripheral<P = P0> + 'd,
|
||||
pin_1: impl Peripheral<P = P1> + 'd,
|
||||
|
@ -14,36 +14,53 @@ use crate::{peripheral::PeripheralRef, peripherals::LCD_CAM};
|
||||
|
||||
pub mod i8080;
|
||||
|
||||
/// Represents an LCD interface.
|
||||
pub struct Lcd<'d, DM: crate::Mode> {
|
||||
/// The `LCD_CAM` peripheral reference for managing the LCD functionality.
|
||||
pub(crate) lcd_cam: PeripheralRef<'d, LCD_CAM>,
|
||||
|
||||
/// A marker for the mode of operation (blocking or asynchronous).
|
||||
pub(crate) _mode: core::marker::PhantomData<DM>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Represents the clock mode configuration for the LCD interface.
|
||||
pub struct ClockMode {
|
||||
/// The polarity of the clock signal (idle high or low).
|
||||
pub polarity: Polarity,
|
||||
|
||||
/// The phase of the clock signal (shift on the rising or falling edge).
|
||||
pub phase: Phase,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Represents the polarity of the clock signal for the LCD interface.
|
||||
pub enum Polarity {
|
||||
/// The clock signal is low when idle.
|
||||
#[default]
|
||||
IdleLow,
|
||||
|
||||
/// The clock signal is high when idle.
|
||||
IdleHigh,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Represents the phase of the clock signal for the LCD interface.
|
||||
pub enum Phase {
|
||||
/// Data is shifted on the low (falling) edge of the clock signal.
|
||||
#[default]
|
||||
ShiftLow,
|
||||
|
||||
/// Data is shifted on the high (rising) edge of the clock signal.
|
||||
ShiftHigh,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Represents the delay mode for the LCD signal output.
|
||||
pub enum DelayMode {
|
||||
/// Output without delay.
|
||||
#[default]
|
||||
|
@ -5,8 +5,6 @@
|
||||
//! used simultaneously. For more information on these modules, please refer to
|
||||
//! the documentation in their respective modules.
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
pub mod cam;
|
||||
pub mod lcd;
|
||||
|
||||
@ -21,12 +19,16 @@ use crate::{
|
||||
InterruptConfigurable,
|
||||
};
|
||||
|
||||
/// Represents a combined LCD and Camera interface.
|
||||
pub struct LcdCam<'d, DM: crate::Mode> {
|
||||
/// The LCD interface.
|
||||
pub lcd: Lcd<'d, DM>,
|
||||
/// The Camera interface.
|
||||
pub cam: Cam<'d>,
|
||||
}
|
||||
|
||||
impl<'d> LcdCam<'d, crate::Blocking> {
|
||||
/// Creates a new `LcdCam` instance.
|
||||
pub fn new(lcd_cam: impl Peripheral<P = LCD_CAM> + 'd) -> Self {
|
||||
crate::into_ref!(lcd_cam);
|
||||
|
||||
@ -63,6 +65,7 @@ impl<'d> InterruptConfigurable for LcdCam<'d, crate::Blocking> {
|
||||
|
||||
#[cfg(feature = "async")]
|
||||
impl<'d> LcdCam<'d, crate::Async> {
|
||||
/// Creates a new `LcdCam` instance for asynchronous operation.
|
||||
pub fn new_async(lcd_cam: impl Peripheral<P = LCD_CAM> + 'd) -> Self {
|
||||
crate::into_ref!(lcd_cam);
|
||||
|
||||
|
@ -48,15 +48,23 @@ pub enum Error {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Number {
|
||||
/// Channel 0
|
||||
Channel0 = 0,
|
||||
/// Channel 1
|
||||
Channel1 = 1,
|
||||
/// Channel 2
|
||||
Channel2 = 2,
|
||||
/// Channel 3
|
||||
Channel3 = 3,
|
||||
/// Channel 4
|
||||
Channel4 = 4,
|
||||
/// Channel 5
|
||||
Channel5 = 5,
|
||||
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
|
||||
/// Channel 6
|
||||
Channel6 = 6,
|
||||
#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32h2)))]
|
||||
/// Channel 7
|
||||
Channel7 = 7,
|
||||
}
|
||||
|
||||
@ -66,16 +74,22 @@ pub mod config {
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
/// Pin configuration for the LEDC channel.
|
||||
pub enum PinConfig {
|
||||
/// Push-pull pin configuration.
|
||||
PushPull,
|
||||
/// Open-drain pin configuration.
|
||||
OpenDrain,
|
||||
}
|
||||
|
||||
/// Channel configuration
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Config<'a, S: TimerSpeed> {
|
||||
/// A reference to the timer associated with this channel.
|
||||
pub timer: &'a dyn TimerIFace<S>,
|
||||
/// The duty cycle percentage (0-100).
|
||||
pub duty_pct: u8,
|
||||
/// The pin configuration (PushPull or OpenDrain).
|
||||
pub pin_config: PinConfig,
|
||||
}
|
||||
}
|
||||
@ -108,6 +122,8 @@ pub trait ChannelHW<O: OutputPin> {
|
||||
/// Configure Channel HW except for the duty which is set via
|
||||
/// [`Self::set_duty_hw`].
|
||||
fn configure_hw(&mut self) -> Result<(), Error>;
|
||||
/// Configure the hardware for the channel with a specific pin
|
||||
/// configuration.
|
||||
fn configure_hw_with_pin_config(&mut self, cfg: config::PinConfig) -> Result<(), Error>;
|
||||
|
||||
/// Set channel duty HW
|
||||
|
@ -60,8 +60,6 @@
|
||||
//! - Source clock selection is not supported
|
||||
//! - Interrupts are not supported
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use self::{
|
||||
channel::Channel,
|
||||
timer::{Timer, TimerSpeed},
|
||||
@ -79,6 +77,7 @@ pub mod timer;
|
||||
/// Global slow clock source
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum LSGlobalClkSource {
|
||||
/// APB clock.
|
||||
APBClk,
|
||||
}
|
||||
|
||||
@ -96,7 +95,9 @@ pub struct HighSpeed {}
|
||||
/// Used to specify LowSpeed Timer/Channel
|
||||
pub struct LowSpeed {}
|
||||
|
||||
/// Trait representing the speed mode of a clock or peripheral.
|
||||
pub trait Speed {
|
||||
/// Boolean constant indicating whether the speed is high-speed.
|
||||
const IS_HS: bool;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ pub enum Error {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum HSClockSource {
|
||||
/// APB clock.
|
||||
APBClk,
|
||||
// TODO RefTick,
|
||||
}
|
||||
@ -41,6 +42,7 @@ pub enum HSClockSource {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum LSClockSource {
|
||||
/// APB clock.
|
||||
APBClk,
|
||||
// TODO SLOWClk
|
||||
}
|
||||
@ -49,9 +51,13 @@ pub enum LSClockSource {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Number {
|
||||
/// Timer 0.
|
||||
Timer0 = 0,
|
||||
/// Timer 1.
|
||||
Timer1 = 1,
|
||||
/// Timer 2.
|
||||
Timer2 = 2,
|
||||
/// Timer 3.
|
||||
Timer3 = 3,
|
||||
}
|
||||
|
||||
@ -63,56 +69,82 @@ pub mod config {
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Duty {
|
||||
/// 1-bit resolution for duty cycle adjustment.
|
||||
Duty1Bit = 1,
|
||||
/// 2-bit resolution for duty cycle adjustment.
|
||||
Duty2Bit,
|
||||
/// 3-bit resolution for duty cycle adjustment.
|
||||
Duty3Bit,
|
||||
/// 4-bit resolution for duty cycle adjustment.
|
||||
Duty4Bit,
|
||||
/// 5-bit resolution for duty cycle adjustment.
|
||||
Duty5Bit,
|
||||
/// 6-bit resolution for duty cycle adjustment.
|
||||
Duty6Bit,
|
||||
/// 7-bit resolution for duty cycle adjustment.
|
||||
Duty7Bit,
|
||||
/// 8-bit resolution for duty cycle adjustment.
|
||||
Duty8Bit,
|
||||
/// 9-bit resolution for duty cycle adjustment.
|
||||
Duty9Bit,
|
||||
/// 10-bit resolution for duty cycle adjustment.
|
||||
Duty10Bit,
|
||||
/// 11-bit resolution for duty cycle adjustment.
|
||||
Duty11Bit,
|
||||
/// 12-bit resolution for duty cycle adjustment.
|
||||
Duty12Bit,
|
||||
/// 13-bit resolution for duty cycle adjustment.
|
||||
Duty13Bit,
|
||||
/// 14-bit resolution for duty cycle adjustment.
|
||||
Duty14Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 15-bit resolution for duty cycle adjustment.
|
||||
Duty15Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 16-bit resolution for duty cycle adjustment.
|
||||
Duty16Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 17-bit resolution for duty cycle adjustment.
|
||||
Duty17Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 18-bit resolution for duty cycle adjustment.
|
||||
Duty18Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 19-bit resolution for duty cycle adjustment.
|
||||
Duty19Bit,
|
||||
#[cfg(esp32)]
|
||||
/// 20-bit resolution for duty cycle adjustment.
|
||||
Duty20Bit,
|
||||
}
|
||||
|
||||
/// Timer configuration
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Config<CS> {
|
||||
/// The duty cycle resolution.
|
||||
pub duty: Duty,
|
||||
/// The clock source for the timer.
|
||||
pub clock_source: CS,
|
||||
/// The frequency of the PWM signal in Hertz.
|
||||
pub frequency: HertzU32,
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait defining the type of timer source
|
||||
pub trait TimerSpeed: Speed {
|
||||
/// The type of clock source used by the timer in this speed mode.
|
||||
type ClockSourceType;
|
||||
}
|
||||
|
||||
/// Timer source type for LowSpeed timers
|
||||
impl TimerSpeed for LowSpeed {
|
||||
/// The clock source type for low-speed timers.
|
||||
type ClockSourceType = LSClockSource;
|
||||
}
|
||||
|
||||
#[cfg(esp32)]
|
||||
/// Timer source type for HighSpeed timers
|
||||
impl TimerSpeed for HighSpeed {
|
||||
/// The clock source type for high-speed timers.
|
||||
type ClockSourceType = HSClockSource;
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,6 @@
|
||||
//! ## Implementation State
|
||||
//! - Low-speed (LS) is not supported.
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
pub use esp_synopsys_usb_otg::UsbBus;
|
||||
use esp_synopsys_usb_otg::UsbPeripheral;
|
||||
|
||||
@ -49,16 +47,20 @@ use crate::{
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Trait representing the USB D+ (data plus) pin.
|
||||
pub trait UsbDp: crate::private::Sealed {}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Trait representing the USB D- (data minus) pin.
|
||||
pub trait UsbDm: crate::private::Sealed {}
|
||||
|
||||
/// USB peripheral.
|
||||
pub struct Usb<'d> {
|
||||
_usb0: PeripheralRef<'d, peripherals::USB0>,
|
||||
}
|
||||
|
||||
impl<'d> Usb<'d> {
|
||||
/// Creates a new `Usb` instance.
|
||||
pub fn new<P, M>(
|
||||
usb0: impl Peripheral<P = peripherals::USB0> + 'd,
|
||||
_usb_dp: impl Peripheral<P = P> + 'd,
|
||||
@ -129,7 +131,7 @@ unsafe impl<'d> UsbPeripheral for Usb<'d> {
|
||||
80_000_000
|
||||
}
|
||||
}
|
||||
|
||||
/// Async functionality
|
||||
#[cfg(feature = "async")]
|
||||
pub mod asynch {
|
||||
use embassy_usb_driver::{
|
||||
|
@ -1096,14 +1096,17 @@ fn internal_clear_interrupts(interrupts: EnumSet<ParlIoInterrupt>) {
|
||||
/// Parallel IO in full duplex mode
|
||||
///
|
||||
/// Full duplex mode might limit the maximum possible bit width.
|
||||
#[allow(missing_docs)]
|
||||
pub struct ParlIoFullDuplex<'d, CH, DM>
|
||||
where
|
||||
CH: DmaChannel,
|
||||
CH::P: ParlIoPeripheral,
|
||||
DM: Mode,
|
||||
{
|
||||
/// The transmitter (TX) channel responsible for handling DMA transfers in
|
||||
/// the parallel I/O full-duplex operation.
|
||||
pub tx: TxCreatorFullDuplex<'d, CH, DM>,
|
||||
/// The receiver (RX) channel responsible for handling DMA transfers in the
|
||||
/// parallel I/O full-duplex operation.
|
||||
pub rx: RxCreatorFullDuplex<'d, CH, DM>,
|
||||
}
|
||||
|
||||
@ -1191,13 +1194,14 @@ where
|
||||
}
|
||||
|
||||
/// Parallel IO in half duplex / TX only mode
|
||||
#[allow(missing_docs)]
|
||||
pub struct ParlIoTxOnly<'d, CH, DM>
|
||||
where
|
||||
CH: DmaChannel,
|
||||
CH::P: ParlIoPeripheral,
|
||||
DM: Mode,
|
||||
{
|
||||
/// The transmitter (TX) channel responsible for handling DMA transfers in
|
||||
/// the parallel I/O operation.
|
||||
pub tx: TxCreator<'d, CH, DM>,
|
||||
}
|
||||
|
||||
@ -1279,13 +1283,14 @@ where
|
||||
}
|
||||
|
||||
/// Parallel IO in half duplex / RX only mode
|
||||
#[allow(missing_docs)]
|
||||
pub struct ParlIoRxOnly<'d, CH, DM>
|
||||
where
|
||||
CH: DmaChannel,
|
||||
CH::P: ParlIoPeripheral,
|
||||
DM: Mode,
|
||||
{
|
||||
/// The receiver (RX) channel responsible for handling DMA transfers in the
|
||||
/// parallel I/O operation.
|
||||
pub rx: RxCreator<'d, CH, DM>,
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,8 @@ pub struct PcntSource {
|
||||
}
|
||||
|
||||
impl PcntSource {
|
||||
/// Creates a `PcntSource` from an input pin with the specified
|
||||
/// configuration.
|
||||
pub fn from_pin<'a, P: InputPin>(
|
||||
pin: impl Peripheral<P = P> + 'a,
|
||||
pin_config: PcntInputConfig,
|
||||
@ -56,12 +58,16 @@ impl PcntSource {
|
||||
inverted: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PcntSource` that is always high.
|
||||
pub fn always_high() -> Self {
|
||||
Self {
|
||||
source: ONE_INPUT,
|
||||
inverted: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a `PcntSource` that is always low.
|
||||
pub fn always_low() -> Self {
|
||||
Self {
|
||||
source: ZERO_INPUT,
|
||||
@ -69,6 +75,7 @@ impl PcntSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// Inverts the `PcntSource` signal.
|
||||
pub fn invert(self) -> Self {
|
||||
Self {
|
||||
source: self.source,
|
||||
@ -77,6 +84,7 @@ impl PcntSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a channel within a pulse counter unit.
|
||||
pub struct Channel<'d, const UNIT: usize, const NUM: usize> {
|
||||
_phantom: PhantomData<&'d ()>,
|
||||
// Individual channels are not Send, since they share registers.
|
||||
|
@ -20,8 +20,6 @@
|
||||
//! [unit]: unit/index.html
|
||||
//! [PCNT Encoder]: https://github.com/esp-rs/esp-hal/blob/main/examples/src/bin/pcnt_encoder.rs
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use self::unit::Unit;
|
||||
use crate::{
|
||||
interrupt::{self, InterruptHandler},
|
||||
@ -34,6 +32,7 @@ use crate::{
|
||||
pub mod channel;
|
||||
pub mod unit;
|
||||
|
||||
/// Pulse Counter (PCNT) peripheral driver.
|
||||
pub struct Pcnt<'d> {
|
||||
_instance: PeripheralRef<'d, peripherals::PCNT>,
|
||||
|
||||
|
@ -57,21 +57,30 @@ impl From<u8> for ZeroMode {
|
||||
}
|
||||
}
|
||||
|
||||
// Events
|
||||
/// Events that can occur in a pulse counter unit.
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct Events {
|
||||
/// Set when the pulse counter reaches the low limit.
|
||||
pub low_limit: bool,
|
||||
/// Set when the pulse counter reaches the high limit.
|
||||
pub high_limit: bool,
|
||||
/// Set when the pulse counter crosses threshold 0.
|
||||
pub threshold0: bool,
|
||||
/// Set when the pulse counter crosses threshold 1.
|
||||
pub threshold1: bool,
|
||||
/// Set when the pulse counter reaches zero.
|
||||
pub zero: bool,
|
||||
}
|
||||
|
||||
/// Represents a pulse counter unit.
|
||||
#[non_exhaustive]
|
||||
pub struct Unit<'d, const NUM: usize> {
|
||||
/// The counter for PCNT unit.
|
||||
pub counter: Counter<'d, NUM>,
|
||||
/// The first channel in PCNT unit.
|
||||
pub channel0: Channel<'d, NUM, 0>,
|
||||
/// The second channel in PCNT unit.
|
||||
pub channel1: Channel<'d, NUM, 1>,
|
||||
}
|
||||
|
||||
@ -301,6 +310,7 @@ impl<'d, const NUM: usize> Drop for Unit<'d, NUM> {
|
||||
// The entire Unit is Send but the individual channels are not.
|
||||
unsafe impl<'d, const NUM: usize> Send for Unit<'d, NUM> {}
|
||||
|
||||
/// Represents the counter within a pulse counter unit.
|
||||
#[derive(Clone)]
|
||||
pub struct Counter<'d, const NUM: usize> {
|
||||
_phantom: PhantomData<&'d ()>,
|
||||
|
@ -272,10 +272,12 @@ mod peripheral_macros {
|
||||
$crate::impl_dma_eligible!(MEM2MEM15,Mem2Mem15);
|
||||
}
|
||||
|
||||
/// The `Peripherals` struct provides access to all of the hardware peripherals on the chip.
|
||||
#[allow(non_snake_case)]
|
||||
pub struct Peripherals {
|
||||
$(
|
||||
$(#[$cfg])?
|
||||
/// Each field represents a hardware peripheral.
|
||||
pub $name: peripherals::$name,
|
||||
)*
|
||||
}
|
||||
@ -325,6 +327,7 @@ mod peripheral_macros {
|
||||
impl peripherals::$name {
|
||||
$(
|
||||
paste::paste!{
|
||||
/// Binds an interrupt handler to the corresponding interrupt for this peripheral.
|
||||
pub fn [<bind_ $interrupt:lower _interrupt >](&mut self, handler: unsafe extern "C" fn() -> ()) {
|
||||
unsafe { $crate::interrupt::bind_interrupt($crate::peripherals::Interrupt::$interrupt, handler); }
|
||||
}
|
||||
@ -350,11 +353,16 @@ mod peripheral_macros {
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
/// Macro to create a peripheral structure.
|
||||
macro_rules! create_peripheral {
|
||||
($(#[$cfg:meta])? $name:ident <= virtual) => {
|
||||
$(#[$cfg])?
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Represents a virtual peripheral with no associated hardware.
|
||||
///
|
||||
/// This struct is generated by the `create_peripheral!` macro when the peripheral
|
||||
/// is defined as virtual.
|
||||
pub struct $name { _inner: () }
|
||||
|
||||
$(#[$cfg])?
|
||||
@ -385,6 +393,10 @@ mod peripheral_macros {
|
||||
$(#[$cfg])?
|
||||
#[derive(Debug)]
|
||||
#[allow(non_camel_case_types)]
|
||||
/// Represents a concrete hardware peripheral.
|
||||
///
|
||||
/// This struct is generated by the `create_peripheral!` macro when the peripheral
|
||||
/// is tied to an actual hardware device.
|
||||
pub struct $name { _inner: () }
|
||||
|
||||
$(#[$cfg])?
|
||||
|
@ -642,15 +642,18 @@ mod impl_for_chip {
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// RMT Instance
|
||||
#[allow(missing_docs)]
|
||||
pub struct Rmt<'d, M>
|
||||
where
|
||||
M: crate::Mode,
|
||||
{
|
||||
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
|
||||
/// RMT Channel 0.
|
||||
pub channel0: ChannelCreator<M, 0>,
|
||||
/// RMT Channel 1.
|
||||
pub channel1: ChannelCreator<M, 1>,
|
||||
/// RMT Channel 2.
|
||||
pub channel2: ChannelCreator<M, 2>,
|
||||
/// RMT Channel 3.
|
||||
pub channel3: ChannelCreator<M, 3>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
@ -710,19 +713,26 @@ mod impl_for_chip {
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// RMT Instance
|
||||
#[allow(missing_docs)]
|
||||
pub struct Rmt<'d, M>
|
||||
where
|
||||
M: crate::Mode,
|
||||
{
|
||||
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
|
||||
/// RMT Channel 0.
|
||||
pub channel0: ChannelCreator<M, 0>,
|
||||
/// RMT Channel 1.
|
||||
pub channel1: ChannelCreator<M, 1>,
|
||||
/// RMT Channel 2.
|
||||
pub channel2: ChannelCreator<M, 2>,
|
||||
/// RMT Channel 3.
|
||||
pub channel3: ChannelCreator<M, 3>,
|
||||
/// RMT Channel 4.
|
||||
pub channel4: ChannelCreator<M, 4>,
|
||||
/// RMT Channel 5.
|
||||
pub channel5: ChannelCreator<M, 5>,
|
||||
/// RMT Channel 6.
|
||||
pub channel6: ChannelCreator<M, 6>,
|
||||
/// RMT Channel 7.
|
||||
pub channel7: ChannelCreator<M, 7>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
@ -818,15 +828,18 @@ mod impl_for_chip {
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// RMT Instance
|
||||
#[allow(missing_docs)]
|
||||
pub struct Rmt<'d, M>
|
||||
where
|
||||
M: crate::Mode,
|
||||
{
|
||||
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
|
||||
/// RMT Channel 0.
|
||||
pub channel0: ChannelCreator<M, 0>,
|
||||
/// RMT Channel 1.
|
||||
pub channel1: ChannelCreator<M, 1>,
|
||||
/// RMT Channel 2.
|
||||
pub channel2: ChannelCreator<M, 2>,
|
||||
/// RMT Channel 3.
|
||||
pub channel3: ChannelCreator<M, 3>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
@ -894,19 +907,26 @@ mod impl_for_chip {
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// RMT Instance
|
||||
#[allow(missing_docs)]
|
||||
pub struct Rmt<'d, M>
|
||||
where
|
||||
M: crate::Mode,
|
||||
{
|
||||
_peripheral: PeripheralRef<'d, crate::peripherals::RMT>,
|
||||
/// RMT Channel 0.
|
||||
pub channel0: ChannelCreator<M, 0>,
|
||||
/// RMT Channel 1.
|
||||
pub channel1: ChannelCreator<M, 1>,
|
||||
/// RMT Channel 2.
|
||||
pub channel2: ChannelCreator<M, 2>,
|
||||
/// RMT Channel 3.
|
||||
pub channel3: ChannelCreator<M, 3>,
|
||||
/// RMT Channel 4.
|
||||
pub channel4: ChannelCreator<M, 4>,
|
||||
/// RMT Channel 5.
|
||||
pub channel5: ChannelCreator<M, 5>,
|
||||
/// RMT Channel 6.
|
||||
pub channel6: ChannelCreator<M, 6>,
|
||||
/// RMT Channel 7.
|
||||
pub channel7: ChannelCreator<M, 7>,
|
||||
phantom: PhantomData<M>,
|
||||
}
|
||||
|
@ -25,28 +25,35 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes the multi-mode configuration to the RSA hardware.
|
||||
pub(super) fn write_multi_mode(&mut self, mode: u32) {
|
||||
self.rsa.mult_mode().write(|w| unsafe { w.bits(mode) });
|
||||
}
|
||||
|
||||
/// Writes the modular exponentiation mode configuration to the RSA
|
||||
/// hardware.
|
||||
pub(super) fn write_modexp_mode(&mut self, mode: u32) {
|
||||
self.rsa.modexp_mode().write(|w| unsafe { w.bits(mode) });
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation.
|
||||
pub(super) fn write_modexp_start(&mut self) {
|
||||
self.rsa
|
||||
.modexp_start()
|
||||
.write(|w| w.modexp_start().set_bit());
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation.
|
||||
pub(super) fn write_multi_start(&mut self) {
|
||||
self.rsa.mult_start().write(|w| w.mult_start().set_bit());
|
||||
}
|
||||
|
||||
/// Clears the RSA interrupt flag.
|
||||
pub(super) fn clear_interrupt(&mut self) {
|
||||
self.rsa.interrupt().write(|w| w.interrupt().set_bit());
|
||||
}
|
||||
|
||||
/// Checks if the RSA peripheral is idle.
|
||||
pub(super) fn is_idle(&mut self) -> bool {
|
||||
self.rsa.interrupt().read().bits() == 1
|
||||
}
|
||||
@ -62,6 +69,7 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Module defining marker types for various RSA operand sizes.
|
||||
pub mod operand_sizes {
|
||||
//! Marker types for the operand sizes
|
||||
use paste::paste;
|
||||
@ -165,10 +173,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the modular exponentiation mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_modexp_mode((N / 16 - 1) as u32)
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_modexp_start();
|
||||
}
|
||||
@ -196,10 +206,12 @@ where
|
||||
self.set_start();
|
||||
}
|
||||
|
||||
/// Sets the multiplication mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_multi_mode(((N * 2) / 16 + 7) as u32)
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_multi_start();
|
||||
}
|
||||
|
@ -51,10 +51,12 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the search functionality is enabled in the RSA hardware.
|
||||
pub(super) fn is_search_enabled(&mut self) -> bool {
|
||||
self.rsa.search_enable().read().search_enable().bit_is_set()
|
||||
}
|
||||
|
||||
/// Sets the search position in the RSA hardware.
|
||||
pub(super) fn write_search_position(&mut self, search_position: u32) {
|
||||
self.rsa
|
||||
.search_pos()
|
||||
@ -79,28 +81,33 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation.
|
||||
pub(super) fn write_modexp_start(&mut self) {
|
||||
self.rsa
|
||||
.set_start_modexp()
|
||||
.write(|w| w.set_start_modexp().set_bit());
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation.
|
||||
pub(super) fn write_multi_start(&mut self) {
|
||||
self.rsa
|
||||
.set_start_mult()
|
||||
.write(|w| w.set_start_mult().set_bit());
|
||||
}
|
||||
|
||||
/// Starts the modular multiplication operation.
|
||||
fn write_modmulti_start(&mut self) {
|
||||
self.rsa
|
||||
.set_start_modmult()
|
||||
.write(|w| w.set_start_modmult().set_bit());
|
||||
}
|
||||
|
||||
/// Clears the RSA interrupt flag.
|
||||
pub(super) fn clear_interrupt(&mut self) {
|
||||
self.rsa.int_clr().write(|w| w.clear_interrupt().set_bit());
|
||||
}
|
||||
|
||||
/// Checks if the RSA peripheral is idle.
|
||||
pub(super) fn is_idle(&mut self) -> bool {
|
||||
self.rsa.query_idle().read().query_idle().bit_is_set()
|
||||
}
|
||||
@ -110,6 +117,7 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Module defining marker types for various RSA operand sizes.
|
||||
pub mod operand_sizes {
|
||||
//! Marker types for the operand sizes
|
||||
use paste::paste;
|
||||
@ -255,10 +263,12 @@ where
|
||||
0
|
||||
}
|
||||
|
||||
/// Sets the modular exponentiation mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_mode((N - 1) as u32)
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_modexp_start();
|
||||
}
|
||||
@ -335,10 +345,12 @@ where
|
||||
self.set_start();
|
||||
}
|
||||
|
||||
/// Sets the multiplication mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_mode((N * 2 - 1) as u32)
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_multi_start();
|
||||
}
|
||||
|
@ -57,10 +57,12 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the search functionality is enabled in the RSA hardware.
|
||||
pub(super) fn is_search_enabled(&mut self) -> bool {
|
||||
self.rsa.search_enable().read().search_enable().bit_is_set()
|
||||
}
|
||||
|
||||
/// Sets the search position in the RSA hardware.
|
||||
pub(super) fn write_search_position(&mut self, search_position: u32) {
|
||||
self.rsa
|
||||
.search_pos()
|
||||
@ -85,28 +87,33 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation.
|
||||
pub(super) fn write_modexp_start(&mut self) {
|
||||
self.rsa
|
||||
.modexp_start()
|
||||
.write(|w| w.modexp_start().set_bit());
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation.
|
||||
pub(super) fn write_multi_start(&mut self) {
|
||||
self.rsa.mult_start().write(|w| w.mult_start().set_bit());
|
||||
}
|
||||
|
||||
/// Starts the modular multiplication operation.
|
||||
fn write_modmulti_start(&mut self) {
|
||||
self.rsa
|
||||
.modmult_start()
|
||||
.write(|w| w.modmult_start().set_bit());
|
||||
}
|
||||
|
||||
/// Clears the RSA interrupt flag.
|
||||
pub(super) fn clear_interrupt(&mut self) {
|
||||
self.rsa
|
||||
.clear_interrupt()
|
||||
.write(|w| w.clear_interrupt().set_bit());
|
||||
}
|
||||
|
||||
/// Checks if the RSA peripheral is idle.
|
||||
pub(super) fn is_idle(&mut self) -> bool {
|
||||
self.rsa.idle().read().idle().bit_is_set()
|
||||
}
|
||||
@ -296,10 +303,12 @@ where
|
||||
0
|
||||
}
|
||||
|
||||
/// Sets the modular exponentiation mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_mode((N - 1) as u32)
|
||||
}
|
||||
|
||||
/// Starts the modular exponentiation operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_modexp_start();
|
||||
}
|
||||
@ -376,10 +385,12 @@ where
|
||||
self.set_start();
|
||||
}
|
||||
|
||||
/// Sets the multiplication mode for the RSA hardware.
|
||||
pub(super) fn set_mode(rsa: &mut Rsa<'d, DM>) {
|
||||
rsa.write_mode((N * 2 - 1) as u32)
|
||||
}
|
||||
|
||||
/// Starts the multiplication operation on the RSA hardware.
|
||||
pub(super) fn set_start(&mut self) {
|
||||
self.rsa.write_multi_start();
|
||||
}
|
||||
|
@ -34,8 +34,6 @@
|
||||
//! [nb]: https://docs.rs/nb/1.1.0/nb/
|
||||
//! [the repository with corresponding example]: https://github.com/esp-rs/esp-hal/blob/main/hil-test/tests/rsa.rs
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::{marker::PhantomData, ptr::copy_nonoverlapping};
|
||||
|
||||
use crate::{
|
||||
@ -141,38 +139,52 @@ impl<'d, DM: crate::Mode> Rsa<'d, DM> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Defines an RSA operation mode.
|
||||
pub trait RsaMode: crate::private::Sealed {
|
||||
/// The input data type used for the RSA operation.
|
||||
type InputType;
|
||||
}
|
||||
|
||||
/// A trait for RSA operations that involve multiple inputs and outputs.
|
||||
pub trait Multi: RsaMode {
|
||||
/// The type of the output produced by the RSA operation.
|
||||
type OutputType;
|
||||
}
|
||||
|
||||
macro_rules! implement_op {
|
||||
(($x:literal, multi)) => {
|
||||
paste! {pub struct [<Op $x>];}
|
||||
paste! {
|
||||
impl Multi for [<Op $x>] {
|
||||
type OutputType = [u32; $x*2 / 32];
|
||||
}}
|
||||
paste! {
|
||||
impl crate::private::Sealed for [<Op $x>] {}
|
||||
}
|
||||
paste! {
|
||||
impl RsaMode for [<Op $x>] {
|
||||
type InputType = [u32; $x / 32];
|
||||
}}
|
||||
};
|
||||
|
||||
(($x:literal)) => {
|
||||
paste! {pub struct [<Op $x>];}
|
||||
paste! {
|
||||
/// Represents an RSA operation for the given bit size with multi-output.
|
||||
pub struct [<Op $x>];
|
||||
}
|
||||
paste! {
|
||||
impl Multi for [<Op $x>] {
|
||||
type OutputType = [u32; $x * 2 / 32];
|
||||
}
|
||||
}
|
||||
paste! {
|
||||
impl crate::private::Sealed for [<Op $x>] {}
|
||||
}
|
||||
paste!{
|
||||
impl RsaMode for [<Op $x>] {
|
||||
type InputType = [u32; $x / 32];
|
||||
}}
|
||||
paste! {
|
||||
impl RsaMode for [<Op $x>] {
|
||||
type InputType = [u32; $x / 32];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
(($x:literal)) => {
|
||||
paste! {
|
||||
/// Represents an RSA operation for the given bit size.
|
||||
pub struct [<Op $x>];
|
||||
}
|
||||
paste! {
|
||||
impl crate::private::Sealed for [<Op $x>] {}
|
||||
}
|
||||
paste! {
|
||||
impl RsaMode for [<Op $x>] {
|
||||
type InputType = [u32; $x / 32];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
($x:tt, $($y:tt),+) => {
|
||||
@ -286,6 +298,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Async functionality
|
||||
#[cfg(feature = "async")]
|
||||
pub(crate) mod asynch {
|
||||
use core::task::Poll;
|
||||
@ -303,11 +316,13 @@ pub(crate) mod asynch {
|
||||
|
||||
static WAKER: AtomicWaker = AtomicWaker::new();
|
||||
|
||||
/// `Future` that waits for the RSA operation to complete.
|
||||
pub(crate) struct RsaFuture<'d> {
|
||||
instance: &'d crate::peripherals::RSA,
|
||||
}
|
||||
|
||||
impl<'d> RsaFuture<'d> {
|
||||
/// Asynchronously initializes the RSA peripheral.
|
||||
pub async fn new(instance: &'d crate::peripherals::RSA) -> Self {
|
||||
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
|
||||
instance.int_ena().modify(|_, w| w.int_ena().set_bit());
|
||||
@ -360,6 +375,7 @@ pub(crate) mod asynch {
|
||||
where
|
||||
T: RsaMode<InputType = [u32; N]>,
|
||||
{
|
||||
/// Asynchronously performs an RSA modular exponentiation operation.
|
||||
pub async fn exponentiation(
|
||||
&mut self,
|
||||
base: &T::InputType,
|
||||
@ -377,6 +393,7 @@ pub(crate) mod asynch {
|
||||
T: RsaMode<InputType = [u32; N]>,
|
||||
{
|
||||
#[cfg(not(esp32))]
|
||||
/// Asynchronously performs an RSA modular multiplication operation.
|
||||
pub async fn modular_multiplication(
|
||||
&mut self,
|
||||
r: &T::InputType,
|
||||
@ -388,6 +405,7 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(esp32)]
|
||||
/// Asynchronously performs an RSA modular multiplication operation.
|
||||
pub async fn modular_multiplication(
|
||||
&mut self,
|
||||
operand_a: &T::InputType,
|
||||
@ -407,6 +425,7 @@ pub(crate) mod asynch {
|
||||
T: RsaMode<InputType = [u32; N]>,
|
||||
{
|
||||
#[cfg(not(esp32))]
|
||||
/// Asynchronously performs an RSA multiplication operation.
|
||||
pub async fn multiplication<'b, const O: usize>(
|
||||
&mut self,
|
||||
operand_b: &T::InputType,
|
||||
@ -420,6 +439,7 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[cfg(esp32)]
|
||||
/// Asynchronously performs an RSA multiplication operation.
|
||||
pub async fn multiplication<'b, const O: usize>(
|
||||
&mut self,
|
||||
operand_a: &T::InputType,
|
||||
@ -435,6 +455,7 @@ pub(crate) mod asynch {
|
||||
}
|
||||
|
||||
#[handler]
|
||||
/// Interrupt handler for RSA.
|
||||
pub(super) fn rsa_interrupt_handler() {
|
||||
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
|
||||
unsafe { &*crate::peripherals::RSA::ptr() }
|
||||
|
@ -69,8 +69,6 @@
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
#[cfg(not(any(esp32c6, esp32h2)))]
|
||||
use fugit::HertzU32;
|
||||
use fugit::MicrosDurationU64;
|
||||
@ -186,8 +184,10 @@ pub(crate) enum RtcCalSel {
|
||||
/// Low-power Management
|
||||
pub struct Rtc<'d> {
|
||||
_inner: PeripheralRef<'d, crate::peripherals::LPWR>,
|
||||
/// Reset Watchdog Timer.
|
||||
pub rwdt: Rwdt,
|
||||
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
|
||||
/// Super Watchdog
|
||||
pub swd: Swd,
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ pub(crate) fn configure_clock() {
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
/// SOC Reset Reason.
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
ChipPowerOn = 0x01,
|
||||
|
@ -201,6 +201,7 @@ fn rtc_sleep_pu() {
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
/// SOC Reset Reason.
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
ChipPowerOn = 0x01,
|
||||
|
@ -259,6 +259,7 @@ fn rtc_sleep_pu() {
|
||||
// System Reset: Reset the whole digital system, including RTC sub-system
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
/// SOC Reset Reason.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
|
@ -1305,6 +1305,7 @@ fn modem_clk_domain_active_state_icg_map_preinit() {
|
||||
// System Reset: Reset the whole digital system, including RTC sub-system
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
/// SOC Reset Reason.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
|
@ -149,6 +149,7 @@ pub(crate) fn configure_clock() {
|
||||
// System Reset: Reset the whole digital system, including RTC sub-system
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
/// SOC Reset Reason.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
|
@ -39,6 +39,7 @@ pub(crate) fn configure_clock() {
|
||||
// System Reset: Reset the whole digital system, including RTC sub-system
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
/// SOC Reset Reason.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
|
@ -39,6 +39,7 @@ pub(crate) fn configure_clock() {
|
||||
// System Reset: Reset the whole digital system, including RTC sub-system
|
||||
// Chip Reset: Reset the whole chip, including the analog part
|
||||
|
||||
/// SOC Reset Reason.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)]
|
||||
pub enum SocResetReason {
|
||||
/// Power on reset
|
||||
|
@ -7,38 +7,66 @@ use crate::{
|
||||
// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
|
||||
// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
|
||||
// Valid if RTC_CNTL_DBG_ATTEN is 0.
|
||||
/// RTC digital bias setting corresponding to 0.90V.
|
||||
pub const RTC_CNTL_DBIAS_0V90: u8 = 0;
|
||||
/// RTC digital bias setting corresponding to 0.95V.
|
||||
pub const RTC_CNTL_DBIAS_0V95: u8 = 1;
|
||||
/// RTC digital bias setting corresponding to 1.00V.
|
||||
pub const RTC_CNTL_DBIAS_1V00: u8 = 2;
|
||||
/// RTC digital bias setting corresponding to 1.05V.
|
||||
pub const RTC_CNTL_DBIAS_1V05: u8 = 3;
|
||||
/// RTC digital bias setting corresponding to 1.10V.
|
||||
pub const RTC_CNTL_DBIAS_1V10: u8 = 4;
|
||||
/// RTC digital bias setting corresponding to 1.15V.
|
||||
pub const RTC_CNTL_DBIAS_1V15: u8 = 5;
|
||||
/// RTC digital bias setting corresponding to 1.20V.
|
||||
pub const RTC_CNTL_DBIAS_1V20: u8 = 6;
|
||||
/// RTC digital bias setting corresponding to 1.25V.
|
||||
pub const RTC_CNTL_DBIAS_1V25: u8 = 7;
|
||||
|
||||
// Various delays to be programmed into power control state machines
|
||||
/// Time (in microseconds) for waiting the XTL buffer to stabilize during sleep.
|
||||
pub const RTC_CNTL_XTL_BUF_WAIT_SLP_US: u32 = 1000;
|
||||
/// Cycles to wait for PLL buffer stabilization.
|
||||
pub const RTC_CNTL_PLL_BUF_WAIT_SLP_CYCLES: u8 = 1;
|
||||
/// Cycles to wait for the 8MHz clock to stabilize.
|
||||
pub const RTC_CNTL_CK8M_WAIT_SLP_CYCLES: u8 = 4;
|
||||
/// Delay in cycles for wakeup signal to be applied.
|
||||
pub const RTC_CNTL_WAKEUP_DELAY_CYCLES: u8 = 7;
|
||||
/// Power-up cycles for other blocks.
|
||||
pub const RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES: u8 = 1;
|
||||
/// Wait cycles for other blocks.
|
||||
pub const RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES: u16 = 1;
|
||||
/// Minimum sleep value (in cycles).
|
||||
pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 128;
|
||||
/// Default debug attenuation value.
|
||||
pub const RTC_CNTL_DBG_ATTEN_DEFAULT: u8 = 3;
|
||||
|
||||
/// Power-up cycles for RTC memory.
|
||||
pub const RTC_MEM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
|
||||
/// Wait cycles for RTC memory.
|
||||
pub const RTC_MEM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
|
||||
/// Power-up cycles for ROM and RAM.
|
||||
pub const ROM_RAM_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
|
||||
/// Wait cycles for ROM and RAM.
|
||||
pub const ROM_RAM_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
|
||||
/// Power-up cycles for Wi-Fi.
|
||||
pub const WIFI_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
|
||||
/// Wait cycles for Wi-Fi.
|
||||
pub const WIFI_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
|
||||
/// Power-up cycles for RTC components.
|
||||
pub const RTC_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
|
||||
/// Wait cycles for RTC components.
|
||||
pub const RTC_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
|
||||
/// Power-up cycles for the digital wrap components.
|
||||
pub const DG_WRAP_POWERUP_CYCLES: u8 = RTC_CNTL_OTHER_BLOCKS_POWERUP_CYCLES;
|
||||
/// Wait cycles for the digital wrap components.
|
||||
pub const DG_WRAP_WAIT_CYCLES: u16 = RTC_CNTL_OTHER_BLOCKS_WAIT_CYCLES;
|
||||
|
||||
/// Default wait cycles for the 8MHz clock.
|
||||
pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
|
||||
/// Default wait cycles to enable the 8MHz clock.
|
||||
pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
|
||||
|
||||
impl WakeSource for TimerWakeupSource {
|
||||
fn apply(
|
||||
&self,
|
||||
@ -162,6 +190,7 @@ impl Drop for Ext1WakeupSource<'_, '_> {
|
||||
|
||||
bitfield::bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
/// Configuration for the RTC sleep behavior.
|
||||
pub struct RtcSleepConfig(u32);
|
||||
impl Debug;
|
||||
/// force normal voltage in sleep mode (digital domain memory)
|
||||
@ -221,6 +250,7 @@ impl Default for RtcSleepConfig {
|
||||
}
|
||||
|
||||
impl RtcSleepConfig {
|
||||
/// Configures the RTC for deep sleep mode.
|
||||
pub fn deep() -> Self {
|
||||
let mut cfg = Self::default();
|
||||
cfg.set_deep_slp(true);
|
||||
|
@ -42,46 +42,83 @@ const I2C_ULP_HOSTID: u8 = 0;
|
||||
// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
|
||||
// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
|
||||
// Valid if RTC_CNTL_DBG_ATTEN is 0.
|
||||
/// Digital bias voltage level of 0.90V.
|
||||
pub const RTC_CNTL_DBIAS_0V90: u32 = 13;
|
||||
/// Digital bias voltage level of 0.95V.
|
||||
pub const RTC_CNTL_DBIAS_0V95: u32 = 16;
|
||||
/// Digital bias voltage level of 1.00V.
|
||||
pub const RTC_CNTL_DBIAS_1V00: u32 = 18;
|
||||
/// Digital bias voltage level of 1.05V.
|
||||
pub const RTC_CNTL_DBIAS_1V05: u32 = 20;
|
||||
/// Digital bias voltage level of 1.10V.
|
||||
pub const RTC_CNTL_DBIAS_1V10: u32 = 23;
|
||||
/// Digital bias voltage level of 1.15V.
|
||||
pub const RTC_CNTL_DBIAS_1V15: u32 = 25;
|
||||
/// Digital bias voltage level of 1.20V.
|
||||
pub const RTC_CNTL_DBIAS_1V20: u32 = 28;
|
||||
/// Digital bias voltage level of 1.25V.
|
||||
pub const RTC_CNTL_DBIAS_1V25: u32 = 30;
|
||||
pub const RTC_CNTL_DBIAS_1V30: u32 = 31; //< voltage is about 1.34v in fact
|
||||
/// Digital bias voltage level of approximately 1.34V.
|
||||
pub const RTC_CNTL_DBIAS_1V30: u32 = 31;
|
||||
|
||||
/// Default attenuation setting during light sleep, with a voltage drop.
|
||||
pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_DEFAULT: u8 = 5;
|
||||
/// No attenuation (no voltage drop) during light sleep.
|
||||
pub const RTC_CNTL_DBG_ATTEN_LIGHTSLEEP_NODROP: u8 = 0;
|
||||
/// Default attenuation setting during deep sleep, with maximum voltage drop.
|
||||
pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_DEFAULT: u8 = 15;
|
||||
/// No attenuation (no voltage drop) during deep sleep.
|
||||
pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_NODROP: u8 = 0;
|
||||
|
||||
/// Default bias setting during sleep mode.
|
||||
pub const RTC_CNTL_BIASSLP_SLEEP_DEFAULT: u8 = 1;
|
||||
/// Keeps the bias for ultra-low power sleep mode always on.
|
||||
pub const RTC_CNTL_BIASSLP_SLEEP_ON: u8 = 0;
|
||||
|
||||
/// Default power-down current setting during sleep mode.
|
||||
pub const RTC_CNTL_PD_CUR_SLEEP_DEFAULT: u8 = 1;
|
||||
/// Keeps the power-down current setting for sleep mode always on.
|
||||
pub const RTC_CNTL_PD_CUR_SLEEP_ON: u8 = 0;
|
||||
|
||||
/// Default driver bias setting for the digital domain during sleep mode.
|
||||
pub const RTC_CNTL_DG_VDD_DRV_B_SLP_DEFAULT: u8 = 254;
|
||||
|
||||
/// Default debug attenuation setting for the monitor mode.
|
||||
pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
|
||||
/// Default bias setting for sleep mode in the monitor mode.
|
||||
pub const RTC_CNTL_BIASSLP_MONITOR_DEFAULT: bool = false;
|
||||
/// Default power-down current setting for the monitor mode.
|
||||
pub const RTC_CNTL_PD_CUR_MONITOR_DEFAULT: bool = false;
|
||||
|
||||
/// Default number of cycles to wait for the PLL buffer to stabilize.
|
||||
pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
|
||||
/// Default number of cycles to wait for the XTL buffer to stabilize.
|
||||
pub const RTC_CNTL_XTL_BUF_WAIT_DEFAULT: u8 = 100;
|
||||
/// Default number of cycles to wait for the internal 8MHz clock to stabilize.
|
||||
pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
|
||||
/// Default number of cycles required to enable the internal 8MHz clock.
|
||||
pub const RTC_CK8M_ENABLE_WAIT_DEFAULT: u8 = 5;
|
||||
|
||||
/// Minimum number of cycles for sleep duration.
|
||||
pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
|
||||
|
||||
/// Power-up cycles for other hardware blocks.
|
||||
pub const OTHER_BLOCKS_POWERUP: u8 = 1;
|
||||
/// Wait cycles for other hardware blocks to stabilize.
|
||||
pub const OTHER_BLOCKS_WAIT: u16 = 1;
|
||||
|
||||
/// Disables GPIO interrupt.
|
||||
pub const GPIO_INTR_DISABLE: u8 = 0;
|
||||
/// Sets GPIO interrupt to trigger on a low level signal.
|
||||
pub const GPIO_INTR_LOW_LEVEL: u8 = 4;
|
||||
/// Sets GPIO interrupt to trigger on a high level signal.
|
||||
pub const GPIO_INTR_HIGH_LEVEL: u8 = 5;
|
||||
|
||||
/// Specifies the function configuration for GPIO pins.
|
||||
pub const PIN_FUNC_GPIO: u8 = 1;
|
||||
/// Index for signaling GPIO output.
|
||||
pub const SIG_GPIO_OUT_IDX: u32 = 128;
|
||||
/// Maximum number of GPIO pins supported.
|
||||
pub const GPIO_NUM_MAX: usize = 22;
|
||||
|
||||
impl WakeSource for TimerWakeupSource {
|
||||
@ -256,6 +293,7 @@ impl WakeSource for RtcioWakeupSource<'_, '_> {
|
||||
|
||||
bitfield::bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
/// RTC Configuration.
|
||||
pub struct RtcConfig(u32);
|
||||
impl Debug;
|
||||
/// Number of rtc_fast_clk cycles to wait for 8M clock to be ready
|
||||
@ -264,16 +302,19 @@ bitfield::bitfield! {
|
||||
pub u8, xtal_wait, set_xtal_wait: 15, 8;
|
||||
/// Number of rtc_fast_clk cycles to wait for PLL clock to be ready
|
||||
pub u8, pll_wait, set_pll_wait: 23, 16;
|
||||
// Perform clock control related initialization.
|
||||
/// Perform clock control related initialization.
|
||||
pub clkctl_init, set_clkctl_init: 24;
|
||||
// Perform power control related initialization.
|
||||
/// Perform power control related initialization.
|
||||
pub pwrctl_init, set_pwrctl_init: 25;
|
||||
// Force power down RTC_DBOOST
|
||||
/// Force power down `RTC_DBOOST`.
|
||||
pub rtc_dboost_fpd, set_rtc_dboost_fpd: 26;
|
||||
/// Keep the XTAL oscillator powered up in sleep.
|
||||
pub xtal_fpu, set_xtal_fpu: 27;
|
||||
/// Keep the BBPLL oscillator powered up in sleep.
|
||||
pub bbpll_fpu, set_bbpll_fpu: 28;
|
||||
/// Enable clock gating when the CPU is in wait-for-interrupt state.
|
||||
pub cpu_waiti_clk_gate, set_cpu_waiti_clk_gate: 29;
|
||||
// Calibrate Ocode to make bandgap voltage more precise.
|
||||
/// Calibrate Ocode to make bandgap voltage more precise.
|
||||
pub cali_ocode, set_cali_ocode: 30;
|
||||
}
|
||||
|
||||
@ -293,17 +334,28 @@ impl Default for RtcConfig {
|
||||
|
||||
bitfield::bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
/// Configuration for RTC initialization.
|
||||
pub struct RtcInitConfig(u128);
|
||||
impl Debug;
|
||||
/// Number of cycles required to power up WiFi
|
||||
pub u8, wifi_powerup_cycles, set_wifi_powerup_cycles: 6, 0;
|
||||
/// Number of wait cycles for WiFi to stabilize
|
||||
pub u16, wifi_wait_cycles, set_wifi_wait_cycles: 15, 7;
|
||||
/// Number of cycles required to power up Bluetooth
|
||||
pub u8, bt_powerup_cycles, set_bt_powerup_cycles: 22, 16;
|
||||
/// Number of wait cycles for Bluetooth to stabilize
|
||||
pub u16, bt_wait_cycles, set_bt_wait_cycles: 31, 23;
|
||||
/// Number of cycles required to power up the top CPU
|
||||
pub u8, cpu_top_powerup_cycles, set_cpu_top_powerup_cycles: 38, 32;
|
||||
/// Number of wait cycles for the top CPU to stabilize
|
||||
pub u16, cpu_top_wait_cycles, set_cpu_top_wait_cycles: 47, 39;
|
||||
/// Number of cycles required to power up the digital wrapper
|
||||
pub u8, dg_wrap_powerup_cycles, set_dg_wrap_powerup_cycles: 54, 48;
|
||||
/// Number of wait cycles for the digital wrapper to stabilize
|
||||
pub u16, dg_wrap_wait_cycles, set_dg_wrap_wait_cycles: 63, 55;
|
||||
/// Number of cycles required to power up the digital peripherals
|
||||
pub u8, dg_peri_powerup_cycles, set_dg_peri_powerup_cycles: 70, 64;
|
||||
/// Number of wait cycles for the digital peripherals to stabilize
|
||||
pub u16, dg_peri_wait_cycles, set_dg_peri_wait_cycles: 79, 71;
|
||||
}
|
||||
|
||||
@ -326,6 +378,7 @@ impl Default for RtcInitConfig {
|
||||
|
||||
bitfield::bitfield! {
|
||||
#[derive(Clone, Copy)]
|
||||
/// Configuration for RTC sleep mode.
|
||||
pub struct RtcSleepConfig(u64);
|
||||
impl Debug;
|
||||
/// force normal voltage in sleep mode (digital domain memory)
|
||||
@ -437,6 +490,7 @@ fn rtc_sleep_pu(val: bool) {
|
||||
}
|
||||
|
||||
impl RtcSleepConfig {
|
||||
/// Configures the RTC for deep sleep mode.
|
||||
pub fn deep() -> Self {
|
||||
// Set up for ultra-low power sleep. Wakeup sources may modify these settings.
|
||||
let mut cfg = Self::default();
|
||||
|
@ -160,11 +160,14 @@ impl WakeSource for WakeFromLpCoreWakeupSource {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for controlling the behavior during sleep modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_sleep_analog_config_t
|
||||
pub struct AnalogSleepConfig {
|
||||
/// High-power system configuration.
|
||||
pub hp_sys: HpAnalog,
|
||||
// pub lp_sys_active: LpAnalog, // unused
|
||||
/// Low-power system analog configuration.
|
||||
pub lp_sys_sleep: LpAnalog,
|
||||
}
|
||||
|
||||
@ -298,9 +301,12 @@ impl AnalogSleepConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for controlling the behavior of digital peripherals during
|
||||
/// sleep modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_sleep_digital_config_t
|
||||
pub struct DigitalSleepConfig {
|
||||
/// High-power system control register configuration.
|
||||
pub syscntl: HpSysCntlReg,
|
||||
}
|
||||
|
||||
@ -329,11 +335,16 @@ impl DigitalSleepConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for controlling the power settings of high-power and low-power
|
||||
/// systems during sleep modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_sleep_power_config_t
|
||||
pub struct PowerSleepConfig {
|
||||
/// Power configuration for the high-power system during sleep.
|
||||
pub hp_sys: HpSysPower,
|
||||
/// Power configuration for the low-power system when it is active.
|
||||
pub lp_sys_active: LpSysPower,
|
||||
/// Power configuration for the low-power system when it is in sleep mode.
|
||||
pub lp_sys_sleep: LpSysPower,
|
||||
}
|
||||
|
||||
@ -424,42 +435,64 @@ impl PowerSleepConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Parameters for high-power system configurations during sleep modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_hp_param_t
|
||||
pub struct HpParam {
|
||||
/// Number of cycles to wait for the modem to wake up.
|
||||
pub modem_wakeup_wait_cycle: u32,
|
||||
/// Number of cycles to wait for the analog component stabilization.
|
||||
pub analog_wait_target_cycle: u16,
|
||||
/// Number of cycles to wait for the digital power-down sequence.
|
||||
pub digital_power_down_wait_cycle: u16,
|
||||
/// Number of cycles to wait for the digital power supply to stabilize.
|
||||
pub digital_power_supply_wait_cycle: u16,
|
||||
/// Number of cycles to wait for the digital power-up sequence.
|
||||
pub digital_power_up_wait_cycle: u16,
|
||||
/// Number of cycles to wait for the PLL to stabilize.
|
||||
pub pll_stable_wait_cycle: u16,
|
||||
/// Number of cycles to wait for modifying the ICG control.
|
||||
pub modify_icg_cntl_wait_cycle: u8,
|
||||
/// Number of cycles to wait for switching the ICG coйntrol.
|
||||
pub switch_icg_cntl_wait_cycle: u8,
|
||||
/// Minimum sleep time measured in slow clock cycles.
|
||||
pub min_slp_slow_clk_cycle: u8,
|
||||
}
|
||||
|
||||
/// Parameters for low-power system configurations during sleep modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_lp_param_t
|
||||
pub struct LpParam {
|
||||
/// Number of cycles to wait for the digital power supply to stabilize.
|
||||
pub digital_power_supply_wait_cycle: u16,
|
||||
/// Minimum sleep time measured in slow clock cycles.
|
||||
pub min_slp_slow_clk_cycle: u8,
|
||||
/// Number of cycles to wait for the analog component stabilization.
|
||||
pub analog_wait_target_cycle: u8,
|
||||
/// Number of cycles to wait for the digital power-down sequence.
|
||||
pub digital_power_down_wait_cycle: u8,
|
||||
/// Number of cycles to wait for the digital power-up sequence.
|
||||
pub digital_power_up_wait_cycle: u8,
|
||||
}
|
||||
|
||||
/// Parameters for high-power and low-power system configurations during sleep
|
||||
/// modes.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_hp_lp_param_t
|
||||
pub struct HpLpParam {
|
||||
// union of two u16 variants, I've elected to not complicate things...
|
||||
/// Union of two u16 variants
|
||||
pub xtal_stable_wait_cycle: u16,
|
||||
}
|
||||
|
||||
/// Configuration of parameters for sleep modes
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_sleep_param_config_t
|
||||
pub struct ParamSleepConfig {
|
||||
/// Configuration of high-power system parameters.
|
||||
pub hp_sys: HpParam,
|
||||
/// Configuration of low-power system parameters.
|
||||
pub lp_sys: LpParam,
|
||||
/// Shared configuration parameters for high-power and low-power systems.
|
||||
pub hp_lp: HpLpParam,
|
||||
}
|
||||
impl ParamSleepConfig {
|
||||
@ -729,10 +762,13 @@ impl SleepTimeConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// Configuration for the RTC sleep behavior.
|
||||
#[derive(Clone, Copy)]
|
||||
// pmu_sleep_config_t + deep sleep flag + pd flags
|
||||
pub struct RtcSleepConfig {
|
||||
/// Deep Sleep flag
|
||||
pub deep: bool,
|
||||
/// Power Down flags
|
||||
pub pd_flags: PowerDownFlags,
|
||||
}
|
||||
|
||||
@ -761,28 +797,46 @@ bitfield::bitfield! {
|
||||
/// Power domains to be powered down during sleep
|
||||
pub struct PowerDownFlags(u32);
|
||||
|
||||
/// Controls the power-down status of the top power domain.
|
||||
pub u32, pd_top , set_pd_top : 0;
|
||||
/// Controls the power-down status of the VDD_SDIO power domain.
|
||||
pub u32, pd_vddsdio , set_pd_vddsdio : 1;
|
||||
/// Controls the power-down status of the modem power domain.
|
||||
pub u32, pd_modem , set_pd_modem : 2;
|
||||
/// Controls the power-down status of the high-performance peripheral power domain.
|
||||
pub u32, pd_hp_periph, set_pd_hp_periph: 3;
|
||||
/// Controls the power-down status of the CPU power domain.
|
||||
pub u32, pd_cpu , set_pd_cpu : 4;
|
||||
/// Controls the power-down status of the high-performance always-on domain.
|
||||
pub u32, pd_hp_aon , set_pd_hp_aon : 5;
|
||||
/// Controls the power-down status of memory group 0.
|
||||
pub u32, pd_mem_g0 , set_pd_mem_g0 : 6;
|
||||
/// Controls the power-down status of memory group 1.
|
||||
pub u32, pd_mem_g1 , set_pd_mem_g1 : 7;
|
||||
/// Controls the power-down status of memory group 2.
|
||||
pub u32, pd_mem_g2 , set_pd_mem_g2 : 8;
|
||||
/// Controls the power-down status of memory group 3.
|
||||
pub u32, pd_mem_g3 , set_pd_mem_g3 : 9;
|
||||
/// Controls the power-down status of the crystal oscillator.
|
||||
pub u32, pd_xtal , set_pd_xtal : 10;
|
||||
/// Controls the power-down status of the fast RC oscillator.
|
||||
pub u32, pd_rc_fast , set_pd_rc_fast : 11;
|
||||
/// Controls the power-down status of the 32kHz crystal oscillator.
|
||||
pub u32, pd_xtal32k , set_pd_xtal32k : 12;
|
||||
/// Controls the power-down status of the 32kHz RC oscillator.
|
||||
pub u32, pd_rc32k , set_pd_rc32k : 13;
|
||||
/// Controls the power-down status of the low-power peripheral domain.
|
||||
pub u32, pd_lp_periph, set_pd_lp_periph: 14;
|
||||
}
|
||||
|
||||
impl PowerDownFlags {
|
||||
/// Checks whether all memory groups (G0, G1, G2, G3) are powered down.
|
||||
pub fn pd_mem(self) -> bool {
|
||||
self.pd_mem_g0() && self.pd_mem_g1() && self.pd_mem_g2() && self.pd_mem_g3()
|
||||
}
|
||||
|
||||
/// Sets the power-down status for all memory groups (G0, G1, G2, G3) at
|
||||
/// once.
|
||||
pub fn set_pd_mem(&mut self, value: bool) {
|
||||
self.set_pd_mem_g0(value);
|
||||
self.set_pd_mem_g1(value);
|
||||
@ -826,10 +880,12 @@ impl MachineConstants {
|
||||
}
|
||||
|
||||
impl RtcSleepConfig {
|
||||
/// Returns whether the device is in deep sleep mode.
|
||||
pub fn deep_slp(&self) -> bool {
|
||||
self.deep
|
||||
}
|
||||
|
||||
/// Configures the device for deep sleep mode with ultra-low power settings.
|
||||
pub fn deep() -> Self {
|
||||
// Set up for ultra-low power sleep. Wakeup sources may modify these settings.
|
||||
Self {
|
||||
|
@ -42,41 +42,69 @@ const I2C_DIG_REG_XPD_DIG_REG_LSB: u32 = 3;
|
||||
// Approximate mapping of voltages to RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_SLP,
|
||||
// RTC_CNTL_DIG_DBIAS_WAK, RTC_CNTL_DIG_DBIAS_SLP values.
|
||||
// Valid if RTC_CNTL_DBG_ATTEN is 0.
|
||||
/// Digital bias setting for 0.90V.
|
||||
pub const RTC_CNTL_DBIAS_0V90: u32 = 13;
|
||||
/// Digital bias setting for 0.95V.
|
||||
pub const RTC_CNTL_DBIAS_0V95: u32 = 16;
|
||||
/// Digital bias setting for 1.00V.
|
||||
pub const RTC_CNTL_DBIAS_1V00: u32 = 18;
|
||||
/// Digital bias setting for 1.05V.
|
||||
pub const RTC_CNTL_DBIAS_1V05: u32 = 20;
|
||||
/// Digital bias setting for 1.10V.
|
||||
pub const RTC_CNTL_DBIAS_1V10: u32 = 23;
|
||||
/// Digital bias setting for 1.15V.
|
||||
pub const RTC_CNTL_DBIAS_1V15: u32 = 25;
|
||||
/// Digital bias setting for 1.20V.
|
||||
pub const RTC_CNTL_DBIAS_1V20: u32 = 28;
|
||||
/// Digital bias setting for 1.25V.
|
||||
pub const RTC_CNTL_DBIAS_1V25: u32 = 30;
|
||||
pub const RTC_CNTL_DBIAS_1V30: u32 = 31; //< voltage is about 1.34v in fact
|
||||
|
||||
/// Digital bias setting for 1.30V. Voltage is approximately 1.34V in practice.
|
||||
pub const RTC_CNTL_DBIAS_1V30: u32 = 31;
|
||||
/// Default monitor debug attenuation value.
|
||||
pub const RTC_CNTL_DBG_ATTEN_MONITOR_DEFAULT: u8 = 0;
|
||||
/// ULP co-processor touch start wait time during sleep, set to maximum.
|
||||
pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_IN_SLEEP: u16 = 0xFF;
|
||||
/// ULP co-processor touch start wait time default value.
|
||||
pub const RTC_CNTL_ULPCP_TOUCH_START_WAIT_DEFAULT: u16 = 0x10;
|
||||
|
||||
/// Default wait time for PLL buffer during startup.
|
||||
pub const RTC_CNTL_PLL_BUF_WAIT_DEFAULT: u8 = 20;
|
||||
/// Default wait time for CK8M during startup.
|
||||
pub const RTC_CNTL_CK8M_WAIT_DEFAULT: u8 = 20;
|
||||
/// Minimum sleep value.
|
||||
pub const RTC_CNTL_MIN_SLP_VAL_MIN: u8 = 2;
|
||||
/// Deep sleep debug attenuation setting for ultra-low power mode.
|
||||
pub const RTC_CNTL_DBG_ATTEN_DEEPSLEEP_ULTRA_LOW: u8 = 15;
|
||||
|
||||
/// Power-up setting for other blocks.
|
||||
pub const OTHER_BLOCKS_POWERUP: u8 = 1;
|
||||
/// Wait cycles for other blocks.
|
||||
pub const OTHER_BLOCKS_WAIT: u16 = 1;
|
||||
|
||||
/// WiFi power-up cycles.
|
||||
pub const WIFI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// WiFi wait cycles.
|
||||
pub const WIFI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// Bluetooth power-up cycles.
|
||||
pub const BT_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// Bluetooth wait cycles.
|
||||
pub const BT_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// RTC power-up cycles.
|
||||
pub const RTC_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// RTC wait cycles.
|
||||
pub const RTC_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// CPU top power-up cycles.
|
||||
pub const CPU_TOP_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// CPU top wait cycles.
|
||||
pub const CPU_TOP_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// DG wrap power-up cycles.
|
||||
pub const DG_WRAP_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// DG wrap wait cycles.
|
||||
pub const DG_WRAP_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// DG peripheral power-up cycles.
|
||||
pub const DG_PERI_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// DG peripheral wait cycles.
|
||||
pub const DG_PERI_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
/// RTC memory power-up cycles.
|
||||
pub const RTC_MEM_POWERUP_CYCLES: u8 = OTHER_BLOCKS_POWERUP;
|
||||
/// RTC memory wait cycles.
|
||||
pub const RTC_MEM_WAIT_CYCLES: u16 = OTHER_BLOCKS_WAIT;
|
||||
|
||||
impl WakeSource for TimerWakeupSource {
|
||||
@ -266,6 +294,7 @@ impl Drop for RtcioWakeupSource<'_, '_> {
|
||||
}
|
||||
|
||||
bitfield::bitfield! {
|
||||
/// Configuration for the RTC sleep behavior.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct RtcSleepConfig(u64);
|
||||
impl Debug;
|
||||
@ -382,6 +411,7 @@ fn rtc_sleep_pu(val: bool) {
|
||||
}
|
||||
|
||||
impl RtcSleepConfig {
|
||||
/// Configures the RTC for deep sleep mode.
|
||||
pub fn deep() -> Self {
|
||||
// Set up for ultra-low power sleep. Wakeup sources may modify these settings.
|
||||
let mut cfg = Self::default();
|
||||
|
@ -33,41 +33,56 @@ mod sleep_impl;
|
||||
pub use sleep_impl::*;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
/// Level at which a wake-up event is triggered
|
||||
pub enum WakeupLevel {
|
||||
/// The wake-up event is triggered when the pin is low.
|
||||
Low,
|
||||
#[default]
|
||||
/// The wake-up event is triggered when the pin is high.
|
||||
High,
|
||||
}
|
||||
|
||||
/// Represents a timer wake-up source, triggering an event after a specified
|
||||
/// duration.
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[cfg(any(esp32, esp32c3, esp32s3, esp32c6))]
|
||||
pub struct TimerWakeupSource {
|
||||
/// The duration after which the wake-up event is triggered.
|
||||
duration: Duration,
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32c3, esp32s3, esp32c6))]
|
||||
impl TimerWakeupSource {
|
||||
/// Creates a new timer wake-up source with the specified duration.
|
||||
pub fn new(duration: Duration) -> Self {
|
||||
Self { duration }
|
||||
}
|
||||
}
|
||||
|
||||
/// Errors that can occur when configuring RTC wake-up sources.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// The selected pin is not a valid RTC pin.
|
||||
NotRtcPin,
|
||||
/// The maximum number of wake-up sources has been exceeded.
|
||||
TooManyWakeupSources,
|
||||
}
|
||||
|
||||
/// External wake-up source (Ext0).
|
||||
#[derive(Debug)]
|
||||
#[cfg(any(esp32, esp32s3))]
|
||||
pub struct Ext0WakeupSource<'a, P: RtcIoWakeupPinType> {
|
||||
/// The pin used as the wake-up source.
|
||||
pin: RefCell<&'a mut P>,
|
||||
/// The level at which the wake-up event is triggered.
|
||||
level: WakeupLevel,
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s3))]
|
||||
impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
|
||||
/// Creates a new external wake-up source (Ext0``) with the specified pin
|
||||
/// and wake-up level.
|
||||
pub fn new(pin: &'a mut P, level: WakeupLevel) -> Self {
|
||||
Self {
|
||||
pin: RefCell::new(pin),
|
||||
@ -76,14 +91,19 @@ impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
|
||||
}
|
||||
}
|
||||
|
||||
/// External wake-up source (Ext1).
|
||||
#[cfg(any(esp32, esp32s3))]
|
||||
pub struct Ext1WakeupSource<'a, 'b> {
|
||||
/// A collection of pins used as wake-up sources.
|
||||
pins: RefCell<&'a mut [&'b mut dyn RtcIoWakeupPinType]>,
|
||||
/// The level at which the wake-up event is triggered across all pins.
|
||||
level: WakeupLevel,
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s3))]
|
||||
impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
|
||||
/// Creates a new external wake-up source (Ext1) with the specified pins and
|
||||
/// wake-up level.
|
||||
pub fn new(pins: &'a mut [&'b mut dyn RtcIoWakeupPinType], level: WakeupLevel) -> Self {
|
||||
Self {
|
||||
pins: RefCell::new(pins),
|
||||
@ -92,6 +112,7 @@ impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
|
||||
}
|
||||
}
|
||||
|
||||
/// External wake-up source (Ext1).
|
||||
#[cfg(esp32c6)]
|
||||
pub struct Ext1WakeupSource<'a, 'b> {
|
||||
pins: RefCell<&'a mut [(&'b mut dyn RtcIoWakeupPinType, WakeupLevel)]>,
|
||||
@ -99,6 +120,8 @@ pub struct Ext1WakeupSource<'a, 'b> {
|
||||
|
||||
#[cfg(esp32c6)]
|
||||
impl<'a, 'b> Ext1WakeupSource<'a, 'b> {
|
||||
/// Creates a new external wake-up source (Ext1) with the specified pins and
|
||||
/// wake-up level.
|
||||
pub fn new(pins: &'a mut [(&'b mut dyn RtcIoWakeupPinType, WakeupLevel)]) -> Self {
|
||||
Self {
|
||||
pins: RefCell::new(pins),
|
||||
@ -118,6 +141,7 @@ pub struct RtcioWakeupSource<'a, 'b> {
|
||||
|
||||
#[cfg(any(esp32c3, esp32s3))]
|
||||
impl<'a, 'b> RtcioWakeupSource<'a, 'b> {
|
||||
/// Creates a new external wake-up source (Ext1).
|
||||
pub fn new(pins: &'a mut [(&'b mut dyn RtcIoWakeupPinType, WakeupLevel)]) -> Self {
|
||||
Self {
|
||||
pins: RefCell::new(pins),
|
||||
@ -247,6 +271,7 @@ uart_wakeup_impl!(1);
|
||||
|
||||
#[cfg(not(pmu))]
|
||||
bitfield::bitfield! {
|
||||
/// Represents the wakeup triggers.
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct WakeTriggers(u16);
|
||||
impl Debug;
|
||||
@ -276,6 +301,7 @@ bitfield::bitfield! {
|
||||
|
||||
#[cfg(pmu)]
|
||||
bitfield::bitfield! {
|
||||
/// Represents the wakeup triggers.
|
||||
#[derive(Default, Clone, Copy)]
|
||||
pub struct WakeTriggers(u16);
|
||||
impl Debug;
|
||||
@ -306,6 +332,8 @@ bitfield::bitfield! {
|
||||
pub usb, set_usb: 14;
|
||||
}
|
||||
|
||||
/// Trait representing a wakeup source.
|
||||
pub trait WakeSource {
|
||||
/// Configures the RTC and applies the wakeup triggers.
|
||||
fn apply(&self, rtc: &Rtc<'_>, triggers: &mut WakeTriggers, sleep_config: &mut RtcSleepConfig);
|
||||
}
|
||||
|
@ -57,8 +57,6 @@
|
||||
//! ## Implementation State
|
||||
//! - DMA-SHA Mode is not supported.
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::{convert::Infallible, marker::PhantomData};
|
||||
|
||||
/// Re-export digest for convenience
|
||||
@ -99,10 +97,17 @@ impl crate::InterruptConfigurable for Context<crate::Blocking> {
|
||||
}
|
||||
|
||||
impl<DM: crate::Mode> Context<DM> {
|
||||
/// Indicates if the SHA context is in the first run.
|
||||
///
|
||||
/// Returns `true` if this is the first time processing data with the SHA
|
||||
/// instance, otherwise returns `false`.
|
||||
pub fn first_run(&self) -> bool {
|
||||
self.first_run
|
||||
}
|
||||
|
||||
/// Indicates if the SHA context has finished processing the data.
|
||||
///
|
||||
/// Returns `true` if the SHA calculation is complete, otherwise returns.
|
||||
pub fn finished(&self) -> bool {
|
||||
self.finished
|
||||
}
|
||||
@ -122,8 +127,14 @@ impl<DM: crate::Mode> Context<DM> {
|
||||
// - This means that we need to buffer bytes coming in up to 4 u8's in order
|
||||
// to create a full u32
|
||||
|
||||
// This implementation might fail after u32::MAX/8 bytes, to increase please see
|
||||
// ::finish() length/self.cursor usage
|
||||
/// Trait for defining the behavior of a SHA algorithm instance.
|
||||
///
|
||||
/// This trait encapsulates the operations and configuration for a specific SHA
|
||||
/// algorithm and provides methods for processing data buffers and calculating
|
||||
/// the final hash.
|
||||
///
|
||||
/// This implementation might fail after u32::MAX/8 bytes, to increase please
|
||||
/// see ::finish() length/self.cursor usage
|
||||
pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
/// Constant containing the name of the algorithm as a string.
|
||||
const ALGORITHM: &'static str;
|
||||
@ -132,8 +143,14 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
#[cfg(not(esp32))]
|
||||
fn mode_as_bits() -> u8;
|
||||
|
||||
/// Returns the length of the chunk that the algorithm processes at a time.
|
||||
///
|
||||
/// For example, in SHA-256, this would typically return 64 bytes.
|
||||
fn chunk_length(&self) -> usize;
|
||||
|
||||
/// Returns the length of the resulting digest produced by the algorithm.
|
||||
///
|
||||
/// For example, in SHA-256, this would return 32 bytes.
|
||||
fn digest_length(&self) -> usize;
|
||||
|
||||
/// ESP32 requires that a control register to be written to calculate the
|
||||
@ -141,10 +158,16 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
#[cfg(esp32)]
|
||||
fn load_reg(&self);
|
||||
|
||||
/// Checks if the SHA peripheral is busy processing data.
|
||||
///
|
||||
/// Returns `true` if the SHA peripheral is busy, `false` otherwise.
|
||||
/// ESP32 uses a different register per hash mode.
|
||||
#[cfg(esp32)]
|
||||
fn is_busy(&self) -> bool;
|
||||
|
||||
/// Checks if the SHA peripheral is busy processing data.
|
||||
///
|
||||
/// Returns `true` if the SHA peripheral is busy, `false` otherwise.
|
||||
#[cfg(not(esp32))]
|
||||
fn is_busy(&self) -> bool {
|
||||
// Safety: This is safe because we only read `SHA_BUSY_REG`
|
||||
@ -152,9 +175,17 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
sha.busy().read().bits() != 0
|
||||
}
|
||||
|
||||
/// Processes the data buffer and updates the hash state.
|
||||
///
|
||||
/// This method is platform-specific and differs for ESP32 and non-ESP32
|
||||
/// platforms.
|
||||
#[cfg(esp32)]
|
||||
fn process_buffer(&mut self);
|
||||
|
||||
/// Processes the data buffer and updates the hash state.
|
||||
///
|
||||
/// This method is platform-specific and differs for ESP32 and non-ESP32
|
||||
/// platforms.
|
||||
#[cfg(not(esp32))]
|
||||
fn process_buffer(&mut self) {
|
||||
// Safety: This is safe because digest state is restored and saved between
|
||||
@ -193,6 +224,11 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
self.saved_digest.replace(saved_digest);
|
||||
}
|
||||
|
||||
/// Flushes any remaining data from the internal buffer to the SHA
|
||||
/// peripheral.
|
||||
///
|
||||
/// Returns a `Result` indicating whether the flush was successful or if the
|
||||
/// operation would block.
|
||||
fn flush_data(&mut self) -> nb::Result<(), Infallible> {
|
||||
if self.is_busy() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
@ -234,8 +270,9 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// This function ensures that incoming data is aligned to u32 (due to issues
|
||||
// with cpy_mem<u8>)
|
||||
/// Writes data into the SHA buffer.
|
||||
/// This function ensures that incoming data is aligned to u32 (due to
|
||||
/// issues with `cpy_mem<u8>`)
|
||||
fn write_data<'a>(&mut self, incoming: &'a [u8]) -> nb::Result<&'a [u8], Infallible> {
|
||||
let mod_cursor = self.cursor % self.chunk_length();
|
||||
|
||||
@ -273,6 +310,7 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
Ok(remaining)
|
||||
}
|
||||
|
||||
/// Updates the SHA context with the provided data buffer.
|
||||
fn update<'a>(&mut self, buffer: &'a [u8]) -> nb::Result<&'a [u8], Infallible> {
|
||||
if self.is_busy() {
|
||||
return Err(nb::Error::WouldBlock);
|
||||
@ -285,12 +323,12 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
Ok(remaining)
|
||||
}
|
||||
|
||||
// Finish of the calculation (if not alreaedy) and copy result to output
|
||||
// After `finish()` is called `update()`s will contribute to a new hash which
|
||||
// can be calculated again with `finish()`.
|
||||
//
|
||||
// Typically output is expected to be the size of digest_length(), but smaller
|
||||
// inputs can be given to get a "short hash"
|
||||
/// Finish of the calculation (if not already) and copy result to output
|
||||
/// After `finish()` is called `update()`s will contribute to a new hash
|
||||
/// which can be calculated again with `finish()`.
|
||||
///
|
||||
/// Typically output is expected to be the size of digest_length(), but
|
||||
/// smaller inputs can be given to get a "short hash"
|
||||
fn finish(&mut self, output: &mut [u8]) -> nb::Result<(), Infallible> {
|
||||
// The main purpose of this function is to dynamically generate padding for the
|
||||
// input. Padding: Append "1" bit, Pad zeros until 512/1024 filled
|
||||
@ -393,6 +431,15 @@ pub trait Sha<DM: crate::Mode>: core::ops::DerefMut<Target = Context<DM>> {
|
||||
/// and a set of parameters
|
||||
macro_rules! impl_sha {
|
||||
($name: ident, $mode_bits: tt, $digest_length: tt, $chunk_length: tt) => {
|
||||
/// A SHA implementation struct.
|
||||
///
|
||||
/// This struct is generated by the macro and represents a specific SHA hashing
|
||||
/// algorithm (e.g., SHA-256, SHA-1). It manages the context and state required
|
||||
/// for processing data using the selected hashing algorithm.
|
||||
///
|
||||
/// The struct provides various functionalities such as initializing the hashing
|
||||
/// process, updating the internal state with new data, and finalizing the
|
||||
/// hashing operation to generate the final digest.
|
||||
pub struct $name<DM: crate::Mode>(Context<DM>);
|
||||
|
||||
impl $name<crate::Blocking> {
|
||||
|
@ -99,14 +99,17 @@ impl<const SIZE: usize> Stack<SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the size of the stack.
|
||||
pub const fn len(&self) -> usize {
|
||||
SIZE
|
||||
}
|
||||
|
||||
/// Provides a mutable pointer to the bottom of the stack.
|
||||
pub fn bottom(&mut self) -> *mut u32 {
|
||||
self.mem.as_mut_ptr() as *mut u32
|
||||
}
|
||||
|
||||
/// Provides a mutable pointer to the top of the stack.
|
||||
pub fn top(&mut self) -> *mut u32 {
|
||||
unsafe { self.bottom().add(SIZE / 4) }
|
||||
}
|
||||
@ -132,9 +135,11 @@ impl<'a> Drop for AppCoreGuard<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents errors that can occur while working with the core.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// The core is already running.
|
||||
CoreAlreadyRunning,
|
||||
}
|
||||
|
||||
@ -168,6 +173,7 @@ unsafe fn internal_park_core(core: Cpu) {
|
||||
}
|
||||
|
||||
impl<'d> CpuControl<'d> {
|
||||
/// Creates a new instance of `CpuControl`.
|
||||
pub fn new(cpu_control: impl Peripheral<P = CPU_CTRL> + 'd) -> CpuControl<'d> {
|
||||
crate::into_ref!(cpu_control);
|
||||
|
||||
|
@ -47,20 +47,30 @@ use crate::peripherals::EFUSE;
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
/// Representing different types of ESP32 chips.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum ChipType {
|
||||
/// Represents the ESP32 D0WDQ6 chip variant.
|
||||
Esp32D0wdq6,
|
||||
/// Represents the ESP32 D0WDQ5 chip variant.
|
||||
Esp32D0wdq5,
|
||||
/// Represents the ESP32 D2WDQ5 chip variant.
|
||||
Esp32D2wdq5,
|
||||
/// Represents the ESP32 Pico D2 chip variant.
|
||||
Esp32Picod2,
|
||||
/// Represents the ESP32 Pico D4 chip variant.
|
||||
Esp32Picod4,
|
||||
/// Represents the ESP32 Pico v3.02 chip variant.
|
||||
Esp32Picov302,
|
||||
/// Represents an unknown or unsupported chip variant.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl Efuse {
|
||||
/// Reads the base MAC address from the eFuse memory.
|
||||
pub fn read_base_mac_address() -> [u8; 6] {
|
||||
Self::read_field_be(MAC)
|
||||
}
|
||||
|
@ -58,6 +58,7 @@ use crate::{
|
||||
Cpu,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 40;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -33,15 +33,19 @@ macro_rules! chip {
|
||||
pub use chip;
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// The base clock frequency for the I2S peripheral (Hertz).
|
||||
pub const I2S_SCLK: u32 = 160_000_000;
|
||||
/// The default clock source for I2S operations.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u32 = 2;
|
||||
|
||||
/// The starting address of the Remote Control (RMT) module's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x3ff56800;
|
||||
/// The size, in bytes, of each RMT channel's dedicated RAM.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 64;
|
||||
|
||||
/// The lower bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_LOW: u32 = 0x3FFA_E000;
|
||||
/// The upper bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x4000_0000;
|
||||
|
||||
/// A reference clock tick of 1 MHz.
|
||||
pub const REF_TICK: fugit::HertzU32 = fugit::HertzU32::MHz(1);
|
||||
}
|
||||
|
||||
|
@ -18,8 +18,12 @@
|
||||
//!
|
||||
//! NOTE: If you want to use `PSRAM` on `ESP32` or `ESP32-S3`, it'll work only
|
||||
//! in `release` mode.
|
||||
|
||||
/// The starting virtual address of the PSRAM (Pseudo-SRAM) region in memory.
|
||||
pub const PSRAM_VADDR_START: usize = 0x3F800000;
|
||||
|
||||
/// Retrieves the starting virtual address of the PSRAM (Pseudo-SRAM) region in
|
||||
/// memory.
|
||||
pub fn psram_vaddr_start() -> usize {
|
||||
PSRAM_VADDR_START
|
||||
}
|
||||
@ -36,8 +40,10 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
/// The total size of the PSRAM (Pseudo-SRAM) in bytes.
|
||||
pub const PSRAM_BYTES: usize = PSRAM_SIZE as usize * 1024 * 1024;
|
||||
|
||||
/// Initializes the PSRAM memory on supported devices.
|
||||
#[cfg(any(feature = "psram-2m", feature = "psram-4m", feature = "psram-8m"))]
|
||||
pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::peripherals::PSRAM>) {
|
||||
utils::psram_init();
|
||||
|
@ -1,6 +1,8 @@
|
||||
//! Helper functions for TRNG functionality
|
||||
|
||||
pub fn ensure_randomness() {
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
let sens = unsafe { &*crate::peripherals::SENS::ptr() };
|
||||
let dport = unsafe { &*crate::peripherals::DPORT::ptr() };
|
||||
@ -104,7 +106,8 @@ pub fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn revert_trng() {
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let sens = unsafe { &*crate::peripherals::SENS::ptr() };
|
||||
let i2s0 = unsafe { &*crate::peripherals::I2S0::ptr() };
|
||||
let apb_ctrl = unsafe { &*crate::peripherals::APB_CTRL::ptr() };
|
||||
|
@ -45,6 +45,7 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -50,6 +50,7 @@ use crate::{
|
||||
peripherals::GPIO,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 21;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -30,9 +30,12 @@ pub(crate) mod registers {
|
||||
}
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// The lower bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_LOW: u32 = 0x3FCA_0000;
|
||||
/// The upper bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x3FCE_0000;
|
||||
|
||||
/// RC FAST Clock value (Hertz).
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500);
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ const ADC_SARADC_ENT_TSENS_ADDR_LSB: u8 = 2;
|
||||
|
||||
use crate::regi2c_write_mask;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
let system = unsafe { &*crate::peripherals::SYSTEM::ptr() };
|
||||
@ -100,6 +102,7 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
|
@ -45,6 +45,7 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -51,6 +51,7 @@ use crate::{
|
||||
peripherals::GPIO,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 22;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -34,17 +34,26 @@ pub(crate) mod registers {
|
||||
}
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// The base clock frequency for the I2S peripheral (Hertz).
|
||||
pub const I2S_SCLK: u32 = 160_000_000;
|
||||
/// The default clock source for I2S operations.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u8 = 2;
|
||||
|
||||
/// The starting address of the Remote Control (RMT) module's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x60016400;
|
||||
/// The size, in bytes, of each RMT channel's dedicated RAM.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 48;
|
||||
/// RMT Clock source value.
|
||||
pub const RMT_CLOCK_SRC: u8 = 1;
|
||||
/// RMT Clock source frequence.
|
||||
pub const RMT_CLOCK_SRC_FREQ: fugit::HertzU32 = fugit::HertzU32::MHz(80);
|
||||
|
||||
/// The lower bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_LOW: u32 = 0x3FC8_0000;
|
||||
/// The upper bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x3FCE_0000;
|
||||
|
||||
/// RC FAST Clock value (Hertz).
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500);
|
||||
}
|
||||
|
||||
|
@ -15,6 +15,8 @@ const ADC_SARADC_ENT_TSENS_ADDR_LSB: u8 = 2;
|
||||
|
||||
use crate::regi2c_write_mask;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
let system = unsafe { &*crate::peripherals::SYSTEM::ptr() };
|
||||
@ -100,6 +102,7 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
|
@ -45,6 +45,7 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -51,6 +51,7 @@ use crate::{
|
||||
peripherals::GPIO,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 31;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -23,8 +23,10 @@ use esp32c6 as pac;
|
||||
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// Represents the possible wakeup sources for the LP (Low Power) core.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum LpCoreWakeupSource {
|
||||
/// Wakeup source from the HP (High Performance) CPU.
|
||||
HpCpu,
|
||||
}
|
||||
|
||||
@ -39,6 +41,7 @@ pub enum LpCoreClockSource {
|
||||
XtalD2Clk,
|
||||
}
|
||||
|
||||
/// Represents the Low Power (LP) core peripheral.
|
||||
pub struct LpCore<'d> {
|
||||
_lp_core: PeripheralRef<'d, crate::soc::peripherals::LP_CORE>,
|
||||
}
|
||||
|
@ -36,22 +36,33 @@ pub(crate) mod registers {
|
||||
}
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// The default clock source for the timer group.
|
||||
pub const TIMG_DEFAULT_CLK_SRC: u8 = 1;
|
||||
|
||||
/// The clock frequency for the I2S peripheral in Hertz.
|
||||
pub const I2S_SCLK: u32 = 160_000_000;
|
||||
/// The default clock source for the I2S peripheral.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u8 = 2;
|
||||
|
||||
/// The starting address of the RMT (Remote Control) peripheral's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x60006400;
|
||||
/// The size of each RMT channel's RAM in bytes.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 48;
|
||||
/// The default clock source for the RMT peripheral.
|
||||
pub const RMT_CLOCK_SRC: u8 = 1;
|
||||
/// The frequency of the RMT clock source in Hertz.
|
||||
pub const RMT_CLOCK_SRC_FREQ: fugit::HertzU32 = fugit::HertzU32::MHz(80);
|
||||
|
||||
/// The clock frequency for the Parallel IO peripheral in Hertz.
|
||||
pub const PARL_IO_SCLK: u32 = 240_000_000;
|
||||
|
||||
/// The lower address boundary for system DRAM.
|
||||
pub const SOC_DRAM_LOW: u32 = 0x4080_0000;
|
||||
/// The upper address boundary for system DRAM.
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x4088_0000;
|
||||
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500);
|
||||
/// RC FAST Clock value (Hertz).
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17_500);
|
||||
}
|
||||
|
||||
#[export_name = "__post_init"]
|
||||
|
@ -60,6 +60,8 @@ const ADC_SARADC2_ENCAL_REF_ADDR: u8 = 0x7;
|
||||
const ADC_SARADC2_ENCAL_REF_ADDR_MSB: u8 = 6;
|
||||
const ADC_SARADC2_ENCAL_REF_ADDR_LSB: u8 = 6;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
|
||||
let pmu = unsafe { &*crate::peripherals::PMU::ptr() };
|
||||
@ -190,10 +192,9 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
let pmu = unsafe { &*crate::peripherals::PMU::ptr() };
|
||||
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
|
||||
|
||||
unsafe {
|
||||
|
@ -45,6 +45,7 @@ use crate::peripherals::EFUSE;
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -52,6 +52,7 @@ use crate::{
|
||||
};
|
||||
|
||||
// https://github.com/espressif/esp-idf/blob/df9310a/components/soc/esp32h2/gpio_periph.c#L42
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 28;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -35,21 +35,33 @@ pub(crate) mod registers {
|
||||
}
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// Default clock source for the timer group (TIMG) peripheral.
|
||||
pub const TIMG_DEFAULT_CLK_SRC: u8 = 2;
|
||||
|
||||
/// Default clock source for the I2S peripheral.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u8 = 1;
|
||||
/// Clock frequency for the I2S peripheral, in Hertz.
|
||||
pub const I2S_SCLK: u32 = 96_000_000;
|
||||
|
||||
/// Start address of the RMT (Remote Control) peripheral's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x60007400;
|
||||
/// Size of the RAM allocated per RMT channel, in bytes.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 48;
|
||||
/// Clock source for the RMT peripheral (false = default source).
|
||||
pub const RMT_CLOCK_SRC: bool = false;
|
||||
/// Frequency of the RMT clock source, in Hertz.
|
||||
pub const RMT_CLOCK_SRC_FREQ: fugit::HertzU32 = fugit::HertzU32::MHz(32);
|
||||
|
||||
/// System clock frequency for the parallel I/O (PARL IO) peripheral, in
|
||||
/// Hertz.
|
||||
pub const PARL_IO_SCLK: u32 = 96_000_000;
|
||||
|
||||
/// Start address of the system's DRAM (low range).
|
||||
pub const SOC_DRAM_LOW: u32 = 0x4080_0000;
|
||||
/// End address of the system's DRAM (high range).
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x4085_0000;
|
||||
|
||||
/// RC FAST Clock value (Hertz).
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500);
|
||||
}
|
||||
|
||||
|
@ -56,6 +56,8 @@ const REGI2C_RTC_WR_CNTL_S: u8 = 24;
|
||||
const REGI2C_RTC_DATA_V: u8 = 0xFF;
|
||||
const REGI2C_RTC_DATA_S: u8 = 16;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
|
||||
let pmu = unsafe { &*crate::peripherals::PMU::ptr() };
|
||||
@ -177,6 +179,7 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
let pcr = unsafe { &*crate::peripherals::PCR::ptr() };
|
||||
|
@ -45,6 +45,7 @@ use crate::peripherals::EFUSE;
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -64,6 +64,7 @@ use crate::{
|
||||
peripherals::GPIO,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 47;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -38,15 +38,19 @@ macro_rules! chip {
|
||||
pub use chip;
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// System clock frequency for the I2S peripheral, in Hertz.
|
||||
pub const I2S_SCLK: u32 = 160_000_000;
|
||||
/// Default clock source for the I2S peripheral.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u32 = 2;
|
||||
|
||||
/// Start address of the RMT (Remote Control) peripheral's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x3f416400;
|
||||
/// Size of the RAM allocated per RMT channel, in bytes.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 64;
|
||||
|
||||
/// Start address of the system's DRAM (low range).
|
||||
pub const SOC_DRAM_LOW: u32 = 0x3FFB_0000;
|
||||
/// End address of the system's DRAM (high range).
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x4000_0000;
|
||||
|
||||
/// Reference clock tick frequency, set to 1 MHz.
|
||||
pub const REF_TICK: fugit::HertzU32 = fugit::HertzU32::MHz(1);
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
//! `4MB`, and `8MB`.
|
||||
const PSRAM_VADDR: u32 = 0x3f500000;
|
||||
|
||||
/// Returns the start address of the PSRAM virtual address space.
|
||||
pub fn psram_vaddr_start() -> usize {
|
||||
PSRAM_VADDR_START
|
||||
}
|
||||
@ -33,10 +34,14 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
/// The total size of the PSRAM in bytes, calculated from the PSRAM size
|
||||
/// constant.
|
||||
pub const PSRAM_BYTES: usize = PSRAM_SIZE as usize * 1024 * 1024;
|
||||
|
||||
/// The start address of the PSRAM virtual address space.
|
||||
pub const PSRAM_VADDR_START: usize = PSRAM_VADDR as usize;
|
||||
|
||||
/// Initialize PSRAM to be used for data.
|
||||
#[cfg(any(feature = "psram-2m", feature = "psram-4m", feature = "psram-8m"))]
|
||||
pub fn init_psram(_peripheral: impl crate::peripheral::Peripheral<P = crate::peripherals::PSRAM>) {
|
||||
#[allow(unused)]
|
||||
|
@ -45,6 +45,8 @@ const I2C_RTC_BBPLL_MASK: u32 = 1 << 17;
|
||||
const I2C_RTC_SAR_MASK: u32 = 1 << 18;
|
||||
const I2C_RTC_BOD_MASK: u32 = 1 << 22;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
let rtc_cntl = unsafe { &*crate::peripherals::RTC_CNTL::ptr() };
|
||||
let dport = unsafe { &*crate::peripherals::SYSTEM::ptr() };
|
||||
@ -157,7 +159,8 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn revert_trng() {
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let dport = unsafe { &*crate::peripherals::SYSTEM::ptr() };
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
let sens = unsafe { &*crate::peripherals::SENS::ptr() };
|
||||
|
@ -42,16 +42,20 @@ use esp32s2 as pac;
|
||||
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// Enum representing the possible wakeup sources for the ULP core.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum UlpCoreWakeupSource {
|
||||
/// Wakeup source from the HP (High Performance) CPU.
|
||||
HpCpu,
|
||||
}
|
||||
|
||||
/// Structure representing the ULP (Ultra-Low Power) core.
|
||||
pub struct UlpCore<'d> {
|
||||
_lp_core: PeripheralRef<'d, crate::soc::peripherals::ULP_RISCV_CORE>,
|
||||
}
|
||||
|
||||
impl<'d> UlpCore<'d> {
|
||||
/// Creates a new instance of the `UlpCore` struct.
|
||||
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::ULP_RISCV_CORE> + 'd) -> Self {
|
||||
crate::into_ref!(lp_core);
|
||||
|
||||
@ -70,6 +74,7 @@ impl<'d> UlpCore<'d> {
|
||||
// ulp_stop();
|
||||
// }
|
||||
|
||||
/// Runs the ULP core with the specified wakeup source.
|
||||
pub fn run(&mut self, wakeup_src: UlpCoreWakeupSource) {
|
||||
ulp_run(wakeup_src);
|
||||
}
|
||||
|
@ -100,14 +100,17 @@ impl<const SIZE: usize> Stack<SIZE> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the length of the stack in bytes.
|
||||
pub const fn len(&self) -> usize {
|
||||
SIZE
|
||||
}
|
||||
|
||||
/// Returns a mutable pointer to the bottom of the stack.
|
||||
pub fn bottom(&mut self) -> *mut u32 {
|
||||
self.mem.as_mut_ptr() as *mut u32
|
||||
}
|
||||
|
||||
/// Returns a mutable pointer to the top of the stack.
|
||||
pub fn top(&mut self) -> *mut u32 {
|
||||
unsafe { self.bottom().add(SIZE / 4) }
|
||||
}
|
||||
@ -132,9 +135,11 @@ impl<'a> Drop for AppCoreGuard<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents errors that can occur while working with the core.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// The core is already running.
|
||||
CoreAlreadyRunning,
|
||||
}
|
||||
|
||||
@ -168,6 +173,7 @@ unsafe fn internal_park_core(core: Cpu) {
|
||||
}
|
||||
|
||||
impl<'d> CpuControl<'d> {
|
||||
/// Creates a new instance of `CpuControl`.
|
||||
pub fn new(cpu_control: impl Peripheral<P = CPU_CTRL> + 'd) -> CpuControl<'d> {
|
||||
crate::into_ref!(cpu_control);
|
||||
|
||||
|
@ -45,6 +45,7 @@ use crate::{analog::adc::Attenuation, peripherals::EFUSE};
|
||||
|
||||
mod fields;
|
||||
|
||||
/// A struct representing the eFuse functionality of the chip.
|
||||
pub struct Efuse;
|
||||
|
||||
impl Efuse {
|
||||
|
@ -52,6 +52,7 @@ use crate::{
|
||||
peripherals::GPIO,
|
||||
};
|
||||
|
||||
/// The total number of GPIO pins available.
|
||||
pub const NUM_PINS: usize = 49;
|
||||
|
||||
pub(crate) const FUNC_IN_SEL_OFFSET: usize = 0;
|
||||
|
@ -39,17 +39,26 @@ macro_rules! chip {
|
||||
pub use chip;
|
||||
|
||||
pub(crate) mod constants {
|
||||
/// The base clock frequency for the I2S peripheral (Hertz).
|
||||
pub const I2S_SCLK: u32 = 160_000_000;
|
||||
/// The default clock source for I2S operations.
|
||||
pub const I2S_DEFAULT_CLK_SRC: u8 = 2;
|
||||
|
||||
/// The starting address of the Remote Control (RMT) module's RAM.
|
||||
pub const RMT_RAM_START: usize = 0x60016800;
|
||||
/// The size, in bytes, of each RMT channel's dedicated RAM.
|
||||
pub const RMT_CHANNEL_RAM_SIZE: usize = 48;
|
||||
/// RMT Clock source value.
|
||||
pub const RMT_CLOCK_SRC: u8 = 1;
|
||||
/// RMT Clock source frequence.
|
||||
pub const RMT_CLOCK_SRC_FREQ: fugit::HertzU32 = fugit::HertzU32::MHz(80);
|
||||
|
||||
/// The lower bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_LOW: u32 = 0x3FC8_8000;
|
||||
/// The upper bound of the system's DRAM (Data RAM) address space.
|
||||
pub const SOC_DRAM_HIGH: u32 = 0x3FD0_0000;
|
||||
|
||||
/// A reference clock tick of 1 MHz.
|
||||
pub const RC_FAST_CLK: fugit::HertzU32 = fugit::HertzU32::kHz(17500);
|
||||
}
|
||||
|
||||
@ -171,6 +180,7 @@ unsafe fn post_init() {
|
||||
Wdt::<TIMG1, crate::Blocking>::set_wdt_enabled(false);
|
||||
}
|
||||
|
||||
/// Write back a specific range of data in the cache.
|
||||
#[doc(hidden)]
|
||||
#[link_section = ".rwtext"]
|
||||
pub unsafe fn cache_writeback_addr(addr: u32, size: u32) {
|
||||
@ -185,6 +195,7 @@ pub unsafe fn cache_writeback_addr(addr: u32, size: u32) {
|
||||
Cache_Resume_DCache_Autoload(autoload);
|
||||
}
|
||||
|
||||
/// Invalidate a specific range of addresses in the cache.
|
||||
#[doc(hidden)]
|
||||
#[link_section = ".rwtext"]
|
||||
pub unsafe fn cache_invalidate_addr(addr: u32, size: u32) {
|
||||
@ -194,6 +205,7 @@ pub unsafe fn cache_invalidate_addr(addr: u32, size: u32) {
|
||||
Cache_Invalidate_Addr(addr, size);
|
||||
}
|
||||
|
||||
/// Get the size of a cache line in the DCache.
|
||||
#[doc(hidden)]
|
||||
#[link_section = ".rwtext"]
|
||||
pub unsafe fn cache_get_dcache_line_size() -> u32 {
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
static mut PSRAM_VADDR: u32 = 0x3C000000;
|
||||
|
||||
/// Returns the start address of the PSRAM virtual address space.
|
||||
pub fn psram_vaddr_start() -> usize {
|
||||
unsafe { PSRAM_VADDR as usize }
|
||||
}
|
||||
@ -42,6 +43,8 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
|
||||
/// The total size of the PSRAM in bytes, calculated from the PSRAM size
|
||||
/// constant.
|
||||
pub const PSRAM_BYTES: usize = PSRAM_SIZE as usize * 1024 * 1024;
|
||||
|
||||
/// Initialize PSRAM to be used for data.
|
||||
@ -862,14 +865,21 @@ pub(crate) mod utils {
|
||||
fn esp_rom_opiflash_pin_config();
|
||||
}
|
||||
|
||||
/// Represents the operational mode registers of an OPI PSRAM.
|
||||
#[derive(Default)]
|
||||
#[repr(C)]
|
||||
struct OpiPsramModeReg {
|
||||
// Mode register 0 (MR0).
|
||||
pub mr0: u8,
|
||||
// Mode register 1 (MR1).
|
||||
pub mr1: u8,
|
||||
// Mode register 2 (MR2).
|
||||
pub mr2: u8,
|
||||
// Mode register 3 (MR3).
|
||||
pub mr3: u8,
|
||||
// Mode register 4 (MR4).
|
||||
pub mr4: u8,
|
||||
// Mode register 8 (MR8).
|
||||
pub mr8: u8,
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,8 @@ const ADC_SARADC_DTEST_RTC_ADDR_LSB: u32 = 0;
|
||||
|
||||
use crate::regi2c_write_mask;
|
||||
|
||||
/// Enable true randomness by enabling the entropy source.
|
||||
/// Blocks `ADC` usage.
|
||||
pub(crate) fn ensure_randomness() {
|
||||
unsafe {
|
||||
let rtc_cntl = &*crate::peripherals::RTC_CNTL::ptr();
|
||||
@ -117,7 +119,8 @@ pub(crate) fn ensure_randomness() {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn revert_trng() {
|
||||
/// Disable true randomness. Unlocks `ADC` peripheral.
|
||||
pub(crate) fn revert_trng() {
|
||||
let system = unsafe { &*crate::peripherals::SYSTEM::ptr() };
|
||||
let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::ptr() };
|
||||
let sens = unsafe { &*crate::peripherals::SENS::ptr() };
|
||||
|
@ -42,16 +42,20 @@ use esp32s3 as pac;
|
||||
|
||||
use crate::peripheral::{Peripheral, PeripheralRef};
|
||||
|
||||
/// Enum representing the possible wakeup sources for the ULP core.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum UlpCoreWakeupSource {
|
||||
/// Wakeup source from the HP (High Performance) CPU.
|
||||
HpCpu,
|
||||
}
|
||||
|
||||
/// Structure representing the ULP (Ultra-Low Power) core.
|
||||
pub struct UlpCore<'d> {
|
||||
_lp_core: PeripheralRef<'d, crate::soc::peripherals::ULP_RISCV_CORE>,
|
||||
}
|
||||
|
||||
impl<'d> UlpCore<'d> {
|
||||
/// Creates a new instance of the `UlpCore` struct.
|
||||
pub fn new(lp_core: impl Peripheral<P = crate::soc::peripherals::ULP_RISCV_CORE> + 'd) -> Self {
|
||||
crate::into_ref!(lp_core);
|
||||
|
||||
@ -66,10 +70,12 @@ impl<'d> UlpCore<'d> {
|
||||
this
|
||||
}
|
||||
|
||||
/// Stops the ULP core.
|
||||
pub fn stop(&mut self) {
|
||||
ulp_stop();
|
||||
}
|
||||
|
||||
/// Runs the ULP core with the specified wakeup source.
|
||||
pub fn run(&mut self, wakeup_src: UlpCoreWakeupSource) {
|
||||
ulp_run(wakeup_src);
|
||||
}
|
||||
|
@ -1,5 +1,3 @@
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use portable_atomic::{AtomicU8, Ordering};
|
||||
|
||||
pub use self::implementation::*;
|
||||
@ -26,8 +24,10 @@ mod efuse_field;
|
||||
static MAC_OVERRIDE_STATE: AtomicU8 = AtomicU8::new(0);
|
||||
static mut MAC_OVERRIDE: [u8; 6] = [0; 6];
|
||||
|
||||
/// Error indicating issues with setting the MAC address.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
pub enum SetMacError {
|
||||
/// The MAC address has already been set and cannot be changed.
|
||||
AlreadySet,
|
||||
}
|
||||
|
||||
|
@ -96,9 +96,14 @@ pub mod prelude {
|
||||
};
|
||||
}
|
||||
|
||||
/// Enumeration of possible SPI interrupt events.
|
||||
#[cfg(not(any(esp32, esp32s2)))]
|
||||
#[derive(EnumSetType)]
|
||||
pub enum SpiInterrupt {
|
||||
/// Indicates that the SPI transaction has completed successfully.
|
||||
///
|
||||
/// This interrupt is triggered when an SPI transaction has finished
|
||||
/// transmitting and receiving data.
|
||||
TransDone,
|
||||
}
|
||||
|
||||
@ -114,26 +119,44 @@ const EMPTY_WRITE_PAD: u8 = 0x00u8;
|
||||
#[allow(unused)]
|
||||
const MAX_DMA_SIZE: usize = 32736;
|
||||
|
||||
/// SPI command, 1 to 16 bits.
|
||||
/// SPI commands, each consisting of a 16-bit command value and a data mode.
|
||||
///
|
||||
/// Used to define specific commands sent over the SPI bus.
|
||||
/// Can be [Command::None] if command phase should be suppressed.
|
||||
pub enum Command {
|
||||
/// No command is sent.
|
||||
None,
|
||||
/// Command1.
|
||||
Command1(u16, SpiDataMode),
|
||||
/// Command2.
|
||||
Command2(u16, SpiDataMode),
|
||||
/// Command3.
|
||||
Command3(u16, SpiDataMode),
|
||||
/// Command4.
|
||||
Command4(u16, SpiDataMode),
|
||||
/// Command5.
|
||||
Command5(u16, SpiDataMode),
|
||||
/// Command6.
|
||||
Command6(u16, SpiDataMode),
|
||||
/// Command7.
|
||||
Command7(u16, SpiDataMode),
|
||||
/// Command8.
|
||||
Command8(u16, SpiDataMode),
|
||||
/// Command9.
|
||||
Command9(u16, SpiDataMode),
|
||||
/// Command10.
|
||||
Command10(u16, SpiDataMode),
|
||||
/// Command11.
|
||||
Command11(u16, SpiDataMode),
|
||||
/// Command12.
|
||||
Command12(u16, SpiDataMode),
|
||||
/// Command13.
|
||||
Command13(u16, SpiDataMode),
|
||||
/// Command14.
|
||||
Command14(u16, SpiDataMode),
|
||||
/// Command15.
|
||||
Command15(u16, SpiDataMode),
|
||||
/// Command16.
|
||||
Command16(u16, SpiDataMode),
|
||||
}
|
||||
|
||||
@ -209,42 +232,76 @@ impl Command {
|
||||
}
|
||||
}
|
||||
|
||||
/// SPI address, 1 to 32 bits.
|
||||
/// SPI address, ranging from 1 to 32 bits, paired with a data mode.
|
||||
///
|
||||
/// This can be used to specify the address phase of SPI transactions.
|
||||
/// Can be [Address::None] if address phase should be suppressed.
|
||||
pub enum Address {
|
||||
/// No address phase.
|
||||
None,
|
||||
/// Address with 1-bit.
|
||||
Address1(u32, SpiDataMode),
|
||||
/// Address with 2-bit.
|
||||
Address2(u32, SpiDataMode),
|
||||
/// Address with 3-bit.
|
||||
Address3(u32, SpiDataMode),
|
||||
/// Address with 4-bit.
|
||||
Address4(u32, SpiDataMode),
|
||||
/// Address with 5-bit.
|
||||
Address5(u32, SpiDataMode),
|
||||
/// Address with 6-bit.
|
||||
Address6(u32, SpiDataMode),
|
||||
/// Address with 7-bit.
|
||||
Address7(u32, SpiDataMode),
|
||||
/// Address with 8-bit.
|
||||
Address8(u32, SpiDataMode),
|
||||
/// Address with 9-bit.
|
||||
Address9(u32, SpiDataMode),
|
||||
/// Address with 10-bit.
|
||||
Address10(u32, SpiDataMode),
|
||||
/// Address with 11-bit.
|
||||
Address11(u32, SpiDataMode),
|
||||
/// Address with 12-bit.
|
||||
Address12(u32, SpiDataMode),
|
||||
/// Address with 13-bit.
|
||||
Address13(u32, SpiDataMode),
|
||||
/// Address with 14-bit.
|
||||
Address14(u32, SpiDataMode),
|
||||
/// Address with 15-bit.
|
||||
Address15(u32, SpiDataMode),
|
||||
/// Address with 16-bit.
|
||||
Address16(u32, SpiDataMode),
|
||||
/// Address with 17-bit.
|
||||
Address17(u32, SpiDataMode),
|
||||
/// Address with 18-bit.
|
||||
Address18(u32, SpiDataMode),
|
||||
/// Address with 19-bit.
|
||||
Address19(u32, SpiDataMode),
|
||||
/// Address with 20-bit.
|
||||
Address20(u32, SpiDataMode),
|
||||
/// Address with 21-bit.
|
||||
Address21(u32, SpiDataMode),
|
||||
/// Address with 22-bit.
|
||||
Address22(u32, SpiDataMode),
|
||||
/// Address with 23-bit.
|
||||
Address23(u32, SpiDataMode),
|
||||
/// Address with 24-bit.
|
||||
Address24(u32, SpiDataMode),
|
||||
/// Address with 25-bit.
|
||||
Address25(u32, SpiDataMode),
|
||||
/// Address with 26-bit.
|
||||
Address26(u32, SpiDataMode),
|
||||
/// Address with 27-bit.
|
||||
Address27(u32, SpiDataMode),
|
||||
/// Address with 28-bit.
|
||||
Address28(u32, SpiDataMode),
|
||||
/// Address with 29-bit.
|
||||
Address29(u32, SpiDataMode),
|
||||
/// Address with 30-bit.
|
||||
Address30(u32, SpiDataMode),
|
||||
/// Address with 31-bit.
|
||||
Address31(u32, SpiDataMode),
|
||||
/// Address with 32-bit.
|
||||
Address32(u32, SpiDataMode),
|
||||
}
|
||||
|
||||
@ -370,6 +427,8 @@ impl Address {
|
||||
|
||||
/// Read and Write in half duplex mode.
|
||||
pub trait HalfDuplexReadWrite {
|
||||
/// The associated error type that will be returned in the event of a
|
||||
/// failure.
|
||||
type Error;
|
||||
|
||||
/// Half-duplex read.
|
||||
@ -457,6 +516,10 @@ where
|
||||
Self::new_internal(spi, frequency, mode, clocks)
|
||||
}
|
||||
|
||||
/// Assign the SCK (Serial Clock) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to push-pull output and connects it to the SPI
|
||||
/// clock signal.
|
||||
pub fn with_sck<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + 'd) -> Self {
|
||||
crate::into_ref!(sck);
|
||||
sck.set_to_push_pull_output(private::Internal);
|
||||
@ -465,6 +528,10 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to push-pull output and connects it to the SPI
|
||||
/// MOSI signal.
|
||||
pub fn with_mosi<MOSI: OutputPin>(self, mosi: impl Peripheral<P = MOSI> + 'd) -> Self {
|
||||
crate::into_ref!(mosi);
|
||||
mosi.set_to_push_pull_output(private::Internal);
|
||||
@ -473,6 +540,9 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the MISO (Master In Slave Out) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to input and connects it to the SPI MISO signal.
|
||||
pub fn with_miso<MISO: InputPin>(self, miso: impl Peripheral<P = MISO> + 'd) -> Self {
|
||||
crate::into_ref!(miso);
|
||||
miso.set_to_input(private::Internal);
|
||||
@ -481,6 +551,10 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the CS (Chip Select) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to push-pull output and connects it to the SPI CS
|
||||
/// signal.
|
||||
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
||||
crate::into_ref!(cs);
|
||||
cs.set_to_push_pull_output(private::Internal);
|
||||
@ -555,6 +629,10 @@ where
|
||||
spi
|
||||
}
|
||||
|
||||
/// Change the bus frequency of the SPI instance.
|
||||
///
|
||||
/// This method allows user to update the bus frequency for the SPI
|
||||
/// communication after the instance has been created.
|
||||
pub fn change_bus_frequency(&mut self, frequency: HertzU32, clocks: &Clocks<'d>) {
|
||||
self.spi.ch_bus_freq(frequency, clocks);
|
||||
}
|
||||
@ -578,6 +656,10 @@ where
|
||||
Self::new_internal(spi, frequency, mode, clocks)
|
||||
}
|
||||
|
||||
/// Assign the SCK (Serial Clock) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to push-pull output and connects it to the SPI
|
||||
/// clock signal.
|
||||
pub fn with_sck<SCK: OutputPin>(self, sck: impl Peripheral<P = SCK> + 'd) -> Self {
|
||||
crate::into_ref!(sck);
|
||||
sck.set_to_push_pull_output(private::Internal);
|
||||
@ -586,6 +668,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the MOSI (Master Out Slave In) pin for the SPI instance in
|
||||
/// half-duplex mode.
|
||||
///
|
||||
/// Enables both input and output functionality for the pin, and connects it
|
||||
/// to the MOSI signal and SIO0 input signal.
|
||||
pub fn with_mosi<MOSI: OutputPin + InputPin>(
|
||||
self,
|
||||
mosi: impl Peripheral<P = MOSI> + 'd,
|
||||
@ -599,6 +686,11 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the MISO (Master In Slave Out) pin for the SPI instance in
|
||||
/// half-duplex mode.
|
||||
///
|
||||
/// Enables both input and output functionality for the pin, and connects it
|
||||
/// to the MISO signal and SIO1 input signal.
|
||||
pub fn with_miso<MISO: OutputPin + InputPin>(
|
||||
self,
|
||||
miso: impl Peripheral<P = MISO> + 'd,
|
||||
@ -612,6 +704,10 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the SIO2 pin for the SPI instance.
|
||||
///
|
||||
/// Enables both input and output functionality for the pin, and connects it
|
||||
/// to the SIO2 output and input signals.
|
||||
pub fn with_sio2<SIO2: OutputPin + InputPin>(
|
||||
self,
|
||||
sio2: impl Peripheral<P = SIO2> + 'd,
|
||||
@ -625,6 +721,10 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the SIO3 pin for the SPI instance.
|
||||
///
|
||||
/// Enables both input and output functionality for the pin, and connects it
|
||||
/// to the SIO3 output and input signals.
|
||||
pub fn with_sio3<SIO3: OutputPin + InputPin>(
|
||||
self,
|
||||
sio3: impl Peripheral<P = SIO3> + 'd,
|
||||
@ -638,6 +738,10 @@ where
|
||||
self
|
||||
}
|
||||
|
||||
/// Assign the CS (Chip Select) pin for the SPI instance.
|
||||
///
|
||||
/// Sets the specified pin to push-pull output and connects it to the SPI CS
|
||||
/// signal.
|
||||
pub fn with_cs<CS: OutputPin>(self, cs: impl Peripheral<P = CS> + 'd) -> Self {
|
||||
crate::into_ref!(cs);
|
||||
cs.set_to_push_pull_output(private::Internal);
|
||||
@ -733,6 +837,10 @@ where
|
||||
spi
|
||||
}
|
||||
|
||||
/// Change the bus frequency of the SPI instance in half-duplex mode.
|
||||
///
|
||||
/// This method allows you to update the bus frequency for the SPI
|
||||
/// communication after the instance has been created.
|
||||
pub fn change_bus_frequency(&mut self, frequency: HertzU32, clocks: &Clocks<'d>) {
|
||||
self.spi.ch_bus_freq(frequency, clocks);
|
||||
}
|
||||
@ -837,6 +945,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA (Direct Memory Access) funtionality (Master).
|
||||
pub mod dma {
|
||||
use core::{
|
||||
cmp::min,
|
||||
@ -868,6 +977,11 @@ pub mod dma {
|
||||
where
|
||||
M: DuplexMode,
|
||||
{
|
||||
/// Configures the SPI instance to use DMA with the specified channel.
|
||||
///
|
||||
/// This method prepares the SPI instance for DMA transfers. It
|
||||
/// initializes the DMA channel for transmission and returns an
|
||||
/// instance of `SpiDma` that supports DMA operations.
|
||||
pub fn with_dma<C, DmaMode>(
|
||||
self,
|
||||
mut channel: Channel<'d, C, DmaMode>,
|
||||
@ -892,6 +1006,11 @@ pub mod dma {
|
||||
where
|
||||
M: DuplexMode,
|
||||
{
|
||||
/// Configures the SPI3 instance to use DMA with the specified channel.
|
||||
///
|
||||
/// This method prepares the SPI instance for DMA transfers using SPI3
|
||||
/// and returns an instance of `SpiDma` that supports DMA
|
||||
/// operations.
|
||||
pub fn with_dma<C, DmaMode>(
|
||||
self,
|
||||
mut channel: Channel<'d, C, DmaMode>,
|
||||
@ -931,6 +1050,10 @@ pub mod dma {
|
||||
M: DuplexMode,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Formats the `SpiDma` instance for debugging purposes.
|
||||
///
|
||||
/// This method returns a debug struct with the name "SpiDma" without
|
||||
/// exposing internal details.
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("SpiDma").finish()
|
||||
}
|
||||
@ -994,6 +1117,7 @@ pub mod dma {
|
||||
M: DuplexMode,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Configures the interrupt handler for the DMA-enabled SPI instance.
|
||||
fn set_interrupt_handler(&mut self, handler: crate::interrupt::InterruptHandler) {
|
||||
SpiDma::set_interrupt_handler(self, handler);
|
||||
}
|
||||
@ -1007,6 +1131,7 @@ pub mod dma {
|
||||
M: DuplexMode,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Changes the SPI bus frequency for the DMA-enabled SPI instance.
|
||||
pub fn change_bus_frequency(&mut self, frequency: HertzU32, clocks: &Clocks<'d>) {
|
||||
self.spi.ch_bus_freq(frequency, clocks);
|
||||
}
|
||||
@ -1018,6 +1143,11 @@ pub mod dma {
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
{
|
||||
/// Configures the DMA buffers for the SPI instance.
|
||||
///
|
||||
/// This method sets up both TX and RX buffers for DMA transfers.
|
||||
/// It returns an instance of `SpiDmaBus` that can be used for SPI
|
||||
/// communication.
|
||||
pub fn with_buffers(
|
||||
self,
|
||||
dma_tx_buf: DmaTxBuf,
|
||||
@ -1034,6 +1164,11 @@ pub mod dma {
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
{
|
||||
/// Configures the DMA buffers for asynchronous SPI communication.
|
||||
///
|
||||
/// This method sets up both TX and RX buffers for DMA transfers.
|
||||
/// It eturns an instance of `SpiDmaAsyncBus` to be used for
|
||||
/// asynchronous SPI operations.
|
||||
pub fn with_buffers(
|
||||
self,
|
||||
dma_tx_buf: DmaTxBuf,
|
||||
@ -1043,6 +1178,10 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// A structure representing a DMA transfer for SPI.
|
||||
///
|
||||
/// This structure holds references to the SPI instance, DMA buffers, and
|
||||
/// transfer status.
|
||||
pub struct SpiDmaTransfer<'d, T, C, M, DmaMode, Buf>
|
||||
where
|
||||
C: DmaChannel,
|
||||
@ -1083,6 +1222,10 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the DMA transfer is complete.
|
||||
///
|
||||
/// This method returns `true` if both TX and RX operations are done,
|
||||
/// and the SPI instance is no longer busy.
|
||||
pub fn is_done(&self) -> bool {
|
||||
if self.is_tx && !self.tx_future_awaited && !self.spi_dma.channel.tx.is_done() {
|
||||
return false;
|
||||
@ -1107,6 +1250,10 @@ pub mod dma {
|
||||
true
|
||||
}
|
||||
|
||||
/// Waits for the DMA transfer to complete.
|
||||
///
|
||||
/// This method blocks until the transfer is finished and returns the
|
||||
/// `SpiDma` instance and the associated buffer.
|
||||
pub fn wait(mut self) -> (SpiDma<'d, T, C, M, DmaMode>, Buf) {
|
||||
self.spi_dma.spi.flush().ok();
|
||||
fence(Ordering::Acquire);
|
||||
@ -1122,6 +1269,9 @@ pub mod dma {
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
/// Waits for the DMA transfer to complete asynchronously.
|
||||
///
|
||||
/// This method awaits the completion of both TX and RX operations.
|
||||
pub async fn wait_for_done(&mut self) {
|
||||
if self.is_tx && !self.tx_future_awaited {
|
||||
let _ = DmaTxFuture::new(&mut self.spi_dma.channel.tx).await;
|
||||
@ -1258,6 +1408,7 @@ pub mod dma {
|
||||
M: IsHalfDuplex,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Perform a half-duplex read operation using DMA.
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[cfg_attr(feature = "place-spi-driver-in-ram", ram)]
|
||||
pub fn read(
|
||||
@ -1335,6 +1486,7 @@ pub mod dma {
|
||||
Ok(SpiDmaTransfer::new(self, buffer, bytes_to_read > 0, false))
|
||||
}
|
||||
|
||||
/// Perform a half-duplex write operation using DMA.
|
||||
#[allow(clippy::type_complexity)]
|
||||
#[cfg_attr(feature = "place-spi-driver-in-ram", ram)]
|
||||
pub fn write(
|
||||
@ -1413,6 +1565,10 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// A DMA-capable SPI bus that handles full-duplex transfers.
|
||||
///
|
||||
/// This structure is responsible for managing SPI transfers using DMA
|
||||
/// buffers.
|
||||
pub struct SpiDmaBus<'d, T, C>
|
||||
where
|
||||
T: InstanceDma,
|
||||
@ -1429,6 +1585,8 @@ pub mod dma {
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
{
|
||||
/// Creates a new `SpiDmaBus` with the specified SPI instance and DMA
|
||||
/// buffers.
|
||||
pub fn new(
|
||||
spi_dma: SpiDma<'d, T, C, FullDuplexMode, crate::Blocking>,
|
||||
tx_buffer: DmaTxBuf,
|
||||
@ -1440,6 +1598,7 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads data from the SPI bus using DMA.
|
||||
pub fn read(&mut self, words: &mut [u8]) -> Result<(), Error> {
|
||||
let mut spi_dma = self.spi_dma.take().unwrap();
|
||||
let (tx_buf, mut rx_buf) = self.buffers.take().unwrap();
|
||||
@ -1467,6 +1626,7 @@ pub mod dma {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Writes data to the SPI bus using DMA.
|
||||
pub fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
||||
let mut spi_dma = self.spi_dma.take().unwrap();
|
||||
let (mut tx_buf, rx_buf) = self.buffers.take().unwrap();
|
||||
@ -1491,6 +1651,7 @@ pub mod dma {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Transfers data to and from the SPI bus simultaneously using DMA.
|
||||
pub fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Error> {
|
||||
let mut spi_dma = self.spi_dma.take().unwrap();
|
||||
let (mut tx_buf, mut rx_buf) = self.buffers.take().unwrap();
|
||||
@ -1534,6 +1695,7 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Transfers data in place on the SPI bus using DMA.
|
||||
pub fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Error> {
|
||||
let mut spi_dma = self.spi_dma.take().unwrap();
|
||||
let (mut tx_buf, mut rx_buf) = self.buffers.take().unwrap();
|
||||
@ -1595,6 +1757,7 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Async functionality
|
||||
#[cfg(feature = "async")]
|
||||
pub mod asynch {
|
||||
use core::{cmp::min, mem::take};
|
||||
@ -1630,6 +1793,10 @@ pub mod dma {
|
||||
InUse,
|
||||
}
|
||||
|
||||
/// An asynchronous DMA-capable SPI bus for full-duplex operations.
|
||||
///
|
||||
/// This struct provides an interface for SPI operations using DMA in an
|
||||
/// asynchronous way.
|
||||
pub struct SpiDmaAsyncBus<'d, T, C>
|
||||
where
|
||||
T: InstanceDma,
|
||||
@ -1645,6 +1812,10 @@ pub mod dma {
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
{
|
||||
/// Creates a new asynchronous DMA SPI bus instance.
|
||||
///
|
||||
/// Initializes the bus with the provided SPI instance and DMA
|
||||
/// buffers for transmit and receive operations.
|
||||
pub fn new(
|
||||
spi: SpiDma<'d, T, C, FullDuplexMode, crate::Async>,
|
||||
dma_tx_buf: DmaTxBuf,
|
||||
@ -1655,6 +1826,8 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Waits for the current SPI DMA transfer to complete, ensuring the
|
||||
/// bus is idle.
|
||||
async fn wait_for_idle(
|
||||
&mut self,
|
||||
) -> (
|
||||
@ -1703,6 +1876,8 @@ pub mod dma {
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
{
|
||||
/// Asynchronously reads data from the SPI bus into the provided
|
||||
/// buffer.
|
||||
async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
// Get previous transfer.
|
||||
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle().await;
|
||||
@ -1741,6 +1916,8 @@ pub mod dma {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asynchronously writes data to the SPI bus from the provided
|
||||
/// buffer.
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
// Get previous transfer.
|
||||
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle().await;
|
||||
@ -1777,6 +1954,12 @@ pub mod dma {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Asynchronously performs a full-duplex transfer over the SPI bus.
|
||||
///
|
||||
/// This method splits the transfer operation into chunks and
|
||||
/// processes it asynchronously. It simultaneously
|
||||
/// writes data from the `write` buffer and reads data into the
|
||||
/// `read` buffer.
|
||||
async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
|
||||
// Get previous transfer.
|
||||
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle().await;
|
||||
@ -1832,6 +2015,8 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
/// Asynchronously performs an in-place full-duplex transfer over
|
||||
/// the SPI bus.
|
||||
async fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
// Get previous transfer.
|
||||
let (mut spi_dma, mut tx_buf, mut rx_buf) = self.wait_for_idle().await;
|
||||
|
@ -9,8 +9,6 @@
|
||||
//! more information on these modes, please refer to the documentation in their
|
||||
//! respective modules.
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use crate::dma::DmaError;
|
||||
|
||||
pub mod master;
|
||||
@ -21,10 +19,17 @@ pub mod slave;
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// Error occurred due to a DMA-related issue.
|
||||
DmaError(DmaError),
|
||||
/// Error indicating that the maximum DMA transfer size was exceeded.
|
||||
MaxDmaTransferSizeExceeded,
|
||||
/// Error indicating that the FIFO size was exceeded during SPI
|
||||
/// communication.
|
||||
FifoSizeExeeded,
|
||||
/// Error indicating that the operation is unsupported by the current
|
||||
/// implementation.
|
||||
Unsupported,
|
||||
/// An unknown error occurred during SPI communication.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
@ -41,13 +46,25 @@ impl embedded_hal::spi::Error for Error {
|
||||
}
|
||||
}
|
||||
|
||||
/// SPI modes
|
||||
/// SPI communication modes, defined by clock polarity (CPOL) and clock phase
|
||||
/// (CPHA).
|
||||
///
|
||||
/// These modes control the clock signal's idle state and when data is sampled
|
||||
/// and shifted.
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SpiMode {
|
||||
/// Mode 0 (CPOL = 0, CPHA = 0): Clock is low when idle, data is captured on
|
||||
/// the rising edge and propagated on the falling edge.
|
||||
Mode0,
|
||||
/// Mode 1 (CPOL = 0, CPHA = 1): Clock is low when idle, data is captured on
|
||||
/// the falling edge and propagated on the rising edge.
|
||||
Mode1,
|
||||
/// Mode 2 (CPOL = 1, CPHA = 0): Clock is high when idle, data is captured
|
||||
/// on the falling edge and propagated on the rising edge.
|
||||
Mode2,
|
||||
/// Mode 3 (CPOL = 1, CPHA = 1): Clock is high when idle, data is captured
|
||||
/// on the rising edge and propagated on the falling edge.
|
||||
Mode3,
|
||||
}
|
||||
|
||||
@ -55,24 +72,28 @@ pub enum SpiMode {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SpiBitOrder {
|
||||
/// Most Significant Bit (MSB) is transmitted first.
|
||||
MSBFirst,
|
||||
/// Least Significant Bit (LSB) is transmitted first.
|
||||
LSBFirst,
|
||||
}
|
||||
|
||||
/// Trait marker for defining SPI duplex modes.
|
||||
pub trait DuplexMode {}
|
||||
/// Trait marker for SPI full-duplex mode.
|
||||
pub trait IsFullDuplex: DuplexMode {}
|
||||
/// Trait marker for SPI half-duplex mode.
|
||||
pub trait IsHalfDuplex: DuplexMode {}
|
||||
|
||||
/// SPI data mode
|
||||
///
|
||||
/// Single = 1 bit, 2 wires
|
||||
/// Dual = 2 bit, 2 wires
|
||||
/// Quad = 4 bit, 4 wires
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum SpiDataMode {
|
||||
/// `Single` Data Mode - 1 bit, 2 wires.
|
||||
Single,
|
||||
/// `Dual` Data Mode - 2 bit, 2 wires
|
||||
Dual,
|
||||
/// `Quad` Data Mode - 4 bit, 4 wires
|
||||
Quad,
|
||||
}
|
||||
|
||||
|
@ -143,6 +143,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// DMA (Direct Memory Access) funtionality (Slave).
|
||||
pub mod dma {
|
||||
use super::*;
|
||||
#[cfg(spi3)]
|
||||
@ -169,12 +170,15 @@ pub mod dma {
|
||||
Mode,
|
||||
};
|
||||
|
||||
/// Trait for configuring DMA with SPI2 peripherals in slave mode.
|
||||
pub trait WithDmaSpi2<'d, C, DmaMode>
|
||||
where
|
||||
C: DmaChannel,
|
||||
C::P: SpiPeripheral,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Configures the SPI2 peripheral with the provided DMA channel and
|
||||
/// descriptors.
|
||||
fn with_dma(
|
||||
self,
|
||||
channel: Channel<'d, C, DmaMode>,
|
||||
@ -183,6 +187,7 @@ pub mod dma {
|
||||
) -> SpiDma<'d, crate::peripherals::SPI2, C, DmaMode>;
|
||||
}
|
||||
|
||||
/// Trait for configuring DMA with SPI3 peripherals in slave mode.
|
||||
#[cfg(spi3)]
|
||||
pub trait WithDmaSpi3<'d, C, DmaMode>
|
||||
where
|
||||
@ -190,6 +195,8 @@ pub mod dma {
|
||||
C::P: SpiPeripheral,
|
||||
DmaMode: Mode,
|
||||
{
|
||||
/// Configures the SPI3 peripheral with the provided DMA channel and
|
||||
/// descriptors.
|
||||
fn with_dma(
|
||||
self,
|
||||
channel: Channel<'d, C, DmaMode>,
|
||||
|
@ -29,8 +29,6 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use crate::{
|
||||
interrupt::InterruptHandler,
|
||||
peripheral::PeripheralRef,
|
||||
@ -38,72 +36,109 @@ use crate::{
|
||||
InterruptConfigurable,
|
||||
};
|
||||
|
||||
/// Peripherals which can be enabled via `PeripheralClockControl`
|
||||
/// Peripherals which can be enabled via `PeripheralClockControl`.
|
||||
///
|
||||
/// This enum represents various hardware peripherals that can be enabled
|
||||
/// by the system's clock control. Depending on the target device, different
|
||||
/// peripherals will be available for enabling.
|
||||
pub enum Peripheral {
|
||||
/// SPI2 peripheral.
|
||||
#[cfg(spi2)]
|
||||
Spi2,
|
||||
/// SPI3 peripheral.
|
||||
#[cfg(spi3)]
|
||||
Spi3,
|
||||
/// External I2C0 peripheral.
|
||||
#[cfg(i2c0)]
|
||||
I2cExt0,
|
||||
/// External I2C1 peripheral.
|
||||
#[cfg(i2c1)]
|
||||
I2cExt1,
|
||||
/// RMT peripheral (Remote Control).
|
||||
#[cfg(rmt)]
|
||||
Rmt,
|
||||
/// LEDC peripheral (LED PWM Controller).
|
||||
#[cfg(ledc)]
|
||||
Ledc,
|
||||
/// MCPWM0 peripheral (Motor Control PWM 0).
|
||||
#[cfg(mcpwm0)]
|
||||
Mcpwm0,
|
||||
/// MCPWM1 peripheral (Motor Control PWM 1).
|
||||
#[cfg(mcpwm1)]
|
||||
Mcpwm1,
|
||||
/// PCNT peripheral (Pulse Counter).
|
||||
#[cfg(pcnt)]
|
||||
Pcnt,
|
||||
/// APB SAR ADC peripheral.
|
||||
#[cfg(apb_saradc)]
|
||||
ApbSarAdc,
|
||||
/// General DMA (GDMA) peripheral.
|
||||
#[cfg(gdma)]
|
||||
Gdma,
|
||||
/// Peripheral DMA (PDMA) peripheral.
|
||||
#[cfg(pdma)]
|
||||
Dma,
|
||||
/// I2S0 peripheral (Inter-IC Sound).
|
||||
#[cfg(i2s0)]
|
||||
I2s0,
|
||||
/// I2S1 peripheral (Inter-IC Sound).
|
||||
#[cfg(i2s1)]
|
||||
I2s1,
|
||||
/// USB0 peripheral.
|
||||
#[cfg(usb0)]
|
||||
Usb,
|
||||
/// AES peripheral (Advanced Encryption Standard).
|
||||
#[cfg(aes)]
|
||||
Aes,
|
||||
/// TWAI0 peripheral.
|
||||
#[cfg(twai0)]
|
||||
Twai0,
|
||||
/// TWAI1 peripheral.
|
||||
#[cfg(twai1)]
|
||||
Twai1,
|
||||
/// Timer Group 0 peripheral.
|
||||
#[cfg(timg0)]
|
||||
Timg0,
|
||||
/// Timer Group 1 peripheral.
|
||||
#[cfg(timg1)]
|
||||
Timg1,
|
||||
/// Low-power watchdog timer (WDT) peripheral.
|
||||
#[cfg(lp_wdt)]
|
||||
Wdt,
|
||||
/// SHA peripheral (Secure Hash Algorithm).
|
||||
#[cfg(sha)]
|
||||
Sha,
|
||||
/// USB Device peripheral.
|
||||
#[cfg(usb_device)]
|
||||
UsbDevice,
|
||||
/// UART0 peripheral.
|
||||
#[cfg(uart0)]
|
||||
Uart0,
|
||||
/// UART1 peripheral.
|
||||
#[cfg(uart1)]
|
||||
Uart1,
|
||||
/// UART2 peripheral.
|
||||
#[cfg(uart2)]
|
||||
Uart2,
|
||||
/// RSA peripheral (Rivest-Shamir-Adleman encryption).
|
||||
#[cfg(rsa)]
|
||||
Rsa,
|
||||
/// Parallel IO peripheral.
|
||||
#[cfg(parl_io)]
|
||||
ParlIo,
|
||||
/// HMAC peripheral (Hash-based Message Authentication Code).
|
||||
#[cfg(hmac)]
|
||||
Hmac,
|
||||
/// ECC peripheral (Elliptic Curve Cryptography).
|
||||
#[cfg(ecc)]
|
||||
Ecc,
|
||||
/// SOC ETM peripheral (Event Task Manager).
|
||||
#[cfg(soc_etm)]
|
||||
Etm,
|
||||
/// TRACE0 peripheral (Debug trace).
|
||||
#[cfg(trace0)]
|
||||
Trace0,
|
||||
/// LCD Camera peripheral.
|
||||
#[cfg(lcd_cam)]
|
||||
LcdCam,
|
||||
}
|
||||
@ -111,8 +146,11 @@ pub enum Peripheral {
|
||||
/// The `DPORT`/`PCR`/`SYSTEM` peripheral split into its different logical
|
||||
/// components.
|
||||
pub struct SystemControl<'d> {
|
||||
/// Inner reference to the SYSTEM peripheral.
|
||||
_inner: PeripheralRef<'d, SYSTEM>,
|
||||
/// Controls the system's clock settings and configurations.
|
||||
pub clock_control: SystemClockControl,
|
||||
/// Controls the system's software interrupt settings.
|
||||
pub software_interrupt_control: SoftwareInterruptControl,
|
||||
}
|
||||
|
||||
@ -244,6 +282,10 @@ impl<const NUM: u8> InterruptConfigurable for SoftwareInterrupt<NUM> {
|
||||
}
|
||||
|
||||
/// This gives access to the available software interrupts.
|
||||
///
|
||||
/// This struct contains several instances of software interrupts that can be
|
||||
/// used for signaling between different parts of a program or system. Each
|
||||
/// interrupt is identified by an index (0 to 3).
|
||||
#[cfg_attr(
|
||||
multi_core,
|
||||
doc = r#"
|
||||
@ -253,9 +295,14 @@ feature is enabled."#
|
||||
)]
|
||||
#[non_exhaustive]
|
||||
pub struct SoftwareInterruptControl {
|
||||
/// Software interrupt 0.
|
||||
pub software_interrupt0: SoftwareInterrupt<0>,
|
||||
/// Software interrupt 1.
|
||||
pub software_interrupt1: SoftwareInterrupt<1>,
|
||||
/// Software interrupt 2.
|
||||
pub software_interrupt2: SoftwareInterrupt<2>,
|
||||
/// Software interrupt 3 (only available when not running on a multi-core
|
||||
/// system with the `embassy` feature enabled).
|
||||
#[cfg(not(all(feature = "embassy", multi_core)))]
|
||||
pub software_interrupt3: SoftwareInterrupt<3>,
|
||||
}
|
||||
@ -1117,6 +1164,7 @@ pub struct SystemClockControl {
|
||||
}
|
||||
|
||||
impl SystemClockControl {
|
||||
/// Creates new instance of `SystemClockControl`.
|
||||
pub fn new() -> Self {
|
||||
Self { _private: () }
|
||||
}
|
||||
@ -1142,12 +1190,16 @@ impl crate::private::Sealed for SystemClockControl {}
|
||||
/// Enumeration of the available radio peripherals for this chip.
|
||||
#[cfg(any(bt, ieee802154, wifi))]
|
||||
pub enum RadioPeripherals {
|
||||
/// Represents the PHY (Physical Layer) peripheral.
|
||||
#[cfg(phy)]
|
||||
Phy,
|
||||
/// Represents the Bluetooth peripheral.
|
||||
#[cfg(bt)]
|
||||
Bt,
|
||||
/// Represents the WiFi peripheral.
|
||||
#[cfg(wifi)]
|
||||
Wifi,
|
||||
/// Represents the IEEE 802.15.4 peripheral.
|
||||
#[cfg(ieee802154)]
|
||||
Ieee802154,
|
||||
}
|
||||
@ -1170,5 +1222,6 @@ pub trait RadioClockController {
|
||||
/// Initialize BLE RTC clocks
|
||||
fn ble_rtc_clk_init(&mut self);
|
||||
|
||||
/// Reset the Resolvable Private Address (RPA).
|
||||
fn reset_rpa(&mut self);
|
||||
}
|
||||
|
@ -364,17 +364,22 @@ impl<'d, T> embedded_hal_02::timer::Periodic for PeriodicTimer<'d, T> where T: T
|
||||
/// A type-erased timer
|
||||
///
|
||||
/// You can create an instance of this by just calling `.into()` on a timer.
|
||||
#[allow(missing_docs)]
|
||||
pub enum ErasedTimer {
|
||||
/// Timer 0 of the TIMG0 peripheral in blocking mode.
|
||||
Timg0Timer0(timg::Timer<timg::Timer0<crate::peripherals::TIMG0>, Blocking>),
|
||||
/// Timer 1 of the TIMG0 peripheral in blocking mode.
|
||||
#[cfg(timg_timer1)]
|
||||
Timg0Timer1(timg::Timer<timg::Timer1<crate::peripherals::TIMG0>, Blocking>),
|
||||
/// Timer 0 of the TIMG1 peripheral in blocking mode.
|
||||
#[cfg(timg1)]
|
||||
Timg1Timer0(timg::Timer<timg::Timer0<crate::peripherals::TIMG1>, Blocking>),
|
||||
/// Timer 1 of the TIMG1 peripheral in blocking mode.
|
||||
#[cfg(all(timg1, timg_timer1))]
|
||||
Timg1Timer1(timg::Timer<timg::Timer1<crate::peripherals::TIMG1>, Blocking>),
|
||||
/// Systimer Alarm in periodic mode with blocking behavior.
|
||||
#[cfg(systimer)]
|
||||
SystimerAlarmPeriodic(systimer::Alarm<'static, systimer::Periodic, Blocking>),
|
||||
/// Systimer Target in periodic mode with blocking behavior.
|
||||
#[cfg(systimer)]
|
||||
SystimerAlarmTarget(systimer::Alarm<'static, systimer::Target, Blocking>),
|
||||
}
|
||||
|
@ -14,8 +14,15 @@
|
||||
use super::{ExtendedId, StandardId};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// Represents the type of filtering to be applied to incoming TWAI frames.
|
||||
pub enum FilterType {
|
||||
/// Uses the acceptance code and mask to define a single filter, which
|
||||
/// allows for the first two data bytes of a standard frame to be filtered,
|
||||
/// or the entirety of an extended frame's 29-bit ID.
|
||||
Single,
|
||||
/// Uses the acceptance code and mask to define two separate filters
|
||||
/// allowing for increased flexibility of ID's to accept, but does not allow
|
||||
/// for all 29-bits of an extended ID to be filtered.
|
||||
Dual,
|
||||
}
|
||||
|
||||
@ -32,6 +39,7 @@ pub enum FilterType {
|
||||
pub trait Filter {
|
||||
/// The type of the filter.
|
||||
const FILTER_TYPE: FilterType;
|
||||
/// Returns filter type.
|
||||
fn filter_type(&self) -> FilterType {
|
||||
Self::FILTER_TYPE
|
||||
}
|
||||
@ -40,6 +48,7 @@ pub trait Filter {
|
||||
fn to_registers(&self) -> [u8; 8];
|
||||
}
|
||||
|
||||
/// A type representing the bitmask used to filter incoming TWAI frames.
|
||||
pub type BitFilter<const N: usize> = [u8; N];
|
||||
|
||||
// Convert a byte from a bytestring into a bit inside a given code and mask.
|
||||
|
@ -14,7 +14,7 @@
|
||||
//! up the timing parameters, configuring acceptance filters, handling
|
||||
//! interrupts, and transmitting/receiving messages on the TWAI bus.
|
||||
//!
|
||||
//! This driver manages the ISO 11898-1 (CAN Specification 2.0) compatible TWAI
|
||||
//! This driver manages the ISO 11898-1 compatible TWAI
|
||||
//! controllers. It supports Standard Frame Format (11-bit) and Extended Frame
|
||||
//! Format (29-bit) frame identifiers.
|
||||
//!
|
||||
@ -34,13 +34,13 @@
|
||||
//! # use core::option::Option::None;
|
||||
//! # use nb::block;
|
||||
//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
//! // Use GPIO pins 2 and 3 to connect to the respective pins on the CAN
|
||||
//! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI
|
||||
//! // transceiver.
|
||||
//! let can_tx_pin = io.pins.gpio2;
|
||||
//! let can_rx_pin = io.pins.gpio3;
|
||||
//!
|
||||
//! // The speed of the CAN bus.
|
||||
//! const CAN_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
|
||||
//! // The speed of the TWAI bus.
|
||||
//! const TWAI_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
|
||||
//!
|
||||
//! // Begin configuring the TWAI peripheral. The peripheral is in a reset like
|
||||
//! // state that prevents transmission but allows configuration.
|
||||
@ -49,7 +49,7 @@
|
||||
//! can_tx_pin,
|
||||
//! can_rx_pin,
|
||||
//! &clocks,
|
||||
//! CAN_BAUDRATE,
|
||||
//! TWAI_BAUDRATE,
|
||||
//! TwaiMode::Normal
|
||||
//! );
|
||||
//!
|
||||
@ -90,13 +90,13 @@
|
||||
//! # use core::option::Option::None;
|
||||
//! # use nb::block;
|
||||
//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||
//! // Use GPIO pins 2 and 3 to connect to the respective pins on the CAN
|
||||
//! // Use GPIO pins 2 and 3 to connect to the respective pins on the TWAI
|
||||
//! // transceiver.
|
||||
//! let can_tx_pin = io.pins.gpio2;
|
||||
//! let can_rx_pin = io.pins.gpio3;
|
||||
//!
|
||||
//! // The speed of the CAN bus.
|
||||
//! const CAN_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
|
||||
//! // The speed of the TWAI bus.
|
||||
//! const TWAI_BAUDRATE: twai::BaudRate = BaudRate::B1000K;
|
||||
//!
|
||||
//! // Begin configuring the TWAI peripheral.
|
||||
//! let mut can_config = twai::TwaiConfiguration::new(
|
||||
@ -104,7 +104,7 @@
|
||||
//! can_tx_pin,
|
||||
//! can_rx_pin,
|
||||
//! &clocks,
|
||||
//! CAN_BAUDRATE,
|
||||
//! TWAI_BAUDRATE,
|
||||
//! TwaiMode::SelfTest
|
||||
//! );
|
||||
//!
|
||||
@ -129,8 +129,6 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use self::filter::{Filter, FilterType};
|
||||
@ -146,12 +144,12 @@ use crate::{
|
||||
|
||||
pub mod filter;
|
||||
|
||||
/// CAN error kind
|
||||
/// TWAI error kind
|
||||
///
|
||||
/// This represents a common set of CAN operation errors. HAL implementations
|
||||
/// This represents a common set of TWAI operation errors. HAL implementations
|
||||
/// are free to define more specific or additional error types. However, by
|
||||
/// providing a mapping to these common CAN errors, generic code can still react
|
||||
/// to them.
|
||||
/// providing a mapping to these common TWAI errors, generic code can still
|
||||
/// react to them.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum ErrorKind {
|
||||
@ -256,15 +254,15 @@ pub enum TwaiMode {
|
||||
ListenOnly,
|
||||
}
|
||||
|
||||
/// Standard 11-bit CAN Identifier (`0..=0x7FF`).
|
||||
/// Standard 11-bit TWAI Identifier (`0..=0x7FF`).
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct StandardId(u16);
|
||||
|
||||
impl StandardId {
|
||||
/// CAN ID `0`, the highest priority.
|
||||
/// TWAI ID `0`, the highest priority.
|
||||
pub const ZERO: Self = StandardId(0);
|
||||
|
||||
/// CAN ID `0x7FF`, the lowest priority.
|
||||
/// TWAI ID `0x7FF`, the lowest priority.
|
||||
pub const MAX: Self = StandardId(0x7FF);
|
||||
|
||||
/// Tries to create a `StandardId` from a raw 16-bit integer.
|
||||
@ -290,7 +288,7 @@ impl StandardId {
|
||||
StandardId(raw)
|
||||
}
|
||||
|
||||
/// Returns this CAN Identifier as a raw 16-bit integer.
|
||||
/// Returns TWAI Identifier as a raw 16-bit integer.
|
||||
#[inline]
|
||||
pub fn as_raw(&self) -> u16 {
|
||||
self.0
|
||||
@ -325,15 +323,15 @@ impl From<embedded_can::StandardId> for StandardId {
|
||||
}
|
||||
}
|
||||
|
||||
/// Extended 29-bit CAN Identifier (`0..=1FFF_FFFF`).
|
||||
/// Extended 29-bit TWAI Identifier (`0..=1FFF_FFFF`).
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct ExtendedId(u32);
|
||||
|
||||
impl ExtendedId {
|
||||
/// CAN ID `0`, the highest priority.
|
||||
/// TWAI ID `0`, the highest priority.
|
||||
pub const ZERO: Self = ExtendedId(0);
|
||||
|
||||
/// CAN ID `0x1FFFFFFF`, the lowest priority.
|
||||
/// TWAI ID `0x1FFFFFFF`, the lowest priority.
|
||||
pub const MAX: Self = ExtendedId(0x1FFF_FFFF);
|
||||
|
||||
/// Tries to create a `ExtendedId` from a raw 32-bit integer.
|
||||
@ -359,7 +357,7 @@ impl ExtendedId {
|
||||
ExtendedId(raw)
|
||||
}
|
||||
|
||||
/// Returns this CAN Identifier as a raw 32-bit integer.
|
||||
/// Returns TWAI Identifier as a raw 32-bit integer.
|
||||
#[inline]
|
||||
pub fn as_raw(&self) -> u32 {
|
||||
self.0
|
||||
@ -400,7 +398,7 @@ impl From<embedded_can::ExtendedId> for ExtendedId {
|
||||
}
|
||||
}
|
||||
|
||||
/// A CAN Identifier (standard or extended).
|
||||
/// A TWAI Identifier (standard or extended).
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum Id {
|
||||
/// Standard 11-bit Identifier (`0..=0x7FF`).
|
||||
@ -474,8 +472,9 @@ pub struct EspTwaiFrame {
|
||||
}
|
||||
|
||||
impl EspTwaiFrame {
|
||||
/// Creates a new `EspTwaiFrame` with the specified ID and data payload.
|
||||
pub fn new(id: Id, data: &[u8]) -> Option<Self> {
|
||||
// CAN2.0 frames cannot contain more than 8 bytes of data.
|
||||
// TWAI frames cannot contain more than 8 bytes of data.
|
||||
if data.len() > 8 {
|
||||
return None;
|
||||
}
|
||||
@ -493,8 +492,10 @@ impl EspTwaiFrame {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `EspTwaiFrame` for a transmission request with the
|
||||
/// specified ID and data length (DLC).
|
||||
pub fn new_remote(id: Id, dlc: usize) -> Option<Self> {
|
||||
// CAN2.0 frames cannot have more than 8 bytes.
|
||||
// TWAI frames cannot have more than 8 bytes.
|
||||
if dlc > 8 {
|
||||
return None;
|
||||
}
|
||||
@ -508,6 +509,8 @@ impl EspTwaiFrame {
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a new `EspTwaiFrame` ready for self-reception with the specified
|
||||
/// ID and data payload.
|
||||
pub fn new_self_reception(id: Id, data: &[u8]) -> Option<Self> {
|
||||
if data.len() > 8 {
|
||||
return None;
|
||||
@ -635,10 +638,23 @@ impl embedded_can::Frame for EspTwaiFrame {
|
||||
|
||||
/// The underlying timings for the TWAI peripheral.
|
||||
pub struct TimingConfig {
|
||||
/// The baudrate prescaler is used to determine the period of each time
|
||||
/// quantum by dividing the TWAI controller's source clock.
|
||||
pub baud_rate_prescaler: u16,
|
||||
|
||||
/// The synchronization jump width is used to determine the maximum number
|
||||
/// of time quanta a single bit time can be lengthened/shortened for
|
||||
/// synchronization purposes.
|
||||
pub sync_jump_width: u8,
|
||||
|
||||
/// Timing segment 1 consists of 1 to 16 time quanta before sample point.
|
||||
pub tseg_1: u8,
|
||||
|
||||
/// Timing Segment 2 consists of 1 to 8 time quanta after sample point.
|
||||
pub tseg_2: u8,
|
||||
|
||||
/// Enabling triple sampling causes 3 time quanta to be sampled per bit
|
||||
/// instead of 1.
|
||||
pub triple_sample: bool,
|
||||
}
|
||||
|
||||
@ -646,33 +662,24 @@ pub struct TimingConfig {
|
||||
/// Currently these timings are sourced from the ESP IDF C driver which assumes
|
||||
/// an APB clock of 80MHz.
|
||||
pub enum BaudRate {
|
||||
/// A baud rate of 125 Kbps.
|
||||
B125K,
|
||||
/// A baud rate of 250 Kbps.
|
||||
B250K,
|
||||
/// A baud rate of 500 Kbps.
|
||||
B500K,
|
||||
/// A baud rate of 1 Mbps.
|
||||
B1000K,
|
||||
/// A custom baud rate defined by the user.
|
||||
///
|
||||
/// This variant allows users to specify their own timing configuration
|
||||
/// using a `TimingConfig` struct.
|
||||
Custom(TimingConfig),
|
||||
}
|
||||
|
||||
impl BaudRate {
|
||||
/// Convert the BaudRate into the timings that the peripheral needs.
|
||||
// These timings are copied from the ESP IDF C driver.
|
||||
// #define TWAI_TIMING_CONFIG_25KBITS() {.brp = 128, .tseg_1 = 16, .tseg_2 =
|
||||
// 8, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_50KBITS() {.brp = 80, .tseg_1 = 15, .tseg_2 =
|
||||
// 4, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_100KBITS() {.brp = 40, .tseg_1 = 15, .tseg_2 =
|
||||
// 4, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_125KBITS() {.brp = 32, .tseg_1 = 15, .tseg_2 =
|
||||
// 4, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_250KBITS() {.brp = 16, .tseg_1 = 15, .tseg_2 =
|
||||
// 4, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_500KBITS() {.brp = 8, .tseg_1 = 15, .tseg_2 = 4,
|
||||
// .sjw = 3, .triple_sampling = false} #define TWAI_TIMING_CONFIG_800KBITS()
|
||||
// {.brp = 4, .tseg_1 = 16, .tseg_2 = 8, .sjw = 3, .triple_sampling = false}
|
||||
// #define TWAI_TIMING_CONFIG_1MBITS() {.brp = 4, .tseg_1 = 15, .tseg_2 = 4,
|
||||
// .sjw = 3, .triple_sampling = false}
|
||||
//
|
||||
// see https://github.com/espressif/esp-idf/tree/master/components/hal/include/hal/twai_types.h
|
||||
// See: https://github.com/espressif/esp-idf/tree/master/components/hal/include/hal/twai_types.h
|
||||
const fn timing(self) -> TimingConfig {
|
||||
#[allow(unused_mut)]
|
||||
let mut timing = match self {
|
||||
@ -1024,10 +1031,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of the receive error counter.
|
||||
pub fn receive_error_count(&self) -> u8 {
|
||||
T::register_block().rx_err_cnt().read().rx_err_cnt().bits()
|
||||
}
|
||||
|
||||
/// Returns the value of the transmit error counter.
|
||||
pub fn transmit_error_count(&self) -> u8 {
|
||||
T::register_block().tx_err_cnt().read().tx_err_cnt().bits()
|
||||
}
|
||||
@ -1067,10 +1076,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Sends the specified `EspTwaiFrame` over the TWAI bus.
|
||||
pub fn transmit(&mut self, frame: &EspTwaiFrame) -> nb::Result<(), EspTwaiError> {
|
||||
self.tx.transmit(frame)
|
||||
}
|
||||
|
||||
/// Receives a TWAI frame from the TWAI bus.
|
||||
pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
|
||||
self.rx.receive()
|
||||
}
|
||||
@ -1082,7 +1093,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Interface to the CAN transmitter part.
|
||||
/// Interface to the TWAI transmitter part.
|
||||
pub struct TwaiTx<'d, T, DM: crate::Mode> {
|
||||
_peripheral: PhantomData<&'d T>,
|
||||
phantom: PhantomData<DM>,
|
||||
@ -1124,7 +1135,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Interface to the CAN receiver part.
|
||||
/// Interface to the TWAI receiver part.
|
||||
pub struct TwaiRx<'d, T, DM: crate::Mode> {
|
||||
_peripheral: PhantomData<&'d T>,
|
||||
phantom: PhantomData<DM>,
|
||||
@ -1135,7 +1146,7 @@ where
|
||||
T: OperationInstance,
|
||||
DM: crate::Mode,
|
||||
{
|
||||
// Receive a frame
|
||||
/// Receive a frame
|
||||
pub fn receive(&mut self) -> nb::Result<EspTwaiFrame, EspTwaiError> {
|
||||
let register_block = T::register_block();
|
||||
let status = register_block.status().read();
|
||||
@ -1166,9 +1177,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents errors that can occur in the TWAI driver.
|
||||
/// This enum defines the possible errors that can be encountered when
|
||||
/// interacting with the TWAI peripheral.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum EspTwaiError {
|
||||
/// TWAI peripheral has entered a bus-off state.
|
||||
BusOff,
|
||||
/// Encapsulates errors defined by the embedded-hal crate.
|
||||
EmbeddedHAL(ErrorKind),
|
||||
}
|
||||
|
||||
@ -1274,28 +1290,41 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// TWAI peripheral instance.
|
||||
pub trait Instance: crate::private::Sealed {
|
||||
/// The system peripheral associated with this TWAI instance.
|
||||
const SYSTEM_PERIPHERAL: system::Peripheral;
|
||||
/// The identifier number for this TWAI instance.
|
||||
const NUMBER: usize;
|
||||
|
||||
/// Input signal.
|
||||
const INPUT_SIGNAL: InputSignal;
|
||||
/// Output signal.
|
||||
const OUTPUT_SIGNAL: OutputSignal;
|
||||
|
||||
/// The interrupt associated with this TWAI instance.
|
||||
const INTERRUPT: crate::peripherals::Interrupt;
|
||||
#[cfg(feature = "async")]
|
||||
/// Provides an asynchronous interrupt handler for TWAI instance.
|
||||
fn async_handler() -> InterruptHandler;
|
||||
|
||||
/// Returns a reference to the register block for TWAI instance.
|
||||
fn register_block() -> &'static RegisterBlock;
|
||||
|
||||
/// Enables the TWAI peripheral.
|
||||
fn enable_peripheral();
|
||||
|
||||
/// Resets the TWAI peripheral.
|
||||
fn reset_peripheral();
|
||||
|
||||
/// Enables interrupts for the TWAI peripheral.
|
||||
fn enable_interrupts();
|
||||
}
|
||||
|
||||
/// An extension of the `Instance` trait that provides additional operations
|
||||
/// for managing and interacting with the TWAI peripheral.
|
||||
pub trait OperationInstance: Instance {
|
||||
#[cfg(feature = "async")]
|
||||
/// Returns a reference to the asynchronous state for this TWAI instance.
|
||||
fn async_state() -> &'static asynch::TwaiAsyncState {
|
||||
&asynch::TWAI_STATE[Self::NUMBER]
|
||||
}
|
||||
@ -1652,10 +1681,11 @@ mod asynch {
|
||||
where
|
||||
T: OperationInstance,
|
||||
{
|
||||
/// Transmits an `EspTwaiFrame` asynchronously over the TWAI bus.
|
||||
pub async fn transmit_async(&mut self, frame: &EspTwaiFrame) -> Result<(), EspTwaiError> {
|
||||
self.tx.transmit_async(frame).await
|
||||
}
|
||||
|
||||
/// Receives an `EspTwaiFrame` asynchronously over the TWAI bus.
|
||||
pub async fn receive_async(&mut self) -> Result<EspTwaiFrame, EspTwaiError> {
|
||||
self.rx.receive_async().await
|
||||
}
|
||||
@ -1665,6 +1695,7 @@ mod asynch {
|
||||
where
|
||||
T: OperationInstance,
|
||||
{
|
||||
/// Transmits an `EspTwaiFrame` asynchronously over the TWAI bus.
|
||||
pub async fn transmit_async(&mut self, frame: &EspTwaiFrame) -> Result<(), EspTwaiError> {
|
||||
T::enable_interrupts();
|
||||
poll_fn(|cx| {
|
||||
@ -1694,6 +1725,7 @@ mod asynch {
|
||||
where
|
||||
T: OperationInstance,
|
||||
{
|
||||
/// Receives an `EspTwaiFrame` asynchronously over the TWAI bus.
|
||||
pub async fn receive_async(&mut self) -> Result<EspTwaiFrame, EspTwaiError> {
|
||||
T::enable_interrupts();
|
||||
poll_fn(|cx| {
|
||||
|
@ -118,8 +118,6 @@
|
||||
//! [embedded-hal-async]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/
|
||||
//! [embedded-io-async]: https://docs.rs/embedded-io-async/latest/embedded_io_async/
|
||||
|
||||
#![allow(missing_docs)] // TODO: Remove when able
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use self::config::Config;
|
||||
@ -150,25 +148,60 @@ use crate::soc::constants::REF_TICK;
|
||||
// Default TX and RX pins for Uart/Serial communication (UART0)
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(esp32)] {
|
||||
/// Default TX pin for UART0 on ESP32.
|
||||
/// Corresponds to GPIO1.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio1;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32.
|
||||
/// Corresponds to GPIO3.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio3;
|
||||
} else if #[cfg(esp32c2)] {
|
||||
/// Default TX pin for UART0 on ESP32-C2.
|
||||
/// Corresponds to GPIO20.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio20;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-C2.
|
||||
/// Corresponds to GPIO19.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio19;
|
||||
} else if #[cfg(esp32c3)] {
|
||||
/// Default TX pin for UART0 on ESP32-C3.
|
||||
/// Corresponds to GPIO21.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio21;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-C3.
|
||||
/// Corresponds to GPIO20.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio20;
|
||||
}else if #[cfg(esp32c6)] {
|
||||
/// Default TX pin for UART0 on ESP32-C6.
|
||||
/// Corresponds to GPIO16.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio16;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-C6.
|
||||
/// Corresponds to GPIO17.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio17;
|
||||
}else if #[cfg(esp32h2)] {
|
||||
/// Default TX pin for UART0 on ESP32-H2.
|
||||
/// Corresponds to GPIO24.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio24;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-H2.
|
||||
/// Corresponds to GPIO23.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio23;
|
||||
} else if #[cfg(esp32s2)] {
|
||||
/// Default TX pin for UART0 on ESP32-S2.
|
||||
/// Corresponds to GPIO43.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio43;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-S2.
|
||||
/// Corresponds to GPIO44.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio44;
|
||||
} else if #[cfg(esp32s3)] {
|
||||
/// Default TX pin for UART0 on ESP32-S3.
|
||||
/// Corresponds to GPIO43.
|
||||
pub type DefaultTxPin = crate::gpio::Gpio43;
|
||||
|
||||
/// Default RX pin for UART0 on ESP32-S3.
|
||||
/// Corresponds to GPIO44.
|
||||
pub type DefaultRxPin = crate::gpio::Gpio44;
|
||||
}
|
||||
}
|
||||
@ -177,15 +210,36 @@ cfg_if::cfg_if! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Error {
|
||||
/// An invalid configuration argument was provided
|
||||
/// An invalid configuration argument was provided.
|
||||
///
|
||||
/// This error occurs when an incorrect or invalid argument is passed during
|
||||
/// the configuration of the UART peripheral.
|
||||
InvalidArgument,
|
||||
/// The RX FIFO overflowed
|
||||
|
||||
/// The RX FIFO overflowed.
|
||||
#[cfg(feature = "async")]
|
||||
RxFifoOvf,
|
||||
|
||||
/// A glitch was detected on the RX line.
|
||||
///
|
||||
/// This error occurs when an unexpected or erroneous signal (glitch) is
|
||||
/// detected on the UART RX line, which could lead to incorrect data
|
||||
/// reception.
|
||||
#[cfg(feature = "async")]
|
||||
RxGlitchDetected,
|
||||
|
||||
/// A framing error was detected on the RX line.
|
||||
///
|
||||
/// This error occurs when the received data does not conform to the
|
||||
/// expected UART frame format.
|
||||
#[cfg(feature = "async")]
|
||||
RxFrameError,
|
||||
|
||||
/// A parity error was detected on the RX line.
|
||||
///
|
||||
/// This error occurs when the parity bit in the received data does not
|
||||
/// match the expected parity configuration.
|
||||
/// with the `async` feature.
|
||||
#[cfg(feature = "async")]
|
||||
RxParityError,
|
||||
}
|
||||
@ -233,33 +287,55 @@ pub mod config {
|
||||
const UART_TOUT_THRESH_DEFAULT: u8 = 10;
|
||||
|
||||
/// Number of data bits
|
||||
///
|
||||
/// This enum represents the various configurations for the number of data
|
||||
/// bits used in UART communication. The number of data bits defines the
|
||||
/// length of each transmitted or received data frame.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum DataBits {
|
||||
/// 5 data bits per frame.
|
||||
DataBits5 = 0,
|
||||
/// 6 data bits per frame.
|
||||
DataBits6 = 1,
|
||||
/// 7 data bits per frame.
|
||||
DataBits7 = 2,
|
||||
/// 8 data bits per frame (most common).
|
||||
DataBits8 = 3,
|
||||
}
|
||||
|
||||
/// Parity check
|
||||
///
|
||||
/// Parity is a form of error detection in UART communication, used to
|
||||
/// ensure that the data has not been corrupted during transmission. The
|
||||
/// parity bit is added to the data bits to make the number of 1-bits
|
||||
/// either even or odd.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum Parity {
|
||||
/// No parity bit is used (most common).
|
||||
ParityNone,
|
||||
/// Even parity: the parity bit is set to make the total number of
|
||||
/// 1-bits even.
|
||||
ParityEven,
|
||||
/// Odd parity: the parity bit is set to make the total number of 1-bits
|
||||
/// odd.
|
||||
ParityOdd,
|
||||
}
|
||||
|
||||
/// Number of stop bits
|
||||
///
|
||||
/// The stop bit(s) signal the end of a data packet in UART communication.
|
||||
/// This enum defines the possible configurations for the number of stop
|
||||
/// bits.
|
||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub enum StopBits {
|
||||
/// 1 stop bit
|
||||
/// 1 stop bit.
|
||||
STOP1 = 1,
|
||||
/// 1.5 stop bits
|
||||
/// 1.5 stop bits.
|
||||
STOP1P5 = 2,
|
||||
/// 2 stop bits
|
||||
/// 2 stop bits.
|
||||
STOP2 = 3,
|
||||
}
|
||||
|
||||
@ -267,51 +343,68 @@ pub mod config {
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
pub struct Config {
|
||||
/// The baud rate (speed) of the UART communication in bits per second
|
||||
/// (bps).
|
||||
pub baudrate: u32,
|
||||
/// Number of data bits in each frame (5, 6, 7, or 8 bits).
|
||||
pub data_bits: DataBits,
|
||||
/// Parity setting (None, Even, or Odd).
|
||||
pub parity: Parity,
|
||||
/// Number of stop bits in each frame (1, 1.5, or 2 bits).
|
||||
pub stop_bits: StopBits,
|
||||
/// Clock source used by the UART peripheral.
|
||||
pub clock_source: super::ClockSource,
|
||||
/// Threshold level at which the RX FIFO is considered full.
|
||||
pub rx_fifo_full_threshold: u16,
|
||||
/// Optional timeout value for RX operations.
|
||||
pub rx_timeout: Option<u8>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Sets the baud rate for the UART configuration.
|
||||
pub fn baudrate(mut self, baudrate: u32) -> Self {
|
||||
self.baudrate = baudrate;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the UART to use no parity check.
|
||||
pub fn parity_none(mut self) -> Self {
|
||||
self.parity = Parity::ParityNone;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the UART to use even parity check.
|
||||
pub fn parity_even(mut self) -> Self {
|
||||
self.parity = Parity::ParityEven;
|
||||
self
|
||||
}
|
||||
|
||||
/// Configures the UART to use odd parity check.
|
||||
pub fn parity_odd(mut self) -> Self {
|
||||
self.parity = Parity::ParityOdd;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the number of data bits for the UART configuration.
|
||||
pub fn data_bits(mut self, data_bits: DataBits) -> Self {
|
||||
self.data_bits = data_bits;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the number of stop bits for the UART configuration.
|
||||
pub fn stop_bits(mut self, stop_bits: StopBits) -> Self {
|
||||
self.stop_bits = stop_bits;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the clock source for the UART configuration.
|
||||
pub fn clock_source(mut self, source: super::ClockSource) -> Self {
|
||||
self.clock_source = source;
|
||||
self
|
||||
}
|
||||
|
||||
/// Calculates the total symbol length in bits based on the configured
|
||||
/// data bits, parity, and stop bits.
|
||||
pub fn symbol_length(&self) -> u8 {
|
||||
let mut length: u8 = 1; // start bit
|
||||
length += match self.data_bits {
|
||||
@ -331,11 +424,13 @@ pub mod config {
|
||||
length
|
||||
}
|
||||
|
||||
/// Sets the RX FIFO full threshold for the UART configuration.
|
||||
pub fn rx_fifo_full_threshold(mut self, threshold: u16) -> Self {
|
||||
self.rx_fifo_full_threshold = threshold;
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the RX timeout for the UART configuration.
|
||||
pub fn rx_timeout(mut self, timeout: Option<u8>) -> Self {
|
||||
self.rx_timeout = timeout;
|
||||
self
|
||||
@ -361,14 +456,27 @@ pub mod config {
|
||||
|
||||
/// Configuration for the AT-CMD detection functionality
|
||||
pub struct AtCmdConfig {
|
||||
/// Optional idle time before the AT command detection begins, in clock
|
||||
/// cycles.
|
||||
pub pre_idle_count: Option<u16>,
|
||||
/// Optional idle time after the AT command detection ends, in clock
|
||||
/// cycles.
|
||||
pub post_idle_count: Option<u16>,
|
||||
/// Optional timeout between characters in the AT command, in clock
|
||||
/// cycles.
|
||||
pub gap_timeout: Option<u16>,
|
||||
/// The character that triggers the AT command detection.
|
||||
pub cmd_char: u8,
|
||||
/// Optional number of characters to detect as part of the AT command.
|
||||
pub char_num: Option<u8>,
|
||||
}
|
||||
|
||||
impl AtCmdConfig {
|
||||
/// Creates a new `AtCmdConfig` with the specified configuration.
|
||||
///
|
||||
/// This function sets up the AT command detection parameters, including
|
||||
/// pre- and post-idle times, a gap timeout, the triggering command
|
||||
/// character, and the number of characters to detect.
|
||||
pub fn new(
|
||||
pre_idle_count: Option<u16>,
|
||||
post_idle_count: Option<u16>,
|
||||
@ -1306,10 +1414,27 @@ where
|
||||
|
||||
/// UART Peripheral Instance
|
||||
pub trait Instance: crate::private::Sealed {
|
||||
/// Returns a reference to the UART register block for the specific
|
||||
/// instance.
|
||||
///
|
||||
/// # Safety
|
||||
/// This function returns a reference to the raw hardware registers, so
|
||||
/// direct interaction with the registers may require careful handling
|
||||
/// to avoid unintended side effects.
|
||||
fn register_block() -> &'static RegisterBlock;
|
||||
|
||||
/// Returns the UART number associated with this instance (e.g., UART0,
|
||||
/// UART1, etc.).
|
||||
fn uart_number() -> usize;
|
||||
|
||||
/// Returns the interrupt associated with this UART instance.
|
||||
fn interrupt() -> Interrupt;
|
||||
|
||||
/// Disables all TX-related interrupts for this UART instance.
|
||||
///
|
||||
/// This function clears and disables the `transmit FIFO empty` interrupt,
|
||||
/// `transmit break done`, `transmit break idle done`, and `transmit done`
|
||||
/// interrupts.
|
||||
fn disable_tx_interrupts() {
|
||||
Self::register_block().int_clr().write(|w| {
|
||||
w.txfifo_empty()
|
||||
@ -1334,6 +1459,11 @@ pub trait Instance: crate::private::Sealed {
|
||||
});
|
||||
}
|
||||
|
||||
/// Disables all RX-related interrupts for this UART instance.
|
||||
///
|
||||
/// This function clears and disables the `receive FIFO full` interrupt,
|
||||
/// `receive FIFO overflow`, `receive FIFO timeout`, and `AT command
|
||||
/// character detection` interrupts.
|
||||
fn disable_rx_interrupts() {
|
||||
Self::register_block().int_clr().write(|w| {
|
||||
w.rxfifo_full()
|
||||
@ -1359,6 +1489,8 @@ pub trait Instance: crate::private::Sealed {
|
||||
}
|
||||
|
||||
#[allow(clippy::useless_conversion)]
|
||||
/// Returns the number of bytes currently in the TX FIFO for this UART
|
||||
/// instance.
|
||||
fn get_tx_fifo_count() -> u16 {
|
||||
Self::register_block()
|
||||
.status()
|
||||
@ -1368,6 +1500,8 @@ pub trait Instance: crate::private::Sealed {
|
||||
.into()
|
||||
}
|
||||
|
||||
/// Returns the number of bytes currently in the RX FIFO for this UART
|
||||
/// instance.
|
||||
#[allow(clippy::useless_conversion)]
|
||||
fn get_rx_fifo_count() -> u16 {
|
||||
let fifo_cnt: u16 = Self::register_block()
|
||||
@ -1408,6 +1542,10 @@ pub trait Instance: crate::private::Sealed {
|
||||
fifo_cnt
|
||||
}
|
||||
|
||||
/// Checks if the TX line is idle for this UART instance.
|
||||
///
|
||||
/// Returns `true` if the transmit line is idle, meaning no data is
|
||||
/// currently being transmitted.
|
||||
fn is_tx_idle() -> bool {
|
||||
#[cfg(esp32)]
|
||||
let idle = Self::register_block().status().read().st_utx_out().bits() == 0x0u8;
|
||||
@ -1422,6 +1560,10 @@ pub trait Instance: crate::private::Sealed {
|
||||
idle
|
||||
}
|
||||
|
||||
/// Checks if the RX line is idle for this UART instance.
|
||||
///
|
||||
/// Returns `true` if the receive line is idle, meaning no data is currently
|
||||
/// being received.
|
||||
fn is_rx_idle() -> bool {
|
||||
#[cfg(esp32)]
|
||||
let idle = Self::register_block().status().read().st_urx_out().bits() == 0x0u8;
|
||||
@ -1436,11 +1578,26 @@ pub trait Instance: crate::private::Sealed {
|
||||
idle
|
||||
}
|
||||
|
||||
/// Returns the output signal identifier for the TX pin of this UART
|
||||
/// instance.
|
||||
fn tx_signal() -> OutputSignal;
|
||||
|
||||
/// Returns the input signal identifier for the RX pin of this UART
|
||||
/// instance.
|
||||
fn rx_signal() -> InputSignal;
|
||||
|
||||
/// Returns the input signal identifier for the CTS (Clear to Send) pin of
|
||||
/// this UART instance.
|
||||
fn cts_signal() -> InputSignal;
|
||||
|
||||
/// Returns the output signal identifier for the RTS (Request to Send) pin
|
||||
/// of this UART instance.
|
||||
fn rts_signal() -> OutputSignal;
|
||||
|
||||
/// Enables the clock for this UART peripheral instance.
|
||||
fn enable_peripheral();
|
||||
|
||||
/// Resets the UART peripheral instance.
|
||||
fn reset_peripheral();
|
||||
}
|
||||
|
||||
@ -2056,15 +2213,18 @@ mod asynch {
|
||||
where
|
||||
T: Instance,
|
||||
{
|
||||
/// See [`UartRx::read_async`]
|
||||
/// Asynchronously reads data from the UART receive buffer into the
|
||||
/// provided buffer.
|
||||
pub async fn read_async(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
self.rx.read_async(buf).await
|
||||
}
|
||||
|
||||
/// Asynchronously writes data to the UART transmit buffer.
|
||||
pub async fn write_async(&mut self, words: &[u8]) -> Result<usize, Error> {
|
||||
self.tx.write_async(words).await
|
||||
}
|
||||
|
||||
/// Asynchronously flushes the UART transmit buffer.
|
||||
pub async fn flush_async(&mut self) -> Result<(), Error> {
|
||||
self.tx.flush_async().await
|
||||
}
|
||||
@ -2111,6 +2271,12 @@ mod asynch {
|
||||
Ok(uart_tx)
|
||||
}
|
||||
|
||||
/// Asynchronously writes data to the UART transmit buffer in chunks.
|
||||
///
|
||||
/// This function sends the contents of the provided buffer `words` over
|
||||
/// the UART. Data is written in chunks to avoid overflowing the
|
||||
/// transmit FIFO, and the function waits asynchronously when
|
||||
/// necessary for space in the buffer to become available.
|
||||
pub async fn write_async(&mut self, words: &[u8]) -> Result<usize, Error> {
|
||||
let mut count = 0;
|
||||
let mut offset: usize = 0;
|
||||
@ -2136,6 +2302,11 @@ mod asynch {
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
/// Asynchronously flushes the UART transmit buffer.
|
||||
///
|
||||
/// This function ensures that all pending data in the transmit FIFO has
|
||||
/// been sent over the UART. If the FIFO contains data, it waits
|
||||
/// for the transmission to complete before returning.
|
||||
pub async fn flush_async(&mut self) -> Result<(), Error> {
|
||||
let count = T::get_tx_fifo_count();
|
||||
if count > 0 {
|
||||
|
@ -71,44 +71,92 @@ pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! {
|
||||
}
|
||||
|
||||
/// Registers saved in trap handler
|
||||
#[allow(missing_docs)]
|
||||
#[derive(Debug, Default, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
pub struct TrapFrame {
|
||||
/// Return address, stores the address to return to after a function call or
|
||||
/// interrupt.
|
||||
pub ra: usize,
|
||||
/// Temporary register t0, used for intermediate values.
|
||||
pub t0: usize,
|
||||
/// Temporary register t1, used for intermediate values.
|
||||
pub t1: usize,
|
||||
/// Temporary register t2, used for intermediate values.
|
||||
pub t2: usize,
|
||||
/// Temporary register t3, used for intermediate values.
|
||||
pub t3: usize,
|
||||
/// Temporary register t4, used for intermediate values.
|
||||
pub t4: usize,
|
||||
/// Temporary register t5, used for intermediate values.
|
||||
pub t5: usize,
|
||||
/// Temporary register t6, used for intermediate values.
|
||||
pub t6: usize,
|
||||
/// Argument register a0, typically used to pass the first argument to a
|
||||
/// function.
|
||||
pub a0: usize,
|
||||
/// Argument register a1, typically used to pass the second argument to a
|
||||
/// function.
|
||||
pub a1: usize,
|
||||
/// Argument register a2, typically used to pass the third argument to a
|
||||
/// function.
|
||||
pub a2: usize,
|
||||
/// Argument register a3, typically used to pass the fourth argument to a
|
||||
/// function.
|
||||
pub a3: usize,
|
||||
/// Argument register a4, typically used to pass the fifth argument to a
|
||||
/// function.
|
||||
pub a4: usize,
|
||||
/// Argument register a5, typically used to pass the sixth argument to a
|
||||
/// function.
|
||||
pub a5: usize,
|
||||
/// Argument register a6, typically used to pass the seventh argument to a
|
||||
/// function.
|
||||
pub a6: usize,
|
||||
/// Argument register a7, typically used to pass the eighth argument to a
|
||||
/// function.
|
||||
pub a7: usize,
|
||||
/// Saved register s0, used to hold values across function calls.
|
||||
pub s0: usize,
|
||||
/// Saved register s1, used to hold values across function calls.
|
||||
pub s1: usize,
|
||||
/// Saved register s2, used to hold values across function calls.
|
||||
pub s2: usize,
|
||||
/// Saved register s3, used to hold values across function calls.
|
||||
pub s3: usize,
|
||||
/// Saved register s4, used to hold values across function calls.
|
||||
pub s4: usize,
|
||||
/// Saved register s5, used to hold values across function calls.
|
||||
pub s5: usize,
|
||||
/// Saved register s6, used to hold values across function calls.
|
||||
pub s6: usize,
|
||||
/// Saved register s7, used to hold values across function calls.
|
||||
pub s7: usize,
|
||||
/// Saved register s8, used to hold values across function calls.
|
||||
pub s8: usize,
|
||||
/// Saved register s9, used to hold values across function calls.
|
||||
pub s9: usize,
|
||||
/// Saved register s10, used to hold values across function calls.
|
||||
pub s10: usize,
|
||||
/// Saved register s11, used to hold values across function calls.
|
||||
pub s11: usize,
|
||||
/// Global pointer register, holds the address of the global data area.
|
||||
pub gp: usize,
|
||||
/// Thread pointer register, holds the address of the thread-local storage
|
||||
/// area.
|
||||
pub tp: usize,
|
||||
/// Stack pointer register, holds the address of the top of the stack.
|
||||
pub sp: usize,
|
||||
/// Program counter, stores the address of the next instruction to be
|
||||
/// executed.
|
||||
pub pc: usize,
|
||||
/// Machine status register, holds the current status of the processor,
|
||||
/// including interrupt enable bits and privilege mode.
|
||||
pub mstatus: usize,
|
||||
/// Machine cause register, contains the reason for the trap (e.g.,
|
||||
/// exception or interrupt number).
|
||||
pub mcause: usize,
|
||||
/// Machine trap value register, contains additional information about the
|
||||
/// trap (e.g., faulting address).
|
||||
pub mtval: usize,
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user