Hello Guys,
I am using the TM4C1294NCPDT part of the launchpad (EK-TM4C1294XL). I am trying to sample the ADC via DMA, at 1Msps. right now I am just using the temperature sensor to test.
I am using ping-pong technique. Here is my code, the project can be downloaded here:files.zip
The code is working somewhat ( i can get ADC values, but they are not values I am expecting)
Basically, I do not really know what to set the following parameters to: ADCClockConfigSet(), UDMA_SIZE_XXX, UDMA_DST_INC_YYY, UDMA_ARB_ZZZ and the size of g_ui8RxBufA, I just guessed, to get something to work. i.e
ADCClockConfigSet(some value);
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_SIZE_XXX | UDMA_SRC_INC_NONE | UDMA_DST_INC_YYY | UDMA_ARB_ZZZ); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, sizeof(g_ui8RxBufA));
you will see in the following program (also can be download above) I have picked some arbitrary values for ADCClockConfigSet(), XXX, YYY, and ZZZ and the size, just to get it working.
I think the following question will help me to clarify things:
Q1. How fast do I have to configure the ADC sampling, to trigger at the rate, DMA can read it? right now the ADC is sampling at ADCClockConfigSet(ADC0_BASE,ADC_CLOCK_SRC_PLL,ADC_CLOCK_RATE_FULL), is this 1Msps? is this fast enough for the DMA?
Q2. From the source code, below, Do does the DMA transfer UDMA_SIZE_8, which is increased by UDMA_DST_INC_8 till size of sizeof(g_ui8RxBufA), which is when the DMA interrupt is fired? i.e 8 bits then 16, 24, 32... bits are transferred till sizeof(g_ui8RxBufA), which is when an interrupt fires?
If my understaning of Q2, is correct, then what I really what to do is, because I know that the ADC FIFO contains uint32_t bit words, and ADC0 has a FIFO of 8, then, the my code should be changed to
uDMAChannelControlSet(UDMA_CHANNEL_ADC0 |UDMA_PRI_SELECT UDMA_SIZE_32 | UDMA_SRC_INC_NONE | UDMA_DST_INC_32 | UDMA_ARB_256);
so the dma should transfer 32 bits, of data, 8 times? which is what I thought would be correct?
The problem: on line 93: ui32Mode only equals UDMA_MODE_STOP the first time it is interrupted, otherwise it != UDMA_MODE_STOP.i.e it doesn't work.
Q3 how big should g_ui8RxBufA be? I dont the sequences has a FIFO of 8 = 32*8bits=256, so should the size of g_ui8RxBufA be 256 bits?
#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" uint32_t gui32ADC0Value[2]; uint32_t gui32ADC1Value[2]; volatile uint32_t gui32ADCIntDone[2]; #pragma DATA_ALIGN(pui8ControlTable, 1024) uint8_t pui8ControlTable[1024]; static uint32_t g_ui8RxBufA[256]; static uint32_t g_ui8RxBufB[256]; //***************************************************************************** // //! \addtogroup adc_examples_list //! <h1>Single Ended ADC (single_ended)</h1> //! // //***************************************************************************** void uDMAErrorHandler(void) { uint32_t ui32Status; // // Check for uDMA error bit // ui32Status = uDMAErrorStatusGet(); // // If there is a uDMA error, then clear the error and increment // the error counter. // if(ui32Status) { uDMAErrorStatusClear(); } } void ADCseq0Handler() { 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, sizeof(g_ui8RxBufA)); uDMAChannelEnable(UDMA_CHANNEL_ADC0); } 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, sizeof(g_ui8RxBufB)); uDMAChannelEnable(UDMA_CHANNEL_ADC0); } } void InitUART1Transfer(uint32_t sysclock) { uint32_t div; // #define ADC_TARGET (8*1000*1000) // // if (sysclock < 2*ADC_TARGET) { // // div = ADC_CLOCK_SRC_PLL; // // } else { // // div = ADC_CLOCK_SRC_PLL | (((sysclock + ADC_TARGET - 1) / ADC_TARGET - 1) << 4); // // } SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_ADC0); ADCClockConfigSet(ADC0_BASE,ADC_CLOCK_SRC_PLL,ADC_CLOCK_RATE_FULL); //*(uint32_t *) (ADC0_BASE + ADC_O_CC) = div; 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_TS); // ADC_CTL_TS = read temp sensor ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 1, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 2, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 3, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 4, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 5, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 6, ADC_CTL_TS); ADCSequenceStepConfigure(ADC0_BASE, 0 /*SS0*/, 7, ADC_CTL_TS | 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_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_2); uDMAChannelControlSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_SIZE_8 | UDMA_SRC_INC_NONE | UDMA_DST_INC_8 | UDMA_ARB_2); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufA, sizeof(g_ui8RxBufA)); uDMAChannelTransferSet(UDMA_CHANNEL_ADC0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), g_ui8RxBufB, sizeof(g_ui8RxBufB)); uDMAChannelEnable(UDMA_CHANNEL_ADC0); ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0); IntEnable(INT_ADC0SS0); } int main(void) { uint32_t sysclock; sysclock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlPeripheralSleepEnable(SYSCTL_PERIPH_UDMA); IntMasterEnable(); IntEnable(INT_UDMAERR); uDMAEnable(); uDMAControlBaseSet(pui8ControlTable); InitUART1Transfer(sysclock); while(1) { } }