[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lwip-users] sys_timeout handler will not be called
From: |
kuwa |
Subject: |
[lwip-users] sys_timeout handler will not be called |
Date: |
Thu, 05 Feb 2004 21:40:43 +0900 (LMT) |
Hi,
I'm currently using lwIP (0.7.0) with uC/OS-II and
trying to invoke three timers within one task by using sys_timeout().
Three timers are ARP timer(10sec), DHCP fine timer (500msec) and DHCP
coarse timer (60sec).
My code looks like this:
void arp_timer(void *arg)
{
etharp_tmr();
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL);
}
void dhcp_fine_timer(void *arg)
{
dhcp_fine_tmr();
sys_timeout(DHCP_FINE_TIMER_MSECS, (sys_timeout_handler)dhcp_fine_timer,
NULL);
}
void dhcp_coarse_timer(void *arg)
{
dhcp_coarse_tmr();
sys_timeout((u32_t)DHCP_COARSE_TIMER_SECS * 1000,
(sys_timeout_handler)dhcp_coarse_timer, NULL);
}
void MainTask(void *pdat)
{
/* Initialize lwIP stack. */
...
/* Register DHCP two timers */
sys_timeout(DHCP_FINE_TIMER_MSECS,
(sys_timeout_handler)dhcp_fine_timer, NULL);
sys_timeout((u32_t)DHCP_COARSE_TIMER_SECS * 1000,
(sys_timeout_handler)dhcp_coarse_timer, NULL);
/* Add Default I/F.
ARP timer (arp_timer()) is registered in ethernetif_init() (in this task)
by calling sys_timeout. */
IP4_ADDR(&ipaddr, 0, 0, 0, 0);
IP4_ADDR(&netmask, 255, 255, 255, 255);
IP4_ADDR(&gw, 0, 0, 0, 0);
netif_add(&netif, &ipaddr, &netmask, &gw, NULL,
ethernetif_init, tcpip_input);
netif_set_default(&netif);
/* start DHCP */
err = dhcp_start(&netif);
if (err != ERR_OK) {
printf("DHCP start failed\n");
}
/* Wait forever */
sys_msleep(0); /* All the timers, which are registered
by calling sys_timeout() in this task
are scheduled. */
}
By the above code, it seems that all these timers work fine at first.
(All of three timeout handlers are called correctly.)
However after a period of time, all of these timers will stop. (Three
timeout handlers will not be called.)
In that situation I found that timeouts->next is NULL (at the line #1
of the below citaion) in sys_sem_wait() which is called from
sys_msleep() of MainTask().
void
sys_sem_wait(sys_sem_t sem)
{
u32_t time;
struct sys_timeouts *timeouts;
struct sys_timeout *tmptimeout;
sys_timeout_handler h;
void *arg;
/* while (sys_arch_sem_wait(sem, 1000) == 0);
return;*/
again:
timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) { /* #1 */
sys_arch_sem_wait(sem, 0); /* #2 */
} else {
if (timeouts->next->time > 0) {
time = sys_arch_sem_wait(sem, timeouts->next->time);
} else {
time = SYS_ARCH_TIMEOUT;
}
...snip...
}
MainTask() calls sys_msleep(), and sys_msleep() calls sys_sem_wait().
Then sys_sem_wait() calls timeout handler and timeout data is removed
from timeouts list.
I'm gussing that a timeout handler (or some functions called from a
timeout handler) call sys_sem_wait() again (removed from timeouts
list), and timeouts list eventually has been empty. And wait forever
at the line #2.
As a workaround, I replace sys_msleep() call in MainTask() with the
following sys_timer_kicker() call, which is almost copied from
sys_sem_wait().
It seems that works fine. How would you think about my guess and
this workaround?
void sys_timer_kicker(void)
{
u32_t time;
struct sys_timeouts *timeouts;
struct sys_timeout *tmptimeout;
sys_timeout_handler h;
void *arg;
sys_sem_t sem;
sem = sys_sem_new(0);
sys_sem_name(sem, "for sys_timeout");
for (;;) {
timeouts = sys_arch_timeouts();
if (!timeouts || !timeouts->next) {
/* Wait for a while */
sys_arch_sem_wait(sem, 50);
} else {
if (timeouts->next->time > 0) {
time = sys_arch_sem_wait(sem, timeouts->next->time);
} else {
time = SYS_ARCH_TIMEOUT;
}
if (time == SYS_ARCH_TIMEOUT) {
/* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
could be fetched. We should now call the timeout handler and
deallocate the memory allocated for the timeout. */
tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next;
h = tmptimeout->h;
arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) {
LWIP_DEBUGF(SYS_DEBUG, ("stk h=%p(%p)\n", (void *)h, (void *)arg));
h(arg);
}
} else {
/* If time != SYS_ARCH_TIMEOUT, a message was received before the
timeout
occured. The time variable is set to the number of
milliseconds we waited for the message. */
if (time <= timeouts->next->time) {
timeouts->next->time -= time;
} else {
timeouts->next->time = 0;
}
}
} /* We try again to fetch a message from the mbox. */
}
}
--
Shuji KUWAHARA
- [lwip-users] sys_timeout handler will not be called,
kuwa <=