diff options
| author | Matous Hybl <[email protected]> | 2022-02-08 14:32:18 +0100 |
|---|---|---|
| committer | Matous Hybl <[email protected]> | 2022-02-08 17:30:20 +0100 |
| commit | d37d714314093747c9042faefcc3a22e2bfee59d (patch) | |
| tree | 16f9b8ce5d8e58f7b6cf32f8071f394795f8300b /examples/stm32h7/src/bin | |
| parent | fee1de109dc5a81ee4e2a74403faec0923e0369e (diff) | |
stm32: Add support for FMC
Diffstat (limited to 'examples/stm32h7/src/bin')
| -rw-r--r-- | examples/stm32h7/src/bin/fmc.rs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/examples/stm32h7/src/bin/fmc.rs b/examples/stm32h7/src/bin/fmc.rs new file mode 100644 index 000000000..b9ac1318e --- /dev/null +++ b/examples/stm32h7/src/bin/fmc.rs | |||
| @@ -0,0 +1,204 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use embassy::executor::Spawner; | ||
| 8 | use embassy::time::{Delay, Duration, Timer}; | ||
| 9 | use embassy_stm32::fmc::Fmc; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | use example_common::*; | ||
| 12 | |||
| 13 | #[embassy::main(config = "config()")] | ||
| 14 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 15 | info!("Hello World!"); | ||
| 16 | |||
| 17 | let mut core_peri = cortex_m::Peripherals::take().unwrap(); | ||
| 18 | |||
| 19 | // taken from stm32h7xx-hal | ||
| 20 | core_peri.SCB.enable_icache(); | ||
| 21 | // See Errata Sheet 2.2.1 | ||
| 22 | // core_peri.SCB.enable_dcache(&mut core_peri.CPUID); | ||
| 23 | core_peri.DWT.enable_cycle_counter(); | ||
| 24 | // ---------------------------------------------------------- | ||
| 25 | // Configure MPU for external SDRAM | ||
| 26 | // MPU config for SDRAM write-through | ||
| 27 | let sdram_size = 32 * 1024 * 1024; | ||
| 28 | |||
| 29 | { | ||
| 30 | let mpu = core_peri.MPU; | ||
| 31 | let scb = &mut core_peri.SCB; | ||
| 32 | let size = sdram_size; | ||
| 33 | // Refer to ARM®v7-M Architecture Reference Manual ARM DDI 0403 | ||
| 34 | // Version E.b Section B3.5 | ||
| 35 | const MEMFAULTENA: u32 = 1 << 16; | ||
| 36 | |||
| 37 | unsafe { | ||
| 38 | /* Make sure outstanding transfers are done */ | ||
| 39 | cortex_m::asm::dmb(); | ||
| 40 | |||
| 41 | scb.shcsr.modify(|r| r & !MEMFAULTENA); | ||
| 42 | |||
| 43 | /* Disable the MPU and clear the control register*/ | ||
| 44 | mpu.ctrl.write(0); | ||
| 45 | } | ||
| 46 | |||
| 47 | const REGION_NUMBER0: u32 = 0x00; | ||
| 48 | const REGION_BASE_ADDRESS: u32 = 0xD000_0000; | ||
| 49 | |||
| 50 | const REGION_FULL_ACCESS: u32 = 0x03; | ||
| 51 | const REGION_CACHEABLE: u32 = 0x01; | ||
| 52 | const REGION_WRITE_BACK: u32 = 0x01; | ||
| 53 | const REGION_ENABLE: u32 = 0x01; | ||
| 54 | |||
| 55 | crate::assert_eq!( | ||
| 56 | size & (size - 1), | ||
| 57 | 0, | ||
| 58 | "SDRAM memory region size must be a power of 2" | ||
| 59 | ); | ||
| 60 | crate::assert_eq!( | ||
| 61 | size & 0x1F, | ||
| 62 | 0, | ||
| 63 | "SDRAM memory region size must be 32 bytes or more" | ||
| 64 | ); | ||
| 65 | fn log2minus1(sz: u32) -> u32 { | ||
| 66 | for i in 5..=31 { | ||
| 67 | if sz == (1 << i) { | ||
| 68 | return i - 1; | ||
| 69 | } | ||
| 70 | } | ||
| 71 | crate::panic!("Unknown SDRAM memory region size!"); | ||
| 72 | } | ||
| 73 | |||
| 74 | //info!("SDRAM Memory Size 0x{:x}", log2minus1(size as u32)); | ||
| 75 | |||
| 76 | // Configure region 0 | ||
| 77 | // | ||
| 78 | // Cacheable, outer and inner write-back, no write allocate. So | ||
| 79 | // reads are cached, but writes always write all the way to SDRAM | ||
| 80 | unsafe { | ||
| 81 | mpu.rnr.write(REGION_NUMBER0); | ||
| 82 | mpu.rbar.write(REGION_BASE_ADDRESS); | ||
| 83 | mpu.rasr.write( | ||
| 84 | (REGION_FULL_ACCESS << 24) | ||
| 85 | | (REGION_CACHEABLE << 17) | ||
| 86 | | (REGION_WRITE_BACK << 16) | ||
| 87 | | (log2minus1(size as u32) << 1) | ||
| 88 | | REGION_ENABLE, | ||
| 89 | ); | ||
| 90 | } | ||
| 91 | |||
| 92 | const MPU_ENABLE: u32 = 0x01; | ||
| 93 | const MPU_DEFAULT_MMAP_FOR_PRIVILEGED: u32 = 0x04; | ||
| 94 | |||
| 95 | // Enable | ||
| 96 | unsafe { | ||
| 97 | mpu.ctrl | ||
| 98 | .modify(|r| r | MPU_DEFAULT_MMAP_FOR_PRIVILEGED | MPU_ENABLE); | ||
| 99 | |||
| 100 | scb.shcsr.modify(|r| r | MEMFAULTENA); | ||
| 101 | |||
| 102 | // Ensure MPU settings take effect | ||
| 103 | cortex_m::asm::dsb(); | ||
| 104 | cortex_m::asm::isb(); | ||
| 105 | } | ||
| 106 | } | ||
| 107 | |||
| 108 | let mut sdram = Fmc::sdram_a12bits_d32bits_4banks_bank2( | ||
| 109 | p.FMC, | ||
| 110 | // A0-A11 | ||
| 111 | p.PF0, | ||
| 112 | p.PF1, | ||
| 113 | p.PF2, | ||
| 114 | p.PF3, | ||
| 115 | p.PF4, | ||
| 116 | p.PF5, | ||
| 117 | p.PF12, | ||
| 118 | p.PF13, | ||
| 119 | p.PF14, | ||
| 120 | p.PF15, | ||
| 121 | p.PG0, | ||
| 122 | p.PG1, | ||
| 123 | // BA0-BA1 | ||
| 124 | p.PG4, | ||
| 125 | p.PG5, | ||
| 126 | // D0-D31 | ||
| 127 | p.PD14, | ||
| 128 | p.PD15, | ||
| 129 | p.PD0, | ||
| 130 | p.PD1, | ||
| 131 | p.PE7, | ||
| 132 | p.PE8, | ||
| 133 | p.PE9, | ||
| 134 | p.PE10, | ||
| 135 | p.PE11, | ||
| 136 | p.PE12, | ||
| 137 | p.PE13, | ||
| 138 | p.PE14, | ||
| 139 | p.PE15, | ||
| 140 | p.PD8, | ||
| 141 | p.PD9, | ||
| 142 | p.PD10, | ||
| 143 | p.PH8, | ||
| 144 | p.PH9, | ||
| 145 | p.PH10, | ||
| 146 | p.PH11, | ||
| 147 | p.PH12, | ||
| 148 | p.PH13, | ||
| 149 | p.PH14, | ||
| 150 | p.PH15, | ||
| 151 | p.PI0, | ||
| 152 | p.PI1, | ||
| 153 | p.PI2, | ||
| 154 | p.PI3, | ||
| 155 | p.PI6, | ||
| 156 | p.PI7, | ||
| 157 | p.PI9, | ||
| 158 | p.PI10, | ||
| 159 | // NBL0 - NBL3 | ||
| 160 | p.PE0, | ||
| 161 | p.PE1, | ||
| 162 | p.PI4, | ||
| 163 | p.PI5, | ||
| 164 | p.PH7, // SDCKE1 | ||
| 165 | p.PG8, // SDCLK | ||
| 166 | p.PG15, // SDNCAS | ||
| 167 | p.PH6, // SDNE1 (!CS) | ||
| 168 | p.PF11, // SDRAS | ||
| 169 | p.PC0, // SDNWE, change to p.PH5 for EVAL boards | ||
| 170 | stm32_fmc::devices::is42s32800g_6::Is42s32800g {}, | ||
| 171 | ); | ||
| 172 | |||
| 173 | let mut delay = Delay; | ||
| 174 | |||
| 175 | let ram_slice = unsafe { | ||
| 176 | // Initialise controller and SDRAM | ||
| 177 | let ram_ptr: *mut u32 = sdram.init(&mut delay) as *mut _; | ||
| 178 | |||
| 179 | // Convert raw pointer to slice | ||
| 180 | core::slice::from_raw_parts_mut(ram_ptr, sdram_size / core::mem::size_of::<u32>()) | ||
| 181 | }; | ||
| 182 | |||
| 183 | // // ---------------------------------------------------------- | ||
| 184 | // // Use memory in SDRAM | ||
| 185 | info!("RAM contents before writing: {:x}", ram_slice[..10]); | ||
| 186 | |||
| 187 | ram_slice[0] = 1; | ||
| 188 | ram_slice[1] = 2; | ||
| 189 | ram_slice[2] = 3; | ||
| 190 | ram_slice[3] = 4; | ||
| 191 | |||
| 192 | info!("RAM contents after writing: {:x}", ram_slice[..10]); | ||
| 193 | |||
| 194 | crate::assert_eq!(ram_slice[0], 1); | ||
| 195 | crate::assert_eq!(ram_slice[1], 2); | ||
| 196 | crate::assert_eq!(ram_slice[2], 3); | ||
| 197 | crate::assert_eq!(ram_slice[3], 4); | ||
| 198 | |||
| 199 | info!("Assertions succeeded."); | ||
| 200 | |||
| 201 | loop { | ||
| 202 | Timer::after(Duration::from_millis(1000)).await; | ||
| 203 | } | ||
| 204 | } | ||
