I'm working with a Cortex M4 (Freescale's Freedom-K64F dev-board). I'm trying to write a long sequence of data to flash. The state machine for this sequence operates in the interrupt handler. This means that in the handler for the processor's flash-controller interrupt, I launch further flash controller operations. The last of my sequence of data operations is short, and is likely to finish very quickly. Launching a successive flash operation from a IRQ handler means that it is possible (in some cases such as the last operation) for the `successive` operation to complete before the IRQ-handler which launched it; and in fact I do see this happening. The problem is that such a sequence where a an active interrupt is made active_and_pending from an internal peripheral seems to not be working reliably for me. I find that the `active and pending state` does not restart the interrupt handler automatically upon return from the handler.
My application fails to field a successive interrupt when a `successive` operation launched from an active interrupt handler completes early. The only way I have been able to reason about it is by arguing that returning from an interrupt clears the pending flag and therefore causes my application to miss pending IRQ-handling.
To support my hypothesis further, I've re-written my IRQ handler in the following fashion:
void IRQ_Handler(void)
{
do {
handleCompletedOperationsAndProgressStateMachine();
} while (NVIC_GetPendingIRQ(...) != 0);
}
This does help, but there is still a small window between while (NVIC_GetPendingIRQ(...) != 0); and the actual return of the IRQ where the interrupt could be set as pending again and be lost.
Is it a processor-implementation thing that the pending status of an interrupt is cleared upon interrupt return?
My question relates to the 'active_and_pending' state as described in ARM Information Center
From the completion IRQ handler of a flash data-transfer operation, let’s call it the ‘base invocation’, I launch a successive flash operation to operate asynchronously. This successive transaction is short enough to get completed before the return of the base invocation, and raises the interrupt-pending flag for the completion interrupt. Unfortunately, the completion IRQ handler does *not* get re-triggered following the return from the base invocation. This can only be explained if the pending flag gets cleared by the interrupt-return sequence of the base invocation, or if the processor implementation doesn’t handle the ‘active_and_pending’ state correctly.
yasuhikokoumoto San : I'm not expecting to receive N (where N > 1) successive interrupts in response to N interrupt pulses received during the lifetime of my base invocation. I'd like to receive *one* successive interrupt if a currently active interrupt is marked as pending by asynchronous activity during its lifetime.
This is beginning to look like a faulty implementation on the part of my particular processor (K64F). What I see can only be explained if the 'pending' flag of the flash interrupt somehow gets cleared automatically upon return from its handler. I know that the pending flag gets cleared upon exception entry; but it seems it is also getting cleared upon exception return.
Hi,
I understand what you say.
However, the 'active_and_pending' state is not one which is implemented.
It is the state in which will be falling by chance.
There would not always be such the state.
I think you had better check your software other than processor hardware.
Best regards,
Yasuhiko Koumoto.
It is almost as if the flash controller though the interrupt was edge triggered but the interrupt controller though it was level sensitive and managed to interrupt the controller always when it wasn't actually handling the interrupt. The other option I can see is that there is some software lurking in the interrupt handler which does a software acknowledge of the interrupt. Neither seems very likely so I'm a bit stumped. It would be interesting to put a delay between the handleCompletedOperationsAndProgressStateMachine() and the while (NVIC_GetPendingIRQ(...) != 0) to see if the next interrupt disappears in between. This would tell you it has nothing to do with the return and the interrupt is level triggered. And it would still leave me wondering why the level is dropped.
The fault lay in my software. I had set PRIMASK by accident during the state machine.
Sorry I hadn't noticed your reply, and thanks. That certainly explains things and shows there's always some other good explanation.
I am glad you solved the problem.