I'm trying to utilize the MPU on the OMAP L138. I'm having trouble figuring out how to write an interrupt handler for it.
As I understand it, the OMAP-L138 has two MPUs that service different memory regions (internal L3 and external DDR). Each MPU can produce two interrupts - one for an address violation error (ADDRERR) and one for a protection violation error (PROTERR). Those four interrupts are then fed into the SYSCFG module in the OMAP where they are multiplexed and presented to the ARM Interrupt Controller (AINTC) as a single system interrupt called PROTERR (event #27). I assume the multiplexed system interrupt called PROTERR indicates ADDRERR events from the MPUs and not just PROTERR events from the MPUs, even though the nomenclature tends to suggest otherwise.
The description of the MPU in the L138 User Guide (SPRUGM7D) says that BOOTCFG_ADDR_ERR and BOOTCFG_PROT_ERR also get multiplexed into that single system interrupt, but I can’t figure that out since the User Guide doesn’t mention anything about these BOOTCFG errors anywhere else.
Each of the MPUs have registers for interrupt enabling (IENSET) and interrupt status (IENSTAT) and registers for fault address (FLTADDRR), fault status (FLTSTAT) and fault clearing (FLTCLR).
The SYSCFG module also has registers regarding the MPUs. It has an IENSET and an IENSTAT just like each of the MPUs. And it has a FLTADDRR and FLTSTAT just like each of the MPUs. It does not have a FLTCLR like the MPUs, but it does have an End of Interrupt Register (EOI).
So, when the ARM receives that one single interrupt from the SYSCFG module (via the AINTC), what the heck is it supposed to do to make sure that both MPUs, the SYSCFG and AINTC modules all get serviced properly? Does the SYSCFG module “latch” the first set of data provided by the MPUs? At what point in the ISR should FLTCLR registers in the MPUs be written to and the EOI register in the SYSCFG module?
I’m thinking the ISR on the ARM should be something along the lines of the following:
While (interrupts pending in the AINTC – check bit 31 in HIPIRx of the AINTC) { Get highest priority interrupt from HIPIRx in the AINTC. When it’s the PROTERR from the SYSCFG Module, service the SYSCFG module as follows: While (interrupts pending in the SYSCFG – check bits 0 and 1 of IENSTAT in SYSCFG) { If (ADDRERR in MPU1 – check bit 1 in IENSTAT of MPU1) { Read FLTADDRR and FLTSTAT from MPU1 and do something useful with it. Clear the FLTADDRR and FLTSTAT registers in MPU1 by writing a 1 to bit 0 of FLTCLR in MPU1. Clear the ADDRERR interrupt in MPU1 by writing a 1 to bit 1 of IENSTAT in MPU1? (The User Guide just says software can write to IENSTAT to clear an interrupt. I’m assuming it means writing a 1 to the bit will clear it. Table 6-12 actually says that Writing a 1 sets the status. Maybe that should say Writing a 1 clears the status?) Clear the ADDRERR interrupt in SYSCFG by writing a 1 to bit 1 of IENSTAT in SYSCFG? Is there any reason to read FLTADDRR and FLTSTAT from SYSCFG at this point? } Else If (PROTERR in MPU1 – check bit 0 in IENSTAT of MPU1) { Do the same as above, but for PROTERR instead of ADDRERR in MPU1 } Else If (ADDRERR in MPU2 – check bit 1 in IENSTAT of MPU2) { And so on… } Else If (PROTERR in MPU2 – check bit 0 of IENSTAT of MPU2) { And so on. } Clear the SYSCFG PROTERR interrupt by writing a 0 to bit 0 of EOI in SYSCFG. (The User Guide contradicts itself here. The description in 11.5.7.5 says to write a 0 to bit 0. But Figure 11-12 and Table 11-16 in that same section indicate that some EOI vector should be written to bits 0:8 of EOI. Since there’s no other mention of this EOI vector anywhere else in the user guide, I assume this is incorrect.) } Clear the PROTERR in the AINTC by writing to SICR in the AINTC. } |
It seems like the marriage of the two MPUs to the SYSCFG module is pretty awkward and not well documented (in the User Guide anyway). So, I’m totally guessing at the required sequence of events for this ISR. Does anyone have any insight?
Thanks,
Arthur