@@ -315,3 +315,155 @@ macro_rules! metadata {
315
315
} ;
316
316
} ;
317
317
}
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