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.

TMS320F28069: ADC SOC/EOC interrupts with PWM2

Part Number: TMS320F28069


Hi,

I am trying to trigger the ADC to start conversion at the falling edge of PWM2B. I am able to generate an ADC interrupt and eventually read a value from channel10 when I trigger conversion on PWM1B ( when I set: EPwm1Regs.ETSEL.bit.SOCBSEL = 6; and AdcRegs.ADCSOC0CTL.bit.TRIGSEL=6;

Could anyone tell me what's missing in this setup which prevents either an SOC or EOC interrupts from occurring?  Thanks you!!

Here is my setup

 /* Configure ADC */
     EALLOW;
     AdcRegs.INTSEL1N2.bit.INT1E = 1;       /* Enabled ADCINT1 */
     AdcRegs.INTSEL1N2.bit.INT1CONT = 0;    /* Disable ADCINT1 Continuous mode */
     AdcRegs.INTSEL1N2.bit.INT1SEL = 0;     /* setup EOC0 to trigger ADCINT1 to fire */
     AdcRegs.ADCSOC0CTL.bit.CHSEL = 0xA;    /* Set SOC0 channel select to ADCINB2 */
     AdcRegs.ADCSOC0CTL.bit.TRIGSEL = 8;    /* Set SOC0 start trigger on EPWM1B, due to round-robin SOC0 converts first then SOC1 */
     AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;      /* Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
     AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;   /* Configure early interrupts */
     EDIS;

     /* Assumes ePWM1 clock is already enabled in InitSysCtrl(); */
     EPwm2Regs.ETSEL.bit.SOCBEN = 1;        /* Enable SOC on B group */
     EPwm2Regs.ETSEL.bit.SOCBSEL = 8;       /* Select SOC from from CPMB on upcount */
     EPwm2Regs.ETPS.bit.SOCBPRD = 0;        /* Generate pulse on 1st event */

     /*PWM2: Set period / duty / count mode */
     EPwm2Regs.TBPHS.half.TBPHS = 0;  //PHASE           /* Set Phase register to zero */
     EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;     //TB_ENABLE;      /* Phase loading disabled */
     EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;    /* Clock ratio to SYSCLKOUT */
     EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;
     EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW;
     EPwm2Regs.AQCTLA.bit.ZRO = AQ_SET;          /* Set PWM2A on Zero */
     EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;        /* Clear PWM1A on match on count A up */
     EPwm2Regs.AQCTLB.bit.ZRO = AQ_SET;          /* Set PWM1B on Zero */
     EPwm2Regs.AQCTLB.bit.CBU = AQ_CLEAR;        /* Clear PWM2B on match on count B up */
     EPwm2Regs.CMPB = 180;                       /* Set compare B value */
     EPwm2Regs.CMPA.half.CMPA = 250;             /* Set compare A value */
     EPwm2Regs.TBPRD = PERIOD;                   /* Set period for ePWM1 */
     EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;  /* Count up and start */
     EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;//TB_SYNC_IN;

  • So you're saying that ePWM1 SOCB works but ePWM2 SOCB does not?

    Could you pull up the Registers view in CCS and make sure the ePWM2 is powered up and the proper values are being written to the registers? I don't think any of the ones you're writing to are EALLOW protected, but I would be good to double check.

    Is the conversion still happening but it's just the interrupt that's missing? Or is the result register not updating either?

    Thanks,

    Whitney

  • Thank you so much for your help! i have managed to fix my issue. Though I still have a question:

    I have 3 ePWMs: PWM1B,PWM2B,and PWM3B and I have configured these ePWMs to trigger an ADC start of conversion (on the falling edge of EPWMB channels)  which eventually generates an ADC Isr.

    Would it be possible for me to figure out inside the ISR which ePWM(among the three) caused the ADC conversion? 

    Thanks!

  • It depends how your interrupts are set up. For example, if the SOCs triggered by PWM1, PWM2, and PWM3 are associated with ADCINT1, INT2, and INT3 but use the same ISR, you could read the PIECTRL.PIEVECT register to see which interrupt vector got you into the ISR and therefore which PWM.

    If you're using the same ADCINT number for all of the SOCs, you could try checking the ETFLG registers for each of the PWMs to see which one has SOCB set. As far as I know, it should only be cleared by a write to the ETCLR register, so you should be able to use it for this purpose.

    Whitney
  • Thank you very much for that!

    Now I need to call CLA1task1, CLA1task2, CLA1task3 from each of the 3 ISRs I have set up. Would this call get the job done: Cla1ForceTask1andWait(); Cla1ForceTask2andWait();Cla1ForceTask3andWait()?
  • You can force the CLA task from your ISR, but I don't know that you'd want to wait for the task to finish there. That seems like a lot of time to spend in an ISR. You may want to just use Cla1ForceTask1 in the ISR but check to see if the task finished elsewhere in the code.

    Whitney
  •   Hi!

    I am back to the same issue again. I am trying to trigger an SOC of the same analog signal using 2 PWMs(at  the falling edge of each at 120 degrees phase shift). I am using the below configuration:

      /* Configure ADC */
         EALLOW;
         AdcRegs.INTSEL1N2.bit.INT1E = 1;       /* Enabled ADCINT1 */
         AdcRegs.INTSEL1N2.bit.INT1CONT = 0;    /* Disable ADCINT1 Continuous mode */
         AdcRegs.INTSEL1N2.bit.INT1SEL = 0;     /* setup EOC0 to trigger ADCINT1 to fire */
         AdcRegs.ADCSOC0CTL.bit.CHSEL = 0xA;    /* Set SOC0 channel select to ADCINB2 */
         AdcRegs.ADCSOC0CTL.bit.TRIGSEL = ADCTRIG_EPWM1_SOCB; //6;    /* Set SOC0 start trigger on EPWM1B, due to round-robin SOC0 converts first then SOC1 */
         AdcRegs.ADCSOC0CTL.bit.ACQPS = 6;      /* Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
         AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;   /* Configure early interrupts */
         EDIS;

         /* Configure ADC */
         EALLOW;
         AdcRegs.INTSEL1N2.bit.INT1E = 1;                             /* Enabled ADCINT2 */
         AdcRegs.INTSEL1N2.bit.INT1CONT = 0;                          /* Disable ADCINT2 Continuous mode */
         AdcRegs.INTSEL1N2.bit.INT1SEL = 1;                           /* setup EOC1 to trigger ADCINT2 to fire */
         AdcRegs.ADCSOC1CTL.bit.CHSEL =0xA;                           /* Set SOC1 channel select to ADCINB0 */
         AdcRegs.ADCSOC1CTL.bit.TRIGSEL= ADCTRIG_EPWM2_SOCB;          /* Set SOC1 start trigger on EPWM1B, due to round-robin SOC0 converts first then SOC1 */
         AdcRegs.ADCSOC1CTL.bit.ACQPS = 6;                            /* Set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
         AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0;                         /* Configure early interrupts */
         EDIS;

    When I get an ISR I check for the SET flag bits to see which triggered the event, and turns out that the flag bits are set in both if statements.

      if(EPwm1Regs.ETFLG.bit.SOCB==1)
        {
           GpioDataRegs.GPBTOGGLE.bit.GPIO32=1;
           EPwm1Regs.ETCLR.bit.SOCB = 1;
        }

        if(EPwm2Regs.ETFLG.bit.SOCB==1)
        {
          GpioDataRegs.GPBTOGGLE.bit.GPIO32=1;
          EPwm2Regs.ETCLR.bit.SOCB = 1;
        }

    Could you please let me know what I am missing my configuration.

    Eventually what I would like to do is to trigger a CLA to compute a PID value for each of the three ADC values sampled after each PWM trigger. Could you please advise on how to proceed with this.

    Regards!

  • Hi,

    I have managed to fix my issue. Now I have 3 PWMs triggering an ADC SOC, and I am getting three different interrupts from which I am reading ADC results from SOC0, SOC1, and SOC2. Now I need to call a CLA task to calculate a PID value from each ISR using the retrieved ADC value.

    Is it better to make a CLA task call after each EOC interrupt, instead of what I am doing now, and then read the ADC value and use that to calculate the PID value ?
  • one more question:

    I am calling task1 from an ISR as follow:

    __interrupt void
    adc_isr1(void)
    {
    ADCValue_PWM1B = AdcResult.ADCRESULT0;
    Cla1ForceTask1();

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; /* Clr ADCINT1 flag for next SOC */
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; /* Acknowledge interrupt to PIE */
    }

    in the CLA I am modifying the ADC value as follow:

    __interrupt void
    Cla1Task1 (void)
    {
    __mdebugstop();
    ADCValue1= ADCValue_PWM1B*3;
    }

    However, the value of ADCValue1 does not change in main, I always read zero. Can anyone advise on how to share variables between CPU and CLA.

    here is how I defined my variables inside shared_data.c:

    #pragma DATA_SECTION(ADCValue_PWM1B,"CpuToCla1MsgRAM");
    Uint16 ADCValue_PWM1B;

    #pragma DATA_SECTION(ADCValue1,"Cla1ToCpuMsgRAM");
    Uint16 ADCValue1;
  • I have assigned an ADC to trigger an CLA task: AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; I have noticed that the CLA is called only once? can any one tells me what I might be missing?


    __interrupt void
    Cla1Task1 (void)
    {
    __mdebugstop();
    ADCValue_PWM1B = AdcResult.ADCRESULT0;
    ADCValue1= ADCValue_PWM1B*2;
    }

    __interrupt void
    cla1_task1_isr(void)
    {
    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
    PieCtrlRegs.PIEACK.bit.ACK11 = 1;

    }
  • Are you still having the issue with sharing ADCValue1? If you look at its address in the .map file, is it definitely being placed in the Cla1ToCpuMsgRAM?

    Can you confirm by looking at the registers window that the ADCINT1 flag is in fact being properly cleared? Are you modeling your code off of the cla_adc_fir32 example? It also uses ADCINT1 to trigger a CLA task.

    Whitney
  • Now I am triggering a CLA task from an ADC EOC ISR, and ADC SOC is triggered by the falling edge of a PWM. I found out before that my CLA task runs only once. But now after I added Cla1Regs.MMEMCFG.all |= CLA_PROG_ENABLE; inside the ISR, the CLA is being called continuously as soon as I receive an ADC interrupt.

    above in main(), I have this piece of code
    EALLOW;
    Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM1CPUE;
    Cla1Regs.MCTL.bit.IACKE = 1;
    EDIS;



    __interrupt void
    adc_isr1(void)
    {

    AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1; /* Clr ADCINT1 flag for next SOC */
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; /* Acknowledge interrupt to PIE */

    ADCValue_PWM1B= AdcResult.ADCRESULT0;

    EALLOW;
    Cla1Regs.MMEMCFG.all |= CLA_PROG_ENABLE;
    EDIS;

    Cla1ForceTask1();
    }

    I don't know what this CLA_PROG_ENABLE has to do with task1 if was already declared in main.

    Also I found out that the delay time between the falling edge of PWN that triggers ADC SOC and ADC ISR (EOS) is around 600ns. Is there any way I can make this time delay shorter.

    Thanks!
  • I added the code below in the ADC ISR and CLA is being called as expected. Can anyone explain what that piece of code has to do with triggering the CLA task.

    EALLOW;
    Cla1Regs.MMEMCFG.all |= CLA_PROG_ENABLE;
    EDIS;

    in main() I already called:
    EALLOW;
    Cla1Regs.MMEMCFG.all = CLA_PROG_ENABLE|CLARAM0_ENABLE|CLARAM1_ENABLE|CLARAM2_ENABLE|CLA_RAM1CPUE;
    Cla1Regs.MCTL.bit.IACKE = 1;
    EDIS;


    adc_isr1(void)
    {
    AdcRegs.ADCINTFLGCLR.bit.ADCINT2 = 1; /* Clr ADCINT2 flag for next SOC */
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; /* Acknowledge interrupt to PIE */

    EALLOW;
    Cla1Regs.MMEMCFG.all |= CLA_PROG_ENABLE;
    EDIS;

    Cla1ForceTask1();

    }