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;
}