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.

SPI communication between two CC1310

Other Parts Discussed in Thread: CC1310, SYSBIOS

Hi,

I'm having trouble making two cc1310 communicate using spi.

one configured as a master and the other is a slave and communicate in blocking mode.
In the master side I made a simple polling on the button1 state so when I press it the master board send spi data to the slave. I'm quite sure that the slave received something. I added a watch on the rxBuf array to visualize the received data but it values seems to never change.

Master side:

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

/* BIOS Header files */
#include <ti/sysbios/BIOS.h>
#include <ti/sysbios/knl/Clock.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 <string.h>

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

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

#define TASKSTACKSIZE   1024

Task_Struct task0Struct;
Task_Struct spiMasterTask;
Char task0Stack[TASKSTACKSIZE];
Task_Params spiMaster_TaskParams;
char spiMasterTaskStack[TASKSTACKSIZE];
uint8_t txBuf[100];
uint8_t rxBuf[100];
/* Pin driver handle */
static PIN_Handle ledPinHandle;
static PIN_State ledPinState;

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

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

void spiMaster_fxn(void){

	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_POL1_PHA1;
	params.mode        = SPI_MASTER;
	params.transferMode        = SPI_MODE_BLOCKING;
	params.transferCallbackFxn = transferCallback;
	// Configure the transaction
	strcpy((char*)rxBuf,"Master SPI");
	transaction.count = 100;
	transaction.txBuf = (Ptr)txBuf;
	transaction.rxBuf = (Ptr)rxBuf;

	// Open the SPI and initiate the first transfer
	handle = SPI_open(Board_SPI0, &params);
	SPI_control(handle, SPICC26XXDMA_RETURN_PARTIAL_ENABLE, NULL);
	while(1){
		if(PIN_getInputValue(Board_BTN1) == FALSE){
			SPI_transfer(handle,&transaction);
		}
	}
}

static spiMasterTaskInit(void){

	Task_Params_init(&spiMaster_TaskParams);
	spiMaster_TaskParams.arg0 =1000000;
	spiMaster_TaskParams.stack =&spiMasterTaskStack;
	spiMaster_TaskParams.stackSize = TASKSTACKSIZE;

	Task_construct(&spiMasterTask,(Task_FuncPtr)spiMaster_fxn,&spiMaster_TaskParams,NULL);
}
/*
 *  ======== main ========
 */
int main(void)
{
    Task_Params taskParams;

    /* Call board init functions */
    Board_initGeneral();
    // Board_initI2C();
    Board_initSPI();
    // Board_initUART();
    // Board_initWatchdog();
    spiMasterTaskInit();

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

    PIN_setOutputValue(ledPinHandle, Board_LED0, 0);

    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);
}

Slave side


//Cleanup
//Change RF settings for 868Mhz, 625bps long range mode
//create JSON string manually

/* XDCtools Header files */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <xdc/runtime/Error.h>

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

/* TI-RTOS Header files */
#include <ti/drivers/PIN.h>
#include <ti/drivers/SPI.h>
#include <ti/drivers/UART.h>
#include <ti/drivers/spi/SPICC26XXDMA.h>
/* Board Header files */
#include "Board.h"

/* EasyLink API Header files */
#include "easylink/EasyLink.h"

/*user defined*/
#include "jsmn.h"
#include <string.h>

/***** Defines *****/
//#define master

#define RFEASYLINKRX_ADDR_FILTER

#define RFEASYLINKEX_TASK_STACK_SIZE     1024
#define SPI_TASK_STACK_SIZE                1024
#define RFEASYLINKEX_TASK_PRIORITY       2
#define SPI_TASK_PRIORITY                1

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

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

/***** Variable declarations *****/
static Task_Params rxTaskParams;
Task_Struct rxTask;    /* not static so you can see in ROV */
static uint8_t rxTaskStack[RFEASYLINKEX_TASK_STACK_SIZE];
static Task_Params spi_TaskParams;
Task_Struct spiTask;
static uint8_t spiTaskStack[RFEASYLINKEX_TASK_STACK_SIZE];
bool transferOK;

jsmn_parser p;
jsmntok_t t[128];
int r_jsonPackets;

/* The RX Output struct contains statistics about the RX operation of the radio */
PIN_Handle pinHandle;
int counter = 0;

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

/***** Function definitions *****/

