1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
//! Hardware Abstraction Layer for STM32 Memory Controllers (FMC/FSMC) //! //! //! # Implementation Guide //! //! You can use the functionality in this crate by implementing the //! [`FmcPeripheral`](FmcPeripheral) trait. You should implement this trait for a //! structure that: //! //! * Takes ownership of the `FMC`/`FSMC` peripheral //! * Takes ownership of any structures / ZSTs related to the power or clock for the `FMC`/`FSMC` peripheral //! * Contains the frequency of the `FMC`/`FSMC` source clock (usually HCLK) //! //! A basic structure: //! //! ``` //! pub struct FMC { //! source_clock: u32, //! // any other fields here... //! } //! ``` //! //! An implementation of [`FmcPeripheral`](FmcPeripheral): //! //! ```rust //! use stm32_fmc::FmcPeripheral; //! //! unsafe impl Sync for FMC {} //! unsafe impl FmcPeripheral for FMC { //! const REGISTERS: *const () = stm32::FMC::ptr() as *const (); //! //! fn enable(&mut self) { //! // Enable and reset the FMC/FSMC using the RCC registers //! // Typically RCC.AHBxEN and RCC.AHBxRST //! } //! //! fn memory_controller_enable(&mut self) { //! // Only required if your part has an `FMCEN` bit //! } //! //! fn source_clock_hz(&self) -> u32 { //! self.hclk //! } //! } //! ``` //! //! In a HAL, you can allow users to construct your structure by implementing a //! `new` method, or by making the fields public. //! //! ## Wrap constructor methods //! //! Each memory controller type ([`SDRAM`](Sdram), `NAND` (todo), ..) provides both //! `new` and `new_unchecked` methods. //! //! For the convenience of users, you may want to wrap these with your `new` method, //! so that each memory can be created from the peripheral in one step. //! //! ``` //! use stm32_fmc::{PinsSdram, Sdram, SdramChip, SdramPinSet, SdramTargetBank}; //! //! impl FMC { //! /// A new SDRAM memory via the Flexible Memory Controller //! pub fn sdram<BANK: SdramPinSet, PINS: PinsSdram<BANK>, CHIP: SdramChip>( //! fmc: stm32::FMC, //! pins: PINS, //! chip: CHIP, //! clocks: &CoreClocks, //! ) -> Sdram<FMC, CHIP> { //! let fmc = Self::new(fmc, clocks); //! Sdram::new(fmc, pins, chip) //! } //! //! /// A new SDRAM memory via the Flexible Memory Controller //! pub fn sdram_unchecked<CHIP: SdramChip, BANK: Into<SdramTargetBank>>( //! fmc: stm32::FMC, //! bank: BANK, //! chip: CHIP, //! clocks: &CoreClocks, //! ) -> Sdram<FMC, CHIP> { //! let fmc = Self::new(fmc, clocks); //! Sdram::new_unchecked(fmc, bank, chip) //! } //! } //! ``` //! //! # Pin implementations //! //! In contrast with the `new_unchecked` methods, the `new` methods require the user //! pass a tuple as the `pins` argument. In a HAL, you can mark which types are //! suitable as follows: //! //! ```rust //! impl stm32_fmc::A0 for gpiof::PF0<Alternate<AF12>> {} //! // ... //! ``` //! #![no_std] // rustc lints. #![warn( bare_trait_objects, missing_copy_implementations, missing_debug_implementations, missing_docs, trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_qualifications, unused_results )] #[macro_use] mod macros; mod fmc; pub use fmc::*; #[cfg(feature = "sdram")] mod sdram; #[cfg(feature = "sdram")] pub use sdram::{PinsSdram, Sdram, SdramChip, SdramPinSet, SdramTargetBank}; /// Memory device definitions pub mod devices; mod ral; /// A trait for device-specific FMC peripherals. Implement this to add support /// for a new hardware platform. Peripherals that have this trait must have the /// same register block as STM32 FMC peripherals. pub unsafe trait FmcPeripheral: Send + Sync { /// Pointer to the register block const REGISTERS: *const (); /// Enables the FMC on its peripheral bus fn enable(&mut self); /// Enables the FMC memory controller (not always required) fn memory_controller_enable(&mut self) {} /// The frequency of the clock used as a source for the fmc_clk. /// /// F4/F7/G4: hclk /// H7: fmc_ker_ck fn source_clock_hz(&self) -> u32; }