当前位置:首页 > 李晨曦 - 嵌入式系统开发毕业论文
第1章 绪论
图4-2 Lwip中的定时事件表的结构
函数sys_arch_timeouts返回对应于当前任务的指向定时事件链表的起始指针.该指针存在lwip_timeouts[MAX_LWIP_TASKS]中. struct sys_timeouts null_timeouts;
struct sys_timeouts * sys_arch_timeouts(void) {
u8_t curr_prio; s16_t err,offset;
OS_TCB curr_task_pcb; null_timeouts.next = NULL; //获取当前任务的优先级
err = OSTaskQuery(OS_PRIO_SELF,&curr_task_pcb); curr_prio = curr_task_pcb.OSTCBPrio; offset = curr_prio - LWIP_START_PRIO;
//判断当前任务优先级是不是tcp/ip相关任务,优先级5-9 if(offset < 0 || offset >= LWIP_TASK_MAX) {
return &null_timeouts; }
return &lwip_timeouts[offset]; }
ping 192.168.1.95 –l 2000 –t,不间断用长度为2000的数据报进行ping测试,同时使用tftp客户端软件给192.168.1.95下载一个十几兆程序,同时再使用telnet连接192.168.1.95端口7(echo端口),往该端口写数测试echo功能.
在运行一段时间以后,开发板进入不再响应.我当时也是经过长时间的分析才发现是因为在低优先级任务运行ys_arch_timeouts()时被高优先级任务打断改写了curr_task_tcb的值,
-21-
第1章 绪论 从而使sys_arch_timeouts返回的指针错误,进而导致系统死锁.函数sys_timeout给当前任务增加一个定时事件:
void sys_timeout(u32_t msecs, sys_timeout_handler h, void *arg) {
struct sys_timeouts *timeouts; struct sys_timeout *timeout, *t;
timeout = memp_malloc(MEMP_SYS_TIMEOUT); if (timeout == NULL) { return; }
timeout->next = NULL; timeout->h = h; timeout->arg = arg; timeout->time = msecs;
timeouts = sys_arch_timeouts(); if (timeouts->next == NULL) { timeouts->next = timeout; return; }
if (timeouts->next->time > msecs) { timeouts->next->time -= msecs; timeout->next = timeouts->next; timeouts->next = timeout; } else {
for(t = timeouts->next; t != NULL; t = t->next) { timeout->time -= t->time; if (t->next == NULL ||
t->next->time > timeout->time) { if (t->next != NULL) {
t->next->time -= timeout->time; }
timeout->next = t->next; t->next = timeout; break; } } } }
函数sys_untimeout从当前任务定时事件链表中删除一个定时事件 void sys_untimeout(sys_timeout_handler h, void *arg) {
struct sys_timeouts *timeouts; struct sys_timeout *prev_t, *t; timeouts = sys_arch_timeouts(); if (timeouts->next == NULL) {
-22-
第1章 绪论 return; }
for (t = timeouts->next, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
if ((t->h == h) && (t->arg == arg)) {
/* We have a match */
/* Unlink from previous in list */ if (prev_t == NULL)
timeouts->next = t->next; else
prev_t->next = t->next;
/* If not the last one, add time of this one back to next */ if (t->next != NULL)
t->next->time += t->time;
memp_free(MEMP_SYS_TIMEOUT, t); return; } }
return; }
4.“mbox”的实现: mbox的创建
sys_mbox_t sys_mbox_new(void) {
u8_t ucErr;
PQ_DESCR pQDesc;
//从消息队列内存分区中得到一个内存块
pQDesc = OSMemGet( pQueueMem, &ucErr ); if( ucErr == OS_NO_ERR ) { //创建一个消息队列
pQDesc->pQ=OSQCreate(&(pQDesc->pvQEntries[0]), MAX_QUEUE_ENTRIES ); if( pQDesc->pQ != NULL ) { return pQDesc; } }
return SYS_MBOX_NULL; }
发一条消息给”mbox”
const void * const pvNullPointer = 0xffffffff;
void sys_mbox_post(sys_mbox_t mbox, void *data) {
INT8U err; if( !data )
data = (void*)&pvNullPointer; err= OSQPost( mbox->pQ, data);
-23-
第1章 绪论 }
在ucos中,如果OSQPost (OS_EVENT *pevent, void *msg)中的msg==NULL 会返回一条OS_ERR_POST_NULL_PTR错误.而在lwip中会调用sys_mbox_post(mbox,NULL)发送一条空消息,我们在本函数中把NULL变成一个常量指针0xffffffff. 从”mbox”中读取一条消息
#define SYS_ARCH_TIMEOUT 0xffffffff
void sys_mbox_fetch(sys_mbox_t mbox, void **msg) {
u32_t time;
struct sys_timeouts *timeouts; struct sys_timeout *tmptimeout; sys_timeout_handler h; void *arg; again:
timeouts = sys_arch_timeouts(); //返回当前任务定时事件链表起始指针 if (!timeouts || !timeouts->next) { //如果定时事件链表为空 sys_arch_mbox_fetch(mbox, msg, 0); //无超时等待消息 } else {
if (timeouts->next->time > 0) {
//如果超时事件链表不为空,而且第一个超时事件的time !=0
//带超时等待消息队列,超时时间等于超时事件链表中第一个超时事件的time, time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
/*在后面分析中可以看到sys_arch_mbox_fetch调用了ucos中的OSQPend系统调用从消息队列中读取消息.*/
//如果”mbox”消息队列不为空,任务立刻返回,否则任务进入阻塞态.
/*需要重点说明的是sys_arch_mbox_fetch的返回值time:如果sys_arch_mbox_fetch*/ //因为超时返回,time=SYS_ARCH_TIMEOUT, //如果sys_arch_mbox_fetch因为收到消息而返回,
//time = 收到消息时刻的时间-执行sys_arch_mbox_fetch时刻的时间,单位是毫秒 //由于在ucos中任务调用OSQPend系统调用进入阻塞态,到收到消息重新开始执行 //这段时间没有记录下来,所以我们要简单修改ucos的源代码.(后面我们会看到). } else {
/*如果定时事件链表不为空,而且第一个定时事件的time ==0,表示该事件的定时*/ //时间到
time = SYS_ARCH_TIMEOUT; }
if (time == SYS_ARCH_TIMEOUT) { //一个定时事件的定时时间到 tmptimeout = timeouts->next;
timeouts->next = tmptimeout->next; h = tmptimeout->h; arg = tmptimeout->arg;
memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
//从内存中释放该定时事件,并执行该定时事件中的函数 if (h != NULL) { h(arg);
-24-
共分享92篇相关文档