1
1
//! System Control Block
2
2
3
3
use core:: ptr;
4
- #[ cfg( not( any( armv6m, armv8m_base) ) ) ]
5
- use crate :: interrupt;
6
4
7
5
use volatile_register:: RW ;
8
6
@@ -330,11 +328,16 @@ impl SCB {
330
328
// Invalidate I-Cache
331
329
cbp. iciallu ( ) ;
332
330
333
- // Enable I-Cache
334
- unsafe { self . ccr . modify ( |r| r | SCB_CCR_IC_MASK ) } ;
331
+ // Enable I-cache
332
+ extern "C" {
333
+ // see asm-v7m.s
334
+ fn __enable_icache ( ) ;
335
+ }
335
336
336
- crate :: asm:: dsb ( ) ;
337
- crate :: asm:: isb ( ) ;
337
+ // NOTE(unsafe): The asm routine manages exclusive access to the SCB
338
+ // registers and applies the proper barriers; it is technically safe on
339
+ // its own, and is only `unsafe` here because it's `extern "C"`.
340
+ unsafe { __enable_icache ( ) ; }
338
341
}
339
342
340
343
/// Disables I-Cache if currently enabled
@@ -392,11 +395,16 @@ impl SCB {
392
395
// Invalidate anything currently in the DCache
393
396
self . invalidate_dcache ( cpuid) ;
394
397
395
- // Now turn on the DCache
396
- unsafe { self . ccr . modify ( |r| r | SCB_CCR_DC_MASK ) } ;
398
+ // Now turn on the D-cache
399
+ extern "C" {
400
+ // see asm-v7m.s
401
+ fn __enable_dcache ( ) ;
402
+ }
397
403
398
- crate :: asm:: dsb ( ) ;
399
- crate :: asm:: isb ( ) ;
404
+ // NOTE(unsafe): The asm routine manages exclusive access to the SCB
405
+ // registers and applies the proper barriers; it is technically safe on
406
+ // its own, and is only `unsafe` here because it's `extern "C"`.
407
+ unsafe { __enable_dcache ( ) ; }
400
408
}
401
409
402
410
/// Disables D-cache if currently enabled
@@ -706,7 +714,7 @@ impl SCB {
706
714
}
707
715
}
708
716
709
- /// Set the PENDSTCLR bit in the ICSR register which will clear a pending SysTick interrupt
717
+ /// Set the PENDSTSET bit in the ICSR register which will pend a SysTick interrupt
710
718
#[ inline]
711
719
pub fn set_pendst ( ) {
712
720
unsafe {
@@ -842,6 +850,20 @@ impl SCB {
842
850
}
843
851
}
844
852
853
+ /// Return the bit position of the exception enable bit in the SHCSR register
854
+ #[ inline]
855
+ #[ cfg( not( any( armv6m, armv8m_base) ) ) ]
856
+ fn shcsr_enable_shift ( exception : Exception ) -> Option < u32 > {
857
+ match exception {
858
+ Exception :: MemoryManagement => Some ( 16 ) ,
859
+ Exception :: BusFault => Some ( 17 ) ,
860
+ Exception :: UsageFault => Some ( 18 ) ,
861
+ #[ cfg( armv8m_main) ]
862
+ Exception :: SecureFault => Some ( 19 ) ,
863
+ _ => None ,
864
+ }
865
+ }
866
+
845
867
/// Enable the exception
846
868
///
847
869
/// If the exception is enabled, when the exception is triggered, the exception handler will be executed instead of the
@@ -856,24 +878,11 @@ impl SCB {
856
878
#[ inline]
857
879
#[ cfg( not( any( armv6m, armv8m_base) ) ) ]
858
880
pub fn enable ( & mut self , exception : Exception ) {
859
- if self . is_enabled ( exception) {
860
- return ;
861
- }
862
-
863
- // Make sure that the read-modify-write sequence happens during a critical section to avoid
864
- // modifying pending and active interrupts.
865
- interrupt:: free ( |_| {
866
- let shift = match exception {
867
- Exception :: MemoryManagement => 16 ,
868
- Exception :: BusFault => 17 ,
869
- Exception :: UsageFault => 18 ,
870
- #[ cfg( armv8m_main) ]
871
- Exception :: SecureFault => 19 ,
872
- _ => return ,
873
- } ;
874
-
881
+ if let Some ( shift) = SCB :: shcsr_enable_shift ( exception) {
882
+ // The mutable reference to SCB makes sure that only this code is currently modifying
883
+ // the register.
875
884
unsafe { self . shcsr . modify ( |value| value | ( 1 << shift) ) }
876
- } )
885
+ }
877
886
}
878
887
879
888
/// Disable the exception
@@ -890,24 +899,11 @@ impl SCB {
890
899
#[ inline]
891
900
#[ cfg( not( any( armv6m, armv8m_base) ) ) ]
892
901
pub fn disable ( & mut self , exception : Exception ) {
893
- if !self . is_enabled ( exception) {
894
- return ;
895
- }
896
-
897
- // Make sure that the read-modify-write sequence happens during a critical section to avoid
898
- // modifying pending and active interrupts.
899
- interrupt:: free ( |_| {
900
- let shift = match exception {
901
- Exception :: MemoryManagement => 16 ,
902
- Exception :: BusFault => 17 ,
903
- Exception :: UsageFault => 18 ,
904
- #[ cfg( armv8m_main) ]
905
- Exception :: SecureFault => 19 ,
906
- _ => return ,
907
- } ;
908
-
902
+ if let Some ( shift) = SCB :: shcsr_enable_shift ( exception) {
903
+ // The mutable reference to SCB makes sure that only this code is currently modifying
904
+ // the register.
909
905
unsafe { self . shcsr . modify ( |value| value & !( 1 << shift) ) }
910
- } )
906
+ }
911
907
}
912
908
913
909
/// Check if an exception is enabled
@@ -921,16 +917,11 @@ impl SCB {
921
917
/// Calling this function with any other exception will read `false`.
922
918
#[ inline]
923
919
#[ cfg( not( any( armv6m, armv8m_base) ) ) ]
924
- pub fn is_enabled ( & mut self , exception : Exception ) -> bool {
925
- let shift = match exception {
926
- Exception :: MemoryManagement => 16 ,
927
- Exception :: BusFault => 17 ,
928
- Exception :: UsageFault => 18 ,
929
- #[ cfg( armv8m_main) ]
930
- Exception :: SecureFault => 19 ,
931
- _ => return false ,
932
- } ;
933
-
934
- ( self . shcsr . read ( ) & ( 1 << shift) ) > 0
920
+ pub fn is_enabled ( & self , exception : Exception ) -> bool {
921
+ if let Some ( shift) = SCB :: shcsr_enable_shift ( exception) {
922
+ ( self . shcsr . read ( ) & ( 1 << shift) ) > 0
923
+ } else {
924
+ false
925
+ }
935
926
}
936
927
}
0 commit comments