Large SPI Transfers on Teensy

Ausplex

Active member
Hi. This is my first use of SPI on a Teensy (and Arduino).

I will be burst transferring 1134 bytes approximately 60 times per second at 2.5MHz.

I'm assuming that if I use SPI.transfer to send 1134 bytes (about 4 milli-seconds) that I'm effectively blocking code execution (apart from interrupt driven stuff) while doing that - i.e. I will be in a for loop while the data is clocked out and after the last SPI.transfer is complete I can continue on with my code execution.

Another way of asking this is apart from the few bytes of hardware FIFO, I assume there is no buffering in the library?

I did find a Teensy DMA SPI library, but not sure if anyone has any other suggestions or recommendations.
https://github.com/crteensy/DmaSpi

thanks
David
 
In many of these cases it would help to know which teensy? If I can assume 3.x, 4 and maybe LC, there are a variety of ways. Also helps to know if your transfer is a TX, or RX or both...

Some are not all that well documented, but...

The slowest way you can do it is by doing something is using the transfer 1 at a time like:

Code:
uint8_t my_buffer[1134];
...
(setup with beginTransaction and selecting CS)
for (uint16_t i = 0; i < sizeof(my_buffer); i++)
    SPI.transfer(my_buffer[i]);
...
Why this is the slowest is for each of these transfers it has to wait for the transfer to fully complete to return the value in that came in over the MISO pin... So FIFO is not good for anything... And there are gaps in the output as the code has to come back to you to get the next character to output.

We do have an ability to transfer a buffer and count...
Code:
SPI.transfer(my_buffer, nullptr, sizeof(my_buffer));
The nullptr is a pointer that can be to a buffer to receive the results, if you want them. Likewise TX buffer could be null and it will send default value (defaults to 0).

This will again wait for the whole thing to complete, but is significantly faster, as it keeps the TX queue full, so there are no gaps in the output. There are a few more tricks it may do depending on which teensy...

Alternatively you can do it using DMA... Yes the DmaSPI can work. Not sure if it was ever updated to T4 processor.

Also SPI library can do it with DMA as well. There is a version of the API, that allows you to use an experimental eventReponder object to be signaled when the transfer completes.

Code:
#include <SPI.h>
#include <EventResponder.h>
EventResponder event;
volatile bool event_happened = false;
void asyncEventResponder(EventResponderRef event_responder)
{
  digitalWriteFast(CS_PIN, HIGH);
  event_happened = true;
}
...
(somewhere probably in setup)
  event.attachImmediate(&asyncEventResponder);

...
(to call...)
  event_happened = false;
  SPI.transfer(my_buffer, nullptr, sizeof(my_buffer), event);
The transfer above will return immediately. When it completes the event object will be signaled. As we setup to be called immediately, the function asyncEventResonder is called, which sets the flag...
Then your can check that flag to know it is done..
 
Thanks Kurt for your reply,

I'm proposing to use a Teensy 3.2, but I have some 3.5's here as well if there is any benefit. I don't need to receive any data for this project.

You mention that "There is a version of the API, that allows you to use an experimental eventReponder object". Is that within the existing Teensy SPI library, is it a library that I need to install ?

I haven't coded an event responder before, but your sample code looks straightforward.
 
By version - I meant that if you are using Teensyduino version that is reasonably up to date (like within the last year or two...)

And that T3.x or T4 is preferable. T3.2 should be fine. T3.5 has some additional capabilities like more memory... But not sure if you need or not.
 
Thanks for the great information. I am looking for one more feature:

SPI on the Teensy has SPI.transfer with the eventResponder and SPI.transfer32 (without event).

Is there a simple way to combine 32 Bit transfer and enabling the event_Responder?

Best regards
 
Back
Top