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.

CCS/TM4C123AE6PM: General Purpose Timer to uDMA

Part Number: TM4C123AE6PM

Tool/software: Code Composer Studio

Hello,

I would like to use PC5 configured as GPIO_PC5_WT0CCP1 and capture the timer value of WTIMER0B on rising edge and automatically transfer the value on the timer to the uDMA every rising edge without have to reload or reset anything in software or use interrupts. Is this something that is possible? Currently I have the following code but I'm not sure that it is what I want or if I have it configured properly for what I would like to do. It looked like ping pong mode might be as close as I can get to continuous transfer but I just need to write the same value over and over no need for a buffer. The code listed below is only the code related to the GPIO, timer, and uDMA. Any assistance would be appreciated!!

HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x01;
HWREG(GPIO_PORTC_BASE + GPIO_O_AFSEL) |= 1;

ROM_GPIOPinConfigure(GPIO_PC5_WT0CCP1);
ROM_GPIOPinTypeTimer(GPIO_PORTC_BASE, GPIO_PIN_5);//qmet_V5_00

// Clear the commit and lock registers just to be safe.
HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY_DD;
HWREG(GPIO_PORTC_BASE + GPIO_O_CR) = 0x00;
HWREG(GPIO_PORTC_BASE + GPIO_O_LOCK) = 0;

ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); 

ROM_TimerConfigure(WTIMER0_BASE, TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_CAP_TIME_UP );
ROM_TimerControlEvent(WTIMER0_BASE,TIMER_B,TIMER_EVENT_POS_EDGE);

// enable uDMA must happen before configuration
ROM_uDMAEnable();

// Point at the control table to use for channel control structures.
ROM_uDMAControlBaseSet(pui8ControlTable);

// set up uDMA control settings to transfer data from WTIMER0B to location
ROM_uDMAChannelAttributeDisable(UDMA_CH11_WTIMER0B, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
ROM_uDMAChannelControlSet(UDMA_CH11_WTIMER0B | UDMA_PRI_SELECT, UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1);
ROM_uDMAChannelControlSet(UDMA_CH11_WTIMER0B | UDMA_ALT_SELECT, UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_NONE | UDMA_ARB_1);
ROM_uDMAChannelTransferSet(UDMA_CH11_WTIMER0B | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(WTIMER0_BASE + TIMER_B), &ulDutyTimer, sizeof(ulDutyTimer));
ROM_uDMAChannelTransferSet(UDMA_CH11_WTIMER0B | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(WTIMER0_BASE + TIMER_B), &ulDutyTimer, sizeof(ulDutyTimer));
ROM_uDMAChannelAttributeEnable(UDMA_CH11_WTIMER0B, UDMA_ATTR_USEBURST);

// enable uDMA channel
ROM_uDMAChannelEnable(UDMA_CH11_WTIMER0B);

ROM_TimerIntEnable(WTIMER0_BASE,TIMER_CAPB_EVENT);
ROM_TimerEnable(WTIMER0_BASE, TIMER_B);

  • It is certainly possible to use the uDMA to copy the edge capture value to RAM, but if you are only going to keep the latest value I'm not sure I see the purpose. If you configure the time in "Input Edge Time Mode", the value of the free running time will be captured and held in the GPTMTBR register until the next edge. If you are trying to keep the last two values in RAM so that you can compute the time difference, then using uDMA in PINGPONG mode makes more sense. You will need to take care that you can identify which is the latest capture when the free running timer overflows.
  • Other than Bob's comments, I also see that you are overwriting each other in the ping-pong mode. Your primary and alternate control setup are transferring data to the same CPU buffer. 

    ROM_uDMAChannelTransferSet(UDMA_CH11_WTIMER0B | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(WTIMER0_BASE + TIMER_B), &ulDutyTimer, sizeof(ulDutyTimer));

    ROM_uDMAChannelTransferSet(UDMA_CH11_WTIMER0B | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(WTIMER0_BASE + TIMER_B), &ulDutyTimer, sizeof(ulDutyTimer));