9

Using two USARTs running at 115200 baud on a STM32F2, one to communicate with a radio module and one for serial from a PC. The clock speed is 120MHz.

When receiving data from both USARTs simultaneously overrun errors can occur on one USART or the other. Doing some quick back of the envelope calculations there should be enough time to process both, as the interrupts are just simple copy the byte to a circular buffer.

In both theory and from measurement the interrupt code to push byte to buffer should/does run in the order of 2-4µS, at 115200 baud we have around 70us to process each char.

Why are we seeing occassional OREs on one or other USART?

Update - additional information:

  1. No other ISRs in our code are firing at this time.
  2. We are running Keil RTX with systick interrupt configured to fire every 10mS.
  3. We are not disabling any interrupts at this time.
  4. According this book (The Designer's Guide to the Cortex-M Processor Family) the interupt latency is around 12cycles (not really deadly)

Given all the above 70us is at least a factor of 10 over the time we take to clear the interrupts - so I'm not sure its is so easy to explain. Should I be concluding that there must be some other factor I am over looking?

MDK-ARM is version 4.70

The systick interrupt is used by the RTOS so cannot time this the other ISRs take 2-3µS to run per byte each.

8
  • 1
    You haven't provided enough information for someone to say why you, specifically, are getting overruns. Obvious candidates: Disabling interrupts somewhere else? Higher priority interrupt handler too slow? Bug in your code? Not enough information to figure out which. Commented Apr 15, 2014 at 10:35
  • ISR latency is pretty deadly on that chip, the UARTs don't have a fifo buffer. Your theoretical calculation is already off by a factor of two. Add higher priority interrupts whose ISR take too much time or interrupts getting disabled in code you don't know about and an overrun gets to be easy to explain. Commented Apr 15, 2014 at 12:16
  • Thanks for the comments I've added some more information to the question, I'm not sure what other information I can provide. Commented Apr 15, 2014 at 13:43
  • What version of RTX (or ARM-MDK)? Early versions for Cortex-M3 had bugs and did not fully support interrupt priority grouping. The question is perhaps unanswerable without code. Commented Apr 15, 2014 at 14:38
  • 1
    I am not one to give up on an unexplained problem since symptoms may show up elsewhere later. Still, for my last few projects, I've always gone with DMA to create a circular buffer which stores data received from the USART. Actual hardware (the DMA controller) just doesn't miss deadlines (unless it too is overloaded, but unless you're using it for something else, 2 USARTs at that rate should be a piece of cake). Commented Apr 18, 2014 at 23:52

3 Answers 3

3

I ran into a similar problem as yours a few months ago on a Cortex M4 (SAM4S). I have a function that gets called at 100 Hz based on a Timer Interrupt.

In the meantime I had a UART configured to interrupt on char reception. The expected data over UART was 64 byte long packets and interrupting on every char caused latency such that my 100 Hz update function was running at about 20 Hz. 100 Hz is relatively slow on this particular 120 MHz processor but interrupting on every char was causing massive delays.

I decided to configure the UART to use PDC (Peripheral DMA controller) and my problems disappeared instantly.

DMA allows the UART to store data in memory WITHOUT interrupting the processor until the buffer is full saving lots of overhead.

In my case, I told PDC to store UART data into an buffer (byte array) and specified the length. When UART via PDC filled the buffer the PDC issued an interrupt.

In PDC ISR:

  1. Give PDC new empty buffer
  2. Restart UART PDC (so can collect data while we do other stuff in isr)
  3. memcpy full buffer into RINGBUFFER
  4. Exit ISR

As swineone recommended above, implement DMA and you'll love life.

Sign up to request clarification or add additional context in comments.

Comments

0

Had a similar problem. Short solution - change oversampling to 8 bits which makes USART clock more precise. And choose your MCU clock wisely!

huart1.Init.OverSampling = UART_OVERSAMPLING_8;

Furthermore, add USART error handler and mechanism to check that your data valid such as CRC16. Here is example for the STM32F0xx series, I am assuming it should be pretty similar across the series.

void UART_flush(void) {
  // Flush UART RX buffer if RXNE is set
  if READ_BIT(huart1.Instance->ISR, USART_ISR_RXNE) {
    SET_BIT(huart1.Instance->RQR, UART_RXDATA_FLUSH_REQUEST);
  }

  // Not available on F030xx devices!
  // SET_BIT(huart1.Instance->RQR, UART_TXDATA_FLUSH_REQUEST);

  // Clear All Errors (if needed)
  if (READ_BIT(huart1.Instance->ISR, USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE)) {
    SET_BIT(huart1.Instance->ICR, USART_ICR_ORECF | USART_ICR_FECF | USART_ICR_NCF);
  }
}

// USART Error Handler
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
  if(huart->Instance==USART1) {
    // See if we have any errors
    if (READ_BIT(huart1.Instance->ISR, USART_ISR_ORE | USART_ISR_FE | USART_ISR_NE | USART_ISR_RXNE)) {
        // Flush errors
        UART_flush();

        // Raise Error Handler
        _Error_Handler(__FILE__, __LINE__);
    }
  }
}

DMA might help as well. My problem was related to USART clock tolerances which might even cause overrun error with DMA implemented. Since it is USART hardware problem. Anyway, hope this helps someone out there! Cheers!

Comments

0

I have this problem recently, so I implemented a UART_ErrorCallback function that had was not implanted yet (just the _weak version). Is like this:

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
     if(huart == &huart1)
     {
         HAL_UART_DeInit(&huart1);
         MX_USART1_UART_Init(); //my initialization code
      ...

And this solve the overrun issue.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.