-
-
Notifications
You must be signed in to change notification settings - Fork 40
fix: SPI: improve compatibility with external libraries #288
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
base: main
Are you sure you want to change the base?
Conversation
|
Does this actually fix the issue? The lock just prevents other callers from accessing the device, and |
|
As @KurtE's issue pointed out this seems to be an open issue on Zephyr: zephyrproject-rtos/zephyr#73930 Has anyone looked at that or at @KurtE's solution? Not sure that is really going to resolve the issue |
|
Thanks @facchinm @iabdalkader @mjs513. @facchinm - which boards did you try this on? As I mentioned in the issue #145, in the past I have tried this approach to blanketly turn on the HOLD_ON_CS flag or As @mjs513 mentioned - there are some Zephyr open issues on some of this, that appear to have several interrelated issues and or things to try, like: FIFO - is it enabled? Does it work. Is DMA enabled? Async Transfer - appears to speed things up, but ran into limits, like there may be a MAX number of bytes you can do And my guess is, it may be different for each different processor. But keeping my fingers crossed that this at least improves it. Thanks |
|
Quick update: I tried out my sort of simple ST7796 driver on Q which does some hacks, to get hold of the underlying SPI And then does several fillRects with different colors and prints out how long it took... Note: the fill code, uses temporary buffer that it fills with color and iterates calling spi_transcive.... With the beginTransaction code change, this code now appears to hang. And using SPI->transfer16... (I could try again, but that was potentially even slower)... And maybe has other issues. EDIT: In case anyone wishes to play along. |
|
@KurtE Thanks for taking the time to test this. Could you please provide a brief summary? Does the change in this PR work or not? If it works, does it improve the performance? About your custom code, assuming you're using a dev core, not a release, you could just add another overload to the SPI library, maybe something like: void transfer(void *buf, size_t count, size_t datasize);
void arduino::ZephyrSPI::transfer(void *buf, size_t count, datasize) {
int ret = transfer(buf, count, datasize==8 ? &config : &config16);
(void)ret;
}This should let you use our library to rule out any issues with your code. We could probably commit that, or later add data size to settings in the API. |
Currently it hangs with my own code. Now if I call with only SPI.transfer call, it did not hang, With the version I have that runs, using the SPI.transfer(buffer, size); Where I use temporary buffer, copy in May try some other simpler sketch to get more details
But could do with released code as changes is only in SPI library.
Could, personally I really really wish there was another API, that allows for write only and/or two buffers, write and read (can be NULL), that allows you to for example output directly out of a buffer without having it's contents overwritten. Also still wonder about hardware. Fifo? |
@KurtE Thanks for confirming. This was expected as the problem, as you and others noted, seems to be with inter-byte gaps, not with whole transfers. This change might still be helpful if you're transferring a single byte at a time, though I'm not sure if it would make sense to hold CS in that case.
I agree, the API is lacking, to say the least, but we can try to improve it. We could start by adding a data size arg somewhere. |
|
@iabdalkader @mjs513 @facchinm @pillo79 - Wondering if we should continue this here, or back to our original Note: I am mainly throwing darts here, and it has been a while since I really played with trying to improve the SPI speed. There are probably several different things that should be looked at and steps to resolve them, including: Are we properly configuring the SPI ports at the hardware level. I believe that there have been changes made in Zephyr over For those processors with FIFO on SPI, are they properly configured and software work with it? I wish there was an API part of the SPI object that returns zephyr specific information, like handle to the underlying Zephyr SPI object. Which allows apps/libraries to easier directly call the zephyr methods. Transfer APIs: allow you to set word size, write only transfers, maybe Async... Fine tunning of SPI and drivers. At least earlier with these drivers, I was finding that for things like Earlier I found that in the case here where we output <8 bit> <16 bit> <16 bit> <8 bit> <16 bit> <16 bit><8 bit> |
|
@facchinm @iabdalkader @pillo79 @mjs513 - Quick update Verified hang on simple sketch: Only output to serial: So it hangs or dies going from Transfer to Transfer16 |
|
@facchinm @pillo79 - Have you tried out this updated fix? Did it properly switch between 8 bit and 16 bit mode? The reason I ask, was I was doing something earlier, but it was not switching modes at the lower levels. That Will try a simple check at least on one board with Logic Analyzer EDIT:
|
libraries/SPI/SPI.cpp
Outdated
| }; | ||
|
|
||
| return spi_transceive(spi_dev, config, &tx_buf_set, &rx_buf_set); | ||
| config.operation = mode | flags; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| config.operation = mode | flags; | |
| config.operation = (config.operation & ~SPI_WORD_SIZE_MASK) | flags; |
libraries/SPI/SPI.cpp
Outdated
|
|
||
| void arduino::ZephyrSPI::beginTransaction(SPISettings settings) { | ||
| uint32_t mode = 0; | ||
| mode = SPI_HOLD_ON_CS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't really fix the issue as discussed. In any case, it should Never be set unconditionally, what if causes an issue with some random SPI device? This should be added to the API and passed in settings.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion SPI_HOLD_ON_CS should be the default way of working, and this is how SPI works with other Arduino cores.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about endTransaction. Okay then. It's weird though that I don't see CS toggling in the first capture, maybe not enough delay? Also, seems the 16bit transfer is swapped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is not an HW CS is a GPIO. Yes it looks swapped, I've used MSBFIRST flag; let me doublecheck.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've used
MSBFIRSTflag; let me doublecheck.
just ignore this, it changes the bit order so it is unrelated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is not an HW CS is a GPIO.
I know. The GPIO CS delay is also controllable.
Yes it looks swapped
If it matches mbed core, an others, then it's probably fine, I guess.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See _spi_context_cs_control in spi_context.h.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
Not sure this SPI issue is pertinent here but looking at your traces it looks like what I was seeing when I was trying to get a Arducam SPI camera working with the Arduino Q: https://forum.arduino.cc/t/spi-strange-behavior-using-begin-end-transaction/1420028 When using SPI.beginTransaction and SPI.endtranasction for transerring data in a bus_read and bus_write function the SPI traces looked more like it was operating in Mode2. (ref: https://www.analog.com/en/resources/analog-dialogue/articles/introduction-to-spi-interface.html), Cant see the clock in the traces above. The only way I was able to retain Mode0 was to call it once in setup and tell the library not to use transactions for the transfers. EDIT: Note tried this along time ago on the R4 using the mbed core with no issue |
|
@iabdalkader @facchinm @pillo79 @mjs513 - Not sure if many of you have looked at my Forum thread: But I have code that does fillScreens (or fillRect of whole screen) of an ST7796 display using SPI, and trying several different ways to do it. Without these changes timings were: (UNO Q) - comments on what each line is: Note: 2nd number per line was one that i write out an image 120x160 to the display a few different ways. Note: I have More details up on the thread. With todays SPI changes I see (two iterations) Maybe slight improvements here in some cases, others, more or less not. My guess is that we may need to look more at the underlying zephyr setup to speed things up. Also changing of the API... You probably need to do it at the HardwareSPI (API) level, as probably most Also CS pins - I believe most if not all implementations at the Arduino layer assume that the CS pins are under software |
This is going to be important if you want to you use multiple SPI devices on the same bus. |
Sorry, I misunderstood. I thought that this PR was in response to my Issue, that there are large gaps in time between outputs and trying to reduce that and improve on the throughput. I understand that there are some issues with SPI on some devices, where for example the clock signal may end stay in a strange state at the end of a transfer, which confuses some devices. Which I personally have not tried to diagnose, but my gut was I know on some other SPI implementations, such as on a Teensy, the endTransaction may not do much in most cases. What I meant to do at some point was to potentially print out all of the SPI registers before and after the call to see Anyway maybe this PR should be renamed? |
|
@pennam With that said I just tested a BME280 with the Adafruit BME280 library and yest its reading transfers however its wrong: Note had to set CPOL = 1 otherwise I get settings mismatches. EDIT: when you tested the BMP388 what library did you use and are you getting data from the sensor |
Ditto |
|
@KurtE @mjs513 my fault, I forgot you issue is referenced in this PR description. The whole story about this, between me @facchinm and @pillo79, started because we were not able to make SPI work with BMP sensor. I will remove the reference and rename the PR. @mjs513 I've used a BMP388 sensor with Adafruit BMP3XX Library and yes I'm getting data from the sensor. |







Adding
SPI_HOLD_ON_CSensures clock and data lines are not released until endOfTransaction()