@@ -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 ! {
@@ -414,63 +440,88 @@ pub enum ComparatorFunction {
414440pub enum DwtError {
415441 /// Invalid combination of [AccessType] and [EmitOption].
416442 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 ,
417446}
418447
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.
421510 #[ allow( clippy:: missing_inline_in_public_items) ]
422511 pub fn configure ( & self , settings : ComparatorFunction ) -> Result < ( ) , DwtError > {
423512 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+ }
469518
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) ,
474525 ComparatorFunction :: CycleCount ( settings) => {
475526 let function = match & settings. emit {
476527 EmitOption :: PCData => 0b0001 ,
@@ -499,9 +550,9 @@ impl Comparator {
499550 self . comp . write ( settings. compare ) ;
500551 self . mask . write ( 0 ) ; // SBZ, see Page 784/C1-724
501552 }
553+
554+ Ok ( ( ) )
502555 }
503556 }
504-
505- Ok ( ( ) )
506557 }
507558}
0 commit comments