Understanding SPI on Teensy 3.6

Status
Not open for further replies.
Hello

I dont unterstand how SPI on teensy work.
On Atmel 8bit i fill an register and start Transmission. Then SPI Hardware transfer the Byte in Background.
If finished Code jumps into Interrupt there i fill the next byte in register and transfer ..
during this tranfer i can do other things in code.

On teensy i cant find information about the SPI tranfer behavior.
If i call spi.tranfer method the teensy start the tranfer but whats then ?
stops the code until this is finished ?
And can i use the Tranfer Time to do other things in code ? and How ?
i Have tranfer a lot of data and i need time to preprocess this data

Thanks for Help .
Please answer simple iam not a native english speaker :rolleyes:
 
There are many ways of doing things here...

First off (but I don't recommend as the primary way) - There is code in place for the Teensy to emulate the AVR registers...

Easy way: Using an asynchronous version of SPI.transfer - Prototype in SPI.c - bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
I am not sure how well this is documented yet... But you can setup an event object to call your function either immediate, or next yield or on ms timer...
So you call this transfer and it returns immediately... You can choose to pass in NULL for either txBuffer or RxBuffer and turn it into send only or receive only...

Alternative method, learn the SPI system for the actual chip from the reference manual(s) which can be downloaded from: https://www.pjrc.com/teensy/datasheets.html
An example using this is the ili9341_t3 library which is downloaded as part of the teensyduino install.
 
Last edited:
Ok i know there are SPI registers in the Mk66 to get spi with interrupt control
but iam not the guy who can handle that.
iam using arduino to program on high abstraction layer .. if i can say this

what is the Way the Teensuido Libary handle the SPI ?
does code stops and wait until spi is done ?
 
Note:
If you are using the standard SPI stuff of all of the Arduino boards, like described in the reference docs like: https://www.arduino.cc/en/Reference/SPITransfer

Calls like SPI.transfer(x);
Will wait for the full transfer to complete before they return, this is necessary as it returns the value that was brought in using the MISO pin...

Likewise for the other standard transfers: SPI.transfer(my_buff, count);
This version transfers the count of bytes specified from my_buff. It also overwrites my_buff with the return values... So again it has to wait.

I don't like the buffer version mentioned as it overwrites the buffer passed in. So Teensy and several other implementations have version of this API:
SPI.transfer(tx_buffer, rx_buffer, count);
Where stuff is sent from tx_buffer, and the return values are put into rx_buffer. Note either of these can be NULL... But still synchronous...

As I mentioned in the previous response (now marked in red) we added an Asynchronous SPI.transfer, where we use an event object that is triggered when a transfer completes...
A simple example of this showing two transfers happening at the same time on SPI and SPI1...

Code:
#include <SPI.h>

EventResponder event;
EventResponder event1;

uint8_t buffer0[100];
uint8_t buffer1[100];
volatile bool spi_active = false;
volatile bool spi1_active = false;

void Event_SPI0_Responder(EventResponderRef event_responder) {
  digitalWriteFast(2, HIGH);
  SPI.endTransaction();
  Serial.println("SPI0 ended");
  spi_active = false;
}
void Event_SPI1_Responder(EventResponderRef event_responder) {
  digitalWriteFast(3, HIGH);
  SPI1.endTransaction();
  Serial.println("SPI1 ended");
  spi1_active = false;
}

void setup() {
  while (!Serial && (millis() < 2000)) ;
  Serial.println("Test SPI DMA on SPI and SPI1");

  pinMode(2, OUTPUT);
  digitalWriteFast(2, HIGH);
  SPI.begin();
  event.attachImmediate(&Event_SPI0_Responder);
  for (int i = 0; i < sizeof(buffer0); i++) buffer0[i] = i;

  pinMode(3, OUTPUT);
  digitalWriteFast(3, HIGH);
  SPI1.begin();
  event1.attachImmediate(&Event_SPI1_Responder);
  for (int i = 0; i < sizeof(buffer1); i++) buffer1[i] = sizeof(buffer1) - i;
}

void loop() {
  Serial.println("Start Two SPI transfers");
  spi_active = true;
  SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
  digitalWriteFast(2, LOW);
  SPI.transfer(buffer0, nullptr, sizeof(buffer0), event);

  spi1_active = true;
  SPI1.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
  digitalWriteFast(3, LOW);
  SPI1.transfer(buffer1, nullptr, sizeof(buffer1), event1);

  while (spi_active || spi1_active) ; // wait until both are done
  Serial.println("Both done");
  delay(1000);  // wait a second

}
This one waits for both to complete before returning, but that was just for this simple example...
 
Status
Not open for further replies.
Back
Top