Skip to content
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

STM32duino and SdFat #454

Open
JFBow opened this issue Nov 19, 2023 · 14 comments · May be fixed by #461
Open

STM32duino and SdFat #454

JFBow opened this issue Nov 19, 2023 · 14 comments · May be fixed by #461

Comments

@JFBow
Copy link

JFBow commented Nov 19, 2023

Hello Greiman,
I used, under IDE Arduino 2.2.1, STM32duino 2.6.0 and SdFat 2.2.2 : perfect, it worked perfectly.
Since I upgraded from STM32duino 2.6.0 to 2.7.0, it generates errors, here they are:

c:\Users\JF\Documents\Arduino\libraries\SdFat\src\SpiDriver\SdSpiSTM32Core.cpp: In member function 'void SdSpiArduinoDriver::send(const uint8_t*, size_t)':
c:\Users\JF\Documents\Arduino\libraries\SdFat\src\SpiDriver\SdSpiSTM32Core.cpp:63:18: error: no matching function for call to 'SPIClass::transfer(uint8_t*, uint8_t [512], size_t&)'
   63 |   m_spi->transfer(const_cast<uint8_t*>(buf), rxBuf, count);
      |   ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from c:\Users\JF\Documents\Arduino\libraries\SdFat\src\SpiDriver\SdSpiDriver.h:90,
                 from c:\Users\JF\Documents\Arduino\libraries\SdFat\src\SpiDriver\SdSpiSTM32Core.cpp:26:
C:\Users\JF\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.0\libraries\SPI\src/SPI.h:202:21: note: candidate: 'virtual uint8_t SPIClass::transfer(uint8_t)'
  202 |     virtual uint8_t transfer(uint8_t _data);
      |                     ^~~~~~~~
C:\Users\JF\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.0\libraries\SPI\src/SPI.h:202:21: note:   candidate expects 1 argument, 3 provided
C:\Users\JF\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.0\libraries\SPI\src/SPI.h:204:18: note: candidate: 'virtual void SPIClass::transfer(void*, size_t)'
  204 |     virtual void transfer(void *buf, size_t count);
      |                  ^~~~~~~~
C:\Users\JF\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.0\libraries\SPI\src/SPI.h:204:18: note:   candidate expects 2 arguments, 3 provided

exit status 1

Compilation error: exit status 1

Is there a solution by keeping the STM32duino 2.7.0 version ?

@greiman
Copy link
Owner

greiman commented Nov 19, 2023

Is there a solution by keeping the STM32duino 2.7.0 version ?

Looks like transfer(txBuf, rxBuf, count) has been removed from SPI in 2.7.0.

Search "transfer" (9 hits in 1 file of 1 searched)
C:\Users\Bill\AppData\Local\Arduino15\packages\STMicroelectronics\hardware\stm32\2.7.0\libraries\SPI\src\SPI.h (9 hits)
Line 44: // Defines a default timeout delay in milliseconds for the SPI transfer
Line 202: virtual uint8_t transfer(uint8_t _data);
Line 203: virtual uint16_t transfer16(uint16_t _data);
Line 204: virtual void transfer(void *buf, size_t count);
Line 247: byte transfer(uint8_t _data);
Line 248: uint16_t transfer16(uint16_t _data);
Line 249: void transfer(void *_buf, size_t _count);
Line 253: using SPIClass::transfer;
Line 254: using SPIClass::transfer16;

You could try USE_SPI_ARRAY_TRANSFER set to one but I looked at the 2.7.0 version of transfer(buf, count) and it looks like it won't help.

I can't believe STMicroelectronics not providing fast DMA SPI for STM32 on Arduino.

For a while I tried to use STM32Cube but then you give up all the Arduino libraries. I have done projects with ChibiOS, it is a great RTOS but you have to port Arduino libraries.

I currently use Teensy 4.1 and RP2040 boards. There is great support for both.

@JFBow
Copy link
Author

JFBow commented Nov 20, 2023

Thank you for your reply.
I contacted STM32duino, here is their response : 2.7.0 contains a clean up of the SPI interface to exactly match the Arduino API. The SdFat library must therefore be updated.

Can I quote you on the provision of fast SPI DMA by STMicroelectronics ?

@greiman
Copy link
Owner

greiman commented Nov 20, 2023

I will remove the custom STM32 code.

For now use the standard Arduino API by editing SdFatConfig.h and change this.
#define SPI_DRIVER_SELECT 1 // << was zero

Can I quote you on the provision of fast SPI DMA by STMicroelectronics ?

Yes. Bet they will hear from other users with apps that need fast SPI.

STM32 is now slower than an UNO R3

Uno R3:

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
689.18,760,728,736
689.18,760,728,736

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
663.75,776,760,765
663.75,776,760,765

STM32 Nucleo L476RG

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
528.65,983,965,966
528.60,983,965,967

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
519.59,995,982,983
519.59,995,982,983

@greiman
Copy link
Owner

greiman commented Nov 20, 2023

You can do better by using this in SdFatConfig.h

