From d37d714314093747c9042faefcc3a22e2bfee59d Mon Sep 17 00:00:00 2001 From: Matous Hybl Date: Tue, 8 Feb 2022 14:32:18 +0100 Subject: stm32: Add support for FMC --- examples/stm32h7/Cargo.toml | 3 +- examples/stm32h7/src/bin/fmc.rs | 204 +++++++++++++++++++++++++++++++++ examples/stm32h7/src/example_common.rs | 1 + 3 files changed, 207 insertions(+), 1 deletion(-) create mode 100644 examples/stm32h7/src/bin/fmc.rs (limited to 'examples') diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml index 463dd83d5..59d99bbcb 100644 --- a/examples/stm32h7/Cargo.toml +++ b/examples/stm32h7/Cargo.toml @@ -9,7 +9,7 @@ resolver = "2" [dependencies] embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt"] } -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743zi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h743bi", "net", "time-driver-any", "exti", "unstable-pac", "unstable-traits"] } embassy-net = { path = "../../embassy-net", default-features = false, features = ["defmt", "tcp", "medium-ethernet", "pool-16"] } embassy-hal-common = { path = "../../embassy-hal-common", default-features = false, features = ["defmt"] } @@ -26,6 +26,7 @@ heapless = { version = "0.7.5", default-features = false } rand_core = "0.6.3" critical-section = "0.2.5" micromath = "2.0.0" +stm32-fmc = "0.2.4" [dependencies.smoltcp] version = "0.8.0" 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 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +#[path = "../example_common.rs"] +mod example_common; +use embassy::executor::Spawner; +use embassy::time::{Delay, Duration, Timer}; +use embassy_stm32::fmc::Fmc; +use embassy_stm32::Peripherals; +use example_common::*; + +#[embassy::main(config = "config()")] +async fn main(_spawner: Spawner, p: Peripherals) { + info!("Hello World!"); + + let mut core_peri = cortex_m::Peripherals::take().unwrap(); + + // taken from stm32h7xx-hal + core_peri.SCB.enable_icache(); + // See Errata Sheet 2.2.1 + // core_peri.SCB.enable_dcache(&mut core_peri.CPUID); + core_peri.DWT.enable_cycle_counter(); + // ---------------------------------------------------------- + // Configure MPU for external SDRAM + // MPU config for SDRAM write-through + let sdram_size = 32 * 1024 * 1024; + + { + let mpu = core_peri.MPU; + let scb = &mut core_peri.SCB; + let size = sdram_size; + // Refer to ARM®v7-M Architecture Reference Manual ARM DDI 0403 + // Version E.b Section B3.5 + const MEMFAULTENA: u32 = 1 << 16; + + unsafe { + /* Make sure outstanding transfers are done */ + cortex_m::asm::dmb(); + + scb.shcsr.modify(|r| r & !MEMFAULTENA); + + /* Disable the MPU and clear the control register*/ + mpu.ctrl.write(0); + } + + const REGION_NUMBER0: u32 = 0x00; + const REGION_BASE_ADDRESS: u32 = 0xD000_0000; + + const REGION_FULL_ACCESS: u32 = 0x03; + const REGION_CACHEABLE: u32 = 0x01; + const REGION_WRITE_BACK: u32 = 0x01; + const REGION_ENABLE: u32 = 0x01; + + crate::assert_eq!( + size & (size - 1), + 0, + "SDRAM memory region size must be a power of 2" + ); + crate::assert_eq!( + size & 0x1F, + 0, + "SDRAM memory region size must be 32 bytes or more" + ); + fn log2minus1(sz: u32) -> u32 { + for i in 5..=31 { + if sz == (1 << i) { + return i - 1; + } + } + crate::panic!("Unknown SDRAM memory region size!"); + } + + //info!("SDRAM Memory Size 0x{:x}", log2minus1(size as u32)); + + // Configure region 0 + // + // Cacheable, outer and inner write-back, no write allocate. So + // reads are cached, but writes always write all the way to SDRAM + unsafe { + mpu.rnr.write(REGION_NUMBER0); + mpu.rbar.write(REGION_BASE_ADDRESS); + mpu.rasr.write( + (REGION_FULL_ACCESS << 24) + | (REGION_CACHEABLE << 17) + | (REGION_WRITE_BACK << 16) + | (log2minus1(size as u32) << 1) + | REGION_ENABLE, + ); + } + + const MPU_ENABLE: u32 = 0x01; + const MPU_DEFAULT_MMAP_FOR_PRIVILEGED: u32 = 0x04; + + // Enable + unsafe { + mpu.ctrl + .modify(|r| r | MPU_DEFAULT_MMAP_FOR_PRIVILEGED | MPU_ENABLE); + + scb.shcsr.modify(|r| r | MEMFAULTENA); + + // Ensure MPU settings take effect + cortex_m::asm::dsb(); + cortex_m::asm::isb(); + } + } + + let mut sdram = Fmc::sdram_a12bits_d32bits_4banks_bank2( + p.FMC, + // A0-A11 + p.PF0, + p.PF1, + p.PF2, + p.PF3, + p.PF4, + p.PF5, + p.PF12, + p.PF13, + p.PF14, + p.PF15, + p.PG0, + p.PG1, + // BA0-BA1 + p.PG4, + p.PG5, + // D0-D31 + p.PD14, + p.PD15, + p.PD0, + p.PD1, + p.PE7, + p.PE8, + p.PE9, + p.PE10, + p.PE11, + p.PE12, + p.PE13, + p.PE14, + p.PE15, + p.PD8, + p.PD9, + p.PD10, + p.PH8, + p.PH9, + p.PH10, + p.PH11, + p.PH12, + p.PH13, + p.PH14, + p.PH15, + p.PI0, + p.PI1, + p.PI2, + p.PI3, + p.PI6, + p.PI7, + p.PI9, + p.PI10, + // NBL0 - NBL3 + p.PE0, + p.PE1, + p.PI4, + p.PI5, + p.PH7, // SDCKE1 + p.PG8, // SDCLK + p.PG15, // SDNCAS + p.PH6, // SDNE1 (!CS) + p.PF11, // SDRAS + p.PC0, // SDNWE, change to p.PH5 for EVAL boards + stm32_fmc::devices::is42s32800g_6::Is42s32800g {}, + ); + + let mut delay = Delay; + + let ram_slice = unsafe { + // Initialise controller and SDRAM + let ram_ptr: *mut u32 = sdram.init(&mut delay) as *mut _; + + // Convert raw pointer to slice + core::slice::from_raw_parts_mut(ram_ptr, sdram_size / core::mem::size_of::()) + }; + + // // ---------------------------------------------------------- + // // Use memory in SDRAM + info!("RAM contents before writing: {:x}", ram_slice[..10]); + + ram_slice[0] = 1; + ram_slice[1] = 2; + ram_slice[2] = 3; + ram_slice[3] = 4; + + info!("RAM contents after writing: {:x}", ram_slice[..10]); + + crate::assert_eq!(ram_slice[0], 1); + crate::assert_eq!(ram_slice[1], 2); + crate::assert_eq!(ram_slice[2], 3); + crate::assert_eq!(ram_slice[3], 4); + + info!("Assertions succeeded."); + + loop { + Timer::after(Duration::from_millis(1000)).await; + } +} diff --git a/examples/stm32h7/src/example_common.rs b/examples/stm32h7/src/example_common.rs index 524bee6d9..b8acc2790 100644 --- a/examples/stm32h7/src/example_common.rs +++ b/examples/stm32h7/src/example_common.rs @@ -22,6 +22,7 @@ defmt::timestamp! {"{=u64}", { pub fn config() -> Config { let mut config = Config::default(); config.rcc.sys_ck = Some(400.mhz().into()); + config.rcc.hclk = Some(200.mhz().into()); config.rcc.pll1.q_ck = Some(100.mhz().into()); config } -- cgit