Other Parts Discussed in Thread: C2000WARE,
Tool/software:
I would like to use the XCMP complex waveform generator mode to configure ePWM waveforms. Currently, I am using DMA to load compare values from memory into the shadow registers of the ePWM module. My goal is to have three shadow registers, one at a time, loaded into the active register of the ePWM.
Right now, I trigger an interrupt when the ePWM1A Time-Base Counter = 0. In the ISR, I:
-
Locate the next source address in memory for the next set of compare values to be moved to the ePWM shadow registers, and
-
Enable the ePWM XCMP reload event.
This works, but when I move to higher frequency ePWM waveforms, the interrupt latency becomes too long.
What I would like to achieve is:
-
Have the DMA automatically reload based on the hardware ePWM trigger, and
-
Have the DMA automatically increment the source memory location for the next compare values.
I’ve attached/pasted my .c
and .syscfg
files, where I implemented ePWM to output on three channels.
Could you please advise on the correct configuration to achieve this DMA-driven automatic reload and address increment behavior with XCMP?
#include "driverlib.h" #include "device.h" #include "board.h" #include "c2000ware_libraries.h" // Globals for XCMP register configuration #define SHADOW_SETS 3 // 3 shadow register sets (Shadow1, Shadow2, Shadow3) #define XCMP_PER_SHADOW 18 // 16 values per shadow #define TOTAL_COMPARE_VALUES (SHADOW_SETS * XCMP_PER_SHADOW) // Total values per config #define NUM_CONFIGS 3 // Number of different configurations // XCMP Compare configurations - using packed structure to match register layout // Note: The registers XCMP2, XCMP3, XCMP4 are consecutive in memory uint16_t compareConfigsCH1[NUM_CONFIGS * TOTAL_COMPARE_VALUES] = { // Configuration 1 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 100, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 200, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 300, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 400, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 600, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 700, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 800, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 200, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 400, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 600, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 800, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 1000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 1200, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 1400, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 1600, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 300, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 600, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 900, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 1200, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 1500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 1800, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 2100, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 2400, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 00, //XCMP1_SHDW1 //Configuration 2 00, //XCMP1HR_SHDW1 400, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 800, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 1200, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 1600, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 2000, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 2400, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 2800, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 3200, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 500, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1000, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 1500, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 2000, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 2500, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 3000, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 3500, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 4000, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 600, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1200, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 1800, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 2400, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 3000, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 3600, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 4200, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 4800, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 //Configuration 3 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 700, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 1400, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 2100, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 2800, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 3500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 4200, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 4900, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 5600, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 800, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1600, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 2400, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 3200, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 4000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 4800, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 5600, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 6400, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 900, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1800, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 2700, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 3600, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 4500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 5400, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 6300, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 7200, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 }; uint16_t compareConfigsCH2[NUM_CONFIGS * TOTAL_COMPARE_VALUES] = { // Configuration 1 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 100, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 200, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 300, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 400, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 600, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 700, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 800, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 200, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 400, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 600, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 800, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 1000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 1200, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 1400, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 1600, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 300, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 600, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 900, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 1200, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 1500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 1800, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 2100, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 2400, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 00, //XCMP1_SHDW1 //Configuration 2 00, //XCMP1HR_SHDW1 400, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 800, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 1200, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 1600, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 2000, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 2400, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 2800, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 3200, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 500, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1000, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 1500, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 2000, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 2500, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 3000, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 3500, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 4000, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 600, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1200, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 1800, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 2400, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 3000, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 3600, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 4200, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 4800, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 //Configuration 3 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 700, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 1400, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 2100, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 2800, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 3500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 4200, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 4900, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 5600, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 800, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1600, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 2400, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 3200, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 4000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 4800, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 5600, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 6400, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 900, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1800, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 2700, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 3600, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 4500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 5400, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 6300, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 7200, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 }; uint16_t compareConfigsCH3[NUM_CONFIGS * TOTAL_COMPARE_VALUES] = { // Configuration 1 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 100, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 200, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 300, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 400, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 600, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 700, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 800, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 200, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 400, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 600, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 800, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 1000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 1200, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 1400, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 1600, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 300, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 600, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 900, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 1200, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 1500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 1800, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 2100, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 2400, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 00, //XCMP1_SHDW1 //Configuration 2 00, //XCMP1HR_SHDW1 400, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 800, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 1200, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 1600, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 2000, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 2400, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 2800, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 3200, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 500, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1000, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 1500, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 2000, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 2500, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 3000, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 3500, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 4000, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 600, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1200, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 1800, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 2400, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 3000, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 3600, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 4200, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 4800, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 //Configuration 3 00, //XCMP1_SHDW1 00, //XCMP1HR_SHDW1 700, //XCMP2_SHDW1 00, //XCMP2HR_SHDW1 1400, //XCMP3_SHDW1 00, //XCMP3HR_SHDW1 2100, //XCMP4_SHDW1 00, //XCMP4HR_SHDW1 2800, //XCMP5_SHDW1 00, //XCMP5HR_SHDW1 3500, //XCMP6_SHDW1 00, //XCMP6HR_SHDW1 4200, //XCMP7_SHDW1 00, //XCMP7HR_SHDW1 4900, //XCMP8_SHDW1 00, //XCMP8HR_SHDW1 5600, //XTBPRD_SHDW1 00, //XTBPRDHR_SHDW1 00, //XCMP1_SHDW2 00, //XCMP1HR_SHDW2 800, //XCMP2_SHDW1 00, //XCMP2HR_SHDW2 1600, //XCMP3_SHDW2 00, //XCMP3HR_SHDW2 2400, //XCMP4_SHDW2 00, //XCMP4HR_SHDW2 3200, //XCMP5_SHDW2 00, //XCMP5HR_SHDW2 4000, //XCMP6_SHDW2 00, //XCMP6HR_SHDW2 4800, //XCMP7_SHDW2 00, //XCMP7HR_SHDW2 5600, //XCMP8_SHDW2 00, //XCMP8HR_SHDW2 6400, //XTBPRD_SHDW2 00, //XTBPRDHR_SHDW2 00, //XCMP1_SHDW3 00, //XCMP1HR_SHDW3 900, //XCMP2_SHDW3 00, //XCMP2HR_SHDW3 1800, //XCMP3_SHDW3 00, //XCMP3HR_SHDW3 2700, //XCMP4_SHDW3 00, //XCMP4HR_SHDW3 3600, //XCMP5_SHDW3 00, //XCMP5HR_SHDW3 4500, //XCMP6_SHDW3 00, //XCMP6HR_SHDW3 5400, //XCMP7_SHDW3 00, //XCMP7HR_SHDW3 6300, //XCMP8_SHDW3 00, //XCMP8HR_SHDW3 7200, //XTBPRD_SHDW3 00, //XTBPRDHR_SHDW3 }; // Offset macros for configuration access #define COMPARE_CONFIG_OFFSET_CH1(config) ((config) * TOTAL_COMPARE_VALUES) #define COMPARE_CONFIG_OFFSET_CH2(config) ((config) * TOTAL_COMPARE_VALUES) #define COMPARE_CONFIG_OFFSET_CH3(config) ((config) * TOTAL_COMPARE_VALUES) // FIXED: Current configuration pointers - CH2 now points to correct array uint16_t *currentCompareConfigCH1 = &compareConfigsCH1[COMPARE_CONFIG_OFFSET_CH1(0)]; uint16_t *currentCompareConfigCH2 = &compareConfigsCH2[COMPARE_CONFIG_OFFSET_CH2(0)]; uint16_t *currentCompareConfigCH3 = &compareConfigsCH3[COMPARE_CONFIG_OFFSET_CH3(0)]; // Configuration index tracker static uint16_t configIndexCH1 = 0; static uint16_t configIndexCH2 = 0; static uint16_t configIndexCH3 = 0; // Place buffers in GSRAM #pragma DATA_SECTION(compareConfigsCH1, "ramgs0") #pragma DATA_SECTION(compareConfigsCH2, "ramgs1") #pragma DATA_SECTION(compareConfigsCH3, "ramgs1") // Function Prototypes void initDMACH1(void); void initDMACH2(void); void initDMACH3(void); void initEPWM(uint16_t EPWM_BASE); __interrupt void dmaCH1ISR(void); __interrupt void dmaCH2ISR(void); __interrupt void dmaCH3ISR(void); void main(void) { // Initialize device clock and peripherals Device_init(); // Disable pin locks and enable internal pull-ups. Device_initGPIO(); // Initialize PIE and clear PIE registers. Disables CPU interrupts. Interrupt_initModule(); // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). Interrupt_initVectorTable(); // Register DMA interrupt handlers Interrupt_register(INT_DMA_CH1, &dmaCH1ISR); Interrupt_register(INT_DMA_CH2, &dmaCH2ISR); Interrupt_register(INT_DMA_CH3, &dmaCH3ISR); // Disable sync(Freeze clock to PWM as well) SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // Set EPWM Clock Divider to 1 to feed 200 MHz SysClock. SysCtl_setEPWMClockDivider(SYSCTL_EPWMCLK_DIV_1); // PinMux and Peripheral Initialization Board_init(); // Initialize DMA for both channels initDMACH1(); initDMACH2(); // NEW: Initialize DMA CH2 for ePWM2 initDMACH3(); // Initialize both ePWMs initEPWM(myEPWM1_BASE); // initEPWM(myEPWM2_BASE); // initEPWM(myEPWM3_BASE); // Enable sync and clock to PWM SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // C2000Ware Library initialization C2000Ware_libraries_init(); // Enable DMA interrupts Interrupt_enable(INT_DMA_CH1); Interrupt_enable(INT_DMA_CH2); Interrupt_enable(INT_DMA_CH3); // Enable Global Interrupt (INTM) and real time interrupt (DBGM) EINT; ERTM; // Reset the prescale counter to ensure clean start EPWM_clearADCTriggerFlag(myEPWM1_BASE, EPWM_SOC_A); EPWM_clearADCTriggerFlag(myEPWM2_BASE, EPWM_SOC_A); EPWM_clearADCTriggerFlag(myEPWM3_BASE, EPWM_SOC_A); // Initial Shadow to Active load strobe EPWM_enableXLoad(myEPWM1_BASE); EPWM_enableXLoad(myEPWM2_BASE); EPWM_enableXLoad(myEPWM3_BASE); // Start DMA channels EALLOW; DMA_startChannel(DMA_CH1_BASE); DMA_startChannel(DMA_CH2_BASE); DMA_startChannel(DMA_CH3_BASE); EDIS; // Force initial SOCA trigger to start DMA immediately // Only trigger ePWM1 since both DMA channels are triggered by ePWM1SOCA EPWM_forceADCTrigger(myEPWM1_BASE, EPWM_SOC_A); while(1) { } } void initEPWM(uint16_t EPWM_BASE) { // Configure ePWM for XCMP register operation // Most settings are handled by syscfg, but we need to add SOCA for DMA // Enable ADC/DMA trigger (SOCA) - only for ePWM1 since it's the master trigger EPWM_enableADCTrigger(EPWM_BASE, EPWM_SOC_A); // Set trigger source to TBCTR_ZERO for consistent timing EPWM_setADCTriggerSource(EPWM_BASE, EPWM_SOC_A, EPWM_SOC_TBCTR_ZERO); // Set prescale to trigger once per complete configuration cycle EPWM_setADCTriggerEventPrescale(EPWM_BASE, EPWM_SOC_A, 1); // Clear any pending flags EPWM_clearADCTriggerFlag(EPWM_BASE, EPWM_SOC_A); } void initDMACH1(void) { // Initialize DMA controller DMA_initController(); // Calculate the exact register addresses for XCMP Shadow1 registers // XCMP2_SHADOW1 register address (0x22U offset from XCMP base) uint32_t xcmp2Shadow1Addr = myEPWM1_BASE + EPWM_O_XCMP + EPWM_O_XCMP1_ACTIVE + 0x20U + 1U; // ============================================================================ // DMA CH1 - XCMP Compare Values (Multiple XCMP Shadow registers) // ============================================================================ DMA_configAddresses(DMA_CH1_BASE, (uint16_t *)xcmp2Shadow1Addr, // Destination (start at XCMP2_SHADOW1) currentCompareConfigCH1); // Source (start with config0) // Burst configuration for XCMP registers with your array structure: DMA_configBurst(DMA_CH1_BASE, XCMP_PER_SHADOW, 1, 1); // Transfer configuration for complete configuration: DMA_configTransfer(DMA_CH1_BASE, SHADOW_SETS, 1, 0x20 - XCMP_PER_SHADOW + 1); DMA_configMode(DMA_CH1_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); // Configure interrupts for CH1 DMA_setInterruptMode(DMA_CH1_BASE, DMA_INT_AT_END); DMA_enableInterrupt(DMA_CH1_BASE); DMA_enableTrigger(DMA_CH1_BASE); } // NEW: DMA CH2 initialization for ePWM2 void initDMACH2(void) { // Calculate the exact register addresses for ePWM2 XCMP Shadow1 registers uint32_t xcmp2Shadow1Addr = myEPWM2_BASE + EPWM_O_XCMP + EPWM_O_XCMP1_ACTIVE + 0x20U + 1U; // ============================================================================ // DMA CH2 - ePWM2 XCMP Compare Values (Multiple XCMP Shadow registers) // ============================================================================ DMA_configAddresses(DMA_CH2_BASE, (uint16_t *)xcmp2Shadow1Addr, // Destination (ePWM2 XCMP2_SHADOW1) currentCompareConfigCH2); // Source (CH2 config array) // Burst configuration for XCMP registers: DMA_configBurst(DMA_CH2_BASE, XCMP_PER_SHADOW, 1, 1); // Transfer configuration for complete configuration: DMA_configTransfer(DMA_CH2_BASE, SHADOW_SETS, 1, 0x20 - XCMP_PER_SHADOW + 1); // KEY: Both DMA channels triggered by the same ePWM1 SOCA signal for synchronization DMA_configMode(DMA_CH2_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); // Configure interrupts for CH2 DMA_setInterruptMode(DMA_CH2_BASE, DMA_INT_AT_END); DMA_enableInterrupt(DMA_CH2_BASE); DMA_enableTrigger(DMA_CH2_BASE); } void initDMACH3(void) { // Calculate the exact register addresses for ePWM2 XCMP Shadow1 registers uint32_t xcmp2Shadow1Addr = myEPWM3_BASE + EPWM_O_XCMP + EPWM_O_XCMP1_ACTIVE + 0x20U + 1U; // ============================================================================ // DMA CH2 - ePWM2 XCMP Compare Values (Multiple XCMP Shadow registers) // ============================================================================ DMA_configAddresses(DMA_CH3_BASE, (uint16_t *)xcmp2Shadow1Addr, // Destination (ePWM3 XCMP2_SHADOW1) currentCompareConfigCH3); // Source (CH3 config array) // Burst configuration for XCMP registers: DMA_configBurst(DMA_CH3_BASE, XCMP_PER_SHADOW, 1, 1); // Transfer configuration for complete configuration: DMA_configTransfer(DMA_CH3_BASE, SHADOW_SETS, 1, 0x20 - XCMP_PER_SHADOW + 1); // KEY: Both DMA channels triggered by the same ePWM1 SOCA signal for synchronization DMA_configMode(DMA_CH3_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE | DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); // Configure interrupts for CH2 DMA_setInterruptMode(DMA_CH3_BASE, DMA_INT_AT_END); DMA_enableInterrupt(DMA_CH3_BASE); DMA_enableTrigger(DMA_CH3_BASE); } // DMA Channel 1 ISR - Triggered once per complete configuration load __interrupt void dmaCH1ISR(void) { GPIO_writePin(myGPIO1, 1); // This ISR executes once per complete configuration // All XCMP values have been loaded for ePWM1 configIndexCH1++; if (configIndexCH1 >= NUM_CONFIGS) { configIndexCH1 = 0; } // Calculate new addresses for next complete configuration currentCompareConfigCH1 = &compareConfigsCH1[COMPARE_CONFIG_OFFSET_CH1(configIndexCH1)]; // Update DMA source addresses for next complete configuration transfer DMA_configSourceAddress(DMA_CH1_BASE, currentCompareConfigCH1); // Enable XLoad to transfer shadow to active registers for ePWM1 // This activates the newly loaded configuration EPWM_enableXLoad(myEPWM1_BASE); // Clear PIEACK for Group 7 (both DMA CH1 and CH2 are in this group) Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); GPIO_writePin(myGPIO1, 0); } // NEW: DMA Channel 2 ISR - Handles ePWM2 configuration updates __interrupt void dmaCH2ISR(void) { // This ISR executes once per complete ePWM2 configuration // All XCMP values have been loaded for ePWM2 GPIO_writePin(myGPIO1, 1); configIndexCH2++; if (configIndexCH2 >= NUM_CONFIGS) { configIndexCH2 = 0; } // Calculate new addresses for next complete configuration currentCompareConfigCH2 = &compareConfigsCH2[COMPARE_CONFIG_OFFSET_CH2(configIndexCH2)]; // Update DMA source addresses for next complete configuration transfer DMA_configSourceAddress(DMA_CH2_BASE, currentCompareConfigCH2); // Enable XLoad to transfer shadow to active registers for ePWM2 // This activates the newly loaded configuration EPWM_enableXLoad(myEPWM2_BASE); // Clear PIEACK for Group 7 (both DMA CH1 and CH2 are in this group) Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); GPIO_writePin(myGPIO1, 0); } __interrupt void dmaCH3ISR(void) { // This ISR executes once per complete ePWM2 configuration // All XCMP values have been loaded for ePWM2 GPIO_writePin(myGPIO1, 1); configIndexCH3++; if (configIndexCH3 >= NUM_CONFIGS) { configIndexCH3 = 0; } // Calculate new addresses for next complete configuration currentCompareConfigCH3 = &compareConfigsCH3[COMPARE_CONFIG_OFFSET_CH3(configIndexCH3)]; // Update DMA source addresses for next complete configuration transfer DMA_configSourceAddress(DMA_CH3_BASE, currentCompareConfigCH3); // Enable XLoad to transfer shadow to active registers for ePWM2 // This activates the newly loaded configuration EPWM_enableXLoad(myEPWM3_BASE); // Clear PIEACK for Group 7 (both DMA CH1 and CH2 are in this group) Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP7); GPIO_writePin(myGPIO1, 0); }