SPISlave_T4

Has anyone had any luck using a master and slave from the same device? i.e. preferably using a teens4.1 SPI as master and SPI1 as slave? or vice versa?
I had it working with two teensy4.1 talking to each other over SPI but struggling to get it working on the same unit.
In this instance I am using SPI1 as the Master but as soon as uncomment
// mySPI.onReceive(myFunc);
// mySPI.begin();
It stops printing out the data being sent by the master

Code:
#include "SPISlave_T4.h"
#include <SPI.h>
#define CS_SLAVE 0
#define CS_MASTER 10
#define DISP_CHANNEL_1 32
#define DISP_RETURN 19
#define SPI_MASTER SPI1
#define DATA 2

SPISlave_T4<&SPI, SPI_16_BITS> mySPI;

void myFunc()
{
  Serial.println("START: ");
  uint8_t arr[] = {3, 2, 8, 3, 10, 11, 33, 13, 14};
  uint8_t i = 0;
  while (mySPI.active())
  {
    if (mySPI.available())
    {
      if (i++ > sizeof(arr))
        i = 0;
      mySPI.pushr(arr[i]);
      Serial.print("VALUE: ");
      Serial.println(mySPI.popr());
    }
  }
  Serial.println("END");
}

void setup()
{
  // Serial
  Serial.begin(115200); // Begin Serial

  // Master SPI
  pinMode(CS_MASTER, OUTPUT);                                              // Set Master Chip Select as Output
  digitalWrite(CS_MASTER, HIGH);                                           // Set Master Chip Select High
  SPI_MASTER.begin();                                                      // Begin Master SPI
  SPI_MASTER.beginTransaction(SPISettings(10000000, MSBFIRST, SPI_MODE0)); // Begin Master SPI Transaction

  // Display Pins
  pinMode(DISP_RETURN, OUTPUT);
  pinMode(DISP_CHANNEL_1, OUTPUT);
  digitalWrite(DISP_RETURN, HIGH);
  digitalWrite(DISP_CHANNEL_1, HIGH);

  while (!Serial)
    ;
  // mySPI.onReceive(myFunc);
  // mySPI.begin();
}

void loop()
{
  digitalWrite(CS_MASTER, LOW);
  for (uint16_t i = 0; i < 50; i++)
    Serial.println(SPI_MASTER.transfer16(i));
  digitalWrite(CS_MASTER, HIGH);
  delay(1000);
}
 
same device? well i would imagine the interrupt being held open with active locked, the loop wouldnt be able to send anything until that's done, i never tested it as a loopback but thats where you would start, by breaking up the function to release back to the loop so it can refire as needed, obviously you'll need to handle a persistant buffer to keep track of the data while the gpio is asserted
 
onRecieve callback confusion

Hello, I have some problems or some confusion how to read the bytes with the callback. I want to do 4 bytes so I first set up 32 bit configuration but now I have changed it to 8 bit and of course send this in 4 bytes. The data is not coming out in order. Based on comments and questions I have seen elsewhere in this forum I feel my experience is similar to what others have experience but I also have to admit I don't perfectly understand what the pushr function does.

In this test I have set a pin high at the beginning and low at the end of the function I attached to onReceive and as you can see it is only raising after 3 bytes have been clocked. This is what I thought was happening but...

TEK00014 - Copy.PNG


Further review shows there appears to be a pattern of 4 in which 3 assertions of the CS line (4 bytes each time) do not trigger the callback. The code for the Teensy4.1 should make it clear where the pin is being raised (green trace)

tek00013(copy).png

Teensy LC - as SPI master NO problems with this function, just here as a reference
Code:
#include <Arduino.h>
#include "SPI.h"

constexpr int32_t READ_INTERVAL_MS   = 5;
constexpr int32_t REPORT_INTERVAL_MS = 500;

constexpr int32_t cs_pin        = 10;
constexpr int32_t spi_clock_pin = 14;

SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);

elapsedMillis report;
elapsedMillis read_spi_slave;

