SNIU028D February 2016 – September 2020 UCD3138 , UCD3138064 , UCD3138064A , UCD3138128 , UCD3138A , UCD3138A64
When the CPU recognizes an interrupt request and responds, the program counter jumps to the appropriate interrupt vector. The interrupt vector is typically a branch statement to an interrupt table. The interrupt table reads the pending interrupt from a vector offset register (FIQIVEC.7:0 for FIQ interrupts and IRQIVEC.7:0 for IRQ interrupts).
The following is an example of how such interrupt service routine needs to be written. In this example two analog comparator interrupts, one DPWM end of period interrupt and two digital fault input pins are all mapped toward the fast interrupt.
#pragma INTERRUPT(fast_interrupt,FIQ)
void fast_interrupt(void)
{
register int32 fiq_number, interrupt_bits;
volatile Uint32 read_scrap;
fiq_number = CimRegs.FIQIVEC.all; // Clear on read
if(fiq_number == 26) // Analog comparator interrupt and more
{
interrupt_bits = FaultMuxRegs.FAULTMUXINTSTAT.all; // Clear on read
if(interrupt_bits & 8) //if Iout1 is high (ACOMP-3)
{
output_over_current_protection();
}
if(interrupt_bits & 4) //if vout1 is high (ACOMP-2)
{
output_over_voltage_protection();
}
}
else if(fiq_number == 27) //DPWM3 interrupt
{
// To do
}
else if(fiq_number == 31) // Fault Pin Interrupt
{
if(interrupt_bits & 0x100) // If FAULT0
{
// To do
}
if(interrupt_bits & 0x200) // If FAULT1
{
// To do
}
}
read_scrap = Dpwm3Regs.DPWMINT.bit.PRD;
}
Since multiple interrupt sources are mapped toward a single ISR (interrupt service routine), the first thing in the ISR should determine which source triggered the entrance to the current execution of ISR.
This can be done first by reading the CimRegs.FIQIVEC register. It is worth noting that the value of CimRegs.FIQIVEC is read just once and saved into the temporary variable fiq_number. The program should follow this format and should not read the CimRegs.FIQIVEC repeatedly in the else if statements.
This is mostly because CimRegs.FIQIVEC is a clear on read register, therefore only the first read attempt per ISR of this register can be used to read intact and relevant values of all relevant bits.
The same is true about FaultMuxRegs.FAULTMUXINTSTAT, this is clear on read register as well. Therefore same technique should be used to read its value.
Please note, the above values used in the elseif() statements within the ISR can be determined by adding a 1 into the interrupt priority level from Table 16-2 (Interrupt Priority Table). In other words, the corresponding values of IRQIVEC and FIQIVEC are equal to (interrupt priority level + 1).
In UCD3138 the interrupt flags need to be cleared by software and are not automatically cleared by hardware.
In some other microcontrollers and microprocessors in the market the interrupt flags are cleared automatically (by hardware) just before the ISR execution ends.
Since UCD3138 does not clear the interrupt flags automatically, this should be done by the ISR routine. Negligence to clear the relevant interrupt flag will cause immediate re-invocation of the ISR instantly after previous ISR execution ended. Therefore the controller (ARM7) will be busy with exaction of the ISR and will never have the chance to execute the background tasks such as PMBus communications in the main() routine.
Once again since multiple interrupt sources are mapped to a single ISR (interrupt service routine), the clearing of the relevant interrupt flag should be added to the related elseif() statement within the ISR.