Hi anyone can do help:
Currently I am working on the F28377D (development tools). I tried to use DMA to read the ADC. Now I have two problems:
1, DMA can be triggered by ADC's interrupt, but each time the ADC's interrupt function will be run with the DMA.
That means the CPU will response each ADC interruption, and the DMA becomes no sense at all.
2, DMA can not read the ADC result registers correctly. In other words, the DMA's registers' value are changing with the ADC interruption, and I can see that the values in source/destination address registers are correct; however, there is no output to the destination variable. --- it may not read the ADC result register, or it may not write the result to the destination variable address.
From the datasheet(TMS320F2837xD Delfino Microcontrollers, Technical Reference Manual), at the DMA part(page591), 'DMA Block Diagram' shows that CPU1/2 Bus can access the ADC result registers, but CPU1/2DMA bus looks like can not.
Thanks for your reading; and if you can answer them, I appreciate it.
-----------------------------------
#include "F28x_Project.h" // Device Headerfile and Examples Include File
#include "F2837xD_struct.h"
#include "F2837xD_Dma_defines.h"
// function prototypes
void ConfigureADC(void);
void ConfigureEPWM(void);
void ConfigureDAC(void);
void SetupADCEpwm(void);
interrupt void adca1_isr(void);
// variables
#define RESULTS_BUFFER_SIZE 256
#define MAX_SAMPLES 1024
#define ONE_WORD_BURST 0 // 16-bit word per burst
#define TWO_WORD_BURST 1 // 32-bit word per burst
#define SOURCE_NO_ADDRESS_CHANGE 0
#define DESTINATION_INCREMENT_ONE_ADDRESS 1
#define TRANSFER_SIZE_256 255
#define TRANSFER_STEP_SOURCE_NO_CHANGE 0
#define TRANSFER_STEP_DEST_INCREMENT_ONE_ADDRESS 1
volatile uint16_t *DMA1Source, *DMA1Dest;
volatile Uint16 DMABuf1[RESULTS_BUFFER_SIZE]; //DMA buffer store ADC results
__interrupt void local_DMACH1_ISR(void);
void DMA_configure(void);
volatile uint16_t DMA_Done = 0;
Uint16 AdcaResults[RESULTS_BUFFER_SIZE];
Uint16 AdcbResults[RESULTS_BUFFER_SIZE];
Uint16 resultsIndex;
Uint16 ToggleCount = 0;
Uint16 dacOffset;
Uint16 dacOutput;
Uint16 sineEnable = 0;
extern int QuadratureTable[40];
Uint16 i;
void main(void)
{
// Initialize System Control: PLL, WatchDog, enable Peripheral Clocks
InitSysCtrl();
EALLOW;
ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 0;
EDIS;
// Initialize GPIO:
InitGpio(); // configure default GPIO
EALLOW;
GpioCtrlRegs.GPADIR.bit.GPIO8 = 1; // used as input to ADC
GpioCtrlRegs.GPADIR.bit.GPIO31 = 1; // drives LED LD2 on controlCARD
EDIS;
GpioDataRegs.GPADAT.bit.GPIO8 = 0; // force GPIO8 output LOW
GpioDataRegs.GPADAT.bit.GPIO31 = 1;// turn off LED
// Clear all interrupts and initialize PIE vector table:
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Map ISR functions
EALLOW;
PieVectTable.DMA_CH1_INT = &local_DMACH1_ISR; //function for DMA interrupt 1
PieVectTable.ADCA1_INT = &adca1_isr;
EDIS;
// Enable global Interrupts and higher priority real-time debug events:
// IER = M_INT7 ; //Enable INT7 (7.1 DMA Ch1)
EnableInterrupts();
// Configure the ADC and power it up
ConfigureADC();
// Configure the ePWM
ConfigureEPWM();
// Setup the ADC for ePWM triggered conversions on channel 0
SetupADCEpwm();
//--- Enable the ADC interrupt
EALLOW;
PieCtrlRegs.PIEIER1.bit.INTx1 = 1; // Enable ADCINT in PIE group 1
IER |= 0x0001; // Enable INT1 in IER to enable PIE group
EDIS;
DMA_configure();
// Initialize results buffer
for(resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++)
{
AdcaResults[resultsIndex] = 0;
AdcbResults[resultsIndex] = 0;
DMABuf1[i] = 0;
}
resultsIndex = 0;
EALLOW;
// Sync ePWM
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Start ePWM
EPwm2Regs.TBCTL.bit.CTRMODE = 0; // un-freeze and enter up-count mode
do {
GpioDataRegs.GPADAT.bit.GPIO31 = 0; // Turn on LED
DELAY_US(1000 * 500); // ON delay
GpioDataRegs.GPADAT.bit.GPIO31 = 1; // Turn off LED
DELAY_US(1000 * 500); // OFF delay
} while(1);
}
void DMA_configure(void)
{
EALLOW;
CpuSysRegs.SECMSEL.bit.VBUS32_1 = 1;
EDIS;
DMAInitialize();
DMA1Source = &AdcaResultRegs.ADCRESULT0;
DMA1Dest = &DMABuf1[0]; //DMA destination;
DMACH1AddrConfig(DMA1Dest,DMA1Source);
// BURST size = 1 | Source step size = 0 | Dest step size += 1
DMACH1BurstConfig(ONE_WORD_BURST,SOURCE_NO_ADDRESS_CHANGE,DESTINATION_INCREMENT_ONE_ADDRESS);
// Transfer size = 0x1000 | Source step size = 0 | Dest step size += 1
DMACH1TransferConfig(TRANSFER_SIZE_256,TRANSFER_STEP_SOURCE_NO_CHANGE,
TRANSFER_STEP_DEST_INCREMENT_ONE_ADDRESS);
DMACH1WrapConfig(0,0,256,256);
DMACH1ModeConfig(DMA_ADCAINT1,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE,SYNC_DISABLE,SYNC_SRC,
OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);
StartDMACH1();
}
__interrupt void local_DMACH1_ISR(void)
{
DMA_Done = 0x0001;
EALLOW;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
DmaRegs.CH1.CONTROL.bit.TRANSFERSTS = 1;
DmaRegs.CH1.CONTROL.bit.RUN = 1;
EDIS;
// ESTOP0;
}
//Write ADC configurations and power up the ADC for both ADC A and ADC B
void ConfigureADC(void)
{
//Device_cal();
EALLOW;
AdcaRegs.ADCCTL2.bit.PRESCALE = 6; // set ADCCLK divider to /4
AdcaRegs.ADCCTL2.bit.RESOLUTION = 0; // 12-bit resolution
AdcaRegs.ADCCTL2.bit.SIGNALMODE = 0; // single-ended channel conversions (12-bit mode only)
AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; // Set pulse positions to late
AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; // power up the ADC
DELAY_US(1000); // delay for 1ms to allow ADC time to power up
EDIS;
}
void ConfigureEPWM(void)
{
EALLOW;
// Assumes ePWM clock is already enabled
EPwm2Regs.TBCTL.bit.CTRMODE = 3; // freeze counter
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // TBCLK pre-scaler = /1
EPwm2Regs.TBPRD = 0x0FA0; // Set period to 4000 counts (50kHz)
EPwm2Regs.CMPA.half.CMPA = 0x0800; // Set compare A value to 2048 counts
EPwm2Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group
EPwm2Regs.ETSEL.bit.SOCASEL = 4; // Select SOC on up-count
EPwm2Regs.ETSEL.bit.SOCAEN = 1; // enable SOCA
EPwm2Regs.ETPS.bit.SOCAPRD = 1; // Generate pulse on 1st event
EDIS;
}
void SetupADCEpwm(void)
{
EALLOW;
AdcaRegs.ADCSOC0CTL.bit.CHSEL = 0; // SOC0 will convert pin A0
AdcaRegs.ADCSOC0CTL.bit.ACQPS = 14; // sample window is 15 SYSCLK cycles
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 7; // trigger on ePWM2 SOCA/C
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL = 0; // end of SOC0 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E = 1; // enable INT1 flag
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // make sure INT1 flag is cleared
EDIS;
}
interrupt void adca1_isr(void)
{
// Read the ADC result and store in circular buffer
AdcaResults[resultsIndex++] = AdcaResultRegs.ADCRESULT0;
if(RESULTS_BUFFER_SIZE <= resultsIndex)
{
resultsIndex = 0;
}
// Return from interrupt
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; // Clear INT1 flag
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // acknowledge PIE group 1 to enable further interrupts
}
// end of file