/*
X       11 MOSI confirmed, idles high, is transitioning on the trailing edge of the clock (falling edge)
X       12 MISO PROBLEM: this data is from the other board - the teensy 4.1 SPI SLAVE
X       10 CS confirmed active low a bit under 200us total span (4 bytes and 200000 clock speed)
X       14 CLK  (requires manual change to different pin) idle low, active high  about 8us extra time between each byte
*/


void setup() {
    Serial.begin(115200);
    pinMode(cs_pin, OUTPUT);
    digitalWrite(cs_pin, HIGH);
    SPI.setSCK(spi_clock_pin);
    SPI.begin();
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, HIGH);
}


void loop() {
    //
    static int32_t toggle         = 0;
    static int32_t result         = 0;
    static int32_t test_indicator = 0;
    int8_t adc_values[4];

    if (read_spi_slave > READ_INTERVAL_MS) {
        read_spi_slave = 1;

        SPI.beginTransaction(settingsA);
        digitalWrite(cs_pin, LOW);
        // reading only, so data sent does not matter what these are
        adc_values[0] = SPI.transfer(0xAA);
        adc_values[1] = SPI.transfer(test_indicator & 0xFF);
        adc_values[2] = SPI.transfer(0x55);
        adc_values[3] = SPI.transfer(0x55);
        digitalWrite(cs_pin, HIGH);
        SPI.endTransaction();

        result = adc_values[0] << 8;
        result |= adc_values[1];
        result = result << 8;
        result |= (adc_values[2] & 0x7F);
        result = (result << 8) >> 8;
        // this does not matter yet - byte values are being checked on the oscilloscope
    }

    // DEBUG OUTPUT but at a slower pace
    if (report > REPORT_INTERVAL_MS) {
        report = 1;
        Serial.print(millis());
        Serial.print("\t");
        Serial.println(result, DEC);
        digitalWrite(LED_BUILTIN, toggle);
        toggle = 1 - toggle;
        test_indicator++;
    }
}

teensy 4.1 SPI Slave - something wrong here. NOTE: the data being pushed is just fake, I am including an index number so that I can look on the scope and see if the bytes are the correct ones.

Code:
#include <Arduino.h>
#include "SPISlave_T4.h"
#include "SPI.h"

constexpr int32_t READ_INTERVAL_MS   = 12;
constexpr int32_t REPORT_INTERVAL_MS = 500;
constexpr uint8_t cs_pin_1           = 6;
constexpr uint8_t test_pin           = 2;

int32_t spi_data_n      = 0;
uint8_t spi_arr[]       = {3, 2, 8, 3};
int32_t interrupt_count = 0;
int32_t loop_count      = 0;
SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);

elapsedMillis report;
elapsedMillis read_adc_ms;

// T4 SLAVE using swapPins
// 11 MOSI
// 12 MISO
// 10 CS
// 13 CLK

SPISlave_T4<&SPI, SPI_8_BITS> mySPI;

void myFunc() {
    // There are 4 bytes being sent at 200khz clock speed SPI Mode 0
    // at 5ms intervals from Teensy LC
    // The CS line goes low and 4 bytes of clock come in
    // and 4 bytes of dummy data from MOSI
    // however, this test_pin does not raise until the beginning of
    // the 4th byte
    digitalWrite(test_pin, 1);
    interrupt_count++;
    while (mySPI.active()) {
        if (mySPI.available()) {
            spi_data_n++;

            if (spi_data_n > 3) {
                spi_data_n = 0;
            }
            loop_count++;
            // looking at these bytes on the scope, lined up with Chip Select as trigger
            // The bytes are not lined up 0, 1,2 ,3 in fact they are randomly placed
            mySPI.pushr(0x50 | spi_data_n);
        }
    }
    digitalWrite(test_pin, 0);
}

void setup() {
    Serial.begin(115200);
    pinMode(test_pin, OUTPUT);

    mySPI.onReceive(myFunc);
    mySPI.begin();
    mySPI.swapPins(); // allows direct 10-10, 11-11, 12-12, 13-13
}


void loop() {
    // DEBUG OUTPUT
    if (report > REPORT_INTERVAL_MS) {
        report = 1;
        Serial.print(millis() - 2);
        Serial.print("\t");
        Serial.print(loop_count);
        Serial.print("\t");
        Serial.println(interrupt_count);
    }
}



