|
| 1 | +//! This example shows how to use the FMC controller on the STM32F7 to communicate with an |
| 2 | +//! off-chip SDRAM memory device. The `stm32-fmc` crate does the majority of the work, and |
| 3 | +//! after initialization the SDRAM is memory mapped to the STM32F7 address space. |
| 4 | +//! |
| 5 | +//! This example was tested on the STM32F746G Discovery Board. The board has an IS42S32400F-6BL |
| 6 | +//! SDRAM chip, with only 16 of the 32 data wires connected to the microcontroller. This device |
| 7 | +//! is not explictly supported in the `stm32-fmc` crate at time of writing, but the IS42S16400J |
| 8 | +//! has very similar parameters and is used as a placeholder for now. Because of this, only half |
| 9 | +//! of the available memory space is available (128 Mb = 16 MB, so 8 MB available). |
| 10 | +//! |
| 11 | +//! To use the example, launch a GDB server and then `cargo run`. After several seconds, the |
| 12 | +//! message "Success!" should be printed in the GDB server terminal (via semihosting). |
| 13 | +
|
| 14 | +#![deny(warnings)] |
| 15 | +#![no_main] |
| 16 | +#![no_std] |
| 17 | + |
| 18 | +extern crate panic_semihosting; |
| 19 | + |
| 20 | +use core::{mem, slice}; |
| 21 | +use cortex_m_rt::entry; |
| 22 | +use cortex_m_semihosting::hprintln; |
| 23 | +use stm32_fmc::devices::is42s16400j_7; |
| 24 | +use stm32f4xx_hal::{ |
| 25 | + fmc::FmcExt, |
| 26 | + gpio::{alt::fmc as alt, Speed}, |
| 27 | + pac, |
| 28 | + prelude::*, |
| 29 | +}; |
| 30 | + |
| 31 | +/// Configure pins for the FMC controller |
| 32 | +macro_rules! fmc_pins { |
| 33 | + ($($alt:ident: $pin:expr,)*) => { |
| 34 | + ( |
| 35 | + $( |
| 36 | + alt::$alt::from($pin.into_alternate() |
| 37 | + .speed(Speed::VeryHigh) |
| 38 | + .internal_pull_up(true) |
| 39 | + ) |
| 40 | + ),* |
| 41 | + ) |
| 42 | + }; |
| 43 | +} |
| 44 | + |
| 45 | +#[entry] |
| 46 | +fn main() -> ! { |
| 47 | + let cp = cortex_m::Peripherals::take().unwrap(); |
| 48 | + let dp = pac::Peripherals::take().unwrap(); |
| 49 | + |
| 50 | + // Get the delay provider. |
| 51 | + let clocks = dp.RCC.constrain().cfgr.sysclk(216.MHz()).freeze(); |
| 52 | + let mut delay = cp.SYST.delay(&clocks); |
| 53 | + |
| 54 | + // IO |
| 55 | + let gpioc = dp.GPIOC.split(); |
| 56 | + let gpiod = dp.GPIOD.split(); |
| 57 | + let gpioe = dp.GPIOE.split(); |
| 58 | + let gpiof = dp.GPIOF.split(); |
| 59 | + let gpiog = dp.GPIOG.split(); |
| 60 | + let gpioh = dp.GPIOH.split(); |
| 61 | + |
| 62 | + // Initialise SDRAM |
| 63 | + let fmc_io = fmc_pins! { |
| 64 | + A0: gpiof.pf0, |
| 65 | + A1: gpiof.pf1, |
| 66 | + A2: gpiof.pf2, |
| 67 | + A3: gpiof.pf3, |
| 68 | + A4: gpiof.pf4, |
| 69 | + A5: gpiof.pf5, |
| 70 | + A6: gpiof.pf12, |
| 71 | + A7: gpiof.pf13, |
| 72 | + A8: gpiof.pf14, |
| 73 | + A9: gpiof.pf15, |
| 74 | + A10: gpiog.pg0, |
| 75 | + A11: gpiog.pg1, |
| 76 | + Ba0: gpiog.pg4, |
| 77 | + Ba1: gpiog.pg5, |
| 78 | + D0: gpiod.pd14, |
| 79 | + D1: gpiod.pd15, |
| 80 | + D2: gpiod.pd0, |
| 81 | + D3: gpiod.pd1, |
| 82 | + D4: gpioe.pe7, |
| 83 | + D5: gpioe.pe8, |
| 84 | + D6: gpioe.pe9, |
| 85 | + D7: gpioe.pe10, |
| 86 | + D8: gpioe.pe11, |
| 87 | + D9: gpioe.pe12, |
| 88 | + D10: gpioe.pe13, |
| 89 | + D11: gpioe.pe14, |
| 90 | + D12: gpioe.pe15, |
| 91 | + D13: gpiod.pd8, |
| 92 | + D14: gpiod.pd9, |
| 93 | + D15: gpiod.pd10, |
| 94 | + Nbl0: gpioe.pe0, |
| 95 | + Nbl1: gpioe.pe1, |
| 96 | + Sdcke0: gpioc.pc3, |
| 97 | + Sdclk: gpiog.pg8, |
| 98 | + Sdncas: gpiog.pg15, |
| 99 | + Sdne0: gpioh.ph3, |
| 100 | + Sdnras: gpiof.pf11, |
| 101 | + Sdnwe: gpioh.ph5, |
| 102 | + }; |
| 103 | + |
| 104 | + // New SDRAM |
| 105 | + let mut sdram = dp.FMC.sdram(fmc_io, is42s16400j_7::Is42s16400j {}, &clocks); |
| 106 | + |
| 107 | + // Initialise controller and SDRAM |
| 108 | + let len_bytes = (16 * 1024 * 1024) / 2; |
| 109 | + let len_words = len_bytes / mem::size_of::<u32>(); |
| 110 | + let ram = unsafe { |
| 111 | + let ram_ptr: *mut u32 = sdram.init(&mut delay); |
| 112 | + slice::from_raw_parts_mut(ram_ptr, len_words) |
| 113 | + }; |
| 114 | + |
| 115 | + // Access all the words in SDRAM (takes several seconds) |
| 116 | + for addr in 0..len_words { |
| 117 | + let val: u32 = addr as u32; |
| 118 | + |
| 119 | + // Write |
| 120 | + ram[addr] = val; |
| 121 | + |
| 122 | + // Read |
| 123 | + let res: u32 = ram[addr]; |
| 124 | + if res != val { |
| 125 | + panic!( |
| 126 | + "Error: Expected {} while reading address {:X} but got {}.", |
| 127 | + val, addr, res |
| 128 | + ); |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + hprintln!("Success!"); |
| 133 | + |
| 134 | + loop {} |
| 135 | +} |
0 commit comments