Skip to content

Crash when using SpiDevice::write (Because of a hidden alignment requirement) #295

Closed
@mlthlschr

Description

@mlthlschr

Hi, I am trying to write a small driver for an SPI device with registers. For that, I have the following function to write the instruction and then read the data:

pub fn read_registers<Spi>(
    spi: &mut Spi,
    first_register: u8,
    data: &mut [u8],
) -> Result<(), Spi::Error>
where
    Spi: SpiDevice,
    Spi::Bus: SpiBus,
{
    let cmd = 0x80 | first_register;
    spi.transaction(|b| {
       // this call crashes
        b.write(&[cmd])?;
        b.read(&mut data[..])?;
        Ok(())
    })?;

    Ok(())
}

However, it crashes on an ESP32-C3 with

PanicInfo {
    payload: Any { .. },
    message: Some(
        unsafe precondition(s) violated: ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null and the specified memory ranges do not overlap,
    ),
    location: Location {
        file: "/home/malte/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/panicking.rs",
        line: 90,
        col: 58,
    },
    can_unwind: false,
}
 
Backtrace:
 
0x420040d8
0x420040d8 - core::intrinsics::copy_nonoverlapping::runtime
    at /home/malte/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/intrinsics.rs:2280
0x42005178
0x42005178 - esp_hal_common::spi::Instance::write_bytes
    at /home/malte/.cargo/registry/src/github.com-1ecc6299db9ec823/esp-hal-common-0.3.0/src/spi.rs:1421
0x420080d8
0x420080d8 - esp_hal_common::spi::ehal1::<impl embedded_hal::spi::SpiBusWrite for esp_hal_common::spi::Spi<T>>::write
    at /home/malte/.cargo/registry/src/github.com-1ecc6299db9ec823/esp-hal-common-0.3.0/src/spi.rs:731
0x42006a1a
0x42006a1a - hal_driver_util::spi::read_registers::{{closure}}
    at /home/malte/code/hardware/ESP-rs/hal-driver-util/src/spi.rs:27
0x420049fa
0x420049fa - <esp_hal_common::spi::ehal1::SpiBusDevice<I,CS> as embedded_hal::spi::SpiDevice>::transaction::{{closure}}
    at /home/malte/.cargo/registry/src/github.com-1ecc6299db9ec823/esp-hal-common-0.3.0/src/spi.rs:907
0x42007c8a
0x42007c8a - critical_section::with
    at /home/malte/.cargo/registry/src/github.com-1ecc6299db9ec823/critical-section-1.1.1/src/lib.rs:226
0x42004934
0x42004934 - <esp_hal_common::spi::ehal1::SpiBusDevice<I,CS> as embedded_hal::spi::SpiDevice>::transaction
    at /home/malte/.cargo/registry/src/github.com-1ecc6299db9ec823/esp-hal-common-0.3.0/src/spi.rs:900
0x42006984
0x42006984 - hal_driver_util::spi::read_registers
    at /home/malte/code/hardware/ESP-rs/hal-driver-util/src/spi.rs:21

Do you know what is happening here? I am using not a line of unsafe code (in the code written by me) before calling this method.

I tried to read the register at a different place in the lib using spi.transfer() and there it works without problems.

Another observation: when I change the code inside the closure to

let cmd = [cmd;2];
b.write(&cmd);

it does not crash.
Using let cmd = [cmd;1]; however also crashes.

Update 1: this observation is not always true. Sometimes it does not work...

Update 2: this also happens when using transfer_in_place()

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions