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.

Stellaris LauchPad LM4F120 ADC => DMA configuration

Hello together,

i have issues to set up the ADC and DMA working together, in the way, that the DMA transfers a converted value to a given RAM address.

I´m using ADC0, Sample Sequencer 3; the RAM address is representes by the uint32_t adcVal; variable. The setup for the ADC supposes a software trigger.

Until now i could manage to make up a config, where the ADC runs in software trigger mode, triggers an ISR on "conversionDONE" and starts a DMA software transfer from the SS3 Fifo to the RAM based on the first example in Lab13 of the "TM4C123G_LaunchPad_Workshop_Workbook".

But i´m not able to get this done with the way, that the ADC sends a request to the DMA. I have inserted comments at points where i´m not sure if it is correct what i´m doing.

First it follows just the config routines and at the bottom the complete code.

#define SEQUENCER3 3
#define AMT_OF_ITEMS 1

// Set up clocking System
ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN |SYSCTL_XTAL_16MHZ);
ROM_SysCtlPeripheralClockGating(true);

// Set up PIN E1 and E2 for analog input
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1|GPIO_PIN_2);

//***************************************************************************************
//**************************    Set  up ADC   ******************************************
//***************************************************************************************
SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);                                             //enable ADC clock
ADCSequenceConfigure(ADC0_BASE, SEQUENCER3, ADC_TRIGGER_PROCESSOR, 0);                  //use SS3, enable software trigger, high priority

/*
Here i have issue with the ADC_CTL_IE bit. The "TM4C123GH6PM" datasheet says 

on page 803; chapter 13.3.2.2 "DMA Operation" (last sentence): 
"A burst transfer request is asserted when the interrupt bit for the sample sequence is set (IE bit in the ADCSSCTLn register is set)."

on page 599; chapter 9.2.8 "Peripheral Interface":
"Note: When using μDMA to transfer data to and from a peripheral, the peripheral must disable all interrupts to the NVIC."
*/
ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER3, 0, ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END); //define STEP 0 with SS3, use AIN2, Interrupt enable, define step as last sample
ADCSequenceEnable(ADC0_BASE, SEQUENCER3);                                               // enable SS3
ADCSequenceDMAEnable(ADC0_BASE, SEQUENCER3);                                            // enable SS3 for DMA


//***************************************************************************************
//**************************    Set  up DMA   ******************************************
//***************************************************************************************
/*
I´m not sure, if "UDMA_CHANNEL_ADC0" is the correct argument. When searching in the document "spmu36" ROM User Guide for the "ROM_uDMAChannelAttributeDisable" ebtry, 
it is written, that the the first argument "uint32_t ui32ChannelNum" must be one of the values 
- UDMA_CHANNEL_ADC0
- UDMA_CHANNEL_ADC1
- UDMA_CHANNEL_ADC2
- UDMA_CHANNEL_ADC3
- UDMA_SEC_CHANNEL_ADC10
- ....

What do the values ADC 0 to 4 relate to? Do they cover the existence of up to 4 ADC hardwares or do they relate to the FIFO´s of the 4 Sample Sequencers?
Plus when i take a look at their definition in udma.h File of TIVA-C WARE driver library the UDMA_CHANNEL_ADC0 is 14. What does 14 mean? For example according to the 
datasheet on page 587, chapter 9.2.1 "Channel Assignments"  the channel for the ADC0_SS3 (which i´m using) would be 17 and channel 14 is for ADC0_SS0.
*/
ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
	                        UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |(UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK));

ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0,
	    	               UDMA_ATTR_USEBURST| UDMA_ATTR_HIGH_PRIORITY);


// arbitation size = 1 since there is one value to transfer
// also tried UDMA_SRC_INC_NONE, since i don´t transfer to an array
ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
	                  UDMA_SIZE_32 | UDMA_SRC_INC_32| UDMA_DST_INC_32 | UDMA_ARB_1); 

ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
	                   UDMA_MODE_AUTO,
	                   (void*)(ADC0_BASE + 0xA8),//address of ADC0´s SS3 FIFO
	                   &adcVal,// dest address
	                   AMT_OF_ITEMS); //AMT_OF_ITEMS = 1

