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: DMA Module and SPI Peripheral #3619

Closed
wants to merge 5 commits into from
Closed

STM32: DMA Module and SPI Peripheral #3619

wants to merge 5 commits into from

Conversation

hierophect
Copy link
Collaborator

This PR adds SPI Peripheral/Slave APIs to shared-bindings, and implements a SPI Peripheral implementation in the STM32 port. Most of the setup and objects in the common-hal implementation are borrowed from the SPI class, since the two implementations are extremely close.

The primary means of accessing SPI Peripheral is wait_for_transaction(), which will wait in an interrupt-able state until CS is brought low, and then begin a non-blocking SPI transaction. Users can check whether the transaction is complete by checking spiperipheral.ready(), after which they can access incoming data.

Tested on the STM32F405 Feather, with an M4 Express master/host. Mostly successful - my only issue has been that the MISO line seems to be dragged low by the M4 Express, and I'm not sure whether that's the fault of this PR or not. When MISO is disconnected from the Feather M4, it outputs correct data when observed with a logic analyzer.

Keeping this PR in a draft state for now, as the implementation and API might change a lot. Open to any and all suggestions!

@hierophect hierophect added the stm label Oct 29, 2020
@hierophect hierophect requested review from tannewt and jepler October 29, 2020 15:49
Copy link
Member

@tannewt tannewt left a comment

Choose a reason for hiding this comment

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

Please add comments to the pyi stubs in shared-bindings about how the functions are used.

Is it possible to read a command and change the response within a single transaction? That's a common way for SPI devices to work.

@hierophect
Copy link
Collaborator Author

hierophect commented Oct 30, 2020

@tannewt so by that you mean the peripheral device takes incoming data, performs operations based on it, and adds to the ongoing TX buffer all during a single transaction (as in, one uninterrupted clock stream)? I hadn't considered that use case, that might require a DMA stream, I'd have to check. Can you provide an example of a device that does that so I could check out the protocol?

@jepler
Copy link
Member

jepler commented Oct 30, 2020

I don't know what kinds of devices you were hoping to implement/emulate, but for instance when you have a RAM-like device on the SPI bus a transaction looks like this (from the datasheet of https://learn.adafruit.com/adafruit-spi-fram-breakout/downloads)

image

this can be tough or impossible for a microcontroller to implement, since there's no clock stretching in SPI.

@tannewt
Copy link
Member

tannewt commented Nov 3, 2020

I suspect we may want specific styles of SPI peripherals that aren't timing sensitive. A simple example is shared memory where the native code implements two standard commands, read and write, and the python code can just read and write that memory. This would work for simple sensors where the python code just updates a value that can be read over SPI.

@hierophect
Copy link
Collaborator Author

hierophect commented Nov 6, 2020

My particular application is as follows - every 8 ms, the master device initiates a transaction and begins shifting bytes of data over to the peripheral. The peripheral is expected to have staged a return packet as well, which it sends in return. Then the CS is returned to high and the peripheral is expected to gather all the information it needs for the next packet, which in this case is acquiring and staging hardware inputs, handling errors, and loading everything into the output buffer, all within the 8ms before the master initiates a transaction again.

For my current API, you have two tools for this process - checking the status of an ongoing transaction with spi.ready() and variants, or using spi.wait_for_transaction() to hang out in an interrupt-able state until the CS line is lowered and the process is ready to begin again. I've considered other methods, such as simply starting the process to run in parallel to the python code, automatically delivering whatever data is in its object buffers at the time it receives a transaction. This would let the user update the buffers at their discretion without worrying about the timing, but it lacks any ability to dynamically change output data such as implementing an error checker or packet-ID auto-increment, which are things my application needs.

I suppose we'd have to hear from other users who want this feature about what they'd actually be using it for.

@hierophect
Copy link
Collaborator Author

Note that this module has been requested before, in #2131 and #2225, but it wasn't specified exactly what the desired application was.

@tannewt
Copy link
Member

tannewt commented Nov 10, 2020

@hierophect Interesting! I think that makes a lot of sense. I don't think it should be called SPIPeripheral though. Is there a name for this specific technique? We should keep this new class specific to this style of use. That way we can add a second class later for different approaches.

@hierophect hierophect changed the title STM32: add SPI Peripheral module STM32: DMA Module and SPI Peripheral Dec 2, 2020
@hierophect
Copy link
Collaborator Author

This has morphed into an implementation of SPI DMA. Unfortunately, it only outputs garbage data, and I can't figure out why. If anyone is interested in the the STM32 DMA module, and would like to help test why this occurs, it would be greatly appreciated.

@hierophect hierophect requested a review from tannewt December 2, 2020 21:16
@tannewt
Copy link
Member

tannewt commented Dec 3, 2020

Why did you request my review? What did you change? What do you want me to review?

@hierophect
Copy link
Collaborator Author

Why did you request my review? What did you change? What do you want me to review?

Sorry, it was a misclick, I mixed it up with another PR I had up. Nothing to review unless you can spot some obvious source of memory corruption that would be messing up the arrays.

@hierophect
Copy link
Collaborator Author

I've had difficulty with the low level implementation of this, which does not seem to be able to deliver outgoing data properly. Closing until I have time to revisit.

@hierophect hierophect closed this Jan 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants