AnsweredAssumed Answered

How to determine which task triggered watchdog timeout?

Question asked by Sean MacKay on Oct 14, 2015
Latest reply on Dec 2, 2015 by Sean MacKay

Hello, I'm using MQX 4.2 and CodeWarrior 10.6.4 with a Freescale FRDM K64F development board.

 

I recently implemented watchdog timers in several of my tasks in my firmware, but am running into an issue determining which task caused the timer to expire.

 

I based my implementation on a combination of this example (MQX Watchdogs for Multiple Tasks ) and the MQX watchdog example application. However, it seems that even David E Seymour might be uncertain which method is best for determining the task which caused the timer expiry.

 

printf("\nWatchdog expired for task: 0x%P", td_ptr);
printf("\nTask Index = %x", ((_mqx_uint *)td_ptr)[3]); //DES added increment td_ptr address to point to TASK_ID
printf("\nTask Index = %x", _task_get_id()); //DES added

 

I settled with the _task_get_id() method, but it seems to fail in certain situations. For instance, if a task somehow delays or blocks and then the watchdog timer expires, that expiry gets attributed to the MQX_Idle_task. I've also had the timer expire during a socket operation and get attributed to the TCP/IP task. This doesn't work well with my watchdog implementation which does the following:

1) reads the task_id of the expired task.
2) sets a variable to that task ID so it can be reset by the main task.
3) log the error.

 

 

void handle_watchdog_expiry(void   *td_ptr)
{
uint32_t error_data[2];
printf("\nTask Index = %x", _task_get_id()); //DES added

Watchdog_resets++;

if (watchdog_resets > 5 || _task_get_id() == 0x10003 ) //check if main task, as that will lock all
{
SCB_AIRCR = SCB_AIRCR_VECTKEY(0x5FA) | SCB_AIRCR_SYSRESETREQ_MASK; 
}
else
{
expired_task = _task_get_id();
error_data[0] = _task_get_id();
error_data[1] = ETC_WATCHDOG_RESET_TASK;
_lwmsgq_send(error_log, error_data, 0);
}
}

 

Which causes the main task to reset the expired task (or resets the full system if the main task is the one to fail the watchdog timer)

if (expired_task != MQX_NULL_TASK_ID)
  {
  _task_restart(expired_task, NULL, FALSE);
  expired_task = MQX_NULL_TASK_ID;
  }
  _time_delay(150);

 

 

The problem is, when the task is read as the idle task, or the TCP/IP task, the main task can't restart it properly, nor restart the actual problem task.

 

So my question is this:

Is there a better way to determine which task's watchdog timer expired in a generic watchdog handling ISR?

Or should I change it so each task has a task specific ISR which is set as each task sets up the watchdog timer, bypassing any reading of the current task.

 

Sean

Outcomes