qspi flash unfinished...

This commit is contained in:
Astro 2020-01-30 21:11:45 +01:00
parent c8d03a43c6
commit 9bfc15cbb9
6 changed files with 162 additions and 43 deletions

View File

@ -20,8 +20,10 @@ static mut STACK_CORE1: [u32; 512] = [0; 512];
#[no_mangle] #[no_mangle]
pub fn main_core0() { pub fn main_core0() {
// zynq::clocks::CpuClocks::enable_io(1_250_000_000); // zynq::clocks::Clocks::enable_io(1_250_000_000);
println!("\nzc706 main"); println!("\nzc706 main");
let clocks = zynq::clocks::Clocks::get();
println!("CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x());
{ {
use libregister::RegisterR; use libregister::RegisterR;
println!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins()); println!("Boot mode: {:?}", zynq::slcr::RegisterBlock::new().boot_mode.read().boot_mode_pins());
@ -52,17 +54,36 @@ pub fn main_core0() {
} }
let mut flash = flash.stop(); let mut flash = flash.stop();
let mut ddr = zynq::ddr::DdrRam::new(); for i in 0../*=*/1 {
#[cfg(not(feature = "target_zc706"))]
ddr.memtest();
ram::init_alloc(&mut ddr);
for i in 0..=1 {
let mut flash_io = flash.manual_mode(i); let mut flash_io = flash.manual_mode(i);
// println!("rdcr={:02X}", flash_io.rdcr());
let mut cr: zynq::flash::CR = flash_io.read_reg();
println!("rdcr={:02X}", cr.inner);
// if cr.quad() {
// println!("disabling quad mode...");
// cr.set_quad(false);
// let sr1: zynq::flash::SR1 = flash_io.read_reg();
// println!("sr1={:02X}", sr1.inner);
// flash_io.write_regs(sr1, cr);
// }
// if ! cr.quad() {
// println!("setting quad mode...");
// cr.set_quad(true);
// let sr1: zynq::flash::SR1 = flash_io.read_reg();
// // println!("sr1={:02X}", sr1.inner);
// flash_io.write_regs(sr1, cr);
// }
print!("Flash {} ID:", i); print!("Flash {} ID:", i);
for b in flash_io.rdid() { for (i, b) in flash_io.rdid().enumerate() {
print!(" {:02X}", b); print!(" {:02X}", b);
if i % 0x10 == 0xf {
println!("");
} else if i % 8 == 7 {
print!(" ");
} else if i % 4 == 3 {
print!(" ");
}
} }
println!(""); println!("");
print!("Flash {} I/O:", i); print!("Flash {} I/O:", i);
@ -85,12 +106,28 @@ pub fn main_core0() {
flash_io.dump("ASP Read", 0x2B); flash_io.dump("ASP Read", 0x2B);
flash_io.dump("Password Read", 0xE7); flash_io.dump("Password Read", 0xE7);
for o in 0..8 {
const SIZE: u32 = 0x100;
println!("WREN");
flash_io.write_enabled(|flash_io| { flash_io.write_enabled(|flash_io| {
flash_io.erase(0); println!("Erase page {}", o);
flash_io.erase(o * SIZE);
}); });
println!("WREN");
flash_io.write_enabled(|flash_io| { flash_io.write_enabled(|flash_io| {
flash_io.program(0, [0x23054223; (0x100 >> 2)].iter().cloned()); println!("Program page {}", o);
flash_io.program(o * SIZE, [0x26121984; (SIZE >> 2) as usize].iter().cloned());
}); });
}
print!("Flash {} I/O:", i);
for o in 0..8 {
const CHUNK: u32 = 32;
for b in flash_io.read(CHUNK * o, CHUNK as usize) {
print!(" {:02X}", b);
}
}
println!("");
flash = flash_io.stop(); flash = flash_io.stop();
} }
@ -119,6 +156,11 @@ pub fn main_core0() {
} }
println!("."); println!(".");
let mut ddr = zynq::ddr::DdrRam::new();
// #[cfg(not(feature = "target_zc706"))]
ddr.memtest();
ram::init_alloc(&mut ddr);
let eth = zynq::eth::Eth::default(HWADDR.clone()); let eth = zynq::eth::Eth::default(HWADDR.clone());
println!("Eth on"); println!("Eth on");

View File

@ -172,9 +172,14 @@ impl DdrRam {
#[cfg(feature = "target_cora_z7_10")] #[cfg(feature = "target_cora_z7_10")]
let width = regs::DataBusWidth::Width16bit; let width = regs::DataBusWidth::Width16bit;
self.regs.ddrc_ctrl.modify(|_, w| w self.regs.ddrc_ctrl.modify(|_, w| w
.soft_rstb(true) .soft_rstb(false)
.powerdown_en(false) .powerdown_en(false)
.data_bus_width(width) .data_bus_width(width)
.burst8_refresh(1)
.rdwr_idle_gap(1)
.dis_rd_bypass(false)
.dis_act_bypass(false)
.dis_auto_refresh(false)
); );
while self.status() == regs::ControllerStatus::Init {} while self.status() == regs::ControllerStatus::Init {}

View File

@ -1,6 +1,6 @@
use volatile_register::{RO, RW}; use volatile_register::{RO, RW};
use libregister::{register, register_bit, register_bits_typed}; use libregister::{register, register_bit, register_bits, register_bits_typed};
#[allow(unused)] #[allow(unused)]
#[repr(u8)] #[repr(u8)]
@ -169,7 +169,11 @@ register_bit!(ddrc_ctrl,
soft_rstb, 0); soft_rstb, 0);
register_bit!(ddrc_ctrl, powerdown_en, 1); register_bit!(ddrc_ctrl, powerdown_en, 1);
register_bits_typed!(ddrc_ctrl, data_bus_width, u8, DataBusWidth, 2, 3); register_bits_typed!(ddrc_ctrl, data_bus_width, u8, DataBusWidth, 2, 3);
// (ddrc_ctrl) ... register_bits!(ddrc_ctrl, burst8_refresh, u8, 4, 6);
register_bits!(ddrc_ctrl, rdwr_idle_gap, u8, 7, 13);
register_bit!(ddrc_ctrl, dis_rd_bypass, 14);
register_bit!(ddrc_ctrl, dis_act_bypass, 15);
register_bit!(ddrc_ctrl, dis_auto_refresh, 16);
// Controller operation mode status // Controller operation mode status
register!(mode_sts_reg, register!(mode_sts_reg,

View File

@ -10,16 +10,21 @@ mod regs;
mod bytes; mod bytes;
pub use bytes::{BytesTransferExt, BytesTransfer}; pub use bytes::{BytesTransferExt, BytesTransfer};
mod spi_flash_register; mod spi_flash_register;
use spi_flash_register::*; pub use spi_flash_register::*;
mod transfer; mod transfer;
use transfer::Transfer; use transfer::Transfer;
const FLASH_BAUD_RATE: u32 = 50_000_000; #[cfg(feature = "target_zc706")]
const FLASH_BAUD_RATE: u32 = 10_000_000;
#[cfg(feature = "target_cora_z7_10")]
const FLASH_BAUD_RATE: u32 = 10_000_000;
/// 16 MB /// 16 MB
pub const SINGLE_CAPACITY: u32 = 0x1000000; pub const SINGLE_CAPACITY: u32 = 0x1000000;
pub const SECTOR_SIZE: u32 = 0x10000; pub const SECTOR_SIZE: u32 = 0x10000;
pub const PAGE_SIZE: u32 = 0x100; pub const PAGE_SIZE: u32 = 0x100;
/// Write Register
const INST_WRR: u8 = 0x01;
/// Instruction: Read Identification /// Instruction: Read Identification
const INST_RDID: u8 = 0x9F; const INST_RDID: u8 = 0x9F;
const INST_READ: u8 = 0x03; const INST_READ: u8 = 0x03;
@ -31,8 +36,10 @@ const INST_WREN: u8 = 0x06;
const INST_PP: u8 = 0x02; const INST_PP: u8 = 0x02;
/// Instruction: Erase 4K Block /// Instruction: Erase 4K Block
const INST_BE_4K: u8 = 0x20; const INST_BE_4K: u8 = 0x20;
/// Instruction: Clear Status Register
const INST_CLSR: u8 = 0x30;
#[derive(Clone)] #[derive(Clone, Debug)]
pub enum SpiWord { pub enum SpiWord {
W8(u8), W8(u8),
W16(u16), W16(u16),
@ -105,9 +112,11 @@ impl<MODE> Flash<MODE> {
); );
} }
fn wait_tx_fifo_flush(&mut self) { fn wait_tx_fifo_flush(&mut self) -> u32 {
self.regs.config.modify(|_, w| w.man_start_com(true)); self.regs.config.modify(|_, w| w.man_start_com(true));
while !self.regs.intr_status.read().tx_fifo_not_full() {} let mut waited = 0;
while !self.regs.intr_status.read().tx_fifo_not_full() { waited += 1; }
waited
} }
} }
@ -220,7 +229,7 @@ impl Flash<()> {
// Option: Add Feedback Output Clock // Option: Add Feedback Output Clock
// 7. Configure MIO pin 8 for feedback clock. // 7. Configure MIO pin 8 for feedback clock.
#[cfg(not(feature = "target_zc706"))] // #[cfg(not(feature = "target_zc706"))]
slcr.mio_pin_08.write( slcr.mio_pin_08.write(
slcr::MioPin08::zeroed() slcr::MioPin08::zeroed()
.l0_sel(true) .l0_sel(true)
@ -259,9 +268,12 @@ impl Flash<()> {
while baud_rate_div < 7 && 2u32.pow(1 + baud_rate_div) < divider { while baud_rate_div < 7 && 2u32.pow(1 + baud_rate_div) < divider {
baud_rate_div += 1; baud_rate_div += 1;
} }
println!("delay: {:08X}", self.regs.delay.read());
self.regs.config.write(regs::Config::zeroed() self.regs.config.write(regs::Config::zeroed()
.baud_rate_div(baud_rate_div as u8) .baud_rate_div(baud_rate_div as u8)
.clk_ph(true)
.clk_pol(true)
.mode_sel(true) .mode_sel(true)
.leg_flsh(true) .leg_flsh(true)
.holdb_dr(true) .holdb_dr(true)
@ -363,9 +375,21 @@ impl Flash<Manual> {
pub fn read_reg<R: SpiFlashRegister>(&mut self) -> R { pub fn read_reg<R: SpiFlashRegister>(&mut self) -> R {
let args = Some(R::inst_code()); let args = Some(R::inst_code());
let transfer = self.transfer(args.into_iter(), 2) let transfer = self.transfer(args.into_iter(), 3)
.bytes_transfer(); .bytes_transfer();
R::new(transfer.skip(1).next().unwrap()) let b = transfer.skip(1).next().unwrap();
R::new(b)
}
pub fn write_regs(&mut self, sr1: SR1, cr: CR) {
self.write_enabled(|flash| {
let args = [
INST_WRR,
sr1.inner,
cr.inner,
];
flash.transfer(args.into_iter().cloned(), 3);
});
} }
pub fn read_reg_until<R, F, A>(&mut self, f: F) -> A pub fn read_reg_until<R, F, A>(&mut self, f: F) -> A
@ -377,7 +401,7 @@ impl Flash<Manual> {
while result.is_none() { while result.is_none() {
let args = Some(R::inst_code()); let args = Some(R::inst_code());
for b in self.transfer(args.into_iter(), 32) for b in self.transfer(args.into_iter(), 32)
.bytes_transfer().skip(1) { .bytes_transfer().skip(5) {
result = f(R::new(b)); result = f(R::new(b));
if result.is_some() { if result.is_some() {
@ -390,19 +414,22 @@ impl Flash<Manual> {
/// Status Register-1 remains `0x00` immediately after invoking a command. /// Status Register-1 remains `0x00` immediately after invoking a command.
fn wait_while_sr1_zeroed(&mut self) -> SR1 { fn wait_while_sr1_zeroed(&mut self) -> SR1 {
self.read_reg_until::<SR1, _, SR1>(|sr1| println!("wait while sr1 0");
let sr1 = self.read_reg_until::<SR1, _, SR1>(|sr1|
if sr1.is_zeroed() { if sr1.is_zeroed() {
None None
} else { } else {
Some(sr1) Some(sr1)
} }
) );
println!("sr1 non-zero: {:02X}", sr1.inner);
sr1
} }
/// Read Identification /// Read Identification
pub fn rdid(&mut self) -> core::iter::Skip<BytesTransfer<Transfer<core::option::IntoIter<u32>, u32>>> { pub fn rdid(&mut self) -> core::iter::Skip<BytesTransfer<Transfer<core::option::IntoIter<u32>, u32>>> {
let args = Some((INST_RDID as u32) << 24); let args = Some((INST_RDID as u32) << 24);
self.transfer(args.into_iter(), 0x44) self.transfer(args.into_iter(), 0x56)
.bytes_transfer().skip(1) .bytes_transfer().skip(1)
} }
@ -431,21 +458,23 @@ impl Flash<Manual> {
print!("."); print!(".");
} }
println!(""); println!("");
} else {
println!("erased? sr1={:02X}", sr1.inner);
} }
println!("erased? sr1={:02X}", sr1.inner);
} }
pub fn program<I: Iterator<Item=u32>>(&mut self, offset: u32, data: I) { pub fn program<I: Iterator<Item=u32>>(&mut self, offset: u32, data: I) {
{ {
let len = 4 + 4 * data.size_hint().0; let len = 4 + 4 * data.size_hint().0;
// let args = Some(SpiWord::W8(INST_PP)).into_iter()
// .chain(Some(SpiWord::W24(offset as u32)).into_iter())
let args = Some(SpiWord::W32(((INST_PP as u32) << 24) | (offset as u32))).into_iter() let args = Some(SpiWord::W32(((INST_PP as u32) << 24) | (offset as u32))).into_iter()
.chain(data.map(SpiWord::W32)); .chain(data.map(SpiWord::W32));
self.transfer(args, len); self.transfer(args, len);
} }
// let sr1 = self.wait_while_sr1_zeroed(); let sr1 = self.wait_while_sr1_zeroed();
let sr1 = self.read_reg::<SR1>(); // let sr1 = self.read_reg::<SR1>();
if sr1.e_err() { if sr1.e_err() {
println!("E_ERR"); println!("E_ERR");
@ -463,10 +492,13 @@ impl Flash<Manual> {
} }
pub fn write_enabled<F: Fn(&mut Self) -> R, R>(&mut self, f: F) -> R { pub fn write_enabled<F: Fn(&mut Self) -> R, R>(&mut self, f: F) -> R {
let args = Some(INST_CLSR);
self.transfer(args.into_iter(), 1);
// Write Enable // Write Enable
let args = Some(INST_WREN); let args = Some(INST_WREN);
self.transfer(args.into_iter(), 1); self.transfer(args.into_iter(), 1);
self.regs.gpio.modify(|_, w| w.wp_n(true)); self.regs.gpio.modify(|_, w| w.wp_n(true));
println!("WPn hi");
let sr1 = self.wait_while_sr1_zeroed(); let sr1 = self.wait_while_sr1_zeroed();
if !sr1.wel() { if !sr1.wel() {
panic!("Cannot write-enable flash"); panic!("Cannot write-enable flash");
@ -477,6 +509,7 @@ impl Flash<Manual> {
// Write Disable // Write Disable
let args = Some(INST_WRDI); let args = Some(INST_WRDI);
self.transfer(args.into_iter(), 1); self.transfer(args.into_iter(), 1);
println!("WPn lo");
self.regs.gpio.modify(|_, w| w.wp_n(false)); self.regs.gpio.modify(|_, w| w.wp_n(false));
result result

View File

@ -35,6 +35,18 @@ macro_rules! u8_register {
} }
u8_register!(CR, "Configuration Register", 0x35); u8_register!(CR, "Configuration Register", 0x35);
impl CR {
/// quad I/O mode
pub fn quad(&self) -> bool {
self.inner.get_bit(1)
}
/// set quad I/O mode
pub fn set_quad(&mut self, value: bool) {
self.inner.set_bit(1, value);
}
}
u8_register!(SR1, "Status Register-1", 0x05); u8_register!(SR1, "Status Register-1", 0x05);
impl SR1 { impl SR1 {
/// Write In Progress /// Write In Progress

View File

@ -1,6 +1,7 @@
use libregister::{RegisterR, RegisterW, RegisterRW}; use libregister::{RegisterR, RegisterW, RegisterRW};
use super::regs; use super::regs;
use super::{SpiWord, Flash, Manual}; use super::{SpiWord, Flash, Manual};
use crate::{print, println};
pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> { pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> {
flash: &'a mut Flash<Manual>, flash: &'a mut Flash<Manual>,
@ -31,13 +32,15 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
let arg = self.args.next() let arg = self.args.next()
.map(|n| n.into()) .map(|n| n.into())
.unwrap_or(SpiWord::W32(0)); .unwrap_or(SpiWord::W32(0));
match arg {
// println!("w {:?}", arg);
let write_len = match arg {
SpiWord::W32(w) => { SpiWord::W32(w) => {
// println!("txd0 {:08X}", w); // println!("txd0 {:08X}", w);
unsafe { unsafe {
self.flash.regs.txd0.write(w); self.flash.regs.txd0.write(w);
} }
self.sent += 4; 4
} }
// Only txd0 can be used without flushing // Only txd0 can be used without flushing
_ => { _ => {
@ -46,32 +49,38 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
self.flash.wait_tx_fifo_flush(); self.flash.wait_tx_fifo_flush();
} }
match arg { let write_len = match arg {
SpiWord::W8(w) => { SpiWord::W8(w) => {
// println!("txd1 {:02X}", w); // println!("txd1 {:02X}", w);
unsafe { unsafe {
self.flash.regs.txd1.write(u32::from(w) << 24); self.flash.regs.txd1.write(u32::from(w) << 24);
} }
self.sent += 1; 1
} }
SpiWord::W16(w) => { SpiWord::W16(w) => {
unsafe { unsafe {
self.flash.regs.txd2.write(u32::from(w) << 16); self.flash.regs.txd2.write(u32::from(w) << 16);
} }
self.sent += 2; 2
} }
SpiWord::W24(w) => { SpiWord::W24(w) => {
unsafe { unsafe {
self.flash.regs.txd3.write(w << 8); self.flash.regs.txd3.write(w << 8);
} }
self.sent += 3; 3
} }
SpiWord::W32(_) => unreachable!(), SpiWord::W32(_) => unreachable!(),
} };
self.flash.wait_tx_fifo_flush(); self.flash.wait_tx_fifo_flush();
write_len
} }
} };
self.sent += write_len;
// if self.sent % 258 == 0 {
// self.flash.wait_tx_fifo_flush();
// }
} }
} }
@ -81,6 +90,7 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
fn read(&mut self) -> u32 { fn read(&mut self) -> u32 {
let rx = self.flash.regs.rx_data.read(); let rx = self.flash.regs.rx_data.read();
// println!("r 0x{:02X}", rx);
self.received += 4; self.received += 4;
rx rx
} }
@ -93,11 +103,21 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Drop for Transfer<'a, Args,
self.read(); self.read();
} }
// // Stop
// self.flash.regs.enable.write(
// regs::Enable::zeroed()
// .spi_en(false)
// );
self.flash.regs.config.modify(|_, w| w self.flash.regs.config.modify(|_, w| w
.pcs(true) .pcs(true)
.man_start_com(false) .man_start_com(false)
); );
/// Leave PCS high for a few cycles
for _ in 0..0x100 {
libcortex_a9::asm::nop();
}
} }
} }
@ -111,7 +131,10 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Iterator for Transfer<'a, A
self.fill_tx_fifo(); self.fill_tx_fifo();
// print!("read:");
while !self.can_read() {} while !self.can_read() {}
Some(self.read()) let b = self.read();
// println!(" {:08X}", b);
Some(b)
} }
} }