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

stm32: add driver to use SPI as slave #2750

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

tomcur
Copy link

@tomcur tomcur commented Mar 29, 2024

This is a rough initial implementation of using the STM32 as an SPI slave device to think about possible APIs.

The non-DMA methods taking buffers don't make a ton of sense at the moment. The internal FIFO buffer of the SPI peripheral is 32 bits, which means these methods will never be able to read or write large buffers. The master device I'm testing with is a Raspberry Pi which doesn't clock lower than a few kilohertz, so it's difficult to see exactly what the behavior is e.g. when starting to read late in a transfer. Perhaps these methods should work on single words, allowing also to implement embedded_hal_nb::serial::Read and Write (though these traits don't include a bidirectional transfer).

The asynchronous version is implemented using DMA backed by ring buffers. This will allow implementing some embedded-io-async traits. On the chip I'm testing with (STM32WB55RGVx on a development board) the DMA-backed communication works up to somewhere between 2.5 and 3.0 MHz continously before overruns start happening. This seems a bit slow: the reference manual indicates this chip should be able to reach 24 Mbit/s.

This chip is SPIv2, I haven't tested the other versions.

This further needs some additional constructors configuring rx-only, tx-only, etc.

Closes #623

@tomcur
Copy link
Author

tomcur commented Apr 4, 2024

I've changed the non-DMA methods to operate on single words with a non-blocking signature using nb, similar to e.g. Uart::nb_read.

/// Read an exact number of elements from the receive ringbuffer into `buf`.
///
/// An overrun error occurs when the portion to be read was overwritten by DMA.
pub async fn read_exact(&mut self, buf: &mut [W]) -> Result<(), Error> {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would probably be good to note in the docstring that this triggers only when the DMA buffer is half full (it's documented in the DMA documentation, but probably it'd be nice to mention it here and in the other async methods as well - I ran into this and missed this when first testing).

@fbeutel
Copy link

fbeutel commented May 29, 2024

I sucessfully tested this branch with an STM32F0R8 device, works very well so far 👍

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

Successfully merging this pull request may close these issues.

stm32/spi: slave mode support
2 participants