Open matthijskooijman opened 9 years ago
Or perhaps the SPI API should be able to accommodate this sort of case? Ideally, what's needed is for beginTransaction() to disable the interrupts being used by all other SPI libraries.
That only works for this particular case. I can imagine libraries that do both SPI transfers from the main loop and from ISRs, which would need their own ISR disabled (though they can of course do that manually). Also, once interruptMode
ends up at 2, the scheme you propose breaks down anyway.
The problem with nRF8001 is the request to initiate communication is done by asserting chip select, which then causes the chip to request an interrupt. SPI transfers must be blocked during that request-to-interrupt time.
Doesn't this actually mean that you have to poll for data instead of properly using interrupts? So can't you just assert SS, then poll the "interupt" pin from a loop for a while, do work if it ever gets asserted, then unassert SS and return? I might be misunderstanding what needs to happen though, could you provide a link to the current code?
Doesn't this actually mean that you have to poll for data instead of properly using interrupts? So can't you just assert SS, then poll the "interupt" pin from a loop for a while, do work if it ever gets asserted, then unassert SS and return?
Yes, that's one possible approach. It's actually the first way I tried this. It gets thorny because the external interrupt hardware detects the low condition while interrupts are disabled, causing a false interrupt afterwards. There are other issues too, which I didn't fully resolve, but yes, this is one possible way to work around the issue.
Also, once interruptMode ends up at 2, the scheme you propose breaks down anyway.
Yes. Other things break when interruptMode is 2. The code should really have some comments or documentation explaining that interruptMode = 2 is a feature that will likely be removed in the future, when/if Arduino gains APIs and definitions for other interrupts. Users should never intentionally pass inputs to usingInterrupt() that cause it to use that mode. It's only meant to allow future parameters (that aren't defined today) to later become backwards compatible.
One alternative is to simply ignore this problem. Libraries wishing to use interrupts this way will simply have to add hardware-specific workarounds, if the SPI API doesn't provide all the needed functionality.
I had a look at the datasheet, I understand how things can get tricky here indeed. I'm not sure what a clean way to fix this in the SPI transaction API is, though, so I guess working around it might indeed be the way to go...
I honestly do not believe there is any perfectly clean solution.
Long-term, if the SPI lib or core lib supported a hardware independent way to disable and re-enable external pin interrupts, I believe that would be a lot cleaner than requiring hardware-specific code inside Adafruit's library.
But politically, perhaps it's easier to have a large mess inside a 3rd party library than a small mess in Arduino's software?
In the PR, @Nantonos posted:
Hello Paul,
Monday, November 17, 2014, 3:39:39 PM, you wrote:
At the moment, I'm working with a kludge where I just turn that specific interrupt back on. That may be the final answer.
Perhaps beginTransaction() could have an alternate/overloaded version that disables all but a specific interrupt. Or perhaps just a function to re-enable the interrupt would work?
Would it be possible to add a (normally empty) list in interrupts to NOT disable to SPISettings?
That way, the SPISettings for nRF8001 would specify its particular CS interrupt, and any other SPISettings would not specify any interrupts (same as they do now).
I don't know if that is feasible or has bad side effects, its just an idea that occurred to me on reading your mail.
Originally posted in arduino/Arduino#2449 by @PaulStoffregen: