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.

TM4C129e: uDMA ADC

I am using uDMA (ping pong mode) to save ADC (at 1 MSP.... I hope so) data in two buffers, while one buffers is getting filled, i operate the data from the another, in order to get a real time application without loosing information , the problem is that the destination buffers change a lot and when I am operating the values from one of them their values get changed and I do not finish to operate all the buffer. In the code as an operation I use a loop to save the data from the the destination buffer in another buffers (salida1 and salida2), they do not get filled completely.

At the end of the code I finish the program after the variable (flag1) reach the value of 2, so, I am just going to save 2048 ADC values in the buffers (salida1 and salida2)

#include <stdbool.h>
#include <stdint.h>
#include "inc/hw_ints.h"
#include "inc/hw_memmap.h"
#include "inc/hw_adc.h"
#include "inc/hw_types.h"
#include "inc/hw_udma.h"
#include "inc/hw_emac.h"
#include "driverlib/debug.h"
#include "driverlib/gpio.h"
#include "driverlib/interrupt.h"
#include "driverlib/pin_map.h"
#include "driverlib/rom.h"
#include "driverlib/sysctl.h"
#include "driverlib/uart.h"
#include "driverlib/adc.h"
#include "driverlib/udma.h"
#include "driverlib/emac.h"

#pragma DATA_ALIGN(pui8ControlTable, 1024)
uint8_t pui8ControlTable[1024];

#define MEM_BUFFER_SIZE         1024
static uint32_t g_ui8RxBufA[MEM_BUFFER_SIZE];
static uint32_t g_ui8RxBufB[MEM_BUFFER_SIZE];
volatile uint32_t salida1[MEM_BUFFER_SIZE];
volatile uint32_t salida2[MEM_BUFFER_SIZE];

int bug=29;
uint32_t sysclock;
uint32_t TX_BUFFER;
volatile uint32_t count = 0;
volatile uint32_t flag = 0;
volatile uint32_t flag1 = 0;
volatile int m,k,n;


//*****************************************************************************
//
//! \addtogroup adc_examples_list
//! <h1>Single Ended ADC (single_ended)</h1>
//!

//*****************************************************************************
void uDMAErrorHandler(void)
{
    uint32_t ui32Status;

    ui32Status = uDMAErrorStatusGet();	// Check for uDMA error bit
    if(ui32Status)						// If there is a uDMA error
    {
        uDMAErrorStatusClear();			//Clear the error status
    }

}
//*****************************************************************************



void ADCseq0Handler()

{
	uint32_t ui32Status = ADCIntStatus(ADC0_BASE, 0, false);
    uint32_t ui32Mode;

    ROM_ADCIntClear(ADC0_BASE, 0);						//se puede eliminar
    ADCIntClearEx(ADC0_BASE, ADC_INT_DMA_SS0);


    ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT);

    if(ui32Mode == UDMA_MODE_STOP)

    {
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                                   UDMA_MODE_PINGPONG,
                                   (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                                   g_ui8RxBufA, MEM_BUFFER_SIZE);
    }

    ui32Mode = uDMAChannelModeGet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT);

    if(ui32Mode == UDMA_MODE_STOP)

    {
        uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                                    UDMA_MODE_PINGPONG,
                                    (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                                    g_ui8RxBufB, MEM_BUFFER_SIZE);
    }
    uDMAChannelEnable(UDMA_CHANNEL_ADC0);
}

//*****************************************************************************
void InitConsole(void)											/*Configuracion de periferico UART*/
{
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);				// Habilitacion de periferico GPIOA
    GPIOPinConfigure(GPIO_PA0_U0RX);							// Configurar pin PA0 para recepción
    GPIOPinConfigure(GPIO_PA1_U0TX);							// Configurar pin PA0 para transmision
    SysCtlPeripheralEnable(SYSCTL_PERIPH_UART0);				// Habilita periferico UART0
    UARTClockSourceSet(UART0_BASE, UART_CLOCK_SYSTEM);			// Fuente de Clock para uart sacada del clock del sistema 120MHz
    GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);  // PA0 y PA1 tipo UART
