@@ -37,10 +37,13 @@ pub struct RegisterBlock {
37
37
pub pcsr : RO < u32 > ,
38
38
/// Comparators
39
39
#[ cfg( armv6m) ]
40
- pub c : [ Comparator ; 2 ] ,
40
+ pub comp : [ Comparator < NoCycleCompare > ; 2 ] ,
41
+ #[ cfg( not( armv6m) ) ]
42
+ /// Cycle count compare enabled Comparator
43
+ pub comp0 : Comparator < HasCycleCompare > ,
41
44
#[ cfg( not( armv6m) ) ]
42
45
/// Comparators
43
- pub c : [ Comparator ; 16 ] ,
46
+ pub comp : [ Comparator < NoCycleCompare > ; 15 ] ,
44
47
#[ cfg( not( armv6m) ) ]
45
48
reserved : [ u32 ; 932 ] ,
46
49
/// Lock Access
@@ -66,16 +69,39 @@ bitfield! {
66
69
u8 , numcomp, _: 31 , 28 ;
67
70
}
68
71
72
+ mod private {
73
+ /// A public trait inaccessible by external users to ensure no one else can
74
+ /// impl a sealed trait outside of the crate of origin. For more info on this
75
+ /// design pattern, see https://rust-lang.github.io/api-guidelines/future-proofing.html
76
+ pub trait Sealed { }
77
+ }
78
+
79
+ /// A zero-sized marker trait indicating the capabilities of a given comparator.
80
+ pub trait ComparatorSupportedFunctions : private:: Sealed { }
81
+
82
+ /// Marker indicating that this comparator has cycle comparison abilities. This
83
+ /// is the case only for the first comparator for armv7m.
84
+ pub enum HasCycleCompare { }
85
+ impl ComparatorSupportedFunctions for HasCycleCompare { }
86
+ impl private:: Sealed for HasCycleCompare { }
87
+
88
+ /// Marker indicating this comparator does not have cycle comparison abilities. This
89
+ /// is the case for all armv6m comparators and comparators 1-15 for armv7m.
90
+ pub enum NoCycleCompare { }
91
+ impl ComparatorSupportedFunctions for NoCycleCompare { }
92
+ impl private:: Sealed for NoCycleCompare { }
93
+
69
94
/// Comparator
70
95
#[ repr( C ) ]
71
- pub struct Comparator {
96
+ pub struct Comparator < SupportedFunctions : ComparatorSupportedFunctions > {
72
97
/// Comparator
73
98
pub comp : RW < u32 > ,
74
99
/// Comparator Mask
75
100
pub mask : RW < u32 > ,
76
101
/// Comparator Function
77
102
pub function : RW < Function > ,
78
103
reserved : u32 ,
104
+ _supported_functions : core:: marker:: PhantomData < SupportedFunctions > ,
79
105
}
80
106
81
107
bitfield ! {
@@ -414,63 +440,88 @@ pub enum ComparatorFunction {
414
440
pub enum DwtError {
415
441
/// Invalid combination of [AccessType] and [EmitOption].
416
442
InvalidFunction ,
443
+ /// An unsupported function was requested, such as [`CycleCount`](ComparatorFunction::CycleCount) on
444
+ /// `armv6m`, or on a comparator other than 0 on `armv7m`.
445
+ UnsupportedFunction ,
417
446
}
418
447
419
- impl Comparator {
420
- /// Configure the function of the comparator
448
+ impl < SupportedFunctions : ComparatorSupportedFunctions > Comparator < SupportedFunctions > {
449
+ /// Private function for configuring address compare on any [`Comparator`] since they all support this.
450
+ /// Utilized publicly through [`Comparator::configure`]
451
+ fn configure_address_compare (
452
+ & self ,
453
+ settings : ComparatorAddressSettings ,
454
+ ) -> Result < ( ) , DwtError > {
455
+ // FUNCTION, EMITRANGE
456
+ // See Table C1-14
457
+ let ( function, emit_range) = match ( & settings. access_type , & settings. emit ) {
458
+ ( AccessType :: ReadOnly , EmitOption :: Data ) => ( 0b1100 , false ) ,
459
+ ( AccessType :: ReadOnly , EmitOption :: Address ) => ( 0b1100 , true ) ,
460
+ ( AccessType :: ReadOnly , EmitOption :: AddressData ) => ( 0b1110 , true ) ,
461
+ ( AccessType :: ReadOnly , EmitOption :: PCData ) => ( 0b1110 , false ) ,
462
+ ( AccessType :: ReadOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0101 , false ) ,
463
+ ( AccessType :: ReadOnly , EmitOption :: CompareMatchEvent ) => ( 0b1001 , false ) ,
464
+
465
+ ( AccessType :: WriteOnly , EmitOption :: Data ) => ( 0b1101 , false ) ,
466
+ ( AccessType :: WriteOnly , EmitOption :: Address ) => ( 0b1101 , true ) ,
467
+ ( AccessType :: WriteOnly , EmitOption :: AddressData ) => ( 0b1111 , true ) ,
468
+ ( AccessType :: WriteOnly , EmitOption :: PCData ) => ( 0b1111 , false ) ,
469
+ ( AccessType :: WriteOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0110 , false ) ,
470
+ ( AccessType :: WriteOnly , EmitOption :: CompareMatchEvent ) => ( 0b1010 , false ) ,
471
+
472
+ ( AccessType :: ReadWrite , EmitOption :: Data ) => ( 0b0010 , false ) ,
473
+ ( AccessType :: ReadWrite , EmitOption :: Address ) => ( 0b0001 , true ) ,
474
+ ( AccessType :: ReadWrite , EmitOption :: AddressData ) => ( 0b0010 , true ) ,
475
+ ( AccessType :: ReadWrite , EmitOption :: PCData ) => ( 0b0011 , false ) ,
476
+ ( AccessType :: ReadWrite , EmitOption :: WatchpointDebugEvent ) => ( 0b0111 , false ) ,
477
+ ( AccessType :: ReadWrite , EmitOption :: CompareMatchEvent ) => ( 0b1011 , false ) ,
478
+
479
+ ( AccessType :: ReadWrite , EmitOption :: PC ) => ( 0b0001 , false ) ,
480
+ ( _, EmitOption :: PC ) => return Err ( DwtError :: InvalidFunction ) ,
481
+ } ;
482
+
483
+ unsafe {
484
+ self . function . modify ( |mut r| {
485
+ r. set_function ( function) ;
486
+ r. set_emitrange ( emit_range) ;
487
+ // don't compare data value
488
+ r. set_datavmatch ( false ) ;
489
+ // don't compare cycle counter value
490
+ // NOTE: only needed for comparator 0, but is SBZP.
491
+ r. set_cycmatch ( false ) ;
492
+ // SBZ as needed, see Page 784/C1-724
493
+ r. set_datavsize ( 0 ) ;
494
+ r. set_datavaddr0 ( 0 ) ;
495
+ r. set_datavaddr1 ( 0 ) ;
496
+
497
+ r
498
+ } ) ;
499
+
500
+ self . comp . write ( settings. address ) ;
501
+ self . mask . write ( settings. mask ) ;
502
+ }
503
+
504
+ Ok ( ( ) )
505
+ }
506
+ }
507
+
508
+ impl Comparator < NoCycleCompare > {
509
+ /// Configure the function of the [`Comparator`]. Does not support cycle count comparison.
421
510
#[ allow( clippy:: missing_inline_in_public_items) ]
422
511
pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
423
512
match settings {
424
- ComparatorFunction :: Address ( settings) => {
425
- // FUNCTION, EMITRANGE
426
- // See Table C1-14
427
- let ( function, emit_range) = match ( & settings. access_type , & settings. emit ) {
428
- ( AccessType :: ReadOnly , EmitOption :: Data ) => ( 0b1100 , false ) ,
429
- ( AccessType :: ReadOnly , EmitOption :: Address ) => ( 0b1100 , true ) ,
430
- ( AccessType :: ReadOnly , EmitOption :: AddressData ) => ( 0b1110 , true ) ,
431
- ( AccessType :: ReadOnly , EmitOption :: PCData ) => ( 0b1110 , false ) ,
432
- ( AccessType :: ReadOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0101 , false ) ,
433
- ( AccessType :: ReadOnly , EmitOption :: CompareMatchEvent ) => ( 0b1001 , false ) ,
434
-
435
- ( AccessType :: WriteOnly , EmitOption :: Data ) => ( 0b1101 , false ) ,
436
- ( AccessType :: WriteOnly , EmitOption :: Address ) => ( 0b1101 , true ) ,
437
- ( AccessType :: WriteOnly , EmitOption :: AddressData ) => ( 0b1111 , true ) ,
438
- ( AccessType :: WriteOnly , EmitOption :: PCData ) => ( 0b1111 , false ) ,
439
- ( AccessType :: WriteOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0110 , false ) ,
440
- ( AccessType :: WriteOnly , EmitOption :: CompareMatchEvent ) => ( 0b1010 , false ) ,
441
-
442
- ( AccessType :: ReadWrite , EmitOption :: Data ) => ( 0b0010 , false ) ,
443
- ( AccessType :: ReadWrite , EmitOption :: Address ) => ( 0b0001 , true ) ,
444
- ( AccessType :: ReadWrite , EmitOption :: AddressData ) => ( 0b0010 , true ) ,
445
- ( AccessType :: ReadWrite , EmitOption :: PCData ) => ( 0b0011 , false ) ,
446
- ( AccessType :: ReadWrite , EmitOption :: WatchpointDebugEvent ) => ( 0b0111 , false ) ,
447
- ( AccessType :: ReadWrite , EmitOption :: CompareMatchEvent ) => ( 0b1011 , false ) ,
448
-
449
- ( AccessType :: ReadWrite , EmitOption :: PC ) => ( 0b0001 , false ) ,
450
- ( _, EmitOption :: PC ) => return Err ( DwtError :: InvalidFunction ) ,
451
- } ;
452
-
453
- unsafe {
454
- self . function . modify ( |mut r| {
455
- r. set_function ( function) ;
456
- r. set_emitrange ( emit_range) ;
457
- // don't compare data value
458
- r. set_datavmatch ( false ) ;
459
- // don't compare cycle counter value
460
- // NOTE: only needed for comparator 0, but is SBZP.
461
- r. set_cycmatch ( false ) ;
462
- // SBZ as needed, see Page 784/C1-724
463
- r. set_datavsize ( 0 ) ;
464
- r. set_datavaddr0 ( 0 ) ;
465
- r. set_datavaddr1 ( 0 ) ;
466
-
467
- r
468
- } ) ;
513
+ ComparatorFunction :: Address ( settings) => self . configure_address_compare ( settings) ,
514
+ ComparatorFunction :: CycleCount ( _settings) => Err ( DwtError :: UnsupportedFunction ) ,
515
+ }
516
+ }
517
+ }
469
518
470
- self . comp . write ( settings. address ) ;
471
- self . mask . write ( settings. mask ) ;
472
- }
473
- }
519
+ impl Comparator < HasCycleCompare > {
520
+ /// Configure the function of the [`Comparator`]. Has support for cycle count comparison.
521
+ #[ allow( clippy:: missing_inline_in_public_items) ]
522
+ pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
523
+ match settings {
524
+ ComparatorFunction :: Address ( settings) => self . configure_address_compare ( settings) ,
474
525
ComparatorFunction :: CycleCount ( settings) => {
475
526
let function = match & settings. emit {
476
527
EmitOption :: PCData => 0b0001 ,
@@ -499,9 +550,9 @@ impl Comparator {
499
550
self . comp . write ( settings. compare ) ;
500
551
self . mask . write ( 0 ) ; // SBZ, see Page 784/C1-724
501
552
}
553
+
554
+ Ok ( ( ) )
502
555
}
503
556
}
504
-
505
- Ok ( ( ) )
506
557
}
507
558
}
0 commit comments