Add status checks

This commit is contained in:
Henrik Alsér 2022-11-05 01:12:25 +01:00
parent a3e8a6bc3a
commit 7da18e194a
2 changed files with 44 additions and 29 deletions

View file

@ -126,7 +126,7 @@ impl<'d, T: Instance> Spis<'d, T> {
let r = T::regs(); let r = T::regs();
// Configure pins // Configure pins.
sck.conf().write(|w| w.input().connect().drive().h0h1()); sck.conf().write(|w| w.input().connect().drive().h0h1());
cs.conf().write(|w| w.input().connect().drive().h0h1()); cs.conf().write(|w| w.input().connect().drive().h0h1());
if let Some(mosi) = &mosi { if let Some(mosi) = &mosi {
@ -151,10 +151,6 @@ impl<'d, T: Instance> Spis<'d, T> {
} }
} }
if config.auto_acquire {
r.shorts.write(|w| w.end_acquire().bit(true));
}
// Select pins. // Select pins.
r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) }); r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) });
r.psel.csn.write(|w| unsafe { w.bits(cs.psel_bits()) }); r.psel.csn.write(|w| unsafe { w.bits(cs.psel_bits()) });
@ -193,15 +189,20 @@ impl<'d, T: Instance> Spis<'d, T> {
w w
}); });
// Set over-read character // Set over-read character.
let orc = config.orc; let orc = config.orc;
r.orc.write(|w| unsafe { w.orc().bits(orc) }); r.orc.write(|w| unsafe { w.orc().bits(orc) });
// Set default character // Set default character.
let def = config.def; let def = config.def;
r.def.write(|w| unsafe { w.def().bits(def) }); r.def.write(|w| unsafe { w.def().bits(def) });
// Disable all events interrupts // Configure auto-acquire on 'transfer end' event.
if config.auto_acquire {
r.shorts.write(|w| w.end_acquire().bit(true));
}
// Disable all events interrupts.
r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) });
irq.set_handler(Self::on_interrupt); irq.set_handler(Self::on_interrupt);
@ -245,11 +246,11 @@ impl<'d, T: Instance> Spis<'d, T> {
r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); r.rxd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
// Reset and enable the end event // Reset and enable the end event.
r.events_end.reset(); r.events_end.reset();
r.intenset.write(|w| w.end().set()); r.intenset.write(|w| w.end().set());
// Release the semaphore // Release the semaphore.
r.tasks_release.write(|w| unsafe { w.bits(1) }); r.tasks_release.write(|w| unsafe { w.bits(1) });
Ok(()) Ok(())
@ -287,12 +288,15 @@ impl<'d, T: Instance> Spis<'d, T> {
let r = T::regs(); let r = T::regs();
let s = T::state(); let s = T::state();
// Clear status register.
r.status.write(|w| w.overflow().clear().overread().clear());
if r.semstat.read().bits() != 1 { if r.semstat.read().bits() != 1 {
// Reset and enable the acquire event // Reset and enable the acquire event.
r.events_acquired.reset(); r.events_acquired.reset();
r.intenset.write(|w| w.acquired().set()); r.intenset.write(|w| w.acquired().set());
// Requests acquiring the SPIS semaphore // Request acquiring the SPIS semaphore.
r.tasks_acquire.write(|w| unsafe { w.bits(1) }); r.tasks_acquire.write(|w| unsafe { w.bits(1) });
// Wait for 'acquire' event. // Wait for 'acquire' event.
@ -341,81 +345,92 @@ impl<'d, T: Instance> Spis<'d, T> {
} }
/// Reads data from the SPI bus without sending anything. Blocks until the buffer has been filled. /// Reads data from the SPI bus without sending anything. Blocks until the buffer has been filled.
/// Returns number of bytes read /// Returns number of bytes read.
pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<usize, Error> { pub fn blocking_read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
self.blocking_inner(data, &[]).map(|n| n.0) self.blocking_inner(data, &[]).map(|n| n.0)
} }
/// Simultaneously sends and receives data. Blocks until the transmission is completed. /// Simultaneously sends and receives data. Blocks until the transmission is completed.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail). /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
/// Returns number of bytes transferred `(n_rx, n_tx)` /// Returns number of bytes transferred `(n_rx, n_tx)`.
pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> { pub fn blocking_transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
self.blocking_inner(read, write) self.blocking_inner(read, write)
} }
/// Same as [`blocking_transfer`](Spis::blocking_transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. /// Same as [`blocking_transfer`](Spis::blocking_transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
/// Returns number of bytes transferred `(n_rx, n_tx)` /// Returns number of bytes transferred `(n_rx, n_tx)`.
pub fn blocking_transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> { pub fn blocking_transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
self.blocking_inner(read, write) self.blocking_inner(read, write)
} }
/// Simultaneously sends and receives data. /// Simultaneously sends and receives data.
/// Places the received data into the same buffer and blocks until the transmission is completed. /// Places the received data into the same buffer and blocks until the transmission is completed.
/// Returns number of bytes transferred /// Returns number of bytes transferred.
pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> { pub fn blocking_transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
self.blocking_inner_from_ram(data, data).map(|n| n.0) self.blocking_inner_from_ram(data, data).map(|n| n.0)
} }
/// Sends data, discarding any received data. Blocks until the transmission is completed. /// Sends data, discarding any received data. Blocks until the transmission is completed.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail). /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
/// Returns number of bytes written /// Returns number of bytes written.
pub fn blocking_write(&mut self, data: &[u8]) -> Result<usize, Error> { pub fn blocking_write(&mut self, data: &[u8]) -> Result<usize, Error> {
self.blocking_inner(&mut [], data).map(|n| n.1) self.blocking_inner(&mut [], data).map(|n| n.1)
} }
/// Same as [`blocking_write`](Spis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. /// Same as [`blocking_write`](Spis::blocking_write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
/// Returns number of bytes written /// Returns number of bytes written.
pub fn blocking_write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> { pub fn blocking_write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
self.blocking_inner(&mut [], data).map(|n| n.1) self.blocking_inner(&mut [], data).map(|n| n.1)
} }
/// Reads data from the SPI bus without sending anything. /// Reads data from the SPI bus without sending anything.
/// Returns number of bytes read /// Returns number of bytes read.
pub async fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> { pub async fn read(&mut self, data: &mut [u8]) -> Result<usize, Error> {
self.async_inner(data, &[]).await.map(|n| n.0) self.async_inner(data, &[]).await.map(|n| n.0)
} }
/// Simultaneously sends and receives data. /// Simultaneously sends and receives data.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail). /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
/// Returns number of bytes transferred `(n_rx, n_tx)` /// Returns number of bytes transferred `(n_rx, n_tx)`.
pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> { pub async fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
self.async_inner(read, write).await self.async_inner(read, write).await
} }
/// Same as [`transfer`](Spis::transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. /// Same as [`transfer`](Spis::transfer) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
/// Returns number of bytes transferred `(n_rx, n_tx)` /// Returns number of bytes transferred `(n_rx, n_tx)`.
pub async fn transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> { pub async fn transfer_from_ram(&mut self, read: &mut [u8], write: &[u8]) -> Result<(usize, usize), Error> {
self.async_inner_from_ram(read, write).await self.async_inner_from_ram(read, write).await
} }
/// Simultaneously sends and receives data. Places the received data into the same buffer. /// Simultaneously sends and receives data. Places the received data into the same buffer.
/// Returns number of bytes transferred /// Returns number of bytes transferred.
pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> { pub async fn transfer_in_place(&mut self, data: &mut [u8]) -> Result<usize, Error> {
self.async_inner_from_ram(data, data).await.map(|n| n.0) self.async_inner_from_ram(data, data).await.map(|n| n.0)
} }
/// Sends data, discarding any received data. /// Sends data, discarding any received data.
/// If necessary, the write buffer will be copied into RAM (see struct description for detail). /// If necessary, the write buffer will be copied into RAM (see struct description for detail).
/// Returns number of bytes written /// Returns number of bytes written.
pub async fn write(&mut self, data: &[u8]) -> Result<usize, Error> { pub async fn write(&mut self, data: &[u8]) -> Result<usize, Error> {
self.async_inner(&mut [], data).await.map(|n| n.1) self.async_inner(&mut [], data).await.map(|n| n.1)
} }
/// Same as [`write`](Spis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more. /// Same as [`write`](Spis::write) but will fail instead of copying data into RAM. Consult the module level documentation to learn more.
/// Returns number of bytes written /// Returns number of bytes written.
pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> { pub async fn write_from_ram(&mut self, data: &[u8]) -> Result<usize, Error> {
self.async_inner_from_ram(&mut [], data).await.map(|n| n.1) self.async_inner_from_ram(&mut [], data).await.map(|n| n.1)
} }
/// Checks if last transaction overread.
pub fn is_overread(&mut self) -> bool {
T::regs().status.read().overread().is_present()
}
/// Checks if last transaction overflowed.
pub fn is_overflow(&mut self) -> bool {
T::regs().status.read().overflow().is_present()
}
} }
impl<'d, T: Instance> Drop for Spis<'d, T> { impl<'d, T: Instance> Drop for Spis<'d, T> {
@ -516,15 +531,15 @@ impl<'d, T: Instance> SetConfig for Spis<'d, T> {
w w
}); });
// Set over-read character // Set over-read character.
let orc = config.orc; let orc = config.orc;
r.orc.write(|w| unsafe { w.orc().bits(orc) }); r.orc.write(|w| unsafe { w.orc().bits(orc) });
// Set default character // Set default character.
let def = config.def; let def = config.def;
r.def.write(|w| unsafe { w.def().bits(def) }); r.def.write(|w| unsafe { w.def().bits(def) });
// Set auto acquire // Configure auto-acquire on 'transfer end' event.
let auto_acquire = config.auto_acquire; let auto_acquire = config.auto_acquire;
r.shorts.write(|w| w.end_acquire().bit(auto_acquire)); r.shorts.write(|w| w.end_acquire().bit(auto_acquire));
} }

View file

@ -5,7 +5,7 @@
use defmt::info; use defmt::info;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_nrf::interrupt; use embassy_nrf::interrupt;
use embassy_nrf::spis::{self, Config}; use embassy_nrf::spis::{Spis, Config};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
#[embassy_executor::main] #[embassy_executor::main]
@ -14,7 +14,7 @@ async fn main(_spawner: Spawner) {
info!("Running!"); info!("Running!");
let irq = interrupt::take!(SPIM2_SPIS2_SPI2); let irq = interrupt::take!(SPIM2_SPIS2_SPI2);
let mut spis = spis::Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default()); let mut spis = Spis::new(p.SPI2, irq, p.P0_31, p.P0_29, p.P0_28, p.P0_30, Config::default());
loop { loop {
let mut buf = [0_u8; 64]; let mut buf = [0_u8; 64];