My questions:
Is it appropriate and correct to use 8-bit transfers even though I want to send 32 bits of data? I think I should stay this way because it is how I have had the most success. This code at least stays running and other attempts have led to worse problems I will not go into.

This code is 'running' but is also useless because the bytes being sent are not what I intend to send.

When is the onRecieve function supposed to be called? what is the trigger for this?

how are the pushr and popr supposed to be used? Is there some kind of buffer at play here that causes my data is getting out of alignment?
 
for the 4.x slave check if you're using the GND beside the 5v pin, and not the one beside pin 0

there is no buffer, this is a fixed register in the SPI hardware
POPR receives byte from bus master
PUSHR stores byte to be transfered to master
 
thanks for the quick response!, I added the extra GND connection. The images I see on the scope seem to indicate no signal problems relative to the low clock speed I am running. popr and pushr are quite straightforward I am glad to know there isn't something fancier behind those.

I cannot understand the behavior of the myFunc() in which my code sets the pin high at the beginning and low at the end. I did another change and had my spi master send 8 bytes instead of 4. Now what I see is after 7 bytes sent the line goes high for the last byte. Previously it went high after 3 bytes. I will keep studying this.

now I realize that one has to pushr the first byte before any transaction occurs because there must be something available to clock out upon the CS line going active. I added that to my setup()

? is the .active function meant to track the state of the CS signal?

? what is the .available() designed to do? is it checking the presence of a byte in the buffer? would this function have a way to know that I have grabbed the previous value?
thanks!
 
update, I changed my Teensy LC SPI Master to send out 8 bytes at 100khz clock speed at the same 5ms intervals. Previously I used 200khz clock speed and sent 4 bytes. I get something kind of similar.


This is showing that the peripheral sends some bytes out, but I cannot control which ones get sent in alignment with the packet.
TEK00002.PNG


This shows the gpio that I am raising during the onRecieve event. Curiously it raises in alignment with the last byte. I don't think this is technically what is going on - after all how could it possibly predict the future ?!! but it is how this appears.
Also if I widened the time scale on the scope I can see that this pin is only being raised for every other packet where previously it was happening every 4th. this is very odd ! ?

TEK00000.PNG


Teensy 4.1 as SPI Slave - added some counters to help debugging

Code:
#include <Arduino.h>
#include "SPISlave_T4.h"
#include "SPI.h"

constexpr int32_t READ_INTERVAL_MS   = 12;
constexpr int32_t REPORT_INTERVAL_MS = 500;
constexpr uint8_t cs_pin_1           = 6;
constexpr uint8_t test_pin           = 2;

int32_t spi_data_n      = 0;
uint8_t spi_arr[]       = {3, 2, 8, 3, 0, 0, 0, 0}; // not used yet
int32_t interrupt_count = 0;
int32_t loop_count      = 0;
int32_t cs_assert_time  = 0;
SPISettings settingsA(200000, MSBFIRST, SPI_MODE0);

elapsedMillis report;
elapsedMillis read_adc_ms;

// T4 SLAVE using swapPins
// 11 MOSI
// 12 MISO
// 10 CS
// 13 CLK

SPISlave_T4<&SPI, SPI_8_BITS> mySPI;

void myFunc() {
    int32_t local_time;
    // There are 8 bytes being sent at 100khz clock speed SPI Mode 0
    // at 5ms intervals from Teensy LC
    // The CS line goes low and 8 bytes of clock come in
    // and 8 bytes of dummy data from MOSI
    // however, this test_pin does not raise until the beginning of
    // the 7th byte (of 8 transmitted within chip select being active)
    digitalWrite(test_pin, 1);
    interrupt_count = 0;
    local_time      = micros();
    while (mySPI.active()) {
        loop_count++;
        if (mySPI.available()) {
            spi_data_n++;
            interrupt_count++; // I would like this to be 8 but is actually 60-61
            if (spi_data_n > 7) {
                spi_data_n = 0;
            }

            // looking at these bytes on the scope, lined up with Chip Select as trigger
            // The bytes are not lined up 0, 1, 2, 3, etc. in fact they seem randomly placed
            mySPI.pushr(0x50 | spi_data_n);
        }
    }
    cs_assert_time = micros() - local_time;
    digitalWrite(test_pin, 0);
}

