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.

Compiler/TMS320F28379D: Problem with DMA reading ADC conversion result

Part Number: TMS320F28379D

Tool/software: TI C/C++ Compiler

Hi,

I am trying to use the DMA on my f28379D board. I try to trigger the DMA CH5 interrupt by EOC0 generated at the end of conversion. I do run ADC in continuous mode: 

AdcbRegs.ADCINTSEL1N2.bit.INT1CONT = 1; //

I have a check variable in the DMA interrupt routine and I see it is being incremented, however I do not see change in the variable that DMA is supposed to write to. I am also not sure how BURST and TRANSMISSION parameters should be configured, datasheet confuses me here.

I will be very thankful for support. My code is here:

//###########################################################################
//
// FILE:   adc_soc_epwm_cpu01.c
//
// TITLE:  ADC triggering via epwm for F2837xD.
//
//! \addtogroup cpu01_example_list
//! <h1> ADC ePWM Triggering (adc_soc_epwm)</h1>
//!
//! This example sets up the ePWM to periodically trigger the ADC.
//!
//! After the program runs, the memory will contain:\n
//! - \b AdcaResults \b: A sequence of analog-to-digital conversion samples from
//! pin A0. The time between samples is determined based on the period
//! of the ePWM timer.
//
//###########################################################################
// $TI Release: F2837xD Support Library v210 $
// $Release Date: Tue Nov  1 14:46:15 CDT 2016 $
// $Copyright: Copyright (C) 2013-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

//
// Included Files
//
#include "F28x_Project.h"



#define BURST         (FIFO_LVL-1)    // burst size should be less than 8
#define TRANSFER      0              // [(MEM_BUFFER_SIZE/FIFO_LVL)-1]


//
// Function Prototypes
//
void ConfigureADC(void);
void ConfigureEPWM(void);
void SetupADCEpwm(Uint16 channel);
__interrupt void adcb1_isr(void);
__interrupt void local_D_INTCH5_ISR(void);
void dma_init(void);

//__interrupt void local_D_INTCH6_ISR(void);

//
// Defines
//
#define RESULTS_BUFFER_SIZE 256

//
// Globals
//
Uint16 AdcbResults[RESULTS_BUFFER_SIZE];
Uint16 resultsIndex;
volatile Uint16 bufferFull;
volatile Uint16 *DMADest;
Uint16 rdata;     // Receive data buffer
Uint16 check;



void main(void)
{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xD_SysCtrl.c file.
//
    InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xD_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
    InitGpio(); // Skipped for this example

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
    DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xD_PieCtrl.c file.
//
    InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
    IER = 0x0000;
    IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
//
    InitPieVectTable();

    //
    // Ensure DMA is connected to Peripheral Frame 2 bridge (EALLOW protected)
    //
        EALLOW;
        CpuSysRegs.SECMSEL.bit.PF2SEL = 1;
        EDIS;

//
// Map ISR functions
//
    EALLOW;
//    PieVectTable.ADCB1_INT = &adcb1_isr; //function for ADCB interrupt 1
    PieVectTable.DMA_CH5_INT= &local_D_INTCH5_ISR;
    EDIS;

//
// Configure the ADC and power it up
//
    ConfigureADC();

//
// Configure the ePWM
//
    ConfigureEPWM();

//
// Setup the ADC for ePWM triggered conversions on channel 0
//
    dma_init();            // Set up DMA for SPI configuration
    SetupADCEpwm(5);

//
// Enable global Interrupts and higher priority real-time debug events:
//
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
    PieCtrlRegs.PIEIER7.bit.INTx5 = 1;   // Enable PIE Group 7, INT 1 (DMA CH1)
    IER |= M_INT7;                         // Enable CPU INT6
//    IER |= M_INT1; //Enable group 1 interrupts
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

//
// Initialize results buffer
//
    for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
    {
        AdcbResults[resultsIndex] = 0;
    }
    resultsIndex = 0;
    bufferFull = 0;

//
// enable PIE interrupt
//
//    PieCtrlRegs.PIEIER1.bit.INTx2 = 1;

//
// sync ePWM
//
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;  //PWM synchronise
    EDIS;

    StartDMACH5();                       // Start DMA



	for(;;)
	{

	}
}








