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.

CC1310 SPI slave example

Other Parts Discussed in Thread: CC1310, SYSBIOS

Hi all,

I need to communicate my raspberry (master) with the cc1310 (slave). I can't find any example on the last and previous rtos package. someone can help me?

I tried to use the docs included in the rtos folder, but the cc1310 replay my only one byte from spi and after it give me all 0xFF. Furthermore I need to use the CS pin to start and end the communication to the slave. 

thanks!

Riccardo

  • Hi Riccardo,

    You are correct that such an example is not available in the latest TI-RTOS. Let me check with the driver team tomorrow and see if there is something they can point you to.

    Best regards,
    Vincent
  • Hi Vincent,

    Thanks for your reply. In my design,  the cc1310 needs to manage dynamic len packet, so the transaction depends from the cs assertion by the master. Is also implemented a clock istance that makes blink a simple led.

    To dontest, in the tx buffer of the spi slave, I have written  two byes to 0xbb and 0xcc. When I execute the transaction, the cc1310  transmits  only the first byte , after and for the  next transactions, it  write only 0xff. The transaction from master is right (checked with a logic analyzer).

    The spi funtion is implemented under a task.

    Very strange, but as I told,  I have used code taken

    from docs and adapted so I don't  know if something goes wrong.

    Riccardo

  • Hi Riccardo,

    Which CC1310 board are you developing on? If you are using the DK EVM, the driver team told me there is an LCD example which uses the LCD driver, located in 'tirtos_cc13xx_cc26xx_2_16_00_08\products\tidrivers_cc13xx_cc26xx_2_16_00_08\packages\ti\mw\lcd' if you are using TIRTOS 2.16. The LCD driver itself is built upon the SPI driver. So you should be able to use that as a reference.

    Best regards,
    Vincent
  • I'm using only the radio module pcb 'cause the entire  kit wasn't avalaible when I bought it, however I will check the lcd example, but in this case I think the cc1310 should be the master and lcd the slave, I need an example where the cc1310 is the slave, with dynamic packet len.

    Riccardo

  • Hi Riccardo,

    Taken from the spiloopback example on other TI devices, the following usage of the SPI driver API should hold true for the CC1310 as well:

    Void slaveTaskFxn (UArg arg0, UArg arg1)
    
    {
    
       SPI_Handle slaveSpi;
    
       SPI_Params slaveSpiParams;
    
       SPI_Transaction slaveTransaction;
    
       bool transferOK;
    
       /* Initialize SPI handle with slave mode */
    
       SPI_Params_init(&slaveSpiParams);
    
       slaveSpiParams.mode = SPI_SLAVE;   //SLAVE MODE
    
       slaveSpi = SPI_open(Board_SPI1, &slaveSpiParams);
    
       if (slaveSpi == NULL) {
    
           System_abort("Error initializing SPI\n");
    
       }
    
       else {
    
           System_printf("SPI initialized\n");
    
       }
    
       /* Initialize slave SPI transaction structure */
    
       slaveTransaction.count = SPI_MSG_LENGTH;
    
       slaveTransaction.txBuf = (Ptr)slaveTxBuffer;
    
       slaveTransaction.rxBuf = (Ptr)slaveRxBuffer;
    
       /* Initiate SPI transfer */
    
       transferOK = SPI_transfer(slaveSpi, &slaveTransaction);
    
       if(transferOK) {
    
           /* Print contents of slave receive buffer */
    
           System_printf("Slave: %s\n", slaveRxBuffer);
    
       }
    
       else {
    
           System_printf("Unsuccessful slave SPI transfer");
    
       }
    
       /* Deinitialize SPI */
    
       SPI_close(slaveSpi);
    
    }
    

    CC1310 uses the same SPI API as other TI devices (e.g. TM4C1294). The key is to set the 'mode' parameter to SPI_SLAVE if you want it to operate in slave mode.

    Best regards,

    Vincent

  • Hi Vincent,

    it's all right but i see that in this example the transaction depends from the .count field, but I need variable len so it should depends from cs deassertion (like hardware  slave spi generic devices).

    What do you think of this thing?

    I hope i should  not have to use fix len.

    Thanks

    Riccardo

  • Hi Riccardo,

    Have you checked out the example code in the section on "Slave Mode With Return Partial" in the SPI driver documentation under tirtos_cc13xx_cc26xx_2_16_00_08/products/tidrivers_cc13xx_cc26xx_2_16_00_08/docs/doxygen/html/_s_p_i_c_c26_x_x_d_m_a_8h.html#USE_CASE_RP

    That technique should allow an unknown amount of bytes to be transferred.

    Best regards,
    Vincent

  • Hi Vincent,

    I'm going crazy......

    After variuos tests, the result is the same, always one byte...:

    Debugging, the transaction.status variable value is correct (CSN_DEASSERTED) but in the rx and tx buffers there is only one byte written(checked with a memory watch).

    In slave mode, the transaction.count variable must be rewritten every time ? I tried also to no rewrite it but nothing changed.

    I'm using Chip Select asserted for all the transition, as generic SPI device transition.

    Please help me, I don't understand if it is a CC1310 issue or a RTOS issue, nobody happen this problem? This issue is blocking my developing and I need to resolve as soon as possible.

    This is the code, I always work with CSN deassertion, no fixed len (count):

    /*
     *  ======== empty.c ========
     */
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>

    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>

    /* TI-RTOS Header files */
    // #include <ti/drivers/I2C.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPICC26XXDMA.h>
    #include <ti/drivers/dma/UDMACC26XX.h>

    // #include <ti/drivers/UART.h>
    // #include <ti/drivers/Watchdog.h>

    /* Board Header files */
    #include "Board.h"

    #define TASKSTACKSIZE   512

    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;

    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];

    Task_Struct taskSPIStruct;
    Char taskSPIStack[TASKSTACKSIZE];


    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config ledPinTable[] = {
        LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };

    /*
     *  ======== heartBeatFxn ========
     *  Toggle the Board_LED0. The Task_sleep is determined by arg0 which
     *  is configured for the heartBeat Task instance.
     */
    Void heartBeatFxn(UArg arg0, UArg arg1)
    {
        while (1) {
            Task_sleep((UInt)arg0);
            PIN_setOutputValue(ledPinHandle, LED2,
                               !PIN_getOutputValue(LED2));
        }
    }


    /*
     *  ======== SPI ========
     *  */



    // Callback function
    static void transferCallback(SPI_Handle handle, SPI_Transaction *transaction)
    {
        // Start another transfer
        transaction->count = 100;
        SPI_transfer(handle, transaction);
    }


    Void SPIFxn(UArg arg0, UArg arg1)
    {

    uint8_t txBuf[100];
    uint8_t rxBuf[100];

        SPI_Handle handle;
        SPI_Params params;
        SPI_Transaction transaction;
        // Init SPI and specify non-default parameters
        SPI_Params_init(&params);
        params.bitRate     = 1000000;
        params.dataSize = 8;
        params.frameFormat = SPI_POL0_PHA0;
        params.mode        = SPI_SLAVE;
        params.transferMode        = SPI_MODE_CALLBACK;
        params.transferCallbackFxn = transferCallback;
        // Configure the transaction
        transaction.count = 100;
        transaction.txBuf = txBuf;
        transaction.rxBuf = rxBuf;

        txBuf[0]=0xCC;
        txBuf[1]=0xEE;
        txBuf[2]=0xDD;

        // Open the SPI and initiate the first transfer
        handle = SPI_open(IC_SPI, &params);
        SPI_control(handle, SPICC26XXDMA_RETURN_PARTIAL_ENABLE, NULL);
        SPI_transfer(handle, &transaction);
        while(1);
        // Wait forever

    }




    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;

        /* Call board init functions */
        initGeneral();
        // Board_initI2C();
        initSPI();
        // Board_initUART();
        // Board_initWatchdog();

        /* Construct heartBeat Task  thread */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 1000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        taskParams.instance->name = "heartBeat";
        taskParams.priority= 2;
        Task_construct(&task0Struct, (Task_FuncPtr)heartBeatFxn, &taskParams, NULL);


        /* SPI task */
        Task_Params_init(&taskParams);
        taskParams.arg0 = 1000;
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &taskSPIStack;
        taskParams.instance->name = "SPI";
        taskParams.priority= 1;
        Task_construct(&taskSPIStruct, (Task_FuncPtr)SPIFxn, &taskParams, NULL);


        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, ledPinTable);
        if(!ledPinHandle) {
            System_abort("Error initializing board LED pins\n");
        }

        PIN_setOutputValue(ledPinHandle, LED1, 1);

        System_printf("Starting the example\nSystem provider is set to SysMin. "
                      "Halt the target to view any SysMin contents in ROV.\n");
        /* SysMin will only print to the console when you call flush or exit */
        System_flush();

        /* Start BIOS */
        BIOS_start();

        return (0);
    }

  • Hi Riccardo,

    Have you verified that your hwAttrs settings is defining csnPin to correspond to your CS pin? Alternatively you can use SPICC26XXDMA_control() with command 'SPICC26XXDMA_CMD_SET_CSN_PIN' to configure your pin.

    Also double-check whether frameFormat = SPI_POL0_PHA0 is really the format you want. It corresponds to the format described in Figure 20-5 in the TRM in www.ti.com/.../swcu117d.pdf.

    Best regards,
    Vincent
  • Hi Vincent,
    I'll recheck all you told me, but in the debug session, the transaction.status give me that the transfer is terminated cause cs deassertion, so I think the cs is correct. The transaction.count give me value 1 that is confirmed by a memory watch from the debug session, the byte value is also correct (the tx one and the rx one), so I exclude a wrong set of clock and phase, in this case I should have wrong value of this first byte also. The impression is that the transfert hang on the first byte, if I try multiple transfer, I got always the first byte only. In each callback call I rewrite the transactio.count to the original value (100).
  • Hi Vincent,

    I attach some screenshot of the CSS debugging and waveform from my logic analyzer, i summarize you the actual situation:

    • Raspberry is the master, and send on MOSI line three bytes [0xAA,0xDD,0xF].
    • CC1310 is the slave, and should send on MISO line three bytes [0xCC,0xEE,0xDD].
    • The communication in POL0 and PHA0, variable len packets terminated by Chip Select deassertion.
    • Frame size is 8, one byte per frame.
    • Max len packets is about 80 bytes, so I declared a txBuf[100] and an rxBuf[100] and set the transaction.count value to 100 to be sure all fits with no problem, the packets will always be terminated before 100 bytes by Chip Select assertion.
    • In the callback function I rewrite transaction.count value to 100 to restart the cycle with no problem.

    In the first attached screenshot (Before) you can see the situation before a SPI transaction, you can see transaction.count set to 100, rx and tx buffer pointers initilized and the transaction.status return SPI_TRANSFER_STARTED. All confirmed by the Printf Logs entries (I'm using instrumented drivers lib), all is ready for a transfer.

    In the second attached screenshot (After) you can see the situation after the SPI transaction, you can see transaction.count set to 1 the transaction.status return SPI_TRANSFER_CSN_DEASSERT. The latter is right, but transaction.count is wrong, and all is confirmed by memory watch (not present in screenshot for space reasons) where in the rxBuf I can find only the first value sent by Raspberry (0xAA), and furthermore Raspberry receveid only the first byte from the CC1310 (0xCC).  The Printf Logs entries give me a DMA transaction cancelled, I don't know if this is a normal thing.

    If a try other transfers, the situation is always the same.

    In the other screenshot you can see the trasfer captured by my logic analyzer.


    I hope can give me some good news, I stuck in developing by this problem.

    Thanks!

    Riccardo

  • Hi all!!!!

    Finally I found the problem!!!

    CC1310 allow multiple bytes transfer with chip select active for the entire transaction only if PHASE is set to 1.

    If it is set to 0, the spi state machine need cs deassertion for every frame/byte instead, to send correctly to the dma.

    This information is written in the cc1310 technical datasheet (1625 pages).

    Thanks to Vincent for the indication about figure 20-5 on the datasheet.

    Riccardo

  • Hi Riccardo,


    Glad to hear you found the issue - thanks for sharing the info!


    Best regards,

    Vincent