上次介绍了使用stm32f407和phy芯片DP83848进行网络通信的硬件组成和注意事项。软件方面移植uC/OS-III过程中可能发生的问题。lwip的特点和组成,移植多线程lwip所需要处理的文件。下面就开始将uC/OS-III和lwip1.4.0揉在一起了。。。。真担心写不好。。。为了F429Discovery,拼了吧。
本文假设uC/OS-III已经移植到stm32f407上了,并且可以完成简单的任务。在移植的过程中将会修改已经移植好的uC/OS-III工程,同时参考st官网lwip单线程的例程。那么只需要修改下lwip相关的port文件就可以了。其中ethernetif.c文件基本不用修改(需要修改的地方是这次使用stm32F407的以太网接收中断,需要在NVIC中使能这个中断,并且在stm32f4xx_int.c文件中添加对中断的处理)。需要处理的文件有sys_arch.c/.h文件;main.c或者叫app.c文件;lwip文件,用于处理lwip的初始化(与单线程的lwip初始化稍有区别);lwipopts.h文件的修改;httpserver_conn.c文件。
ethernetif.c文件的修改。主要是添加stm32F407的以太网接收中断的配置,如果dp83848连接了F407的io,则可以在程序初始化时,根据dp83848状态寄存器的连接状态位来决定是否启用mac和phy的自动协商功能。等连接之后再重新初始化一下即可。
修改stm32f4xx_it.c。添加对两个中断的响应函数,一是以太网接收中断,判断接收到了数据就调用ethernet_input来处理,请中断标志退出。二是处理dp过来的中断,修改连接状态的标志变量。
lwip文件的修改。可以参照官网lwip例程来修改,将初始化函数中的lwip_init用tcpip_init(NULL,NULL)来代替,将netif_add(&main_net, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernetif_input);最后一个参数用LWIP的api函数tcpip_input来代替。即netif_add(&main_net, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &tcpip_input);
main.c或者叫app.c文件。修改appstarttask,添加刚刚修改的lwip的初始化函数。添加http_server_netconn_init();初始化http处理线程(这个函数在httpserver_conn.c函数中)。然后删除任务,或者循环delay,你懂的。
最后修改sys_arch.c/.h。先修改sys_arch.h文件,添加在lwip中对信号量和邮箱的定义。接着是修改sys_arch.c文件,具体内容为:
1.信号量的封装。主要是对sys_sem_new(),sys_arch_sem_wait(),sys_sem_signal(),sys_sem_free(),sys_sem_valid(),sys_sem_set_invalid()。通过对uCOS的信号量进行简单封装就可以了,成功返回0,失败返回-1,超时返回SYS_ARCH_TIMEOUT。这里不再详述。
2.互斥对象的实现。这个并不是很重要,可以简单的用信号量函数代替,也可以用uCOS的互斥对象实现。如果用信号量函数代替,需要定义宏LWIP_COMPAT_MUTEX。
3.消息邮箱的封装。sys_mbox_new(),sys_mbox_free(),sys_mbox_post(),sys_mbox_trypost()相对比较简单,sys_mbox_free的实现需要在删除邮箱之前,用OSQFlush清空消息队列的内容。sys_mbox_post和sys_mbox_trypost的区别是post的次数,一个是尝试发送一次,一个是尝试发送十次左右。
4.sys_arch_mbox_fetch的实现,这是一个比较重要的函数,用来阻塞一个线程,知道接收到消息。阻塞的时间视参数timeout而定,返回超时的时间。所以这个函数就是对 OSQPend的简单封装,填充传入的消息指针,返回超时时间即可。
5.sys_arch_mbox_tryfetch的实现。根据lwip作者的解释,This is similar to sys_arch_mbox_fetch, however if a message is not present in the mailbox, it immediately returns with the code.
To allow for efficient implementations, this can be defined as a
function-like macro in sys_arch.h instead of a normal function. For
example, a naive implementation could be:
#define sys_arch_mbox_tryfetch(mbox,msg) \
sys_arch_mbox_fetch(mbox,msg,1)
although this would introduce unnecessary delays.
就这样一个宏kill了一个函数。
|