nrf: spim/spis: Add size checks for EasyDMA buffer

On most nRF chips, maximum buffer size for EasyDMA is 255, thus
we never got any data when attempting to use 256 bytes as RX/TX buffer.
This commit is contained in:
Priit Laes 2024-02-08 21:43:05 +02:00
parent 2e15d1371a
commit 27411658d9
2 changed files with 18 additions and 4 deletions

View file

@ -13,7 +13,7 @@ pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MO
pub use pac::spim0::config::ORDER_A as BitOrder; pub use pac::spim0::config::ORDER_A as BitOrder;
pub use pac::spim0::frequency::FREQUENCY_A as Frequency; pub use pac::spim0::frequency::FREQUENCY_A as Frequency;
use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;
use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits};
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::typelevel::Interrupt;
@ -25,9 +25,9 @@ use crate::{interrupt, pac, Peripheral};
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[non_exhaustive] #[non_exhaustive]
pub enum Error { pub enum Error {
/// TX buffer was too long. /// Supplied TX buffer overflows EasyDMA transmit buffer
TxBufferTooLong, TxBufferTooLong,
/// RX buffer was too long. /// Supplied RX buffer overflows EasyDMA receive buffer
RxBufferTooLong, RxBufferTooLong,
/// EasyDMA can only read from data memory, read only buffers in flash will fail. /// EasyDMA can only read from data memory, read only buffers in flash will fail.
BufferNotInRAM, BufferNotInRAM,
@ -220,11 +220,19 @@ impl<'d, T: Instance> Spim<'d, T> {
// Set up the DMA write. // Set up the DMA write.
let (ptr, tx_len) = slice_ptr_parts(tx); let (ptr, tx_len) = slice_ptr_parts(tx);
if tx_len > EASY_DMA_SIZE {
return Err(Error::TxBufferTooLong);
}
r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) }); r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) });
// Set up the DMA read. // Set up the DMA read.
let (ptr, rx_len) = slice_ptr_parts_mut(rx); let (ptr, rx_len) = slice_ptr_parts_mut(rx);
if rx_len > EASY_DMA_SIZE {
return Err(Error::RxBufferTooLong);
}
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(rx_len as _) }); r.rxd.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) });

View file

@ -11,7 +11,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef};
pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3};
pub use pac::spis0::config::ORDER_A as BitOrder; pub use pac::spis0::config::ORDER_A as BitOrder;
use crate::chip::FORCE_COPY_BUFFER_SIZE; use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE};
use crate::gpio::sealed::Pin as _; use crate::gpio::sealed::Pin as _;
use crate::gpio::{self, AnyPin, Pin as GpioPin}; use crate::gpio::{self, AnyPin, Pin as GpioPin};
use crate::interrupt::typelevel::Interrupt; use crate::interrupt::typelevel::Interrupt;
@ -227,11 +227,17 @@ impl<'d, T: Instance> Spis<'d, T> {
// Set up the DMA write. // Set up the DMA write.
let (ptr, len) = slice_ptr_parts(tx); let (ptr, len) = slice_ptr_parts(tx);
if len > EASY_DMA_SIZE {
return Err(Error::TxBufferTooLong);
}
r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) }); r.txd.ptr.write(|w| unsafe { w.ptr().bits(ptr as _) });
r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); r.txd.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });
// Set up the DMA read. // Set up the DMA read.
let (ptr, len) = slice_ptr_parts_mut(rx); let (ptr, len) = slice_ptr_parts_mut(rx);
if len > EASY_DMA_SIZE {
return Err(Error::RxBufferTooLong);
}
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 _) });