Hello,
There are quite a few posts already pertaining to using the uDMA with the ADC on the TM4C123GH6PZ. I have gone through and pulled a lot of code from other examples to try and get a working piece of code (specifically here).
I call ADC0Init() from my main and the ADC and uDMA initialize. ADC0IntHandler() is set as the interrupt handler for ADC0. I periodically call GetCPUTemp(). With a breakpoint in that function, I notice that my ADC_OUT values are always 4095. ADC0IntHandler() is called, switching off between the two returning if statements. Is my arbitration size correct (16 * 8 = 128)? Am I missing a configuration setting? Is this the proper way to read the data transferred by the uDMA from the ADC?
I've attached the relevant code and an image containing my uDMA configuration table.
Regards,
Cam
#include "stdint.h" #include "stdbool.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "inc/hw_adc.h" #include "inc/hw_ints.h" #include "driverlib/debug.h" #include "driverlib/gpio.h" #include "driverlib/pwm.h" #ifdef _NOT_PROFILING_ #include "driverlib/rom.h" #endif #include "driverlib/rom_map.h" #include "driverlib/sysctl.h" #include "driverlib/adc.h" #include "driverlib/udma.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/timer.h" #include "ADC.h" #define VMON24_CH ADC_CTL_CH11 #define VMON24_ADC GPIO_PB5 #define VMON24_ADC_PORT GPIO_PORTB_BASE #define VMON24_ADC_PIN GPIO_PIN_5 #define IMON24_CH ADC_CTL_CH10 #define IMON24_ADC GPIO_PB4 #define IMON24_ADC_PORT GPIO_PORTB_BASE #define IMON24_ADC_PIN GPIO_PIN_4 #define VMON12_CH ADC_CTL_CH2 #define VMON12_ADC GPIO_PE1 #define VMON12_ADC_PORT GPIO_PORTE_BASE #define VMON12_ADC_PIN GPIO_PIN_1 #define IMON12_CH ADC_CTL_CH3 #define IMON12_ADC GPIO_PE0 #define IMON12_ADC_PORT GPIO_PORTE_BASE #define IMON12_ADC_PIN GPIO_PIN_0 #define VMON5_CH ADC_CTL_CH0 #define VMON5_ADC GPIO_PE3 #define VMON5_ADC_PORT GPIO_PORTE_BASE #define VMON5_ADC_PIN GPIO_PIN_3 #define IMON5_CH ADC_CTL_CH1 #define IMON5_ADC GPIO_PE2 #define IMON5_ADC_PORT GPIO_PORTE_BASE #define IMON5_ADC_PIN GPIO_PIN_2 #define ADC_SAMPLE_BUF_SIZE (8) #pragma DATA_ALIGN(udmaCtrlTable, 1024) uint8_t udmaCtrlTable[1024]; volatile uint16_t ADC_OUT[8]; static uint32 CPUTempCount; static uint32 CPUTemp; uint32 GetCPUTemp(void) { CPUTempCount = ADC_OUT[6]; CPUTempCount = ADC_OUT[7]; CPUTemp = ((295 / 2) - (225 * CPUTempCount / 4096)); return CPUTemp; } void uDMAErrorHandler(void) { uint32_t ui32Status; ui32Status = uDMAErrorStatusGet(); if(ui32Status) { uDMAErrorStatusClear(); } } void ADC0IntHandler() { ADCIntClear(ADC0_BASE, 0); if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT) == UDMA_MODE_STOP) { // found the full buffer // re-set up a DMA transfer to the buffer uDMAChannelTransferSet((UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT), UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable(UDMA_CH14_ADC0_0 ); // Enables DMA channel so it can perform transfers return; } if (uDMAChannelModeGet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT) == UDMA_MODE_STOP) { // found the full buffer // re-set up a DMA transfer to the buffer uDMAChannelTransferSet((UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT), UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable(UDMA_CH14_ADC0_0 ); // Enables DMA channel so it can perform transfers return; } } void ADC0Init(void) { TypeConversion Var; CPUTemp = 0; CPUTempCount = 0; /* * Enable the Peripheral */ SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0); SysCtlDelay(10); SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA); SysCtlDelay(10); /* * Set the speed of the ADC to 16 MHz. */ ADCClockConfigSet(ADC0_BASE, ADC_CLOCK_SRC_PLL | ADC_CLOCK_RATE_FULL, 25); /* * Configure GPIO pins as ADC */ GPIOPinTypeADC(VMON24_ADC_PORT, VMON24_ADC_PIN); GPIOPinTypeADC(IMON24_ADC_PORT, IMON24_ADC_PIN); GPIOPinTypeADC(VMON12_ADC_PORT, VMON12_ADC_PIN); GPIOPinTypeADC(IMON12_ADC_PORT, IMON12_ADC_PIN); GPIOPinTypeADC(VMON5_ADC_PORT, VMON5_ADC_PIN); GPIOPinTypeADC(IMON5_ADC_PORT, IMON5_ADC_PIN); /* * Configure the primary ADC sequence based on the default settings. */ ADCReferenceSet(ADC0_BASE, ADC_REF_EXT_3V); /* * Disable the ADC sequence and interrupts for safe reconfiguration of * the ADC sequences. */ IntDisable(INT_ADC0SS0); ADCIntDisable(ADC0_BASE, 0); ADCSequenceDisable(ADC0_BASE, 0); /* * Ensure that this sequence is the highest priority sequence * (in the event that other ADC sequences are being used * elsewhere in the system). */ ADCSequenceConfigure(ADC0_BASE, 0, ADC_TRIGGER_ALWAYS, 0); //Program the sequence Number 0. One steps for each channel and onchip temperature sensor ADCSequenceStepConfigure(ADC0_BASE, 0, 0, VMON24_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 1, IMON24_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 2, VMON12_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 3, IMON12_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 4, VMON5_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 5, IMON5_CH); ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_TS); //CPU Temperature ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_END | ADC_CTL_IE | ADC_CTL_TS); //Re enable the ADC sequence code. ADCSequenceEnable(ADC0_BASE, 0); ADCIntClear(ADC0_BASE,0); uDMAEnable(); uDMAControlBaseSet(udmaCtrlTable); ADCSequenceDMAEnable(ADC0_BASE, 0); uDMAChannelAttributeDisable(UDMA_CH14_ADC0_0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); uDMAChannelAttributeEnable(UDMA_CH14_ADC0_0, UDMA_ATTR_USEBURST); uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE); uDMAChannelTransferSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_MODE_PINGPONG, (void *)(ADC0_BASE + ADC_O_SSFIFO0), &ADC_OUT, ADC_SAMPLE_BUF_SIZE); uDMAChannelEnable(UDMA_CH14_ADC0_0); // Enables DMA channel so it can perform transfers MAP_IntPrioritySet(INT_ADC0SS0, 0x30); IntEnable(INT_UDMAERR); ADCIntEnable(ADC0_BASE,0); IntEnable(INT_ADC0SS0); }