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

Spurious CS high when using SPI enable_chip_select_0 #111

Closed
algesten opened this issue Jul 5, 2021 · 3 comments
Closed

Spurious CS high when using SPI enable_chip_select_0 #111

algesten opened this issue Jul 5, 2021 · 3 comments

Comments

@algesten
Copy link
Contributor

algesten commented Jul 5, 2021

I've been debugging an SPI problem for the last week, and in the end I ended up buying a logic analyzer to hunt the problem down.

The problem seems to stem from using enable_chip_select_0 instead of taking control over the CS myself.

I apologize in advance if the problem isn't in imxrt-hal, I've tried to follow the code, but I don't quite get how this specific feature works.

The code in question is this:

    let (_, _, _, spi4_builder) = p.spi.clock(
        &mut p.ccm.handle,
        ccm::spi::ClockSelect::Pll2,
        ccm::spi::PrescalarSelect::LPSPI_PODF_5,
    );

    let mut spi = spi4_builder.build(pins.p11, pins.p12, pins.p13);

    spi.set_clock_speed(bsp::hal::spi::ClockSpeed(1_000_000))
        .unwrap();

    spi.enable_chip_select_0(pins.p10);

    spi.set_mode(spi::MODE_0).unwrap();
    spi.clear_fifo();


// and later (using u16, since my chip uses that by default)

        let mut buf2 = [0x4100, 0];
        spi.transfer(&mut buf2)?;

Recording this with the logic analyzer I get this:

  • White is CS
  • Brown is clock
  • Red is MOSI
  • Orange is MISO

Screen Shot 2021-07-05 at 18 37 11 2

Notice how the white CS goes to high in between word 1 and word 2. I believe this not correct and the chip I'm working with (an IO-expander MCP23S17), does not like it at all.

The workaround is to take control over the CS myself, so quite easily solved once I saw the problem, but I wonder whether the behavior of method.enable_chip_select_0 can be fixed?

@mciantyre
Copy link
Member

Thanks for the detailed report! These observations are consistent with how I've seen this SPI peripheral manage the chip select pin. Since the CS pin is fully managed by the hardware, changing the behavior requires us to study the reference manual, and understand what settings are available. It's definitely an imxrt-hal issue, so you're in the right place.

Besides driving CS manually, there might be two other options:

  • Try using a u32 transfer with one value, instead of u16 transfers with two values. The timing diagram shows a CS transition in between two u16s. It does not show a CS transition in between the two u8s that comprise one u16. So if we we treat the transaction as a u32, we shouldn't see the CS transition. I'll guess that this is a workaround, but it may be easier to implement and test. A u32 implementation resembling this code might be all we need.

  • Quick check through the reference manual reveals this field in the transmit command register:

    image

    At a glance, this sounds like the real solution. But, I've not tried it. This might warrant a custom implementation for the embedded_hal::blocking::spi traits.

@mciantyre
Copy link
Member

This should be resolved in imxrt-hal v0.5. The LPSPI driver now uses continuous transfers for blocking u8/u16/u32 exchanges and writes. Chip select remains asserted throughout the entire transfer.

The images below (click to expand) show logic analyzer recordings of the hal_spi example that exchanges this buffer

let data: [Elem; 5] = [0xDE, 0xAD, 0xBE, 0xEF, 0xA5];

where Elem is one of

u8 hal_spi_u8
u16 hal_spi_u16
u32 hal_spi_u32

@algesten
Copy link
Contributor Author

algesten commented Jan 5, 2023

Excellent! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants