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