@@ -37,10 +37,13 @@ pub struct RegisterBlock {
3737 pub pcsr : RO < u32 > ,
3838 /// Comparators
3939 #[ 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 > ,
4144 #[ cfg( not( armv6m) ) ]
4245 /// Comparators
43- pub c : [ Comparator ; 16 ] ,
46+ pub comp : [ Comparator < NoCycleCompare > ; 15 ] ,
4447 #[ cfg( not( armv6m) ) ]
4548 reserved : [ u32 ; 932 ] ,
4649 /// Lock Access
@@ -66,16 +69,39 @@ bitfield! {
6669 u8 , numcomp, _: 31 , 28 ;
6770}
6871
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+
6994/// Comparator
7095#[ repr( C ) ]
71- pub struct Comparator {
96+ pub struct Comparator < SupportedFunctions : ComparatorSupportedFunctions > {
7297 /// Comparator
7398 pub comp : RW < u32 > ,
7499 /// Comparator Mask
75100 pub mask : RW < u32 > ,
76101 /// Comparator Function
77102 pub function : RW < Function > ,
78103 reserved : u32 ,
104+ _supported_functions : core:: marker:: PhantomData < SupportedFunctions > ,
79105}
80106
81107bitfield ! {
@@ -402,63 +428,88 @@ pub enum ComparatorFunction {
402428pub enum DwtError {
403429 /// Invalid combination of [AccessType] and [EmitOption].
404430 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 ,
405434}
406435
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.
409498 #[ allow( clippy:: missing_inline_in_public_items) ]
410499 pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
411500 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+ }
457506
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) ,
462513 ComparatorFunction :: CycleCount ( settings) => {
463514 let function = match & settings. emit {
464515 EmitOption :: PCData => 0b0001 ,
@@ -487,9 +538,9 @@ impl Comparator {
487538 self . comp . write ( settings. compare ) ;
488539 self . mask . write ( 0 ) ; // SBZ, see Page 784/C1-724
489540 }
541+
542+ Ok ( ( ) )
490543 }
491544 }
492-
493- Ok ( ( ) )
494545 }
495546}
0 commit comments