Hi
Based on the information in
I tried to implement a DMA channel that reloads timer5 with a given constant value upon each rising edge on GPIO PortE Pin5.
As far as i can tell, this works once (the TIMER_TAILR register shows the value copied by the DMA, not the one set using timerParams.period = TIMER_LOAD_PERIOD; but then my application seems to lock up somehow.
Is my approach completely wrong, or am I only slightly off?
Any help is greatly appreciated!
Timer Initialization:
/* ******************************************************************************************************************** * @brief Initialize board specific Timer settings. * * This function initializes the board specific Timer settings * * ********************************************************************************************************************/ void B134_332_initTimer(void) { Timer_Params timerParams; Error_Block eb; Error_init(&eb); Timer_Params_init(&timerParams); timerParams.period = TIMER_LOAD_PERIOD; timerParams.periodType = Timer_PeriodType_COUNTS; timerParams.startMode = Timer_StartMode_USER; timerParams.runMode = Timer_RunMode_ONESHOT; g_mlsTimer = Timer_create(5, ISR_Timer5, &timerParams, &eb); if (g_mlsTimer == NULL) { System_abort("Timer create failed"); } }
DMA Initialization:
uint8_t GPTMCTL_disable= 0x00; uint8_t GPTMCTL_enable = TIMER_CTL_TAEN; uint32_t GPTM_ILR= TIMER_DMA_LOAD_PEROID; // Temporary storage for the first uDMA primary task, for scatter-gather looping static tDMAControlTable uDMAsg_LoopTask; static tDMAControlTable uDMAsg_TaskList[] = { // // Task 2: copy source buffer to timer interval load // uDMATaskStructEntry(1, UDMA_SIZE_32, UDMA_SRC_INC_NONE, &GPTM_ILR, UDMA_DST_INC_NONE, (void*)(TIMER5_BASE + TIMER_O_TAILR), UDMA_ARB_1, UDMA_MODE_PER_SCATTER_GATHER ), // // Task 4: loop // uDMATaskStructEntry( 4, UDMA_SIZE_32, UDMA_SRC_INC_32, &uDMAsg_LoopTask, UDMA_DST_INC_32, &(B134_332_DMAControlTable[UDMA_CH14_GPIOE & 0x1f]), UDMA_ARB_4, UDMA_MODE_MEM_SCATTER_GATHER ) }; void initMLSFallingEdgeDetection(){ // initialize interrupt uDMAChannelDisable(UDMA_CH14_GPIOE & 0xffff); // Ensure channel is disabled before modifying register uDMAChannelAssign(UDMA_CH14_GPIOE); uDMAChannelAttributeDisable((UDMA_CH14_GPIOE & 0xffff)|UDMA_PRI_SELECT,UDMA_ATTR_ALL); uDMAChannelAttributeDisable((UDMA_CH14_GPIOE & 0xffff)|UDMA_ALT_SELECT,UDMA_ATTR_ALL); uDMAChannelAttributeEnable((UDMA_CH14_GPIOE & 0xffff)|UDMA_PRI_SELECT,UDMA_ATTR_USEBURST); uDMAChannelAttributeEnable((UDMA_CH14_GPIOE & 0xffff)|UDMA_ALT_SELECT,UDMA_ATTR_USEBURST); uDMAChannelScatterGatherSet(UDMA_CH14_GPIOE & 0xffff, 2, uDMAsg_TaskList, true); // Copy the primary control structure from the uDMA controltable uDMAsg_LoopTask.pvDstEndAddr = B134_332_DMAControlTable[UDMA_CH14_GPIOE & 0xffff].pvDstEndAddr; uDMAsg_LoopTask.pvSrcEndAddr = B134_332_DMAControlTable[UDMA_CH14_GPIOE & 0xffff].pvSrcEndAddr; uDMAsg_LoopTask.ui32Control = B134_332_DMAControlTable[UDMA_CH14_GPIOE & 0xffff].ui32Control; uDMAsg_LoopTask.ui32Spare = B134_332_DMAControlTable[UDMA_CH14_GPIOE & 0xffff].ui32Spare; Timer_setPeriod(g_mlsTimer, TIMER_LOAD_PERIOD); }
Starting the DMA:
void startFallingEdgeDetection(){ Timer_start(g_mlsTimer); GPIODMATriggerEnable(MLS_GPIO_PORT, MLS_GPIO_PIN); uDMAChannelEnable(UDMA_CH14_GPIOE & 0xffff); }