HI TI team:
I rework adc_soc_continuous_dma.c and implemented 32 reads with some periodicity and it works one time, it triggers DMA interrupt, and it is OK for me.
But I can't figure out how to reload this by demand.
I found another example in edma_interrupt_transfer.c:
for(loopCnt = 0; loopCnt < (EDMA_TEST_B_COUNT * EDMA_TEST_C_COUNT); loopCnt++)
{
EDMA_enableTransferRegion(
baseAddr, regionId, dmaCh, EDMA_TRIG_MODE_MANUAL);
SemaphoreP_pend(&gEdmaTestDoneSem, SystemP_WAIT_FOREVER);
}
And I tried to put this logic to adc_soc_continuous_dma example, but unfortunately, it does not help.
void adc_soc_continuous_dma_main(void *args)
{
int32_t status;
Edma_IntrObject intrObj;
uint32_t loopCnt = 0;
uint32_t tccAlloc0, tccAlloc1, tccAlloc2;
DebugP_log("ADC Continuous DMA transfer Test Started ...\r\n");
/* Initialize both the result buffers with zeroes */
for(loopCnt = 0U; loopCnt < RESULTS_BUFFER_SIZE; loopCnt++)
{
gUnusedBuffer[loopCnt] = 0U;
gAdc0DataBuffer[loopCnt] = 0U;
gAdc1DataBuffer[loopCnt] = 0U;
gAdc2DataBuffer[loopCnt] = 0U;
}
/* Perform a cache write back to the result buffers */
CacheP_wb((void *)gUnusedBuffer, RESULTS_BUFFER_SIZE*2, CacheP_TYPE_ALL);
CacheP_wb((void *)gAdc0DataBuffer, RESULTS_BUFFER_SIZE*2, CacheP_TYPE_ALL);
CacheP_wb((void *)gAdc1DataBuffer, RESULTS_BUFFER_SIZE*2, CacheP_TYPE_ALL);
CacheP_wb((void *)gAdc2DataBuffer, RESULTS_BUFFER_SIZE*2, CacheP_TYPE_ALL);
/* Create a semaphore to signal EDMA transfer completion */
status = SemaphoreP_constructBinary(&gEdmaTransferDoneSem, 0);
DebugP_assert(SystemP_SUCCESS == status);
uint32_t regionId0;
uint32_t regionId1;
uint32_t regionId2;
/* Configure DMA channels to transfer both ADC results */
App_dmaConfigure_(gAdc0DataBuffer, RESULTS_BUFFER_SIZE, gEdmaHandle[0],
ADC0_EDMA_CHANNEL, CONFIG_ADC0_RESULT_BASE_ADDR, &tccAlloc0, ®ionId0);
App_dmaConfigure_(gAdc1DataBuffer, RESULTS_BUFFER_SIZE, gEdmaHandle[0],
ADC1_EDMA_CHANNEL, CONFIG_ADC1_RESULT_BASE_ADDR, &tccAlloc1, ®ionId1);
App_dmaConfigure_(gAdc2DataBuffer, RESULTS_BUFFER_SIZE, gEdmaHandle[0],
ADC2_EDMA_CHANNEL, CONFIG_ADC2_RESULT_BASE_ADDR, &tccAlloc2, ®ionId2);
/* Register interrupt */
intrObj.tccNum = tccAlloc0;
intrObj.cbFxn = &App_dmach0ISR;
intrObj.appData = (void *) &gEdmaTransferDoneSem;
status = EDMA_registerIntr(gEdmaHandle[0], &intrObj);
DebugP_assert(status == SystemP_SUCCESS);
/* Clear ADC Interrupt status */
ADC_clearInterruptStatus(gAdc0baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(gAdc1baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(gAdc2baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc0baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc1baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc2baseAddr, ADC_INT_NUMBER1);
/* RTI timer for trigering SOC ADC */
TimerP_Params timerParams;
TimerP_Params_init(&timerParams);
timerParams.periodInUsec = 0;
timerParams.periodInNsec = 1116;
TimerP_setup(gTimerBaseAddr[CONFIG_TIMER_AI_MON], &timerParams);
TimerP_start(gTimerBaseAddr[CONFIG_TIMER_AI_MON]);
/*
* Wait while DMA transfers ADC conversion results to buffer.
*/
SemaphoreP_pend(&gEdmaTransferDoneSem, SystemP_WAIT_FOREVER);
DebugP_log("test %u passed!!\r\n", __LINE__);
loopCnt = 0;
/* Print few elements from the result buffer */
while(loopCnt < RESULTS_BUFFER_SIZE)
{
DebugP_log("%d : %d : %d\r\n", gAdc0DataBuffer[loopCnt], gAdc1DataBuffer[loopCnt], gAdc2DataBuffer[loopCnt]);
loopCnt += 1;
}
memset(gAdc0DataBuffer, 0, sizeof(gAdc0DataBuffer));
memset(gAdc1DataBuffer, 0, sizeof(gAdc0DataBuffer));
memset(gAdc2DataBuffer, 0, sizeof(gAdc0DataBuffer));
/* Clear ADC Interrupt status */
ADC_clearInterruptStatus(gAdc0baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(gAdc1baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptStatus(gAdc2baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc0baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc1baseAddr, ADC_INT_NUMBER1);
ADC_clearInterruptOverflowStatus(gAdc2baseAddr, ADC_INT_NUMBER1);
EDMA_enableTransferRegion(EDMA_getBaseAddr(gEdmaHandle[0]), regionId0, ADC0_EDMA_CHANNEL,
EDMA_TRIG_MODE_EVENT);
EDMA_enableTransferRegion(EDMA_getBaseAddr(gEdmaHandle[0]), regionId1, ADC1_EDMA_CHANNEL,
EDMA_TRIG_MODE_EVENT);
EDMA_enableTransferRegion(EDMA_getBaseAddr(gEdmaHandle[0]), regionId2, ADC2_EDMA_CHANNEL,
EDMA_TRIG_MODE_EVENT);
TimerP_start(gTimerBaseAddr[CONFIG_TIMER_AI_MON]);
/*
* Wait while DMA transfers ADC conversion results to buffer.
*/
SemaphoreP_pend(&gEdmaTransferDoneSem, SystemP_WAIT_FOREVER);
//
//
//
// Can not reach there
//
//
//
DebugP_log("test %u passed!!\r\n", __LINE__);
loopCnt = 0;
/* Print few elements from the result buffer */
while(loopCnt < RESULTS_BUFFER_SIZE)
{
DebugP_log("%d : %d : %d\r\n", gAdc0DataBuffer[loopCnt], gAdc1DataBuffer[loopCnt], gAdc2DataBuffer[loopCnt]);
loopCnt += 1;
}
}
uint16_t App_dmaConfigure_(
const uint16_t *table, uint16_t table_size,
EDMA_Handle dma_handle, uint32_t dma_ch,
uint32_t adc_base, uint32_t *tccAlloc, uint32_t *regionId)
{
uint32_t baseAddr;
EDMACCPaRAMEntry empty_edmaParam, edmaParam;
uint32_t empty_dmaCh, dmaCh, empty_tcc, tcc, empty_param, param;
// EDMACCPaRAMEntry empty_edmaParam;
// uint32_t empty_dmaCh, empty_tcc, empty_param;
int32_t testStatus = SystemP_SUCCESS;
/* Enable only TC and ITC chaining on dmaCh0.
TC and ITC interrupt enable not required. */
uint32_t chainOptions = (EDMA_OPT_TCCHEN_MASK |
EDMA_OPT_ITCCHEN_MASK);
baseAddr = EDMA_getBaseAddr(gEdmaHandle[0]);
DebugP_assert(baseAddr != 0);
*regionId = EDMA_getRegionId(gEdmaHandle[0]);
DebugP_assert(*regionId < SOC_EDMA_NUM_REGIONS);
empty_dmaCh = dma_ch;
testStatus = EDMA_allocDmaChannel(gEdmaHandle[0], &empty_dmaCh);
DebugP_assert(testStatus == SystemP_SUCCESS);
/* typically allocates the next available channel */
empty_tcc = EDMA_RESOURCE_ALLOC_ANY;
testStatus = EDMA_allocTcc(gEdmaHandle[0], &empty_tcc);
DebugP_assert(testStatus == SystemP_SUCCESS);
empty_param = EDMA_RESOURCE_ALLOC_ANY;
testStatus = EDMA_allocParam(gEdmaHandle[0], &empty_param);
DebugP_assert(testStatus == SystemP_SUCCESS);
dmaCh = EDMA_RESOURCE_ALLOC_ANY;
testStatus = EDMA_allocDmaChannel(gEdmaHandle[0], &dmaCh);
DebugP_assert(testStatus == SystemP_SUCCESS);
tcc = EDMA_RESOURCE_ALLOC_ANY;
testStatus = EDMA_allocTcc(gEdmaHandle[0], &tcc);
DebugP_assert(testStatus == SystemP_SUCCESS);
/* Passing back the Channel parameter to register the interrupt ISR*/
*tccAlloc = tcc;
param = EDMA_RESOURCE_ALLOC_ANY;
testStatus = EDMA_allocParam(gEdmaHandle[0], ¶m);
DebugP_assert(testStatus == SystemP_SUCCESS);
/* Request channel */
EDMA_configureChannelRegion(baseAddr, *regionId, EDMA_CHANNEL_TYPE_DMA,
empty_dmaCh, empty_tcc, empty_param, EDMA_TEST_EVT_QUEUE_NO);
/* Program Param Set */
EDMA_ccPaRAMEntry_init(&empty_edmaParam);
empty_edmaParam.srcAddr = (uint32_t) SOC_virtToPhy((void *)(adc_base+CSL_ADC_RESULT_ADCRESULT0));
empty_edmaParam.destAddr = (uint32_t) SOC_virtToPhy((void *)gUnusedBuffer);
empty_edmaParam.aCnt = (uint16_t) 2;
empty_edmaParam.bCnt = (uint16_t) table_size;
empty_edmaParam.cCnt = (uint16_t) 1;
empty_edmaParam.bCntReload = 0;
empty_edmaParam.srcBIdx = (int16_t) EDMA_PARAM_BIDX(0);
empty_edmaParam.destBIdx = (int16_t) EDMA_PARAM_BIDX(2);
empty_edmaParam.srcCIdx = (int16_t) 0;
empty_edmaParam.destCIdx = (int16_t) 0;
empty_edmaParam.linkAddr = 0xFFFFU;
empty_edmaParam.srcBIdxExt = (int8_t) EDMA_PARAM_BIDX_EXT(0);
empty_edmaParam.destBIdxExt = (int8_t) EDMA_PARAM_BIDX_EXT(2);
empty_edmaParam.opt = (EDMA_OPT_TCINTEN_MASK | EDMA_OPT_ITCINTEN_MASK |
((((uint32_t)empty_tcc) << EDMA_OPT_TCC_SHIFT) & EDMA_OPT_TCC_MASK));
/* Enabling in options for the,
the Transfer-complete Interrupt --> After total data is transferred
, Intermediate transfer complete interrupt --> After each A data chunk transfer is comeplete
this will be used for the chaining of the actual transfer.
*/
EDMA_setPaRAM(baseAddr, empty_param, &empty_edmaParam);
EDMA_configureChannelRegion(baseAddr, *regionId, EDMA_CHANNEL_TYPE_DMA,
dmaCh, tcc, param, EDMA_TEST_EVT_QUEUE_NO);
/* Program Param Set */
EDMA_ccPaRAMEntry_init(&edmaParam);
edmaParam.srcAddr = (uint32_t) SOC_virtToPhy((void *)(adc_base+CSL_ADC_RESULT_ADCRESULT0));
edmaParam.destAddr = (uint32_t) SOC_virtToPhy((void *)table);
edmaParam.aCnt = (uint16_t) 2;
edmaParam.bCnt = (uint16_t) table_size;
edmaParam.cCnt = (uint16_t) 1;
edmaParam.bCntReload = 0;
edmaParam.srcBIdx = (int16_t) EDMA_PARAM_BIDX(0);
edmaParam.destBIdx = (int16_t) EDMA_PARAM_BIDX(2);
edmaParam.srcCIdx = (int16_t) 0;
edmaParam.destCIdx = (int16_t) 0;
edmaParam.linkAddr = 0xFFFFU;
edmaParam.srcBIdxExt = (int8_t) EDMA_PARAM_BIDX_EXT(0);
edmaParam.destBIdxExt = (int8_t) EDMA_PARAM_BIDX_EXT(2);
edmaParam.opt = (EDMA_OPT_TCINTEN_MASK |
((((uint32_t)tcc) << EDMA_OPT_TCC_SHIFT) & EDMA_OPT_TCC_MASK));
/* Enabling the Interrupt for Transfer complete of all the data */
EDMA_setPaRAM(baseAddr, param, &edmaParam);
/* Chain the empty transfer to the actual transfer.
Chain options include Total transfer completion and intermediate channel completion flags
from empty channel*/
EDMA_chainChannel(baseAddr, empty_param, dmaCh, chainOptions);
/* Enabling the transfer region for empty channel for the trigger mode set in the Syscfg through
the DMA Xbars adn DMA TRIG Xbars.*/
EDMA_enableTransferRegion(baseAddr, *regionId, empty_dmaCh,
EDMA_TRIG_MODE_EVENT);
return testStatus;
}
void App_dmach0ISR(Edma_IntrHandle intrHandle, void *args)
{
SemaphoreP_Object *semObjPtr = (SemaphoreP_Object *)args;
DebugP_assert(semObjPtr != NULL);
TimerP_stop(gTimerBaseAddr[CONFIG_TIMER_AI_MON]);
/* Post the semaphore to signal end of DMA transfer */
SemaphoreP_post(semObjPtr);
}
Why App_dmach0ISR() calling once?
How to reload the transfer configuration? Or we should re-allocate resources for reinitialization DMA configuration and interrupt config, I doubt it is the correct way.
Regards!