11//! Instruction Cache management
22//!
3- //! To enable the the ICACHE :
3+ //! To enable the ICACHE in the default N-way set associative mode :
44//!
55//! ```
66//! let dp = ...; // Device peripherals
7- //! let mut icache = dp.ICACHE.constrain();
7+ //! let mut icache = dp.ICACHE.enable();
8+ //! ```
9+ //!
10+ //! To enable the ICACHE in a specific mode (e.g. Direct-mapped):
811//!
9- //! icache.enable();
12+ //! ```
13+ //! let dp = ...; // Device peripherals
14+ //! let mut icache = dp.ICACHE.enable_direct_mapped();
1015//! ```
1116//!
1217//! To invalidate the cache, use the ICache::invalidate() method:
2732//! let hit_count = icache.hit_count();
2833//! let miss_count = icache.miss_count();
2934//! ```
35+ //!
36+ //! Using interrupts to trigger cache invalidation and determine when it is
37+ //! complete:
38+ //!
39+ //! ```
40+ //! icache.start_invalidation();
41+ //!
42+ //! // In interrupt context
43+ //! if icache.check_event(Event::CacheInvalidationFinished) {
44+ //! icache.clear_irq(Event::CacheInvalidationFinished)
45+ //! }
46+ //! ```
47+ //!
3048
3149use crate :: stm32:: ICACHE ;
3250
33- pub trait ICacheExt {
34- fn constrain ( self ) -> ICache ;
51+ pub enum Event {
52+ CacheError ,
53+ CacheInvalidationFinished ,
54+ }
55+
56+ pub trait ICacheExt : Sized {
57+ /// Enable in N-way set associative mode (default)
58+ fn enable_n_way ( self ) -> ICache ;
59+
60+ /// Enable in direct mapped mode
61+ fn enable_direct_mapped ( self ) -> ICache ;
62+
63+ /// Enable in default mode (N-way set associative)
64+ fn enable ( self ) -> ICache {
65+ self . enable_n_way ( )
66+ }
3567}
3668
3769impl ICacheExt for ICACHE {
38- fn constrain ( self ) -> ICache {
39- ICache :: new ( self )
70+ fn enable_n_way ( self ) -> ICache {
71+ ICache :: new ( self ) . enable_n_way ( )
72+ }
73+
74+ fn enable_direct_mapped ( self ) -> ICache {
75+ ICache :: new ( self ) . enable_direct_mapped ( )
4076 }
4177}
4278
@@ -49,85 +85,106 @@ impl ICache {
4985 Self { icache }
5086 }
5187
52- pub fn is_enabled ( & self ) -> bool {
53- cortex_m:: asm:: dsb ( ) ;
54- cortex_m:: asm:: isb ( ) ;
55-
56- self . icache . cr ( ) . read ( ) . en ( ) . bit_is_set ( )
57- }
58-
5988 fn wait_for_busy_complete ( & self ) {
6089 while self . icache . sr ( ) . read ( ) . busyf ( ) . bit_is_set ( ) { }
6190 }
6291
63- /// Enable ICACHE in default operating mode (N-way associative)
64- pub fn enable ( & mut self ) {
65- self . enable_n_way ( )
66- }
67-
6892 /// Enable the ICACHE in N-way associative mode
69- pub fn enable_n_way ( & mut self ) {
70- if self . is_enabled ( ) {
71- return ;
72- }
73-
93+ fn enable_n_way ( self ) -> Self {
7494 // Wait for any ongoing cache invalidation operation to complete
7595 self . wait_for_busy_complete ( ) ;
7696
7797 self . icache
7898 . cr ( )
7999 . write ( |w| w. waysel ( ) . set_bit ( ) . en ( ) . set_bit ( ) ) ;
100+
101+ self
80102 }
81103
82104 /// Enable the ICACHE in 1-way associative mode (direct mapping)
83- pub fn enable_direct_mapped ( & mut self ) {
84- if self . is_enabled ( ) {
85- return ;
86- }
87-
105+ fn enable_direct_mapped ( self ) -> Self {
88106 // Wait for any ongoing cache invalidation operation to complete
89107 self . wait_for_busy_complete ( ) ;
90108
91109 self . icache
92110 . cr ( )
93111 . write ( |w| w. waysel ( ) . clear_bit ( ) . en ( ) . set_bit ( ) ) ;
112+
113+ self
94114 }
95115
96116 /// Disable the ICACHE
97- pub fn disable ( & mut self ) {
98- if !self . is_enabled ( ) {
99- return ;
100- }
101-
117+ pub fn disable ( mut self ) -> ICACHE {
102118 // Restore cache mode to default (N-way associative)
103119 self . icache
104120 . cr ( )
105121 . write ( |w| w. waysel ( ) . set_bit ( ) . en ( ) . clear_bit ( ) ) ;
106122
123+ // Disable interrupts
124+ self . icache
125+ . ier ( )
126+ . modify ( |_, w| w. errie ( ) . clear_bit ( ) . bsyendie ( ) . clear_bit ( ) ) ;
127+
107128 self . invalidate ( ) ;
108129
109130 cortex_m:: asm:: dsb ( ) ;
110131 cortex_m:: asm:: isb ( ) ;
132+
133+ self . free ( )
111134 }
112135
113136 /// Invalidate the ICACHE. This will block while the cache is being
114137 /// invalidated
115138 pub fn invalidate ( & mut self ) {
116- self . icache . cr ( ) . modify ( |_ , w| w . cacheinv ( ) . set_bit ( ) ) ;
139+ self . start_cache_invalidation ( ) ;
117140
118141 self . wait_for_busy_complete ( ) ;
119142
120143 cortex_m:: asm:: dsb ( ) ;
121144 cortex_m:: asm:: isb ( ) ;
122145 }
123146
124- /// Enable the cache hit counter. The number of hits can be queried with ICache::hit_counter()
125- pub fn enable_hit_counter ( & mut self ) {
126- assert ! (
127- self . is_enabled( ) ,
128- "ICACHE must be enabled before enabling the hit counter"
129- ) ;
147+ /// Start cache invalidation
148+ pub fn start_cache_invalidation ( & mut self ) {
149+ self . icache . cr ( ) . modify ( |_, w| w. cacheinv ( ) . set_bit ( ) ) ;
150+ }
151+
152+ /// Enable interrupts for the given event
153+ pub fn listen ( & mut self , event : Event ) {
154+ self . icache . ier ( ) . modify ( |_, w| match event {
155+ Event :: CacheError => w. errie ( ) . set_bit ( ) ,
156+ Event :: CacheInvalidationFinished => w. bsyendie ( ) . set_bit ( ) ,
157+ } ) ;
158+ }
159+
160+ /// Disable interrupts for the given event
161+ pub fn unlisten ( & mut self , event : Event ) {
162+ self . icache . ier ( ) . modify ( |_, w| match event {
163+ Event :: CacheError => w. errie ( ) . clear_bit ( ) ,
164+ Event :: CacheInvalidationFinished => w. bsyendie ( ) . clear_bit ( ) ,
165+ } ) ;
166+ }
167+
168+ /// Clear the IRQ for the given event
169+ pub fn clear_irq ( & mut self , event : Event ) {
170+ self . icache . fcr ( ) . write ( |w| match event {
171+ Event :: CacheError => w. cerrf ( ) . set_bit ( ) ,
172+ Event :: CacheInvalidationFinished => w. cbsyendf ( ) . set_bit ( ) ,
173+ } ) ;
174+ }
175+
176+ /// Check whether an interrupt event has occurred. Returns true if it has.
177+ /// Clear the event IRQ by calling `clear_event`
178+ pub fn check_event ( & mut self , event : Event ) -> bool {
179+ let sr = self . icache . sr ( ) . read ( ) ;
180+ match event {
181+ Event :: CacheError => sr. errf ( ) . bit_is_set ( ) ,
182+ Event :: CacheInvalidationFinished => sr. bsyendf ( ) . bit_is_set ( ) ,
183+ }
184+ }
130185
186+ /// Enable the cache hit counter. The number of hits can be queried with ICache::hit_counter()
187+ pub fn start_hit_counter ( & mut self ) {
131188 // Enable and reset the cache hit counter
132189 self . icache
133190 . cr ( )
@@ -141,29 +198,17 @@ impl ICache {
141198
142199 /// Reset the hit counter
143200 pub fn reset_hit_counter ( & mut self ) {
144- if !self . is_enabled ( ) {
145- return ;
146- }
147201 self . icache . cr ( ) . modify ( |_, w| w. hitmrst ( ) . set_bit ( ) ) ;
148202 }
149203
150204 /// Disable the hit counter. The hit counter is disabled when the peripheral
151205 /// is disabled
152- pub fn disable_hit_counter ( & mut self ) {
153- // Disabling the ICACHE disables the hitmem counter
154- if !self . is_enabled ( ) {
155- return ;
156- }
206+ pub fn stop_hit_counter ( & mut self ) {
157207 self . icache . cr ( ) . modify ( |_, w| w. hitmen ( ) . clear_bit ( ) ) ;
158208 }
159209
160210 /// Enable the cache miss counter
161- pub fn enable_miss_counter ( & mut self ) {
162- assert ! (
163- self . is_enabled( ) ,
164- "ICACHE must be enabled before enabling the miss counter"
165- ) ;
166-
211+ pub fn start_miss_counter ( & mut self ) {
167212 // Enable and reset the miss counter
168213 self . icache
169214 . cr ( )
@@ -177,19 +222,12 @@ impl ICache {
177222
178223 /// Reset the miss counter
179224 pub fn reset_miss_counter ( & mut self ) {
180- if !self . is_enabled ( ) {
181- return ;
182- }
183225 self . icache . cr ( ) . modify ( |_, w| w. missmrst ( ) . set_bit ( ) ) ;
184226 }
185227
186228 /// Disable the miss counter. The miss counter is disabled when the ICACHE
187229 /// is disabled
188- pub fn disable_miss_counter ( & mut self ) {
189- // Disabling the ICACHE disables the missmem counter
190- if !self . is_enabled ( ) {
191- return ;
192- }
230+ pub fn stop_miss_counter ( & mut self ) {
193231 self . icache . cr ( ) . modify ( |_, w| w. missmen ( ) . clear_bit ( ) ) ;
194232 }
195233
0 commit comments