#define SPI_DRIVER_SELECT 1
...
#define USE_SPI_ARRAY_TRANSFER 1

STM32 Nucleo L476RG

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1101.08,480,462,463
1100.84,480,462,463

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1095.05,478,465,465
1094.57,477,465,466

Please don't close this since I don't want to change SdFat for a while since I will break all apps using other versions of the STM32 board package before 2.7.0.

I may just modify the STM32 code and keep a custom driver using transfer(buf, count).

Still the transfer(buf, count) API can be much faster with DMA.

@greiman
Copy link
Owner

greiman commented Nov 20, 2023

Here is Teensy 4.1 using DMA SPI with:

#define SPI_DRIVER_SELECT 1
...
#define USE_SPI_ARRAY_TRANSFER 1

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5175.98,1221,98,98
5186.72,110,98,98

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
5181.35,107,98,98
5213.76,106,98,98

So even with the standard Arduino SPI API you can go fast.

Teensy 4.1 also has 4-bit SDIO:

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
21929.82,48,22,22
21645.02,414,22,23

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
22727.27,167,22,22
22624.43,166,22,22

All of these test used 512 byte read/write size.

@fpistm
Copy link

fpistm commented Nov 21, 2023

Hi,
I will provide a PR which will be able to support all core version.
About DMA, I know. Time is always the missing ingredient. Anyway, any contribution are welcome :)

@greiman
Copy link
Owner

greiman commented Nov 21, 2023

@fpistm
Why should I waste time on STM32?

Here is a logic analyzer trace of transfer(buf, count) 40 MHz clock. almost 600 ns dead time between bytes.

Screenshot 2023-11-21 072501

SPI transfer rate is about 1.27 MB/sec - DMA should be 5 MB/sec.

Whats really sad is SDIO support for STM32. STM32Cube has the wrong approach to SDIO.

I did a PIO SDIO for the RP2040 chip which costs $0.75 in quantity or $4 for a Pi Pico board.

I get over 20 times faster write on RP2040 than the 1100 KB/sec I get on STM32.

@fpistm
Copy link

fpistm commented Nov 21, 2023

When I said "any contribution are welcome". I talk generally. This does not mean you should implement the SPI DMA support. :)

@greiman
Copy link
Owner

greiman commented Nov 21, 2023

When I said "any contribution are welcome". I talk generally. This does not mean you should implement the SPI DMA support. :)

I meant fix SdFat when you break the API.

Why not have transfer(txBuf, rxBuf, count). Arduino won't add it to their "standard" API but most other popular board packages have it.

transfer(buf, count) trashes buf so if you want to just send data you need to do a memcpy.

@fpistm
Copy link

fpistm commented Nov 21, 2023

That's the point, to be or not to be fully Arduino Compatible. 🤔
I will think to bring back this API including the const 😉
FYI, I will release in the coming days a 2.7.1 version with some fixes and hope including way to fix this issue (with or without fix in SdFat).

@greiman
Copy link
Owner

greiman commented Nov 21, 2023

I will think to bring back this API including the const

That would be great.

Some versions of the the transfer(txBuf, rxBuf, count) treat a null pointer for txBuf as send 0XFF and a null pointer for rxBuf as discard receive data.

When a SPI device is full duplex like a SD card in SPI mode you can't send junk if you only want receive data.

Many board support packages now have a API like this. myFunction is only used if DMA is supported.

SPI.transfer(tx_buffer, rx_buffer, length, myFunction);

tx_buffer: array of Tx bytes that is filled by the user before starting the SPI transfer. If NULL, default dummy 0xFF bytes will be clocked out.

rx_buffer: array of Rx bytes that will be filled by the slave during the SPI transfer. If NULL, the received data will be discarded.

length: number of data bytes that are to be transferred

myFunction: user specified function callback to be called after completion of the SPI DMA transfer. It takes no argument and returns nothing, e.g.: void myHandler(). Can be NULL if not using a callback.

NOTE: tx_buffer and rx_buffer sizes MUST be identical (of size length)

@fpistm
Copy link

fpistm commented Nov 23, 2023

Hi @greiman
could you file an issue to request to add this API, please?
Thanks in advance.

@JFBow
Copy link
Author

JFBow commented Nov 24, 2023

Good morning,
thank you very much to both of you for your discussions, I hope that this will move forward in the right direction and also a version 2.7.1 !
I lost the usb of my blackpill so I can't test your suggestions now.
I will find and fix the problem and get back to you.
THANKS.

fpistm added a commit to fpistm/SdFat that referenced this issue Dec 20, 2023
Fixes greiman#454.

Signed-off-by: Frederic Pillon <frederic.pillon@st.com>
@fpistm fpistm linked a pull request Dec 20, 2023 that will close this issue
@JFBow
Copy link
Author

JFBow commented Dec 21, 2023

Good morning,
thank you, I was able to test version 2.7.1 of stm32duino with SdFat, it works without modifying my code, as with version 2.6.0
Thanks again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants