Time sensitive UART with only one IRQ

14 Jan 2018

Disclaimer: I'm a beginner in embedded development; this is basically my first embedded project so I probably have some conceptual deficiencies.

For the project I’m working on we have a board with a STM32F030CC processor. Similar to the F091RC it features multiple UARTs - 6 in total. Unfortunately, it only has three IRQs for these 6 UARTs. UART 3 to 6 are all handled through the same interrupt. Two UARTs (3 and 5) will be RS485 Modbus slaves - so they are both time critical. UART 4 and 6 will handle board internal communication, so they are not as critical. What all these ports have in common is, that messages arrive unsolicited. Neither do I know when the Modbus master sends a request nor do I know when commands arrive on UART 4 or 6 (which are simple ascii/textual commands).

To implement support for the F030CC I looked at how the F091RC is currently implemented in mbed. It seems, however, that the way serial_device is implemented for the F091RC is currently wrong. When a callback is attached to a serial, the appropriate IRQ handler is assigned. Since UART3 to 8 on the F091RC share one interrupt, the last call to ::attach wins. To make matters worse: if an interrupt for one of the other UARTs is called now, that one will end up in an interrupt “endless loop”, since the another ISR has been assigned which obviously wont clear the registers of another UART.

Example:

Serial u4(UART4_TX, UART4_RX);
Serial u6(UART6_TX, UART6_RX);

void uart4Rx() {...};
void uart6Rx() {...};

void main() {
  u4.attach(uart4Rx);
  u6.attach(uart6Rx);
}

If some data arrives on UART6, everything will be fine. If something arrives on UART4, it will enter an endless loop, since u6.attach set the IRQ to uart6_irq() (in serial_device.c) which does not know how to handle UART4.

An obvious solution would be to have kind of a meta IRQ handler that will call _all_ relevant IRQs (3, 4, 5, 6, 7 and 8 in case of F091RC and 3, 4, 5 and 6 in my case - F030CC). That will probably impose a performance penalty since each IRQ invocation now has 4 to 6 times as much to do and it needs to be reference counted (otherwise a de-attachment could disable the IRQ that is still needed for other UARTs). I will try that as soon as possible. But for now I want to make sure I am not looking at this problem from the wrong perspective and maybe miss something.

So: what is best practice here? How can I still handle time critical communication via UART if multiple UARTs share the same IRQ? Or ... is this simply the wrong µController for the task at hand?

23 Jan 2018

Hi,

For a better follow-up of this problem can you please enter an Issue on GitHub (https://github.com/ARMmbed/mbed-os/issues) ?

If you have already found a fix, don't hesitate to send a pull-request on GitHub as well so that we can review it.

Thanks.

23 Jan 2018

I have sent a pull-request here: https://github.com/ARMmbed/mbed-os/pull/5907

It would be nice if you can test it and tell us if it is ok or not in your application.

Thanks.