//
// ConfigureADC - Write ADC configurations and power up the ADC for both
//                ADC A and ADC B
//
void ConfigureADC(void)
{
    EALLOW;

    //
    //write configurations
    //
    AdcbRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4
    AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE);

    //
    //Set pulse positions to late
    //
    AdcbRegs.ADCCTL1.bit.INTPULSEPOS = 1;

    //
    //power up the ADC
    //
    AdcbRegs.ADCCTL1.bit.ADCPWDNZ = 1;

    //
    //delay for 1ms to allow ADC time to power up
    //
    DELAY_US(1000);

    EDIS;
}

//
// ConfigureEPWM - Configure EPWM SOC and compare values
//
void ConfigureEPWM(void)
{

	   EALLOW;
	   GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0b01;
	   GpioCtrlRegs.GPAGMUX1.bit.GPIO0 = 0b00;
	   EDIS;

    EALLOW;
    // Assumes ePWM clock is already enabled
    EPwm1Regs.ETSEL.bit.SOCAEN    = 1;    // Disable SOC on A group
    EPwm1Regs.ETSEL.bit.SOCASEL    = 0b001;   // Select SOC on up-count
    EPwm1Regs.ETPS.bit.SOCAPRD = 1;       // Generate pulse on 1st event
    EPwm1Regs.CMPA.bit.CMPA = 2500;     // Set compare A value
    EPwm1Regs.TBPRD = 5000;             // Set period
    EPwm1Regs.TBCTL.bit.CTRMODE = 0b10;      // up-down
    EPwm1Regs.AQCTLA.bit.ZRO = 0b10;      //
    EPwm1Regs.AQCTLA.bit.PRD = 0b01;      //
    EPwm1Regs.AQCTLA.bit.CAU = 0b01;      //
    EPwm1Regs.AQCTLA.bit.CAD = 0b10;      //


    EDIS;
}

//
// SetupADCEpwm - Setup ADC EPWM acquisition window
//
void SetupADCEpwm(Uint16 channel)
{
    Uint16 acqps;

    //
    //determine minimum acquisition window (in SYSCLKS) based on resolution
    //
    if(ADC_RESOLUTION_12BIT == AdcbRegs.ADCCTL2.bit.RESOLUTION)
    {
        acqps = 14; //75ns
    }
    else //resolution is 16-bit
    {
        acqps = 63; //320ns
    }

    //
    //Select the channels to convert and end of conversion flag
    //
    EALLOW;
    AdcbRegs.ADCSOC0CTL.bit.CHSEL = channel;  //SOC0
    AdcbRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 100 SYSCLK cycles
    AdcbRegs.ADCSOC0CTL.bit.TRIGSEL = 5; //trigger on ePWM1 SOCA/C
    AdcbRegs.ADCINTSEL1N2.bit.INT1SEL = 0; //end of EOC1 will set INT1 flag
    AdcbRegs.ADCINTSEL1N2.bit.INT1E = 1;   //enable INT1 flag
    AdcbRegs.ADCINTSEL1N2.bit.INT1CONT = 1;   //
    AdcbRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //make sure INT1 flag is cleared
    EDIS;
}




void dma_init()
{
    //
    // Initialize DMA
    //

    DMAInitialize();

    DMADest = &rdata;

    //
    DMACH5AddrConfig(DMADest,&AdcbResultRegs.ADCRESULT0);
    DMACH5BurstConfig(1,0,1);
    DMACH5TransferConfig(0,0,1);
    DMACH5ModeConfig(6,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,
                     SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,
                     CHINT_END,CHINT_ENABLE);
}

//
// local_D_INTCH5_ISR - DMA Channel 5 ISR
//
__interrupt void local_D_INTCH5_ISR(void)
{
    EALLOW;  // NEED TO EXECUTE EALLOW INSIDE ISR !!!
    DmaRegs.CH5.CONTROL.bit.TRANSFERSTS = 1;
    DmaRegs.CH5.CONTROL.bit.RUN = 1;
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP7; // ACK to receive more interrupts
                                            // from this PIE group
    EDIS;
    check++;

    return;
}

//
// End of file
//

  • Hello,
    I am writing to let you know that a C2000 team member has been assigned to this post and should be answering shortly.

    Regards
    Baskaran
  • I see a few things--

    1. Make sure that DMADest is being placed in a location that the DMA has access to. You'll probably want to use a #pragma DATA_SECTION.
    2. The size parameter of DMACH5BurstConfig() is supposed to be N-1--that is, if you want to move a single word per burst, you'll want to set this to 0.
    3. I'm guessing you're going to want to fill your buffer every transfer...? If that's the case, I think you'll want to change the size parameter of DMACH5TransferConfig to (RESULTS_BUFFER_SIZE - 1).


    Whitney