SPI Slave

Status
Not open for further replies.

brtaylor

Well-known member
I'm trying to transfer data very quickly between 2 Teensy 3.6's. I'm trying to use SPI, since that should be the fastest method. I'm using the following config for my SPI master Teensy 3.6:
* CS: 10
* MOSI: 11
* MISO: 12
* SCK: 13

I'm using the following config for my SPI slave Teensy 3.6:
* CS: 2
* MOSI: 11
* MISO: 12
* SCK: 14

This is my master code:
Code:
#include "SPI.h"

void setup()
{
  Serial.begin(115200);
  delay(5000);
  pinMode(10, OUTPUT);
  SPI.begin();
  SPI.beginTransaction(SPISettings(24000000, MSBFIRST, SPI_MODE0));
  digitalWriteFast(10, LOW);
  SPI.transfer16(10);
  digitalWriteFast(10, HIGH);
  SPI.endTransaction();
}

void loop()
{
}

And my slave code:
Code:
#include "SPI.h"

void spi0_isr(void) {
  Serial.println(SPI0_POPR);
  SPI0_SR |= SPI_SR_RFDF;
}

void setup()
{
  Serial.begin(115200);
  SIM_SCGC6 |= SIM_SCGC6_SPI0; // enable slave clock
  SPI0_MCR |= SPI_MCR_HALT | SPI_MCR_MDIS; // stop
  SPI0_CTAR0_SLAVE = SPI_CTAR_FMSZ(15) & SPI0_CTAR0_SLAVE & (~(SPI_CTAR_CPOL | SPI_CTAR_CPHA) | 0x00 << 25);
  SPI0_RSER = 0x00020000;
  CORE_PIN14_CONFIG = PORT_PCR_MUX(2);
  CORE_PIN11_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
  CORE_PIN12_CONFIG = PORT_PCR_MUX(2);
  CORE_PIN2_CONFIG =  PORT_PCR_PS | PORT_PCR_MUX(2); // this uses pin 2 for the CS so Serial2 can be used instead.
  SPI0_MCR &= ~SPI_MCR_HALT & ~SPI_MCR_MDIS; // start
  NVIC_ENABLE_IRQ(IRQ_SPI0); // enable CS IRQ
}

void loop()
{

}

I took gratuitously from this thread: https://forum.pjrc.com/threads/48749-I2C-SPI-ESP-webSockets-controller-for-teensy

My issues is that I would expect to see the slave print the number 10. Instead, I'm seeing 65535. Hoping that someone here will see my mistake.

Cheers!
Brian
 
Hey Brian.
Never could get spislave mode to work reliably. You might me better off using tonton81's spi_mst library to transfer data.
 
or take a peek at TSPISlave library that supports SPI slave mode among LC and T3.x for all available SPI ports (SPI,SPI1,SPI2)

also if you are getting 65535, make sure your MOSI and MISO lines are not reversed and make sure theyre common ground
 
or take a peek at TSPISlave library that supports SPI slave mode among LC and T3.x for all available SPI ports (SPI,SPI1,SPI2)

also if you are getting 65535, make sure your MOSI and MISO lines are not reversed and make sure theyre common ground

Oh wow, TSPISlave looks exactly like what I want. Going to give that a try, cheers!
 
the only issue i would correct of that library but didnt have time yet to do is instead of declaring a void isr function of the core was to overwrite the existing vector with a new isr function, this is because if i would change the vector to a new function, we can #include <SPI.h> after, otherwise the SPI.h complains about the spi0_isr already declared...

vector modification would allow both mastar and slave capability at same time
library in its current state can be SPI slave only until thats done
 
Last edited:
Sorry, I should be more specific. I'm trying to create what might be a similar device to what brtaylor is doing. I'm using I2C to tell the Teensy 3.6 *what* I want to read from the SPI port; the problem is...actually reading it. This will be 8-bit data (rather a lot of it) that I'm sending. If single 8-bit transfers aren't available, I can use structs or unions (or just bit shifting) to do the dirtywork of storing the data on the slave. Same for decoding on the master. Or is there another library I should be looking at?
 
