# [Documentation](https://docs.rs/stm32-fmc) # stm32-fmc [![docs.rs](https://docs.rs/stm32-fmc/badge.svg)](https://docs.rs/stm32-fmc) [![Crates.io](https://img.shields.io/crates/v/stm32-fmc.svg)](https://crates.io/crates/stm32-fmc) Hardware Abstraction Layer for STM32 Memory Controllers (FMC/FSMC) Currently only SDRAM functions are implemented. **This crate is a work in progress! Contributions very welcome** ## Implementing (If your HAL already implements FMC, you can skip this) See the [docs](https://docs.rs/stm32-fmc) # Usage ### SDRAM The FMC peripheral supports up to 2 external SDRAM devices. This crate currently only supports 1, although it may be on either bank 1 or 2. External memories are defined by [`SdramChip`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.SdramChip.html) implementations. There are several examples in the [`devices`](src/devices/) folder, or you can make your own. To pass pins to a constructor, create a tuple with the following ordering: ```rust let pins = ( // A0-A12 pa0, ... // BA0-BA1 // D0-D31 // NBL0 - NBL3 // SDCKE // SDCLK // SDNCAS // SDNE // SDRAS // SDNWE ); ``` You can leave out address/data pins not used by your memory. #### Constructing If you are using a HAL, see the HAL documentation. Otherwise you can implement [`FmcPeripheral`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.FmcPeripheral.html) yourself then use [`Sdram::new`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.new) / [`Sdram::new_unchecked`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.new_unchecked) directly. #### Initialising Once you have an [`Sdram`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html) instance, you can: * Initialise it by calling [`init`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Sdram.html#method.init). This returns a raw pointer * Convert the raw pointer to a sized slice using `from_raw_parts_mut` ```rust let ram = unsafe { // Initialise controller and SDRAM let ram_ptr: *mut u32 = sdram.init(&mut delay); // 32 MByte = 256Mbit SDRAM = 8M u32 words slice::from_raw_parts_mut(ram_ptr, 8 * 1024 * 1024) }; ``` ### NAND Flash The FMC peripheral supports once external parallel NAND flash device. External memories are defined by [`NandChip`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.NandChip.html) implementations. There are examples in the [`devices`](src/devices/) folder, or you can make your own. To pass pins to a constructor, create a tuple with the following ordering: ```rust let pins = ( // A17/ALE // A16/CLE pa0, ... // D0-D7 // NCE/#CE // NOE/#RE // NWE/#WE // NWAIT/R/#B ); ``` #### Constructing If you are using a HAL, see the HAL documentation. Otherwise you can implement [`FmcPeripheral`](https://docs.rs/stm32-fmc/latest/stm32_fmc/trait.FmcPeripheral.html) yourself then use [`Nand::new`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.new) / [`Nand::new_unchecked`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.new_unchecked) directly. #### Initialising Once you have an [`Nand`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html) instance you should initialise it by calling [`init`](https://docs.rs/stm32-fmc/latest/stm32_fmc/struct.Nand.html#method.init). This returns a [`NandDevice`](https://docs.rs/stm32-fmc/latest/stm32_fmc/nand_device/struct.NandDevice.html) instance. ```rust let mut nand_device = nand.init(&mut delay); // Read device identifier let id = nand_device.read_id(); ``` ### NOR Flash/PSRAM TODO ### Troubleshooting The library automatically does some trace-level logging either via `log` or via `defmt`. To enable such logging, enable either the `log` or `defmt` feature in your `Cargo.toml`. For debugging the SDRAM register contents, the library provides additional feature `trace-register-values`, which when enabled causes the init function to log the register contents to the trace level. This is useful for example when you want to compare the register values between `stm32-fmc` and CubeMX code. Note that one of the logging features (`log`/`defmt`) must be enabled for this to work. ### Implementing a new device If you end up depending on a fork or a newer version of this crate than the HAL crate for your device, you can override the version pulled in by the external crate using a `[patch]` section in your `Cargo.toml`, as described in the [Cargo Book](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section). ## Releasing * Update Cargo.toml * Update CHANGELOG.md ``` git commit -am 'v0.2.0' git push --set-upstream origin v0.2.0 ``` Create a PR and check CI passes ``` git push --set-upstream origin v0.2.0:master git tag -a 'v0.2.0' -m 'v0.2.0' git push origin refs/tags/v0.2.0 cargo publish ``` ## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ## Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.