I am porting a bare metal application to the Keil MDK-PRO middleware so that we can use USB HOST.
I have nested interrupt handlers in the code, most take less than 25us to run. I have one interrupt handler though that can run as long as 1.5ms and I am hoping this will not disrupt the RTOS.
This long ISR allows higher priority ISR's to nest within it. I realize that this could cause the SYSTICK 1ms interrupt to "skip" a millisecond and I am hoping this will not cause any problems for the RTOS.
Rewriting this ISR would take a lot of work and I have limited time. Moving the code from the ISR to a RTOS Task would slow the response time down a lot (from ~100us at present to over 1ms).
Anyone have experience with running long ISR's and CMSIS-OS?
By the way the code is designed to "catch up" if it fails to run something at the requested time. For example if the 100Hz I/O loop does not run at the 10ms "tick" it will execute twice at the next 10ms tick. The system is deigned to be tolerant like that.
The ISR's, with the exception of the long "generate response for UART" ISR, all run in less than 20us. It is expected that higher priority interrupts will slow down the "generate response for UART" ISR, this is harmless as the bus protocol is designed to "catch up" as well.
The low priority bus traffic can simply be delayed to allow this to happen.
Some UART have a flexible enough FIFO that you can have the FIFO produce an interrupt after the receive stalls after two character cycles.
Another thing is that I would normally process data on-the-fly using a state machine if I need to be able to react with some action within a very short time after the last character of a message is received.
A third thing here is that you claim a very long time for copying the data at the end of the transfer. But the UART receive ISR should be copying the data on every receive interrupt and not do any extra copying when the message frame ends - either use a ring buffer or dual-buffering or whatever so you just make a single update of a counter, flag or pointer to make the full set of data available to the receive task - no additional copying should be involved at that stage unless it's data you need to write to EEPROM or similar.
Another thing - you say the code looks at the header of the received data. But can't the ISR directly understand the header so it knows what to expect?
If I look at NMEA (GPS) data in an ISR, I can have the ISR know that $ is start of a line and \n is end of a line. So the ISR can prepackage individual lines for the processing task. The ISR can even use a state machine so it notices that $GPRMC should be stored in one buffer, $GPGGA in another buffer, ... And it can compute the checksum on-the-fly so when it reaches the line break it already knows if the line has a correct checksum or not.
Most message-based systems either have unique characters for framing, or have a fixed header that contains enough information to know the length of the message. So the ISR should be able to process that information by consuming just a few microseconds and in the end manage the handover of a complete message while consuming just a few microseconds. It would be very strange if there is a need to consume 100us or more at the end of the message just for hand-over.
The goal with realtime systems is seldom to produce the fastest code possible. It's normally more important to see how the processing can be split to minimize the worst-case timing.
In your case, I suggest you take a very, very close look at that data copying, and figure out if you need it at all. Or if you can amortize it.
Thanks for the reply, I appreciate it. I don't have the option of changing the wire protocol which must be backwards compatible with MODBUS.
There is lot more detail which I don't want to bore anyone with, as to how and why the existing software is this way. Suffice it to say the UART has a ring buffer and there is a state engine that examines the packets (which runs in the long ISR). Data copying itself is fast and is only used to move data to and from the UART ring buffer to the application space.
If the software had been designed with an RTOS initially then it would have been designed quite differently. Unfortunately parts of the software go back 15 years and were designed for a much smaller microcontroller using a superloop.
If I cannot use the existing code with CMSIS-OS RTX because of this long ISR then I face a lot more work. Anyway thanks for taking the time to reply.