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.

TMS320F280039C: DMA Burst destination step

Part Number: TMS320F280039C

Hi Experts,

                 I am working with the DMA, starting with the example adc_ex6_soc_continuous_dma.c.

I am sampling two ADCs at the same time, with 2 channels on each. I want that on each transfer, the moved word from the ADC goes to a different array.  

After reading all the documentation, it is supposed that if you write a value to  DSTBURSTSTEP, on each transfer the destination is incremented by this value.

So together with DSTTRANSFERSTEP it should let me move the values to different arrays.

Well, It doesn't matter what I write on the DSTBURSTSTEP register, the values are moved together. In other words, the moved data is one value next to the other.

Here is the modified example. I have checked with the debugger that the register is properly wrtitten

//###########################################################################
//
// FILE:   adc_ex6_soc_continuous_dma.c
//
// TITLE:  ADC continuous conversions read by DMA.
//
//! \addtogroup driver_example_list
//! <h1> ADC Continuous Conversions Read by DMA (adc_soc_continuous_dma)</h1>
//!
//! This example sets up two ADC channels to convert simultaneously. The
//! results will be transferred by the DMA into a buffer in RAM.
//!
//! \b External \b Connections \n
//!  - A3 & C3 pins should be connected to signals to convert
//!
//! \b Watch \b Variables \n
//! - \b myADC0DataBuffer \b: a digital representation of the voltage on pin A3\n
//! - \b myADC1DataBuffer \b: a digital representation of the voltage on pin C3\n
//!
//
//#############################################################################
//
//
// $Copyright:
// Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//

//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "board.h"

//
// Function Prototypes
//
__interrupt void dmach1ISR(void);

void configureEPWM(uint32_t epwmBase);
void initializeDMA(void);
void configureDMAChannels(void);

//
// Defines
//
#define RESULTS_BUFFER_SIZE     80  //buffer for storing conversion results
#define CHANNELS                2
//
// Globals
//
#pragma DATA_SECTION(myADC0DataBuffer, "ramgs0");
#pragma DATA_SECTION(myADC1DataBuffer, "ramgs0");
uint16_t myADC0DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
uint16_t myADC1DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
volatile uint16_t done;

