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.

TMS320F28388D: DMA ISR is not working for high speed trigger source

Part Number: TMS320F28388D

Hi,

 Currently I am planning to transfer ADC result data to SDRAM via DMA.

And EPWM is my trigger source for ADC.

ADC interrupt is my trigger source for DMA transfer.

When I am using a low sampling rate configuration for ADC , DMA is working fine and DMA Interrupt is coming.

But I increased the Sampling rate(~1MSPS) by increasing the EPWM frequency, The DMA interrupt is not working , but data is getting copied to SDRAM from ADC result register.

I am not able to find any solution to this problem and why this problem is happening for a high speed Trigger source.

Please let me know if I missing something here when I am dealing with high speed trigger sources for DMA.

  • Please see this thread:
    https://e2e.ti.com/support/microcontrollers/c2000-microcontrollers-group/c2000/f/c2000-microcontrollers-forum/1089078/tms320f28388d-adc-samples-acquired-by-mcbsp-at-high-speed-are-lost---high-priority-dma-channel-is-blocked-by-multiple-sdram-refresh-cycles

    Maybe this is the same problem.

    In addition: are you sure you are not getting DMA overrun error? The SDRAM refresh process can take occasionally very long time (depending on your SDRAM speed and refresh timings), and it is possible that the DMA (or rather SDRAM) cannot keep up with such high data rate.


    Regards,
    Andy

  • Kurakula,

    How many DMA channels are you using? What are you doing in your DMA ISR routine? As AndyP pointed out, do you get DMA overun error?

    Also, please share your DMA configuration details.

    Regards,

    Manoj

  • Hi Manoj,

    I am using only one DMA channel. 

    IN my DMA ISR , I am updating my DMA destination register and destination shadow register contents. But DMA interrupt only not occurring. but data is getting copied from source to destination via DMA.

    As of now I have disabled the overrun interrupt.

    Here is my DMA configuration.

    //
    // Buffer in far memory.
    //
    __attribute__((far)) volatile uint16_t extSDRAMBuf[1048576];

    void configDMAChannel1()
    {
    //
    // Configure DMA Channel 1 (16 - bit datasize).
    //
    destDMA = extSDRAMBuf;
    //srcDMA = (volatile uint16_t *)localSrcRAMBuf;
    srcDMA = (volatile uint16_t *)(ADCBRESULT_BASE+2);
    DMA_configAddresses(DMA_CH1_BASE,(const void*)destDMA,(const void*)srcDMA);
    DMA_configBurst(DMA_CH1_BASE, 1U, 1U, 1U); //chnaged
    //!@NOTE In order to acieve const src , keep trsnfer srcstep to Zero
    DMA_configTransfer(DMA_CH1_BASE, 1024, 0U, 1);
    DMA_configWrap(DMA_CH1_BASE, 0x10000U, 0, 0x10000U, 0);

    //
    // Configure DMA trigger source as software, enable oneshot, disable
    // continuous mode, data size of DMA transfer to 16 bits.
    //
    DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_ADCB1, (DMA_CFG_ONESHOT_DISABLE
    | DMA_CFG_CONTINUOUS_DISABLE | DMA_CFG_SIZE_16BIT));

    //
    // Enable selected peripheral trigger to start a DMA transfer on DMA
    // channel 1.
    //
    DMA_enableTrigger(DMA_CH1_BASE);

    //DMA_enableOverrunInterrupt(DMA_CH1_BASE);
    DMA_disableOverrunInterrupt(DMA_CH1_BASE);
    DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH1_BASE);
    //
    // Clear any spurious Peripheral interrupts flags.
    //
    DMA_clearTriggerFlag(DMA_CH1_BASE);

    //
    // Clear any spurious sync error flags.
    //
    DMA_clearErrorFlag(DMA_CH1_BASE);
    }

    //DMA_ISR
    __interrupt void dmach1ISR(void)
    {
    DMA_configDestAddress(DMA_CH1_BASE, (const void*)(extSDRAMBuf+(1024*usn_DMA_ISR_Counter)));
    DMA_disableTrigger(DMA_CH1_BASE);
    DMA_enableTrigger(DMA_CH1_BASE);

    DMA_startChannel(DMA_CH1_BASE);
    usn_DMA_ISR_Counter++;
    //STOP DMA after transferring 1048576(1M samples)
    if(usn_DMA_ISR_Counter > 1024)
    DMA_stopChannel(DMA_CH1_BASE);
    //
    // Stop the ADC by removing the trigger for SOC0
    //
    //ADC_setInterruptSOCTrigger(myADC0_BASE, ADC_SOC_NUMBER0,
    // ADC_INT_SOC_TRIGGER_NONE);
    // ADC_setInterruptSOCTrigger(myADC1_BASE, ADC_SOC_NUMBER0,
    // ADC_INT_SOC_TRIGGER_NONE);

    //
    // Acknowledge interrupt
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);

    }

  • I have enabled the Overrun Interrupt but i am not sure how to check overrun has occurred or not. please let me know how to check overrun is happening or not

  • Please check CONTROL.OVRFLG flag bit to know whether overun condition occured. Also, hope you realize that DMA interrupt doesn't happen for each burst, it happens for every transfer.

    So, in your case, you will get DMA interrupt only after every 1024 word transfer.

  • Hi Manoj,

    I have checked CONTROL.OVRFLG flag bit but it was not set and it is always zero.

    I have check CONTROL.ERRCLR flag also but it is also always zero.

    But I observed a strange behavior that , DMA interrupt is coming but not at expected interval .

    As I mentioned in my previous response, ADC interrupt is Trigger source for DMA channel and I have taken a uint32_t counter and incrementing in ADC_ISR routines, so that I will get to know how many ADC conversions happened and how many times trigger happened for DMA.

    Then I found that DMA interrupt is coming for 122042(not fixed, vary if reset the MCU and run again) counts of ADC interrupts, but I am expecting an DMA interrupt for 1024 counts of ADC interrupts as my transfer config for DMA is 1024.

    1st DMA interrupt occurring at 122042 counts of ADC interrupt( i.e 122042 ADC interrupts are encountered)

    2nd DMA interrupt occurring at 225192  counts of ADC interrupt

    3rd  DMA interrupt occurring at 506195  counts of ADC interrupt.

     

    the pattern doesn't make any sense.  And if you reset the MCU and start testing again , you will get some other random numbers( DMA interrupt after ADC interrupt counts).

    The same configuration works as expected if I reduce the sampling rate(100KSPS) of the ADC, DMA interrupt is properly coming after 1024 transactions(1024 ADC interrupt counts).

    Please let me know if I am missing something here , when dealing with high speed trigger source for DMA (1MSPS of ADC).

     Note: As of now there is no to much load on MCU also , only 1 ADC ,1 EPWM, SDRAM  and 1 DMA channel is configured.

    interrupt wise also only ADC interrupt nd DMA interrupt are configured and enabled.

  • How are you interfacing with SDRAM (SPI (or) EMIF)? Are there other high priority interrupt sources which would cause delay in count? Instead of writing to SDRAM, can u try writing to F28388D RAM location and see whether this problem goes away? I'm wondering whether this problem is introduced by SDRAM interface

  • I am interfacing with SDRAM with EMIF only.

    There only two interrupts in my entire code, one is ADC interrupt and another one is DMA interrupt. ADC interrupt(PIE Group 1 Vectors)  is having a high priority than DMA interrupt(PIE Group 7 Vectors) and its necessary also.

    As suggested, I have tried F28388D RAM as my destination for DMA, and commented all the EMIF configuration part, still the behavior is same.

    Also I have reduced the ADC sampling speed to 100ksps,  DMA working as excepted with F28388D RAM also.

    I feel that in DMA only some problem is there , when its dealing with high speed trigger sources.

    But I am not find which configuration exactly causing problem.

  • Kurakula,

    In your earlier post you had reported you were not getting DMA interrupts. I hope we have already got around that problem. correct?

    Now you main question is shouldn't my DMA interrupt be periodic (with same cycle count)? correct? Can you privately message me your email address? I would like to have webex call to better understand the problem?

    Regards,

    Manoj

  • After changing the ADC configuration , DMA interrupt is working as expected.

    In ADC configuration, I have enabled continuous mode for an ADC interrupt.

    So that ADC interrupt will be generated irrespective of interrupt flag bit set or not. So DMA is getting its event triggers perfectly and DMA ISR is working as expected .

    After going through TRM I found this mode.

    Special thanks for  for quick support. 

  • In continuation to my previous response, I am adding here my ADC configuration code details here.

     

    //ADC INIT for A
    void AdcA_init()
    {
    //myADC0 initialization

    // ADC Initialization: Write ADC configurations and power up the ADC
    // Configures the analog-to-digital converter module prescaler.
    ADC_setPrescaler(ADCA_BASE, ADC_CLK_DIV_1_0/*ADC_CLK_DIV_4_0*/);
    // Configures the analog-to-digital converter resolution and signal mode.
    ADC_setMode(ADCA_BASE,ADC_RESOLUTION_16BIT /*ADC_RESOLUTION_12BIT*/, ADC_MODE_DIFFERENTIAL/*ADC_MODE_SINGLE_ENDED*/);
    // Sets the timing of the end-of-conversion pulse
    ADC_setInterruptPulseMode(ADCA_BASE, ADC_PULSE_END_OF_CONV);
    // Powers up the analog-to-digital converter core.
    ADC_enableConverter(ADCA_BASE);
    // Delay for 1ms to allow ADC time to power up
    DEVICE_DELAY_US(500);

    // SOC Configuration: Setup ADC EPWM channel and trigger settings
    // Disables SOC burst mode.
    //ADC_disableBurstMode(ADCA_BASE); 07-04-2022

    // Sets the priority mode of the SOCs.
    ADC_setSOCPriority(ADCA_BASE, ADC_PRI_ALL_ROUND_ROBIN);
    // Start of Conversion 2 Configuration
    // Configures a start-of-conversion (SOC) in the ADC and its interrupt SOC trigger.
    // SOC number : 1
    // Trigger : ADC_TRIGGER_EPWM1_SOCA
    // Channel : ADC_CH_ADCIN0_ADCIN1
    // Sample Window : 15 SYSCLK cycles
    // Interrupt Trigger: ADC_INT_SOC_TRIGGER_NONE
    ADC_setupSOC(ADCA_BASE, ADC_SOC_NUMBER0, ADC_TRIGGER_EPWM7_SOCA, ADC_CH_ADCIN0_ADCIN1, 15U);

    //ADDED by SOM- 07-04-2022
    ADC_enableContinuousMode(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_setInterruptSOCTrigger(ADCA_BASE, ADC_SOC_NUMBER0, ADC_INT_SOC_TRIGGER_NONE);
    // ADC Interrupt 1 Configuration
    // SOC/EOC number : 1
    // Interrupt Source: enabled
    ADC_setInterruptSource(ADCA_BASE, ADC_INT_NUMBER1, ADC_SOC_NUMBER0);

    ADC_enableInterrupt(ADCA_BASE, ADC_INT_NUMBER1);
    ADC_clearInterruptStatus(ADCA_BASE, ADC_INT_NUMBER1);


    Interrupt_register(INT_ADCA1, &adcA1ISR);
    Interrupt_enable(INT_ADCA1);

    //ADCA_BASE
    }
    __interrupt void adcA1ISR(void)
    {

    }

    Note: DMA configuration I have already added in my previous responses in the same thread.

    Regards,

    Someshwar K

    L&T Technology Services.