Has anyone managed to get any of the SPI slave code, from any of the libraries, to work? I've downloaded tonton's library, and tested it; it hangs immediately when data reception begins. My setup is really, really basic; two Teensy 3.6-es, connected as specified, using SPI0.
Connections are CS0 <-> CS0, MOSI0 <-> MOSI0, MISO0 <-> MISO0, SCK0 <-> SCK0 (on a 3.6, that's 10, 11, 12, and 13, respectively).

Master code is:
Code:
#include "SPI.h"

void setup()
{
  Serial.begin(115200);
  delay(5000);
  pinMode(10, OUTPUT);
  SPI.begin();
}

void loop()
{
  SPI.beginTransaction(SPISettings(16000000, MSBFIRST, SPI_MODE0));
  digitalWriteFast(10, LOW);
  Serial.println(SPI.transfer16(10));
  digitalWriteFast(10, HIGH);
  SPI.endTransaction();
  delay(500);
}

Slave code is:
Code:
#include "TSPISlave.h"

uint8_t miso = 12;
uint8_t mosi = 11;
uint8_t sck = 13;
uint8_t cs = 10;
uint8_t spimode = 16;

TSPISlave mySPI = TSPISlave(SPI, miso, mosi, sck, cs, spimode);

void setup() {
  Serial.begin(115200);
  mySPI.onReceive(myFunc);
}

void loop() {
  delay(1000);
  Serial.println(millis());
}

void myFunc() {
  Serial.println("START: ");
  uint16_t arr[2] = { 0x1111, 0x2222 };
  uint8_t i = 0;
  while ( mySPI.active() ) {
    if (mySPI.available()) {
      mySPI.pushr(arr[i++]);
      Serial.print("VALUE: 0x");
      Serial.println(mySPI.popr(), HEX);
    }
  }
  Serial.println("END");
}

The output from the slave is clearly incorrect; it's too long to copy, but consists of this (after several seconds of operation):
START:
END
START:
END
START:
END
START:
END
START:
E18300


And the output from the master is:
65535
65535
65535
65535
65535
65535
65535
65535
65535

You'd think after three years and change I'd know how to deal with this, but this one is definitely over my head. And seems to be quite the rare bird, too; reading high-speed data from an SPI slave is something that not many people seem to need to do. But in this case, I need to be able to read rather a lot of data from another Teensy 3.6. I2C and UART are out of the question; it's a LOT of data and needs to be transferred quickly.

I know there are folks out there who have the "well, if you don't understand it, you don't need to use it" mind-set; I've encountered four (on other sites' forums) already this morning; and the "why don't you use a Raspberry Pi for that much data" folks as well. And the "Why aren't you using an Arduino, since it's better understood" folks. Please understand that my persistence is not mere stubbornness; I understand my technical problem, I really do, and I know how I want to solve it.
 
change spimode to “8” instead of 16 for 8 bit transfers, if your getting 65535 verify your miso is not swapped with mosi, you can always swap them to see if it works or use a scope. To so a simple test, send a spi byte every second from a master device amd verify the slave connections/code until you start seeing data
 
if you want to transfer arrays you could also try out SPI_MSTransfer, where it has peripheral controls and callback payload transfers in both directions

This library was developed for high speed data transfers between one or more teensies

use the final.zip file in the repo if you go that route, it was the last updated edition
 
tonton:

I decided to give SPI_MSTransfer a shot. I commented at the end of your development thread. The demos aren't working (although they are compiling). I tried crossing/uncrossing the streams, and moving CS pins around; no luck. I also replaced the library files with the ones from the .zip file, still no luck.

I'm trying to build a small peripheral, based on a Teensy 3.6. The Teensy has some sensors on it; I will tell it which sensor I want data for by writing a command over I2C. That part is working; there's tons of code out there for that; I can even get back the number of bytes I want to transfer back from the slave to the master over SPI. The data I'm sending back will all be 8-bit data, no 16-bit data.

I have to say, though...your code is really pretty advanced, and I'm having a difficult time reading it, though it's starting to make (a little) sense. But the SPI stuff isn't working at all, or doesn't seem to be. I'm guessing that you and defragster were using SPI to get GPS data back from another Teensy with a GPS sensor unit on it, but I'm having extreme difficulty adapting your example.
 
I'm trying to set up a SPI bus between 2 teensy 3.6 too. But I am unable to start any function on my slave to reply something when the master is asking. I tried to use the code from ariesboy571 but I didn't have any "START/END" printing from the slave (only the time from millis() in the loop). So I assume myFunction() is never called but I used the same code ase you...
One of my 2 teensy is warming up a lot too.. I hope it isn't broken but I still have the feedback from Serial.println() so I think it's still working.
Any guess on any solution to call a function on my slave when the master transfer some byte ?
 
sorry i didnt have much time lately in the process of changing work locations and hours, and snow, i need a few more days to stabilize :)
 
getting ready for work soon but this morning I decided to setup a T3.5 and a T3.6 unit for testing SPI_MST

Here is the last sketch that has worked on latest build of SPI_MST:
https://forum.pjrc.com/threads/50008-Project-SPI_MSTransfer?p=179524&viewfull=1#post179524

I must admit my code is not easy to look at, but I was still learning to code ;)

As per above last code, I modified it for my setup, you can download it here:
Code:
[ATTACH]16014._xfImport[/ATTACH]

On the T3.5 (Master) ------> T3.6 (Slave)

GND (next to pin 0) ---------> GND (next to pin 0)
^-- *** DO NOT RELY ON USB COMMON GROUND ***

pin 10 -----------> pin 2
pin 11 -----------> pin 11
pin 12 -----------> pin 12
pin 14 -----------> pin 14


As far as that goes, thats whats running as we speak now, validate it on your setup and if it doesn't work check the cabling. Also be aware the slave starts accepting traffic only after 5 seconds of boot, so just wait for it to kick in.
Once you have it working you can strip out the rest of the uneeded bloat in the example thats not useful to you and you'll find the callback there where you can send data between teensies at SPI speeds :)

Video: https://www.youtube.com/watch?v=VKtNqssDjS4
 
Last edited:
Status
Not open for further replies.
Back
Top