void setup() {
    Serial.begin(115200);
    pinMode(test_pin, OUTPUT);

    mySPI.onReceive(myFunc);
    mySPI.begin();
    mySPI.swapPins();               // allows direct 10-10, 11-11, 12-12, 13-13
    mySPI.pushr(0x50 | spi_data_n); // put the first value
}


void loop() {
    // DEBUG OUTPUT
    if (report > REPORT_INTERVAL_MS) {
        report = 1;
        Serial.print(millis() - 2);
        Serial.print("ms\t");
        Serial.print(loop_count);
        Serial.print("\t");
        Serial.print(cs_assert_time);
        Serial.print(" cs us\t");
        Serial.print(interrupt_count);
        Serial.println(" counts during loop of onRecieve");
    }
}



Here is some of the output. I have timed the onRecieve function at about 86us and this corresponds with the trace I see on the scope. In order for me to get all the bytes out this Function should be active coincident to the CS line and then I would need some way to know 'when' each Byte is available. or I would need an interrupt for every single individual byte one at a time.

222299ms 26879643 86 cs us 110 counts during loop of onRecieve
222799ms 26940692 86 cs us 110 counts during loop of onRecieve
223299ms 27001741 86 cs us 110 counts during loop of onRecieve
223799ms 27062790 86 cs us 111 counts during loop of onRecieve
224299ms 27123839 86 cs us 110 counts during loop of onRecieve
224799ms 27184888 86 cs us 111 counts during loop of onRecieve
225299ms 27245937 86 cs us 110 counts during loop of onRecieve
225799ms 27306986 86 cs us 110 counts during loop of onRecieve
226299ms 27368035 86 cs us 110 counts during loop of onRecieve
226799ms 27429084 86 cs us 110 counts during loop of onRecieve
227299ms 27490133 86 cs us 110 counts during loop of onRecieve
227799ms 27551182 86 cs us 110 counts during loop of onRecieve
228299ms 27612231 86 cs us 110 counts during loop of onRecieve
228799ms 27673280 86 cs us 110 counts during loop of onRecieve
229299ms 27734329 86 cs us 110 counts during loop of onRecieve
 
i don't see POPR used in your last code, both of them must be used. if you dont care for POPR (receiving) then flush it at very least:

Code:
(void)mySPI.popr();
 
shoot, no go on that. I tried that statement just after.. .and then just before the pushr in that loop and what this does is make the serial output halt/never start. There is still strange activity on the logic analyzer/scope but nothing worth bothering with. I am pretty sure I had that line in the code before and probably just randomly took it out as a try. I had been having problems where my serial output didn't work at all so I was happy to have that running. I did that testing before I put the scope on it.

as you stated, I didn't use the code for receiving because I didn't intend to ever do anything with that data. Being just a single register (not a queue or buffer, etc.) I don't see why I would need to grab the value from it. couldn't it just keep getting over-ridden without being used?

I'm not sure where to go next.

are there any other working examples out there that I could try? I am still wondering what event is supposed to trigger the callback of onReceive.
 
I got an account and got the reference manual. I see the SPI (LPSPI ) peripheral has 16-word FIFO. This probably explains why my onReceive function was only being called each 4 transactions when the board was receiving 4 bytes - and when I changed to send 8 bytes it was every other transaction. There is some kind of buffer in the hardware or in the peripheral somehow there so I've got to deal with that.
 
I am encountering some issues with communicating to a teensy 4.1 running the library with a teensy 4.0. The teensy 4.1 that is acting as a slave is hanging until it receives the first message over SPI. The slave functions normally and as expected after the first message is received.

My goal is to have the 4.1 board running before the first SPI message without any hanging. Is this possible?

I am receiving every message correctly, but it hangs until it receives the first message.

spi.PNG

I have the hardware connected in the following way:
Teensy 4.0 (Master)CS (10)MOSI (11)MISO (12)SCK (13)GND
Teensy 4.1 (Slave)CS (10) MISO(12)MISO (11)SCK (13)GND

