I'm using K60 and MQX 4.1.something.
I have a HWTIMER firing every 2.5ms and also a Processor Expert SPI slave device which is receiving data from elsewhere.
With some random regularity, the HWTIMER fires during a SPI transaction, and the SPI slave loses a byte, thus screwing up the sync between SPI master and slave.
The PE SPI slave routine fires an interrupt with every byte that comes in, and after th expected number of bytes calls a callback which posts an MQX semaphore. The interrupt must be an MQX-handled interrupt for the semaphore to work. Except sometimes when the HWTIMER is in the user-provided callback, which is already in the interrupt frame, it prevents the SPI handler from executing. So the SPI slave peripheral, not having been updated by the ISR, places the previous byte in the shift register and the SPI master therefore reads double of a given byte. In my particular case the SPI transaction is about 140 bytes, so the actual byte that is screwed up is kind of random within that sequence. The SPI slave afterwards doesn't realize that all 140 bytes have been sent (it thinks there are only 139 bytes sent), so things get screwed up from there.
I've tried everything, from _int_disable() in the timer callback, to EnterCritical() in the SPI ISR, to trying to use kernel interrupts for SPI which set a flag which is picked up by another task which posts the semaphore, etc. it's taken me a long time to track it down to this one issue. The one thing that seems to work is to disable the HWTIMER when the SPI slave expects a transaction (there is a GPIO line which is asserted telling the SPI master to come read stuff out). But it means that in heavy SPI traffic, or if the SPI master is slow to respond to the GPIO, the HWTIMER is disabled much more than I'd like.
Is there any way to tweak the interrupt priorities of HWTIMER so it never clobbers the PE SPI slave ISR, but still can fire, say, while a SPI byte is transferring, but not during the actual ISR for said SPI byte?
Ie I need a way to mask out HWTIMER interrupt during SPI slave interrupt. I could not do it with _int_disable(0 or EnterCritical().