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.

AM625: Unable to start new SPI transfer after using MCSPI_transferCancel

Part Number: AM625
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

We are transferring quite a lot of data over SPI, and every now and then, the SPI transfer fails. We want to recover gracefully, and tried calling MCSPI_transferCancel. But when we do, the next time we try to call MCSPI_transfer, we get the following error:

ASSERT: 10.290044s: mcspi/v0/dma/udma/mcspi_dma_udma.c:MCSPI_udmaConfigPdmaRx:511: UDMA_SOK == retVal failed !!!

Is there some cleanup that is not done properly?

Relevant configuration and code included below. This is mcu_plus_sdk_am62x version 11.00

Best regards,

Endre

/* MCSPI atrributes */

static MCSPI_Attrs gMcspiAttrs[CONFIG_MCSPI_NUM_INSTANCES] =
{
{
.baseAddr = CSL_MCSPI1_CFG_BASE,
.inputClkFreq = 50000000U,
.intrNum = 205,
#ifdef BUILD_C7X
.eventId = ,
#endif
.operMode = MCSPI_OPER_MODE_DMA,
.intrPriority = 4U,
.chMode = MCSPI_CH_MODE_SINGLE,
.pinMode = MCSPI_PINMODE_4PIN,
.initDelay = MCSPI_INITDLY_0,
},
};
static Udma_InitPrms gUdmaInitPrms[CONFIG_UDMA_NUM_INSTANCES] =
{
{
.instId = UDMA_INST_ID_PKTDMA_0,
.skipGlobalEventReg = FALSE,
.virtToPhyFxn = Udma_defaultVirtToPhyFxn,
.phyToVirtFxn = Udma_defaultPhyToVirtFxn,
},
};
MCSPI_OpenParams gMcspiOpenParams[CONFIG_MCSPI_NUM_INSTANCES] =
{
{
.transferMode = MCSPI_TRANSFER_MODE_CALLBACK,
.transferTimeout = SystemP_WAIT_FOREVER,
.transferCallbackFxn = SPI0_callbackFxn,
.msMode = MCSPI_MS_MODE_SLAVE,
.mcspiDmaIndex = 0,
},
};
/* MCSPI Driver Channel Configurations */
MCSPI_ChConfig gConfigMcspi0ChCfg[CONFIG_MCSPI0_NUM_CH] =
{
{
.chNum = MCSPI_CHANNEL_0,
.frameFormat = MCSPI_FF_POL0_PHA0,
.bitRate = 1000000,
.csPolarity = MCSPI_CS_POL_LOW,
.trMode = MCSPI_TR_MODE_RX_ONLY,
.inputSelect = MCSPI_IS_D0,
.dpe0 = MCSPI_DPE_DISABLE,
.dpe1 = MCSPI_DPE_DISABLE,
.slvCsSelect = MCSPI_SLV_CS_SELECT_0,
.startBitEnable = FALSE,
.startBitPolarity = MCSPI_SB_POL_LOW,
.csIdleTime = MCSPI_TCS0_0_CLK,
.defaultTxData = 0x0U,
.txFifoTrigLvl = 1U,
.rxFifoTrigLvl = 8U,
},
};
MCSPI_OpenParams gMcspiOpenParams[CONFIG_MCSPI_NUM_INSTANCES] =
{
{
.transferMode = MCSPI_TRANSFER_MODE_CALLBACK,
.transferTimeout = SystemP_WAIT_FOREVER,
.transferCallbackFxn = SPI0_callbackFxn,
.msMode = MCSPI_MS_MODE_SLAVE,
.mcspiDmaIndex = 0,
},
};
/* MCSPI Driver Channel Configurations */
MCSPI_ChConfig gConfigMcspi0ChCfg[CONFIG_MCSPI0_NUM_CH] =
{
{
.chNum = MCSPI_CHANNEL_0,
.frameFormat = MCSPI_FF_POL0_PHA0,
.bitRate = 1000000,
.csPolarity = MCSPI_CS_POL_LOW,
.trMode = MCSPI_TR_MODE_RX_ONLY,
.inputSelect = MCSPI_IS_D0,
.dpe0 = MCSPI_DPE_DISABLE,
.dpe1 = MCSPI_DPE_DISABLE,
.slvCsSelect = MCSPI_SLV_CS_SELECT_0,
.startBitEnable = FALSE,
.startBitPolarity = MCSPI_SB_POL_LOW,
.csIdleTime = MCSPI_TCS0_0_CLK,
.defaultTxData = 0x0U,
.txFifoTrigLvl = 1U,
.rxFifoTrigLvl = 8U,
},
};
MCSPI_DmaChConfig gConfigMcspi0DmaChCfg[CONFIG_MCSPI0_NUM_CH] =
{
{
.txChHandle = &gMcspi0UdmaTxChObj0,
.rxChHandle = &gMcspi0UdmaRxChObj0,
.cqTxEvtHandle = &gMcspi0UdmaCqTxEventObjCh0,
.cqRxEvtHandle = &gMcspi0UdmaCqRxEventObjCh0,
.txHpdMem = &gMcspi0UdmaTxHpdMemCh0,
.rxHpdMem = &gMcspi0UdmaRxHpdMemCh0,
.hpdMemSize = MCSPI_UDMA_TEST_DESC_SIZE,
.txRingMem = &gMcspi0UdmaTxRingMemCh0,
.rxRingMem = &gMcspi0UdmaRxRingMemCh0,
.ringMemSize = MCSPI_UDMA_TEST_RING_MEM_SIZE,
.ringElemCnt = MCSPI_UDMA_TEST_RING_ENTRIES,
.rxEvtNum = UDMA_PDMA_CH_MAIN0_MCSPI1_CH0_RX,
.txEvtNum = UDMA_PDMA_CH_MAIN0_MCSPI1_CH0_TX,
.isOpen = FALSE,
},

};
Main loop:
MCSPI_Transaction_init(&spiTransaction);
spiTransaction.channel = gConfigMcspi0ChCfg[0].chNum;
spiTransaction.dataSize = 8U;
spiTransaction.csDisable = TRUE;
// Todo: Possible optimization is to use 16 or 32 bit transfers instead of 8 bit transfers
spiTransaction.count = BYTES_PER_BLOCK / (spiTransaction.dataSize/8);
spiTransaction.txBuf = NULL;
spiTransaction.rxBuf = (void *)spi_rx_buffer;
spiTransaction.args = &gMcspiISRDoneSem; /* Pass semaphore */

