Supporting real-time tasks on a CPU requires the use of interrupts. If an external sensor senses a fault, the CPU needs to be interrupted or halted to perform a subroutine that is able to handle the fault. In this example, timing of the interrupt of when the signal reaches the CPU matters. Interrupts are hardware or software-driven signals that cause the CPU to suspend the current program sequence and execute a subroutine. Interrupts often handle time critical loops and control algorithms that are critical to the application and need to execute in timely fashion. Most of the case interrupts can happen periodically with a known frequency. However, when designing the software architecture, have you ever seen an interrupt waveform oscillate incorrectly, as shown in Figure 1?
First, there are two concepts to focus on with interrupt latency that are interrupt propagation path and interrupt timing. The interrupt propagation path is the time from an interrupt request triggering to the beginning of the interrupt service function. Second, confirm if there are any interference factors during an interrupt request triggering or with normal interrupt execution. Third, interrupt latency is maintained to be executed normally by setting interrupt priority reasonably (such as interrupt nesting and register stack restore/protect) and shielding others interrupt interference source.
Interrupt propagation path on C28x handles interrupts in four main phases:
Most programmers only pay attention to first two phases, and know less about stack protection or recovery and interrupt response in the last two phases. This application brief dives deeper into phases three and four.
Figure 3 shows how peripheral interrupts propagate to the CPU.
Figure 4 shows how C28x generates and responds to interrupt service functions.
The interrupt timing from interrupt request triggering to interrupt service function ISR:
In addition to correct usage of interrupt request and interrupt approval operation bits (Such as INTM, IER bit), consider the following interference factors and interrupt nesting that can affect interrupts.
These two points are sources that can affect how the interrupt timing can be affected.
When talking about interrupt nesting, interrupts are automatically prioritized by the C28x hardware. Prioritization for all interrupts can be found in the System Control guide specific to the particular device family. When the C28x CPU is responding to a low-priority interrupt, the CPU interferes with the normal response of a high-priority interrupt, as described in Figure 6.
Therefore, application code needs to add simple software prioritization during low priority interrupts. This allows the CPU to respond to high-priority interrupt processing in a timely manner from the execution of low-priority interrupts. Here are the steps C28x performs interrupt nesting:
// // C28x ISR Code // // Enable nested interrupts // // ADCA1 interrupt for loop Interrput
void INT_myCPUTIMER2_ISR(void)
{
uint16_t TempPIEIER;
TempPIEIER = PieCtrlRegs.PIEIER1.all; // Save PIEIER register for later
IER |= 0x001; // Set global priority by adjusting IER
IER &= 0x001;
PieCtrlRegs.PIEIER1.all &= 0x0001; // Set group priority by adjusting PIEIER1 to //allow INT1.1 to interrupt current CPU time0 ISR
PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
asm(" NOP"); // Wait one cycle
EINT; // Clear INTM to enable interrupts
//
// Insert ISR Code here.......
// for now just insert a delay
//
//for(i = 1; i <= 10; i++) {}
//
// Restore registers saved:
//
DINT;
PieCtrlRegs.PIEIER1.all = TempPIEIER;
}
Our next-generation C29x architecture F29H85x supports Hardware Interrupt Prioritization requires no software overhead and allows interrupt nesting. For C29x architecture all registers are save/restored automatically by hardware on real-time interrupt in 10 cycles when compared C28x 40 cycles.
Nesting for INTs within the PIPE module is enabled within an Interrupt Service Routine (ISR) by setting the CPU level DSTS.INTE bit active because this bit is disabled while entering the ISR., as described in Figure 7. Here are the steps C28x performs interrupt nesting:
// // C29x ISR Code // // Enable nested interrupts // // ADCA1 interrupt for loop Interrput
void INT_myCPUTIMER0_ISR(void)
{
// Set INTE to 1 to enable interrupts here.
ENINT;
// Insert ISR Code here.......
}
The below test results are with two interrupts: EPWM interrupt at 150kHz (yellow signal) and Timer2 interrupt at 1kHz (blue signal). Timer2 interrupt has lower priority than the EPWM interrupt. Without C28x interrupt nesting enabled, the interrupt frequency of the EPWM is not be 150kHz, as shown in Figure 8. Keeping EPWM interrupt fixed at 150Khz is only possible by leveraging C28x CPU interrupt nesting, as shown in Figure 9. The test results are based on LAUNCHXL-F280039C. If interrupt nesting is not enabled by software method as described with the above code there is abnormal interrupt behavior.
With interrupt nesting enabled, the higher priority interrupts can still be entered and executed even when a lower priority interrupt has occurred. This makes sure higher priority interrupt frequencies are constant..
The below test results are with two interrupts: EPWM interrupt at 150kHz (pink signal) and Timer2 interrupt at 1kHz (green signal). Timer2 interrupt has lower priority than the EPWM interrupt. Without C29x interrupt nesting enabled, the interrupt frequency of the EPWM is not be 150kHz, as shown in Figure 10. Keeping EPWM interrupt fixed at 150Khz is only possible by leveraging C29x CPU interrupt nesting, as shown in Figure 11. This is tested based on the F29x devices. If interrupt nesting is not enabled by software method as described the above code there is abnormal interrupt behavior.
With interrupt nesting enabled, the higher priority interrupts can still be entered and executed even when a lower priority interrupt has occurred. This makes sure higher priority interrupt frequencies are constant.
When talking about uninterruptible instructions RPT, a large number of repeated global initialization variables are used in the main program or state machine such as Memcopy, for loop assigns the same array, or repeated operations are performed, the C2000 compiler automatically generates RPT instructions. The repeat (RPT) instruction allows the execution of a single instruction (N + 1) times, where N is specified as an operand of the RPT instruction. The instruction is executed once and then repeated N times. When RPT is executed, the repeat counter (RPTC) is loaded with N. RPTC is then decremented every time the repeated instruction is executed, until RPTC equals 0. For a description of RPT and a list of repeatable instructions, see the RPT *8bit/loc16 section in the C28x Assembly Language Instructions chapter of the TMS320C28x CPU and Instruction Set Reference Guide.
Due to this RPT instruction being uninterruptible, it does not have the context saving stack protection or restore function. So, the PC pointer stays in RPT at this time and it may not be able to respond to the interrupt request in time, as described in Figure 12.
Therefore, you can go into the C2000 compilers using the correct settings or you can avoid generated C usage notes. Regarding the C2000 compilers, you can change the Project Properties -> C2000 Compiler -> Advanced Options -> Runtime Model Options -> Enable “Don’t generate RPT instructions, as described in Figure 13.
Finally, follow the above C2000 compilers settings and the EPWM ISR works normally, as described in Figure 16.
The interrupt is executed normally by observing the minimum interrupt delay. However, the factors that affect the normal execution of the interrupt are:
This technical article tells you how to locate and troubleshoot the factors affecting the interrupts.
All trademarks are the property of their respective owners.