ROM_uDMAControlBaseSet(pui8ControlTable);
ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
ROM_uDMAChannelAssign(UDMA_CH17_ADC0_3);

/*
For the following IE´s i´m not sure weather to activate them or not 
*/
ADCIntEnable(ADC0_BASE, SEQUENCER3);
IntEnable(INT_ADC0SS3);
IntEnable(INT_UDMA);
IntMasterEnable();

ADCProcessorTrigger(ADC0_BASE, SEQUENCER3);


#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "inc/hw_uart.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/udma.h"
#include "driverlib/adc.h"

#define SEQUENCER3 3
#define AMT_OF_ITEMS 1

static uint32_t adcVal;

// Define errors counters
static uint32_t g_ui32DMAErrCount = 0;



// The control table used by the uDMA controller.  This table must be aligned to a 1024 byte boundary.
#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];

// Library error routine
#ifdef DEBUG
void
__error__(char *pcFilename, uint32_t ui32Line)
{
}
#endif

// uDMA transfer error handler
void
uDMAErrorHandler(void)
{
    uint32_t ui32Status;

    // Check for uDMA error bit
    ui32Status = ROM_uDMAErrorStatusGet();

    // If there is a uDMA error, then clear the error and increment the error counter.
    if(ui32Status)
    {
        ROM_uDMAErrorStatusClear();
        g_ui32DMAErrCount++;
    }
}

// Initialize the uDMA software channel to perform a memory to memory uDMA transfer.

void adcConversionSeq3DoneHandler(void)
{
	ADCIntClear(ADC0_BASE, SEQUENCER3);
	ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
		                               UDMA_MODE_AUTO,
		                               (void*)(ADC0_BASE + 0xA8),
		                               &adcVal,
		                               AMT_OF_ITEMS);
	ADCProcessorTrigger(ADC0_BASE, SEQUENCER3);
}


int
main(void)
{
	volatile int dummy = 0;

		ROM_SysCtlClockSet(SYSCTL_SYSDIV_4 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ);
	    ROM_SysCtlPeripheralClockGating(true);

	    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
		GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_1|GPIO_PIN_2);

		SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
		ADCSequenceConfigure(ADC0_BASE, SEQUENCER3, ADC_TRIGGER_PROCESSOR, 0);
		//ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER3, 0, ADC_CTL_CH2|ADC_CTL_IE|ADC_CTL_END);
		ADCSequenceStepConfigure(ADC0_BASE, SEQUENCER3, 0, ADC_CTL_CH2|ADC_CTL_END);
		ADCSequenceEnable(ADC0_BASE, SEQUENCER3);
		ADCSequenceDMAEnable(ADC0_BASE, SEQUENCER3);

		ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
		ROM_uDMAEnable();
		ROM_IntEnable(INT_UDMAERR);

	    /**/ROM_uDMAChannelAttributeDisable(UDMA_CHANNEL_ADC0,
	                                    UDMA_ATTR_USEBURST | UDMA_ATTR_ALTSELECT |
	                                    (UDMA_ATTR_HIGH_PRIORITY |
	                                    UDMA_ATTR_REQMASK));

	    ROM_uDMAChannelAttributeEnable(UDMA_CHANNEL_ADC0,
	    	                           UDMA_ATTR_USEBURST|
	                                   UDMA_ATTR_HIGH_PRIORITY);


	    ROM_uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
	                              UDMA_SIZE_32 | UDMA_SRC_INC_32| UDMA_DST_INC_32 |
	                              UDMA_ARB_1);


	    ROM_uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
	                               UDMA_MODE_AUTO,
	                               (void*)(ADC0_BASE + 0xA8),
	                               &adcVal,
	                               AMT_OF_ITEMS);

	    ROM_uDMAControlBaseSet(pui8ControlTable);
	    ROM_uDMAChannelEnable(UDMA_CHANNEL_ADC0);
	    ROM_uDMAChannelAssign(UDMA_CH17_ADC0_3);



    ADCIntEnable(ADC0_BASE, SEQUENCER3);
    IntEnable(INT_ADC0SS3);

    //IntEnable(INT_UDMA);
    IntMasterEnable();
    ADCProcessorTrigger(ADC0_BASE, SEQUENCER3);


    while(1)
    {

    }
}