Closed hathach closed 4 years ago
Been spending some time with this today and have not found the cause yet. I did find and fix an obscure bug in the SPI library (in ArduinoCore-samd) but that has no impact here. Need to set this aside for the time being due to other projects.
Thanks @PaintYourDragon , whenever you got the time. Let's me know if you need my help with testing or other part of code with SPIFlash :)
PS: I have no idea, but may this SPI DMA related PR to SAMD core could help https://github.com/adafruit/ArduinoCore-samd/pull/234
Think it’s fixed. Change pushed to ArduinoCore-samd main branch (changes are in SPI library). Tested on Feather M0 and M4, including both default settings and overclock + dragon optimization on M4…plus Grand Central running OV7670 cameratest (to TFT shield).
Grateful for other eyes to test this, especially with other code that uses SPI DMA (GFX, SD cards, etc.). Holding off on closing the issue until others can confirm it’s solid.
BONUS: large SPI transfers can be fully non-blocking now. Previously large transfers were “mostly-blocking.” This will help things like the camera and possibly NES emulator, anything that writes full screens worth of data.
Bug was not where expected. It only manifested in flash_speedtest because of the particular order in which it called SPI.transfer() with writes followed by reads, apparently a rare sequence of events. Should handle everything really well now.
@PaintYourDragon superb !!! I have just run the test and verified that the issue is fixed with latest samd core. Read speed is almost got doubled using DMA.
without DMA (speed in KB/s)
- M0 FRAM: read (noDMA, 12Mhz) = 490
- M0 GD25Q16C: read (noDMA, 24Mhz) = 570
- M4 FRAM: read (noDMA, 24Mhz) = 1300
with DMA (speed in KB/s)
- M0 FRAM: read (DMA, 12Mhz) = 1200
- M0 GD25Q16C: read (DMA, 24Mhz) = 1200
- M4 FRAM: read (DMA, 24Mhz) = 2950
I really like the enhancement with non-blocking, this can be used to improve the SPIFlash speed even more. The read won't get much usage since most of the time the application want to use the read data immediately after the call. For WRITE, SPIFlash need to have some guard to prevent application to overwrite to the same caching buffer (before the previous DMA complete). I will try to look at this later on if user complains about the performance, since this may need quite a bit of testing since it involve racing condition.
SPI.waitForTransfer() will wait for a non-blocking transfer to complete…call this before ANY other action on the same SPI bus. Returns immediately if transfer is already finished.
SPI.waitForTransfer() will wait for a non-blocking transfer to complete…call this before ANY other action on the same SPI bus. Returns immediately if transfer is already finished.
Thank for the tip, will try it out later on. Kind of satisfied by the result now and get bored with testing with SPIFlash :stuck_out_tongue: :stuck_out_tongue:
it is solid enough to be closed now.
Describe the bug When improving spi flash accessing speed, I find out that M0 can perform SPI DMA write without issue, but can only carry out exactly 1 DMA Read (still has issue).
Code that enable DMA write https://github.com/adafruit/Adafruit_SPIFlash/blob/master/src/spi/Adafruit_FlashTransport_SPI.cpp#L147
Code that eanble DMA read https://github.com/adafruit/Adafruit_SPIFlash/blob/master/src/spi/Adafruit_FlashTransport_SPI.cpp#L121
Set up (mandatory)
To Reproduce Steps to reproduce the behavior:
#elif
to enable SPI DMA read https://github.com/adafruit/Adafruit_SPIFlash/blob/master/src/spi/Adafruit_FlashTransport_SPI.cpp#L119 Code should beflash_speedtest
exampleContext the example sketch will
Then it does the second pass with 0x55 pattern. The sketch complete successfully when DMA Read is not used, and failed when it does. In both cases DMA Write is eanbled. Below is the output log.
By my observation, the DMA Read seems to have an error, it does read several hundreds byte before failing. Afterwards, it doesn't seem to be able to execute another Read ( second pass is all zeroes).
@PaintYourDragon @ladyada Since you are expert on SPI DMA on SAMD, would you mind taking a look at the issue. It is probably some condition is not clear, or maybe I didn't understand enough of the DMA API. Thanks in advance.
Serial Log
With DMA Read eanbled
Without DMA Read