Other Parts Discussed in Thread: TM4C1294NCPDT, EK-TM4C1294XL
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)
{
}
}