@@ -315,3 +315,155 @@ macro_rules! metadata {
315315 } ;
316316 } ;
317317}
318+
319+ #[ procmacros:: doc_replace]
320+ /// Extract fields from [`Peripherals`][crate::peripherals::Peripherals] into named groups.
321+ ///
322+ /// ## Example
323+ ///
324+ /// ```rust,no_run
325+ /// # {before_snippet}
326+ /// #
327+ /// use esp_hal::assign_resources;
328+ ///
329+ /// assign_resources! {
330+ /// Resources<'d> {
331+ /// display: DisplayResources<'d> {
332+ /// spi: SPI2,
333+ /// sda: GPIO6,
334+ /// sclk: GPIO7,
335+ /// cs: GPIO8,
336+ /// dc: GPIO9,
337+ /// },
338+ /// axl: AccelerometerResources<'d> {
339+ /// i2c: I2C0,
340+ /// sda: GPIO12,
341+ /// scl: GPIO13,
342+ /// },
343+ /// }
344+ /// }
345+ ///
346+ /// # struct Display<'d>(core::marker::PhantomData<&'d ()>);
347+ /// fn init_display<'d>(r: DisplayResources<'d>) -> Display<'d> {
348+ /// // use `r.spi`, `r.sda`, `r.sclk`, `r.cs`, `r.dc`
349+ /// todo!()
350+ /// }
351+ ///
352+ /// # struct Accelerometer<'d>(core::marker::PhantomData<&'d ()>);
353+ /// fn init_accelerometer<'d>(r: AccelerometerResources<'d>) -> Accelerometer<'d> {
354+ /// // use `r.i2c`, `r.sda`, `r.scl`
355+ /// todo!()
356+ /// }
357+ ///
358+ /// // let peripherals = esp_hal::init(...);
359+ /// let resources = split_resources!(peripherals);
360+ ///
361+ /// let display = init_display(resources.display);
362+ /// let axl = init_accelerometer(resources.axl);
363+ ///
364+ /// // Other fields (`peripherals.UART0`, ...) of the `peripherals` struct can still be accessed.
365+ /// # {after_snippet}
366+ /// ```
367+ // Based on https://crates.io/crates/assign-resources
368+ #[ macro_export]
369+ #[ cfg( feature = "unstable" ) ]
370+ #[ cfg_attr( docsrs, doc( cfg( feature = "unstable" ) ) ) ]
371+ macro_rules! assign_resources {
372+ {
373+ $( #[ $struct_meta: meta] ) *
374+ $vis: vis $struct_name: ident<$struct_lt: lifetime> {
375+ $(
376+ $( #[ $group_meta: meta] ) *
377+ $group_name: ident : $group_struct: ident<$group_lt: lifetime> {
378+ $(
379+ $( #[ $resource_meta: meta] ) *
380+ $resource_name: ident : $resource_field: ident
381+ ) ,*
382+ $( , ) ?
383+ }
384+ ) ,+
385+ $( , ) ?
386+ }
387+ } => {
388+ // Group structs
389+ $(
390+ $( #[ $group_meta] ) *
391+ #[ allow( missing_docs) ]
392+ $vis struct $group_struct<$group_lt> {
393+ $(
394+ $( #[ $resource_meta] ) *
395+ pub $resource_name: $crate:: peripherals:: $resource_field<$group_lt>,
396+ ) +
397+ }
398+
399+ impl <$group_lt> $group_struct<$group_lt> {
400+ /// Unsafely create an instance of the assigned peripherals out of thin air.
401+ ///
402+ /// # Safety
403+ ///
404+ /// You must ensure that you're only using one instance of the contained peripherals at a time.
405+ pub unsafe fn steal( ) -> Self {
406+ unsafe {
407+ Self {
408+ $( $resource_name: $crate:: peripherals:: $resource_field:: steal( ) ) ,*
409+ }
410+ }
411+ }
412+
413+ /// Creates a new reference to the peripheral group with a shorter lifetime.
414+ ///
415+ /// Use this method if you would like to keep working with the peripherals after
416+ /// you dropped the drivers that consume this.
417+ pub fn reborrow( & mut self ) -> $group_struct<' _> {
418+ $group_struct {
419+ $( $resource_name: self . $resource_name. reborrow( ) ) ,*
420+ }
421+ }
422+ }
423+ ) +
424+
425+ // Outer struct
426+ $( #[ $struct_meta] ) *
427+ /// Assigned resources.
428+ $vis struct $struct_name<$struct_lt> {
429+ $( pub $group_name: $group_struct<$struct_lt>, ) +
430+ }
431+
432+ impl <$struct_lt> $struct_name<$struct_lt> {
433+ /// Unsafely create an instance of the assigned peripherals out of thin air.
434+ ///
435+ /// # Safety
436+ ///
437+ /// You must ensure that you're only using one instance of the contained peripherals at a time.
438+ pub unsafe fn steal( ) -> Self {
439+ unsafe {
440+ Self {
441+ $( $group_name: $group_struct:: steal( ) ) ,*
442+ }
443+ }
444+ }
445+
446+ /// Creates a new reference to the assigned peripherals with a shorter lifetime.
447+ ///
448+ /// Use this method if you would like to keep working with the peripherals after
449+ /// you dropped the drivers that consume this.
450+ pub fn reborrow( & mut self ) -> $struct_name<' _> {
451+ $struct_name {
452+ $( $group_name: self . $group_name. reborrow( ) ) ,*
453+ }
454+ }
455+ }
456+
457+ /// Extracts resources from the `Peripherals` struct.
458+ #[ macro_export]
459+ macro_rules! split_resources {
460+ ( $peris: ident) => {
461+ $struct_name {
462+ $( $group_name: $group_struct {
463+ $( $resource_name: $peris. $resource_field) ,*
464+ } ) ,*
465+ }
466+ }
467+ }
468+ } ;
469+ }
0 commit comments