@@ -669,3 +669,115 @@ impl SCB {
669
669
}
670
670
}
671
671
}
672
+
673
+ /// System handlers, exceptions with configurable priority
674
+ #[ allow( non_camel_case_types) ]
675
+ #[ derive( Clone , Copy , Debug , Eq , PartialEq ) ]
676
+ pub enum SystemHandler {
677
+ // NonMaskableInt, // priority is fixed
678
+ // HardFault, // priority is fixed
679
+ /// Memory management interrupt (not present on Cortex-M0 variants)
680
+ #[ cfg( not( armv6m) ) ]
681
+ MemoryManagement ,
682
+
683
+ /// Bus fault interrupt (not present on Cortex-M0 variants)
684
+ #[ cfg( not( armv6m) ) ]
685
+ BusFault ,
686
+
687
+ /// Usage fault interrupt (not present on Cortex-M0 variants)
688
+ #[ cfg( not( armv6m) ) ]
689
+ UsageFault ,
690
+
691
+ /// Secure fault interrupt (only on ARMv8-M)
692
+ #[ cfg( any( armv8m, target_arch = "x86_64" ) ) ]
693
+ SecureFault ,
694
+
695
+ /// SV call interrupt
696
+ SVCall ,
697
+
698
+ /// Debug monitor interrupt (not present on Cortex-M0 variants)
699
+ #[ cfg( not( armv6m) ) ]
700
+ DebugMonitor ,
701
+
702
+ /// Pend SV interrupt
703
+ PendSV ,
704
+
705
+ /// System Tick interrupt
706
+ SysTick ,
707
+ }
708
+
709
+ impl SystemHandler {
710
+ fn index ( & self ) -> u8 {
711
+ match * self {
712
+ #[ cfg( not( armv6m) ) ]
713
+ SystemHandler :: MemoryManagement => 4 ,
714
+ #[ cfg( not( armv6m) ) ]
715
+ SystemHandler :: BusFault => 5 ,
716
+ #[ cfg( not( armv6m) ) ]
717
+ SystemHandler :: UsageFault => 6 ,
718
+ #[ cfg( any( armv8m, target_arch = "x86_64" ) ) ]
719
+ SystemHandler :: SecureFault => 7 ,
720
+ SystemHandler :: SVCall => 11 ,
721
+ #[ cfg( not( armv6m) ) ]
722
+ SystemHandler :: DebugMonitor => 12 ,
723
+ SystemHandler :: PendSV => 14 ,
724
+ SystemHandler :: SysTick => 15 ,
725
+ }
726
+ }
727
+ }
728
+
729
+ impl SCB {
730
+ /// Returns the hardware priority of `system_handler`
731
+ ///
732
+ /// *NOTE*: Hardware priority does not exactly match logical priority levels. See
733
+ /// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
734
+ pub fn get_priority ( system_handler : SystemHandler ) -> u8 {
735
+ let index = system_handler. index ( ) ;
736
+
737
+ #[ cfg( not( armv6m) ) ]
738
+ {
739
+ // NOTE(unsafe) atomic read with no side effects
740
+ unsafe { ( * Self :: ptr ( ) ) . shpr [ usize:: from ( index - 4 ) ] . read ( ) }
741
+ }
742
+
743
+ #[ cfg( armv6m) ]
744
+ {
745
+ // NOTE(unsafe) atomic read with no side effects
746
+ let shpr = unsafe { ( * Self :: ptr ( ) ) . shpr [ usize:: from ( ( index - 8 ) / 4 ) ] . read ( ) } ;
747
+ let prio = ( shpr >> ( 8 * ( index % 4 ) ) ) & 0x000000ff ;
748
+ prio as u8
749
+ }
750
+ }
751
+
752
+ /// Sets the hardware priority of `system_handler` to `prio`
753
+ ///
754
+ /// *NOTE*: Hardware priority does not exactly match logical priority levels. See
755
+ /// [`NVIC.get_priority`](struct.NVIC.html#method.get_priority) for more details.
756
+ ///
757
+ /// On ARMv6-M, updating a system handler priority requires a read-modify-write operation. On
758
+ /// ARMv7-M, the operation is performed in a single, atomic write operation.
759
+ ///
760
+ /// # Unsafety
761
+ ///
762
+ /// Changing priority levels can break priority-based critical sections (see
763
+ /// [`register::basepri`](../register/basepri/index.html)) and compromise memory safety.
764
+ pub unsafe fn set_priority ( & mut self , system_handler : SystemHandler , prio : u8 ) {
765
+ let index = system_handler. index ( ) ;
766
+
767
+ #[ cfg( not( armv6m) ) ]
768
+ {
769
+ self . shpr [ usize:: from ( index - 4 ) ] . write ( prio)
770
+ }
771
+
772
+ #[ cfg( armv6m) ]
773
+ {
774
+ self . shpr [ usize:: from ( ( index - 8 ) / 4 ) ] . modify ( |value| {
775
+ let shift = 8 * ( index % 4 ) ;
776
+ let mask = 0x000000ff << shift;
777
+ let prio = u32:: from ( prio) << shift;
778
+
779
+ ( value & !mask) | prio
780
+ } ) ;
781
+ }
782
+ }
783
+ }
0 commit comments