//  UARTStdioConfig(0, 115200, 120000000);
    UARTConfigSetExpClk(UART0_BASE
    					,sysclock				     			//Fuente de señal de Configurar pin PA0 para recepciónConfigurar pin PA0 para recepciónclock
						,115200									//Baud rate
						,(UART_CONFIG_WLEN_8					//Longitud de trama 8 bits
						 |UART_CONFIG_STOP_ONE					//Un bit de stop
						 |UART_CONFIG_PAR_NONE));				//No hay bit de paridad
}
//*****************************************************************************

void ADCconfigure(uint32_t sysclock)

{
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE); 										//Habilita puerto E
    SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3|GPIO_PIN_2|GPIO_PIN_1); 					//PE3 PE2 PE1 tipo ADC
    SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0);

    ADCClockConfigSet(ADC0_BASE,ADC_CLOCK_SRC_PIOSC | ADC_CLOCK_RATE_FULL, 1);			//Clock source (Precision Internal Clock)
//  ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 30);

    ADCSequenceConfigure(ADC0_BASE, 0 /*SS0*/, ADC_TRIGGER_ALWAYS, 3 /*priority*/);  // SS0-SS3 priorities must always be different
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 0, ADC_CTL_CH0);  // ADC_CTL_TS = read temp sensor
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 1, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 2, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 3, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 4, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 5, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 6, ADC_CTL_CH0);
    ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 7, ADC_CTL_CH0 | ADC_CTL_END | ADC_CTL_IE);   // ADC_CTL_IE fires every 8 samples
    ADCSequenceEnable(ADC0_BASE, 0);
    ADCSequenceDMAEnable(ADC0_BASE, 0);

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

    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                            UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 |
                              UDMA_ARB_256);

    uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                            UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 |
                            UDMA_ARB_256);

    uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT,
                               UDMA_MODE_PINGPONG,
                               (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                               g_ui8RxBufA, MEM_BUFFER_SIZE);

    uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT,
                                UDMA_MODE_PINGPONG,
                                (void *)(ADC0_BASE + ADC_O_SSFIFO0),
                                g_ui8RxBufB, MEM_BUFFER_SIZE);
    uDMAChannelEnable(UDMA_CHANNEL_ADC0);
    ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);
    IntEnable(INT_ADC0SS0);
}

int main(void)

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

     InitConsole();
     for(k=0;k<=bug-1;k++)
     {
			UARTCharPut(UART0_BASE,0x69);
     }
        SysCtlDelay(sysclock / 10);        					// Delay for a bit.

     ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);    						// Enable the GPIO port that is used for the on-board LED.
     ROM_GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0);    					// Enable the GPIO pins for the LED (PN0).

     SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
     SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA);
     IntMasterEnable();
     IntEnable(INT_UDMAERR);
     uDMAEnable();
     uDMAControlBaseSet(pui8ControlTable);
     ADCconfigure(sysclock);



    while(1)

    {
    	if(flag == 0)
    	{
    		for(n=0;n<MEM_BUFFER_SIZE;n++)
    		{
                salida1[n] = (int16_t)(g_ui8RxBufA[n]);
    		}
            flag = 1;
            flag1++;
    	}

    	if(flag == 1)
    	{
    		for(n=0;n<MEM_BUFFER_SIZE;n++)
    		{
                salida2[n] = (int16_t)(g_ui8RxBufB[n]);
    		}
            flag = 0;   
            flag1++;
    	}
    	if (flag1 == 2)

    	{
    		while(1){}
    	}

    }

}

how can I solve the problem in order to operate the values from the ADC(at 1MSPS and more) in a real time aplication.

Thanks in Advance

  • Hello Josue

    The first thing you need to verify is that the operation of the DMA i.e. its interrupts are occurring at 1024*1us boundary for both ping and pong buffer. This can be ascertained by putting a GPIO pin toggle.

    The next thing you need to check is the time for the processing of the buffers (which do not seem to by much). Since the samples from the ADC is 12 bit, then instead of doing a 32 bit read, you can perform 16 bit read and the typecasting can be avoided.

    Regards
    Amit