My slave code for the teensy 4.1.
This is the example program that is included with the library. I swapped the onReceive and begin function calls for the same reasons as previous users have stated in the forum.
Code:
#include "SPISlave_T4.h"
SPISlave_T4<&SPI, SPI_8_BITS> mySPI;

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

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

void myFunc() {
  Serial.println("START: ");
  uint8_t arr[] = { 3, 2, 8, 3, 10, 11, 33, 13, 14 };
  uint8_t i = 0;
  while ( mySPI.active() ) {
    if (mySPI.available()) {
      if ( i++ > sizeof(arr) ) i = 0;
      mySPI.pushr(arr[i]);
      Serial.print("VALUE: ");
      Serial.println(mySPI.popr());
    }
  }
  Serial.println("END");
}

My master code for the teensy 4.0
This is example code from the base teensy SPI library.

Code:
#include <SPI.h>  // include the SPI library:

const int slaveSelectPin = 10;

void setup() {
  // set the slaveSelectPin as an output:
  pinMode (slaveSelectPin, OUTPUT);
  // initialize SPI:
  SPI.begin(); 
}

void loop() {
  // go through the six channels of the digital pot:
  for (int channel = 0; channel < 6; channel++) { 
    // change the resistance on this channel from min to max:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, level);
      delay(10);
    }
    // wait a second at the top:
    delay(100);
    // change the resistance on this channel from max to min:
    for (int level = 0; level < 255; level++) {
      digitalPotWrite(channel, 255 - level);
      delay(10);
    }
  }
}

int digitalPotWrite(int address, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(address);
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH); 
}
 
Last edited:
the master 4.x need a patch for the DSE bits, check out the commits for SPI_MSTransfer_T4, this only affects the master, just make sure your ground is the one next to the 5v pin (not near pin 0)
 
Thank you for the quick reply!

Is there a way to fix it on the slave side? I want to eventually switch the master over to one of the Texas Instrument microcontrollers leaving only the teensy as a slave.
 
just my opinions as new users of Teensy and the slave library....

I have made some edits to the library to get my system working - just sharing what I did right or wrong - I have been observing the transactions on the scope as I do the changes.

I changed this:
SLAVE_IER = 0x1; /* RX Interrupt */

to
SLAVE_IER = LPSPI_IER_FCIE; // ((uint32_t)(1<<9))

making use of #defines in imxrt.h

what this does is set the interrupt to only occur at the end of a frame.

TylerJulian, you are sending 2 bytes so you could change your slave to SPI_16_BITS instead of SPI_8_BITS. The receive and send buffers can hold 32 bit words.


because I changed the interrupt to work on the end of the frame the receive FIFO has all the words (qty 1 in your case TylerJulian) and will be in need of one word for the TX FIFO for the next transaction.

The nominal interrupt code could then be this (bear in mind the library adds additional code for the interrupt beyond this, to clear the flags and something else...)

Code:
void frame_complete_isr() {
    // at this point there should be 0 items in the send buffer
   
    // read one and get one 16 bit value
    mySPI.pushr(value);
    data_sent  = mySPI.popr();
    
}

although this does not account for errors or help get the fifo buffers into the correct state at startup. my code has some protections for this by reading the current size of each fifo buffer. it would only be active at program start, if ever.

I didn't use the .active() or .available() because they don't seem needed when the interrupt runs at the end of the frame.

although it is not pertinent to the most recent question, I added a definition for a 64 bit frame size because my master code is sending 2 32 bit words.
Code:
typedef enum SPI_BITS {
    SPI_8_BITS = 8,
    SPI_16_BITS = 16,
    SPI_32_BITS = 32,
    SPI_64_BITS = 64,
} SPI_BITS;
 
Last edited:
Thank you for the quick reply!

Is there a way to fix it on the slave side? I want to eventually switch the master over to one of the Texas Instrument microcontrollers leaving only the teensy as a slave.

only thr t4.x masters needs specific dse bits set, other masters work fine
 
Hi all,

