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.

TI RTOS SPI driver for CC2560

Other Parts Discussed in Thread: CC2650

Hello Experts,

I'm using TI-RTOS and SPI driver for CC2650 SPI slave mode, and have a question about SPICC26XXDMA.c in the following install path.

C:\ti\tirtos_simplelink_2_11_01_09\packages\ti\drivers\spi

In SPICC26XXDMA_csnCallback function of SPICC26XXDMA.c, SPICC26XXDMA_transferCancel is there.

[Question]

Could you tell me how to reduce the execution time for SPICC26XXDMA_transferCancel for SPI slave communication?

*  ======== SPICC26XXDMA_csnDeassertCallback ========
 *  Slave mode optional callback function for when the CSN is deasserted
 *
 *  @pre    Function assumes that the handle is not NULL
 */
static void SPICC26XXDMA_csnCallback(PIN_Handle handle, PIN_Id pinId)
{
    SPICC26XX_Object        *object;
    SPI_Handle              spiHandle;
    PIN_Config              csnConfig;

    /* Get the pointer to the SPI object */
    spiHandle = (SPI_Handle) PIN_getUserArg(handle);
    object    = spiHandle->object;

    /* Get current CSN config */
    csnConfig = PIN_getConfig(object->csnPin);

    /* Disable all interrupts */
    PIN_setInterrupt(handle, object->csnPin);

    /* Cancel transfer if POSEDGE interrupt */
    /* TODO: Consider doing this in a SWI */
    if ((csnConfig & PIN_IRQ_POSEDGE) == PIN_IRQ_POSEDGE) {
        /* Indicate why the transaction completed */
        object->currentTransaction->status = SPI_TRANSFER_CSN_DEASSERT;
extern void appNotifySpiDone(void);
extern uint16_t transfer_done_flag;
extern PIN_Handle hGpioPin;
        appNotifySpiDone();
        PIN_setOutputValue(hGpioPin, Board_IRQ, Board_PIN_INACTIVE);
        transfer_done_flag = 0;
        /* Cancel the current transaction */
        SPICC26XXDMA_transferCancel(spiHandle);
    }
}

[Background]

This function is called every time CSN deassert, and this call take a lot of time to finish it. 

Now, my customer have to reduce the time between CSN deassert and assert from SPI master as fast as possible on u second order. But it take a time about 100usec to accept the next CSN assert(low) and recieve SPI data from master.

If external MCU(SPI master) assert CSN and transfer data within 100usec since CSN deassert, SPI command is not accepted by CC2650. Customer want to reduce this interval time to access from SPI master as much as possible.

[Evaluation Result]

As a trial, I did comment out this function from SPIICC26XXDMA_csnCallback, but SPI did not operate correctly since next access.

Second, I did comment out some function call in SPICC26XXDMA_transferCancel to reduce execution time, and some function(Red character) is deleted and operation correctly, but it reduce the execution time only 5usec(result was 95usec from 100usec). When I did comment out the other function call, SPI also did not operate correctly since next access.

void SPICC26XXDMA_transferCancel(SPI_Handle handle) {
    SPICC26XX_Object          *object;
    SPI_Transaction           *msg;
    SPICC26XX_HWAttrs const   *hwAttrs;
    volatile tDMAControlTable *dmaControlTableEntry;
    unsigned int              key;

    /* Get the pointer to the object and hwAttrs */
    object = handle->object;
    hwAttrs = handle->hwAttrs;

    /* Check if a transfer is in progress */
    key = Hwi_disable();

    /* Check if there is an active transaction */
    if(!(object->currentTransaction)) {
        Hwi_restore(key);
        return;
    }
    Hwi_restore(key);

    /* Disable the SPI module */
    SSIDisable(hwAttrs->baseAddr);

    /* Disable SPI TX/RX DMA and clear DMA done interrupt just in case it finished */
    SSIDMADisable(hwAttrs->baseAddr, SSI_DMA_TX | SSI_DMA_RX);
    UDMACC26XX_clearInterrupt(object->udmaHandle, (hwAttrs->rxChannelBitMask) | (hwAttrs->txChannelBitMask));

    /* Disable and clear any pending interrupts */
    SSIIntDisable(hwAttrs->baseAddr, SSI_RXOR);
    SSIIntClear(hwAttrs->baseAddr, SSI_RXOR);

    /* Clear out the FIFO by resetting SPI module and re-initting */
    HapiResetPeripheral(hwAttrs->baseAddr == SSI0_BASE ? PRCM_PERIPH_SSI0 : PRCM_PERIPH_SSI1);
    SPICC26XXDMA_initHw(handle);

    /* Ensure flash is available if TX buffer is in flash. Flash starts with 0x0..*/
    if( ( (uint32_t)(object->currentTransaction->txBuf) & 0xF0000000) == 0x0) {
      Power_releaseConstraint(Power_NEED_FLASH_IN_IDLE);
    }

    /* Release constraint since transaction is done */
    Power_releaseConstraint(Power_SB_DISALLOW);

    /* Mark the transaction as failed if we didn't end up here due to a CSN deassertion */
    if (object->currentTransaction->status != SPI_TRANSFER_CSN_DEASSERT) {
        object->currentTransaction->status = SPI_TRANSFER_FAILED;
    }

    /* Disable the UDMA channels */
    UDMACC26XX_channelDisable(object->udmaHandle, (hwAttrs->rxChannelBitMask) | (hwAttrs->txChannelBitMask));

    /* Update the SPI_Transaction.count parameter */
    /* rxChannel always finishes after txChannel so remaining bytes of the rxChannel is used to update count */
    dmaControlTableEntry = (hwAttrs->baseAddr == SSI0_BASE ? &dmaRxControlTableEntry0 : &dmaRxControlTableEntry1);
    object->currentTransaction->count -= UDMACC26XX_GET_TRANSFER_SIZE(dmaControlTableEntry->ui32Control);

    /* Use a temporary transaction pointer in case the callback function
     * attempts to perform another SPI_transfer call
     */
    msg = object->currentTransaction;

    /* Indicate we are done with this transfer */
    object->currentTransaction = NULL;

    Log_print2(Diags_USER1,"SPI:(%p) DMA transaction: %p cancelled",
                            hwAttrs->baseAddr, (UArg)msg);

    /* Perform callback */
    object->transferCallbackFxn(handle, msg);

    /* Transaction was successfully canceled */
    return;
}

