Howdy,
I'm trying to use Port D on the TM4C with Tivaware as a digital output port with the data to write stored in RAM. The data should be transferred from waveform.array (a uint8_t array) one byte at a time to Port D bit band address (bits 0 to 5) when Timer 1A expires and the transfer should last for the size of the array (waveform.size). The goal is to use very little CPU to output a waveform onto Port D bits 0 to 5 with hardware timed precision until the waveform array is exhausted.
My latest attempt is embedded in the post. The timer works fine and I'm able to verify it works by checking an interrupt function (not shown), but I'm getting an unspecified error in the "udma_error" function.
Questions:
- Is the goal even possible using uDMA?
- How do I determine uDMA errors other than an error occurred?
- The setup of the channels in both the Tivaware and TM4C documentation is confusing, do I use GPIO D Channel or Timer A channel? Neither seem to work.
#define MDI_V2_DAC (*((volatile unsigned long *)0x400070FC)) // Port D bits 5-0
void udma_error(){
uint32_t error = uDMAErrorStatusGet();
uDMAErrorStatusClear();
}
void udma_timer_test(){
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_TIMER1))
{
}
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
while(!SysCtlPeripheralReady(SYSCTL_PERIPH_UDMA))
{
}
uDMAEnable();
uDMAControlBaseSet(dma_table);
uDMAChannelAttributeDisable(UDMA_CHANNEL_TMR1A, 0);
uDMAIntRegister(INT_UDMAERR, udma_error);
//This configure the DMA to fire when Timer 1A times out, and increments the
//memory to increment by 8 bytes, and the destination (GPIO to not change).
//In short, when Timer 1A expires, it outputs a new value to the GPIO
uDMAChannelControlSet(UDMA_CHANNEL_TMR1A | UDMA_PRI_SELECT,
UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
//Configure Timer 0 to be split pair timer, with timer A counting up
TimerConfigure(TIMER1_BASE, (TIMER_CFG_A_PERIODIC | TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_PERIODIC));
//TimerIntRegister(TIMER1_BASE, TIMER_A, mdi_waveform_interrupt);
//Increment on pos edge of the clock
TimerControlEvent(TIMER1_BASE, TIMER_A, TIMER_EVENT_POS_EDGE);
uDMAChannelTransferSet(UDMA_CHANNEL_TMR1A | UDMA_PRI_SELECT,
UDMA_MODE_BASIC, waveform.array, MDI_V2_DAC,
waveform.size);
//Enable the timer interrupt
TimerIntEnable(TIMER1_BASE, TIMER_TIMA_TIMEOUT);
//Set that Timer 1A timeout triggers a DMA
TimerDMAEventSet(TIMER1_BASE, TIMER_DMA_TIMEOUT_A);
//Enable DMA for Timer 1A
uDMAChannelEnable(UDMA_CHANNEL_TMR1A);
//Enable the timer
TimerEnable(TIMER1_BASE, TIMER_A);
}
Thank you for any help!
Austin