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.

CC2642R: SPI Callback mode not working while trying to switch from Blocking mode

Part Number: CC2642R

Hi,

I am trying to interface an external flash memory (for generic data storage) with the BLE peripheral software in CC2642R1. In the callback mode, the SPI seems to be fine when I set it up during initialization, but the Flash driver needs both blocking and nonblocking modes depending on the scenario. Hence I was trying to switch back and forth, but then it does not call the callback function after the first nonblocking transfer (determined from the Slave Select pin). Following are the relevant code snippets:

SPI_Handle spiHandle0;
SPI_Params SPI_customParams;

static void SimplePeripheral_init(void)
{
    ...
    GPIO_init();
    SPI_init();
    SPI_Params_init(&SPI_customParams);
    SPI_customParams.bitRate = 8000000;
    spiHandle0 = SPI_open(CONFIG_SPI_0, &SPI_customParams);
    external_flash_init(...);
}

static void SimplePeripheral_processAppMsg(spEvt_t *pMsg)
{
    ...
    switch (pMsg->event)
    {
    case SP_SPI0_EVT:
        spi_xfer_done = true;
        SPI_MEM_enable_blocking();
        ...
        break;
    ...
    }
    ...
}



void SimplePeripheral_SPI_CB(SPI_Handle spi, SPI_Transaction *tran)
{
    GPIO_write(GPIO_SPI_SS_MEM, 1);
    SimplePeripheral_enqueueMsg(SP_SPI0_EVT, NULL);
}

void SPI_MEM_enable_blocking()
{
    SPI_close(spiHandle0);
    SPI_customParams.transferCallbackFxn = NULL;
    SPI_customParams.transferMode = SPI_MODE_BLOCKING;
    spiHandle0 = SPI_open(CONFIG_SPI_0, &SPI_customParams);
}

void SPI_MEM_disable_blocking()
{
    SPI_close(spiHandle0);
    SPI_customParams.transferCallbackFxn = SimplePeripheral_SPI_CB;
    SPI_customParams.transferMode = SPI_MODE_CALLBACK;
    spiHandle0 = SPI_open(CONFIG_SPI_0, &SPI_customParams);
}

bool spi_nand_transfer(uint8_t const * p_tx_buffer, uint32_t tx_buffer_length, uint8_t * p_rx_buffer, uint32_t rx_buffer_length, bool block)
{
    bool retCode;
    
    if (!block)
        SPI_MEM_disable_blocking();
    
    SPI_Transaction MEMspiRW;
    MEMspiRW.count = rx_buffer_length ? rx_buffer_length : tx_buffer_length;
    MEMspiRW.txBuf = (void *)p_tx_buffer;
    MEMspiRW.rxBuf = (void *)p_rx_buffer;
    
    spi_xfer_done = false;
    GPIO_write(GPIO_SPI_SS_MEM, 0);
    
    retCode = SPI_transfer(spiHandle0, &MEMspiRW);
    
    if (block) {
        GPIO_write(GPIO_SPI_SS_MEM, 1);
        spi_xfer_done = true;
    }
    return retCode;
}

  • Hey Parvez,

    Which SDK are you using? I would first verify your code in a driver project like spimaster or spislave, and then integrate this to the simple_peripheral project. Have you done this?

    I've assigned an expert to help you further.

  • Hi Parvez,

    Here are links to the spimaster README and TI Drivers Runtime API for easy reference.  I don't quite understand why the Flash driver requires both blocking and non-blocking transfers as it is not necessary for the MX25R8035 external flash devices on-board LaunchPads, but it should be possible to switch between the two modes using the close/open approach you've implemented.  Have you attempted this with four-pin SPI mode instead, so that the SS pin is controlled by hardware instead of software?  If you can replicate behavior with the TI spimaster/spislave examples then it will be easier to debug.

    Regards,
    Ryan

  • Hi Ammar,

    I am using simplelink_cc13xx_cc26xx_sdk_5_30_01_01 SDK.

    As you suggested, I tried this on the spimaster project, still has the same behavior. I am putting more details on Ryan's reply.

  • Hi Ryan, 

    Actually, the driver was initially written for some other platform, which I modified to work with the CC2642, and the modified one works fine in blocking mode. The original implementation used the non-blocking mode for just the data write function (single page is 2048 bytes). So I am trying to do the same by switching modes. Basically, I am enabling the callback mode just for one function to keep the processor free for other interrupts, the rest of the driver still uses the blocking mode.

    I attempted this with four-pin SPI mode, but the hardware de-asserts the SS pin after every byte which is not compatible with the Flash memory's SPI protocol. 

    As Ammar and you suggested, I have tried it with the spimaster project. But the SPI is not calling the callback function when the transaction is complete.

  • Hi,

    Thanks for confirming that you see the same issue in a spimaster example.

    I notice that you have SPI_Transaction MEMspiRW; declared in scope of function spi_nand_transfer.
    You may want to re-consider this, as the SPI Driver states the following (can be found in SPI.h):

     *  From calling #SPI_transfer() until transfer completion, the #SPI_Transaction
     *  structure must stay persistent and must not be altered by application code.

    When spi_nand_transfer function exits, we cannot assume that MEMspiRW is persistent, which violates the above documented requirement.

    Can you run a simple test where SPI_Transaction is persistent?
    The simplest way would be to declare it as a global variable.

    Thanks,
    Toby

  • Thanks a lot! It is working perfectly now, after declaring the SPI_Transaction variable global.