@@ -2,9 +2,10 @@ use std::collections::HashMap;
2
2
use std:: io:: { self , Write } ;
3
3
4
4
use cast:: u64;
5
- use quote:: Tokens ;
5
+ use quote:: { Tokens , ToTokens } ;
6
6
use svd:: { Access , BitRange , Defaults , Device , EnumeratedValues , Field ,
7
7
Peripheral , Register , Usage , WriteConstraint } ;
8
+ use syn;
8
9
use syn:: { Ident , Lit } ;
9
10
10
11
use errors:: * ;
@@ -460,8 +461,15 @@ pub fn peripheral(
460
461
Ok ( ( ) )
461
462
}
462
463
464
+ struct RegisterBlockField {
465
+ field : syn:: Field ,
466
+ description : Ident ,
467
+ offset : u32 ,
468
+ size : u32 ,
469
+ }
470
+
463
471
fn register_block ( registers : & [ Register ] , defs : & Defaults ) -> Result < Tokens > {
464
- let mut fields = vec ! [ ] ;
472
+ let mut fields = Tokens :: new ( ) ;
465
473
// enumeration of reserved fields
466
474
let mut i = 0 ;
467
475
// offset from the base address, in bytes
@@ -470,8 +478,19 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
470
478
471
479
for register in registers {
472
480
match * register {
473
- Register :: Single ( ref _into) => registers_expanded. push ( register. clone ( ) ) ,
474
- Register :: Array ( ref _into, ref array_info) => {
481
+ Register :: Single ( ref info) => registers_expanded. push (
482
+ RegisterBlockField {
483
+ field : util:: convert_svd_register ( register) ,
484
+ description : Ident :: from ( info. description . clone ( ) ) ,
485
+ offset : info. address_offset ,
486
+ size : info. size . or ( defs. size )
487
+ . ok_or_else (
488
+ || {
489
+ format ! ( "Register {} has no `size` field" , register. name)
490
+ } , ) ?,
491
+ }
492
+ ) ,
493
+ Register :: Array ( ref info, ref array_info) => {
475
494
let index_convertible = if let Some ( ref indexes) = array_info. dim_index {
476
495
let mut index_iter = indexes. iter ( ) ;
477
496
let mut previous = 0 ;
@@ -512,69 +531,90 @@ fn register_block(registers: &[Register], defs: &Defaults) -> Result<Tokens> {
512
531
let array_convertible = index_convertible && packed_registers;
513
532
514
533
if array_convertible {
515
- registers_expanded. push ( register. clone ( ) ) ;
534
+ registers_expanded. push (
535
+ RegisterBlockField {
536
+ field : util:: convert_svd_register ( & register) ,
537
+ description : Ident :: from ( info. description . clone ( ) ) ,
538
+ offset : info. address_offset ,
539
+ size : info. size . or ( defs. size )
540
+ . ok_or_else (
541
+ || {
542
+ format ! ( "Register {} has no `size` field" , register. name)
543
+ } , ) ?
544
+ * array_info. dim ,
545
+ } ) ;
516
546
} else {
517
- registers_expanded. append ( & mut util:: expand ( register) ) ;
547
+ let mut field_num = 0 ;
548
+ for field in util:: expand_svd_register ( register) . iter ( ) {
549
+ registers_expanded. push (
550
+ RegisterBlockField {
551
+ field : field. clone ( ) ,
552
+ description : Ident :: from ( info. description . clone ( ) ) ,
553
+ offset : info. address_offset + field_num * array_info. dim_increment ,
554
+ size : info. size . or ( defs. size )
555
+ . ok_or_else (
556
+ || {
557
+ format ! ( "Register {} has no `size` field" , register. name)
558
+ } , ) ?
559
+ } ) ;
560
+ field_num += 1 ;
561
+ }
518
562
}
519
563
} ,
520
564
}
521
565
}
522
566
523
-
524
- for register in util:: sort_by_offset ( registers_expanded) {
525
- let pad = if let Some ( pad) = register. address_offset . checked_sub ( offset) {
567
+ registers_expanded. sort_by_key ( |x| x. offset ) ;
568
+
569
+ for register in registers_expanded {
570
+ let pad = if let Some ( pad) = register. offset . checked_sub ( offset) {
526
571
pad
527
572
} else {
528
573
writeln ! (
529
574
io:: stderr( ) ,
530
575
"WARNING {} overlaps with another register at offset {}. \
531
576
Ignoring.",
532
- register. name,
533
- register. address_offset
534
- ) . ok ( ) ;
577
+ register. field. ident. unwrap( ) ,
578
+ register. offset
579
+ )
580
+ . ok ( ) ;
535
581
continue ;
536
582
} ;
537
583
538
584
if pad != 0 {
539
585
let name = Ident :: new ( format ! ( "_reserved{}" , i) ) ;
540
586
let pad = pad as usize ;
541
- fields. push ( quote ! {
542
- #name : [ u8 ; #pad] ,
543
- } ) ;
587
+ fields. append (
588
+ quote ! {
589
+ #name : [ u8 ; #pad] ,
590
+ } ) ;
544
591
i += 1 ;
545
592
}
593
+
594
+ let comment = & format ! (
595
+ "0x{:02x} - {}" ,
596
+ register. offset,
597
+ register. description,
598
+ )
599
+ [ ..] ;
546
600
547
- fields. push ( util:: register_to_rust ( & register) ) ;
601
+ fields. append (
602
+ quote ! {
603
+ #[ doc = #comment]
604
+ }
605
+ ) ;
548
606
549
- offset = match register {
550
- Register :: Single ( ref _into) => register. address_offset
551
- +
552
- register
553
- . size
554
- . or ( defs. size )
555
- . ok_or_else (
556
- || {
557
- format ! ( "Register {} has no `size` field" , register. name)
558
- } ,
559
- ) ? / 8 ,
560
- Register :: Array ( ref _into, ref array_info) => register. address_offset
561
- +
562
- register
563
- . size
564
- . or ( defs. size )
565
- . ok_or_else (
566
- || {
567
- format ! ( "Register {} has no `size` field" , register. name)
568
- } ,
569
- ) ? * array_info. dim / 8 ,
570
- } ;
607
+ register. field . to_tokens ( & mut fields) ;
608
+ Ident :: new ( "," ) . to_tokens ( & mut fields) ;
609
+
610
+ offset = register. offset + register. size /8 ;
571
611
}
572
612
573
613
Ok ( quote ! {
574
614
/// Register block
575
615
#[ repr( C ) ]
576
616
pub struct RegisterBlock {
577
- #( # fields) *
617
+ #fields
578
618
}
579
619
} )
580
620
}
0 commit comments