Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix known SPI issues #2179

Merged
merged 12 commits into from
Sep 19, 2024
4 changes: 4 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fix `SpiBus::transfer` transferring data twice in some cases (#2159)
- Fixed UART freezing when using `RcFast` clock source on ESP32-C2/C3 (#2170)
- I2S: on ESP32 and ESP32-S2 data is now output to the right (WS=1) channel first. (#2194)
- SPI: Fixed an issue where unexpected data was written outside of the read buffer (#2179)
- SPI: Fixed an issue where `wait` has returned before the DMA has finished writing the memory (#2179)
- SPI: Fixed an issue where repeated calls to `dma_transfer` may end up looping indefinitely (#2179)
- SPI: Fixed an issue that prevented correctly reading the first byte in a transaction (#2179)

### Removed

Expand Down
41 changes: 33 additions & 8 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ where
bitfield::bitfield! {
#[doc(hidden)]
#[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DmaDescriptorFlags(u32);

u16;
Expand All @@ -227,6 +228,7 @@ impl Debug for DmaDescriptorFlags {

/// A DMA transfer descriptor.
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct DmaDescriptor {
pub(crate) flags: DmaDescriptorFlags,
pub(crate) buffer: *mut u8,
Expand Down Expand Up @@ -397,6 +399,29 @@ macro_rules! dma_circular_descriptors {
};
}

/// Declares a DMA buffer with a specific size, aligned to 4 bytes
#[doc(hidden)]
#[macro_export]
macro_rules! declare_aligned_dma_buffer {
($name:ident, $size:expr) => {
// ESP32 requires word alignment for DMA buffers.
// ESP32-S2 technically supports byte-aligned DMA buffers, but the
// transfer ends up writing out of bounds.
// if the buffer's length is 2 or 3 (mod 4).
static mut $name: [u32; ($size + 3) / 4] = [0; ($size + 3) / 4];
MabezDev marked this conversation as resolved.
Show resolved Hide resolved
};
}

/// Turns the potentially oversized static `u32`` array reference into a
/// correctly sized `u8` one
#[doc(hidden)]
#[macro_export]
macro_rules! as_mut_byte_array {
($name:ident, $size:expr) => {
unsafe { &mut *($name.as_mut_ptr() as *mut [u8; $size]) }
};
}

/// Convenience macro to create DMA buffers and descriptors with specific chunk
/// size.
///
Expand All @@ -414,15 +439,15 @@ macro_rules! dma_circular_descriptors {
#[macro_export]
macro_rules! dma_buffers_chunk_size {
bugadani marked this conversation as resolved.
Show resolved Hide resolved
($rx_size:expr, $tx_size:expr, $chunk_size:expr) => {{
static mut RX_BUFFER: [u8; $rx_size] = [0u8; $rx_size];
static mut TX_BUFFER: [u8; $tx_size] = [0u8; $tx_size];
$crate::declare_aligned_dma_buffer!(RX_BUFFER, $rx_size);
$crate::declare_aligned_dma_buffer!(TX_BUFFER, $tx_size);
let (mut rx_descriptors, mut tx_descriptors) =
$crate::dma_descriptors_chunk_size!($rx_size, $tx_size, $chunk_size);
unsafe {
(
&mut RX_BUFFER,
$crate::as_mut_byte_array!(RX_BUFFER, $rx_size),
rx_descriptors,
&mut TX_BUFFER,
$crate::as_mut_byte_array!(TX_BUFFER, $tx_size),
tx_descriptors,
)
}
Expand Down Expand Up @@ -450,15 +475,15 @@ macro_rules! dma_buffers_chunk_size {
#[macro_export]
macro_rules! dma_circular_buffers_chunk_size {
($rx_size:expr, $tx_size:expr, $chunk_size:expr) => {{
static mut RX_BUFFER: [u8; $rx_size] = [0u8; $rx_size];
static mut TX_BUFFER: [u8; $tx_size] = [0u8; $tx_size];
$crate::declare_aligned_dma_buffer!(RX_BUFFER, $rx_size);
$crate::declare_aligned_dma_buffer!(TX_BUFFER, $tx_size);
let (mut rx_descriptors, mut tx_descriptors) =
$crate::dma_circular_descriptors_chunk_size!($rx_size, $tx_size, $chunk_size);
unsafe {
(
&mut RX_BUFFER,
$crate::as_mut_byte_array!(RX_BUFFER, $rx_size),
rx_descriptors,
&mut TX_BUFFER,
$crate::as_mut_byte_array!(TX_BUFFER, $tx_size),
tx_descriptors,
)
}
Expand Down
2 changes: 1 addition & 1 deletion esp-hal/src/soc/esp32/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ pub(crate) fn get_io_mux_reg(gpio_num: u8) -> &'static io_mux::GPIO0 {
37 => transmute::<&'static io_mux::GPIO37, &'static io_mux::GPIO0>(iomux.gpio37()),
38 => transmute::<&'static io_mux::GPIO38, &'static io_mux::GPIO0>(iomux.gpio38()),
39 => transmute::<&'static io_mux::GPIO39, &'static io_mux::GPIO0>(iomux.gpio39()),
_ => panic!(),
other => panic!("GPIO {} does not exist", other),
}
}
}
Expand Down
Loading
Loading