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.

TMS320F28035: External Interrupt have a big abnormal delay by reading XINT1CTR

Part Number: TMS320F28035

Hi,

I want to read a real delay for determining how far into the past the interrupt was triggered.

I read the value of the register immediately When the interrupt is triggered, but it has a large numerical range, the project only have one isr(XINT1_ISR), the XINT1CTR value is display by graph as below. 

Theoretically, this value should be relatively constant,I'm very confused about the abnormal value. 

Attached is my project, connect GPIO0/EPWM1A  to GPIO3  before dubug,  add array variable wBufferEPWM1TBCTR to watch window or grgph.

wBufferEPWM1TBCTR[temp_cnt_a++] = readxint1ctr;//Sys_PhaseMargin;//*16.6667;
if(temp_cnt_a >= 50)
{
temp_cnt_a = 0;
}

 

thanks in advance

 

  0285.HB358K.rar

  • Hi,

    I find that my problem is similar to this one  https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/535190?120cycles-Interrupt-latency-on-28035  

    and this https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/88357

    To simplify testing, I simplified the code as below.

    It can be clearly observed that   asm(" RPT #5 || NOP")   have an effect on interrupt latency,the more number of NOP the more interrupt latency,.

    it can be seen in the attached chart. i don't know what is the reason for this situation. I think maybe my project problem is also related to this NOP code although I didn't call this NOP explicitly

    //
    // Included Files
    //
    #include "DSP28x_Project.h" // Device Headerfile and Examples Include File

    //
    // Function Prototype
    //
    __interrupt void xint1_isr(void);
    __interrupt void xint2_isr(void);

    //
    // Globals
    //
    volatile Uint32 Xint1Count;
    volatile Uint32 Xint2Count;
    Uint32 LoopCount;

    Uint16 readxint1ctr;
    Uint16 temp_cnt_a = 0;
    Uint16 buffer[50];
    //
    // Defines
    //
    #define DELAY (CPU_RATE/1000*6*510) //Qual period at 6 samples

    //
    // Main
    //
    void main(void)
    {


    //
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the DSP2803x_SysCtrl.c file.
    //
    InitSysCtrl();

    //
    // Step 2. Initialize GPIO:
    // This example function is found in the DSP2803x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    //
    //InitGpio(); // Skipped for this example

    //
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
    //
    DINT;

    //
    // Initialize PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the DSP2803x_PieCtrl.c file.
    //
    InitPieCtrl();

    //
    // Disable CPU interrupts and clear all CPU interrupt flags:
    //
    IER = 0x0000;
    IFR = 0x0000;

    //
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example. This is useful for debug purposes.
    // The shell ISR routines are found in DSP2803x_DefaultIsr.c.
    // This function is found in DSP2803x_PieVect.c.
    //
    InitPieVectTable();

    //
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
    //
    EALLOW; // This is needed to write to EALLOW protected registers
    PieVectTable.XINT1 = &xint1_isr;
    EDIS; // This is needed to disable write to EALLOW protected registers

    //
    // Step 4. Initialize all the Device Peripherals:
    // Not required for this example
    //

    //
    // Step 5. User specific code, enable interrupts:
    //

    //
    // Clear the counters
    //


    //
    // Enable XINT1 and XINT2 in the PIE: Group 1 interrupt 4 & 5
    // Enable INT1 which is connected to WAKEINT:
    //
    PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block
    PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // Enable PIE Group 1 INT4
    IER |= M_INT1; // Enable CPU INT1

    EALLOW;
    GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0; // 0=GPIO, 1=COMP2OUT, 2=Resv, 3=COMP3OUT
    GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // 1=OUTput, 0=INput
    EDIS;

    /*
    * config external interrupt IO
    *
    */
    EALLOW;
    // GPIO-03 - PIN FUNCTION =
    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0; // 0=GPIO, 1=EPWM2B, 2=SPISOMI-A, 3=COMP2OUT
    GpioCtrlRegs.GPADIR.bit.GPIO3 = 0; // 1=OUTput, 0=INput
    GpioCtrlRegs.GPAQSEL1.bit.GPIO3 = 0; // XINT1 Synch to SYSCLKOUT only

    // GPIO3 is XINT1
    GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 3; // XINT1 is GPIO3
    EDIS;

    // Configure XINT1
    XIntruptRegs.XINT1CR.bit.POLARITY = 0; // Falling edge interrupt
    XIntruptRegs.XINT1CR.bit.ENABLE = 1; // Enable XINT1

    /*
    * config pwm1 output
    */
    Pwm1_Init();
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
    EDIS;

    EINT; // Enable Global interrupt INTM
    ERTM;

    while(1)
    {

    asm(" RPT #5 || NOP");
    //asm(" RPT #75 || NOP");
    }
    }
    //
    // xint1_isr -
    //
    __interrupt void xint1_isr(void)
    {
    readxint1ctr = XIntruptRegs.XINT1CTR;
    GpioDataRegs.GPBTOGGLE.bit.GPIO34 = 1; // uncomment if --> Set Low initially
    buffer[temp_cnt_a++] = readxint1ctr;
    if(temp_cnt_a >= 50)
    {
    temp_cnt_a = 0;
    }

    //
    // Acknowledge this interrupt to get more from group 1
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
    }

    void Pwm1_Init(void)
    {
    Uint16 wPWM1Freq,wPWM1Period;

    EALLOW;
    GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 status from input to EPWM1A
    EDIS;

    //--------------------------------------------------
    //pwm1
    //---------------------------------------------------
    wPWM1Freq = 40000; // init Freq
    wPWM1Period = (Uint16)(60000000 / wPWM1Freq);
    wPWM1Period = wPWM1Period/2;

    EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // set load on CTR=0

    EPwm1Regs.TBPRD = wPWM1Period; // PWM frequency = 1 / period
    EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm1Regs.TBCTR = 0x0000; // Clear counter

    // Setup TBCLK
    EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Count updown
    EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading
    EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module
    EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // Clock ratio to SYSCLKOUT
    EPwm1Regs.TBCTL.bit.CLKDIV = 0; // Slow so we can observe on the scope

    //EPwm1Regs.TBCTL.bit.FREE_SOFT = 11; // XYN, Emulation Mode Bits 1X FREE RUN

    // Setup compare
    EPwm1Regs.CMPA.half.CMPA = 1;
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=PRD--asymmetric PWM

    EPwm1Regs.CMPB = 12;//one adc convert time befor pwmB turn off
    EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW;
    EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // load on CTR=PRD--asymmetric PWM

    // Set actions
    EPwm1Regs.AQCTLA.bit.PRD = AQ_CLEAR;
    EPwm1Regs.AQCTLA.bit.CAU = AQ_SET;

    EPwm1Regs.AQCTLB.bit.PRD = AQ_CLEAR;
    EPwm1Regs.AQCTLB.bit.CAD = AQ_SET;

    // Active high complementary PWMs - Setup the deadband
    EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm1Regs.DBCTL.bit.IN_MODE = DBA_RED_DBB_FED;
    EPwm1Regs.DBRED = 210;
    EPwm1Regs.DBFED = 210;
    }


    //
    // End of File
    //

  • Hi,

    I have something new progress.

    After I blocked other functions,The problem in my project in first floor focus on one function, it have a local variable array, if i change this array to global variable, interrupt latency get better and is about 30 clocks delay which i think this value is a normal value(but it also appear in the case of high latency Infrequently). chart is shown as below.

    Now i have one question:

    1. why function local variable array can lead to interrupt latency? It seems that I did not find the root cause, if i uncomment next line code 

     PhaseAngle = 180.0*Sys_PhaseMargin/period;    interrupt latency is also abnormal。

    2. why asm(" RPT #5 || NOP")   have an effect on interrupt latency?  --- a RPT instruction (single repeat). This cannot be interrupted.

    any answer will be appreciate.

  • Yanan,

    I am glad that you made progress on your debugging.  I will get someone from our software team to comment about the local variable array leading to interrupt latency.  As for your second question, please see the "TMS320C28x CPU and Instruction Set Reference Guide":

    http://www.ti.com/lit/spru430

    On page 395 you will notice that the assembly instruction RPT is not repeatable.

    - Ken

  • Hello

    The large local variable array needs to be initialized on every entry into this function which I suspect is an action that can't be interrupted. 

    If you don't want to make it global, you can make it a local static variable array. On first function entry it will initialize but on further entries into the function, it will already be initialized. Essentially a "global" variable only for that function. 

    Best regards

    Chris 

  • Yanan,

    If this answers your questions, please close this thread by clicking the green "Verified Answer" button. Thanks.

    - Ken

  • Hi, Ken and Chris 

    I really appreciate your help.
    According to your answer i located the cause of the problem,  the reason is Assembly code contains RPT instruction,When the RPT instruction is executing, interrupt  triggered at the same time.
    beside assignment statements for large arrays, Math calculations also be compiled into instructions containing RPT
    the below picture can explain the reason
    I want the interrupt latency to be as stable as possible,therefore,i config project "Don't generate RPT instructions", there is no RPT in assignment statements for large local arrays, but  other Math calculations also have RPT, picture as below
    How can I completely avoid this RPT instruction?
    TKS
  • Hello

    Good to see that the local variable has been resolved. The "--no_rpt" should remove the RPT usage. We suspect since the math is being handled by an RTS library function, that is why you still see RPT there. Can you try setting your optimization level to O4 for your application? At O4, a re-compile will also recompile the RTS library object code.

    If that doesn't work, please provide the math statement code and any details on what libraries your including to perform the math.

    Best regards

    Chris 

  • Hi, Chris

    Thanks for your reply,

    After i set potimization level to O4, There are some new problems, it seems nothing to  do with this title, I don’t know if I should put the question here,so, I wrote a new post。

    I will reply to you after solving these problems

  • Yanan,

    Since this thread is being continued in a new thread, I will close this thread.  For reference, the new thread can be found at:

    https://e2e.ti.com/support/microcontrollers/c2000/f/171/t/903451

    - Ken