Hosed UART

I am using a program with 3 interrupt sources. UART, P1INT and Timer1. There seems to be a race condition between P1INT and UART1. So after getting multiple interrupts the UART1 stops responding and i need to reset it (run the SerialUart1Init again) i have given max priority to the P1INT. I have not modified the UART1 code at all, using the wixel SDK. Any known issues or ideas on why would this happen ? THe symptom is basically that any bytes that i sent to the UART don’t get transmitted. The rest of the program continues to run without an issue.

Hello. It’s pretty hard to debug this without seeing a simplified version of your code, along with instructions for how to reproduce the undesirable behavior. I reviewed the Wixel’s UART library source code and the only thing I noticed is that we have lines that disable and enable the TX interrupt by setting the UTXxIE bit in IEN2. I believe these lines should compile to single instructions, but maybe somehow that still causes a problem. The IEN2 register also contains P1IE, which you are probably using.

–David

i will post the interrupt routine code. when i get home tonight, But basically the scenario is the following:

  1. P1_6 is used as an input to monitor a square wave which is the output of a speed sensor. I use Timer1 to calculate the period of that signal, so i can calculate the speed of a motor and also the position by counting the number of pulses. The interrupt fires on rising edge and the P1INT ISR code only increments the value of a variable there and nothing else.

  2. On the meantime there is a serial stream of data being received at 9600bps and another stream being sent at 9600bps as well. This is using UART1.

  3. I use IEN2 and IP0,IP1 to give the highest priority possible to P1INT, so i don’t miss any pulses coming through P1INT.

Reproduction scenario:

  1. Run the system with both the serial stream and the signal that triggers the P1INT (which is a square wave with a minimum period of 83ms. The UART will hang after 2/3 minutes, not always in the exact same time, that’s why i think it is some sort of race condition, as the square wave signal that triggers P1 has variable period that is unpredictable

  2. If i dont trigger P1INT (by disconnecting the square wave source) the UART never hangs

Now that you mention that the UART disables interrupts, it makes sense now of why i am seeing missing pulses on my counter. Now, can this be the source of the problem? is there any drawback of modifying the UART code and never disable interrupts ?

Here is the ISR code:

ISR(P1INT, 0)  // interrupt to capture the counter pulse (CP)
{
    P1IFG  &= ~0x08;      //  Clear interrupt plag of P1_3 (P1F3)
                          
    IRCON2 &= ~0x08;      //  Clear CPU interrupt flag
    
    if (UP_DOWN_PIN)      //  Read direction, and increment or decrement the total pulse count
        pulseCounter++;
    else
        pulseCounter--;
   
    tachoPulseTime=readTimer1Counter();   // Read value of timer used to calulate the pulse period
    T1CNTL = 0;           // Reset the counter to zero, so a new period measurement can take place
    timer1OvrFlow=0;
    newTachoReadAvailable=1;     // Flag used to signal that the interrupt has been attended, meaning fresh data is available
}

ISR(T3,0)  // interrupt used as serial command watchdog
{
    TIMIF &= ~0b00000111;      //   T3OVFIF Clear T3 overflow interrupt flag - bit 0 (clearing all interrupts)
    auxCounter++;              // variable used to expand the timer resolution, will count number of times that there is an overflow
    if(auxCounter==WATCHDOG_TIMEOUT)
    {
        watchDogExpired=1;      // set timer watchdog flag - will need to be cleared by the consumer
        auxCounter=0;
    }
}

P1INT i am giving interrupt priority 1. UART1 is priority 3. any ideas on why the UART gets stuck randomly ? only happens when both interrupts are enabled. WIth P1INT disabled or without the source triggering it, the UART works fine

The UART code only disables one interrupt. You could change it, but then I think you will need to have your main loop handle the transfer of bytes from the TX buffer to the UART, instead of having the interrupt do it.

I looked at the code you provided and do not have any ideas of what might be going wrong.

–David

any ideas on how to modify the uart library to make it non-interrupt driven ? i can use it in my main loop.

First you would need to understand what the code in the TX interrupt is doing, and then make a function in the main loop that serves the same purpose. However, I am not convinced that any of this will help because we still do not know why you are getting the unexpected behavior. --David

i have instrumented the code to follow the behavior and the uartTxSend is called with the proper arguments, but nothing comes out. Something is hosing it, and it only happens when the two interrupts are enabled simultaneously. I will try increaseing the interrupt priority of the uart to see if that makes a difference

I resolved this in two ways:

Re-wrote the uart libraries using the DMA. during that i found that the problem was interrupt priority, the serial interrupts were lower priority as they are set on the uartN library overriding my interrupt priority settings that were set before calling the UART init settings. WIth that fixed i dont see the problem anymore. THe issue is well documented on the SDCC manual. Basically what was happening was that the uart ISRs were interrupted by another ISR, given the atomic access issues with SDCC, the UART ISR got hosed even after returning. Longer term it will be safer to do the UART libraries with DMA instead to avoid this risk/issue.

Hello.

I am glad you were able to figure it out. There are some weird pitfalls with using interrupts in SDCC. Section 3.9.2 says:

SDCC’s treatment of bank 0 sounds like it is exactly what we want in order to be safe. Each interrupt should save the registers it uses to the stack and restore them afterwards. This is why we use bank 0 for all the interrupts in the Wixel SDK. If all the interrupts in your system use bank 0, there should not be a problem with registers getting clobbered. If you have two interrupts using the same non-zero bank and they have different priority levels, that could cause interrupts to step on eachother.

There are also unavoidable atomic access issues, but that should only cause a problem if two interrupts are trying to access the same variable or special function register. Was that happening in your system?

–David

hi, i am using, same bank 0 on all interrupts, but with different priorities.

When P1INT or USBINT interrupts the UART ISRs, the UART never recovers and has to be reset.

About the atomic access, by looking at SDCC documentation, it maybe easier to hit and not recover.

hit this problem again. There definitely an issue with interrupts and the SDK UART libraries. If you use both UARTs at the same time, the one with the lowest interrupt priority will stop working and has to be reset. I have the two UARTs running simultaneously sending and receiving a stream of data (@9600 bps).

I will now move on and rewrite them using DMA as i need to use both for my application.