@@ -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 ! {
@@ -402,63 +428,88 @@ pub enum ComparatorFunction {
402
428
pub enum DwtError {
403
429
/// Invalid combination of [AccessType] and [EmitOption].
404
430
InvalidFunction ,
431
+ /// An unsupported function was requested, such as [`CycleCount`](ComparatorFunction::CycleCount) on
432
+ /// `armv6m`, or on a comparator other than 0 on `armv7m`.
433
+ UnsupportedFunction ,
405
434
}
406
435
407
- impl Comparator {
408
- /// Configure the function of the comparator
436
+ impl < SupportedFunctions : ComparatorSupportedFunctions > Comparator < SupportedFunctions > {
437
+ /// Private function for configuring address compare on any [`Comparator`] since they all support this.
438
+ /// Utilized publicly through [`Comparator::configure`]
439
+ fn configure_address_compare (
440
+ & self ,
441
+ settings : ComparatorAddressSettings ,
442
+ ) -> Result < ( ) , DwtError > {
443
+ // FUNCTION, EMITRANGE
444
+ // See Table C1-14
445
+ let ( function, emit_range) = match ( & settings. access_type , & settings. emit ) {
446
+ ( AccessType :: ReadOnly , EmitOption :: Data ) => ( 0b1100 , false ) ,
447
+ ( AccessType :: ReadOnly , EmitOption :: Address ) => ( 0b1100 , true ) ,
448
+ ( AccessType :: ReadOnly , EmitOption :: AddressData ) => ( 0b1110 , true ) ,
449
+ ( AccessType :: ReadOnly , EmitOption :: PCData ) => ( 0b1110 , false ) ,
450
+ ( AccessType :: ReadOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0101 , false ) ,
451
+ ( AccessType :: ReadOnly , EmitOption :: CompareMatchEvent ) => ( 0b1001 , false ) ,
452
+
453
+ ( AccessType :: WriteOnly , EmitOption :: Data ) => ( 0b1101 , false ) ,
454
+ ( AccessType :: WriteOnly , EmitOption :: Address ) => ( 0b1101 , true ) ,
455
+ ( AccessType :: WriteOnly , EmitOption :: AddressData ) => ( 0b1111 , true ) ,
456
+ ( AccessType :: WriteOnly , EmitOption :: PCData ) => ( 0b1111 , false ) ,
457
+ ( AccessType :: WriteOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0110 , false ) ,
458
+ ( AccessType :: WriteOnly , EmitOption :: CompareMatchEvent ) => ( 0b1010 , false ) ,
459
+
460
+ ( AccessType :: ReadWrite , EmitOption :: Data ) => ( 0b0010 , false ) ,
461
+ ( AccessType :: ReadWrite , EmitOption :: Address ) => ( 0b0001 , true ) ,
462
+ ( AccessType :: ReadWrite , EmitOption :: AddressData ) => ( 0b0010 , true ) ,
463
+ ( AccessType :: ReadWrite , EmitOption :: PCData ) => ( 0b0011 , false ) ,
464
+ ( AccessType :: ReadWrite , EmitOption :: WatchpointDebugEvent ) => ( 0b0111 , false ) ,
465
+ ( AccessType :: ReadWrite , EmitOption :: CompareMatchEvent ) => ( 0b1011 , false ) ,
466
+
467
+ ( AccessType :: ReadWrite , EmitOption :: PC ) => ( 0b0001 , false ) ,
468
+ ( _, EmitOption :: PC ) => return Err ( DwtError :: InvalidFunction ) ,
469
+ } ;
470
+
471
+ unsafe {
472
+ self . function . modify ( |mut r| {
473
+ r. set_function ( function) ;
474
+ r. set_emitrange ( emit_range) ;
475
+ // don't compare data value
476
+ r. set_datavmatch ( false ) ;
477
+ // don't compare cycle counter value
478
+ // NOTE: only needed for comparator 0, but is SBZP.
479
+ r. set_cycmatch ( false ) ;
480
+ // SBZ as needed, see Page 784/C1-724
481
+ r. set_datavsize ( 0 ) ;
482
+ r. set_datavaddr0 ( 0 ) ;
483
+ r. set_datavaddr1 ( 0 ) ;
484
+
485
+ r
486
+ } ) ;
487
+
488
+ self . comp . write ( settings. address ) ;
489
+ self . mask . write ( settings. mask ) ;
490
+ }
491
+
492
+ Ok ( ( ) )
493
+ }
494
+ }
495
+
496
+ impl Comparator < NoCycleCompare > {
497
+ /// Configure the function of the [`Comparator`]. Does not support cycle count comparison.
409
498
#[ allow( clippy:: missing_inline_in_public_items) ]
410
499
pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
411
500
match settings {
412
- ComparatorFunction :: Address ( settings) => {
413
- // FUNCTION, EMITRANGE
414
- // See Table C1-14
415
- let ( function, emit_range) = match ( & settings. access_type , & settings. emit ) {
416
- ( AccessType :: ReadOnly , EmitOption :: Data ) => ( 0b1100 , false ) ,
417
- ( AccessType :: ReadOnly , EmitOption :: Address ) => ( 0b1100 , true ) ,
418
- ( AccessType :: ReadOnly , EmitOption :: AddressData ) => ( 0b1110 , true ) ,
419
- ( AccessType :: ReadOnly , EmitOption :: PCData ) => ( 0b1110 , false ) ,
420
- ( AccessType :: ReadOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0101 , false ) ,
421
- ( AccessType :: ReadOnly , EmitOption :: CompareMatchEvent ) => ( 0b1001 , false ) ,
422
-
423
- ( AccessType :: WriteOnly , EmitOption :: Data ) => ( 0b1101 , false ) ,
424
- ( AccessType :: WriteOnly , EmitOption :: Address ) => ( 0b1101 , true ) ,
425
- ( AccessType :: WriteOnly , EmitOption :: AddressData ) => ( 0b1111 , true ) ,
426
- ( AccessType :: WriteOnly , EmitOption :: PCData ) => ( 0b1111 , false ) ,
427
- ( AccessType :: WriteOnly , EmitOption :: WatchpointDebugEvent ) => ( 0b0110 , false ) ,
428
- ( AccessType :: WriteOnly , EmitOption :: CompareMatchEvent ) => ( 0b1010 , false ) ,
429
-
430
- ( AccessType :: ReadWrite , EmitOption :: Data ) => ( 0b0010 , false ) ,
431
- ( AccessType :: ReadWrite , EmitOption :: Address ) => ( 0b0001 , true ) ,
432
- ( AccessType :: ReadWrite , EmitOption :: AddressData ) => ( 0b0010 , true ) ,
433
- ( AccessType :: ReadWrite , EmitOption :: PCData ) => ( 0b0011 , false ) ,
434
- ( AccessType :: ReadWrite , EmitOption :: WatchpointDebugEvent ) => ( 0b0111 , false ) ,
435
- ( AccessType :: ReadWrite , EmitOption :: CompareMatchEvent ) => ( 0b1011 , false ) ,
436
-
437
- ( AccessType :: ReadWrite , EmitOption :: PC ) => ( 0b0001 , false ) ,
438
- ( _, EmitOption :: PC ) => return Err ( DwtError :: InvalidFunction ) ,
439
- } ;
440
-
441
- unsafe {
442
- self . function . modify ( |mut r| {
443
- r. set_function ( function) ;
444
- r. set_emitrange ( emit_range) ;
445
- // don't compare data value
446
- r. set_datavmatch ( false ) ;
447
- // don't compare cycle counter value
448
- // NOTE: only needed for comparator 0, but is SBZP.
449
- r. set_cycmatch ( false ) ;
450
- // SBZ as needed, see Page 784/C1-724
451
- r. set_datavsize ( 0 ) ;
452
- r. set_datavaddr0 ( 0 ) ;
453
- r. set_datavaddr1 ( 0 ) ;
454
-
455
- r
456
- } ) ;
501
+ ComparatorFunction :: Address ( settings) => self . configure_address_compare ( settings) ,
502
+ ComparatorFunction :: CycleCount ( _settings) => Err ( DwtError :: UnsupportedFunction ) ,
503
+ }
504
+ }
505
+ }
457
506
458
- self . comp . write ( settings. address ) ;
459
- self . mask . write ( settings. mask ) ;
460
- }
461
- }
507
+ impl Comparator < HasCycleCompare > {
508
+ /// Configure the function of the [`Comparator`]. Has support for cycle count comparison.
509
+ #[ allow( clippy:: missing_inline_in_public_items) ]
510
+ pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
511
+ match settings {
512
+ ComparatorFunction :: Address ( settings) => self . configure_address_compare ( settings) ,
462
513
ComparatorFunction :: CycleCount ( settings) => {
463
514
let function = match & settings. emit {
464
515
EmitOption :: PCData => 0b0001 ,
@@ -487,9 +538,9 @@ impl Comparator {
487
538
self . comp . write ( settings. compare ) ;
488
539
self . mask . write ( 0 ) ; // SBZ, see Page 784/C1-724
489
540
}
541
+
542
+ Ok ( ( ) )
490
543
}
491
544
}
492
-
493
- Ok ( ( ) )
494
545
}
495
546
}
0 commit comments