-
-
Notifications
You must be signed in to change notification settings - Fork 7k
Ide 1.5.x AVR and sam (ARM) SPI atomicity fixes #2376
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
Conversation
Hi @xxxajk, wow, at a first sight it looks like there is a lot of work behind this patch. BTW it's very difficult to review your changes because there are a lot of whitespace/indent changes: if you look at the diff here https://github.com/arduino/Arduino/pull/2376/files it seems that you changed the whole file. May I ask you to remove all the whitespace/indent changes? I see also that the "atomicity" fix is just one of many fixes. It would be really great if you could isolate each fix into a separate commit. For example I see that you added some NOPs into the SPI.transfer() on AVR, I guess that this change is unrelated with atomicity and having that into a separate commit with 2 lines of comment into the commit itself will help a lot the global understanding and review of your patch. |
I believe this is based on the copy from Teensy, which differs slightly from Arduino's version. For the patch I submitted to Arduino a few months ago, I did pretty much what you just described... bringing all the code into the Arduino original file with formatting and white space preserved. On the ARM Teensy code, I had added an experimental feature to turn on a LED if a transaction begin/end mismatch was detected. Looks like that was ported to AVR. I only developed this on ARM and used it briefly while testing the horribly confusing CC3000 library. It's not a feature we discussed on the developer mail list, so I never brought it up, as I didn't want to complicate matters. Still, it's kinda useful when testing. |
Yes, paul, and i sent you a copy as well for teensyduino on the forum Christian: sorry abot the whitespace. Just tell git to ignore it
|
git diff -b --ignore-blank-lines |
I'll take care of the whitespace dilemma. It really isn't a big deal IMHO. I just need some time to do that. |
Some time ago, 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. I also didn't bring this and many other minor SPI issues up before, because I didn't want to over-complicate a contribution that was already very "large". |
@xxxajk I'm going to remove the indent changes from your commits with |
Go for it
|
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.
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.
Can one of the admins verify this patch? |
I see that half the patch made it into 1.6.0 (the avr half). |
From arduino/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.
From arduino/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. (Filtered from arduino/Arduino@53e25d8)
From arduino/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.
From arduino/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.
From arduino/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.
From arduino/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.
From arduino/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.
From arduino/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.
Closing as already merged in master (please reopen if I'm wrong) |
I actually think this is only merged for AVR, not SAM or SAMD. I was going to write that I'm not entirely convinced of the necessity of this atomicity, but looking through the comments it seems making One other change included here that is still missing from SAM/SAMD is the addition of I'm not sure if we should reopen this, or just create new issues on the SAM and SAMD repositories to track this? |
I'd go for keeping it closed and create new PRs on sam/samd |
About the atomicity fix for AVR I remember your comment here and by re-reading it now I see that at the times we didn't realize that the operation:
is probably not compiled as a single-instruction but as a read+set+write. My feeling is that taking this into consideration we may optimize the code and remove the guards. Anyway, the SPI lib is now well tested and untouched for a very long time, changing it again will require a lot of validation test I don't have the time to look again into this. About the atomicity fix for SAM, since we hadn't any report about issues on SPI, my feeling is that the guard is not needed but, again, this is totally empirical. |
I'm not sure why that would be? Wouldn't this only be more reason to do this atomically? Consider a case where another pin ISR runs (e.g. one that is not in
I'm pretty sure it is needed, for the same reasons on AVR, but it perhaps it doesn't show up so much due to the limited number of users, or because they don't often do tricky things in ISRs? In any case, it would be good to at least create an issue in both repositories to track this, probably with a link to my comment above (which again links to various other relevant comments). I don't have time to create the tickets right now, though. |
oh, you're right :-)
No, my thought is that on ARM disabling the ISR is already atomic (-> is done in a single instruction), but this is just a thought, all to be verified :-) |
Ah, but that still leaves the issue with the static I also just realized that the race condition I described here:
is a lot broader then I thought. If, at any point during an SPI transaction, a pin interrupt (that is or is not in
(or possibly do the masking with |
From arduino/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.
These are the fixes for interacting with SPI methods without accidentally stepping on them from some other place, such as a scheduler, or other non-pin interrupt source. It also prevents updates to the variables from being interrupted by a pin interrupt, which can corrupt the mask/stored mask. and other states.
AVR is 100% tested, and solid.
sam is untested because I lack the hardware to do so.