Part Number: MSP432P4111
My current setup is:
- MSP432P4111 custom board
- SimpleLink MSP432P4SDK 2.10.0.14
- CCS V7.3.0
- XDCTools 3.50.5.12
- Compiler TI v17.9.0.STS
Ideally I would like to capture ADC Channels A3, A2, A1, A0 sequentially and repeatedly via DMA ping-pong mode.
My ideal scenario would be capturing 2048 samples (1024 ping, 1024 pong), running at the 1 Megasample rate.
The best I have been able to do is the source code below. Where i'm capturing 32 samples via DMA ping-pong mode (32 ping, 32 pong). Using the source increment feature so the DMA steps through ADC_MEM0 to ADC_MEM31. I don't see a way of doing a repeated sequence DMA Ping Pong mode so the DMA will automatically loop around and repeatedly capture A3, A2, A1, A0, A3, A2, A1, A0, A3, A2... My current method of 32 sample DMA's is still to slow to sustain the 1Msample rate.
I've searched through the forums, and haven't had any luck finding a possible solution. Only bits and pieces of incomplete answers. That brings up 3 questions:
- Is there an example of a multi-channel sequence repeat mode ADC example with a large ping-pong DMA buffer?
- Any suggestions of how to better implement this type of DMA, that I'm missing?
- My example only works if I call the ADC14_toggleConversionTrigger(); in the setup and DMA ISR. This is having a timing impact on my current system. What am I doing incorrectly to require this call?
#define DMA_ADC_CHAN 7 #define DMA_CAPTURE_SIZE 32 #define ADC_HS_BLOCK_SIZE 256 #define ADC_HS_BUFF_SIZE (2*ADC_HS_BLOCK_SIZE) #pragma DATA_ALIGN(dmaCtrlTable, 256) uint8 dmaCtrlTable[256]; #pragma DATA_ALIGN(adcDmaBuf, 256) uint32 adcDmaBuf[DMA_CAPTURE_SIZE*2]; #pragma DATA_ALIGN(adcHsSamples, 256) uint32 adcHsSamples[ADC_HS_BUFF_SIZE]; int16 adcHsSampleIdx = 0; int16 skipBlock = 0; void ADCStartDmaCaptureSequence(void) { int16 idx = 0, inputSelect; uint32 adcMem = 0; ADC14_configureMultiSequenceMode(ADC_MEM0, ADC_MEM31, false); // capture A3, A2, A1, A0, from ADC_MEM0 to ADC_MEM31 (32 samples) for( idx = 0; idx < DMA_CAPTURE_SIZE; idx ++ ) { inputSelect = idx & 0x00000003; switch(inputSelect) { case 0: ADC14_configureConversionMemory(1 << idx, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A3, false); break; case 1: ADC14_configureConversionMemory(1 << idx, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A2, false); break; case 2: ADC14_configureConversionMemory(1 << idx, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A1, false); break; case 3: ADC14_configureConversionMemory(1 << idx, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A0, false); break; } } ADC14_setSampleHoldTime(ADC_PULSE_WIDTH_4, ADC_PULSE_WIDTH_4); ADC14_setSampleHoldTrigger(ADC_TRIGGER_ADCSC, false); // Now configure DMA DMA_enableModule(); DMA_setControlBase(dmaCtrlTable); /* * Primary DMA Channel, ADC14 * Size = 32bits * Source Increment = 32bits * Destination Increment = 32bits * Arbitration = 32 , no other sources */ DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_32); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], &adcDmaBuf[0], DMA_CAPTURE_SIZE); DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_32); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], &adcDmaBuf[DMA_CAPTURE_SIZE], DMA_CAPTURE_SIZE); adcHsSampleIdx = 0; DMA_assignInterrupt(DMA_INT1, DMA_ADC_CHAN); Interrupt_enableInterrupt(INT_DMA_INT1); DMA_assignChannel(DMA_CH7_ADC14); DMA_clearInterruptFlag(0x07); DMA_enableChannel(DMA_ADC_CHAN); //Interrupt_enableInterrupt(INT_ADC14); ADC14_enableSampleTimer(ADC_AUTOMATIC_ITERATION); ADC14_enableConversion(); //ADC14_enableInterrupt(ADC_INT31); // Interrupt after ADC_MEM3 complete ADC14_toggleConversionTrigger(); SetStatus1Low(); } //__attribute__((ramfunc)) void Dma1ISR(UArg arg0) { BOOL dmaEvent = FALSE; uint32 select = DMA_getChannelAttribute(7); SetStatus1High(); ADC14_toggleConversionTrigger(); // does not work without this! if ( select & UDMA_ATTR_ALTSELECT ) { DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_32); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], &adcDmaBuf[0], DMA_CAPTURE_SIZE); memcpy( &adcHsSamples[adcHsSampleIdx], &adcDmaBuf[0], DMA_CAPTURE_SIZE * sizeof(uint32)); if( (adcHsSampleIdx + DMA_CAPTURE_SIZE) < ADC_HS_BUFF_SIZE ) adcHsSampleIdx += DMA_CAPTURE_SIZE; else adcHsSampleIdx = 0; } else { DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_32 | UDMA_SRC_INC_32 | UDMA_DST_INC_32 | UDMA_ARB_32); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], &adcDmaBuf[DMA_CAPTURE_SIZE], DMA_CAPTURE_SIZE); memcpy( &adcHsSamples[adcHsSampleIdx], &adcDmaBuf[DMA_CAPTURE_SIZE], DMA_CAPTURE_SIZE * sizeof(uint32)); if( (adcHsSampleIdx + DMA_CAPTURE_SIZE) < ADC_HS_BUFF_SIZE ) adcHsSampleIdx += DMA_CAPTURE_SIZE; else adcHsSampleIdx = 0; } if(adcHsSampleIdx == ADC_HS_BLOCK_SIZE ) dmaEvent = TRUE; // insert event post here else if( adcHsSampleIdx == 0 ) dmaEvent = TRUE; // insert event post here SetStatus1Low(); }