Thanks for this library. I wondering if I could get some help! I've been tinkering with it for a while, and I don't understand some of the issues I am seeing. I have established communication between a master and slave T4.1. The data that comes from the master to the slave looks correct, and I can get up to 4 bytes returned from slave to master. But this only works when I have a few bytes hard coded to send. If I do anything in my code, I don't seem to see the changes and/or the changes don't make sense.

Slave:
Code:
void setup() 
{  
  // Debug output
  Serial.begin(9600);

  delay(2000);

  //init the SPI
  
  mySPI.begin();
  mySPI.swapPins();
  mySPI.sniffer(false);
  mySPI.onReceive(spi_interrupt);
   
  delay(2000);
}

void loop() 
{
  relay_select(2);
  delay(1000);
  relay_select(13);
  delay(1000);
  // relay_select(2);
  // delay(1000);

  if(new_SPI)
  {
    new_SPI = false;
    relay_select(2); // make sound
  }
}

void spi_interrupt(void)
{

  uint8_t arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  uint8_t i = 0;
  
  while ( mySPI.active() ) 
  {
    if (mySPI.available()) 
    {
      if ( i++ > sizeof(arr) )
      {
        i = 0;
      } 
      mySPI.pushr(arr[i]);    //i - 1?
      SPI_data = mySPI.popr();    
    }
  }
}
relay_select() just makes a ticking sound from a relay to let me know where the program is

master code:
Code:
void setup (void)
{
  Serial.begin(115200);                   //Starts Serial Communication at Baud Rate 115200 
  pinMode(ipbutton,INPUT);                //Sets pin 2 as input 
  pinMode(LED,OUTPUT);                    //Sets pin 7 as Output
  SPI.begin();                            //Begins the SPI commnuication
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(SPI_MODE0);

  SPI.setClockDivider(SPI_CLOCK_DIV32);    //Sets clock for SPI communication at 8 (16/32=0.5Mhz)
  
  digitalWrite(SS, HIGH);
  delay(500);
  digitalWrite(SS, LOW); 
  delay(500); 
  digitalWrite(SS, HIGH);
  delay(5000);
}


void loop(void)
{
  Serial.println("Start");
  byte Mastersend;          
  uint8_t Mastereceive;

  Serial.println("test");
  digitalWrite(SS, LOW);       
  delay(10); 
  Mastereceive=SPI.transfer(0xAA);    // Update voltages command (should tick)
  Mastereceive=SPI.transfer(0xAA); 
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  digitalWrite(SS, HIGH);
  delay(3000);
    
  Serial.println("Writing initial byte");  
  digitalWrite(SS, LOW);       
  delay(10);           
  Mastereceive=SPI.transfer(0x07);    // Update voltages command (should tick)  
  Mastereceive=SPI.transfer(0xAA);    // Update voltages command (should tick)
  digitalWrite(SS, HIGH);
  
  delay(7500);    //allow time for updates, should hear tick go away

  Serial.println("Get readings");  
  digitalWrite(SS, LOW);       
  delay(10); 
  Mastereceive=SPI.transfer(0x01);    // Update voltages command (should tick)
  Mastereceive=SPI.transfer(0x01); 
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  Mastereceive=SPI.transfer(0xAA); 
  Mastereceive=SPI.transfer(0xAA);
  Serial.println(Mastereceive);
  digitalWrite(SS, HIGH);

  delay(1000);

  Serial.println("yup I'm alive");

}

As soon as the master sends an SPI byte, I no longer hear ticking and it seems like the the main loop is not running anymore. It never comes back until I reset the device. Is the interrupt hanging? Its odd because although the loop is not going, future reads from the master to return the correct bytes.

If I try to change the contents of the array in the slave based on the byte sent by the master, i do notice a different value but its not the value I set.

Any tips or advice for me?

Thanks!
 
if you are using a T4.x master there is a slight bug in the DSE gpio bits, which is fixed in SPI_MSTransfer_T4. Other master controllers don't seem to have this issue. Also for your common ground don't use the GND pin next to pin 0 on master T4, use the one beside the 3.3/5v pins instead, either the GND or the pin config settings will help you get better results
 
