2024-11-20 09:28 AM
Hi All
I have a problem with a ThreadX-based project on a Nucleo H563ZI board when using a mutex.
The mutex locks access to an FDCAN peripheral, and a message-buffer data structure during CAN-FD message transmission. The problem only shows up when I load-test the system by running a tight loop on a thread attempting to send messages continuously; there is a separate thread will will send heartbeat messages at a much lower rate.
After a seemingly random amount of time (typically of the order of 10 seconds, equating to usually 50,000-100,000 mutex accesses) the code hard-faults in tx_mutex_put.c, at line 386, snippet below. The fault is at the check for `(mutex_ptr -> tx_mutex_owner) -> tx_thread_priority;` at this point mutex_ptr->tx_mutex_owner is null, hence the crash.
I can workaround it by putting a check for (mutex_ptr->tx_mutex_owner != TX_NULL) around the if block, but I don't feel comfortable with this, it feels like covering up the symptom rather than addressing the cause.
I have checked all tx_mutex_get calls return TX_SUCCESS. I have tried toggling the TX_NOT_INTERRUPTABLE flag in tx_user.h. I have tried wrapping the mutex calls in C++ classes to allow use of a lock-guard (to be sure there are no mismatches in gets and puts) - nothing makes any difference except the fix in tx_mutex_put.c
There are two callback interrupts from the FDCAN peripherals, but the only ThreadX operations they perform is setting a semaphore. As suggested at https://stackoverflow.com/questions/72200459/tx-semaphore-inside-a-interrupt I tried adding _tx_thread_context_save/restore into the interrupts, but this made no difference either (probably to be expected based on https://community.st.com/t5/stm32-mcus-embedded-software/requirement-to-call-tx-thread-context-save-restore-for-various/td-p/718770 )
Could anyone give me any pointers on where to look next?
Any advice appreciated!
Nic
Snippet from tx_mutex_put:
/* Mutex is not owned, but it is possible that a thread that
caused a priority inheritance to occur is no longer waiting
on the mutex. */
/* Setup the highest priority waiting thread. */
mutex_ptr -> tx_mutex_highest_priority_waiting = (UINT) TX_MAX_PRIORITIES;
/* Determine if we need to restore priority. */
if ((mutex_ptr -> tx_mutex_owner) -> tx_thread_priority != old_priority)
{
/* Yes, restore the priority of thread. */
_tx_mutex_priority_change(mutex_ptr -> tx_mutex_owner, old_priority);
}