Teensy 3.0 as SPI Slave

Status
Not open for further replies.

ebrady

New member
Could someone point me to an example of how to program Teensy 3.0 as an SPI Slave? I am a little confused at the moment.

Thanks,
Ed
 
Here's where I'm at with it, and begging for help from some Jedi Master out there:

From my research, doing SPI slave mode should be pretty easy.
1) Configure the MCR register for slave mode, write MCR = 0x00000000.
2) Configure the CTAR0_SLAVE register for the correct frame size, clock polarity, and clock phase (same as the master uses).
3) Clock in data to the SIN pin.
4) Use the RXCTR and the POPR register to grab the data from the RX FIFO registers.

But I can't get data to clock in!

According to the datasheet (MK20 Datasheet):
1) In Slave Mode "The SCK signal and the PCS[0]/SS signals are configured as inputs and driven by an SPI bus master."
So...once in slave mode, no further configuration of these pins is necessary?

2) "SPI data is added to the RX FIFO at the completion of a transfer when the received data in the shift register is transferred into the RX FIFO...The RX FIFO is filled with the received SPI data from the shift register. While the RX FIFO is not full, SPI frames from the shift register are transferred to the RX FIFO. Every time an SPI frame is transferred to the RX FIFO, the RX FIFO Counter is incremented by one."
I can't get my RXCTR to increment, meaning that I'm not getting anything to shift into the RX FIFO registers.

Maybe I am mis-reading something somewhere. I have even tried re-assigning CLK pin 13 to CLK pin 14 (I thought maybe there was hardware interference with the LED).
I feel like my spi module isn't receiving clocks.

Here is the sketch I'm running...there is a serial print of MCR, CTAR0_SLAVE, SR, RSER, and the RXFR0 registers, and also an indicator showing that I am receiving clock cycles.
Code:
uint32_t ctar0, ctar1, ctar_slave, mcr;
bool serialPrint_ONS=LOW;
long clkCTU=0;
unsigned long serialTMR=0;

void setup(){
  
  Serial.begin(57600);
  
  SPCR =0x40; // |= _BV(SPE);  //From Arduino, dosn't work without it??
  SPI0_MCR         = 0x01000400;
  SPI0_RSER        = 0x00000000;
  SPI0_CTAR0_SLAVE = 0x38000000; //0x11000000;
  
  //take clock off pin 13
  CORE_PIN13_CONFIG = PORT_PCR_MUX(1);
  //put clock on pun 14
  CORE_PIN14_CONFIG = PORT_PCR_DSE | PORT_PCR_MUX(2);
  
  pinMode(SS, INPUT);      //Pin 10
  pinMode(MISO, INPUT);    //Pin 12
  pinMode(14, INPUT);      //Clock
}

void loop(){
  if (digitalReadFast(14)){
    clkCTU++;}

  if (serialPrint_ONS == LOW){
    serialTMR = millis();
    serialPrint_ONS = HIGH;}
  if(millis() - serialTMR > 1000){ 
    
    //These numbers show what bit you are looking at
    Serial.println("                      33222222222211111111110000000000");
    Serial.println("                      10987654321098765432109876543210");
    Serial.println("                      --------------------------------");
    
    //Zeros are uses for placeholders
    Serial.print("SPIO_MCR:             0000000");
    Serial.println(SPI0_MCR,BIN);
    Serial.print("SPIO_CTAR0_SLAVE:     00");
    Serial.println(SPI0_CTAR0_SLAVE,BIN);
    Serial.print("SPI_SR:               0");
    Serial.println(SPI0_SR,BIN);
    Serial.print("SPI_RSER:             0000000000000000000000000000000");
    Serial.println(SPI0_RSER,BIN);
    Serial.println("                      --------------------------------");
    Serial.print("SPI_RXFR              ");
    Serial.println(SPI0_RXFR0,BIN);
    Serial.print("Clock (not accurate)  ");
    Serial.println(clkCTU);
    Serial.println();
    Serial.println();
    Serial.println();
    serialPrint_ONS = LOW;
  }
}
 
Last edited:
I'm receiving SPI data on my slave. I have a lot of cleanup to do with the logic, but I'm getting data.
Thanks CMASON & PLOVEDAY...I'm using big chunks of code that you two did before me.
I'll try post something more significant in the next couple of days.
 
I have a functioning teensy 3.0 spi master/slave set. Need to run some speed tests, I'll post everything tomorrow after work.
 
Here's what I have so far. The slave is interrupt based, but it works at 24Mhz (I don't have an oscope so I can't verify that I'm clocking 24Mhz). It works for 8 & 16 bits.
The examples serial.print several transfer statistics.

@ 24MHz, On 16 bit transfers, 1000 transfers per packet, looping 500 times, I get 1.25 MBpS (my FOR loop is probably slowing it down a lot).

The Slave is using the clock input on pin14, Master clock is pin13.
ChipSelect pin is 10 on both Master and Slave.
DataOut is Pin11 on the master.
DataIn is pin12 on the slave.


