zynq::flash: add read_reg_until()

This commit is contained in:
Astro 2019-12-15 23:52:47 +01:00
parent 0d1cf04a34
commit b94afa1581
2 changed files with 47 additions and 12 deletions

View File

@ -359,9 +359,40 @@ 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(), R::transfer_len()) let transfer = self.transfer(args.into_iter(), 2)
.bytes_transfer().skip(1); .bytes_transfer();
R::new(transfer) R::new(transfer.skip(1).next().unwrap())
}
pub fn read_reg_until<R, F, A>(&mut self, f: F) -> A
where
R: SpiFlashRegister,
F: Fn(R) -> Option<A>,
{
let mut result = None;
while result.is_none() {
let args = Some(R::inst_code());
for b in self.transfer(args.into_iter(), 32)
.bytes_transfer().skip(1) {
result = f(R::new(b));
if result.is_none() {
break;
}
}
}
result.unwrap()
}
/// Status Register-1 remains `0x00` immediately after invoking a command.
fn wait_while_sr1_zeroed(&mut self) -> SR1 {
self.read_reg_until::<SR1, _, SR1>(|sr1|
if sr1.is_zeroed() {
None
} else {
Some(sr1)
}
)
} }
/// Read Identification /// Read Identification
@ -385,7 +416,10 @@ impl Flash<Manual> {
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));
while !self.read_reg::<SR1>().wel() {} let sr1 = self.wait_while_sr1_zeroed();
if !sr1.wel() {
panic!("Cannot write-enable flash");
}
let result = f(self); let result = f(self);

View File

@ -2,8 +2,7 @@ use bit_field::BitField;
pub trait SpiFlashRegister { pub trait SpiFlashRegister {
fn inst_code() -> u8; fn inst_code() -> u8;
fn transfer_len() -> usize; fn new(src: u8) -> Self;
fn new<I: Iterator<Item=u8>>(src: I) -> Self;
} }
macro_rules! u8_register { macro_rules! u8_register {
@ -18,14 +17,16 @@ macro_rules! u8_register {
$inst_code $inst_code
} }
fn transfer_len() -> usize { fn new(src: u8) -> Self {
2 $name {
inner: src,
}
}
} }
fn new<I: Iterator<Item=u8>>(mut src: I) -> Self { impl $name {
$name { pub fn is_zeroed(&self) -> bool {
inner: src.next().unwrap(), self.inner == 0
}
} }
} }
}; };