Compare commits
No commits in common. "8a9dde611921e0881b518b34b1390a60949a9d45" and "e1068af9481ff82516477e3ae0e059798a0d4a5c" have entirely different histories.
8a9dde6119
...
e1068af948
|
@ -8,22 +8,16 @@ use super::clocks::CpuClocks;
|
||||||
mod regs;
|
mod regs;
|
||||||
mod bytes;
|
mod bytes;
|
||||||
pub use bytes::{BytesTransferExt, BytesTransfer};
|
pub use bytes::{BytesTransferExt, BytesTransfer};
|
||||||
mod spi_flash_register;
|
|
||||||
use spi_flash_register::*;
|
|
||||||
|
|
||||||
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
||||||
/// 16 MB
|
const SINGLE_CAPACITY: u32 = 16 * 1024 * 1024;
|
||||||
pub const SINGLE_CAPACITY: u32 = 0x1000000;
|
|
||||||
pub const SECTOR_SIZE: u32 = 0x10000;
|
|
||||||
pub const PAGE_SIZE: u32 = 0x100;
|
|
||||||
|
|
||||||
|
/// Instruction: Read Configure Register
|
||||||
|
const INST_RDCR: u8 = 0x35;
|
||||||
|
/// Instruction: Read Status Register-1
|
||||||
|
const INST_RDSR1: u8 = 0x05;
|
||||||
/// Instruction: Read Identification
|
/// Instruction: Read Identification
|
||||||
const INST_RDID: u8 = 0x9F;
|
const INST_RDID: u8 = 0x9F;
|
||||||
const INST_READ: u8 = 0x03;
|
|
||||||
/// Instruction: Write Disable
|
|
||||||
const INST_WRDI: u8 = 0x04;
|
|
||||||
/// Instruction: Write Enable
|
|
||||||
const INST_WREN: u8 = 0x06;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub enum SpiWord {
|
pub enum SpiWord {
|
||||||
|
@ -355,14 +349,23 @@ impl Flash<Manual> {
|
||||||
self.transition()
|
self.transition()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_reg<R: SpiFlashRegister>(&mut self) -> R {
|
/// Read Configuration Register
|
||||||
let args = Some(R::inst_code());
|
pub fn rdcr(&mut self) -> u8 {
|
||||||
let transfer = self.transfer(args.into_iter(), R::transfer_len())
|
let args = Some((INST_RDCR as u32) << 24);
|
||||||
.bytes_transfer().skip(1);
|
self.transfer(args.into_iter(), 4)
|
||||||
R::new(transfer)
|
.bytes_transfer().skip(1)
|
||||||
|
.next().unwrap() as u8
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read Identification
|
/// Read Status Register-1
|
||||||
|
pub fn rdsr1(&mut self) -> u8 {
|
||||||
|
let args = Some(INST_RDSR1 as u8);
|
||||||
|
self.transfer(args.into_iter(), 2)
|
||||||
|
.bytes_transfer().skip(1)
|
||||||
|
.next().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read Identifiaction
|
||||||
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(), 0x44)
|
||||||
|
@ -378,24 +381,6 @@ impl Flash<Manual> {
|
||||||
.bytes_transfer().skip(6).take(len)
|
.bytes_transfer().skip(6).take(len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_enabled<F: Fn(&mut Self) -> R, R>(&mut self, f: F) -> R {
|
|
||||||
// Write Enable
|
|
||||||
let args = Some(INST_WREN);
|
|
||||||
self.transfer(args.into_iter(), 1);
|
|
||||||
self.regs.gpio.modify(|_, w| w.wp_n(true));
|
|
||||||
while !self.read_reg::<SR1>().wel() {}
|
|
||||||
|
|
||||||
let result = f(self);
|
|
||||||
|
|
||||||
// Write Disable
|
|
||||||
let args = Some(INST_WRDI);
|
|
||||||
self.transfer(args.into_iter(), 1);
|
|
||||||
self.regs.gpio.modify(|_, w| w.wp_n(false));
|
|
||||||
while self.read_reg::<SR1>().wel() {}
|
|
||||||
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn transfer<'s: 't, 't, Args, W>(&'s mut self, args: Args, len: usize) -> Transfer<'t, Args, W>
|
pub fn transfer<'s: 't, 't, Args, W>(&'s mut self, args: Args, len: usize) -> Transfer<'t, Args, W>
|
||||||
where
|
where
|
||||||
Args: Iterator<Item = W>,
|
Args: Iterator<Item = W>,
|
||||||
|
@ -458,19 +443,19 @@ impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
|
||||||
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(w.into());
|
||||||
}
|
}
|
||||||
self.sent += 1;
|
self.sent += 1;
|
||||||
}
|
}
|
||||||
SpiWord::W16(w) => {
|
SpiWord::W16(w) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.flash.regs.txd2.write(u32::from(w) << 16);
|
self.flash.regs.txd2.write(w.into());
|
||||||
}
|
}
|
||||||
self.sent += 2;
|
self.sent += 2;
|
||||||
}
|
}
|
||||||
SpiWord::W24(w) => {
|
SpiWord::W24(w) => {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.flash.regs.txd3.write(w << 8);
|
self.flash.regs.txd3.write(w);
|
||||||
}
|
}
|
||||||
self.sent += 3;
|
self.sent += 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ pub struct RegisterBlock {
|
||||||
pub slave_idle_count: RW<u32>,
|
pub slave_idle_count: RW<u32>,
|
||||||
pub tx_thres: RW<u32>,
|
pub tx_thres: RW<u32>,
|
||||||
pub rx_thres: RW<u32>,
|
pub rx_thres: RW<u32>,
|
||||||
pub gpio: QspiGpio,
|
pub gpio: RW<u32>,
|
||||||
pub _unused1: RO<u32>,
|
pub _unused1: RO<u32>,
|
||||||
pub lpbk_dly_adj: RW<u32>,
|
pub lpbk_dly_adj: RW<u32>,
|
||||||
pub _unused2: [RO<u32>; 17],
|
pub _unused2: [RO<u32>; 17],
|
||||||
|
@ -108,12 +108,6 @@ register_bit!(intr_dis, tx_fifo_underflow, 6);
|
||||||
register!(enable, Enable, RW, u32);
|
register!(enable, Enable, RW, u32);
|
||||||
register_bit!(enable, spi_en, 0);
|
register_bit!(enable, spi_en, 0);
|
||||||
|
|
||||||
// named to avoid confusion with normal gpio
|
|
||||||
register!(qspi_gpio, QspiGpio, RW, u32);
|
|
||||||
register_bit!(qspi_gpio,
|
|
||||||
/// Write protect pin (inverted)
|
|
||||||
wp_n, 0);
|
|
||||||
|
|
||||||
register!(lqspi_cfg, LqspiCfg, RW, u32);
|
register!(lqspi_cfg, LqspiCfg, RW, u32);
|
||||||
register_bits!(lqspi_cfg, inst_code, u8, 0, 7);
|
register_bits!(lqspi_cfg, inst_code, u8, 0, 7);
|
||||||
register_bits!(lqspi_cfg, dummy_byte, u8, 8, 10);
|
register_bits!(lqspi_cfg, dummy_byte, u8, 8, 10);
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
use bit_field::BitField;
|
|
||||||
|
|
||||||
pub trait SpiFlashRegister {
|
|
||||||
fn inst_code() -> u8;
|
|
||||||
fn transfer_len() -> usize;
|
|
||||||
fn new<I: Iterator<Item=u8>>(src: I) -> Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! u8_register {
|
|
||||||
($name: ident, $inst_code: expr) => {
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct $name {
|
|
||||||
pub inner: u8,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpiFlashRegister for $name {
|
|
||||||
fn inst_code() -> u8 {
|
|
||||||
$inst_code
|
|
||||||
}
|
|
||||||
|
|
||||||
fn transfer_len() -> usize {
|
|
||||||
2
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new<I: Iterator<Item=u8>>(mut src: I) -> Self {
|
|
||||||
$name {
|
|
||||||
inner: src.next().unwrap(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
u8_register!(CR, 0x35);
|
|
||||||
u8_register!(SR1, 0x05);
|
|
||||||
impl SR1 {
|
|
||||||
/// Write In Progress
|
|
||||||
pub fn wip(&self) -> bool {
|
|
||||||
self.inner.get_bit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Write Enable Latch
|
|
||||||
pub fn wel(&self) -> bool {
|
|
||||||
self.inner.get_bit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Erase Error Occurred
|
|
||||||
pub fn e_err(&self) -> bool {
|
|
||||||
self.inner.get_bit(5)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Programming Error Occurred
|
|
||||||
pub fn p_err(&self) -> bool {
|
|
||||||
self.inner.get_bit(6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u8_register!(SR2, 0x07);
|
|
Loading…
Reference in New Issue