This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Higher Priority on UART1

How can I increase the interrupt priority of UART1 of the LPC2364?
Due to heavy load on timer interrupts, I'm missing receiving characters every 5 - 10 seconds.

The initialization of UART1 is as follow:

void enableUART1(void)
{
  VICVectAddr7  = (unsigned long) UART1_IRQHandler; // Set Interrupt Vector
  VICVectCntl7  = 17; //15;                         // use it for UART1 Interrupt
  VICIntEnable |= (1<<7);                           // Enable UART1 Interrupt
}

      // Enable RS485  P2.7 Initialisiert auf Out high
      PINSEL4 = PINSEL4|P2_00TXD1|P2_01RXD1;
      U1LCR   = bits|parity|stops|_DLABON;
      U1DLL   = (U8)baud;
      U1DLM   = (U8)(baud>>8);
      U1LCR   = bits|parity|stops|_DLABOFF;
      uart[_UART1].openChar1 =uart[_UART1].openChar2 =uart[_UART1].openChar3 =uart[_UART1].openChar4 =0;
      uart[_UART1].closeChar1=uart[_UART1].closeChar2=uart[_UART1].closeChar3=uart[_UART1].closeChar4=0;
      uart[_UART1].closeTimeout=timeout;
      flushBufferUART1( );
      U1IER   =(1<<0);        // Enable Rx Interrupt
      uart[_UART1].initialized=1;

Many thanks for any input.
Peter

  • adjusting interrupt priority levels for an STR7 is done like this:

    via ST library:

    EIC_IRQChannelPriorityConfig(T3TIMI_IRQChannel, 1);
    

    or directly:

    EIC->SIR[IRQChannel] = (EIC->SIR[IRQChannel]&0xFFFF0000) | (u16)Priority & 0x000F;
    

  • VIC (Vectored Interrupt Controller) in LPC23xx has registers VICVectPriorityX (x=0..31) which set the Interrupt Priority for each IRQ from 0 (highest) to 15 (lowest). After reset all priorities are set to 15.

    You need to set the priority for UART1 which will be in your case VICVectPriority7 = 0 (highest priority).

    Please check the NXP user manual for more details.

  • How can I increase the interrupt priority of UART1 of the LPC2364?

    Are you sure that this will solve your problem ? Instead of missing UART events, your system might start missing (or reacting too late to) timer events.

    Have you looked into other ways to solve the problem ? According to the datasheet, the UART on your device has 16 byte transmit and receive FIFOs. If you use them, and your timer interrupts still need more time than the UART needs to receive 16 bytes (for usual baudrates, that's a small eternity for a uC), then are you sure you followed the KISS (Keep ISRs short and simple) strategy for your timer ISRs ?

    And if the FIFO is not large enough, there is still the possibility of using DMA to handle the UART transfers, which will basically give you a buffer size equal to any RAM you can spare.

  • Hi Frank
    That's what I'm thinking about now.
    But, I don't understand this with the FIFO exactly:
    If I set

    U1FCR = 0x01;
    


    then FIFO is enabled and will interrupt on every character.
    But if I set

    U1FCR = 0xC1;
    


    then it will only interrupt on every 14th character.
    But what happens if I receive a string of only 11 characters?

  • I can only agree. FIFO and correctly implemented ISR (all of them) should allow the processor to take quite a punishment without dropping characters.

    You have a data structure with a lot of start and stop characters and timeout. Are you sure that you don't let your serial port ISR do too much work?

    Are transmit and receive being multiplexed on the same wire, so that you need to implement a bus logic where you very quickly has to change the traceiver from transmit to receive when you detect an end-of-frame?

  • You can get interrupts both when you pass the FIFO trig level (configured in UxFCR) but you can also get a Character Time-out indicator (CTI).

    Chapter 16, paragraph 4.5 in the user manual describes this. You will get a CTI when you have data in the receive FIFO but haven't received any new character in 3.5-4.5 character times. This interrupt allows you to retrieve any remaining character from the RX FIFO.

  • But what happens if I receive a string of only 11 characters?<p>

    If you want to receive every single character, set the UART to raise an interrupt as soon as there is one character in the FIFO. The beauty about the FIFO is that even if the UART has received additional characters by the time the uC starts the ISR, these additional character are not "lost", but stored in the FIFO, and you can read them from there.

  • Many thanks to all of you.
    For the moment, the problem seems to be solved by increasing the priority. Now I will run some tests and look for some sideeffects (timers).
    But I also will think about your inputs, specially at the one about what I'm doing within the UART-interrupt.

    The other thing is setting the trigger to 14 chars and
    look for the CTI.

  • Now I will run some tests and look for some sideeffects (timers).

    Are your tests going to catch that "little once-a-month" glitch ? What about "once a year" ? If it's a high volume product, or a safety-critical product, these little glitches can turn into major headaches.

    But I also will think about your inputs, specially at the one about what I'm doing within the UART-interrupt.

    What you should do first is have a good, close look at your timers ISRs. If they are starving the UART ISR, chances are good that there is way too much work packed in the timer ISRs that can (and should be) done outside the ISR.

    Just out of curiosity, what baudrate are you running the UART at ?

  • Try to measure the min/max/avg time consumed by each individual interrupt.

    Then look at the expected frequency (at burst rate) for the individual interrupts. Check if you have the raw processing power to fulfill your requirements.

    Unless the protocol or connection mode have very strict timing requirements for the serial communication, it may be far worse to increase the UART priority.

    You should - at all times - have enough processing power to be able to service all critical interrupts within the allowed latency and still have a reasonable amount of time left for non-critical interrupts and any main loops. If you don't have nested interrupts (which really complicates your analyses) then you should consider all interrupts as critical, and see what happens if all interrupt sources are trigged almost at the same time, with the longest-running low-priority interrupt arriving just before all others.

    Will you still be able to service all interrupts (potentially multiple high-priority interrupts before the last low-priority interrupt) without failing any interrupt, and without failing your narrowest timing-requirement in any main loop?

    Everything isn't testable but you need to produce some form of confidence intervals for the system, or you need to perform traditional testing at a significantly higher load (higher baudrates with faster/longer bursts of data) etc. than the system will be used for in real life.

    In some situations you can let different parts of the software drive a large number of LED and use a logic analyzer or similar to trace the LED pattern. Just remember that a LED turned on/off in an ISR does not represent the time needed to enter/leave the ISR.

    Anyway - it is very important to have a lot of spare capacity, since "normal" testing seldom manages to come close to worst-time scenarios. Some worst-case scenarios may be hard to even identify, and you can't create a test case for a scenario you can't identify.

  • Per's comments are very correct. What you can do to calculate your timing budget is create a table that contains all the time consuming operations in your system in the form of period, duration, total cost. if you know that your system should do all its work within X[ms] (that is usually the least common multiple of all periods), then you can calculate a worst case scenario and the CPU load. this assumes of course a simple scheduling (non-preemptive).

  • Hi, people,

    I've tried your project and It's works fine...
    Thanks again...

    Regards,
    Marine bOY