stm32: Add support for FMC
This commit is contained in:
@ -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"
|
||||
|
204
examples/stm32h7/src/bin/fmc.rs
Normal file
204
examples/stm32h7/src/bin/fmc.rs
Normal file
@ -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::<u32>())
|
||||
};
|
||||
|
||||
// // ----------------------------------------------------------
|
||||
// // 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;
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user