From 9bfc15cbb96741bf85e2e698c3f652bf207b3947 Mon Sep 17 00:00:00 2001 From: Astro Date: Thu, 30 Jan 2020 21:11:45 +0100 Subject: [PATCH] qspi flash unfinished... --- experiments/src/main.rs | 72 +++++++++++++++---- libboard_zynq/src/ddr/mod.rs | 7 +- libboard_zynq/src/ddr/regs.rs | 8 ++- libboard_zynq/src/flash/mod.rs | 65 ++++++++++++----- libboard_zynq/src/flash/spi_flash_register.rs | 12 ++++ libboard_zynq/src/flash/transfer.rs | 41 ++++++++--- 6 files changed, 162 insertions(+), 43 deletions(-) diff --git a/experiments/src/main.rs b/experiments/src/main.rs index dcaecc1..c7675cf 100644 --- a/experiments/src/main.rs +++ b/experiments/src/main.rs @@ -20,8 +20,10 @@ static mut STACK_CORE1: [u32; 512] = [0; 512]; #[no_mangle] 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"); + let clocks = zynq::clocks::Clocks::get(); + println!("CPU Clocks: {}/{}/{}/{}", clocks.cpu_6x4x(), clocks.cpu_3x2x(), clocks.cpu_2x(), clocks.cpu_1x()); { use libregister::RegisterR; 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 ddr = zynq::ddr::DdrRam::new(); - #[cfg(not(feature = "target_zc706"))] - ddr.memtest(); - ram::init_alloc(&mut ddr); - - for i in 0..=1 { + for i in 0../*=*/1 { 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); - for b in flash_io.rdid() { + for (i, b) in flash_io.rdid().enumerate() { print!(" {:02X}", b); + if i % 0x10 == 0xf { + println!(""); + } else if i % 8 == 7 { + print!(" "); + } else if i % 4 == 3 { + print!(" "); + } } println!(""); print!("Flash {} I/O:", i); @@ -85,12 +106,28 @@ pub fn main_core0() { flash_io.dump("ASP Read", 0x2B); flash_io.dump("Password Read", 0xE7); - flash_io.write_enabled(|flash_io| { - flash_io.erase(0); - }); - flash_io.write_enabled(|flash_io| { - flash_io.program(0, [0x23054223; (0x100 >> 2)].iter().cloned()); - }); + for o in 0..8 { + const SIZE: u32 = 0x100; + println!("WREN"); + flash_io.write_enabled(|flash_io| { + println!("Erase page {}", o); + flash_io.erase(o * SIZE); + }); + println!("WREN"); + flash_io.write_enabled(|flash_io| { + 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(); } @@ -119,6 +156,11 @@ pub fn main_core0() { } 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()); println!("Eth on"); diff --git a/libboard_zynq/src/ddr/mod.rs b/libboard_zynq/src/ddr/mod.rs index 1596394..523be55 100644 --- a/libboard_zynq/src/ddr/mod.rs +++ b/libboard_zynq/src/ddr/mod.rs @@ -172,9 +172,14 @@ impl DdrRam { #[cfg(feature = "target_cora_z7_10")] let width = regs::DataBusWidth::Width16bit; self.regs.ddrc_ctrl.modify(|_, w| w - .soft_rstb(true) + .soft_rstb(false) .powerdown_en(false) .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 {} diff --git a/libboard_zynq/src/ddr/regs.rs b/libboard_zynq/src/ddr/regs.rs index 1ca54fc..92c0abb 100644 --- a/libboard_zynq/src/ddr/regs.rs +++ b/libboard_zynq/src/ddr/regs.rs @@ -1,6 +1,6 @@ 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)] #[repr(u8)] @@ -169,7 +169,11 @@ register_bit!(ddrc_ctrl, soft_rstb, 0); register_bit!(ddrc_ctrl, powerdown_en, 1); 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 register!(mode_sts_reg, diff --git a/libboard_zynq/src/flash/mod.rs b/libboard_zynq/src/flash/mod.rs index 65466c3..6556b14 100644 --- a/libboard_zynq/src/flash/mod.rs +++ b/libboard_zynq/src/flash/mod.rs @@ -10,16 +10,21 @@ mod regs; mod bytes; pub use bytes::{BytesTransferExt, BytesTransfer}; mod spi_flash_register; -use spi_flash_register::*; +pub use spi_flash_register::*; mod 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 pub const SINGLE_CAPACITY: u32 = 0x1000000; pub const SECTOR_SIZE: u32 = 0x10000; pub const PAGE_SIZE: u32 = 0x100; +/// Write Register +const INST_WRR: u8 = 0x01; /// Instruction: Read Identification const INST_RDID: u8 = 0x9F; const INST_READ: u8 = 0x03; @@ -31,8 +36,10 @@ const INST_WREN: u8 = 0x06; const INST_PP: u8 = 0x02; /// Instruction: Erase 4K Block const INST_BE_4K: u8 = 0x20; +/// Instruction: Clear Status Register +const INST_CLSR: u8 = 0x30; -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum SpiWord { W8(u8), W16(u16), @@ -105,9 +112,11 @@ impl Flash { ); } - 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)); - 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 // 7. Configure MIO pin 8 for feedback clock. - #[cfg(not(feature = "target_zc706"))] + // #[cfg(not(feature = "target_zc706"))] slcr.mio_pin_08.write( slcr::MioPin08::zeroed() .l0_sel(true) @@ -259,9 +268,12 @@ impl Flash<()> { while baud_rate_div < 7 && 2u32.pow(1 + baud_rate_div) < divider { baud_rate_div += 1; } + println!("delay: {:08X}", self.regs.delay.read()); self.regs.config.write(regs::Config::zeroed() .baud_rate_div(baud_rate_div as u8) + .clk_ph(true) + .clk_pol(true) .mode_sel(true) .leg_flsh(true) .holdb_dr(true) @@ -363,9 +375,21 @@ impl Flash { pub fn read_reg(&mut self) -> R { let args = Some(R::inst_code()); - let transfer = self.transfer(args.into_iter(), 2) + let transfer = self.transfer(args.into_iter(), 3) .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(&mut self, f: F) -> A @@ -377,7 +401,7 @@ impl Flash { while result.is_none() { let args = Some(R::inst_code()); for b in self.transfer(args.into_iter(), 32) - .bytes_transfer().skip(1) { + .bytes_transfer().skip(5) { result = f(R::new(b)); if result.is_some() { @@ -390,19 +414,22 @@ impl Flash { /// Status Register-1 remains `0x00` immediately after invoking a command. fn wait_while_sr1_zeroed(&mut self) -> SR1 { - self.read_reg_until::(|sr1| + println!("wait while sr1 0"); + let sr1 = self.read_reg_until::(|sr1| if sr1.is_zeroed() { None } else { Some(sr1) } - ) + ); + println!("sr1 non-zero: {:02X}", sr1.inner); + sr1 } /// Read Identification pub fn rdid(&mut self) -> core::iter::Skip, u32>>> { let args = Some((INST_RDID as u32) << 24); - self.transfer(args.into_iter(), 0x44) + self.transfer(args.into_iter(), 0x56) .bytes_transfer().skip(1) } @@ -431,21 +458,23 @@ impl Flash { print!("."); } println!(""); - } else { - println!("erased? sr1={:02X}", sr1.inner); } + println!("erased? sr1={:02X}", sr1.inner); } pub fn program>(&mut self, offset: u32, data: I) { { 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() .chain(data.map(SpiWord::W32)); self.transfer(args, len); } - // let sr1 = self.wait_while_sr1_zeroed(); - let sr1 = self.read_reg::(); + let sr1 = self.wait_while_sr1_zeroed(); + // let sr1 = self.read_reg::(); if sr1.e_err() { println!("E_ERR"); @@ -463,10 +492,13 @@ impl Flash { } pub fn write_enabled R, R>(&mut self, f: F) -> R { + let args = Some(INST_CLSR); + self.transfer(args.into_iter(), 1); // Write Enable let args = Some(INST_WREN); self.transfer(args.into_iter(), 1); self.regs.gpio.modify(|_, w| w.wp_n(true)); + println!("WPn hi"); let sr1 = self.wait_while_sr1_zeroed(); if !sr1.wel() { panic!("Cannot write-enable flash"); @@ -477,6 +509,7 @@ impl Flash { // Write Disable let args = Some(INST_WRDI); self.transfer(args.into_iter(), 1); + println!("WPn lo"); self.regs.gpio.modify(|_, w| w.wp_n(false)); result diff --git a/libboard_zynq/src/flash/spi_flash_register.rs b/libboard_zynq/src/flash/spi_flash_register.rs index ad3521e..21c2573 100644 --- a/libboard_zynq/src/flash/spi_flash_register.rs +++ b/libboard_zynq/src/flash/spi_flash_register.rs @@ -35,6 +35,18 @@ macro_rules! u8_register { } 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); impl SR1 { /// Write In Progress diff --git a/libboard_zynq/src/flash/transfer.rs b/libboard_zynq/src/flash/transfer.rs index 03f8bb0..42e1e17 100644 --- a/libboard_zynq/src/flash/transfer.rs +++ b/libboard_zynq/src/flash/transfer.rs @@ -1,6 +1,7 @@ use libregister::{RegisterR, RegisterW, RegisterRW}; use super::regs; use super::{SpiWord, Flash, Manual}; +use crate::{print, println}; pub struct Transfer<'a, Args: Iterator, W: Into> { flash: &'a mut Flash, @@ -31,13 +32,15 @@ impl<'a, Args: Iterator, W: Into> Transfer<'a, Args, W> { let arg = self.args.next() .map(|n| n.into()) .unwrap_or(SpiWord::W32(0)); - match arg { + + // println!("w {:?}", arg); + let write_len = match arg { SpiWord::W32(w) => { // println!("txd0 {:08X}", w); unsafe { self.flash.regs.txd0.write(w); } - self.sent += 4; + 4 } // Only txd0 can be used without flushing _ => { @@ -46,32 +49,38 @@ impl<'a, Args: Iterator, W: Into> Transfer<'a, Args, W> { self.flash.wait_tx_fifo_flush(); } - match arg { + let write_len = match arg { SpiWord::W8(w) => { // println!("txd1 {:02X}", w); unsafe { self.flash.regs.txd1.write(u32::from(w) << 24); } - self.sent += 1; + 1 } SpiWord::W16(w) => { unsafe { self.flash.regs.txd2.write(u32::from(w) << 16); } - self.sent += 2; + 2 } SpiWord::W24(w) => { unsafe { self.flash.regs.txd3.write(w << 8); } - self.sent += 3; + 3 } SpiWord::W32(_) => unreachable!(), - } + }; 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, W: Into> Transfer<'a, Args, W> { fn read(&mut self) -> u32 { let rx = self.flash.regs.rx_data.read(); + // println!("r 0x{:02X}", rx); self.received += 4; rx } @@ -93,11 +103,21 @@ impl<'a, Args: Iterator, W: Into> Drop for Transfer<'a, Args, self.read(); } + // // Stop + // self.flash.regs.enable.write( + // regs::Enable::zeroed() + // .spi_en(false) + // ); self.flash.regs.config.modify(|_, w| w .pcs(true) .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, W: Into> Iterator for Transfer<'a, A self.fill_tx_fifo(); + // print!("read:"); while !self.can_read() {} - Some(self.read()) + let b = self.read(); + // println!(" {:08X}", b); + Some(b) } }