This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RTOS/LAUNCHXL-CC1350: CC1350 SPI Slave mode not working reliably

Part Number: LAUNCHXL-CC1350
Other Parts Discussed in Thread: CC1350, CC1310

Tool/software: TI-RTOS

Greetings:

I have a CC1350 SPI slave that I cannot get to work correctly. I have attempted slaving it to both a BeagleBone Black and a Teensy (via Arduino), but I cannot shakedown the root cause of these errors. I get about a 5:1 error:success radio sending a 3-byte frame {0x7f,0x00,0xff}. It appears that the values in the receive buffer are correct, but not in the proper sequence. This suggests to me some sort of timing issue. I have attempted tests on all modes, with the latest test using mode 3 in a nearly identical configuration to that depicted in the documentation for SPICC26XXDMA.h. Furthermore, I have attempted various configurations for the pin config values to no success. The results are similar regardless of whether or not I use the wakeup feature.

Excerpt from <Board>.h

/* SPI Board */
#define CC1350_LAUNCHXL_SPI0_MISO             IOID_8          /* RF1.20 */
#define CC1350_LAUNCHXL_SPI0_MOSI             IOID_9          /* RF1.18 */
#define CC1350_LAUNCHXL_SPI0_CLK              IOID_10         /* RF1.16 */
#define CC1350_LAUNCHXL_SPI0_CSN              IOID_11

Excerpt from <Board>.c

    CC1350_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
    CC1350_LAUNCHXL_SPI0_MISO | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL,                                            /* SPI master in - slave out */
    CC1350_LAUNCHXL_SPI0_CLK | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* SPI clock */
    CC1350_LAUNCHXL_SPI0_CSN | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* SPI CS */

SPI Task

Void spiTaskFunc( UArg arg0, UArg arg1 )
{
    SPI_Handle handle;
    SPI_Params params;
    SPI_Transaction transaction;
    uint8_t rxBuf[3] = {0};                  // Receive and transmit buffer

    // Init SPI and specify non-default parameters
    SPI_Params_init(&params);
    params.transferTimeout = SPI_WAIT_FOREVER;
    params.bitRate             = 1000000;
    params.frameFormat         = SPI_POL1_PHA1;
    params.mode                = SPI_SLAVE;
//    params.transferMode        = SPI_MODE_CALLBACK;
    //    params.transferCallbackFxn = transferCallback
    params.transferMode        = SPI_MODE_BLOCKING;
    params.dataSize = 8;

    // Configure the transaction
    transaction.count = 3;
    transaction.txBuf = NULL;
    transaction.rxBuf = rxBuf;
    // Open the SPI and initiate the first transfer
    handle = SPI_open(CC1350_LAUNCHXL_SPI0, &params);

    //    SPI_control(handle, SPICC26XXDMA_RETURN_PARTIAL_ENABLE, NULL);
    PIN_Id pin = CC1350_LAUNCHXL_SPI0_CSN;
    SPI_control(handle, SPICC26XXDMA_CMD_SET_CSN_PIN, &pin);

    uint32_t successcounter = 0;
    uint32_t errorcounter = 0;
    while(1)
    {
        memset( rxBuf, 0, 3 );

        SPI_transfer(handle, &transaction);

        if( rxBuf[0] == 0x7f && rxBuf[1] == 0x00 && rxBuf[2] == 0xff )
        {
            successcounter += 1;
        }
        else
        {
            errorcounter += 1;
        }
    }
}

Arduino code

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

const int slaveSelectPin = 10;

SPISettings settingsA(1000000, MSBFIRST, SPI_MODE3);

void setup() {

  Serial.begin(9600);

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

//char data[3] = {'H','i','\0'};
//char data[3] = { 0x88, 0x88, 0x00};
uint8_t data[3] = { 0x7F, 0x00, 0xFF};
char temp;

void loop() {

  SPI.beginTransaction(settingsA);

  //Wakeup CC1350
  digitalWrite (slaveSelectPin, LOW);
  digitalWrite (slaveSelectPin, HIGH);

  //Start SPI transfer
  digitalWrite (slaveSelectPin, LOW);
  SPI.transfer( (uint8_t) data[0] );
  digitalWrite (slaveSelectPin, HIGH);
 
  digitalWrite (slaveSelectPin, LOW);
  SPI.transfer( (uint8_t) data[1] );
  digitalWrite (slaveSelectPin, HIGH);
 
  digitalWrite (slaveSelectPin, LOW);
  SPI.transfer( (uint8_t) data[2] );
  digitalWrite (slaveSelectPin, HIGH);

//  Serial.print("Received: ");
//  temp = (char) SPI.transfer( 0 );
//  Serial.print(temp);
//  temp = (char) SPI.transfer( 0 );
//  Serial.print(temp);
//  temp = (char) SPI.transfer( 0 );
//  Serial.println(temp);
 
  SPI.endTransaction();

//  digitalWrite (slaveSelectPin, HIGH);

  Serial.print("Sent " );
  Serial.println( (char *) data );

  delay(1);
}

  • Hi,

    Michael Cress said:

      SPI.beginTransaction(settingsA);

      //Wakeup CC1350
      digitalWrite (slaveSelectPin, LOW);
      digitalWrite (slaveSelectPin, HIGH);

      //Start SPI transfer
      digitalWrite (slaveSelectPin, LOW);
      SPI.transfer( (uint8_t) data[0] );
      digitalWrite (slaveSelectPin, HIGH);
     
      digitalWrite (slaveSelectPin, LOW);
      SPI.transfer( (uint8_t) data[1] );
      digitalWrite (slaveSelectPin, HIGH);
     
      digitalWrite (slaveSelectPin, LOW);
      SPI.transfer( (uint8_t) data[2] );
      digitalWrite (slaveSelectPin, HIGH);

    I don't think that it is valid to de-assert the chip-select pin between each byte. The CC13xx will think that the message is complete. Does it work when you change the Arduino code accordingly?

      SPI.beginTransaction(settingsA);
    
      //Wakeup CC1350
      digitalWrite (slaveSelectPin, LOW);
      digitalWrite (slaveSelectPin, HIGH);
    
      //Start SPI transfer
      digitalWrite (slaveSelectPin, LOW);
      SPI.transfer( (uint8_t) data[0] );
      SPI.transfer( (uint8_t) data[1] );
      SPI.transfer( (uint8_t) data[2] );
      digitalWrite (slaveSelectPin, HIGH);
    
      SPI.endTransaction();
  • I originally tried it without doing that. However, Figure 20-3 of the Technical Reference Manual shows the SSIn_FSS line going high after each frame (4-16 bytes).
  • Indeed, I was not aware of that. Are you sure that the time of the timing of the SS pin is correct?
  • There is no time domain declared in the TRF. However, I did test this case with a 1mS delay. I also researched implications this has with respect to the power management routines. However, it is documented in the TI Drivers documentation that in slave mode the device is not allowed to exit the Idle state, so I concluded it wasn't a sleep/wakeup timing issue.
  • Ok, I take that back. It declares the lowering to be one clock cycle. I did not test that case specifically. However, I did attempt the wake-up feature, which pulses the slave select prior to initiating the transfer.
  • Michael,

    actually, the CC1310 supports continuous transfers with the SS pin held low only if the SPH bit is 1 (). You are using this mode and you are using the correct transfer mode on the Teensy as well. So I wonder why it doesn't work in that case. Does it work when you reduce the speed?