1 下载LwIP
很简单,到LwIP的官方网站即可:http://savannah.nongnu.org/projects/lwip/。如果你不想看看其它内容(可能对你会很重要),就只是想得到源码,好的,直接到这个地址下载:http://download.savannah.nongnu.org/releases/lwip/。目前官方发布的最新版本是1.1.1,找到lwip-1.1.1.zip,然后下载、解压缩,第一项工作完成。
2 建立一个最基本的工程
要想完成移植工作,我们必须要有一个包含uC/OS-II的工程才行,这一步我们就是要建立这个工程。工程建立完毕后,编译链接没有问题,那么,第二项工作也完成了。关于如何建立一个包含uC/OS-II的ADS工程的问题,不在本文描述范围之内,这里不做讲述。随本笔记一同发布的源码文档中LwIPPortingTest_2文件夹下包含了这个最基本工程的源码,读者可以直接使用。我的基本工程建立的路径是D:\work\LwIPPortingTest,下文将以相对路径进行讲述,不再提供绝对路径。
3 把LwIP加入工程
都可以正常工作。邮箱用于消息传递,用户即可以将其实现为一个队列,允许多条消息投递到这个邮箱,也可以每次只允许投递一个消息。这两种方式LwIP都可以正常运作。不过,前者更加有效。需要用户特别注意的是――投递到邮箱中的消息只能是一个指针。
在sys_arch.h文件中,我们指定数据类型“sys_sem_t”表示信号量,“sys_mbox_t”表示邮箱。至于sys_sem_t和sys_mbox_t如何表示这两种不同类型,LwIP没有任何限制。
以下函数必须在sys_arch中实现: - void sys_init(void)
初始化sys_arch层。 - sys_sem_t sys_sem_new(u8_t count) 建立并返回一个新的信号量。参数count指定信号量的初始状态。 - void sys_sem_free(sys_sem_t sem) 释放信号量。 - void sys_sem_signal(sys_sem_t sem) 发送一个信号。 - u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) 等待指定的信号并阻塞线程。timeout参数为0,线程会一直被阻塞至收到指定的信号;非0,则线程仅被阻塞至指定的timeout时间(单位为毫秒)。在timeout参数值非0的情况下,返回值为等待指定的信号所消耗的毫秒数。如果在指定的时间内并没有收到信号,返回值为 SYS_ARCH_TIMEOUT。如果线程不必再等待这个信号(也就是说,已经收到信号),返回值也可以为0。注意,LwIP实现了一个名称与之相似的函数来调用这个函数,sys_sem_wait(),注意区别。
- sys_mbox_t sys_mbox_new(void) 建立一个空的邮箱。 - void sys_mbox_free(sys_mbox_t mbox) 释放一个邮箱。如果释放时邮箱中还有消息,它表明LwIP中存在一个编程错误,应该通知开发者(原文如此,这句话很费解。个人理解的意思是:当执行sys_mbox_free()这个函数时,按道理邮箱中不应该再存在任何消息,如果用户使用LwIP时发现邮箱中还存在消息,说明LwIP的开发者存在一个编程错误,不能把邮箱中的消息全部取出并处理掉。遇到这种情况,用户应该告诉LwIP的作者,纠正这个bug,译注)。
- 4 -
uC/OS-II 平台下的 LwIP 移植笔记――作者:焦海波 2006-9-1
- void sys_mbox_post(sys_mbox_t mbox, void *msg) 投递消息“msg”到指定的邮箱“mbox”。 - u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) 阻塞线程直至邮箱收到至少一条消息。最长阻塞时间由timeout参数指定(与sys_arch_sem_wait()函数类似)。msg是一个结果参数,用来保存邮箱中的消息指针(即*msg = ptr),它的值由这个函数设置。“msg”参数有可能为空,这表明当前这条消息应该被丢弃。 返回值与sys_arch_sem_wait()函数相同:等待的毫秒数或者SYS_ARCH_TIMEOUT――如果时间溢出的话。LwIP实现的函数中,有一个名称与之相似的――sys_mbox_fetch(),注意区分。 - struct sys_timeouts *sys_arch_timeouts(void) 返回一个指向当前线程使用的sys_timeouts结构的指针。LwIP中,每一个线程都有一个timeouts链表,这个链表由sys_timeout结构组成,sys_timeouts结构则保存了指向这个链表的指针。这个函数由LwIP的超时调度程序调用,并且不能返回一个空(NULL)值。 单线程sys_arch实现中,这个函数只需简单返回一个指针即可。这个指针指向保存在sys_arch模块中的sys_timeouts全局变量。 如果底层操作系统支持多线程并且LwIP中需要这样的功能,那么,下面的函数必须实现: - sys_thread_t sys_thread_new(void(*thread)(void *arg), void *arg, int prio) 启动一个由函数指针thread指定的新线程,arg将作为参数传递给thread()函数,prio指定这个新线程的优先级。返回值为这个新线程的ID,ID和优先级由底层操作系统决定。 - sys_prot_t sys_arch_protect(void) 这是一个可选函数,它负责完成临界区域保护并返回先前的保护状态。该函数只有在小的临界区域需要保护时才会被调用。基于ISR驱动的嵌入式系统可以通过禁止中断来实现这个函数。基于任务的系统可以通过互斥量或禁止任务来实现这个函数。该函数应该支持来自于同一个任务或中断的递归调用。换句话说,当该区域已经被保护,sys_arch_protect()函数依然能被调用。这时,函数的返回值会通知调用者该区域已经被保护。 如果你的移植正在支持一个操作系统,sys_arch_protect()函数仅仅是一个需要。 - void sys_arch_unprotect(sys_prot_t pval) 该函数同样是一个可选函数。它的功能就是恢复受保护区域的先前保护状态,先前是受到保护还是没有受到保护由参数pval指定。它与sys_arch_protect()函数配套使用,详细信息参看sys_arch_protect()函数。 该函数的说明是按照译者个人理解的意思翻译,原文讲述不是很清楚,如有错误,欢迎批评指正,译注。 -------------------------------------------------------------------------------------- OS支持的模拟层需要添加的头文件说明 -------------------
很简单,到LwIP的官方网站即可:http://savannah.nongnu.org/projects/lwip/。如果你不想看看其它内容(可能对你会很重要),就只是想得到源码,好的,直接到这个地址下载:http://download.savannah.nongnu.org/releases/lwip/。目前官方发布的最新版本是1.1.1,找到lwip-1.1.1.zip,然后下载、解压缩,第一项工作完成。
2 建立一个最基本的工程
要想完成移植工作,我们必须要有一个包含uC/OS-II的工程才行,这一步我们就是要建立这个工程。工程建立完毕后,编译链接没有问题,那么,第二项工作也完成了。关于如何建立一个包含uC/OS-II的ADS工程的问题,不在本文描述范围之内,这里不做讲述。随本笔记一同发布的源码文档中LwIPPortingTest_2文件夹下包含了这个最基本工程的源码,读者可以直接使用。我的基本工程建立的路径是D:\work\LwIPPortingTest,下文将以相对路径进行讲述,不再提供绝对路径。
3 把LwIP加入工程
都可以正常工作。邮箱用于消息传递,用户即可以将其实现为一个队列,允许多条消息投递到这个邮箱,也可以每次只允许投递一个消息。这两种方式LwIP都可以正常运作。不过,前者更加有效。需要用户特别注意的是――投递到邮箱中的消息只能是一个指针。
在sys_arch.h文件中,我们指定数据类型“sys_sem_t”表示信号量,“sys_mbox_t”表示邮箱。至于sys_sem_t和sys_mbox_t如何表示这两种不同类型,LwIP没有任何限制。
以下函数必须在sys_arch中实现: - void sys_init(void)
初始化sys_arch层。 - sys_sem_t sys_sem_new(u8_t count) 建立并返回一个新的信号量。参数count指定信号量的初始状态。 - void sys_sem_free(sys_sem_t sem) 释放信号量。 - void sys_sem_signal(sys_sem_t sem) 发送一个信号。 - u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout) 等待指定的信号并阻塞线程。timeout参数为0,线程会一直被阻塞至收到指定的信号;非0,则线程仅被阻塞至指定的timeout时间(单位为毫秒)。在timeout参数值非0的情况下,返回值为等待指定的信号所消耗的毫秒数。如果在指定的时间内并没有收到信号,返回值为 SYS_ARCH_TIMEOUT。如果线程不必再等待这个信号(也就是说,已经收到信号),返回值也可以为0。注意,LwIP实现了一个名称与之相似的函数来调用这个函数,sys_sem_wait(),注意区别。
- sys_mbox_t sys_mbox_new(void) 建立一个空的邮箱。 - void sys_mbox_free(sys_mbox_t mbox) 释放一个邮箱。如果释放时邮箱中还有消息,它表明LwIP中存在一个编程错误,应该通知开发者(原文如此,这句话很费解。个人理解的意思是:当执行sys_mbox_free()这个函数时,按道理邮箱中不应该再存在任何消息,如果用户使用LwIP时发现邮箱中还存在消息,说明LwIP的开发者存在一个编程错误,不能把邮箱中的消息全部取出并处理掉。遇到这种情况,用户应该告诉LwIP的作者,纠正这个bug,译注)。
- 4 -
uC/OS-II 平台下的 LwIP 移植笔记――作者:焦海波 2006-9-1
- void sys_mbox_post(sys_mbox_t mbox, void *msg) 投递消息“msg”到指定的邮箱“mbox”。 - u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout) 阻塞线程直至邮箱收到至少一条消息。最长阻塞时间由timeout参数指定(与sys_arch_sem_wait()函数类似)。msg是一个结果参数,用来保存邮箱中的消息指针(即*msg = ptr),它的值由这个函数设置。“msg”参数有可能为空,这表明当前这条消息应该被丢弃。 返回值与sys_arch_sem_wait()函数相同:等待的毫秒数或者SYS_ARCH_TIMEOUT――如果时间溢出的话。LwIP实现的函数中,有一个名称与之相似的――sys_mbox_fetch(),注意区分。 - struct sys_timeouts *sys_arch_timeouts(void) 返回一个指向当前线程使用的sys_timeouts结构的指针。LwIP中,每一个线程都有一个timeouts链表,这个链表由sys_timeout结构组成,sys_timeouts结构则保存了指向这个链表的指针。这个函数由LwIP的超时调度程序调用,并且不能返回一个空(NULL)值。 单线程sys_arch实现中,这个函数只需简单返回一个指针即可。这个指针指向保存在sys_arch模块中的sys_timeouts全局变量。 如果底层操作系统支持多线程并且LwIP中需要这样的功能,那么,下面的函数必须实现: - sys_thread_t sys_thread_new(void(*thread)(void *arg), void *arg, int prio) 启动一个由函数指针thread指定的新线程,arg将作为参数传递给thread()函数,prio指定这个新线程的优先级。返回值为这个新线程的ID,ID和优先级由底层操作系统决定。 - sys_prot_t sys_arch_protect(void) 这是一个可选函数,它负责完成临界区域保护并返回先前的保护状态。该函数只有在小的临界区域需要保护时才会被调用。基于ISR驱动的嵌入式系统可以通过禁止中断来实现这个函数。基于任务的系统可以通过互斥量或禁止任务来实现这个函数。该函数应该支持来自于同一个任务或中断的递归调用。换句话说,当该区域已经被保护,sys_arch_protect()函数依然能被调用。这时,函数的返回值会通知调用者该区域已经被保护。 如果你的移植正在支持一个操作系统,sys_arch_protect()函数仅仅是一个需要。 - void sys_arch_unprotect(sys_prot_t pval) 该函数同样是一个可选函数。它的功能就是恢复受保护区域的先前保护状态,先前是受到保护还是没有受到保护由参数pval指定。它与sys_arch_protect()函数配套使用,详细信息参看sys_arch_protect()函数。 该函数的说明是按照译者个人理解的意思翻译,原文讲述不是很清楚,如有错误,欢迎批评指正,译注。 -------------------------------------------------------------------------------------- OS支持的模拟层需要添加的头文件说明 -------------------