Tool/software:
Hi,
I need the possibility to run the ePWM module with the DMA but 2 times faster. The Background is that I want to update the ePWM module with the DMA for center aligned PWM.
FOC (Field Oriented Control) is done with around 20kHz and the PWM is at 40kHz. Now to count for the phase delay for a highspeed application, the DMA should already contain 4 sets of PWM. So I want the update for center aligned PWM also in the middle.
I already tried out the epwm_ex9_dma example in the TI examples but I was not able to achieve that. Any ideas how that could be done?
EDIT1: I tried in a first step to update the DMA with every PWM cycle and the FOC ISR at half the speed but I am not able to achieve that:
EPWM init (From Universal Motor Control):
// USER_M1_NUM_PWM_TICKS_PER_ISR_TICK = 2
uint16_t pwmPeriodCycles = (uint16_t)(USER_M1_PWM_TBPRD_NUM);
uint16_t pwmPeriodBCCycles = (uint16_t)(USER_M1_BC_TBPRD_NUM);
uint16_t numPWMTicksPerISRTick = USER_M1_NUM_PWM_TICKS_PER_ISR_TICK;
// setup the Time-Base Control Register (TBCTL)
EPWM_setTimeBaseCounterMode(obj->pwmHandle[cnt],
EPWM_COUNTER_MODE_UP_DOWN);
EPWM_disablePhaseShiftLoad(obj->pwmHandle[cnt]);
// EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_SHADOW_LOAD); //EPWM_PERIOD_SHADOW_LOAD //EPWM_PERIOD_DIRECT_LOAD
EPWM_setPeriodLoadMode(obj->pwmHandle[cnt], EPWM_PERIOD_SHADOW_LOAD); //EPWM_PERIOD_SHADOW_LOAD //EPWM_PERIOD_DIRECT_LOAD
EPWM_enableSyncOutPulseSource(obj->pwmHandle[cnt],
EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
EPWM_setClockPrescaler(obj->pwmHandle[cnt], EPWM_CLOCK_DIVIDER_1,
EPWM_HSCLOCK_DIVIDER_1);
EPWM_setCountModeAfterSync(obj->pwmHandle[cnt],
EPWM_COUNT_MODE_UP_AFTER_SYNC);
EPWM_setEmulationMode(obj->pwmHandle[cnt], EPWM_EMULATION_FREE_RUN);
// setup the Timer-Based Phase Register (TBPHS)
EPWM_setPhaseShift(obj->pwmHandle[cnt], 0);
// setup the Time-Base Counter Register (TBCTR)
EPWM_setTimeBaseCounter(obj->pwmHandle[cnt], 0);
// setup the Time-Base Period Register (TBPRD)
// set to zero initially
EPWM_setTimeBasePeriod(obj->pwmHandle[cnt], 0);
// setup the Counter-Compare Control Register (CMPCTL)
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
EPWM_COUNTER_COMPARE_A,
EPWM_COMP_LOAD_ON_CNTR_ZERO); //EPWM_COMP_LOAD_ON_CNTR_ZERO
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
EPWM_COUNTER_COMPARE_B,
EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
EPWM_COUNTER_COMPARE_C,
EPWM_COMP_LOAD_ON_CNTR_ZERO);
EPWM_setCounterCompareShadowLoadMode(obj->pwmHandle[cnt],
EPWM_COUNTER_COMPARE_D,
EPWM_COMP_LOAD_ON_CNTR_ZERO);
// setup the Action-Qualifier Output A Register (AQCTLA)
EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH,
EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_HIGH,
EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW,
EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
EPWM_setActionQualifierAction(obj->pwmHandle[cnt],
EPWM_AQ_OUTPUT_A,
EPWM_AQ_OUTPUT_LOW,
EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
// setup the Dead-Band Generator Control Register (DBCTL)
EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_RED, true);
EPWM_setDeadBandDelayMode(obj->pwmHandle[cnt], EPWM_DB_FED, true);
// select EPWMA as the input to the dead band generator
EPWM_setRisingEdgeDeadBandDelayInput(obj->pwmHandle[cnt],
EPWM_DB_INPUT_EPWMA);
// configure the right polarity for active high complementary config.
EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
EPWM_DB_RED,
EPWM_DB_POLARITY_ACTIVE_HIGH);
EPWM_setDeadBandDelayPolarity(obj->pwmHandle[cnt],
EPWM_DB_FED,
EPWM_DB_POLARITY_ACTIVE_LOW);
// setup the Dead-Band Rising Edge Delay Register (DBRED)
EPWM_setRisingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBRED_CNT);
// setup the Dead-Band Falling Edge Delay Register (DBFED)
EPWM_setFallingEdgeDelayCount(obj->pwmHandle[cnt], MTR1_PWM_DBFED_CNT);
// setup the PWM-Chopper Control Register (PCCTL)
EPWM_disableChopper(obj->pwmHandle[cnt]);
// setup the Trip Zone Select Register (TZSEL)
EPWM_disableTripZoneSignals(obj->pwmHandle[cnt], HAL_TZSEL_SIGNALS_ALL);
// setup the Event Trigger Selection Register (ETSEL)
EPWM_setInterruptSource(obj->pwmHandle[0], EPWM_INT_TBCTR_ZERO); //EPWM_INT_TBCTR_ZERO
EPWM_enableInterrupt(obj->pwmHandle[0]);
//Initial ADC trigger --> used for FOC
EPWM_setADCTriggerSource(obj->pwmHandle[0], EPWM_SOC_A, EPWM_SOC_TBCTR_D_CMPC); //EPWM_SOC_TBCTR_D_CMPC
EPWM_enableADCTrigger(obj->pwmHandle[0], EPWM_SOC_A);
EPWM_setInterruptEventCount(obj->pwmHandle[0], numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_A,
numPWMTicksPerISRTick);
EPWM_setADCTriggerEventPrescale(obj->pwmHandle[0], EPWM_SOC_B,
numPWMTicksPerISRTick);
// setup the Event Trigger Clear Register (ETCLR)
EPWM_clearEventTriggerInterruptFlag(obj->pwmHandle[0]);
EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_A);
EPWM_clearADCTriggerFlag(obj->pwmHandle[0], EPWM_SOC_B);
// since the PWM is configured as an up/down counter, the period register is
// set to one-half of the desired PWM period
EPWM_setTimeBasePeriod(obj->pwmHandle[0], pwmPeriodCycles);
EPWM_setTimeBasePeriod(obj->pwmHandle[1], pwmPeriodCycles);
EPWM_setTimeBasePeriod(obj->pwmHandle[2], pwmPeriodCycles);
// write the PWM data value for ADC trigger
EPWM_setCounterCompareValue(obj->pwmHandle[0], EPWM_COUNTER_COMPARE_C, 10);
DMA Init:
//
// DMA CH4
//
DMA_configAddresses(DMA_CH4_BASE, (uint16_t *)(MTR1_PWM_U_BASE + EPWM_O_CMPA),
dma_epwm_config.dmaConfigsCycleU);
DMA_configBurst(DMA_CH4_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
DMA_configTransfer(DMA_CH4_BASE, 1, 1, -2); //4 Transfers, CMPAHR , CMPA , CMPBHR , CMPB
DMA_configMode(DMA_CH4_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
//
// DMA CH5
//
DMA_configAddresses(DMA_CH5_BASE, (uint16_t *)(MTR1_PWM_V_BASE + EPWM_O_CMPA),
dma_epwm_config.dmaConfigsCycleV);
DMA_configBurst(DMA_CH5_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
DMA_configTransfer(DMA_CH5_BASE, 1, 1, -2); //4 Transfers, CMPAHR , CMPA , CMPBHR , CMPB
DMA_configMode(DMA_CH5_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT); //Every channel triggers on the 1SOCA or same trigger
//
// DMA CH6
//
DMA_configAddresses(DMA_CH6_BASE, (uint16_t *)(MTR1_PWM_W_BASE + EPWM_O_CMPA),
dma_epwm_config.dmaConfigsCycleW);
DMA_configBurst(DMA_CH6_BASE, 2, 1, 1); //4 bursts --> One for for each up and down of the center aligned PWM
DMA_configTransfer(DMA_CH6_BASE, 1, 1, -2); //4 Transfers, CMPAHR , CMPA , CMPBHR , CMPB
DMA_configMode(DMA_CH6_BASE, DMA_TRIGGER_EPWM1SOCA, DMA_CFG_ONESHOT_DISABLE |
DMA_CFG_CONTINUOUS_ENABLE | DMA_CFG_SIZE_16BIT);
DMA_enableTrigger(DMA_CH6_BASE);
//Start
DMA_startChannel(DMA_CH4_BASE);
DMA_startChannel(DMA_CH5_BASE);
DMA_startChannel(DMA_CH6_BASE);
Thanks
