Add derive macro for BuilderLite, add #[non_exhaustive] to some enums and structs (#2614)

* Add a derive procmacro to implement the Builder Lite pattern for a struct

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in I2C module

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in UART module

* Add `#[non_exhaustive]` and derive `BuilderLite` where necessary in SPI module

* Update `CHANGELOG.md`

* Fix build errors in HIL tests

* Fix generated doc comments

* Return a `ParseError` rather than panicking

* Add a method to set the value to `None` for `Option` types
This commit is contained in:
Jesse Braham 2024-11-27 07:54:43 -08:00 committed by GitHub
parent aeda6ac00a
commit 1a2bee6f1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 235 additions and 132 deletions

View File

@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- Added the `BuilderLite` derive macro which implements the Builder Lite pattern for a struct (#2614)
### Fixed ### Fixed
### Changed ### Changed

View File

@ -52,7 +52,22 @@ use proc_macro::{Span, TokenStream};
use proc_macro2::Ident; use proc_macro2::Ident;
use proc_macro_crate::{crate_name, FoundCrate}; use proc_macro_crate::{crate_name, FoundCrate};
use proc_macro_error2::abort; use proc_macro_error2::abort;
use syn::{parse, parse::Error as ParseError, spanned::Spanned, Item, ItemFn, ReturnType, Type}; use quote::{format_ident, quote};
use syn::{
parse,
parse::Error as ParseError,
spanned::Spanned,
Data,
DataStruct,
GenericArgument,
Item,
ItemFn,
Path,
PathArguments,
PathSegment,
ReturnType,
Type,
};
use self::interrupt::{check_attr_whitelist, WhiteListCaller}; use self::interrupt::{check_attr_whitelist, WhiteListCaller};
@ -238,8 +253,8 @@ pub fn ram(args: TokenStream, input: TokenStream) -> TokenStream {
/// esp_hal::interrupt::Priority::Priority2)]`. /// esp_hal::interrupt::Priority::Priority2)]`.
/// ///
/// If no priority is given, `Priority::min()` is assumed /// If no priority is given, `Priority::min()` is assumed
#[proc_macro_error2::proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
#[proc_macro_error2::proc_macro_error]
pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream { pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream {
#[derive(Debug, FromMeta)] #[derive(Debug, FromMeta)]
struct MacroArgs { struct MacroArgs {
@ -341,8 +356,8 @@ pub fn load_lp_code(input: TokenStream) -> TokenStream {
/// Marks the entry function of a LP core / ULP program. /// Marks the entry function of a LP core / ULP program.
#[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))] #[cfg(any(feature = "is-lp-core", feature = "is-ulp-core"))]
#[proc_macro_error2::proc_macro_error]
#[proc_macro_attribute] #[proc_macro_attribute]
#[proc_macro_error2::proc_macro_error]
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
lp_core::entry(args, input) lp_core::entry(args, input)
} }
@ -381,3 +396,127 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
run(&args.meta, f, main()).unwrap_or_else(|x| x).into() run(&args.meta, f, main()).unwrap_or_else(|x| x).into()
} }
/// Automatically implement the [Builder Lite] pattern for a struct.
///
/// This will create an `impl` which contains methods for each field of a
/// struct, allowing users to easily set the values. The generated methods will
/// be the field name prefixed with `with_`, and calls to these methods can be
/// chained as needed.
///
/// ## Example
///
/// ```rust, no_run
/// #[derive(Default)]
/// enum MyEnum {
/// #[default]
/// A,
/// B,
/// }
///
/// #[derive(Default, BuilderLite)]
/// #[non_exhaustive]
/// struct MyStruct {
/// enum_field: MyEnum,
/// bool_field: bool,
/// option_field: Option<i32>,
/// }
///
/// MyStruct::default()
/// .with_enum_field(MyEnum::B)
/// .with_bool_field(true)
/// .with_option_field(-5);
/// ```
///
/// [Builder Lite]: https://matklad.github.io/2022/05/29/builder-lite.html
#[proc_macro_derive(BuilderLite)]
pub fn builder_lite_derive(item: TokenStream) -> TokenStream {
let input = syn::parse_macro_input!(item as syn::DeriveInput);
let span = input.span();
let ident = input.ident;
let mut fns = Vec::new();
if let Data::Struct(DataStruct { fields, .. }) = &input.data {
for field in fields {
let field_ident = field.ident.as_ref().unwrap();
let field_type = &field.ty;
let function_ident = format_ident!("with_{}", field_ident);
let maybe_path_type = extract_type_path(field_type)
.and_then(|path| extract_option_segment(path))
.and_then(|path_seg| match path_seg.arguments {
PathArguments::AngleBracketed(ref params) => params.args.first(),
_ => None,
})
.and_then(|generic_arg| match *generic_arg {
GenericArgument::Type(ref ty) => Some(ty),
_ => None,
});
let (field_type, field_assigns) = if let Some(inner_type) = maybe_path_type {
(inner_type, quote! { Some(#field_ident) })
} else {
(field_type, quote! { #field_ident })
};
fns.push(quote! {
#[doc = concat!(" Assign the given value to the `", stringify!(#field_ident) ,"` field.")]
pub fn #function_ident(mut self, #field_ident: #field_type) -> Self {
self.#field_ident = #field_assigns;
self
}
});
if maybe_path_type.is_some() {
let function_ident = format_ident!("with_{}_none", field_ident);
fns.push(quote! {
#[doc = concat!(" Set the value of `", stringify!(#field_ident), "` to `None`.")]
pub fn #function_ident(mut self) -> Self {
self.#field_ident = None;
self
}
});
}
}
} else {
return ParseError::new(
span,
"#[derive(Builder)] is only defined for structs, not for enums or unions!",
)
.to_compile_error()
.into();
}
let implementation = quote! {
#[automatically_derived]
impl #ident {
#(#fns)*
}
};
implementation.into()
}
// https://stackoverflow.com/a/56264023
fn extract_type_path(ty: &Type) -> Option<&Path> {
match *ty {
Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path),
_ => None,
}
}
// https://stackoverflow.com/a/56264023
fn extract_option_segment(path: &Path) -> Option<&PathSegment> {
let idents_of_path = path.segments.iter().fold(String::new(), |mut acc, v| {
acc.push_str(&v.ident.to_string());
acc.push('|');
acc
});
vec!["Option|", "std|option|Option|", "core|option|Option|"]
.into_iter()
.find(|s| idents_of_path == *s)
.and_then(|_| path.segments.last())
}

View File

@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added `esp_hal::psram::psram_raw_parts` (#2546) - Added `esp_hal::psram::psram_raw_parts` (#2546)
- The timer drivers `OneShotTimer` & `PeriodicTimer` have `into_async` and `new_typed` methods (#2586) - The timer drivers `OneShotTimer` & `PeriodicTimer` have `into_async` and `new_typed` methods (#2586)
- `timer::Timer` trait has three new methods, `wait`, `async_interrupt_handler` and `peripheral_interrupt` (#2586) - `timer::Timer` trait has three new methods, `wait`, `async_interrupt_handler` and `peripheral_interrupt` (#2586)
- Configuration structs in the I2C, SPI, and UART drivers now implement the Builder Lite pattern (#2614)
### Changed ### Changed
@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- The timer drivers `OneShotTimer` & `PeriodicTimer` now have a `Mode` parameter and type erase the underlying driver by default (#2586) - The timer drivers `OneShotTimer` & `PeriodicTimer` now have a `Mode` parameter and type erase the underlying driver by default (#2586)
- `timer::Timer` has new trait requirements of `Into<AnyTimer>`, `'static` and `InterruptConfigurable` (#2586) - `timer::Timer` has new trait requirements of `Into<AnyTimer>`, `'static` and `InterruptConfigurable` (#2586)
- `systimer::etm::Event` no longer borrows the alarm indefinitely (#2586) - `systimer::etm::Event` no longer borrows the alarm indefinitely (#2586)
- A number of public enums and structs in the I2C, SPI, and UART drivers have been marked with `#[non_exhaustive]` (#2614)
### Fixed ### Fixed

View File

@ -28,11 +28,7 @@
//! //!
//! let mut spi = Spi::new_with_config( //! let mut spi = Spi::new_with_config(
//! peripherals.SPI2, //! peripherals.SPI2,
//! Config { //! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
//! frequency: 100.kHz(),
//! mode: SpiMode::Mode0,
//! ..Config::default()
//! },
//! ) //! )
//! .with_sck(sclk) //! .with_sck(sclk)
//! .with_mosi(mosi) //! .with_mosi(mosi)

View File

@ -86,6 +86,7 @@ const MAX_ITERATIONS: u32 = 1_000_000;
/// I2C-specific transmission errors /// I2C-specific transmission errors
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error { pub enum Error {
/// The transmission exceeded the FIFO size. /// The transmission exceeded the FIFO size.
ExceedingFifo, ExceedingFifo,
@ -106,14 +107,15 @@ pub enum Error {
/// I2C-specific configuration errors /// I2C-specific configuration errors
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum ConfigError {} pub enum ConfigError {}
#[derive(PartialEq)]
// This enum is used to keep track of the last/next operation that was/will be // This enum is used to keep track of the last/next operation that was/will be
// performed in an embedded-hal(-async) I2c::transaction. It is used to // performed in an embedded-hal(-async) I2c::transaction. It is used to
// determine whether a START condition should be issued at the start of the // determine whether a START condition should be issued at the start of the
// current operation and whether a read needs an ack or a nack for the final // current operation and whether a read needs an ack or a nack for the final
// byte. // byte.
#[derive(PartialEq)]
enum OpKind { enum OpKind {
Write, Write,
Read, Read,
@ -217,6 +219,7 @@ enum Ack {
Ack = 0, Ack = 0,
Nack = 1, Nack = 1,
} }
impl From<u32> for Ack { impl From<u32> for Ack {
fn from(ack: u32) -> Self { fn from(ack: u32) -> Self {
match ack { match ack {
@ -226,6 +229,7 @@ impl From<u32> for Ack {
} }
} }
} }
impl From<Ack> for u32 { impl From<Ack> for u32 {
fn from(ack: Ack) -> u32 { fn from(ack: Ack) -> u32 {
ack as u32 ack as u32
@ -233,8 +237,9 @@ impl From<Ack> for u32 {
} }
/// I2C driver configuration /// I2C driver configuration
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy, procmacros::BuilderLite)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct Config { pub struct Config {
/// The I2C clock frequency. /// The I2C clock frequency.
pub frequency: HertzU32, pub frequency: HertzU32,

View File

@ -45,11 +45,7 @@
//! //!
//! let mut spi = Spi::new_with_config( //! let mut spi = Spi::new_with_config(
//! peripherals.SPI2, //! peripherals.SPI2,
//! Config { //! Config::default().with_frequency(100.kHz()).with_mode(SpiMode::Mode0)
//! frequency: 100.kHz(),
//! mode: SpiMode::Mode0,
//! ..Config::default()
//! },
//! ) //! )
//! .with_sck(sclk) //! .with_sck(sclk)
//! .with_mosi(mosi) //! .with_mosi(mosi)
@ -93,6 +89,7 @@ use crate::{
#[cfg(gdma)] #[cfg(gdma)]
#[derive(Debug, EnumSetType)] #[derive(Debug, EnumSetType)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum SpiInterrupt { pub enum SpiInterrupt {
/// Indicates that the SPI transaction has completed successfully. /// Indicates that the SPI transaction has completed successfully.
/// ///
@ -423,8 +420,9 @@ impl Address {
} }
/// SPI peripheral configuration /// SPI peripheral configuration
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug, procmacros::BuilderLite)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct Config { pub struct Config {
/// SPI clock frequency /// SPI clock frequency
pub frequency: HertzU32, pub frequency: HertzU32,

View File

@ -17,6 +17,7 @@ pub mod slave;
/// SPI errors /// SPI errors
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error { pub enum Error {
/// Error occurred due to a DMA-related issue. /// Error occurred due to a DMA-related issue.
DmaError(DmaError), DmaError(DmaError),

View File

@ -244,6 +244,7 @@ const UART_FIFO_SIZE: u16 = 128;
/// UART Error /// UART Error
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum Error { pub enum Error {
/// An invalid configuration argument was provided. /// An invalid configuration argument was provided.
/// ///
@ -289,21 +290,23 @@ impl embedded_io::Error for Error {
// (outside of `config` module in order not to "use" it an extra time) // (outside of `config` module in order not to "use" it an extra time)
/// UART clock source /// UART clock source
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ClockSource { pub enum ClockSource {
/// APB_CLK clock source (default for UART on all the chips except of /// APB_CLK clock source (default for UART on all the chips except of
/// esp32c6 and esp32h2) /// esp32c6 and esp32h2)
#[cfg_attr(not(any(esp32c6, esp32h2, lp_uart)), default)]
Apb, Apb,
#[cfg(not(any(esp32, esp32s2)))]
/// RC_FAST_CLK clock source (17.5 MHz) /// RC_FAST_CLK clock source (17.5 MHz)
RcFast,
#[cfg(not(any(esp32, esp32s2)))] #[cfg(not(any(esp32, esp32s2)))]
RcFast,
/// XTAL_CLK clock source (default for UART on esp32c6 and esp32h2 and /// XTAL_CLK clock source (default for UART on esp32c6 and esp32h2 and
/// LP_UART) /// LP_UART)
#[cfg(not(any(esp32, esp32s2)))]
#[cfg_attr(any(esp32c6, esp32h2, lp_uart), default)]
Xtal, Xtal,
#[cfg(any(esp32, esp32s2))]
/// REF_TICK clock source (derived from XTAL or RC_FAST, 1MHz) /// REF_TICK clock source (derived from XTAL or RC_FAST, 1MHz)
#[cfg(any(esp32, esp32s2))]
RefTick, RefTick,
} }
@ -317,7 +320,7 @@ const UART_TOUT_THRESH_DEFAULT: u8 = 10;
/// This enum represents the various configurations for the number of data /// This enum represents the various configurations for the number of data
/// bits used in UART communication. The number of data bits defines the /// bits used in UART communication. The number of data bits defines the
/// length of each transmitted or received data frame. /// length of each transmitted or received data frame.
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum DataBits { pub enum DataBits {
/// 5 data bits per frame. /// 5 data bits per frame.
@ -327,6 +330,7 @@ pub enum DataBits {
/// 7 data bits per frame. /// 7 data bits per frame.
DataBits7 = 2, DataBits7 = 2,
/// 8 data bits per frame (most common). /// 8 data bits per frame (most common).
#[default]
DataBits8 = 3, DataBits8 = 3,
} }
@ -336,10 +340,11 @@ pub enum DataBits {
/// ensure that the data has not been corrupted during transmission. The /// 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 /// parity bit is added to the data bits to make the number of 1-bits
/// either even or odd. /// either even or odd.
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Parity { pub enum Parity {
/// No parity bit is used (most common). /// No parity bit is used (most common).
#[default]
ParityNone, ParityNone,
/// Even parity: the parity bit is set to make the total number of /// Even parity: the parity bit is set to make the total number of
/// 1-bits even. /// 1-bits even.
@ -354,10 +359,11 @@ pub enum Parity {
/// The stop bit(s) signal the end of a data packet in UART communication. /// 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 /// This enum defines the possible configurations for the number of stop
/// bits. /// bits.
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum StopBits { pub enum StopBits {
/// 1 stop bit. /// 1 stop bit.
#[default]
STOP1 = 1, STOP1 = 1,
/// 1.5 stop bits. /// 1.5 stop bits.
STOP1P5 = 2, STOP1P5 = 2,
@ -366,8 +372,9 @@ pub enum StopBits {
} }
/// UART Configuration /// UART Configuration
#[derive(Debug, Copy, Clone)] #[derive(Debug, Clone, Copy, procmacros::BuilderLite)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub struct Config { pub struct Config {
/// The baud rate (speed) of the UART communication in bits per second /// The baud rate (speed) of the UART communication in bits per second
/// (bps). /// (bps).
@ -467,18 +474,10 @@ impl Default for Config {
fn default() -> Config { fn default() -> Config {
Config { Config {
baudrate: 115_200, baudrate: 115_200,
data_bits: DataBits::DataBits8, data_bits: Default::default(),
parity: Parity::ParityNone, parity: Default::default(),
stop_bits: StopBits::STOP1, stop_bits: Default::default(),
clock_source: { clock_source: Default::default(),
cfg_if::cfg_if! {
if #[cfg(any(esp32c6, esp32h2, lp_uart))] {
ClockSource::Xtal
} else {
ClockSource::Apb
}
}
},
rx_fifo_full_threshold: UART_FULL_THRESH_DEFAULT, rx_fifo_full_threshold: UART_FULL_THRESH_DEFAULT,
rx_timeout: Some(UART_TOUT_THRESH_DEFAULT), rx_timeout: Some(UART_TOUT_THRESH_DEFAULT),
} }
@ -1158,6 +1157,7 @@ where
/// List of exposed UART events. /// List of exposed UART events.
#[derive(Debug, EnumSetType)] #[derive(Debug, EnumSetType)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive]
pub enum UartInterrupt { pub enum UartInterrupt {
/// Indicates that the received has detected the configured /// Indicates that the received has detected the configured
/// [`Uart::set_at_cmd`] character. /// [`Uart::set_at_cmd`] character.
@ -1589,12 +1589,13 @@ where
} }
} }
#[derive(EnumSetType, Debug)] #[derive(Debug, EnumSetType)]
pub(crate) enum TxEvent { pub(crate) enum TxEvent {
TxDone, TxDone,
TxFiFoEmpty, TxFiFoEmpty,
} }
#[derive(EnumSetType, Debug)]
#[derive(Debug, EnumSetType)]
pub(crate) enum RxEvent { pub(crate) enum RxEvent {
FifoFull, FifoFull,
CmdCharDetected, CmdCharDetected,
@ -1705,6 +1706,7 @@ struct UartTxFuture {
state: &'static State, state: &'static State,
registered: bool, registered: bool,
} }
impl UartTxFuture { impl UartTxFuture {
fn new(uart: impl Peripheral<P = impl Instance>, events: impl Into<EnumSet<TxEvent>>) -> Self { fn new(uart: impl Peripheral<P = impl Instance>, events: impl Into<EnumSet<TxEvent>>) -> Self {
crate::into_ref!(uart); crate::into_ref!(uart);

View File

@ -59,11 +59,9 @@ async fn main(_spawner: Spawner) {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_mosi(mosi) .with_mosi(mosi)

View File

@ -39,11 +39,9 @@ fn main() -> ! {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_miso(miso) // order matters .with_miso(miso) // order matters

View File

@ -90,11 +90,9 @@ fn main() -> ! {
// output connection (because we are using the same pin to loop back) // output connection (because we are using the same pin to loop back)
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_miso(miso) .with_miso(miso)

View File

@ -120,11 +120,9 @@ mod test {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 10000.kHz(), .with_frequency(10000.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_miso(unsafe { mosi.clone_unchecked() }) .with_miso(unsafe { mosi.clone_unchecked() })
.with_mosi(mosi) .with_mosi(mosi)
@ -135,11 +133,9 @@ mod test {
#[cfg(any(esp32, esp32s2, esp32s3))] #[cfg(any(esp32, esp32s2, esp32s3))]
let other_peripheral = Spi::new_with_config( let other_peripheral = Spi::new_with_config(
peripherals.SPI3, peripherals.SPI3,
Config { Config::default()
frequency: 10000.kHz(), .with_frequency(10000.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_dma(dma_channel2) .with_dma(dma_channel2)
.into_async(); .into_async();
@ -231,11 +227,9 @@ mod test {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.spi, peripherals.spi,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_dma(peripherals.dma_channel) .with_dma(peripherals.dma_channel)
.with_buffers(dma_rx_buf, dma_tx_buf) .with_buffers(dma_rx_buf, dma_tx_buf)

View File

@ -202,11 +202,9 @@ mod tests {
let spi = Spi::new_with_config( let spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
); );
Context { Context {

View File

@ -73,13 +73,8 @@ mod tests {
let (mosi_loopback_pcnt, mosi) = mosi.split(); let (mosi_loopback_pcnt, mosi) = mosi.split();
// Need to set miso first so that mosi can overwrite the // Need to set miso first so that mosi can overwrite the
// output connection (because we are using the same pin to loop back) // output connection (because we are using the same pin to loop back)
let spi = Spi::new_with_config( let spi =
peripherals.SPI2, Spi::new_with_config(peripherals.SPI2, Config::default().with_frequency(10.MHz()))
Config {
frequency: 10.MHz(),
..Config::default()
},
)
.with_sck(sclk) .with_sck(sclk)
.with_miso(unsafe { mosi.clone_unchecked() }) .with_miso(unsafe { mosi.clone_unchecked() })
.with_mosi(mosi); .with_mosi(mosi);
@ -487,10 +482,7 @@ mod tests {
// This means that without working cancellation, the test case should // This means that without working cancellation, the test case should
// fail. // fail.
ctx.spi ctx.spi
.apply_config(&Config { .apply_config(&Config::default().with_frequency(80.kHz()))
frequency: 80.kHz(),
..Config::default()
})
.unwrap(); .unwrap();
// Set up a large buffer that would trigger a timeout // Set up a large buffer that would trigger a timeout
@ -513,10 +505,7 @@ mod tests {
fn can_transmit_after_cancel(mut ctx: Context) { fn can_transmit_after_cancel(mut ctx: Context) {
// Slow down. At 80kHz, the transfer is supposed to take a bit over 3 seconds. // Slow down. At 80kHz, the transfer is supposed to take a bit over 3 seconds.
ctx.spi ctx.spi
.apply_config(&Config { .apply_config(&Config::default().with_frequency(80.kHz()))
frequency: 80.kHz(),
..Config::default()
})
.unwrap(); .unwrap();
// Set up a large buffer that would trigger a timeout // Set up a large buffer that would trigger a timeout
@ -533,10 +522,7 @@ mod tests {
transfer.cancel(); transfer.cancel();
(spi, (dma_rx_buf, dma_tx_buf)) = transfer.wait(); (spi, (dma_rx_buf, dma_tx_buf)) = transfer.wait();
spi.apply_config(&Config { spi.apply_config(&Config::default().with_frequency(10.MHz()))
frequency: 10.MHz(),
..Config::default()
})
.unwrap(); .unwrap();
let transfer = spi let transfer = spi

View File

@ -48,11 +48,9 @@ mod tests {
let spi = Spi::new_with_config( let spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_miso(miso) .with_miso(miso)

View File

@ -52,11 +52,9 @@ mod tests {
let spi = Spi::new_with_config( let spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_mosi(mosi) .with_mosi(mosi)

View File

@ -64,11 +64,9 @@ mod tests {
let spi = Spi::new_with_config( let spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_mosi(mosi) .with_mosi(mosi)

View File

@ -90,11 +90,11 @@ mod tests {
let mut byte_to_write = 0xA5; let mut byte_to_write = 0xA5;
for (baudrate, clock_source) in configs { for (baudrate, clock_source) in configs {
ctx.uart ctx.uart
.apply_config(&uart::Config { .apply_config(
baudrate, &uart::Config::default()
clock_source, .with_baudrate(baudrate)
..Default::default() .with_clock_source(clock_source),
}) )
.unwrap(); .unwrap();
ctx.uart.write(byte_to_write).ok(); ctx.uart.write(byte_to_write).ok();
let read = block!(ctx.uart.read()); let read = block!(ctx.uart.read());

View File

@ -36,8 +36,7 @@ use esp_hal::{
delay::Delay, delay::Delay,
dma_loop_buffer, dma_loop_buffer,
gpio::{Level, Output}, gpio::{Level, Output},
i2c, i2c::{self, master::I2c},
i2c::master::I2c,
lcd_cam::{ lcd_cam::{
lcd::{ lcd::{
dpi::{Config, Dpi, Format, FrameTiming}, dpi::{Config, Dpi, Format, FrameTiming},
@ -61,10 +60,7 @@ fn main() -> ! {
let i2c = I2c::new( let i2c = I2c::new(
peripherals.I2C0, peripherals.I2C0,
i2c::master::Config { i2c::master::Config::default().with_frequency(400.kHz()),
frequency: 400.kHz(),
..Default::default()
},
) )
.with_sda(peripherals.GPIO47) .with_sda(peripherals.GPIO47)
.with_scl(peripherals.GPIO48); .with_scl(peripherals.GPIO48);

View File

@ -77,11 +77,9 @@ fn main() -> ! {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_mosi(mosi) .with_mosi(mosi)

View File

@ -63,11 +63,9 @@ fn main() -> ! {
let mut spi = Spi::new_with_config( let mut spi = Spi::new_with_config(
peripherals.SPI2, peripherals.SPI2,
Config { Config::default()
frequency: 100.kHz(), .with_frequency(100.kHz())
mode: SpiMode::Mode0, .with_mode(SpiMode::Mode0),
..Config::default()
},
) )
.with_sck(sclk) .with_sck(sclk)
.with_mosi(mosi) .with_mosi(mosi)