//########################################################################### // // FILE: Example_2833xEPwm_DMA.c // // TITLE: DSP2833x Device DMA interface with ePWM example. // // ASSUMPTIONS: // // This program requires the DSP2833x header files. // // As supplied, this project is configured for "boot to SARAM" // operation. The 2833x Boot Mode table is shown below. // For information on configuring the boot mode of an eZdsp, // please refer to the documentation included with the eZdsp, // // $Boot_Table: // // GPIO87 GPIO86 GPIO85 GPIO84 // XA15 XA14 XA13 XA12 // PU PU PU PU // ========================================== // 1 1 1 1 Jump to Flash // 1 1 1 0 SCI-A boot // 1 1 0 1 SPI-A boot // 1 1 0 0 I2C-A boot // 1 0 1 1 eCAN-A boot // 1 0 1 0 McBSP-A boot // 1 0 0 1 Jump to XINTF x16 // 1 0 0 0 Jump to XINTF x32 // 0 1 1 1 Jump to OTP // 0 1 1 0 Parallel GPIO I/O boot // 0 1 0 1 Parallel XINTF boot // 0 1 0 0 Jump to SARAM <- "boot to SARAM" // 0 0 1 1 Branch to check boot mode // 0 0 1 0 Boot to flash, bypass ADC cal // 0 0 0 1 Boot to SARAM, bypass ADC cal // 0 0 0 0 Boot to SCI-A, bypass ADC cal // Boot_Table_End$ // // DESCRIPTION: // // This example demonstrates several cases where the DMA is triggered from // SOC signals generated by ePWM modules. // // DMA CH1 setup: // Trigger = ADCSOCA from ePWM1 // Datasize = 16 bits // Source = VarA // Dest = EPwm1Regs.TBPRD // Burst = One word / burst // Transfer = One burst / transfer // CPU int = every transfer // // DMA CH2 setup: // Trigger = ADCSOCB from ePWM2 // Datasize = 32 bits // Source = VarB // Dest = EPwm1Regs.CMPA.all // Burst = One 32-bit word / burst // Transfer = One burst / transfer // CPU int = none // // DMA CH3 setup: // Trigger = ADC SEQ1INT // Datasize = 32 bits // Source = AdcMirror.ADCRESULT[0-5] // Dest = ADCbuffer // Burst = Three 32-bit words / burst // Transfer = One burst / transfer // CPU int = none // // Watch Variables: // // EPwm1Regs.TBPRD // EPwm1Regs.CMPA.all // ADCbuffer // InterruptCount // //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File // Prototype statements for functions found within this file. 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); // Global Variables #pragma DATA_SECTION(ADCbuffer,"DMARAML4"); volatile Uint32 ADCbuffer[3]; Uint16 VarA; Uint32 VarB; volatile Uint16 *MAPCNF = (Uint16 *)0x00702E; Uint16 InterruptCount; 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. Initalize 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; } void DMACH1Config(void) { EALLOW; // Configure CH1: // // Reset selected channel via CONTROL Register: // DmaRegs.CH1.CONTROL.bit.SOFTRESET = 1; // Perform SOFT reset on channel (clears all counters) // Set up MODE Register: DmaRegs.CH1.MODE.bit.PERINTSEL = 18; // ePWM1 SOCA as peripheral interrupt source 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 DmaRegs.CH1.MODE.bit.CHINTMODE = 0; // Generate interrupt to CPU at the beg of transfer DmaRegs.CH1.MODE.bit.CHINTE = 1; // Channel Interrupt to CPU enabled // Set up BURST registers: DmaRegs.CH1.BURST_SIZE.all = 0; // Number (N-1) of 16-bit words transferred in a burst 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: DmaRegs.CH1.DST_ADDR_SHADOW = (Uint32) &EPwm1Regs.TBPRD; // Point to ePWM1 TBPRD register remapped for DMA // need to make sure .cmd file has ePWMs remapped // 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; } void DMACH2Config(void) { EALLOW; // Configure CH2: // // Reset selected channel via CONTROL Register: // DmaRegs.CH2.CONTROL.bit.SOFTRESET = 1; // Perform SOFT reset on channel (clears all counters) // Set up MODE Register: DmaRegs.CH2.MODE.bit.PERINTSEL = 21; // ePWM2 SOCB as peripheral interrupt source 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: DmaRegs.CH2.BURST_SIZE.all = 1; // Number (N-1) of 16-bit words transferred in a burst DmaRegs.CH2.SRC_BURST_STEP = 0x0000; // Not needed since only 1 32-bit move per burst DmaRegs.CH2.DST_BURST_STEP = 0x0000; // Not needed since only 1 32-bit move per burst // 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: DmaRegs.CH2.DST_ADDR_SHADOW = (Uint32) &EPwm1Regs.CMPA.all; // Point to ePWM1 CMPAHR/CMPA registers // 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: DmaRegs.CH3.MODE.bit.PERINTSEL = 1; // ADC SEQ1INT as peripheral interrupt source 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: DmaRegs.CH3.BURST_SIZE.all = 5; // Number (N-1) of 16-bit words transferred in a burst DmaRegs.CH3.SRC_BURST_STEP = 2; // Increment source burst address by 2 (32-bit) DmaRegs.CH3.DST_BURST_STEP = 2; // Increment destination burst address by 2 (32-bit) // 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: DmaRegs.CH3.SRC_ADDR_SHADOW = (Uint32) &AdcMirror.ADCRESULT0; // Point to first RESULT reg // Set up DESTINATION address: DmaRegs.CH3.DST_ADDR_SHADOW = (Uint32) &ADCbuffer[0]; // Point to beginning of ADCbuffer // 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; } 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 } 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 AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // Enable ADC to accept ePWM_SOCA trigger 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 } void config_ePWM1_to_generate_ADCSOCA(void) { // Configure ePWM1 Timer // Interrupt triggers ADCSOCA EALLOW; EPwm1Regs.TBPRD = 74; // Setup period (one off so DMA transfer will be obvious) 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; } 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++) {} } //=========================================================================== // No more. //===========================================================================