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.

Stuck in a simple SPI code.

Other Parts Discussed in Thread: CC1350, CC1310, CC2650

Hi, I'm stuck in my code SPI. It is simply a code that must be able to send a few bites.
When the code reaches "SPI_transfer (spiHandle, & spiTransaction);" it is completely stuck.
I followed the guide to the letter and it should work.

I am using the "CC1350 LaunchPad".

I attached a picture of debug, with a message that I do not understand



I attached the code


/* XDC Module Headers */ #include <xdc/std.h> #include <xdc/runtime/System.h> #include <ti/drivers/SPI.h> /* BIOS Header files */ #include <ti/sysbios/BIOS.h> #include <ti/sysbios/knl/Task.h> #include <ti/drivers/GPIO.h> #include <ti/drivers/SPI.h> /* Example/Board Header files */ #include "Board.h" #include <stdbool.h> bool loop = true; SPI_Handle spiHandle; SPI_Params spiParams; SPI_Transaction spiTransaction; /* Pin driver handles */ static PIN_Handle pinHandle; /* Global memory storage for a PIN_Config table */ static PIN_State pinState; PIN_Config pinTable[] = { Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MAX, IOID_30 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, PIN_TERMINATE }; void delay_s(int dly) { while (dly > 0) { __delay_cycles(48000000); dly--; } } void delay_ms(int dly) { while (dly > 0) { __delay_cycles(48000); dly--; } } #define c 0x01 // ======== SETUP ======== void setup(){ System_printf("Start Setup\n"); /* Call board init functions */ Board_initGeneral() ; //BIOS_start(); // to enable interrupts and start the scheduler and kick BIOS into gear. pinHandle = PIN_open(&pinState, pinTable); if (!pinHandle) { System_abort("Error initializing board LED pins\n"); } System_printf("End Setup\n"); } /* * ======== main ======== */ Int main() { setup(); // ======== LOOP ======== while (loop) { PIN_setOutputValue(pinHandle, Board_LED0, 1); delay_ms(2000); PIN_setOutputValue(pinHandle, Board_LED0, 0); delay_ms(2000); uint8_t transmitBuffer[1]; SPI_Params_init(&spiParams); spiParams.transferMode = SPI_MODE_BLOCKING; spiParams.transferTimeout = SPI_WAIT_FOREVER; spiParams.transferCallbackFxn = NULL; spiParams.mode = SPI_MASTER; spiParams.bitRate = 4000000; spiParams.dataSize = 6; spiHandle = SPI_open(0, &spiParams); transmitBuffer[0] = c; spiTransaction.count = 1; spiTransaction.txBuf = transmitBuffer; spiTransaction.rxBuf = NULL; SPI_transfer(spiHandle, &spiTransaction); SPI_close(spiHandle); } BIOS_exit(0); /* terminates program and dumps SysMin output */ return (0); }

  • Hi Carlos,

    Are you referring to the error message: "Error cannot load from non-primitive location"? I believe that is an expected message, given the type of txBuf, rxBuf and arg is 'void *', and thus cannot be properly dereferenced.

    That aside, could you make sure Board_initSPI() (i.e. SPI_init()) is called? I don't seem to see the SPI module being initialized in your code shown. Ideally it should be called right after Board_initGeneral().

    Best regards,
    Vincent

  • Hi Vincent,

    First of all, thanks for answering.

    I added "Board_initSPI() or SPI_init() " but still the same. I had already tried before. But the same thing. It gets stuck in the moment "SPI_transfer (spiHandle, & spiTransaction);".

    I added a "System printf ("End transfer \ n");" before "SPI_transfer (spiHandle, & spiTransaction);" and never is printed on the console. The code just doesn't advance, but it doesn't crash.
  • Hi Carlos,

    The CC1310 drivers require the kernel to be started but your BIOS_start() is commented in your code.

    The SPI driver uses Semaphore_pend() when you call SPI_transfer(..), and therefore tries to put your "task" and therefore it locks there until the kernel is started.

    BIOS_start() does not return until you call BIOS_exit()  (that means that your code will never reach BIOS_exit() in your case). BIOS_start() will usually placed as the last line of main. You should create and start a Task to place your SPI functions with the while loop inside. Also, as mentioned, you should also place Board_initSPI() before you make any calls to the SPI interface.

    Here's what your modified code will look like:

    Char myTaskStack[1024];
    Task_Struct myTaskStruct;
    
    Void taskFxn(UArg arg0, UArg arg1) {
      System_printf("Start SPI task\n");
    
      SPI_Params_init(&spiParams);
      spiParams.transferMode = SPI_MODE_BLOCKING;
      spiParams.transferTimeout = SPI_WAIT_FOREVER;
      spiParams.transferCallbackFxn = NULL;
      spiParams.mode = SPI_MASTER;
      spiParams.bitRate = 4000000;
      spiParams.dataSize = 6;
      spiHandle = SPI_open(0, &spiParams);
      
      while (loop) {
    
        PIN_setOutputValue(pinHandle, Board_LED0, 1);
        delay_ms(2000);
        PIN_setOutputValue(pinHandle, Board_LED0, 0);
        delay_ms(2000);
    
        uint8_t transmitBuffer[1];
    
        transmitBuffer[0] = c;
    
        spiTransaction.count = 1;
        spiTransaction.txBuf = transmitBuffer;
        spiTransaction.rxBuf = NULL;
    
        SPI_transfer(spiHandle, &spiTransaction);
    
      }
    }
    
    // ======== SETUP ========
    void setup(){
    
      System_printf("Start Setup\n");
      /* Call board init functions */
      Board_initGeneral(); 

    Board_initSPI(); pinHandle = PIN_open(&pinState, pinTable); if (!pinHandle) { System_abort("Error initializing board LED pins\n"); } /* Configure task. */ Task_Params taskParams; Task_Params_init(&taskParams); taskParams.stack = myTaskStack; taskParams.stackSize = sizeof(myTaskStack); Task_construct(&myTaskStruct, taskFxn, &taskParams, NULL); System_printf("End Setup\n"); } /* * ======== main ======== */ Int main() { setup(); // to enable interrupts and start the scheduler and kick BIOS into gear. BIOS_start(); // this should never be called return (0); }

    Regards,

    Michel

  • Good catch, Michel. Thanks for pitching in. That is correct - BIOS_start() should be called in main(), and the SPI calls handled in a Task context after starting the kernel. Carlos, could you try Michel's suggestions and let us know how it goes?

    Best regards,
    Vincent
  • Thank you very much.

    Now the code runs perfectly. I'm starting to program this platform and I have many doubts.


    Thanks again.

  • Hi All,

    I have a very similar issue with the CC2650 launchpad.

    Basically, all the SPI functions run successfully from a task (with the default priority), and when I get to the SPI_transfer the program gets stuck.

    My goal is to communicate with the on-chip flash (MX25R8035F), which corresponds to the PIN Board_SPI_FLASH_CS, but I also tried communicating with the LEDs.

    Any idea what's wrong? Would highly appreciate any help.

    Thanks

    Here's my last attempt, which is pretty much the same as the one in this post:

    /*
     *  ======== 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/Clock.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/SPI.h>
    #include <ti/drivers/spi/SPICC26XXDMA.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #define delay_ms(i) 	Task_sleep( ((i) * 1000) / Clock_tickPeriod )
    #define TASKSTACKSIZE   512
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    static SPI_Handle spiHandle = NULL;
    static SPI_Params spiParams;
    SPI_Transaction spiTransaction;
    
    
    static PIN_Handle hFlashPin = NULL;
    static PIN_State flashPinState;
    static PIN_Config BoardFlashPinTable[] =
    {
        Board_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN, // Ext. flash chip select
        PIN_TERMINATE
    };
    
    
    
    Void taskFxn(UArg arg0, UArg arg1)
    {
    	System_printf("Start SPI task\n");
    
    	SPI_Params_init(&spiParams);
    	spiParams.transferMode = SPI_MODE_BLOCKING;
    	spiParams.mode = SPI_MASTER;
    	spiParams.bitRate = 1000000;
    	spiHandle = SPI_open(Board_SPI0, &spiParams);
    
    	while (1) {
    		delay_ms(2000);
    		const uint8_t wbuf[] = {0x90, 0xFF, 0xFF, 0x00};
    		uint8_t rbuf[2];
    		int ret = 0;
    
    		SPI_Transaction masterTransaction;
    		masterTransaction.count  = sizeof(wbuf);
    		masterTransaction.txBuf  = (void*)wbuf;
    		masterTransaction.arg    = NULL;
    		masterTransaction.rxBuf  = NULL;
    		ret = SPI_transfer(spiHandle, &masterTransaction) ? 0 : -1;
    		System_printf("Returned %d\n",ret);
    
    		delay_ms(2000);
    		masterTransaction.count  = sizeof(rbuf);
    		masterTransaction.txBuf  = NULL;
    		masterTransaction.arg    = NULL;
    		masterTransaction.rxBuf  = rbuf;
    
    		ret = SPI_transfer(spiHandle, &masterTransaction) ? 0 : -1;
    		System_printf("Returned %d\n",ret);
    
    	}
    }
    
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initSPI();
    
        /* Construct Task  thread */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        Task_construct(&task0Struct, (Task_FuncPtr)taskFxn, &taskParams, NULL);
    
        hFlashPin = PIN_open(&flashPinState, BoardFlashPinTable);
        if (!hFlashPin) {
        	System_abort("Error initializing flash pin\n");
        }
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }

  • Hi Mega,

    At first glance, I do not see anything wrong in the code except for one thing:

    /* Construct Task  thread */
    Task_Params_init(&taskParams);
    taskParams.stackSize = TASKSTACKSIZE;
    // Change this line taskParams.stack = &task0Stack; // to this taskParams.stack = task0Stack; // &task0Stack[0];

    You were giving a pointer to where the pointer was located (instead of a pointer to the data itself).

    If that doesn't fix the problem, I would recommend that you open a new thread since this issue was previously resolved (which means that people will most likely overlook this thread).

    If you do post a new thread, include all the information mentioned above, and take a look at the ROV (in CCS, it's under the Tools menu). Under BIOS, you will see Scan for Errors, you can also look under Tasks to find any useful information that could help you figure out what the problem.

    Regards,

    Michel 

  • Thank you, Michel!

    I looked in the ROV view and I saw that the task stack size was not sufficient (it needed 516 bytes instead of 512).
    When I enlarged it, the problem was solved.