uint64_t startTimeInUSec, elapsedTimeInUsecs;
startTimeInUSec = ClockP_getTimeUsec();
*spi_ctrl_block = 0;
// Start first block transfer over spi/dma, next blocks are started by ISR (SPI0_callbackFxn)
spiTransaction.rxBuf = (void *)spi_rx_buffer;
DebugP_log("Starting transfer\r\n");
transferOK = MCSPI_transfer(gMcspiHandle[CONFIG_MCSPI0], &spiTransaction);
if (SystemP_SUCCESS != transferOK) {
DebugP_log("Transfer failed\r\n");
DebugP_assert(FALSE); /* MCSPI transfer failed!! */
}

// Wait until all blocks are received (semaphore is posted by ISR)
// status = SemaphoreP_pend(&gMcspiISRDoneSem, SystemP_WAIT_FOREVER);

status = SemaphoreP_pend(&gMcspiISRDoneSem, spi_timeout_ticks); // 80ms timeout
if (SystemP_SUCCESS != status) {
DebugP_log("Timeout waiting for full transfer (%d/%d blocks)\r\n", *spi_ctrl_block, BLOCKS_PER_TRANSFER);
status =MCSPI_transferCancel(gMcspiHandle[CONFIG_MCSPI0]);
}
ISR:
void SPI0_callbackFxn(MCSPI_Handle handle,
MCSPI_Transaction *transaction)
{
SemaphoreP_Object *semObj;

if((NULL != transaction) &&
(MCSPI_TRANSFER_COMPLETED == transaction->status))
{
*spi_ctrl_block += 1;
// Test code to simulate a missed block:
//if (tx_count == 100 && *spi_ctrl_block == 32) {
//*spi_ctrl_block -= 1;
//tx_count++;
//}
if (*spi_ctrl_block < BLOCKS_PER_TRANSFER) {
// Trigger next transfer
transaction->rxBuf = (void *)(spi_rx_buffer + *spi_ctrl_block*BYTES_PER_BLOCK);
int32_t transferOK = MCSPI_transfer(handle, transaction);
if (SystemP_SUCCESS != transferOK) {
DebugP_log("Transfer failed\r\n");
DebugP_assert(FALSE); /* MCSPI transfer failed!! */
}
} else {
// Last transfer completed, signal main task
semObj = (SemaphoreP_Object *) transaction->args;
if(NULL != semObj)
{
SemaphoreP_post(semObj);
}
tx_count++;
}
} else {
DebugP_log("Failed in callback %d\r\n", transaction->status);
}
}