add distinct read and write functions
This commit is contained in:
parent
d0dd0f007a
commit
28c0023c9a
@ -456,11 +456,138 @@ where
|
|||||||
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
|
type WriteReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a;
|
||||||
|
|
||||||
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
fn read<'a>(&'a mut self, address: u8, buffer: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
||||||
self.write_read(address, &[], buffer)
|
async move {
|
||||||
|
// NOTE: RAM slice check for buffer is not necessary, as a mutable
|
||||||
|
// slice can only be built from data located in RAM.
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
|
// before any DMA action has started.
|
||||||
|
compiler_fence(SeqCst);
|
||||||
|
|
||||||
|
r.address.write(|w| unsafe { w.address().bits(address) });
|
||||||
|
|
||||||
|
// Set up the DMA read.
|
||||||
|
unsafe { self.set_rx_buffer(buffer)? };
|
||||||
|
|
||||||
|
// Reset events
|
||||||
|
r.events_stopped.reset();
|
||||||
|
r.events_error.reset();
|
||||||
|
self.clear_errorsrc();
|
||||||
|
|
||||||
|
// Enable events
|
||||||
|
r.intenset.write(|w| w.stopped().set().error().set());
|
||||||
|
|
||||||
|
// Start read operation.
|
||||||
|
r.shorts.write(|w| w.lastrx_stop().enabled());
|
||||||
|
r.tasks_startrx.write(|w|
|
||||||
|
// `1` is a valid value to write to task registers.
|
||||||
|
unsafe { w.bits(1) });
|
||||||
|
|
||||||
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
|
// after all possible DMA actions have completed.
|
||||||
|
compiler_fence(SeqCst);
|
||||||
|
|
||||||
|
// Wait for 'stopped' event.
|
||||||
|
poll_fn(|cx| {
|
||||||
|
s.end_waker.register(cx.waker());
|
||||||
|
if r.events_stopped.read().bits() != 0 {
|
||||||
|
r.events_stopped.reset();
|
||||||
|
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop if an error occured
|
||||||
|
if r.events_error.read().bits() != 0 {
|
||||||
|
r.events_error.reset();
|
||||||
|
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
Poll::Pending
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.read_errorsrc()?;
|
||||||
|
|
||||||
|
if r.rxd.amount.read().bits() != buffer.len() as u32 {
|
||||||
|
return Err(Error::Receive);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
|
fn write<'a>(&'a mut self, address: u8, bytes: &'a [u8]) -> Self::WriteFuture<'a> {
|
||||||
self.write_read(address, bytes, &mut [])
|
async move {
|
||||||
|
slice_in_ram_or(bytes, Error::DMABufferNotInDataMemory)?;
|
||||||
|
|
||||||
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
|
// before any DMA action has started.
|
||||||
|
compiler_fence(SeqCst);
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
let s = T::state();
|
||||||
|
|
||||||
|
// Set up current address we're trying to talk to
|
||||||
|
r.address.write(|w| unsafe { w.address().bits(address) });
|
||||||
|
|
||||||
|
// Set up DMA buffers.
|
||||||
|
unsafe {
|
||||||
|
self.set_tx_buffer(bytes)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset events
|
||||||
|
r.events_stopped.reset();
|
||||||
|
r.events_error.reset();
|
||||||
|
r.events_lasttx.reset();
|
||||||
|
self.clear_errorsrc();
|
||||||
|
|
||||||
|
// Enable events
|
||||||
|
r.intenset.write(|w| w.stopped().set().error().set());
|
||||||
|
|
||||||
|
// Start write operation.
|
||||||
|
r.shorts.write(|w| w.lasttx_stop().enabled());
|
||||||
|
r.tasks_starttx.write(|w|
|
||||||
|
// `1` is a valid value to write to task registers.
|
||||||
|
unsafe { w.bits(1) });
|
||||||
|
|
||||||
|
// Conservative compiler fence to prevent optimizations that do not
|
||||||
|
// take in to account actions by DMA. The fence has been placed here,
|
||||||
|
// after all possible DMA actions have completed.
|
||||||
|
compiler_fence(SeqCst);
|
||||||
|
|
||||||
|
// Wait for 'stopped' event.
|
||||||
|
poll_fn(|cx| {
|
||||||
|
s.end_waker.register(cx.waker());
|
||||||
|
if r.events_stopped.read().bits() != 0 {
|
||||||
|
r.events_stopped.reset();
|
||||||
|
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop if an error occured
|
||||||
|
if r.events_error.read().bits() != 0 {
|
||||||
|
r.events_error.reset();
|
||||||
|
r.tasks_stop.write(|w| unsafe { w.bits(1) });
|
||||||
|
}
|
||||||
|
|
||||||
|
Poll::Pending
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
|
||||||
|
self.read_errorsrc()?;
|
||||||
|
|
||||||
|
if r.txd.amount.read().bits() != bytes.len() as u32 {
|
||||||
|
return Err(Error::Transmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_read<'a>(
|
fn write_read<'a>(
|
||||||
@ -533,6 +660,8 @@ where
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
self.read_errorsrc()?;
|
||||||
|
|
||||||
let bad_write = r.txd.amount.read().bits() != bytes.len() as u32;
|
let bad_write = r.txd.amount.read().bits() != bytes.len() as u32;
|
||||||
let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32;
|
let bad_read = r.rxd.amount.read().bits() != buffer.len() as u32;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user