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.

UDMA with little-endianness allows individual pointers in TM4C1294?

I am trying to get a "simultaneous" parallel transfer to differents ports at a time through the UDMA of TM4C1294. Firstly I built two triggers with the timeout of timer 2A for write in the ports N and F (where TM4C1294 has the LEDs) by the uDMA channels 4 and 6 respectively. For the LED states I used two arrays of variables named "Output" and "Output2" respectively. That worked fine. Now I'd like to build the same concept but I want to use only one array variable with double lenght instead of use two variables. So the output states of the port N will be the high-bytes of each position of the array and the output states of the port F would be the low bytes of each position of the array. But I can't work this properly. Is the little-endianness configuration  my problem? Thanks in advance. I will copy the codes of the two experiments.

CODE WORKS GOOD:

//*****************************************************************************
// DEFINES
//*****************************************************************************

void InitTimer(void);
void Timer2IntHandler(void);
void InitGPIO(void);
void InitUDMA(void);

#if defined(ewarm)
#pragma data_aligment=1024
uint8_t DMAcontroltable[1024];

#elif defined(ccs)
#pragma DATA_ALIGN(DMAcontroltable, 1024)
uint8_t DMAcontroltable[1024];

#else
uint8_t DMAcontroltable[1024] __attribute__ ((aligned(1024)));
#endif

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
// GLOBALS
//*****************************************************************************
static uint8_t OutputState[4], OutputState2[4];

static uint32_t g_ui32SysClock;
//*****************************************************************************
//
// Blink GPIOF with DMA
//
//*****************************************************************************
int
main(void)
{

uint32_t ui32Period;
uint32_t ui32SysClkFreq;

ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

InitTimer();
InitGPIO();
InitUDMA();

/*
* Sets the pins state for all LED states.
*/
OutputState[0] = 0x00;
OutputState[1] = 0x01;
OutputState[2] = 0x02;
OutputState[3] = 0x03;

OutputState2[0] = 0x00;
OutputState2[1] = 0x01;
OutputState2[2] = 0x10;
OutputState2[3] = 0x11;

//Enable the timer to start counting
TimerEnable(TIMER2_BASE,TIMER_A);

//
// Loop forever.
//
while(1)
{

}

}

void InitTimer(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER2);
SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER2);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
SysCtlDelay(10);

TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER2_BASE, TIMER_A, 80000000-1);

TimerIntClear(TIMER2_BASE, TIMER_TIMA_DMA);
TimerIntRegister(TIMER2_BASE, TIMER_A, Timer2IntHandler);
TimerIntEnable(TIMER2_BASE, TIMER_TIMA_DMA);

TimerDMAEventSet(TIMER2_BASE, TIMER_DMA_TIMEOUT_A);

}

void InitGPIO(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_GPION);
SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralReset(SYSCTL_PERIPH_GPION);
SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
// SysCtlDelay(10);

GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1, 0x00);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4, 0x00);

}
void InitUDMA(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlDelay(10);

uDMAEnable();
uDMAControlBaseSet(DMAcontroltable);

/*
* This is for setting up the GPIOs with CH4 and CH6 timer2A
*/
uDMAChannelAssign(UDMA_CH4_TIMER2A);
uDMAChannelAssign(UDMA_CH6_TIMER2A);

uDMAChannelAttributeDisable(UDMA_CH4_TIMER2A, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

uDMAChannelAttributeDisable(UDMA_CH6_TIMER2A, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
//---------------------------------------------

uDMAChannelControlSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);

uDMAChannelControlSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
//-----------------------------------------------

uDMAChannelTransferSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, OutputState, (void *)(GPIO_PORTN_BASE + 0x3FC), sizeof(OutputState));

uDMAChannelTransferSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, OutputState2, (void *)(GPIO_PORTF_BASE + 0x3FC), sizeof(OutputState2));
/*
* End of CH4 and CH6
*/

uDMAChannelEnable(UDMA_CH4_TIMER2A);
uDMAChannelEnable(UDMA_CH6_TIMER2A);

}
void Timer2IntHandler(void)
{

uint32_t ui32Mode1, ui32Mode2;
/*
* This is to reset the DMA transfers
*/

TimerIntClear(TIMER2_BASE, TIMER_TIMA_DMA);

ui32Mode1 = uDMAChannelModeGet(UDMA_SEC_CHANNEL_TMR2A_4 |UDMA_PRI_SELECT);
ui32Mode2 = uDMAChannelModeGet(UDMA_SEC_CHANNEL_TMR2A_6 |UDMA_PRI_SELECT);

if(ui32Mode1 == UDMA_MODE_STOP && ui32Mode2 == UDMA_MODE_STOP)
{

uDMAChannelTransferSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, OutputState, (void *)(GPIO_PORTN_BASE + 0x3FC), sizeof(OutputState));

uDMAChannelTransferSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, OutputState2, (void *)(GPIO_PORTF_BASE + 0x3FC), sizeof(OutputState2));

uDMAChannelEnable(UDMA_CH4_TIMER2A);
uDMAChannelEnable(UDMA_CH6_TIMER2A);

}

}

*************************************************************************************************************************************************************

CODE WITH ISSUES:

//*****************************************************************************
// DEFINES
//*****************************************************************************

void InitTimer(void);
void Timer2IntHandler(void);
void InitGPIO(void);
void InitUDMA(void);

