This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

2 Channels ADC udma pingpong

I managed to get this example to work for 1 ADC channel for udma:

How would I set this up for 2 Channels of ADC simultaneously sampling at 1MS/s

  • Hello Lee,

    And what is the issue with uDMA in Ping Pong. Did you refer to the udma_demo code example which has a Ping Pong example for UART?

    Regards
    Amit
  • The issue is that I can't sample 2 channels of ADC simultaneously. Yes I am referring to the udma code example in the link.
  • Hello Lee

    Which TM4C device are you using?

    Regards
    Amit
  • Hello Lee,

    Each ADC Sequencer on each of the ADC peripheral instances has an independent UDMA request. To be able to sample 2 channels at 1 MSPS, you need to set up both the ADC instances and their respective uDMA sequencers.

    Regards
    Amit
  • I can get 1 ADC channel to work properly but I can't get 2 channels to work at the same time. My code is as follows

    This is where I can dynamically enable the ADCs

            IntEnable(INT_UDMAERR);
    	IntEnable(INT_ADC0SS0);
    	IntEnable(INT_ADC1SS0);
    	ADCIntEnableEx(ADC0_BASE, ADC_INT_DMA_SS0);
    	ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS0);

    This is where I can dynamically disable the ADCs

    	IntDisable(INT_UDMAERR);
    	IntDisable(INT_ADC0SS0);
    	IntDisable(INT_ADC1SS0);
    	ADCIntDisableEx(ADC0_BASE, ADC_INT_DMA_SS0);
    	ADCIntDisableEx(ADC1_BASE, ADC_INT_DMA_SS0);

    This is where I setup the 2 ADC's

        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC0);
        SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
    
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);				// Use PE3 and PE2
    	GPIOPinTypeADC(GPIO_PORTE_BASE, GPIO_PIN_3 | GPIO_PIN_2);	// Set Pin type to Analog IN
    
        SysCtlDelay(10);
    
        ADCSequenceConfigure(ADC0_BASE, 0 /* SS0 */ , ADC_TRIGGER_PROCESSOR, 3 /* priority */);
        ADCSequenceStepConfigure(ADC0_BASE, 0, 0, ADC_CTL_CH0 ); // Channel 3 -> PE0
        ADCSequenceStepConfigure(ADC0_BASE, 0, 1, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 2, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 3, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 4, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 5, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 6, ADC_CTL_CH0 );
        ADCSequenceStepConfigure(ADC0_BASE, 0, 7, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END);
        ADCSequenceEnable(ADC0_BASE, 0);
    
        // Enable the uDMA controller.
        uDMAEnable();
        uDMAChannelAssign(UDMA_CH14_ADC0_0); // Check the channel
    
        // Point at the control table to use for channel control structures.
        uDMAControlBaseSet(udmaControlTable);
    
    	ADCSequenceDMAEnable(ADC0_BASE, 0);
    
    	// disable some bits
    	uDMAChannelAttributeDisable(UDMA_CH14_ADC0_0, UDMA_ATTR_ALTSELECT /*start with ping-pong PRI side*/ |
    		UDMA_ATTR_HIGH_PRIORITY /*low priority*/ | UDMA_ATTR_REQMASK /*unmask*/);
    	// enable some bits
    	uDMAChannelAttributeEnable(UDMA_CH14_ADC0_0, UDMA_ATTR_USEBURST /*only allow burst transfers*/);
    
    
        // set dma params on PRI_ and ALT_SELECT
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); //1024 or 128
        uDMAChannelControlSet(UDMA_CH14_ADC0_0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128);
    
        uDMAChannelEnable(UDMA_CH14_ADC0_0);
    
    	/* The following lines are essential to start cycle */
    	ADCIntClear(ADC0_BASE, 0);
    	ADCProcessorTrigger(ADC0_BASE,0);
    
        SysCtlPeripheralEnable(SYSCTL_PERIPH_ADC1);
    
        SysCtlDelay(10);
    
        ADCSequenceConfigure(ADC1_BASE, 0 /* SS0 */ , ADC_TRIGGER_PROCESSOR, 3 /* priority */);
        ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH1 ); // Channel 3 -> PE0
        ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 5, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 6, ADC_CTL_CH1 );
        ADCSequenceStepConfigure(ADC1_BASE, 0, 7, ADC_CTL_CH1 | ADC_CTL_IE | ADC_CTL_END);
        ADCSequenceEnable(ADC1_BASE, 0);
    
        // Enable the uDMA controller.
        uDMAEnable();
        uDMAChannelAssign(UDMA_CH24_ADC1_0); // Check the channel
    
        // Point at the control table to use for channel control structures.
        uDMAControlBaseSet(udmaControlTable);
    
    	ADCSequenceDMAEnable(ADC1_BASE, 0);
    
    	// disable some bits
    	uDMAChannelAttributeDisable(UDMA_CH24_ADC1_0, UDMA_ATTR_ALTSELECT /*start with ping-pong PRI side*/ |
    		UDMA_ATTR_HIGH_PRIORITY /*low priority*/ | UDMA_ATTR_REQMASK /*unmask*/);
    	// enable some bits
    	uDMAChannelAttributeEnable(UDMA_CH24_ADC1_0, UDMA_ATTR_USEBURST /*only allow burst transfers*/);
    
    
        // set dma params on PRI_ and ALT_SELECT
        uDMAChannelControlSet(UDMA_CH24_ADC1_0  | UDMA_PRI_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128); //1024 or 128
        uDMAChannelControlSet(UDMA_CH24_ADC1_0 | UDMA_ALT_SELECT, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_128);
    
        uDMAChannelEnable(UDMA_CH24_ADC1_0);
        uDMAChannelEnable(UDMA_CH24_SSI1RX);
    
    	/* The following lines are essential to start cycle */
    	ADCIntClear(ADC1_BASE, 0);
    	ADCProcessorTrigger(ADC1_BASE, 0);

  • Hello Lee

    What is "uDMAChannelEnable(UDMA_CH24_SSI1RX);" doing in the code?

    Regards
    Amit
  • Using a different udma channel for the second adc sampler.
  • Hello Lee

    Can you please share the UDMA Control Table values?

    Also please change the ARB Size to 8.

    Regards
    Amit
  • I'm sorry if this sounds stupid but where do I find the udma control table values?
  • Hello lee

    I should have elaborated that as well. Read the UDMA's CTLBASE register. The address is where the Control structure is located. It would be 512 bytes from that address as the primary control structure and the next 512 control structure.

    Also another exercise would be to check if the ADC0 DMA is not used then does ADC1 DMA work or not. This will help isolate the cause to the source of the issue being a missing DMA request in the first place.

    Regards
    Amit