anonymous wrote on Tuesday, July 03, 2012:
Thanks for taking interest in my problem.
I looked over the code to be executed, and it *should* have worked, however I suspect there is a “bug” in the Cortex-M3 port - even though it does not cause a problem if the OS is used “as it should be”. That said, it is still a bug.
The following defines do not behave as they should:
#define portSET_INTERRUPT_MASK_FROM_ISR() 0;portSET_INTERRUPT_MASK()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x) portCLEAR_INTERRUPT_MASK();(void)x
First one always returns 0 as the interrupt mask, second one always clears all interrupts masks, and does not restore the previous state, as it would be logical in the context of xQueueGenericSendFromISR:
signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE *pxHigherPriorityTaskWoken, portBASE_TYPE xCopyPosition )
signed portBASE_TYPE xReturn;
unsigned portBASE_TYPE uxSavedInterruptStatus;
/* Similar to xQueueGenericSend, except we don’t block if there is no room
in the queue. Also we don’t directly wake a task that was blocked on a
queue read, instead we return a flag to say whether a context switch is
required or not (i.e. has a task with a higher priority than us been woken
by this post). */
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
Now suppose I have a few interrupts that also need OS API, but have a low priority.
When one of my functions are meddling with the same peripheral that is used by the ISR, they set mask that interrupt by setting the BASEPRI register (disabling all interrupts below a certain priority). If another interrupt happens at that point that will use queue ISR functions, after returning from the interrupt, my interrupt that should be disabled is not. BANG.
The fix for this problem is quite obvious, but if you like I can create a patch.