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) { } }