This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F28379D: ADC halts after updating EPwmRegs1.CMPA

Part Number: TMS320F28379D

Tool/software: Code Composer Studio

Dear,

I have written a program for the TMS320F28379D which is a basic control loop application using 4 complementary PWM signals EPwmRegs1...4, so 8 PWM outputs in total. The EPwmRegs5 pwm channel is configured and used to trigger the ADC in the middle of the switching period. The cycle essentially occurs as follows:

  1. ePwmRegs5.CMPB is set at half the switching period and triggers the ADC
  2. in the ADC isr routine, the measurements are processed (offset compensation and scaling) and a CLA routine is called to calculate the new duty cycles
  3. Also in the ADC isr routine, the new duty cycle values are loaded in EPwmRegs1...4.CMPA

The whole sequence runs properly if step 3 is omitted and I verified the duration of the whole cycle from measurement to control output. It takes 1027 cycles (5 us) on average to determine a new control setting from the measurements. In case I want to send the new duty cycle command to the EPwmRegs1.CMPA register, the routine halts and the ADC isr is no longer called. However, the processor's main loop continues operating, indicating that the processor is still functioning.

Could you please advice on the root cause of this error and how to solve it? I have included some code excerpts below for clarification.

Thanks for your help.

Giel

Set up of the PWM

(*ePWM[j]).TBCTL.bit.PRDLD = TB_SHADOW;  // set Shadow load (enable PWM value at next switching cycle)
        (*ePWM[j]).TBPRD = period;               // PWM frequency = 1/(2*TBPRD)
        //(*ePWM[j]).CMPA.bit.CMPA = period / 2;   // set duty 50% initially
        (*ePWM[j]).CMPA.bit.CMPA = 0;   		// set duty 0% initially
        (*ePWM[j]).CMPA.bit.CMPAHR = (1 << 8);   // initialize HRPWM extension (<< 8 means the shift to the left operand by 8 bits)
        (*ePWM[j]).CMPB.bit.CMPB = period / 2;   // set duty 50% initially
        //(*ePWM[j]).CMPB.all |= 1;
        (*ePWM[j]).TBPHS.all = 0;
        (*ePWM[j]).TBCTR = 0;

        (*ePWM[j]).TBCTL.bit.PHSEN = 1;

        (*ePWM[j]).TBCTL.bit.CTRMODE = TB_COUNT_UP; 	// Select up count mode (ramp up)
                                                        // count mode
        (*ePWM[j]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN;		// Synchronize ePwm clocks
        (*ePWM[j]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
        (*ePWM[j]).TBCTL.bit.CLKDIV = TB_DIV1;          // TBCLK = SYSCLKOUT
        (*ePWM[j]).TBCTL.bit.FREE_SOFT = 11;

        (*ePWM[j]).CMPCTL.bit.LOADAMODE = CC_CTR_PRD;  // LOAD CMPA on CTR = 0
        (*ePWM[j]).CMPCTL.bit.LOADBMODE = CC_CTR_PRD;
        (*ePWM[j]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;	// A shadow register stores the PWM settings until the next PWM cycle where they will be effectively applied
        (*ePWM[j]).CMPCTL.bit.SHDWBMODE = CC_SHADOW;

        (*ePWM[j]).AQCTLA.bit.ZRO = AQ_SET;             // PWM toggle high/low
        (*ePWM[j]).AQCTLA.bit.CAU = AQ_CLEAR;
        (*ePWM[j]).AQCTLB.bit.ZRO = AQ_SET;             // PWM toggle high/low (note: the bit DBCTL.bit.POLSEL further down specifies the complimentarity of the PWM channels signals)
        (*ePWM[j]).AQCTLB.bit.CAU = AQ_CLEAR;

Setup of the PWM to trigger the ADC

EPwm5Regs.ETSEL.bit.SOCASEL    = ET_CTRU_CMPB;       // Trigger SOC when counter equals CMPB which is set at half the switching period
EPwm5Regs.ETPS.bit.SOCAPRD     = ET_1ST;           // Generate pulse on every event
EPwm5Regs.ETSEL.bit.SOCAEN    = 1;                // Enable SOC on A group

Each ADC SOC channel is triggered by SOCA of EPwmRegs5

AdcaRegs.ADCSOC1CTL.bit.TRIGSEL = 13;     //trigger on ePWM5 SOCA

ADC isr routine:

// Process measurements
    CLA_process_measurements();

    // Check protection limits
    Protection();

    // State machine
    state_machine();

    // Control law
    RunControlLaw();

    // Set duty cycle
    //setDutyCycle(500,500,500,500);
    //setDutyCycle(res3[2],res3[3],res3[4],res3[5]);

    cycle_duration = CpuTimer0Regs.PRD.bit.LSW - CpuTimer0Regs.TIM.bit.LSW;

    // Acknowledge interrupt
    AdcaRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; //clear INT1 flag
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;

res3[2]...[5] are 4 duty cycles calculated by the CLA.

setDutyCycle:

//
// setDutyCycle - set the duty cycle of the converter
//
void setDutyCycle(Uint16 pwm1, Uint16 pwm2, Uint16 pwm3, Uint16 pwm4)
{
    EPwm1Regs.CMPA.bit.CMPA = pwm1;
    EPwm2Regs.CMPA.bit.CMPA = pwm2;
    EPwm3Regs.CMPA.bit.CMPA = pwm3;
    EPwm4Regs.CMPA.bit.CMPA = pwm4;
}

  • Hi Giel,

    Since the setDutyCycle function has nothing to do with EPWM5 which is triggering the ADC, I'm leaning towards this being a timing issue. if you comment out the setDutyCycle and replace it with a bunch of NOPs (10-20) by putting asm(" NOP"), does the ISR routing continue to get triggered?

    Are you actually calling setDutyCycle twice in your code or were you just testing with known values on this line (setDutyCycle(500,500,500,500);)? When it fails, can you check the status of various interrupt flags? ETFLG in the EPWM, any flags which should be set in the ADC, PIEIFR, IFR.


    Regards,
    Kris

  • Hi Kris,

    Thanks for your help.

    I have thus far tested the routine with 20 lines of NOPs, as you suggested but without updating the duty cycle. Everything runs properly and the whole cycle takes 1098 clock periods, somewhat more than before due to the NOPs. The ISR thus remains triggered.

    I am not calling setDutyCycle twice, it was indeed just for testing purposes.

    Furthermore, as you suggested, I verified the ETFLG registers. It appears that the SOCA bit of the EPwm5Regs.ETFLG register is properly set to trigger the ADC. However, the ADCINT flag no longer gets set. I will hence further look into the interrupt routine as the DSP gets stuck there.

    I will keep you informed about my progress, but additional recommendations are always welcome. Thanks!

    Kind regards,
    Giel