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.

No uDMA transfer complete Interrupt for ADC scatter-gather transfer

Other Parts Discussed in Thread: TM4C123AH6PM

Hello,

I'm using TM4C123AH6PM with CCS and TivaWare.

I want to measure 8 channels with ADC1 in "ADC_TRIGGER_ALWAYS" mode for 200 samples. All this samples shall get copied to a buffer with uDMA in peripheral scatter gather mode. After all samples have been transfered I expect a uDMA transfer complete Interrupt, but I can't see one. The ADC values gets transfered once and the uDMA gets disabled but no interrupt occures.

I'm pasting the interesting code here. Do I miss something?

ADC initialisation:

ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 1);
ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH1);
ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH4);
ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH5);
ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH6);
ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH7);
ADCSequenceStepConfigure(ADC1_BASE, 0, 5, ADC_CTL_CH2);
ADCSequenceStepConfigure(ADC1_BASE, 0, 6, ADC_CTL_CH0);
ADCSequenceStepConfigure(ADC1_BASE, 0, 7, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH8);
ADCIntRegister(ADC1_BASE, 0, ADC1SS0uDMATransferFinishedISR);
ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS0);
ADCSequenceEnable(ADC1_BASE, 0);

ADC ISR:

ADCIntClear(ADC1_BASE, 0);
if (uDMAIntStatus() & (1 << (UDMA_CH24_ADC1_0 & 0x1F)))
{
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_5, 0);
GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_5, GPIO_PIN_5);
}

uDMA init:
uDMAEnable();
uDMAControlBaseSet(uDMAControlTable);
uDMAChannelDisable(UDMA_CH24_ADC1_0);
uDMAChannelAssign(UDMA_CH24_ADC1_0);
uDMAChannelAttributeDisable(UDMA_CH24_ADC1_0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
uDMAChannelScatterGatherSet(UDMA_CH24_ADC1_0, MAX_ADC_SAMPLES, (void*)TaskList, true);
uDMAChannelEnable(UDMA_CH24_ADC1_0);

Thank you in advance

Regards

Christian

ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 1);

ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH1); //UZELL_A

ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH4); //UZELL_B

ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH5); //UZELL_C

ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH6); //UZELL_D

ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH7); //UZELL_E

ADCSequenceStepConfigure(ADC1_BASE, 0, 5, ADC_CTL_CH2); //UZELL_F

ADCSequenceStepConfigure(ADC1_BASE, 0, 6, ADC_CTL_CH0); //UZELL_1