if you are using a T4.x master there is a slight bug in the DSE gpio bits, which is fixed in SPI_MSTransfer_T4. Other master controllers don't seem to have this issue. Also for your common ground don't use the GND pin next to pin 0 on master T4, use the one beside the 3.3/5v pins instead, either the GND or the pin config settings will help you get better results

Thanks for this!

Are you suggesting that my master controller is not de-asserting the SS pin or something like that? I was able to observe that this isn't the case with a scope. In either case, my master is using SPI.h.

Apologies if its apparent to a better programmer than me, but will a slave running SPI_MSTransfer_T4 interface with any (non bugged of course) master controller? Or do I need to use SPI_MSTransfer_T4 on the master as well? I'm using a T4.1 right now for a master, but long term this will not be the case. All I need to do is transfer a few bytes back and forth.

Thanks!
 
SPI_MSTransfer_T4 is a 2-way daisy-chainable data transfer utility. It includes the slave and master headers and source files, with simple examples.

if you prefer to keep a teensy4.x as master using SPISlave_T4 i suggest you use the mentioned common ground path and the patch that is in SPI_MSTransfer_T4 posted below:

Code:
#if defined(__IMXRT1062__)
    IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_01 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SDI (MISO) */
    IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_02 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SDO (MOSI) */
    IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_03 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 SCK (CLK) */
    IOMUXC_SW_PAD_CTL_PAD_GPIO_B0_00 = IOMUXC_PAD_DSE(3) | IOMUXC_PAD_SPEED(3) | IOMUXC_PAD_PKE; /* LPSPI4 PCS0 (CS) */
#endif
if you are using teensy 3.x or LC, they run fine without the DSE pad settings being corrected
 
Tonton, thank you again.

My Teensy SPI slave device will eventually connect with a master R-Pi. This R-Pi is in development, and the hardware is set in stone, hence why I am stuck with SPI.

My current mock up master (using Teensy 4.1) doesn't use SPISlave_T4 at all, it uses the standard Arduino SPI library, this should be no problem, correct?

The part I don't understand is why my slave loop seems to freeze when it receives a message from the master, yet apparently the slave can still respond to SPI messages even with this frozen loop. Can you help me to understand at all?

If I understand you, I should be able to make SPISlave_T4 work if I apply the patch you mentioned in the above quote? Becaue SPI_MSTranser_T4 is intended as a data transfer utility that where I must use that library on both master and slave?

Thanks!
 
yes but the master end *should* work on any other arduinos, you'd have to test as it uses the standard SPI library for master. The slave end is only working for the Teensy 3.x/LC/T4.x end. The patch is if you still want to use SPISlave_T4 with a master T4.x, if RPI is master you should be able to send fine via it's own SPI library with a TLC/T3.x/T4.x slave using SPISlave_T4
 
Ok, thanks again. I will try it again tonight and see where I get.

Do you know of any examples of SPISlave_T4 being used to receive a byte, and then return a group of bytes based on what the first byte was?

Is there a good way to not have the slave device hang until the SS pin of the master goes HIGH LOW HIGH?

My code above doesn't seem to work well. I really appreciate you taking the time to help me out.
 
its one byte/word at a time, not grouped. if you want the slave to send more data you need to basically send dummy bytes/words to push the data out of the slave, so you need to handle that as needed
 
Ok, thanks again. I will try it again tonight and see where I get.

Do you know of any examples of SPISlave_T4 being used to receive a byte, and then return a group of bytes based on what the first byte was?

Is there a good way to not have the slave device hang until the SS pin of the master goes HIGH LOW HIGH?

My code above doesn't seem to work well. I really appreciate you taking the time to help me out.

if I were doing this I would do it as two transactions from the master. The first is to send a packet of the same size you intend to receive and at some position in there put your command word or byte. Based on this command word you can set up the return packet as desired

There would be two separate assertions of the chip select line.

The second transactions sends meaningless bytes and definitely do NOT have any valid command words in there and then of course receive the pertinent data from that transaction.

The simplicity is having both packets or frames be the same size to make the slave code easier.

I recommend you have an oscilloscope connected and also reference the datasheet. This is pretty advanced stuff and I expect you will need to modify things to get it working.
 
Back
Top