I have not set it up yet for slave to master transfers, so it is currently one-way master to slave. I intend to post some updates, make the library more universal, use other CTAR's, CS pins, and enable slave to master transfers. Please post or message any questions or comments. And feel free to suggest changes.

Teensy 3.0 Master & Slave (on GitHub)
 
Last edited:
Good work ... but the github link doesn't work for me ???
... though it is possible github is having problems.... i'll try again later
 
yep, github is working now. code looks good.

Just curious why use pin 14 for clk and not 13? (I don't really understand the gray-ed out pin names on the "pin assignment" image ...)
thanks
 
yes, there is a "wait" function being used after every data TX, it can be removed for even faster rates. When I removed it, I couldn't communicate with my SPI digi potentiometer, so I guess it depends on your application.
I would think that at 24mhz, if the SPI_wait() was removed, the master might over-run the slave. There are only 4 registers in the slave RX buffer, so if you don't call the interrupt fast enough, you're gonna start skipping data.
The RX interrupt could probably be streamlined to get a little more speed out of it.

I know nothing about DMA, but I'm guessing we would get much higher speeds if we used DMA instead of the interrupt. I don't know if I have the energy or patience to attempt it.

What Logic Analyzer do you use? I want to get one.
 
Last edited:
I have the Saleae Logic16. I use Linux as my primary system, and I would absolutely NOT recommend Saleae to anyone who uses Linux. Their software crashes frequently, often causing total data loss.

I saw them at Maker Faire and mentioned this. Apparently at that very moment, they were trying to run it on one of their computers which someone had installed Linux upon. It was crashing. They mentioned a new developer was hired and hopefully improved software will be out by the end of the summer. I'm hopeful, because it does seem like a nice product (and I did use it once, but it took many tries to get a capture saved to a text file which I then anayzed by writing Perl scripts).

Saleae probably runs much better on Windows, maybe Mac too? But if you use Linux, the software is so buggy it's pretty much unusable.
 
Saleae probably runs much better on Windows, maybe Mac too? But if you use Linux, the software is so buggy it's pretty much unusable.

I have had same experience with Linux, and I run logic16 on old XP laptop. Saleae said they are working on fixing the linux version, but I haven't tried it with Linux recently ...
 
Here's what I have so far. The slave is interrupt based, but it works at 24Mhz (I don't have an oscope so I can't verify that I'm clocking 24Mhz). It works for 8 & 16 bits.
The examples serial.print several transfer statistics.

@ 24MHz, On 16 bit transfers, 1000 transfers per packet, looping 500 times, I get 1.25 MBpS (my FOR loop is probably slowing it down a lot).

The Slave is using the clock input on pin14, Master clock is pin13.
ChipSelect pin is 10 on both Master and Slave.
DataOut is Pin11 on the master.
DataIn is pin12 on the slave.


I have not set it up yet for slave to master transfers, so it is currently one-way master to slave. I intend to post some updates, make the library more universal, use other CTAR's, CS pins, and enable slave to master transfers. Please post or message any questions or comments. And feel free to suggest changes.

Teensy3.0 SPI Master & Slave Set (on GitHub)

Nice work,

btw. did I see that right the slave can only receive messages and not answer?
 
yes. I haven't checked it yet, but you should be able to use PUSHR_SLAVE to queue data to be shifted out. And the master can use POPR to get it.
 
What Logic Analyzer do you use? I want to get one.

Just a comment on this. I saw this list someone had compiled a while back about Logic Analyzers under $500:
Logic Analyzers under $500

I have a Zeroplus and I highly recommend it (I have a 16128+, but IMO the 16128 is at the best price/performance point). The software is Windows only, unfortunately no idea if it would run under Wine or such. I think for analyzers the software is really almost more important than the hardware. I would recommend running any demos if they exist.

The Zeroplus analyzers can decode a large number of protocols, nothing else even comes close (and they usually have a 30 free protocol offer). Only caveat I've found is that it doesn't effectively trigger on an arbitrary software protocol condition. This is because protocols are decoded on the PC and it doesn't stream continuously (reason for that is because it can capture at 200MHz). In the program software triggers exist, but I haven't quite figured out how to use them effectively. What it requires is a hardware trigger (eg. for I2C something like SDA falling-edge while SCL high), but once triggered the protocol decoders kick in and you can search for and jump around to specific protocol patterns. I had some captures shown in this thread if your curious what it looks like.
 
I have uploaded a more complete library for using SPI master & slave.

This lib lets you:
1) send data from the slave back to the master
2) use any SPI pin, including the alternate pins (gray on the pinout chart)
3) easily begin SPI and setup custom CTAR's
4) see statistical data from your sending/receiving (SPI registers, mbps, uSec per byte, ect.)
5) extensive readme.txt explaining the purpose & use of all functions

Teensy 3.0 Master & Slave (on GitHub)
 
Last edited:
I have. It works. I have updated the library some, and I've learned some new tricks with it. Let me know if you need any assistance.
 
Status
Not open for further replies.
Back
Top