Other Parts Discussed in Thread: CONTROLSUITE
Hello all. I am new into C2000 family but have some experiences with C6000 DSPs and Tiva MCU. I am working with the LAUNCHXL-F28377S board
In my project I need to sync two epwm timers between them (epwm7A-epwm8A), with 0 phase delay and use the lower frequency one (epwm8A) to trigger the ADC. The problem I have is that the pwm timer which triggers the ADCs, has to be stopped and then relaunched in sync with the first pwm.
Everything is done in my code, but when I stopped and relaunch my second pwm signal (epwm8A), then I see am irregular delay between them. In Tiva family, this was very easy to do using TimerSynchronize(TIMER0_BASE, TIMER_1A_SYNC | TIMER_1B_SYNC).
Is there any similar function in C2000 Controlsuite?
If not, what changes do I need to do to my code?
Thank you:
//########################################################################### // FILE: ADC_PWM_SYNC.c // TITLE: ADC triggering via epwm for F2837xS. // //! \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 //! 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: F2837xS Support Library v191 $ // $Release Date: Fri Mar 11 15:58:35 CST 2016 $ // $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated - // http://www.ti.com/ ALL RIGHTS RESERVED $ //########################################################################### #include "F28x_Project.h" // Device Headerfile and Examples Include File ///////////////////////////////////////////////////////////////////////////////// //#include "C28x_FPU_FastRTS.h" #include <math.h> #include "float.h" #include "FPU.h" //#include "fpu_rfft.h" #include <string.h> #include "inc/hw_ints.h" #include "inc/hw_memmap.h" #include "inc/hw_types.h" #include "driverlib/interrupt.h" #include "driverlib/sysctl.h" #include "driverlib/systick.h" #define UART_ON 1 #ifdef UART_ON #include "utils/cmdline.h" #include "utils/uartstdio.h" #include "utils/ustdlib.h" #endif ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// static unsigned short indexX = 0; static unsigned short indexY = 0; Uint16 DMA_Done = 0; ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// uint32_t cnt_interr_ADC = 0; uint32_t cnt_interr_ADC_completo = 0; int16 cnt_print = 0; #define RFFT_STAGES 7//128 8-256 #define RFFT_SIZE (1 << RFFT_STAGES) #define F_PER_SAMPLE (758000.0L/((float)RFFT_SIZE)) //Assuming sampling rate is 758kHz RFFT_ADC_F32_STRUCT rfft_adc; RFFT_F32_STRUCT rfft; #pragma DATA_SECTION(RFFTin1Buff,"RFFTdata1"); Uint16 RFFTin1Buff[RFFT_SIZE]; //Buffer alignment for the input array, //RFFT_adc_f32u(optional) RFFT_adc_f32(required) //Output of FFT overwrites input if //RFFT_STAGES is ODD #pragma DATA_SECTION(RFFToutBuff,"RFFTdata2"); float32 RFFToutBuff[RFFT_SIZE]; //Output of FFT here if RFFT_STAGES is EVEN #pragma DATA_SECTION(RFFTmagBuff,"RFFTdata3"); float32 RFFTmagBuff[RFFT_SIZE / 2 + 1]; //Additional Buffer used in Magnitude calc #pragma DATA_SECTION(RFFTF32Coef,"RFFTdata4"); float32 RFFTF32Coef[RFFT_SIZE]; //Twiddle buffer ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// // variables #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_128 127 #define TRANSFER_STEP_SOURCE_NO_CHANGE 0 #define TRANSFER_STEP_DEST_INCREMENT_ONE_ADDRESS 1 volatile uint16_t *DMA1Source, *DMA1Dest; interrupt void local_DMACH1_ISR(void); ///////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////// void ConfigureADC(void); void ConfigureEPWM(void); void SetupADCEpwm(Uint16 channel); interrupt void adca1_isr_con_dma(void); void ConfigureUART(void); void Configurar_Serie(); void DMA_configure(void); //buffer for storing conversion results #define RESULTS_BUFFER_SIZE RFFT_SIZE//256 #pragma DATA_SECTION(AdcaResults,"SecureRam0"); Uint16 AdcaResults[RESULTS_BUFFER_SIZE]; Uint16 resultsIndex; volatile Uint16 bufferFull; void main(void) { Uint16 i, j; float32 freq; float32 freq2; uint16_t cnt_do = 0; uint32_t Aux_u32 = 0; uint32_t Aux_u32_2 = 0; float32 aux_float = 0; float32 aux_float2 = 0; uint32_t reloj_pak = 0; // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the F2837xS_SysCtrl.c file. InitSysCtrl(); // Step 2. Initialize GPIO: // This example function is found in the F2837xS_Gpio.c file and // illustrates how to set the GPIO to it's default state. // InitGpio(); // Skipped for this example InitEPwm7Gpio(); InitEPwm8Gpio(); GPIO_SetupPinMux(2, GPIO_MUX_CPU1, 0); GPIO_SetupPinOptions(2, GPIO_OUTPUT, GPIO_PUSHPULL); GPIO_SetupPinMux(3, GPIO_MUX_CPU1, 0); GPIO_SetupPinOptions(3, GPIO_OUTPUT, GPIO_PUSHPULL); GPIO_SetupPinMux(4, GPIO_MUX_CPU1, 0); GPIO_SetupPinOptions(4, GPIO_OUTPUT, GPIO_PUSHPULL); // 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 F2837xS_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 F2837xS_DefaultIsr.c. // This function is found in F2837xS_PieVect.c. InitPieVectTable(); //Map ISR functions EALLOW; PieVectTable.DMA_CH1_INT = &local_DMACH1_ISR; //function for DMA interrupt 1 PieVectTable.ADCA1_INT = &adca1_isr_con_dma; //function for ADCA interrupt 1 EDIS; #ifdef UART_ON // // Configure UART0 for debug output. // ConfigureUART(); // Print hello message to user. UARTprintf("\n\nHelloWorld on F28377S - ADC Card Example Program\n"); #endif //Configure the ADC and power it up ConfigureADC(); //Configure the ePWM ConfigureEPWM(); //Setup the ADC for ePWM triggered conversions on channel 0 SetupADCEpwm(0); //--- Enable the ADC interrupt DMA_configure(); //Enable global Interrupts and higher priority real-time debug events: IER |= M_INT1; //Enable group 1 interrupts - Para el ADC1 IER |= M_INT7; //Enable group 1 interrupts - Para la DMA EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM //Initialize results buffer for (resultsIndex = 0; resultsIndex < RESULTS_BUFFER_SIZE; resultsIndex++) { AdcaResults[resultsIndex] = 0; } resultsIndex = 0; bufferFull = 0; //enable PIE interrupt PieCtrlRegs.PIEIER1.bit.INTx1 = 1; //ADC PieCtrlRegs.PIEIER7.bit.INTx1 = 1; //dma //sync ePWM EALLOW; CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; EDIS; ///////////////////////////////////////////////////////////// //FFT //RFFT_F32_STRUCT. Tail pointer of //RFFT_ADC_F32_STRUCT is passed to //the OutBuf pointer of RFFT_F32_STRUCT ////////////////////////////////////////////////////////////// //start ePWM EPwm8Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA EPwm8Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode //take conversions indefinitely in loop while (1) { //wait while ePWM causes ADC conversions, which then cause interrupts, //which fill the results buffer, eventually setting the bufferFull //flag if (DMA_Done == 1) DMA_Done = 0; while (!bufferFull) ; bufferFull = 0; //clear the buffer full flag //stop ePWM EPwm8Regs.ETSEL.bit.SOCAEN = 0; //disable SOCA EPwm8Regs.TBCTL.bit.CTRMODE = 3; //freeze counter DELAY_US(1000); for (i = 0; i < RFFT_SIZE; i++) { RFFTin1Buff[i] = AdcaResults[i]; //Clean up output buffer } ////////////////////////////////////////////////////////// //Will do some processing /////////////////////////////////////////////// EALLOW; //start ePWM EPwm8Regs.ETSEL.bit.SOCAEN = 1; //enable SOCA EPwm8Regs.TBCTL.bit.CTRMODE = 0; //unfreeze, and enter up count mode // CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0; //EPwm8Regs.TBCTL.bit.SWFSYNC = 1; //EPwm7Regs.TBCTL.bit.SWFSYNC = 1; // CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1; EDIS; //at this point, AdcaResults[] contains a sequence of conversions //from the selected channel //software breakpoint, hit run again to get updated conversions //asm(" ESTOP0"); } } //Write ADC configurations and power up the ADC for both ADC A and ADC B void ConfigureADC(void) { EALLOW; //write configurations AdcaRegs.ADCCTL2.bit.PRESCALE = 6; //set ADCCLK divider to /4 AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //Set pulse positions to late AdcaRegs.ADCCTL1.bit.INTPULSEPOS = 1; //power up the ADC AdcaRegs.ADCCTL1.bit.ADCPWDNZ = 1; //delay for 1ms to allow ADC time to power up DELAY_US(1000); EDIS; } void ConfigureEPWM(void) { EALLOW; // Assumes ePWM clock is already enabled EPwm7Regs.ETSEL.bit.SOCAEN = 1; // Disable SOC on A group EPwm7Regs.ETSEL.bit.SOCASEL = 4;// Select SOC from CTR=PRD (6 for CMPB up count) -orig:Select SOC on up-count EPwm7Regs.ETPS.bit.SOCAPRD = 1; //1 // Generate pulse on 1st event EPwm7Regs.CMPA.bit.CMPA = 0x0040; // Set compare A value to 64 counts EPwm7Regs.TBPRD = 0x0080; // Set period to 128 counts EPwm7Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; //TB_COUNT_UPDOWN; - TB_COUNT_UP or freeze counter 0x03 //EPwm7Regs.TBCTL.bit.PHSDIR = TB_DOWN; EPwm7Regs.TBPHS.all = 0x00000000; EPwm7Regs.AQCTLA.bit.PRD = AQ_TOGGLE; // Toggle on PRD //pHASE EPwm7Regs.TBPHS.bit.TBPHS = 0; // Set Phase register to zero, master EPwm7Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm7Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; EPwm7Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm7Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm7Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; EPwm7Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero EDIS; //////////////////////////////////////////// EALLOW; // Assumes ePWM clock is already enabled EPwm8Regs.ETSEL.bit.SOCAEN = 0; // Disable SOC on A group EPwm8Regs.ETSEL.bit.SOCASEL = 4; // Select SOC from CTR=PRD (6 for CMPB up count) -orig:Select SOC on up-count EPwm8Regs.ETPS.bit.SOCAPRD = 1; //1 // Generate pulse on 1st event EPwm8Regs.CMPA.bit.CMPA = 0x0050; EPwm8Regs.TBPRD = 0x0100; //Double of epwm7 EPwm8Regs.TBCTL.bit.CTRMODE = 3;//TB_COUNT_UP or freeze counter 0x03 //EPwm8Regs.TBCTL.bit.PHSDIR = TB_UP; EPwm8Regs.TBPHS.all = 0x00000000; EPwm8Regs.AQCTLA.bit.PRD = AQ_TOGGLE; // Toggle on PRD //pHASE EPwm8Regs.TBPHS.bit.TBPHS = 0; //xDEGREES Set Phase register to zero, master EPwm8Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master module EPwm8Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; //TB_SYNC_IN; // Select SyncOut to EPWM7SYNC EPwm8Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm8Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm8Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; // load on CTR=Zero EPwm8Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; // load on CTR=Zero EDIS; } void SetupADCEpwm(Uint16 channel) { Uint16 acqps; //determine minimum acquisition window (in SYSCLKS) based on resolution if (ADC_RESOLUTION_12BIT == AdcaRegs.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; AdcaRegs.ADCSOC0CTL.bit.CHSEL = channel; //SOC0 will convert pin A0 AdcaRegs.ADCSOC0CTL.bit.ACQPS = acqps; //sample window is 15-100 SYSCLK cycles AdcaRegs.ADCSOC0CTL.bit.TRIGSEL = 0X13; //trigger on ePWM8 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; } uint16_t valor_LED = 0; interrupt void adca1_isr_con_dma(void) { //AdcaResults[resultsIndex++] = AdcaResultRegs.ADCRESULT0; cnt_interr_ADC++; AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; } void DMA_configure(void) { EALLOW; CpuSysRegs.SECMSEL.bit.PF1SEL = 1; EDIS; // refer to dma.c for the descriptions of the following functions. //Initialize DMA DMAInitialize(); DMA1Source = &AdcaResultRegs.ADCRESULT0; DMA1Dest = &AdcaResults[0]; //DMA destination; // configure DMACH5 for TX DMACH1AddrConfig(DMA1Dest, DMA1Source); //DMACH5BurstConfig(BURST,1,0); // Burst size, src step, dest step DMACH1BurstConfig(ONE_WORD_BURST, SOURCE_NO_ADDRESS_CHANGE, DESTINATION_INCREMENT_ONE_ADDRESS); // transfer size, src step, dest step //DMACH5TransferConfig(TRANSFER,1,0); // transfer size, src step, dest step DMACH1TransferConfig(TRANSFER_SIZE_128, TRANSFER_STEP_SOURCE_NO_CHANGE, TRANSFER_STEP_DEST_INCREMENT_ONE_ADDRESS);// transfer size, src step, dest step DMACH1WrapConfig(0, 0, 128, 128); DMACH1ModeConfig(DMA_ADCAINT1, PERINT_ENABLE, ONESHOT_DISABLE, CONT_DISABLE, SYNC_DISABLE, SYNC_SRC, OVRFLOW_DISABLE, SIXTEEN_BIT, CHINT_END, CHINT_ENABLE); StartDMACH1(); /* // configure DMA CH2 for RX DMACH6AddrConfig(DMADest,&SpiaRegs.SPIRXBUF); DMACH6BurstConfig(BURST,0,1); DMACH6TransferConfig(TRANSFER,0,1); DMACH6ModeConfig(DMA_SPIARX,PERINT_ENABLE,ONESHOT_DISABLE,CONT_DISABLE, SYNC_DISABLE,SYNC_SRC,OVRFLOW_DISABLE,SIXTEEN_BIT,CHINT_END,CHINT_ENABLE);/**/ } 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; resultsIndex = 0; bufferFull = 1; cnt_interr_ADC_completo++; // ESTOP0; } #ifdef UART_ON //***************************************************************************** // // Configure the UART and its pins. This must be called before UARTprintf(). // //***************************************************************************** void ConfigureUART(void) { // // Enable UART0 // SysCtlPeripheralEnable(SYSCTL_PERIPH_SCI1); // // Configure GPIO Pins for UART mode. // /* EALLOW; GpioCtrlRegs.GPAMUX2.bit.GPIO28 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO28 = 0; GpioCtrlRegs.GPAQSEL2.bit.GPIO28 = 3; GpioCtrlRegs.GPADIR.bit.GPIO28 = 0; GpioCtrlRegs.GPAMUX2.bit.GPIO29 = 1; GpioCtrlRegs.GPAPUD.bit.GPIO29 = 0; GpioCtrlRegs.GPADIR.bit.GPIO29 = 1; EDIS;/**/ // For this example, only init the pins for the SCI-A port. EALLOW; GpioCtrlRegs.GPCMUX2.bit.GPIO84 = 1; GpioCtrlRegs.GPCMUX2.bit.GPIO85 = 1; GpioCtrlRegs.GPCGMUX2.bit.GPIO84 = 1; GpioCtrlRegs.GPCGMUX2.bit.GPIO85 = 1; EDIS; // // Initialize the UART for console I/O. // UARTStdioConfig(0, 115200, SysCtlLowSpeedClockGet(SYSTEM_CLOCK_SPEED) / 2); } #endif