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 to GPIO

Other Parts Discussed in Thread: TM4C1294NCPDT

Hi,

I want to toggle my GPIO during specific time, e.g at 10msec if I Turn on the GPIO and then later I would like to turn it off at 12msec. These timings are not constant, it will vary. Can I use uDMA to do this? If Yes, how can I set the timing, I mean can I set both the timings at a time and tell when to turn on and off, or I have to set to turn on first  and then after it is complete then I need to set it to turn off.

Is there any example code for this?

  • Hello,

    i look also for an example that triggers a udma burst with a timer. Data destination should be a gpio port...

    My own source fails... :-/

    I never was so much confused about a DMA implementation...

    Thx

    Basti

  • Hi Sebastian,

         As this post is more than a year ago, it would be much better to create a new post for your question. Indicate relevant details. See, below. 

         Information to provide when asking for help

         You, can also review the udma_demo example program at Tivaware.

    -kel     

  • Hello Sebastian,

    Do you have a code already implemented? If yes, then we can review and see why it does not work/

    Regards

    Amit

  • Here is my code... I call setup_dma before setup_timer:

    void setup_dma()
    {
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    	//SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    
    	GPIOPinTypeGPIOOutput(GPIO_PORTE_BASE, 0xFFFFFFFF);
    
    
    	IntEnable(INT_UDMAERR);
    
    
    	uDMAEnable();
    
        IntEnable(INT_UDMA);
    
        // Point at the control table to use for channel control structures.
        //
    	uDMAControlBaseSet(pui8ControlTable);
    
    	uDMAChannelAssign(UDMA_CH18_TIMER1A);
    
    	uDMAChannelAttributeDisable(UDMA_CHANNEL_TMR1A,
    	                                    UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST |
    	                                    UDMA_ATTR_HIGH_PRIORITY |
    	                                    UDMA_ATTR_REQMASK);
    
    	uDMAChannelControlSet(UDMA_CHANNEL_TMR1A | UDMA_PRI_SELECT,
    	                              UDMA_SIZE_8 | UDMA_SRC_INC_8 |
    	                              UDMA_DST_INC_NONE |
    	                              UDMA_ARB_1);
    
    	uDMAChannelTransferSet(UDMA_CHANNEL_TMR1A | UDMA_PRI_SELECT,
    	                               UDMA_MODE_BASIC, image_A,
    	                               (void *)(GPIO_PORTE_AHB_DATA_R),
    	                               1023);
    
    
    
    	uDMAChannelEnable(UDMA_CHANNEL_TMR1A);
    }
    
    
    void setup_timer()
    {
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER1);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOD);
    
    	GPIOPinConfigure(GPIO_PD2_T1CCP0);
    
    	GPIOPinTypeTimer(GPIO_PORTD_BASE,GPIO_PIN_2);
    
    	//
    	// Configure the two 32-bit periodic timers.
    	//
    	TimerConfigure(TIMER1_BASE, TIMER_CFG_PERIODIC | TIMER_CFG_SPLIT_PAIR | TIMER_CFG_A_PWM |TIMER_CFG_B_PWM);
    	
    	TimerLoadSet(TIMER1_BASE, TIMER_BOTH, 5);
    	TimerMatchSet(TIMER1_BASE,TIMER_A,2);
    	TimerMatchSet(TIMER1_BASE,TIMER_B,1);
    
    
    	TimerDMAEventSet(TIMER1_BASE,TIMER_DMA_MODEMATCH_A);
    
    	//TimerIntEnable(TIMER1_BASE,TIMER_TIMA_MATCH);
    	TimerIntEnable(TIMER1_BASE,TIMER_TIMA_DMA);
    
    	//
    	// Setup the interrupts for the timer timeouts.
    	//
    	IntEnable(INT_TIMER1A);
    
    	//
    	// Enable the timers.
    	//
    	TimerEnable(TIMER1_BASE, TIMER_BOTH);
    }

  • Hello Sebastien,

    In the uDMAChannelControlSet the Destination Size is not mentioned. Though it defaults to 8 but it is an SRAM location so would be better that it does not remain uninitialized

    Secondly, the uDMA takes time for processing a request. By keeping the timer match to a small value, it would cause a lot of trigger.

    lastly the uDMA interrupt will be triggered on the GPT Interrupt line. I do not see a Timer Interrupt routine. Could you confirm the same?

    Regards

    Amit

  • Hello,

    thx for your help... but for me it's already unclear... =(

    1. I don't understand, sorry. 

    2. Sure, but it seems my problem is that no request is send to the DMA Channel... Request will saved until 2 are reached... the 3rd will delete... is it to fast, it should also work?! Should I use UDMA_MODE_AUTO instead BASIC?

    3. I have a Interrupt Routine but it gets never called:

    void MyTimerInterrupt1A(void)
    {
    
        uDMAChannelEnable(UDMA_CHANNEL_TMR1A);
    
        TimerIntClear(TIMER1_BASE,TIMER_TIMA_MATCH);
    
        GPIO_PORTN_DATA_R ^= 0x01;
    }

    Regards

    Basti

  • Hello Sebastien,

    1. Is the clock to GPIO Port A enabled in the code?

    2. The TM4C123 GPIO is mapped to APB bus by default whereas you are using AHB Address Space.

    Regards

    Amit

  • I use just Port D for compare action, Port E for the destination of the Data and Port N for LED indication... 

    Why should I activate Port A?

    2. GPIO_PORTE_AHB_DATA_R = image_A[a][pwm_c]; does work correctly...

    I think the destination address isn't the Problem...

    I have tried also another timer (0A) and different DMA options... my interrupt routine gets now called... but the DMA transfer is never done :(

    void MyTimerInterrupt0A(void)
    {
    
    	//uDMAChannelDisable(UDMA_CHANNEL_TMR0A);
    
    
    
    
    	/*uDMAChannelTransferSet(UDMA_CHANNEL_TMR0A | UDMA_PRI_SELECT,
    		                               UDMA_MODE_BASIC, &image_A[dma_counter],
    		                               (void *)(GPIO_PORTE_AHB_DATA_R),
    		                               192);*/
    
    
    	mode = uDMAChannelModeGet(UDMA_CHANNEL_TMR0A | UDMA_PRI_SELECT);
    
    	if(mode == UDMA_MODE_STOP)
    	{
    	    uDMAChannelEnable(UDMA_CHANNEL_TMR0A);
    
    		dma_counter += 192;
    
    		if(dma_counter >= (256*256))
    			dma_counter = 0;
    
    	    GPIO_PORTN_DATA_R ^= 0x01;
    	}
    
    
        //TimerIntClear(TIMER0_BASE,TIMER_TIMA_DMA);
        TimerIntClear(TIMER0_BASE,0xFFFFFFFF);
    }

    For correction: I would like to set a complete byte to a port (E for example) time sync with a timer. I hope after all bytes clocked out to the port, the interrupt routine from the timer gets called and I can calculate the new source address...

    But I stuck a lot and there is no much help out there :(

    Thx Basti

  • Hello Sebastian,

    Can you zip the CCS project. It would be easier for me to look at the full code, to analyze the issue.

    Regards

    Amit

  • Hello Amit,

    thanks for your help... here is the project...

    I have notice that the dma error interrupt gets called... but i don't know why... :(

    5126.blinky.rar

  • Hello Sebastian

    My suspicion is on GPIO_PORTE_AHB_DATA_R

    Can you replace it with (void *)(GPIO_PORTE_AHB_DATA_R)  with just GPIO_PORTE_DATA, while I build it in my setup

    Regards

    Amit

  • sorry, I can't find a header file for this macro... where is it defined?

    thx a lot

  • Amit Ashara said:
    GPIO_PORTE_AHB_DATA_R

    @Sebastian are you referring to this above. That  can be found at #include "inc/tm4c1294ncpdt.h"

    -kel

  • Hello Sebastian

    Are you using a TM4C129 device? If that is the case then I need to go through the whole code as the uDMA has some changes for TM4C129 in terms of Interrupt Vector.

    Will post an update later.

    Regards

    Amit

  • I use the tiva launchpad with the ethernet functionality and yes it's an TM4C1294 Rev. B (for erreta)

    @markel sorry I look for the other macro: GPIO_PORTE_DATA

  • Hello Sebastian

    There are two issues

    1. The Destination Address is pointer and I had to replace it with Actual Address of the Data Port

            uDMAChannelTransferSet(UDMA_CHANNEL_TMR0A | UDMA_PRI_SELECT,
                                                   UDMA_MODE_BASIC, &image_A[dma_counter],
                                                   (GPIO_PORTE_AHB_BASE+0x400),
                                                   192);
    2. It runs properly but the ImageA address computed goes above 256KB SRAM address space causing another Fault. You may want to check how to optimize this

    Regards

    Amit

  • Hello Amit,

    +0x400 is the DIR Address Space...

    The Data Space has a 256 byte space... because of this "feature":

    "To aid in the efficiency of software, the GPIO ports allow for the modification of individual bits in the

    GPIO Data (GPIODATA) register (see page 753) by using bits [9:2] of the address bus as a mask.

    ....

    To implement this
    feature, the GPIODATA register covers 256 locations in the memory map."

    How can I direct control the PINs with a DMA?

    Regards

    Basti

  • Hello Sebastian

    My bad!! It is 0x3FC and not 0x400. Doing the same with DMA is going to be complicated and I would rather do a CPU method than DMA for such a requirement.

    Regards

    Amit

  • Ahhhhhhhhhhhh...

    Okay, I have it...

    &GPIO_PORTE_AHB_DATA_R == GPIO_PORTE_AHB_BASE+0x3FC

    Now I seems to work...

    DMA is required... CPU has to calculate the the PWM to the SRAM from the image... 

    Thank you for your great help!