#if defined(ewarm)
#pragma data_aligment=1024
uint8_t DMAcontroltable[1024];

#elif defined(ccs)
#pragma DATA_ALIGN(DMAcontroltable, 1024)
uint8_t DMAcontroltable[1024];

#else
uint8_t DMAcontroltable[1024] __attribute__ ((aligned(1024)));
#endif

//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

//*****************************************************************************
// GLOBALS
//*****************************************************************************
static uint16_t OutputState3[4];

static uint32_t g_ui32SysClock;
//*****************************************************************************
//
// Blink GPIOF with DMA
//
//*****************************************************************************
int
main(void)
{

uint32_t ui32Period;
uint32_t ui32SysClkFreq;

ui32SysClkFreq = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);

InitTimer();
InitGPIO();
InitUDMA();

/*
* Sets the pins state for all LED states.
*/
OutputState3[0] = 0x0000;
OutputState3[1] = 0x0101;
OutputState3[2] = 0x1002;
OutputState3[3] = 0x1103;

//Enable the timer to start counting
TimerEnable(TIMER2_BASE,TIMER_A);

//
// Loop forever.
//
while(1)
{

}

}

void InitTimer(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_TIMER2);
SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER2);
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER2);
SysCtlDelay(10);

TimerConfigure(TIMER2_BASE, TIMER_CFG_PERIODIC);
TimerLoadSet(TIMER2_BASE, TIMER_A, 80000000-1);

TimerIntClear(TIMER2_BASE, TIMER_TIMA_DMA);
TimerIntRegister(TIMER2_BASE, TIMER_A, Timer2IntHandler);
TimerIntEnable(TIMER2_BASE, TIMER_TIMA_DMA);

TimerDMAEventSet(TIMER2_BASE, TIMER_DMA_TIMEOUT_A);

}

void InitGPIO(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_GPION);
SysCtlPeripheralDisable(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralReset(SYSCTL_PERIPH_GPION);
SysCtlPeripheralReset(SYSCTL_PERIPH_GPIOF);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
// SysCtlDelay(10);

GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1);
GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4);
GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0|GPIO_PIN_1, 0x00);
GPIOPinWrite(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4, 0x00);

}
void InitUDMA(void)
{

SysCtlPeripheralDisable(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralReset(SYSCTL_PERIPH_UDMA);
SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
SysCtlDelay(10);

uDMAEnable();
uDMAControlBaseSet(DMAcontroltable);

/*
* This is for setting up the GPIOs with CH4 and CH6 timer2A
*/
uDMAChannelAssign(UDMA_CH4_TIMER2A);
uDMAChannelAssign(UDMA_CH6_TIMER2A);

uDMAChannelAttributeDisable(UDMA_CH4_TIMER2A, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);

uDMAChannelAttributeDisable(UDMA_CH6_TIMER2A, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
//---------------------------------------------

uDMAChannelControlSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);

uDMAChannelControlSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_8 | UDMA_DST_INC_NONE | UDMA_ARB_1);
//-----------------------------------------------

uDMAChannelTransferSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) OutputState3, (void *)(GPIO_PORTN_BASE + 0x3FC), sizeof(OutputState3)/2);

uDMAChannelTransferSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *)(OutputState3+1), (void *)(GPIO_PORTF_BASE + 0x3FC), sizeof(OutputState3)/2);
/*
* End of CH4 and CH6
*/

uDMAChannelEnable(UDMA_CH4_TIMER2A);
uDMAChannelEnable(UDMA_CH6_TIMER2A);

}
void Timer2IntHandler(void)
{

uint32_t ui32Mode1, ui32Mode2;
/*
* This is to reset the DMA transfers
*/

TimerIntClear(TIMER2_BASE, TIMER_TIMA_DMA);

ui32Mode1 = uDMAChannelModeGet(UDMA_SEC_CHANNEL_TMR2A_4 |UDMA_PRI_SELECT);
ui32Mode2 = uDMAChannelModeGet(UDMA_SEC_CHANNEL_TMR2A_6 |UDMA_PRI_SELECT);

if(ui32Mode1 == UDMA_MODE_STOP && ui32Mode2 == UDMA_MODE_STOP)
{

uDMAChannelTransferSet(UDMA_CH4_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void *) OutputState3, (void *)(GPIO_PORTN_BASE + 0x3FC), sizeof(OutputState3)/2);

uDMAChannelTransferSet(UDMA_CH6_TIMER2A | UDMA_PRI_SELECT, UDMA_MODE_BASIC, (void  *) (OutputState3 +1), (void *)(GPIO_PORTF_BASE + 0x3FC), sizeof(OutputState3)/2);

uDMAChannelEnable(UDMA_CH4_TIMER2A);
uDMAChannelEnable(UDMA_CH6_TIMER2A);

}

}

 

  • I just checked all possible combination of address sources in UDMA transfer set. May be the (void *)(OutputState3 +1) is wrong with little-endianness, is it possible?
  • Hello Salvador

    The uDMA works on 32-bit aligned words. Hence if specifying the byte/half-word location in the buffer, you need to make sure that they are 32-bit word aligned. Simple way to check is what is being configured by the CPU in the DMA Control Channel Table for working and non-working case and post the contents of the Control Table for both conditions

    Regards
    Amit