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.

Missing UART Interrupt SYSBIOS on AM1806

Other Parts Discussed in Thread: AM1806

I am using SYS/BIOS version 6.32.05.54 with AM1806 and seem to be having a problem with Hwi_disableInterrupt() and Hwi_restoreInterrupt() functions.

If I run the following sequence of code:

SetUpUart1Interrupts();
hwiState = Hwi_disableInterrupt(UART1);
  Now Send Characters to UART from an external device
Hwi_restoreInterrupt(UART1,hwiState);

I would expect that after executing the Hwi_restoreInterrupt() call I would imediately get a interrupt to the ISR since the UART received some characters while the interrupt was disabled. But the interrupt never happens and the following lines of code are performed. In fact the UART Interrupt is ignored from then on.

When this happens I can see that the PEND interrupt bit is clear in UART1's IIR register (indicating a pending Interrupt for the UART) also the UART's LSR has the DR bit set. In checking ESR2 I can see that UART1 interrupt is enabled. Checking HIPIR2 it indicates that the UART1 interrupt is the highest pending interrupt. GLobal Interrupts are enabled and from all AINTC registers it looks like the UART1 interrupt should be active but the ISR is not called. For this test  the UART1 interrupt is the only interrupt assigned to the channel 16 (Channels 2-15 are not used) so it should be the highest interrupt priority.

If I do not usew the Hwi_disableInterrupt() and Hwi_restoreInterrupt() functions the ISR works like it should.  The ISR routine I'm using has been used on many other 16550 style UARTS without problems.

Is there an issue with SYS/BIOS and UART interrupts on the AM1806.

  • Hi Thomas,

    can you check what the value of UART1 to be the correct interrupt vector?

    I looked that the code contents of those two functions and I don't see anything that would prevent it from being enabled again. Does hwiState have a non-zero value?

    /*
     *  ======== Hwi_disableInterrupt ========
     */
    UInt Hwi_disableInterrupt(UInt intNum)
    {
        UInt oldEnableState, index;
    
        index = intNum >> 5;
    
        oldEnableState = Hwi_cpIntc.ESR[index] & (1 << (intNum & 0x1f));
    
        Hwi_cpIntc.EICR = intNum; /* clear the enable for this int */
    
        return oldEnableState;
    }
    
    /*
     *  ======== Hwi_RestoreInterrupt ========
     */
    Void Hwi_restoreInterrupt(UInt intNum, UInt key)
    {
        if (key) {
            Hwi_cpIntc.EISR = intNum; /* set the enable for this int */
        }
        else {
            Hwi_cpIntc.EICR = intNum; /* clear the enable for this int */
        }
    }

    Just as a test, could you try using Hwi_disable() and Hwi_restore()? These two functions should just touch the global interrupt enable bit.

  • Tom,

    The hwiState value returned from Hwi_disableInterrupt() is non zero. The vector in the AM1806 HIPVR2 register is correct (it's 0xFFFF01E8 - this location has a pointer to the ISR) for the UART. Also the VBA is correct. Fromn looking at the registers it looks like the interrutp to the UART ISR is pending but there are no other interrupts running.

    If I place a break point just befor the Hwi restore then single step, I get the vector to the ISR. I can then single step through the ISR and get all the characters on the FIFO. But if I let the program run at full speed after this break point to a few lines below this code, I only get a few characters from the FIFO and I'm left with a pending interrupt on the UART. This pending UART isinterrupt is never serviced. The UART interrupt is the highest interrupt priority so it should always run as long a global interrupts are enabled, which they are.

    Interesting note, when I used Hwi_disable() and Hwi_restore() for the two previous Hwi functions the code works correctly, but I also noticed that interrupts are not disabled. Prior to the call Hwi_disable() the Global Interrupt in GER register is set and after the call to Hwi_disable() the global interrupt enable is still set. Also the Hwi_disable() returns a non 0 value.

     

     

     

  • Thomas,

    can you post your .cfg file?

    Thomas Mitchell said:
    Interesting note, when I used Hwi_disable() and Hwi_restore() for the two previous Hwi functions the code works correctly, but I also noticed that interrupts are not disabled. Prior to the call Hwi_disable() the Global Interrupt in GER register is set and after the call to Hwi_disable() the global interrupt enable is still set.

    A Hwi_disable/Hwi_restore will set/clear the "Disable IRQ" bit in the CPSR (program status register); not the GER.

    Thomas Mitchell said:
    If I place a break point just befor the Hwi restore then single step, I get the vector to the ISR. I can then single step through the ISR and get all the characters on the FIFO. But if I let the program run at full speed after this break point to a few lines below this code, I only get a few characters from the FIFO and I'm left with a pending interrupt on the UART. This pending UART isinterrupt is never serviced. The UART interrupt is the highest interrupt priority so it should always run as long a global interrupts are enabled, which they are.

    Hwi_restore() or Hwi_restoreInterrupt()? If I understand you correctly, the fact that your application does jump to the ISR (at least when you use breakpoints) which in my mind means that right interrupts bits are set. Could your ISR being optimized by any chance? Could it be possible the interrupt wasn't enabled before Hwi_disableInterrupt? Perhaps you want to use Hwi_disableInterrupt() / Hwi_enableInterrupt().

  • I have resolved this issue. In an effort to help others I will list my findings.

    The interrupts on the AM1806 appear to be edge triggered not level triggered. If a second interrupt from the UART occurs while  you are in the ISR for the UART that second interrupt will be missed and when the ISR completes the UART will have a pending interrupt but the AM1806 interrupt controller will not respond. This condition can still happen even if check for a pending interrupt while in the ISR since the time between clearing the interrupt and exiting the ISR leaves a small window where a second interrupt can occur.

    To prevent this you need to have the ISR have the highest priority possible then in the ISR the only function should be a Swi_post(). This will insure that the ISR can be completed before the first pending interrupt is serviced and a second interrupt is generated. When the SWI is run it should read the IIR and LSR to determine the cause of the interrupt and process all pending interrupts. While in the SWI if a new interrupt is generated by the UART it will force the ISR to run which will then do a second Swi_post().

    With this method resolves the missing UART interrupt problem.