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/TMS320F28027: Conflict with CPU Timer 1 and ADC Interrupts

Part Number: TMS320F28027


Tool/software: Code Composer Studio

Hello everyone, 

I use a C2000 Piccolo LaunchPad evaluation board, equipped with the TMS320F28027 and I'm trying to implement a CPU Timer 1 Interrupt, every 1 sec, in order to automatically change the Comparator 2 internal reference set-point (Comp2Regs.RAMPMAXREF_SHWD), according to an exponential equation. In my code, I also use an ADC interrupt, for ADC conversion purposes. I thought that these 2 interrupts are independent. Although, it seems that the 2 interrupt functions do not operate properly. When I comment the line "IER = M_INT13", only the ADC Interrupt operates, whereas by commenting "IER = M_INT1", only the CPU Timer 1 interrupt operates. I attach you my main function, along with the 2 Interrupt function codes. For the Timer 1 interrupt, I used the "Example_2802xCpuTimer" as a guide. Please provide some help! 

Thanks a lot, in advance!

Nick

#include "DSP28x_Project.h"   
#include "stdio.h"    
#include "math.h"

__interrupt void cpu_timer1_isr(void);
interrupt void adc1_isr(void);

//...

void main()
{

#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

    InitSysCtrl();
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 0;
    DINT;

    InitPieCtrl();

    IER = 0x0000;
    IFR = 0x0000;

    InitPieVectTable();

EALLOW;  
       
PieVectTable.TINT1 = &cpu_timer1_isr;
       
EDIS;    

InitCpuTimers();   

ConfigCpuTimer(&CpuTimer1, 60, 1000000);

CpuTimer1Regs.TCR.all = 0x4001; 

IER |= M_INT13;


    EALLOW;
        
        PieVectTable.ADCINT1 = &adc1_isr;
        
    EDIS;

    InitGPIO();

    EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    ADCConfig();
    InitADC();
    InitAIO();
    InitEPwm3Example();
    Comp();
    CompTripZone();
    scia_init();
    scia_fifo_init();

    EALLOW;
        SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;
    
    IER |=M_INT3;
    IER |= M_INT1;

    PieCtrlRegs.PIEIER3.bit.INTx1 = 1;  
    PieCtrlRegs.PIEIER1.bit.INTx1 = 1;     

    EINT;                                 
    ERTM;

    for(;;);
}

//...

interrupt void adc1_isr(void)
{
    if (button==1){
                EALLOW;
                    EPwm1Regs.TZCTL.bit.DCAEVT2=3;
                    EPwm1Regs.CMPA.half.CMPA = 0;                  
                    DELAY_US(ADC_usDELAY);
                    EPwm4Regs.CMPA.half.CMPA = 1500;
                EDIS;
    }

    temp=(3.3*AdcResult.ADCRESULT0)/4096;
    flag1=AdcResult.ADCRESULT0/16;                                  
    flag2=AdcResult.ADCRESULT4/16;    
    scia_xmit(flag1);
    sum=AdcResult.ADCRESULT0;
    sum=sum/1000;
    AV=AV+sum;
    if (pointer<1000)
     {  pointer=pointer+1;
     }
     else
     {
     RealVoltage=AV;
     AV=0;
     pointer =0;
}
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;      //Clear ADCINT1 flag reinitialize for next SOC
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;    // Acknowledge interrupt to PIE
      return;
}

//...

__interrupt void cpu_timer1_isr(void)
{
   CpuTimer1.InterruptCount++;
   flag3=CpuTimer1.InterruptCount;
   if (CpuTimer1.InterruptCount<=120){
       temp1 = 58000;
   }
       else if ((CpuTimer1.InterruptCount>120) && (CpuTimer1.InterruptCount<=300)){
           temp1 = 58000*exp((-flag3+120)/(100+6*flag3));
       }
           else{
               temp1 = 52800;
           }
   Comp2Regs.RAMPMAXREF_SHDW=temp1;
}
  • Nikolaos,
    Thanks for reaching out to the E2E forums.  I beleive what you are seeing is conflict in the interrupts, that is after one interrupt is recognized and serviced by the CPU, the default action is to globally disable all other interrupts until the ISR has completed.  In your case this will show up as unexplained ISR timings based on the expected ADC sample rate and timer.  

    When you disabled the respective IER for one or the other, you will see the correct timing come through.  Also note that the ADC ISR is in group 1 which has the highest priority (group 1) so if it coming before the ISR is complete, it will pend and prevent the timer ISR(in group 13) from being serviced.

    Please take a look at this WIKI article on Interrupt priority and methods for nesting/arbitration if needed:

    https://processors.wiki.ti.com/index.php/Interrupt_Nesting_on_C28x#Adding_Simple_Software_Prioritization_.28Nesting.29  

    Best,

    Matthew

  • Dear Matthew,

    Thanks a lot for your response and useful advice. I finally managed to solve my problem, by simply nesting the code of Timer 1 Interrupt function, into the ADC interrupt function, which operated properly. Although this seems to work (with some modifications), I didn't understand if the priority of the Interrupts is changeable by the user or do I have to make the "nesting", according to the link you sent me.

    For example, if I want to use Timer 0 Interrupt (TINT0) and ADC Interrupt (ADCINT1), which are both in PIE, how can I change the priority between these 2??? As it is stated in the Interrupt Datasheet for TMS320F28027, the priority is according to a PIE MUX (i.e. INT1.1 for ADCINT1 and INT1.7 for TINT0), which I think is fixed. I understand that INT1.1 has higher priority than INT1.7, according to the link you sent. Is this right? Are there any code examples available for prioritizing interrupts? 

    Best Regards,

    Nick

  • Nick,

    There are 2 parameters in play with the interrupts on the C2000 MCU; I think it will help to clarify these a bit:

    1)Priority - As you mentioned all ISRs in the PIE have a fixed priority both outside their group; i.e. group1 interrupt sources have higher priority than group 2 ansd so on and within a group ISR 1.1 has higher priority than ISR1.2, and so on.

    This priority is only really applicable if the ISR source(s) issued a trigger to the PIE at the same time OR while another ISR is being processed 2 or more interrupts come in and set their respective IFR bits(flag bits).  

    For example; lets say that the C28x is currently servicing PIE Interrupt 3.2; and while the ISR is executing PIE Interrupt 5.1 comes in and a few cycles later PIE Interrupt 2.7 comes in.  In a normal case, other interrupts are disabled globally when and  ISR is received, and does not clear until the end of the ISR(unless you nest).  Once this ISR is finished, since there are interrupt pending the PIE will proceed to service PIE 2.7, even though PIE 5.1 came in time before.  This is the influence of priority

    2)Nesting - This is manually re-enalbling interrupts even though the current ISR is not complete.  Even if an interrupt is a higher priority than the one being serviced it cannot break in unless the code re-enables interrupts(which you have done per the above).

    I would recommend taking a look at chapter 1.6 in the TRM http://www.ti.com/lit/sprui09 

    Let me know if you have further questions.

    Best,
    Matthew

  • Dear Matthew, 

    Thank you for your response and your helpful comments and suggestions! The interrupts issue is clearer now. If further questions occur, concerning the C2000 programming, I"ll be back with a new post. 

    Best regards,

    Nick.