前段时间论坛搞网络的培训移植过LwIP到STM32F769-DISCO,当时的移植并没有添加RTOS,在ST的开发包里面有几个lwip + freertos 的例子,下面分享一个LwIP+UCOSIII 移植的例子,需要的同学可以测试下。
1、硬件初始化的部分
和不带RTOS 相比较,添加了RTOS之后,LAN8742A的接收模式从之前的轮询模式修改为中断接收模式。
- <font face="微软雅黑" size="3">EthHandle.Instance = ETH;
- EthHandle.Init.MACAddr = macaddress;
- EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
- EthHandle.Init.Speed = ETH_SPEED_100M;
- EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
- EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
- EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE; //中断接收模式
- EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
- EthHandle.Init.PhyAddress = LAN8742A_PHY_ADDRESS;
- /* configure ethernet peripheral (GPIOs, clocks, MAC, DMA) */
- if(HAL_ETH_Init(&EthHandle) == HAL_OK)
- {
- /* Set netif link flag */
- netif->flags |= NETIF_FLAG_LINK_UP;
- }</font>
复制代码
相应的网卡的接收数据也使用一个任务来处理,在这个任务里面我们pend一个任务信号量来处理接收的数据,
- <font face="微软雅黑" size="3">void ethernetif_input(void * p_arg)
- {
- OS_ERR err;
- struct pbuf *p;
- struct netif *netif = (struct netif *) p_arg;
- for(;;)
- {
- OSTaskSemPend(0,OS_OPT_PEND_BLOCKING,0,&err);
- do
- {
- p = low_level_input(netif);
- if(p != NULL)
- {
- if(netif->input(p, netif) != ERR_OK)
- {
- pbuf_free(p);
- }
- }
- }
- while(p != NULL);
- }
- }</font>
复制代码 然后在网卡接收中断中post这个任务信号量,这样能高效实时的处理接收的网络数据,这也是RTOS的优势所在。
- <font face="微软雅黑" size="3">void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
- {
- OS_ERR err;
- OSTaskSemPost(ÐRXTASKTCB,OS_OPT_POST_NONE,&err);
- }</font>
复制代码 2、软件的移植
带RTOS 的LWIP 使用的时候要移植一个sys_arch.c 文件中几个函数,这个主要是用于lwip 的信号量转化为ucosiii的信号量。还有一个是用于创建lwip的主线程使用,这里调用的sys_thread_new需要在sys_arch.c中实现。
- <font face="微软雅黑" size="3">/**
- * @ingroup lwip_os
- * Initialize this module:
- * - initialize all sub modules
- * - start the tcpip_thread
- *
- * @param initfunc a function to call when tcpip_thread is running and finished initializing
- * @param arg argument to pass to initfunc
- */
- void
- tcpip_init(tcpip_init_done_fn initfunc, void *arg)
- {
- lwip_init();
- tcpip_init_done = initfunc;
- tcpip_init_done_arg = arg;
- if (sys_mbox_new(&mbox, TCPIP_MBOX_SIZE) != ERR_OK) {
- LWIP_ASSERT("failed to create tcpip_thread mbox", 0);
- }
- #if LWIP_TCPIP_CORE_LOCKING
- if (sys_mutex_new(&lock_tcpip_core) != ERR_OK) {
- LWIP_ASSERT("failed to create lock_tcpip_core", 0);
- }
- #endif /* LWIP_TCPIP_CORE_LOCKING */
- sys_thread_new(TCPIP_THREAD_NAME, tcpip_thread, NULL, TCPIP_THREAD_STACKSIZE, TCPIP_THREAD_PRIO);
- }</font>
复制代码
总的来说也就是必须创建2个任务 一个网卡的接收任务,一个是lwip内核的处理任务。
3、添加几个测试任务
为了测试移植的效果我添加4个通信任务:
1) TCP任务:电脑作为服务器,开发板作为客户端。开发板连上服务器后主动循环发送测试数据。
2)UDP任务: 开发板连上电脑后,将电脑通过UDP发送给开发板的数据原封不动的返回给电脑。
3)开发板高速虚拟串口:连上电脑后主动发送数据数据到电脑
4)stlink虚拟串口:将开发板的串口通过stlink发送数据给电脑
几个任务代码:
- <font face="微软雅黑" size="3"> //USB_VCP
- OSTaskCreate((OS_TCB * )&USBVCPTASKTCB,
- (CPU_CHAR * )"USB_VCP_task",
- (OS_TASK_PTR )USB_VCP_Test,
- (void * )0,
- (OS_PRIO )USB_VCP_TASK_PRIO,
- (CPU_STK * )&USB_VCP_TASK_STK[0],
- (CPU_STK_SIZE)USB_VCP_STK_SIZE/10,
- (CPU_STK_SIZE)USB_VCP_STK_SIZE,
- (OS_MSG_QTY )0,
- (OS_TICK )0,
- (void * )0,
- (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
- (OS_ERR * )&err);
-
- //eth_rx
-
- OSTaskCreate((OS_TCB * )ÐRXTASKTCB,
- (CPU_CHAR * )"ETH_RX_task",
- (OS_TASK_PTR )ethernetif_input,
- (void * )&gnetif,
- (OS_PRIO )ETH_RX_TASK_PRIO,
- (CPU_STK * )Ð_RX_TASK_STK[0],
- (CPU_STK_SIZE)ETH_RX_STK_SIZE/10,
- (CPU_STK_SIZE)ETH_RX_STK_SIZE,
- (OS_MSG_QTY )0,
- (OS_TICK )0,
- (void * )0,
- (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
- (OS_ERR * )&err);
- tcpip_init(NULL, NULL);
-
- OSTaskCreate((OS_TCB * )&TCPCLIENTTASKTCB,
- (CPU_CHAR * )"tcp_client_task",
- (OS_TASK_PTR )tcp_client_thread,
- (void * )0,
- (OS_PRIO )TCP_CLIENT_TASK_PRIO,
- (CPU_STK * )&TCP_CLIENT_TASK_STK[0],
- (CPU_STK_SIZE)TCP_CLIENT_STK_SIZE/10,
- (CPU_STK_SIZE)TCP_CLIENT_STK_SIZE,
- (OS_MSG_QTY )0,
- (OS_TICK )0,
- (void * )0,
- (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
- (OS_ERR * )&err);
- //´
- OSTaskCreate((OS_TCB * )&UDPSERVERASKTCB,
- (CPU_CHAR * )"udp_server_task",
- (OS_TASK_PTR )udp_server_thread,
- (void * )0,
- (OS_PRIO )UDP_SERVER_TASK_PRIO,
- (CPU_STK * )&UDP_SERVER_TASK_STK[0],
- (CPU_STK_SIZE)UDP_SERVER_STK_SIZE/10,
- (CPU_STK_SIZE)UDP_SERVER_STK_SIZE,
- (OS_MSG_QTY )0,
- (OS_TICK )0,
- (void * )0,
- (OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|OS_OPT_TASK_SAVE_FP,
- (OS_ERR * )&err); </font>
复制代码 运行是下面的这样子:
4个通信任务动态运行如下:
关于UCOSIII的移植和LwIP的详细使用可以参考之前的帖子。测试代码非常简陋,不合理的地方在所难免,实际使用时请完善。
测试代码:
UCOSIII LwIP.rar
(5.73 MB, 下载次数: 72)
|
难得冒个泡啊