CTL semaphore timeout issue
First let me say I have been using CTL for the last 3 years in all my projects. All of the designs in question are using LPC23xx. In the last 3 months I caught a weird problem with semaphores. I have a thread waiting for an ISR to signal a semaphore. Sometimes the thread waiting will have a false timeout. If I tell the semaphore to wait for one second I will see one or two false timeouts in that one second interval. I do not believe this problem was present in the version 1 or the early version 2, however I have not tested for this. One other note about the projects, they are quite big. Anywhere from 150K to 400K in size without any optimizing. Some have upto 10 threads runing , 10 or more ISRs, Ethernet DMA active and GPDMA with SDcard. I am working the LPC23XX quite hard.
Little history
In my older code I was using the semaphores as mutex locks, due to version 1 not having mutexes. When I first saw this problem I switched all the semaphores to mutexes and the only semaphores left in the any of my projects are being use to count up things. But in some cases I have some error handlers for when a timeout happens. When they get tripped my code will reset a state machine for the given system. These false trips are causing my code reset things that do not need resets. See example code at bottom of post.
Thanks,
Michael Freeman
Principal Design Engineer
Update Systems, Inc.
Example code:
boolean fnSerial0_Initalize(void)
{
ctl_semaphore_init(&g_srSerial0_ReceiveSemaphore, 0);
……
ctl_set_isr(6, 8, CTL_ISR_TRIGGER_FIXED, fnSerial0_Isr, NULL);
ctl_unmask_isr(6);
……
return true;
}
boolean fnSerial0_WaitForChar(unsigned short usTimeout)
{
if(ctl_semaphore_wait(&g_srSerial0_ReceiveSemaphore, CTL_TIMEOUT_DELAY, usTimeout))
{
return true;
}
return false;
}
void fnSerial0_Isr(void)
{
…
ctl_semaphore_signal(&g_srSerial0_ReceiveSemaphore);
…
}
-
No, timeout and timeout_occured do not have values to my understanding of how thing work, that make any sense.
In file ctl.c: ((long)(t->timeout - ctl_current_time) < 0
The value of timeout is greater than ctl_current_time when the false timeout happens, this code should not go active.
Also the member variable timeout_occurred is set to zero when this false timeout happens. I suspect ctl_semaphore_wait is returning a zero when it should be returning a one.
-
Okay I pinned the tail on the donkey. I put both stacks back to size they were and disable the second thread that was tripping. I remembered, there was a change I made around the same time this problem showed up. My tick timer has two functions one to tick the CTL OS and the other to make “soft-timer” callbacks. For the last 2 ½ years this code was a single ISR. Every now and then I would want to make CTL call from one of those soft timers, but since it was a ISR I could not. So I changed it to be a thread with ISR control. Note the line of code I commented out. This one line was breaking the semaphores.
Now to the real question, why would this break the semaphores??
//*****************************************************************************
//#############################################################################
//*****************************************************************************
// Name: fnTimersIsr()
//
// Description: This is the timer isr. It is called at ~1mS intervals.
// The callback timers counter are decremented to zero. Then
// callback is then called and its counter is reloaded.
//
// Notes: Isr
//
// MP safe: Should be ok
//
void fnTimersIsr(void)
{
if(g_bTimersIsrBusy)
{
g_bTimersIsrOverrun = true;
}
ctl_increment_tick_from_isr();
ctl_semaphore_signal(&g_srTimerSemaphore);
//ctl_task_reschedule(); //This is the bad line of codereturn;
}//*****************************************************************************
//#############################################################################
//*****************************************************************************
// Name: fnTimersThread()
//
// Description: This is the timer thread. It is called at ~1mS intervals.
// The callback timers counter are decremented to zero. Then
// callback is then called and its counter is reloaded.
//
// Notes:
//
// MP safe: Should be ok
//
void fnTimersThread(void *p)
{
unsigned char ucTimerId;
while(1)
{
if((ctl_semaphore_wait(&g_srTimerSemaphore, CTL_TIMEOUT_NONE, WAIT_FOREVER)) != 0)
{
//Let Isr know we are busy
g_bTimersIsrBusy = true;
g_bTimersOnline = true;
for(ucTimerId = 0; ucTimerId < MAX_NUMBER_OF_1MS_TIMERS; ucTimerId++)
{ //Is this timer active?
if(g_bTimerEnable[ucTimerId])
{ //Yes, check counter for zero
if(g_usTimerCounters[ucTimerId])
{ //Not ready dec
g_usTimerCounters[ucTimerId]--;
}
else
{ //Ready to run, reload and run timer callback
g_usTimerCounters[ucTimerId] = g_usTimerReloads[ucTimerId];
g_apfnTimerCallbacks[ucTimerId]();
}
}
}
//Timers are done
g_bTimersIsrBusy = false;
}
}
return;
}
Please sign in to leave a comment.
Comments
9 comments