stm32f4xx/
flash.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright OxidOS Automotive SRL.
4
5//! STM32F4xx flash driver
6//!
7//! This driver provides basic functionalities for the entire STM32F4 series.
8//!
9//! # Features
10//!
11//! - [x] Configuring latency based on the system clock frequency
12//!
13//! # Missing features
14//!
15//! - [ ] Support for different power supplies
16//! - [ ] Instruction prefetch
17//! - [ ] Instruction and data cache
18//!
19//!
20//! # Usage
21//!
22//! To use this driver, a reference to the Flash peripheral is required:
23//!
24//! ```rust,ignore
25//! // Inside the board main.rs
26//! let flash = &peripherals.stm32f4.flash;
27//! ```
28//!
29//! ## Retrieve the current flash latency
30//!
31//! ```rust,ignore
32//! let flash_latency = flash.get_latency() as usize;
33//! debug!("Current flash latency is {}", flash_latency);
34//! ```
35
36use crate::chip_specific::flash::FlashChipSpecific as FlashChipSpecificTrait;
37use crate::chip_specific::flash::FlashLatency16;
38use crate::chip_specific::flash::RegisterToFlashLatency;
39
40use kernel::debug;
41use kernel::utilities::registers::interfaces::{ReadWriteable, Readable};
42use kernel::utilities::registers::{register_bitfields, ReadWrite, WriteOnly};
43use kernel::utilities::StaticRef;
44use kernel::ErrorCode;
45
46use core::marker::PhantomData;
47
48#[repr(C)]
49struct FlashRegisters {
50    /// Flash access control register
51    acr: ReadWrite<u32, ACR::Register>,
52    /// Flash key register
53    keyr: WriteOnly<u32>,
54    /// Flash option key register
55    optkeyr: WriteOnly<u32>,
56    /// Status register
57    sr: ReadWrite<u32, SR::Register>,
58    /// Control register
59    cr: ReadWrite<u32, CR::Register>,
60    /// Flash option control register
61    optcr: ReadWrite<u32, OPTCR::Register>,
62    /// Flash option control register 1
63    #[cfg(feature = "stm32f429")]
64    optcr1: ReadWrite<u32, OPTCR1::Register>,
65}
66
67register_bitfields![u32,
68    ACR [
69        /// Latency
70        // NOTE: This bit field can be either 3 or 4 bits long
71        LATENCY OFFSET(0) NUMBITS(4) [],
72        /// Prefetch enable
73        PRFTEN OFFSET(8) NUMBITS(1) [],
74        /// Instruction cache enable
75        ICEN OFFSET(9) NUMBITS(1) [],
76        /// Data cache enable
77        DCEN OFFSET(10) NUMBITS(1) [],
78        /// Instruction cache reset
79        ICRST OFFSET(11) NUMBITS(1) [],
80        /// Data cache reset
81        DCRST OFFSET(12) NUMBITS(1) []
82    ],
83    KEYR [
84        /// FPEC key
85        KEY OFFSET(0) NUMBITS(32) []
86    ],
87    OPTKEYR [
88        /// Option byte key
89        OPTKEY OFFSET(0) NUMBITS(32) []
90    ],
91    SR [
92        /// End of operation
93        EOP OFFSET(0) NUMBITS(1) [],
94        /// Operation error
95        OPERR OFFSET(1) NUMBITS(1) [],
96        /// Write protection error
97        WRPERR OFFSET(4) NUMBITS(1) [],
98        /// Programming alignment error
99        PGAERR OFFSET(5) NUMBITS(1) [],
100        /// Programming parallelism error
101        PGPERR OFFSET(6) NUMBITS(1) [],
102        /// Programming sequence error
103        PGSERR OFFSET(7) NUMBITS(1) [],
104        /// Read protection error
105        // NOTE: This bit field is not available on STM32F405, STM32F415, STM32F407 and STM32F417
106        RDERR OFFSET(8) NUMBITS(1) [],
107        /// Busy
108        BSY OFFSET(16) NUMBITS(1) []
109    ],
110    CR [
111        /// Programming
112        PG OFFSET(0) NUMBITS(1) [],
113        /// Sector Erase
114        SER OFFSET(1) NUMBITS(1) [],
115        /// Mass Erase of sectors 0 to 11
116        MER OFFSET(2) NUMBITS(1) [],
117        /// Sector number
118        // NOTE: This bit field can be either 4 or 5 bits long depending on the chip model
119        SNB OFFSET(3) NUMBITS(5) [],
120        /// Program size
121        PSIZE OFFSET(8) NUMBITS(2) [],
122        /// Mass Erase of sectors 12 to 23
123        // NOTE: This bit is not available on all chip models
124        MER1 OFFSET(15) NUMBITS(1) [],
125        /// Start
126        STRT OFFSET(16) NUMBITS(1) [],
127        /// End of operation interrupt enable
128        EOPIE OFFSET(24) NUMBITS(1) [],
129        /// Error interrupt enable
130        ERRIE OFFSET(25) NUMBITS(1) [],
131        /// Lock
132        LOCK OFFSET(31) NUMBITS(1) []
133    ],
134    OPTCR [
135        /// Option lock
136        OPTLOCK OFFSET(0) NUMBITS(1) [],
137        /// Option start
138        OPTSTRT OFFSET(1) NUMBITS(1) [],
139        /// BOR reset Level
140        BOR_LEV OFFSET(2) NUMBITS(2) [],
141        /// WDG_SW User option bytes
142        WDG_SW OFFSET(5) NUMBITS(1) [],
143        /// nRST_STOP User option bytes
144        nRST_STOP OFFSET(6) NUMBITS(1) [],
145        /// nRST_STDBY User option bytes
146        nRST_STDBY OFFSET(7) NUMBITS(1) [],
147        /// Read protect
148        RDP OFFSET(8) NUMBITS(8) [],
149        /// Not write protect
150        // NOTE: The length of this bit field varies with the chip model
151        nWRP OFFSET(16) NUMBITS(12) []
152    ],
153    OPTCR1 [
154        /// Not write protect
155        // NOTE: The length of this bit field varies with the chip model
156        nWRP OFFSET(16) NUMBITS(12) []
157    ]
158];
159
160// All chips models have the same FLASH_BASE
161const FLASH_BASE: StaticRef<FlashRegisters> =
162    unsafe { StaticRef::new(0x40023C00 as *const FlashRegisters) };
163
164/// Main Flash struct
165pub struct Flash<FlashChipSpecific> {
166    registers: StaticRef<FlashRegisters>,
167    _marker: PhantomData<FlashChipSpecific>,
168}
169
170impl<FlashChipSpecific: FlashChipSpecificTrait> Flash<FlashChipSpecific> {
171    // Flash constructor. It should be called when creating Stm32f4xxDefaultPeripherals.
172    pub(crate) fn new() -> Self {
173        Self {
174            registers: FLASH_BASE,
175            _marker: PhantomData,
176        }
177    }
178
179    fn read_latency_from_register(&self) -> u32 {
180        self.registers.acr.read(ACR::LATENCY)
181    }
182
183    // TODO: Take into the account the power supply
184    //
185    // NOTE: This method is pub(crate) to prevent modifying the flash latency from board files.
186    // Flash latency is dependent on the system clock frequency. Other peripherals will modify this
187    // when appropriate.
188    pub(crate) fn set_latency(&self, sys_clock_frequency: usize) -> Result<(), ErrorCode> {
189        let flash_latency =
190            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(sys_clock_frequency);
191        self.registers
192            .acr
193            .modify(ACR::LATENCY.val(flash_latency.into()));
194
195        // Wait until the flash latency is set
196        // The value 16 was chosen randomly, but it behaves well in tests. It can be tuned in a
197        // future revision of the driver.
198        for _ in 0..16 {
199            if self.get_latency() == flash_latency {
200                return Ok(());
201            }
202        }
203
204        // Return BUSY if setting the frequency took too long. The caller can either:
205        //
206        // + recall this method
207        // + or busy wait get_latency() until the flash latency has the desired value
208        Err(ErrorCode::BUSY)
209    }
210
211    pub(crate) fn get_latency(&self) -> FlashChipSpecific::FlashLatency {
212        FlashChipSpecific::FlashLatency::convert_register_to_enum(self.read_latency_from_register())
213    }
214}
215
216/// Tests for the STM32F4xx flash driver.
217///
218/// If any contributions are made to this driver, it is highly recommended to run these tests to
219/// ensure that everything still works as expected. The tests are chip agnostic. They can be run
220/// on any STM32F4 chips.
221///
222/// # Usage
223///
224/// First, the flash module must be imported:
225///
226/// ```rust,ignore
227/// // Change this line depending on the chip the board is using
228/// use stm32f429zi::flash;
229/// ```
230///
231/// Then, get a reference to the peripheral:
232///
233/// ```rust,ignore
234/// // Inside the board main.rs
235/// let flash = &peripherals.stm32f4.flash;
236/// ```
237///
238/// To run all tests:
239///
240/// ```rust,ignore
241/// flash::tests::run_all(flash);
242/// ```
243///
244/// The following output should be printed:
245///
246/// ```text
247/// ===============================================
248/// Testing setting flash latency...
249///
250/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251/// Testing number of wait cycles based on the system frequency...
252/// Finished testing number of wait cycles based on the system clock frequency. Everything is alright!
253/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
254///
255///
256/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
257/// Testing setting flash latency...
258/// Finished testing setting flash latency. Everything is alright!
259/// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
260///
261/// Finished testing flash. Everything is alright!
262/// ===============================================
263/// ```
264///
265/// To run individual tests, see the functions in this module.
266///
267/// # Errors
268///
269/// In case of any errors, open an issue ticket at <https://github.com/tock/tock>. Please provide
270/// the output of the test execution.
271pub mod tests {
272    use super::{debug, Flash, FlashChipSpecificTrait, FlashLatency16};
273    use crate::clocks::hsi::HSI_FREQUENCY_MHZ;
274
275    const AHB_ETHERNET_MINIMUM_FREQUENCY_MHZ: usize = 25;
276    // Different chips have different maximum values for APB1
277    const APB1_MAX_FREQUENCY_MHZ_1: usize = 42;
278    const APB1_MAX_FREQUENCY_MHZ_2: usize = 45;
279    const APB1_MAX_FREQUENCY_MHZ_3: usize = 50;
280    // Different chips have different maximum values for APB2
281    const APB2_MAX_FREQUENCY_MHZ_1: usize = 84;
282    #[cfg(not(feature = "stm32f401"))] // Not needed for this chip model
283    const APB2_MAX_FREQUENCY_MHZ_2: usize = 90;
284    #[cfg(not(feature = "stm32f401"))] // Not needed for this chip model
285    const APB2_MAX_FREQUENCY_MHZ_3: usize = 100;
286    // Many STM32F4 chips allow a maximum frequency of 168MHz and some of them 180MHz if overdrive
287    // is turned on
288    #[cfg(not(any(feature = "stm32f401", feature = "stm32f412",)))] // Not needed for these chips
289    const SYS_MAX_FREQUENCY_NO_OVERDRIVE_MHZ: usize = 168;
290    #[cfg(not(any(feature = "stm32f401", feature = "stm32f412",)))] // Not needed for these chips
291    const SYS_MAX_FREQUENCY_OVERDRIVE_MHZ: usize = 180;
292    // Default PLL frequency
293    #[cfg(not(feature = "stm32f401"))] // Not needed for this chip model
294    const PLL_FREQUENCY_MHZ: usize = 96;
295
296    //#[cfg(any(
297    //feature = "stm32f401",
298    //feature = "stm32f412",
299    //feature = "stm32f429",
300    //feature = "stm32f446"
301    //))]
302    /// Test for the mapping between the system clock frequency and flash latency
303    ///
304    /// It is highly recommended to run this test since everything else depends on it.
305    pub fn test_get_number_wait_cycles_based_on_frequency<
306        FlashChipSpecific: FlashChipSpecificTrait<FlashLatency = FlashLatency16>,
307    >() {
308        debug!("");
309        debug!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
310        debug!("Testing number of wait cycles based on the system frequency...");
311
312        assert_eq!(
313            FlashChipSpecific::FlashLatency::Latency0,
314            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(HSI_FREQUENCY_MHZ)
315        );
316
317        assert_eq!(
318            FlashChipSpecific::FlashLatency::Latency0,
319            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(
320                AHB_ETHERNET_MINIMUM_FREQUENCY_MHZ
321            )
322        );
323
324        assert_eq!(
325            FlashChipSpecific::FlashLatency::Latency1,
326            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(APB1_MAX_FREQUENCY_MHZ_1)
327        );
328        assert_eq!(
329            FlashChipSpecific::FlashLatency::Latency1,
330            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(APB1_MAX_FREQUENCY_MHZ_2)
331        );
332        assert_eq!(
333            FlashChipSpecific::FlashLatency::Latency1,
334            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(APB1_MAX_FREQUENCY_MHZ_3)
335        );
336
337        assert_eq!(
338            FlashChipSpecific::FlashLatency::Latency2,
339            FlashChipSpecific::get_number_wait_cycles_based_on_frequency(APB2_MAX_FREQUENCY_MHZ_1)
340        );
341
342        // STM32F401 maximum clock frequency is 84MHz
343        #[cfg(not(feature = "stm32f401"))]
344        {
345            assert_eq!(
346                FlashChipSpecific::FlashLatency::Latency2,
347                FlashChipSpecific::get_number_wait_cycles_based_on_frequency(
348                    APB2_MAX_FREQUENCY_MHZ_2
349                )
350            );
351
352            assert_eq!(
353                FlashChipSpecific::FlashLatency::Latency3,
354                FlashChipSpecific::get_number_wait_cycles_based_on_frequency(
355                    APB2_MAX_FREQUENCY_MHZ_3
356                )
357            );
358
359            assert_eq!(
360                FlashChipSpecific::FlashLatency::Latency3,
361                FlashChipSpecific::get_number_wait_cycles_based_on_frequency(PLL_FREQUENCY_MHZ)
362            );
363        }
364
365        #[cfg(not(any(feature = "stm32f401", feature = "stm32f412",)))]
366        // Not needed for these chips
367        {
368            assert_eq!(
369                FlashChipSpecific::FlashLatency::Latency5,
370                FlashChipSpecific::get_number_wait_cycles_based_on_frequency(
371                    SYS_MAX_FREQUENCY_NO_OVERDRIVE_MHZ
372                )
373            );
374
375            assert_eq!(
376                FlashChipSpecific::FlashLatency::Latency5,
377                FlashChipSpecific::get_number_wait_cycles_based_on_frequency(
378                    SYS_MAX_FREQUENCY_OVERDRIVE_MHZ
379                )
380            );
381        }
382
383        debug!("Finished testing number of wait cycles based on the system clock frequency. Everything is alright!");
384        debug!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
385        debug!("");
386    }
387
388    /// Test for the set_flash() method
389    ///
390    /// If there is no error, the following output will be printed on the console:
391    ///
392    /// ```text
393    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
394    /// Testing setting flash latency...
395    /// Finished testing setting flash latency. Everything is alright!
396    /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
397    /// ```
398    pub fn test_set_flash_latency<
399        FlashChipSpecific: FlashChipSpecificTrait<FlashLatency = FlashLatency16>,
400    >(
401        flash: &Flash<FlashChipSpecific>,
402    ) {
403        debug!("");
404        debug!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
405        debug!("Testing setting flash latency...");
406
407        assert_eq!(Ok(()), flash.set_latency(HSI_FREQUENCY_MHZ));
408        assert_eq!(
409            FlashChipSpecific::FlashLatency::Latency0,
410            flash.get_latency()
411        );
412
413        assert_eq!(
414            Ok(()),
415            flash.set_latency(AHB_ETHERNET_MINIMUM_FREQUENCY_MHZ)
416        );
417        assert_eq!(
418            FlashChipSpecific::FlashLatency::Latency0,
419            flash.get_latency()
420        );
421
422        assert_eq!(Ok(()), flash.set_latency(APB1_MAX_FREQUENCY_MHZ_1));
423        assert_eq!(
424            FlashChipSpecific::FlashLatency::Latency1,
425            flash.get_latency()
426        );
427
428        assert_eq!(Ok(()), flash.set_latency(APB1_MAX_FREQUENCY_MHZ_2));
429        assert_eq!(
430            FlashChipSpecific::FlashLatency::Latency1,
431            flash.get_latency()
432        );
433
434        assert_eq!(Ok(()), flash.set_latency(APB1_MAX_FREQUENCY_MHZ_3));
435        assert_eq!(
436            FlashChipSpecific::FlashLatency::Latency1,
437            flash.get_latency()
438        );
439
440        assert_eq!(Ok(()), flash.set_latency(APB2_MAX_FREQUENCY_MHZ_1));
441
442        // STM32F401 maximum system clock frequency is 84MHz
443        #[cfg(not(feature = "stm32f401"))]
444        {
445            assert_eq!(Ok(()), flash.set_latency(APB2_MAX_FREQUENCY_MHZ_2));
446
447            assert_eq!(Ok(()), flash.set_latency(APB2_MAX_FREQUENCY_MHZ_3));
448            assert_eq!(
449                FlashChipSpecific::FlashLatency::Latency3,
450                flash.get_latency()
451            );
452
453            assert_eq!(Ok(()), flash.set_latency(PLL_FREQUENCY_MHZ));
454            assert_eq!(
455                FlashChipSpecific::FlashLatency::Latency3,
456                flash.get_latency()
457            );
458        }
459
460        // Low entries STM32F4 chips don't support frequencies higher than 100 MHz,
461        // but the foundation and advanced ones support system clock frequencies up to
462        // 180MHz
463        #[cfg(not(any(feature = "stm32f401", feature = "stm32f412",)))]
464        {
465            assert_eq!(
466                Ok(()),
467                flash.set_latency(SYS_MAX_FREQUENCY_NO_OVERDRIVE_MHZ)
468            );
469            assert_eq!(
470                FlashChipSpecific::FlashLatency::Latency5,
471                flash.get_latency()
472            );
473
474            assert_eq!(Ok(()), flash.set_latency(SYS_MAX_FREQUENCY_OVERDRIVE_MHZ));
475            assert_eq!(
476                FlashChipSpecific::FlashLatency::Latency5,
477                flash.get_latency()
478            );
479        }
480
481        // Revert to default settings
482        assert_eq!(Ok(()), flash.set_latency(HSI_FREQUENCY_MHZ));
483        assert_eq!(
484            FlashChipSpecific::FlashLatency::Latency0,
485            flash.get_latency()
486        );
487
488        debug!("Finished testing setting flash latency. Everything is alright!");
489        debug!("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
490        debug!("");
491    }
492
493    /// Run the entire test suite
494    pub fn run_all<FlashChipSpecific: FlashChipSpecificTrait<FlashLatency = FlashLatency16>>(
495        flash: &Flash<FlashChipSpecific>,
496    ) {
497        debug!("");
498        debug!("===============================================");
499        debug!("Testing setting flash latency...");
500
501        test_get_number_wait_cycles_based_on_frequency::<FlashChipSpecific>();
502        test_set_flash_latency::<FlashChipSpecific>(flash);
503
504        debug!("Finished testing flash. Everything is alright!");
505        debug!("===============================================");
506        debug!("");
507    }
508}