ADCSequenceStepConfigure(ADC1_BASE, 0, 7, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH8); //USTACK

  • Pasting the code didn't work good. I attach a file with the code.

    Sorry for that

    void uDMAInit()
    {
       uDMAEnable();
       uDMAControlBaseSet(uDMAControlTable);
    
       /* Ensure channel is disabled before modifying register. */
       uDMAChannelDisable(UDMA_CH24_ADC1_0);
       uDMAChannelAssign(UDMA_CH24_ADC1_0);
       uDMAChannelAttributeDisable(UDMA_CH24_ADC1_0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
       uDMAChannelScatterGatherSet(UDMA_CH24_ADC1_0, MAX_ADC_SAMPLES, (void*)TaskList, true);
    
       uDMAChannelEnable(UDMA_CH24_ADC1_0);
    }
    
    void ADC1SS0uDMATransferFinishedISR()
    {
       ADCIntClear(ADC1_BASE, 0);
       if (uDMAIntStatus() & (1 << (UDMA_CH24_ADC1_0 & 0x1F)))
       {
          GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_5, 0);
          GPIOPinWrite(GPIO_PORTD_BASE, GPIO_PIN_5, GPIO_PIN_5);
       }
    }
    
    void ADCInit()
    {
       ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 1);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH1); //UZELL_A
       ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH4); //UZELL_B
       ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH5); //UZELL_C
       ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH6); //UZELL_D
       ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH7); //UZELL_E
       ADCSequenceStepConfigure(ADC1_BASE, 0, 5, ADC_CTL_CH2); //UZELL_F
       ADCSequenceStepConfigure(ADC1_BASE, 0, 6, ADC_CTL_CH0); //UZELL_1
       ADCSequenceStepConfigure(ADC1_BASE, 0, 7, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH8); //USTACK
    
       ADCReferenceSet(ADC1_BASE, ADC_REF_INT);
    
       ADCIntRegister(ADC1_BASE, 0, ADC1SS0uDMATransferFinishedISR);
    
       ADCIntEnableEx(ADC1_BASE, ADC_INT_DMA_SS0);
    
       ADCSequenceEnable(ADC1_BASE, 0);
    }
    

  • Hello Christian,

    The ADC_INT_DMA_SS0 is not a valid setting for TM4C123 class of device. Instead you must use ADC_INT_SS0 to enable the interrupt vector.

    Regards
    Amit
  • Hello Amit.

    Thank you. I've already tried this also. But then I'm getting an interrupt everytime the sample sequencer has finished (every ~8µs) and uDMAIntStatus() always returns zero.

    Regards,

    Christian

  • Hello Amit,

    solved it. I have to reinit the uDMA in the ADCSS0 ISR this way:

    ADCIntClear(ADC1_BASE, 0);
    uDMAChannelScatterGatherSet(UDMA_CH24_ADC1_0, MAX_ADC_SAMPLES, (void*)TaskList, true);
    uDMAChannelEnable(UDMA_CH24_ADC1_0);
    

    Thank you.

    Regards

    Christian

  • Hello Christian,

    Glad that you figured it out. May be a code post can be useful for others on the forum.

    Regards
    Amit
  • uint16_t ADC1Values[MAX_ADC_SAMPLES][8];
    #pragma DATA_ALIGN(uDMAControlTable, 1024)
    uint8_t uDMAControlTable[1024];
    
    tDMAControlTable ADC1TaskList[MAX_ADC_SAMPLES];
    
    /* Must not be greater than 256 */
    #define MAX_ADC_SAMPLES 256
    
    void ADC1SS0uDMATransferFinishedISR()
    {
       ADCIntClear(ADC1_BASE, 0);
       uDMAChannelScatterGatherSet(UDMA_CH24_ADC1_0, MAX_ADC_SAMPLES, (void*)ADC1TaskList, true);
       uDMAChannelEnable(UDMA_CH24_ADC1_0);
    }
    
    void ADCInit()
    {
       ADCSequenceConfigure(ADC1_BASE, 0, ADC_TRIGGER_ALWAYS, 1);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 0, ADC_CTL_CH1);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 1, ADC_CTL_CH4);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 2, ADC_CTL_CH5);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 3, ADC_CTL_CH6);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 4, ADC_CTL_CH7);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 5, ADC_CTL_CH2);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 6, ADC_CTL_CH0);
       ADCSequenceStepConfigure(ADC1_BASE, 0, 7, ADC_CTL_IE | ADC_CTL_END | ADC_CTL_CH8);
    
       ADCReferenceSet(ADC1_BASE, ADC_REF_INT);
    
       ADCIntRegister(ADC1_BASE, 0, ADC1SS0uDMATransferFinishedISR);
    
       ADCIntEnable(ADC1_BASE, 0);
    
       ADCSequenceEnable(ADC1_BASE, 0);
    }
    
    void uDMAInit()
    {
       uint16_t i;
    
       memset(uDMAControlTable, 0, sizeof(uDMAControlTable));
       memset(ADC1Values, 0xA5, sizeof(ADC1Values));
    
       /* Create ADC1 TaskList */
       for (i = 0; i < MAX_ADC_SAMPLES; i++)
       {
          ADC1TaskList[i].pvSrcEndAddr = (void *)(((uint8_t *)(ADC1_BASE + ADC_O_SSFIFO0)));
          ADC1TaskList[i].pvDstEndAddr = (void *)(&ADC1Values[i][7]);
          ADC1TaskList[i].ui32Control = UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_SIZE_16 | UDMA_ARB_8 | ((8 - 1) << 4) | UDMA_MODE_PER_SCATTER_GATHER | UDMA_MODE_ALT_SELECT;
          ADC1TaskList[i].ui32Spare = 0;
       }
    
       SysCtlPeripheralEnable(SYSCTL_PERIPH_UDMA);
       uDMAEnable();
       uDMAControlBaseSet(uDMAControlTable);
    
       /* Ensure channel is disabled before modifying register. */
       uDMAChannelDisable(UDMA_CH24_ADC1_0);
       uDMAChannelAssign(UDMA_CH24_ADC1_0);
       uDMAChannelAttributeDisable(UDMA_CH24_ADC1_0, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK);
       uDMAChannelScatterGatherSet(UDMA_CH24_ADC1_0, MAX_ADC_SAMPLES, (void*)ADC1TaskList, true);
    
       uDMAChannelEnable(UDMA_CH24_ADC1_0);
    }
    
    Hi,

    here are the most important function.

    Regards

    Christian