void main(void)
{
    uint16_t resultsIndex;

    //
    // Initialize device clock and peripherals
    //
    Device_init();

    //
    // Disable pin locks and enable internal pullups.
    //
    Device_initGPIO();

    //
    // Initialize PIE and clear PIE registers. Disables CPU interrupts.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    // 
    // Board Initializatrion
    // - Configure the ADCA & ADCC and power it up
    // - Setup the ADC for continuous conversions on channels A3 and C3
    // - Set up ISR for ADCA INT1 - occurs after first conversion
    // - Enable specific PIE & CPU interrupts: ADCA INT1 - Group 1, interrupt 1
    // 
    Board_init();

    //
    // Set up ISRs used by this example
    // ISR for DMA ch1 - occurs when DMA transfer is complete
    //
    Interrupt_register(INT_DMA_CH1, &dmach1ISR);

    //
    // Enable specific PIE & CPU interrupts:
    // DMA interrupt - Group 7, interrupt 1
    //
    Interrupt_enable(INT_DMA_CH1);

    //
    // Stop the ePWM clock
    //
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Call the set up function for ePWM 2
    //
    configureEPWM(EPWM2_BASE);

    //
    // Start the ePWM clock
    //
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Initialize the DMA & configure DMA channels 1 & 2
    //
    initializeDMA();
    configureDMAChannels();

    //
    // Initialize results buffer
    //
    for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
    {
        myADC0DataBuffer[0][resultsIndex] = 0;
        myADC0DataBuffer[1][resultsIndex] = 0;
        myADC1DataBuffer[0][resultsIndex] = 0;
        myADC1DataBuffer[1][resultsIndex] = 0;
    }

    //
    // Clearing all pending interrupt flags
    //
    DMA_clearTriggerFlag(DMA_CH1_BASE);   // DMA channel 1
    DMA_clearTriggerFlag(DMA_CH2_BASE);   // DMA channel 2
    HWREGH(myADC0_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCA
    HWREGH(myADC1_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCC
    EPWM_forceADCTriggerEventCountInit(EPWM2_BASE, EPWM_SOC_A); // EPWM2 SOCA
    EPWM_clearADCTriggerFlag(EPWM2_BASE, EPWM_SOC_A);    // EPWM2 SOCA


    //
    // Enable global Interrupts and higher priority real-time debug events:
    //
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

    //
    // Start DMA
    //
    done = 0;
    DMA_startChannel(DMA_CH1_BASE);
    DMA_startChannel(DMA_CH2_BASE);

    //
    // Finally, enable the SOCA trigger from ePWM. This will kick off
    // conversions at the next ePWM event.
    //
    EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);

    //
    // Loop until the ISR signals the transfer is complete
    //
    while(done == 0)
    {
        __asm(" NOP");
    }
    //ESTOP0;
}

//
// adcA1ISR - This is called after the very first conversion and will disable
//                      the ePWM SOC to avoid re-triggering problems.
//
#pragma CODE_SECTION(adcA1ISR, ".TI.ramfunc");
__interrupt void adcA1ISR(void)
{

    //
    // Disable this interrupt from happening again
    //
    Interrupt_disable(INT_ADCA1);

    //
    // Acknowledge interrupt
    //
    Interrupt_clearACKGroup(INT_myADC0_1_INTERRUPT_ACK_GROUP);
}

//
// dmach1ISR - This is called at the end of the DMA transfer, the conversions
//              are stopped by removing the trigger of the first SOC from
//              the last.
//
#pragma CODE_SECTION(dmach1ISR, ".TI.ramfunc");
__interrupt void dmach1ISR(void)
{
    //
    // Acknowledge interrupt
    //
    Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
}

//
// configureEPWM - Set up the ePWM2 module so that the A output has a period
//                 of 40us with a 50% duty. The SOCA signal is coincident with
//                 the rising edge of this.
//
void configureEPWM(uint32_t epwmBase)
{
    //
    // Make the timer count up with a period of 40us
    //
    HWREGH(epwmBase + EPWM_O_TBCTL) = 0x0000U;
    EPWM_setTimeBasePeriod(epwmBase, 124U);

    //
    // Set the A output on zero and reset on CMPA
    //
    EPWM_setActionQualifierAction(epwmBase, EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_HIGH,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(epwmBase, EPWM_AQ_OUTPUT_A,
                                  EPWM_AQ_OUTPUT_LOW,
                                  EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    //
    // Set CMPA to 20us to get a 50% duty
    //
    EPWM_setCounterCompareValue(epwmBase, EPWM_COUNTER_COMPARE_A, 60U);

    //
    // Start ADC when timer equals zero (note: don't enable yet)
    //
    EPWM_setADCTriggerSource(epwmBase, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
    EPWM_setADCTriggerEventPrescale(epwmBase, EPWM_SOC_A, 1U);

    //
    // Enable initialization of the SOCA event counter. Since we are
    // disabling the ETSEL.SOCAEN bit, we need a way to reset the SOCACNT.
    // Hence, enable the counter initialize control.
    //
    EPWM_enableADCTriggerEventCountInit(epwmBase, EPWM_SOC_A);
}

//
// initializeDMA - Initialize DMA through hard reset
//
void initializeDMA(void)
{
    //
    // Perform a hard reset on DMA
    //
    DMA_initController();

    //
    // Allow DMA to run free on emulation suspend
    //
    DMA_setEmulationMode(DMA_EMULATION_FREE_RUN);
}

//
// configureDMAChannels - Initialize DMA ch 1 to transfer ADCA results
//                        and DMA ch 2 to transfer ADCB results
//
void configureDMAChannels(void)
{
    //
    // DMA channel 1 set up for ADCA
    //
    DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)&myADC0DataBuffer,
                        (uint16_t *)ADCARESULT_BASE);

    //
    // Perform enough 2-word bursts to fill the results buffer. Data will be
    // transferred 32 bits at a time hence the address steps below.
    //
    DMA_configBurst(DMA_CH1_BASE, 2, 2, 2); // It doesn't matters the value of DSTBURSTSTEP, the values are moved one nect to the other


    DMA_configTransfer(DMA_CH1_BASE, (RESULTS_BUFFER_SIZE), 0, 2);
    DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_ADCA2,
                   (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                    DMA_CFG_SIZE_32BIT));

    DMA_enableTrigger(DMA_CH1_BASE);
    DMA_disableOverrunInterrupt(DMA_CH1_BASE);
    DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH1_BASE);

    //
    // DMA channel 2 set up for ADCC
    //
    DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)&myADC1DataBuffer,
                        (uint16_t *)ADCCRESULT_BASE);

    //
    // Perform enough 2-word bursts to fill the results buffer. Data will be
    // transferred 32 bits at a time hence the address steps below.
    //

    DMA_configBurst(DMA_CH2_BASE, 2, 2, 2);


    DMA_configTransfer(DMA_CH2_BASE, (RESULTS_BUFFER_SIZE), 0, 2);
    DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_ADCA2,
                   (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                    DMA_CFG_SIZE_32BIT));

    DMA_enableTrigger(DMA_CH2_BASE);
    DMA_disableOverrunInterrupt(DMA_CH2_BASE);
    DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END);
    DMA_enableInterrupt(DMA_CH2_BASE);
}

