forked from M-Labs/zynq-rs
zynq::flash: split into mod transfer
This commit is contained in:
parent
8a9dde6119
commit
0d1cf04a34
@ -10,6 +10,8 @@ mod bytes;
|
|||||||
pub use bytes::{BytesTransferExt, BytesTransfer};
|
pub use bytes::{BytesTransferExt, BytesTransfer};
|
||||||
mod spi_flash_register;
|
mod spi_flash_register;
|
||||||
use spi_flash_register::*;
|
use spi_flash_register::*;
|
||||||
|
mod transfer;
|
||||||
|
use transfer::Transfer;
|
||||||
|
|
||||||
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
const FLASH_BAUD_RATE: u32 = 50_000_000;
|
||||||
/// 16 MB
|
/// 16 MB
|
||||||
@ -403,128 +405,4 @@ impl Flash<Manual> {
|
|||||||
{
|
{
|
||||||
Transfer::new(self, args, len)
|
Transfer::new(self, args, len)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> {
|
|
||||||
flash: &'a mut Flash<Manual>,
|
|
||||||
args: Args,
|
|
||||||
sent: usize,
|
|
||||||
received: usize,
|
|
||||||
len: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
|
|
||||||
pub fn new(flash: &'a mut Flash<Manual>, args: Args, len: usize) -> Self {
|
|
||||||
flash.regs.config.modify(|_, w| w.pcs(false));
|
|
||||||
flash.regs.enable.write(
|
|
||||||
regs::Enable::zeroed()
|
|
||||||
.spi_en(true)
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut xfer = Transfer {
|
|
||||||
flash,
|
|
||||||
args,
|
|
||||||
sent: 0,
|
|
||||||
received: 0,
|
|
||||||
len,
|
|
||||||
};
|
|
||||||
xfer.fill_tx_fifo();
|
|
||||||
xfer.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
|
||||||
xfer
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fill_tx_fifo(&mut self) {
|
|
||||||
while self.sent < self.len && !self.flash.regs.intr_status.read().tx_fifo_full() {
|
|
||||||
let arg = self.args.next()
|
|
||||||
.map(|n| n.into())
|
|
||||||
.unwrap_or(SpiWord::W32(0));
|
|
||||||
match arg {
|
|
||||||
SpiWord::W32(w) => {
|
|
||||||
// println!("txd0 {:08X}", w);
|
|
||||||
unsafe {
|
|
||||||
self.flash.regs.txd0.write(w);
|
|
||||||
}
|
|
||||||
self.sent += 4;
|
|
||||||
}
|
|
||||||
// Only txd0 can be used without flushing
|
|
||||||
_ => {
|
|
||||||
if !self.flash.regs.intr_status.read().tx_fifo_not_full() {
|
|
||||||
// Flush if neccessary
|
|
||||||
self.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
|
||||||
self.flash.wait_tx_fifo_flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
match arg {
|
|
||||||
SpiWord::W8(w) => {
|
|
||||||
// println!("txd1 {:02X}", w);
|
|
||||||
unsafe {
|
|
||||||
self.flash.regs.txd1.write(u32::from(w) << 24);
|
|
||||||
}
|
|
||||||
self.sent += 1;
|
|
||||||
}
|
|
||||||
SpiWord::W16(w) => {
|
|
||||||
unsafe {
|
|
||||||
self.flash.regs.txd2.write(u32::from(w) << 16);
|
|
||||||
}
|
|
||||||
self.sent += 2;
|
|
||||||
}
|
|
||||||
SpiWord::W24(w) => {
|
|
||||||
unsafe {
|
|
||||||
self.flash.regs.txd3.write(w << 8);
|
|
||||||
}
|
|
||||||
self.sent += 3;
|
|
||||||
}
|
|
||||||
SpiWord::W32(_) => unreachable!(),
|
|
||||||
}
|
|
||||||
|
|
||||||
self.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
|
||||||
self.flash.wait_tx_fifo_flush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn can_read(&mut self) -> bool {
|
|
||||||
self.flash.regs.intr_status.read().rx_fifo_not_empty()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read(&mut self) -> u32 {
|
|
||||||
let rx = self.flash.regs.rx_data.read();
|
|
||||||
self.received += 4;
|
|
||||||
rx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Drop for Transfer<'a, Args, W> {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// Discard remaining rx_data
|
|
||||||
while self.can_read() {
|
|
||||||
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)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Iterator for Transfer<'a, Args, W> {
|
|
||||||
type Item = u32;
|
|
||||||
|
|
||||||
fn next<'s>(&'s mut self) -> Option<u32> {
|
|
||||||
if self.received >= self.len {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
self.fill_tx_fifo();
|
|
||||||
|
|
||||||
while !self.can_read() {}
|
|
||||||
Some(self.read())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
127
src/zynq/flash/transfer.rs
Normal file
127
src/zynq/flash/transfer.rs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
use crate::regs::{RegisterR, RegisterW, RegisterRW};
|
||||||
|
use super::regs;
|
||||||
|
use super::{SpiWord, Flash, Manual};
|
||||||
|
|
||||||
|
pub struct Transfer<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> {
|
||||||
|
flash: &'a mut Flash<Manual>,
|
||||||
|
args: Args,
|
||||||
|
sent: usize,
|
||||||
|
received: usize,
|
||||||
|
len: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Transfer<'a, Args, W> {
|
||||||
|
pub fn new(flash: &'a mut Flash<Manual>, args: Args, len: usize) -> Self {
|
||||||
|
flash.regs.config.modify(|_, w| w.pcs(false));
|
||||||
|
flash.regs.enable.write(
|
||||||
|
regs::Enable::zeroed()
|
||||||
|
.spi_en(true)
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut xfer = Transfer {
|
||||||
|
flash,
|
||||||
|
args,
|
||||||
|
sent: 0,
|
||||||
|
received: 0,
|
||||||
|
len,
|
||||||
|
};
|
||||||
|
xfer.fill_tx_fifo();
|
||||||
|
xfer.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
||||||
|
xfer
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fill_tx_fifo(&mut self) {
|
||||||
|
while self.sent < self.len && !self.flash.regs.intr_status.read().tx_fifo_full() {
|
||||||
|
let arg = self.args.next()
|
||||||
|
.map(|n| n.into())
|
||||||
|
.unwrap_or(SpiWord::W32(0));
|
||||||
|
match arg {
|
||||||
|
SpiWord::W32(w) => {
|
||||||
|
// println!("txd0 {:08X}", w);
|
||||||
|
unsafe {
|
||||||
|
self.flash.regs.txd0.write(w);
|
||||||
|
}
|
||||||
|
self.sent += 4;
|
||||||
|
}
|
||||||
|
// Only txd0 can be used without flushing
|
||||||
|
_ => {
|
||||||
|
if !self.flash.regs.intr_status.read().tx_fifo_not_full() {
|
||||||
|
// Flush if necessary
|
||||||
|
self.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
||||||
|
self.flash.wait_tx_fifo_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
match arg {
|
||||||
|
SpiWord::W8(w) => {
|
||||||
|
// println!("txd1 {:02X}", w);
|
||||||
|
unsafe {
|
||||||
|
self.flash.regs.txd1.write(u32::from(w) << 24);
|
||||||
|
}
|
||||||
|
self.sent += 1;
|
||||||
|
}
|
||||||
|
SpiWord::W16(w) => {
|
||||||
|
unsafe {
|
||||||
|
self.flash.regs.txd2.write(u32::from(w) << 16);
|
||||||
|
}
|
||||||
|
self.sent += 2;
|
||||||
|
}
|
||||||
|
SpiWord::W24(w) => {
|
||||||
|
unsafe {
|
||||||
|
self.flash.regs.txd3.write(w << 8);
|
||||||
|
}
|
||||||
|
self.sent += 3;
|
||||||
|
}
|
||||||
|
SpiWord::W32(_) => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.flash.regs.config.modify(|_, w| w.man_start_com(true));
|
||||||
|
self.flash.wait_tx_fifo_flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_read(&mut self) -> bool {
|
||||||
|
self.flash.regs.intr_status.read().rx_fifo_not_empty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(&mut self) -> u32 {
|
||||||
|
let rx = self.flash.regs.rx_data.read();
|
||||||
|
self.received += 4;
|
||||||
|
rx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Drop for Transfer<'a, Args, W> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// Discard remaining rx_data
|
||||||
|
while self.can_read() {
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, Args: Iterator<Item = W>, W: Into<SpiWord>> Iterator for Transfer<'a, Args, W> {
|
||||||
|
type Item = u32;
|
||||||
|
|
||||||
|
fn next<'s>(&'s mut self) -> Option<u32> {
|
||||||
|
if self.received >= self.len {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.fill_tx_fifo();
|
||||||
|
|
||||||
|
while !self.can_read() {}
|
||||||
|
Some(self.read())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user