Similar to post viewtopic.php?f=24&t=3943 I've encountered a "priority order violation".
This happens when multiple threads use one of the chEvtWaitxxxTimeout(...) set of functions and the chEvtGetAndClearEvents() function.
The problem was exposed when some monitoring was added to the main thread to check for events being broadcast by other threads.
In this case the other thread is a decoder taking PWM data and decoding it as audio FSK.
I can cure the issue by adding a chSchRescheduleS() prior to the ChSysUnlock() in the locked code section that throws the priority order violation.
This locked section is called just after an event posted from another thread (not main) is detected in the PWM decoder thread by the chEvtGetAndClearEvents() function.
Unfortunately the project is somewhat complex with multiple threads and event signalling.
The following code is the event processing and the function that throws the "priority order violation"...
A thread running a decoder of PWM data...
Code: Select all
case DECODER_IDLE: {
/*
* Check for stop event.
*/
eventmask_t evt = chEvtGetAndClearEvents(DEC_COMMAND_STOP);
if(evt) {
pktDisablePWM(myDriver);
myDriver->decoder_state = DECODER_WAIT;
pktAddEventFlags(myDriver, DEC_STOP_EXEC);
break;
}
myDriver->decoder_state = DECODER_POLL;
break;
} /* End case DECODER_IDLE. */
The function it calls when the decoder finds an event requesting it to stop (pause really).
Code: Select all
/**
* @brief Disables PWM stream from radio.
* @post The ICU capture is stopped.
* @post The port for CCA input is disabled.
* @post The PWM buffer reference is removed.
* @post The ICU remains ready to be restarted.
*
* @param[in] myDriver pointer to a @p AFSKDemodDriver structure
* @api
*/
void pktDisablePWM(AFSKDemodDriver *myDriver) {
chDbgAssert(myDriver->icudriver != NULL, "no ICU driver");
chSysLock();
/* Close the PWM stream. */
pktClosePWMChannelI(myDriver->icudriver, 0, PWM_TERM_DECODE_STOP);
/* Stop ICU capture. */
icuStopCaptureI(myDriver->icudriver);
/* Stop any timeouts in ICU handling. */
pktStopAllICUTimersS(myDriver->icudriver);
/* Disable CCA port event. */
palDisableLineEventI(LINE_CCA);
myDriver->icustate = PKT_PWM_STOP;
/*
* FIXME: This reschedule is required to avoid a "priority order violation".
*/
chSchRescheduleS();
chSysUnlock();
}
All the interrupt levels in the mcuconf.h are at standard ChibiOS settings.
Any thoughts?
Thanks,
Bob