//
// End of file
//

Probably there is something that I don't configure properly

Thanks in Advance,

Fernando Gatto

  • Gatto,

    Can you elaborate your system requirement with respect to DMA? which memory range are you trying to use? Why is ADCARESULT_BASE used as source address in both CH1 and CH2? Are you trying to store ADCARESULT_BASE  results in two buffers (myADC0DataBuffer & myADC1DataBuffer)?

    Do you want to store odd results in myADC0DataBuffer and even results in myADC1DataBuffer? Please provide more details.

    Regards,

    Manoj

  • Hi Manoj,

                   Thanks for your response. The final idea of what I am trying to do is the following:

    Continuous sampling 4 channels at 980Ksamples/s in alternative buffers of 80 samples. In other words, while I am processing 80 samples of each buffer, the DMA continues transferring samples to the second set of buffers. Now I am reviewing the channels sets and there are some errors, once I get the code Ok. I will post it again. It will be very helpful if there is some example of a continuous sampling program

                            Regards,

                           Fernando

  • Here is the code with the ADC corrected. It samples the 4 mentioned channels, alternating the destination buffers but I can't modify the destination step of the burst in a way that each sample of each channel is copied in the correct array. The copied values are placed together, it doesn't matter what destination busrst step I write.

    Regards

    //###########################################################################
    //
    // FILE:   adc_ex6_soc_continuous_dma.c
    //
    // TITLE:  ADC continuous conversions read by DMA.
    //
    //
    //#############################################################################
    //
    //
    // $Copyright:
    // Copyright (C) 2021 Texas Instruments Incorporated - http://www.ti.com/
    //
    // Redistribution and use in source and binary forms, with or without 
    // modification, are permitted provided that the following conditions 
    // are met:
    // 
    //   Redistributions of source code must retain the above copyright 
    //   notice, this list of conditions and the following disclaimer.
    // 
    //   Redistributions in binary form must reproduce the above copyright
    //   notice, this list of conditions and the following disclaimer in the 
    //   documentation and/or other materials provided with the   
    //   distribution.
    // 
    //   Neither the name of Texas Instruments Incorporated nor the names of
    //   its contributors may be used to endorse or promote products derived
    //   from this software without specific prior written permission.
    // 
    // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
    // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
    // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
    // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
    // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
    // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
    // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
    // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    // $
    //#############################################################################
    //
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    //
    // Function Prototypes
    //
    __interrupt void dmach1ISR(void);
    
    void configureEPWM(uint32_t epwmBase);
    void initializeDMA(void);
    void configureDMAChannels(void);
    
    //
    // Defines
    //
    #define RESULTS_BUFFER_SIZE     4  //buffer for storing conversion results
    #define CHANNELS                2
    //
    // Globals
    //
    #pragma DATA_SECTION(myADC_A0_DataBuffer, "ramgs0");
    #pragma DATA_SECTION(myADC_B0_DataBuffer, "ramgs0");
    #pragma DATA_SECTION(myADC_A1_DataBuffer, "ramgs0");
    #pragma DATA_SECTION(myADC_B1_DataBuffer, "ramgs0");
    
    uint16_t myADC_A0_DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
    uint16_t myADC_B0_DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
    
    uint16_t myADC_A1_DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
    uint16_t myADC_B1_DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];
    
    volatile uint16_t dest_buffer;
    
    void main(void)
    {
        uint16_t resultsIndex;
    
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pullups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        // 
        // Board Initializatrion
        // - Configure the ADCA & ADCC and power it up
        // - Setup the ADC for continuous conversions on channels A3 and C3
        // - Set up ISR for ADCA INT1 - occurs after first conversion
        // - Enable specific PIE & CPU interrupts: ADCA INT1 - Group 1, interrupt 1
        // 
        Board_init();
    
        //
        // Set up ISRs used by this example
        // ISR for DMA ch1 - occurs when DMA transfer is complete
        //
        Interrupt_register(INT_DMA_CH2, &dmach1ISR);
    
        //
        // Enable specific PIE & CPU interrupts:
        // DMA interrupt - Group 7, interrupt 1
        //
        Interrupt_enable(INT_DMA_CH2);
    
        //
        // Stop the ePWM clock
        //
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Call the set up function for ePWM 2
        //
        configureEPWM(EPWM2_BASE);
    
        //
        // Start the ePWM clock
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Initialize the DMA & configure DMA channels 1 & 2
        //
        initializeDMA();
        configureDMAChannels();
    
        //
        // Initialize results buffer
        //
        for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
        {
            myADC_A0_DataBuffer[0][resultsIndex] = 0;
            myADC_A0_DataBuffer[1][resultsIndex] = 0;
            myADC_A1_DataBuffer[0][resultsIndex] = 0;
            myADC_A1_DataBuffer[1][resultsIndex] = 0;
            myADC_B0_DataBuffer[0][resultsIndex] = 0;
            myADC_B0_DataBuffer[1][resultsIndex] = 0;
            myADC_B1_DataBuffer[0][resultsIndex] = 0;
            myADC_B1_DataBuffer[1][resultsIndex] = 0;
        }
    
        //
        // Clearing all pending interrupt flags
        //
        DMA_clearTriggerFlag(DMA_CH1_BASE);   // DMA channel 1
        DMA_clearTriggerFlag(DMA_CH2_BASE);   // DMA channel 2
        HWREGH(myADC0_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCA
        HWREGH(myADC1_BASE + ADC_O_INTFLGCLR) = 0x3U; // ADCC
        EPWM_forceADCTriggerEventCountInit(EPWM2_BASE, EPWM_SOC_A); // EPWM2 SOCA
        EPWM_clearADCTriggerFlag(EPWM2_BASE, EPWM_SOC_A);    // EPWM2 SOCA
        dest_buffer = 0;
    
        //
        // Enable global Interrupts and higher priority real-time debug events:
        //
        EINT;  // Enable Global interrupt INTM
        ERTM;  // Enable Global realtime interrupt DBGM
    
        //
        // Start DMA
        //
        dest_buffer = 1;
        DMA_startChannel(DMA_CH1_BASE);
        DMA_startChannel(DMA_CH2_BASE);
        DMA_enableTrigger(DMA_CH1_BASE);
        DMA_enableTrigger(DMA_CH2_BASE);
        //
        // Finally, enable the SOCA trigger from ePWM. This will kick off
        // conversions at the next ePWM event.
        //
        EPWM_enableADCTrigger(EPWM2_BASE, EPWM_SOC_A);
    
        //
        // Loop until the ISR signals the transfer is complete
        //
        while(1)
        {
            __asm(" NOP");
        }
    
    }
    
    //
    // adcA1ISR - This is called after the very first conversion and will disable
    //                      the ePWM SOC to avoid re-triggering problems.
    //
    #pragma CODE_SECTION(adcA1ISR, ".TI.ramfunc");
    __interrupt void adcA1ISR(void)
    {
        //
        // Disable this interrupt from happening again
        //
        Interrupt_disable(INT_ADCA1);
    
        //
        // Acknowledge interrupt
        //
        Interrupt_clearACKGroup(INT_myADC0_1_INTERRUPT_ACK_GROUP);
    }
    
    //
    // dmach1ISR - This is called at the end of the DMA transfer, the conversions
    //              are stopped by removing the trigger of the first SOC from
    //              the last.
    //
    #pragma CODE_SECTION(dmach1ISR, ".TI.ramfunc");
    __interrupt void dmach1ISR(void)
    {
        if( dest_buffer == 1 )
        {
            dest_buffer = 2;
    
            DMA_configDestAddress(DMA_CH1_BASE, (uint16_t *)&myADC_A1_DataBuffer);
            DMA_configDestAddress(DMA_CH2_BASE, (uint16_t *)&myADC_B1_DataBuffer);
        }
        else if( dest_buffer == 2 )
        {
            dest_buffer = 1;
    
            DMA_configDestAddress(DMA_CH1_BASE, (uint16_t *)&myADC_A0_DataBuffer);
            DMA_configDestAddress(DMA_CH2_BASE, (uint16_t *)&myADC_B0_DataBuffer);
        }
    
        //
        // Acknowledge interrupt
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7);
    }
    
    //
    // configureEPWM - Set up the ePWM2 module to 960Khz
    //
    void configureEPWM(uint32_t epwmBase)
    {
        //
        // Make the timer count up with a period of 40us
        //
        HWREGH(epwmBase + EPWM_O_TBCTL) = 0x0000U;
        EPWM_setTimeBasePeriod(epwmBase, 124U);
    
        //
        // Set the A output on zero and reset on CMPA
        //
        EPWM_setActionQualifierAction(epwmBase, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(epwmBase, EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
        //
        // Set CMPA to 20us to get a 50% duty
        //
        EPWM_setCounterCompareValue(epwmBase, EPWM_COUNTER_COMPARE_A, 60U);
    
        //
        // Start ADC when timer equals zero (note: don't enable yet)
        //
        EPWM_setADCTriggerSource(epwmBase, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO);
        EPWM_setADCTriggerEventPrescale(epwmBase, EPWM_SOC_A, 1U);
    
        //
        // Enable initialization of the SOCA event counter. Since we are
        // disabling the ETSEL.SOCAEN bit, we need a way to reset the SOCACNT.
        // Hence, enable the counter initialize control.
        //
        EPWM_enableADCTriggerEventCountInit(epwmBase, EPWM_SOC_A);
    }
    
    //
    // initializeDMA - Initialize DMA through hard reset
    //
    void initializeDMA(void)
    {
        //
        // Perform a hard reset on DMA
        //
        DMA_initController();
    
        //
        // Allow DMA to run free on emulation suspend
        //
        DMA_setEmulationMode(DMA_EMULATION_STOP);
    }
    
    //
    // configureDMAChannels - Initialize DMA ch 1 to transfer ADCA results
    //                        and DMA ch 2 to transfer ADCB results
    //
    
    void configureDMAChannels(void)
    {
        //
        // DMA channel 1 set up for ADCA
        //
        DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)&myADC_A0_DataBuffer,
                            (uint16_t *)ADCARESULT_BASE);
    
        //
        // Perform enough 2-word bursts to fill the results buffer. Data will be
        // transferred 32 bits at a time hence the address steps below.
        //
        DMA_configBurst(DMA_CH1_BASE, 2, 2, 2); // No matters which value I write in the dststep, the values are copied one next to the other
    
    
        DMA_configTransfer(DMA_CH1_BASE, (RESULTS_BUFFER_SIZE), 0, 2);
        DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_ADCA2,
                       (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                        DMA_CFG_SIZE_32BIT));
    
    
        //DMA_enableTrigger(DMA_CH1_BASE);
        DMA_disableOverrunInterrupt(DMA_CH1_BASE);
        //DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_BEGINNING);
        //DMA_enableInterrupt(DMA_CH1_BASE);
    
        //
        // DMA channel 2 set up for ADCC
        //
        DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)&myADC_B0_DataBuffer,
                            (uint16_t *)ADCBRESULT_BASE);
    
        //
        // Perform enough 2-word bursts to fill the results buffer. Data will be
        // transferred 32 bits at a time hence the address steps below.
        //
    
        DMA_configBurst(DMA_CH2_BASE, 2, 2, 2); // No matters which value I write in the dststep, the values are copied one next to the other
    
    
    
        DMA_configTransfer(DMA_CH2_BASE, (RESULTS_BUFFER_SIZE), 0, 2);
        DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_ADCB2,
                       (DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE |
                        DMA_CFG_SIZE_32BIT));
    
    
        //DMA_enableTrigger(DMA_CH2_BASE);
        DMA_disableOverrunInterrupt(DMA_CH2_BASE);
        DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_BEGINNING);
        DMA_enableInterrupt(DMA_CH2_BASE);
    }
    
    //
    // End of file
    //
    

  • Posting the code is not going to help me. Can you answer my questions in earlier post?

    Are you saying you have 4 buffer which will store 80 samples? Once you fill the buffer with first 80 samples, you want to start storing in next buffer?

  • Hi Manoj,

                   Yes, the idea is to alternate buffers with the results of the 4 channels ( 2 on each ADC )

    Having each buffer defined as uint16_t myADC_A0_DataBuffer[CHANNELS][RESULTS_BUFFER_SIZE];

    I want that each sample goes to its corresponding place as this

    myADC_A0_DataBuffer[0][0] = first sample of ADCA SOC0

    myADC_A0_DataBuffer[1][0] = first sample of ADCA SOC1

    As the last word ( myADC_A0_DataBuffer[1][0] ) is not next to myADC_A0_DataBuffer[0][0] I supposed that adjusting the burst dst step could manage to do that. But no matter what I write using DMA_configBurst(), I always get this

    myADC_A0_DataBuffer[0][0] = first sample of ADCA SOC0

    myADC_A0_DataBuffer[0][1] = first sample of ADCA SOC1

    Regards,

  • Fernando,

    Lets say you have two buffers shown below.

    Buffer 1 = 0xC000

    Buffer 2 = 0xC050

    Are you expecting the below behavior?

    0xC000 - first sample of ADCA SOC0

    0xC050 - first sample of ADCA SOC1

    0xC001 - Second sample of ADCA SOC0

    0xC051 - Second sample of ADCA SOC1

    Regards,

    Manoj

  • Exactly, that is what I want to do, and I can't. The code is the last one I've posted.

    One doubt about the DMA configuration of the example is why is using the 32bit mode.

                       Regards,

                       Fernando

  • Fernando,

    Try the below DMA settings.

    Burst Size                        = 2
    Source Burst Step            = 1
    Destination Burst Step    = 80
    DATASIZE                     = 16-bit data transfer size


    Source Transfer Step          = -1
    Destination Transfer Step    = -79

    Regards,

    Manoj

  • Thank you, this setting works