From 27411658d9710451b04efe014747606018646527 Mon Sep 17 00:00:00 2001 From: Priit Laes Date: Thu, 8 Feb 2024 21:43:05 +0200 Subject: [PATCH] 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. --- embassy-nrf/src/spim.rs | 14 +++++++++++--- embassy-nrf/src/spis.rs | 8 +++++++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 6b6f79188..8937159df 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -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::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::{self, AnyPin, Pin as GpioPin, PselBits}; use crate::interrupt::typelevel::Interrupt; @@ -25,9 +25,9 @@ use crate::{interrupt, pac, Peripheral}; #[cfg_attr(feature = "defmt", derive(defmt::Format))] #[non_exhaustive] pub enum Error { - /// TX buffer was too long. + /// Supplied TX buffer overflows EasyDMA transmit buffer TxBufferTooLong, - /// RX buffer was too long. + /// Supplied RX buffer overflows EasyDMA receive buffer RxBufferTooLong, /// EasyDMA can only read from data memory, read only buffers in flash will fail. BufferNotInRAM, @@ -220,11 +220,19 @@ impl<'d, T: Instance> Spim<'d, T> { // Set up the DMA write. 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.maxcnt.write(|w| unsafe { w.maxcnt().bits(tx_len as _) }); // Set up the DMA read. 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.maxcnt.write(|w| unsafe { w.maxcnt().bits(rx_len as _) }); diff --git a/embassy-nrf/src/spis.rs b/embassy-nrf/src/spis.rs index 60f4c9865..772ca40cc 100644 --- a/embassy-nrf/src/spis.rs +++ b/embassy-nrf/src/spis.rs @@ -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 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::{self, AnyPin, Pin as GpioPin}; use crate::interrupt::typelevel::Interrupt; @@ -227,11 +227,17 @@ impl<'d, T: Instance> Spis<'d, T> { // Set up the DMA write. 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.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) }); // Set up the DMA read. 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.maxcnt.write(|w| unsafe { w.maxcnt().bits(len as _) });