-
-
Notifications
You must be signed in to change notification settings - Fork 7k
[AVR] SPI atomicity fix avr (part 1/2 of #2376), second try #2449
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
[AVR] SPI atomicity fix avr (part 1/2 of #2376), second try #2449
Conversation
From the previous, I think some of my comments haven't been responded to and are still relevant:
I also suggested the use of
Regarding the last commit, I'm not too happy with that commit message. The commit really still contains a couple of different changes, and the message doesn't really help in understanding what's happening and why. I'd propose the following commit message, just for the begin/endTransaction part:
Trying to write a commit message for the other change, disabling interrupts in |
Recently I've been working on Adafruit's nRF8001 (Bluetooth LE) library. It's the third of the 3 widely used libraries where SPI conflicts occur due to interrupts. The other 2 are CC3000 and RadioHead, which I ported some time ago. The last thing I want to do is make this already-difficult contribution even more complicated, or to delay 1.0.7, but I'm sad to say it seems the beginTransaction() API isn't quite enough for nRF8001. I'm still very actively working on this, so I'd prefer to comment in more detail within the next couple days, after I've had a chance to really work on this more. |
I believe there is a higher atomic level missing here. Shouldn't there be a way to acquire and release the SPI hardware module to allow several SPI transfers that must be run together? An example is the S25FL127S Flash. To erase a block two commands are transfered. The first to enable the operation and the second the actual erase command. Each begin-end operation is atomic with regard to updates of the internal data in the SPI driver but the high level operation also needs to be atomic with regard to the SPI resource. This is necessary for multiple SPI devices (interrupt sources) and/or multi-tasking with several task using the SPI resource. The Cosa SPI interface adds acquire/require on the SPI driver resource to handle this. The Cosa SPI begin/end operations does a little more than the Arduino version as they also handle the chip select. Cheers! |
The API allows this. All you have to do is surround the 2 SPI operations with a single SPI.beginTransaction() and SPI.endTransaction(). You can assert and de-assert chip selects or do pretty much anything you want during a SPI transaction. |
@mikaelpatel, I'm not sure I understand what you mean? Do you mean we need support for transactions consisting of multiple transfers, e.g. multiple SS ping toggles? We have that - because nothing in the SPI library toggles the SS pin for you, you can just begin a transaction and then toggle the SS pin as often as you like. Looking at the Cosa code, it seems that Arduino's begin/endTransaction are essentially Cosa's aqcuire/release and there is no Arduino equivalent of Cosa's begin end (these just toggle the SS pin, which is done manually in Arduino). |
@PaulStoffregen @matthijskooijman |
@PaulStoffregen, I've taken the liberty to create a new issue with the comment you posted and delete it here. I feel the issue you indicated is pretty orthogonal to this PR, so best keep discussion separate. See #2453. |
Agreed. We can use the |
453f176
to
0eb80f7
Compare
I've just pushed a revision that address some of the notes from Matthijs. |
Would be nice to be able to not have an ISR declared at all too, so that On Tue, Nov 18, 2014 at 2:33 PM, Cristian Maglie notifications@github.com
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
Changes look good. I'm still not convinced that I do feel we should be dropping We decided that |
The entire idea of SPI_ATOMIC_VERSION is so you DON'T need to add any new Next major fix you increment the number instead. On Wed, Nov 19, 2014 at 3:35 AM, Matthijs Kooijman <notifications@github.com
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
That applies to fixes related to SPI and atomicity, but what about a fix to the Wire library? digitalRead operation? Millis()? etc. We can add version numbers for all of those, but why not just use the global version number ( |
Personally, I would place a version number on them all. On Wed, Nov 19, 2014 at 8:36 AM, Matthijs Kooijman <notifications@github.com
Visit my github for awesome Arduino code @ https://github.com/xxxajk |
From arduino#2376 (comment) Quoting Andrew Kroll: [..this commit..] introduces a small delay that can prevent the wait loop form iterating when running at the maximum speed. This gives you a little more speed, even if it seems counter-intuitive. At lower speeds, it is unnoticed. Watch the output on an oscilloscope when running full SPI speed, and you should see closer back-to-back writes. Quoting Paul Stoffregen: I did quite a bit of experimenting with the NOP addition. The one that's in my copy gives about a 10% speedup on AVR.
… (Andrew Kroll) Previously, it could happen that SPI::beginTransaction was interrupted by an ISR, while it is changing the SPI_AVR_EIMSK register or interruptSave variable (it seems that there is a small window after changing SPI_AVR_EIMSK where an interrupt might still occur). If this happens, interruptSave is overwritten with an invalid value, permanently disabling the pin interrupts. To prevent this, disable interrupts globally while changing these values.
0eb80f7
to
a9735bf
Compare
Just added the comment about usingInterrupt()/notUsingInterrupt(). Tested on the @xxxajk's first test: it's fully working. About the SPI_ATOMIC_VERSION, this is a single variable that can be checked across different platforms/cores. I'm wondering that also SPI_HAVE_TRANSACTIONS could be inferred from the global ARDUINO variable, but having it allows to detect if SPI transaction are available even on non-arduino platforms where the ARDUINO variable is not present, and the same is valid for SPI_ATOMIC_VERSION, so I'm for keeping it. If there are no more concerns I'll go forward and merge this on 1.5 and 1.0. |
The other point is that someone may have an SPI library in their arduino/libraries directory, so, it makes sense overall. That's the additional intention. it would be beneficial for all libraries to have some sort of version number for this reason alone. Technically libraries are add-ons. |
Same needs to be done on Due and Zero. I have not had time to write the Zero code, since I am busy currently with a full rewrite of the USB HOST System code and USB Host Shield driver. |
Follow up #2381.
/cc @PaulStoffregen @matthijskooijman @xxxajk