Best Regards,

Kengo Furuya

  • Hi Kengo,

    A few questions. What are the transfer times you are seeing and what is the goal ? Can you explain your setup in more detail ? In particular, things like what bit rate have you configured for the SPI transfers. Based on your setup details maybe we can provide some suggestions on speeding up transfers.

    I presume the SPICC26XXDMA_transferCancel() function is doing the absolute necessary stuff but I will discuss with the TI-RTOS SPI driver experts if they see scope for further optimization and get back to you.

    Best,
    Ashish
  • Hi Ashish,

    In ideal, target is no wait, but real target is within 50usec at least. Now SPI transfer rate is 3.57MHz, but maximum rate is 4MHz. For system setup, I attached block diagram.

    Application is smart meter. CC2650 output IRQ to external MCU. After that, some command and read/write communication is occurred between MCU and CC2650 via SPI, and finally MCU transfer the RF packet to RF transceiver through CC2650.

    Customer need to reduce transfer time from first IRQ is occurred. So they are trying to reduce CC2650 execution time other than SPI. But, now SPI access is dominant time in the system. 

    Best Regards,

    Kengo Furuya

  • Hi Kengo,

    Its unfortunately not possible to further optimize the SPICC26XXDMA_transferCancel() function. The function has to perform certain tasks like clearing the FIFOs and resetting the peripheral which are time consuming but important to ensure SPI can continue to function correctly for all future transactions.

    Can you share why your customer needs to call transferCancel() ? Maybe we can find an alternative to calling transferCancel().

    Also, I presume you are using non-instrumented TI-RTOS library. Is that correct ? If not, you should switch from instrumented to non-instrumented.

    Best,
    Ashish
  • Hi Ashish,

    Can you share why your customer needs to call transferCancel() ?
    Because they use SPICC26XXDMA_csnCallback() in SPICC26XXDMA.c, transferCancel is called in csnCallback.
    What is non-instrumented TI-RTOS library? I'm not sure about both non-instrumented and instrumented.
    I'm just using the following driver in TI-RTOS folder.
    C:\ti\tirtos_simplelink_2_11_01_09\packages\ti\drivers\spi

    Best Regards,
    Kengo Furuya

  • The non-instrumented library can be selected from the TI-RTOS - Driver Options window in the cfg GUI as shown below:

    Alternatively, you can add the below lines to your cfg script to change the library type:

    /* ================ Driver configuration ================ */
    var TIRTOS = xdc.useModule('ti.tirtos.TIRTOS');
    TIRTOS.libType = TIRTOS.LibType_NonInstrumented

    Best,

    Ashish

  • Hi Ashish,What is difference between non-instrumented and instrumented?Regards,
    Kengo Furuya
  • Kengo Furuya said:

    What is non-instrumented TI-RTOS library?

    Its a release version of the library with logging/asserts disabled.

    Best,

    Ashish

  • Hi Kengo,

    Kengo Furuya said:

    Can you share why your customer needs to call transferCancel() ? 

    Because they use SPICC26XXDMA_csnCallback() in SPICC26XXDMA.c, transferCancel is called in csnCallback.

    Instead of calling transferCancel() to ensure the slave is ready for the next transfer, can you use a different mechanism for ensuring the slave is ready ? For example, the slave can use a GPIO pin to signal the master that it is ready for a transfer.

    Best,
    Ashish

  • Ashish,

    Thank you for your suggestion, but unfortunately, customer is not prepare GPIO pin on CC2650 to tell the ready for the next transfer. Now, only csn is there on thier system.

    Regards,

    Kengo Furuya

  • Ashish,

    >Its a release version of the library with logging/asserts disabled.
    I confirmed they use release version, logging/asserts was already disabled.

    Regards,

    Kengo Furuya