static void spiFnx(UArg arg0, UArg arg1){
    SPI_Handle handle;
    SPI_Params params;
    SPI_Transaction transaction;
    uint8_t txBuf[100];
    uint8_t rxBuf[100];
    UART_Params uartParams;
    const char echoPrompt[] = "\fEchoing characters:\r\n";

    // Init SPI and specify non-default parameters
    SPI_Params_init(&params);
    params.bitRate     = 1000000;
    params.dataSize = 8;
    params.frameFormat = SPI_POL1_PHA1;
    params.mode        = SPI_SLAVE;
    params.transferMode        = SPI_MODE_BLOCKING;
    params.transferCallbackFxn = transferCallback;
    // Configure the transaction
    strcpy((char*)txBuf,"Hello, This is Slave SPI");
    transaction.count = 100;
    transaction.txBuf = (Ptr)txBuf;
    transaction.rxBuf = (Ptr)rxBuf;

    // Open the SPI and initiate the first transfer
    handle = SPI_open(Board_SPI0, &params);
    SPI_control(handle, SPICC26XXDMA_RETURN_PARTIAL_ENABLE, NULL);
    PIN_setOutputValue(ledPinHandle, Board_LED0, 1);
    SPI_transfer(handle, &transaction);
    PIN_setOutputValue(ledPinHandle, Board_LED1, 1);
    while(1){}
}


static void rfEasyLinkRxFnx(UArg arg0, UArg arg1)
{
    EasyLink_RxPacket rxPacket = {0};

    EasyLink_init(EasyLink_Phy_625bpsLrm);
    EasyLink_setFrequency(868000000);

#ifdef RFEASYLINKRX_ADDR_FILTER
    uint8_t addrFilter = 0xaa;
    EasyLink_enableRxAddrFilter(&addrFilter, 1, 1);
#endif //RFEASYLINKRX_ADDR_FILTER

    while(1) {
        rxPacket.absTime = 0;
        EasyLink_Status result = EasyLink_receive(&rxPacket);

        /*Check if it is a good JSON package than send it with spi to master board*/
        r_jsonPackets = jsmn_parse(&p,(const char *)rxPacket.payload,strlen((const char *)rxPacket.payload),t,sizeof(t)/sizeof(t[0]));
        if (r_jsonPackets<0){
            //Failed to parse JSNO?
            PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
            PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));
        }else{
            //send data with spi

        }
        if (result == EasyLink_Status_Success)
        {
            /* Toggle LED2 to indicate RX */
            PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));
        }
        else
        {
            /* Toggle LED1 and LED2 to indicate error */
            PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
            PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));
        }
    }
}

void rxTask_init(PIN_Handle ledPinHandle) {
    pinHandle = ledPinHandle;

    Task_Params_init(&rxTaskParams);
    rxTaskParams.stackSize = RFEASYLINKEX_TASK_STACK_SIZE;
    rxTaskParams.priority = RFEASYLINKEX_TASK_PRIORITY;
    rxTaskParams.stack = &rxTaskStack;
    rxTaskParams.arg0 = (UInt)1000000;

    Task_construct(&rxTask, rfEasyLinkRxFnx, &rxTaskParams, NULL);
}

void spiTask_init(){
    Task_Params_init(&spi_TaskParams);
    spi_TaskParams.stackSize =SPI_TASK_STACK_SIZE;
    spi_TaskParams.priority = SPI_TASK_PRIORITY;
    spi_TaskParams.stack = &spiTaskStack;
    spi_TaskParams.arg0 = (UInt)1000000;

    Task_construct(&spiTask,spiFnx,&spi_TaskParams,NULL);
}

/*
 *  ======== main ========
 */
int main(void)
{
    /* Call board init functions. */
    Board_initGeneral();
    SPI_init();
    UART_init();
    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if(!ledPinHandle) {
        System_abort("Error initializing board LED pins\n");
    }else{
        System_printf("Leds initialized!");

    }

    /* Clear LED pins */
    PIN_setOutputValue(ledPinHandle, Board_LED1, 0);
    PIN_setOutputValue(ledPinHandle, Board_LED2, 0);

    spiTask_init();

    /* Start BIOS */
    BIOS_start();

    return (0);
}

Any will be much appreciated

  • Mazen,

    I think the problem is with the SPI slave code. It looks like the SPI slave is configured in SPI_MODE_BLOCKING, but I think your intent is to use CALLBACK mode. When using blocking mode, your transfer callback is never invoked by the SPI driver. So, your spiFxn task will block on the first and only call to SPI_transfer. After that, your slave will never prepare another transfer.

    Also, the spiFxn task spins in an empty while loop. It would be good to add a call to Task_sleep in your loop. This would allow the Idle task to run. Or better, simply block on a semaphore. Another option is to move the code from your transfer callback into the while loop and stay in SPI blocking mode.

    The SPI master code also configures a transfer callback but is also in SPI blocking mode. However, the spiMaster_fxn task does call SPI_transfer on a button press. It just looks confusing to have a callback as well. Finally, the master is doing a strcpy of "Master SPI" into the receive buffer (rxBuf). I think you want it in the transmit buffer (txBuf).

    ~Ramsey

  • Hello Ramsey,


    The callback function was there because at first I wanted to use callback mode, but later I just wanted to make sure that I have at least one transaction.


    Thank you for pointing that I was writing in the rxBuf, it was stupid mistake and now it is working.

    Best