//########################################################################### // // FILE: Example_2833xEPwm_DMA.c // // TITLE: ePWM to DMA Example // //! \addtogroup f2833x_example_list //!

ePWM to DMA (epwm_dma)

//! //! This example demonstrates several cases where the DMA is triggered from //! SOC signals generated by ePWM modules. //! //! \b Watch \b Variables \n //! - EPwm1Regs.TBPRD //! - EPwm1Regs.CMPA.all //! - ADCbuffer //! - InterruptCount // //########################################################################### // $TI Release: $ // $Release Date: $ // $Copyright: // Copyright (C) 2009-2023 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 "DSP28x_Project.h" // Device Headerfile and Examples Include File // // Function Prototype statements // void delay_loop(void); void DMAInitialize(void); void DMACH1Config(void); void DMACH2Config(void); void DMACH3Config(void); void ConfigAdc(void); void config_ePWM1_to_generate_ADCSOCA(void); void config_ePWM2_to_generate_ADCSOCB(void); __interrupt void local_DINTCH1_ISR(void); // // Globals // #pragma DATA_SECTION(ADCbuffer,"DMARAML4"); volatile Uint32 ADCbuffer[3]; Uint16 VarA; Uint32 VarB; volatile Uint16 *MAPCNF = (Uint16 *)0x00702E; Uint16 InterruptCount; // // Main // void main(void) { Uint16 i; // // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2833x_SysCtrl.c file. // InitSysCtrl(); // // Step 2. Initialize GPIO: // This example function is found in the DSP2833x_Gpio.c file and // illustrates how to set the GPIO to it's default state. // // InitGpio(); // Skipped for this example // // For this example use the following configuration: // // // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts // DINT; // // Initialize 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 DSP2833x_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 DSP2833x_DefaultIsr.c. // This function is found in DSP2833x_PieVect.c. // InitPieVectTable(); EALLOW; // // Initialize PIE vector for CPU interrupt: // PieVectTable.DINTCH1 = &local_DINTCH1_ISR; // Point to DMA CH1 ISR PieCtrlRegs.PIEIER7.bit.INTx1 = 1; // Enable DMA CH1 interrupt in PIE EDIS; // // Step 4. Initialize all the Device Peripherals: // This function is found in DSP2833x_InitPeripherals.c // // InitPeripherals(); // Not required for this example // // Step 5. User specific code: // InterruptCount = 0; EALLOW; GpioCtrlRegs.GPADIR.all = 0xFFFFFFFF; // All outputs SysCtrlRegs.MAPCNF.bit.MAPEPWM = 1; // Remap ePWMs for DMA access EDIS; GpioDataRegs.GPASET.all = 0xFFFFFFFF; delay_loop(); GpioDataRegs.GPACLEAR.all = 0x00000002; for(i=0; i<3; i++) { ADCbuffer[i] = ((Uint32)i*0x00011000) + 0x00044000; } VarA = 75; VarB = 0x652000; // // Enable and configure clocks to peripherals: // EALLOW; SysCtrlRegs.PCLKCR3.bit.DMAENCLK = 1; // Enable SYSCLK to DMA EDIS; DMAInitialize(); DMACH1Config(); DMACH2Config(); DMACH3Config(); // // Enable all interrupts: // IER = M_INT7; // Enable INT7 (7.1 DMA Ch1) EINT; InitAdc(); ConfigAdc(); config_ePWM1_to_generate_ADCSOCA(); config_ePWM2_to_generate_ADCSOCB(); EALLOW; DmaRegs.CH1.CONTROL.bit.RUN = 1; DmaRegs.CH2.CONTROL.bit.RUN = 1; DmaRegs.CH3.CONTROL.bit.RUN = 1; __asm(" NOP"); EPwm1Regs.TBCTL.bit.CTRMODE = 0; // Up count mode EPwm2Regs.TBCTL.bit.CTRMODE = 0; // Up count mode EDIS; for(;;) { } } // // DMA Functions // void DMAInitialize(void) { EALLOW; // // Perform a hard reset on DMA // DmaRegs.DMACTRL.bit.HARDRESET = 1; // // always perform one NOP after a HARDRESET // __asm(" NOP"); // // Stop DMA on emulation suspend // DmaRegs.DEBUGCTRL.bit.FREE = 0; EDIS; } // // DMACH1Config - // void DMACH1Config(void) { EALLOW; // // Configure CH1: // // // Reset selected channel via CONTROL Register: // // // Perform SOFT reset on channel (clears all counters) // //DmaRegs.CH1.CONTROL.bit.SOFTRESET = 1; // // Set up MODE Register: // // // ePWM1 SOCA as peripheral interrupt source // DmaRegs.CH1.MODE.bit.PERINTSEL = 18; DmaRegs.CH1.MODE.bit.PERINTE = 1; // Peripheral interrupt enabled DmaRegs.CH1.MODE.bit.ONESHOT = 0; // 1 burst per SW interrupt DmaRegs.CH1.MODE.bit.CONTINUOUS = 1; // Do not stop after each transfer DmaRegs.CH1.MODE.bit.SYNCE = 0; // No sync signal DmaRegs.CH1.MODE.bit.SYNCSEL = 0; // No sync signal DmaRegs.CH1.MODE.bit.DATASIZE = 0; // 16-bit data size transfers // // Generate interrupt to CPU at the beg of transfer // DmaRegs.CH1.MODE.bit.CHINTMODE = 0; DmaRegs.CH1.MODE.bit.CHINTE = 1; // Channel Interrupt to CPU enabled // // Set up BURST registers // // // Number (N-1) of 16-bit words transferred in a burst // DmaRegs.CH1.BURST_SIZE.all = 0; DmaRegs.CH1.SRC_BURST_STEP = 0; // Not needed since BURST_SIZE = 0 DmaRegs.CH1.DST_BURST_STEP = 0; // Not needed since BURST_SIZE = 0 // // Set up TRANSFER registers // DmaRegs.CH1.TRANSFER_SIZE = 0; // Bursts (N-1) per transfer DmaRegs.CH1.SRC_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 DmaRegs.CH1.DST_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 // // Set up WRAP registers // DmaRegs.CH1.SRC_WRAP_SIZE = 0xFFFF; // No source wrap-around DmaRegs.CH1.DST_WRAP_SIZE = 0xFFFF; // No destination wrap-around DmaRegs.CH1.SRC_WRAP_STEP = 0; DmaRegs.CH1.DST_WRAP_STEP = 0; // // Set up SOURCE address // DmaRegs.CH1.SRC_ADDR_SHADOW = (Uint32) &VarA; // Point to variable in RAM // // Set up DESTINATION address // // // Point to ePWM1 TBPRD register remapped for DMA need to make sure // .cmd file has ePWMs remapped // DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32) &EPwm1Regs.TBPRD; // // Clear any spurious flags // DmaRegs.CH1.CONTROL.bit.PERINTCLR = 1; //Clear any spurious interrupt flags DmaRegs.CH1.CONTROL.bit.SYNCCLR = 1; // Clear any spurious sync flags DmaRegs.CH1.CONTROL.bit.ERRCLR = 1; //Clear any spurious sync error flags EDIS; } // // DMACH2Config - // void DMACH2Config(void) { EALLOW; // // Configure CH2 // // // Reset selected channel via CONTROL Register // // // Perform SOFT reset on channel (clears all counters) // //DmaRegs.CH2.CONTROL.bit.SOFTRESET = 1; // // Set up MODE Register // // // ePWM2 SOCB as peripheral interrupt source // DmaRegs.CH2.MODE.bit.PERINTSEL = 21; DmaRegs.CH2.MODE.bit.PERINTE = 1; // Peripheral interrupt enabled DmaRegs.CH2.MODE.bit.ONESHOT = 0; // 1 burst per SW interrupt DmaRegs.CH2.MODE.bit.CONTINUOUS = 1; // Do not stop after each transfer DmaRegs.CH2.MODE.bit.SYNCE = 0; // No sync signal DmaRegs.CH2.MODE.bit.SYNCSEL = 0; // No sync signal DmaRegs.CH2.MODE.bit.DATASIZE = 1; // 32-bit data size transfers DmaRegs.CH2.MODE.bit.CHINTMODE = 0; DmaRegs.CH2.MODE.bit.CHINTE = 0; // Channel Interrupt to CPU disabled // // Set up BURST registers // // // Number (N-1) of 16-bit words transferred in a burst // DmaRegs.CH2.BURST_SIZE.all = 1; // // Not needed since only 1 32-bit move per burst // DmaRegs.CH2.SRC_BURST_STEP = 0x0000; // // Not needed since only 1 32-bit move per burst // DmaRegs.CH2.DST_BURST_STEP = 0x0000; // // Set up TRANSFER registers // DmaRegs.CH2.TRANSFER_SIZE = 0; // Bursts (N-1) per transfer DmaRegs.CH2.SRC_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 DmaRegs.CH2.DST_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 // // Set up WRAP registers // DmaRegs.CH2.SRC_WRAP_SIZE = 0xFFFF; // No source wrap-around DmaRegs.CH2.DST_WRAP_SIZE = 0xFFFF; // No destination wrap-around DmaRegs.CH2.SRC_WRAP_STEP = 0; DmaRegs.CH2.DST_WRAP_STEP = 0; // // Set up SOURCE address // DmaRegs.CH2.SRC_ADDR_SHADOW = (Uint32) &VarB; // Point to variable in RAM // // Set up DESTINATION address // // // Point to ePWM1 CMPAHR/CMPA registers // DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &EPwm1Regs.CMPA.all; // // Clear any spurious flags // DmaRegs.CH2.CONTROL.bit.PERINTCLR = 1; //Clear any spurious interrupt flags DmaRegs.CH2.CONTROL.bit.SYNCCLR = 1; //Clear any spurious sync flags DmaRegs.CH2.CONTROL.bit.ERRCLR = 1; //Clear any spurious sync error flags EDIS; } void DMACH3Config(void) { EALLOW; // // Configure CH3 // // // Set up MODE Register // // // ADC SEQ1INT as peripheral interrupt source // DmaRegs.CH3.MODE.bit.PERINTSEL = 1; DmaRegs.CH3.MODE.bit.PERINTE = 1; // Peripheral interrupt enabled DmaRegs.CH3.MODE.bit.ONESHOT = 0; // 1 burst per SW interrupt DmaRegs.CH3.MODE.bit.CONTINUOUS = 1; // Do not stop after each transfer DmaRegs.CH3.MODE.bit.SYNCE = 0; // No sync signal DmaRegs.CH3.MODE.bit.SYNCSEL = 0; // No sync signal DmaRegs.CH3.MODE.bit.DATASIZE = 1; // 32-bit data size transfers DmaRegs.CH3.MODE.bit.CHINTMODE = 0; DmaRegs.CH3.MODE.bit.CHINTE = 0; // Channel Interrupt to CPU disabled // // Set up BURST registers // // // Number (N-1) of 16-bit words transferred in a burst // DmaRegs.CH3.BURST_SIZE.all = 5; // // Increment source burst address by 2 (32-bit) // DmaRegs.CH3.SRC_BURST_STEP = 2; // // Increment destination burst address by 2 (32-bit) // DmaRegs.CH3.DST_BURST_STEP = 2; // // Set up TRANSFER registers // DmaRegs.CH3.TRANSFER_SIZE = 0; // Bursts (N-1) per transfer DmaRegs.CH3.SRC_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 DmaRegs.CH3.DST_TRANSFER_STEP = 0; // Not needed since TRANSFER_SIZE = 0 // // Set up WRAP registers // DmaRegs.CH3.SRC_WRAP_SIZE = 0xFFFF; // No source wrap-around DmaRegs.CH3.DST_WRAP_SIZE = 0xFFFF; // No destination wrap-around DmaRegs.CH3.SRC_WRAP_STEP = 0; DmaRegs.CH3.DST_WRAP_STEP = 0; // // Set up SOURCE address // // // Point to first RESULT reg // DmaRegs.CH3.SRC_ADDR_SHADOW = (Uint32) &AdcMirror.ADCRESULT0; // // Set up DESTINATION address // // // Point to beginning of ADCbuffer // DmaRegs.CH3.DST_ADDR_SHADOW = (Uint32) &ADCbuffer[0]; // // Clear any spurious flags // DmaRegs.CH3.CONTROL.bit.PERINTCLR = 1; //Clear any spurious interrupt flags DmaRegs.CH3.CONTROL.bit.SYNCCLR = 1; //Clear any spurious sync flags DmaRegs.CH3.CONTROL.bit.ERRCLR = 1; //Clear any spurious sync error flags EDIS; } // // local_DINTCH1_ISR - // __interrupt void local_DINTCH1_ISR(void) // DMA INT7.1 { GpioDataRegs.GPATOGGLE.all = 0x00000001; // Toggle GPIOA0 InterruptCount++; if((DmaRegs.CH1.CONTROL.bit.OVRFLG == 1) || (DmaRegs.CH2.CONTROL.bit.OVRFLG == 1) || (DmaRegs.CH3.CONTROL.bit.OVRFLG == 1)) { __asm(" ESTOP0"); } PieCtrlRegs.PIEACK.bit.ACK7 = 1; // Clear PIEIFR bit } // // ConfigAdc - // void ConfigAdc(void) { AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 7; AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0; // ADCINA0 AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 1; // ADCINA1 AdcRegs.ADCCHSELSEQ1.bit.CONV02 = 2; // ADCINA2 AdcRegs.ADCCHSELSEQ1.bit.CONV03 = 3; // ADCINA3 AdcRegs.ADCCHSELSEQ2.bit.CONV04 = 4; // ADCINA4 AdcRegs.ADCCHSELSEQ2.bit.CONV05 = 5; // ADCINA5 // // Enable ADC to accept ePWM_SOCA trigger // AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1; AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1; // Clear interrupt flag AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1; // Enable SEQ1 interrupt } // // config_ePWM1_to_generate_ADCSOCA - // void config_ePWM1_to_generate_ADCSOCA(void) { // // Configure ePWM1 Timer // Interrupt triggers ADCSOCA // EALLOW; // // Setup period (one off so DMA transfer will be obvious) // EPwm1Regs.TBPRD = 74; EPwm1Regs.CMPA.all = 0x501000; EPwm1Regs.ETSEL.bit.SOCASEL = 2; // ADCSOCA on TBCTR=TBPRD EPwm1Regs.ETPS.bit.SOCAPRD = 1; // Generate SOCA on 1st event EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable SOCA generation EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // /1 clock mode EDIS; } // // config_ePWM2_to_generate_ADCSOCB - // void config_ePWM2_to_generate_ADCSOCB(void) { // // Configure ePWM2 Timer // Interrupt triggers ADCSOCB // EALLOW; EPwm2Regs.TBPRD = 150; // Setup periodSetup period EPwm2Regs.CMPA.all = 0x200000; EPwm2Regs.ETSEL.bit.SOCBSEL = 2; // ADCSOCB on TBCTR=TBPRD EPwm2Regs.ETPS.bit.SOCBPRD = 1; // Generate SOCB on 1st event EPwm2Regs.ETSEL.bit.SOCBEN = 1; // Enable SOCB generation EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // /1 clock mode EDIS; } void delay_loop() { short i; for (i = 0; i < 1000; i++) { } } // // End of File //