pub const BASE: usize = 0xC000_0000;
const WORDS: usize = 16 * 1024 * 1024;
pub struct Is42s16160j;
impl stm32_fmc::SdramChip for Is42s16160j {
const MODE_REGISTER: u16 = 0x0020 | 0x0200;
const TIMING: stm32_fmc::SdramTiming = stm32_fmc::SdramTiming {
startup_delay_ns: 100_000, max_sd_clock_hz: 100_000_000, refresh_period_ns: 7_812, mode_register_to_active: 2,
exit_self_refresh: 7,
active_to_precharge: 4,
row_cycle: 7,
row_precharge: 2,
row_to_column: 2,
};
const CONFIG: stm32_fmc::SdramConfiguration = stm32_fmc::SdramConfiguration {
column_bits: 9,
row_bits: 13,
memory_data_width: 32,
internal_banks: 4,
cas_latency: 2,
write_protection: false,
read_burst: true,
read_pipe_delay_cycles: 0,
};
}
pub struct BusyDelay(pub u32);
impl embedded_hal::delay::DelayNs for BusyDelay {
fn delay_ns(&mut self, ns: u32) {
cortex_m::asm::delay(self.0 * ns.div_ceil(1000));
}
}
pub fn smoke_test(base: usize) {
let p = base as *mut u32;
unsafe {
for i in 0..4096usize {
p.add(i).write_volatile(0xA5A5_0000 ^ i as u32);
}
cortex_m::asm::dsb();
for i in 0..4096usize {
defmt::assert_eq!(p.add(i).read_volatile(), 0xA5A5_0000 ^ i as u32);
}
p.write_volatile(0xDEAD_BEEF);
p.add(WORDS - 1).write_volatile(0x1234_5678);
cortex_m::asm::dsb();
defmt::assert!(p.read_volatile() == 0xDEAD_BEEF);
defmt::assert!(p.add(WORDS - 1).read_volatile() == 0x1234_5678);
}
defmt::info!("sdram: 64 MiB @ {=usize:#010x}, pattern+aliasing OK", base);
}