I have a problem similar to others: https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/425881/1750461
while using the MSP432 launchpad ADC DMA in Ping-Pong mode. In my code (see below) the dma will only successfully fill the first buffer and then stops.
I have attempted to add most of the suggestions that i could find in other posts, but to no avail.
This program is a modified version of the MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT example.
I suspect my problem is caused by the : while(1) { MAP_PCM_gotoLPM0(); not looping forever, or possibly by lack of understanding of how to setup interrupt service routines.
Please see the code below, any suggestions greatly appreciated
Jack
------------------------------------------------------------- //**************************************************************************** //extracted from MSP-EXP432P401R + Educational Boosterpack MkII - Microphone FFT #include "msp.h" #include "driverlib.h" #include "rom_map.h" #include "arm_const_structs.h" /* Standard Includes */ #include <stdio.h> #include <stdint.h> #define SAMPLE_LENGTH 512 /* ------------------------------------------------------------------ * Global variables for FFT Bin Example * ------------------------------------------------------------------- */ volatile arm_status status; #define SMCLK_FREQUENCY 48000000 // sample frequency is nyquist #define SAMPLE_FREQUENCY 8000 //#define SAMPLE_FREQUENCY 200000 /* FFT data/processing buffers*/ int16_t data_array0[SAMPLE_LENGTH]; int16_t data_array1[SAMPLE_LENGTH]; int16_t data_array2[SAMPLE_LENGTH]; int16_t value; /* DMA Control Table */ #ifdef ewarm #pragma data_alignment=256 #else #pragma DATA_ALIGN(controlTable, 256) #endif uint8_t controlTable[256]; volatile int switch_data = 0; /* Timer_A PWM Configuration Parameter */ Timer_A_PWMConfig pwmConfig = { TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY), TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2 }; void main(void) { /* Halting WDT and disabling master interrupts */ MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); /* Initialize the launchpad fpu. */ MAP_FPU_enableModule(); MAP_FPU_enableLazyStacking(); // boardInit(); /* Initializes Clock System */ MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1 ); MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); /* Configuring Timer_A to have a period of approximately 500ms and * an initial duty cycle of 10% of that (3200 ticks) */ Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); /* Initializing ADC (MCLK/1/1) */ ADC14_enableModule(); ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); MAP_ADC14_setResolution(ADC_14BIT); ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* Configuring GPIOs (4.3 A10) */ // GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN3, // GPIO_TERTIARY_MODULE_FUNCTION); /* Setting up GPIO pins p5.5 and p5.4 as analog inputs */ // MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, // GPIO_PIN5 | GPIO_PIN4, GPIO_TERTIARY_MODULE_FUNCTION); /* Configuring GPIOs (5.5 A0) */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN5, GPIO_TERTIARY_MODULE_FUNCTION); /* Configuring ADC Memory */ ADC14_configureSingleSampleMode(ADC_MEM0, true); // ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, // ADC_INPUT_A10, false); // MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, // ADC_INPUT_A0, true); MAP_ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A0, false); /* Set ADC result format to signed binary */ // ADC14_setResultFormat(ADC_SIGNED_BINARY); ADC14_setResultFormat(ADC_UNSIGNED_BINARY); /* Configuring DMA module */ DMA_enableModule(); DMA_setControlBase(controlTable); DMA_disableChannelAttribute(DMA_CH7_ADC12C, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); /* Setting Control Indexes. In this case we will set the source of the * DMA transfer to ADC14 Memory 0 * and the destination to the * destination data array. */ MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C, UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0), data_array1, SAMPLE_LENGTH); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C, UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0), data_array2, SAMPLE_LENGTH); /* Assigning/Enabling Interrupts */ MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC12C); MAP_DMA_clearInterruptFlag(7); MAP_Interrupt_enableMaster(); /* Making it so that we go back to sleep when interrupts end */ MAP_Interrupt_enableSleepOnIsrExit(); /* Now that the DMA is primed and setup, enabling the channels. The ADC14 * hardware should take over and transfer/receive all bytes */ MAP_DMA_enableChannel(7); /* FROM TIM-TI, We need to enable interrupts after enabling the DMA channel * to ensure that we don't get stuck in a "deadlock" situation */ MAP_ADC14_enableConversion(); while(1) { MAP_PCM_gotoLPM0(); int i = 0; /* Computer real FFT using the completed data buffer */ if (switch_data & 1) { value = data_array1[1]; for (i=0; i<SAMPLE_LENGTH; i++) { data_array0[i] = data_array1[i]; } printf(" switch buf 1 %i\r\n ", switch_data); } else { value = data_array2[1]; for (i=0; i<SAMPLE_LENGTH; i++) { data_array0[i] = data_array2[i]; } printf(" switch buf 2 %i\r\n ", switch_data); } } } /* Completion interrupt for ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { MAP_DMA_clearInterruptFlag(7); /* Switch between primary and alternate bufferes with DMA's PingPong mode */ if (DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC12C, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC12C, UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0), data_array1, SAMPLE_LENGTH); switch_data = 1; } else { DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC12C, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC12C, UDMA_MODE_PINGPONG, (void*) (ADC14_BASE + OFS_ADC14MEM0), data_array2, SAMPLE_LENGTH); switch_data = 0; } } ---------------------------------------------------------------------------------
Jack