wz2b wrote on Wednesday, May 30, 2007:
I am looking for some ideas about how to improve interrupt performance, namely by making interrupt service routines much quicker. I wrote a small ISR for the CAN controller’s receive routine:
void can2_rx_irq()
{
portENTER_SWITCHING_ISR();
portBASE_TYPE ret;
ret = xQueueSendFromISR(rxQ2, (CanMsg *) &CAN2_RFS, pdFALSE);
CAN2_CMR.word = 0x04;
portEXIT_SWITCHING_ISR(ret);
}
This generates a whopping 256 instructions. I haven’t gone through and counted cycles but these interrupts could potentially occur at a rate of 128 microseconds, if a burst of packets arrives in both CAN controllers at once.
I could instead create a circular buffer of incoming frames and have an assembly language ISR stuff packets into that buffer in a handful of assembly language instructions. The problem is, that wouldn’t wake up any tasks waiting on incoming messages. Using a semaphore is exactly the same as using a queue, less a little copying (these frames are only 4 words of copying).
Does anybody have a suggested architecture that might work better? One idea I had was to make the ISR be an FIQ that just stores the packet then triggers a software interrupt through the VICSoftInt. The FIQ would stuff the packets, the IRQ would pull them from the first level buffer then do as above. In order to help, ordinary IRQs would have to be interruptible by the FIQ. Normally I try to avoid interrupt nesting at all expense, but in this case I think that this will be a problem because the FIQ handler wouldn’t even need a stack.
It almost seems like what I need is a REALLY lightweight asynchronous event / signal mechanism. Or, if I had some way for my ISR to easily notify the schedule to wake up a certain task next time the scheduler happens to run.
I could fake this through the idle task and a global pretty easily but that sounds like poor design, and there’s no guarantee the idle task will ever get to run. I could make a high level task wake up on a timer and check to see whether or not any new packets have arrived but that’s either going to have high latency or waste a lot of cycles polling the queue.