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.
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
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":
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
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