creep 发表于 2017-8-20 18:18:15

【F769IDISCOVERY评测】UCSOIII+LwIP 移植

       前段时间论坛搞网络的培训移植过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,       
               (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,       
               (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,       
               (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,       
               (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的详细使用可以参考之前的帖子。测试代码非常简陋,不合理的地方在所难免,实际使用时请完善。



测试代码:



推荐阅读:


【F769IDISCOVERY评测】LwIP Echo 及数据传输测试

【F769IDISCOVERY评测】LwIP之以太网固件升级


【NUCLEO-L496ZG评测】+ UCOSIII:内存管理和消息队列

【NUCLEO-L496ZG评测】+ UCOSIII:软件定时器和信号量

【NUCLEO-L496ZG评测】+ UCOSIII简单移植

【NUCLEO-L496ZG评测】+ UCOSIII:事件标志组


Paderboy 发表于 2017-8-20 19:07:44

:loveliness:学习了。。。。顶起

哈佛祖安智 发表于 2017-8-20 20:51:51

学习了。。。。顶起

zero99 发表于 2017-8-21 08:51:19

谢谢支持,加到汇总贴了https://www.stmcu.org.cn/module/forum/thread-609491-1-1.html

creep 发表于 2017-8-21 09:15:00

zero99 发表于 2017-8-21 08:51
谢谢支持,加到汇总贴了https://www.stmcu.org.cn/module/forum/thread-609491-1-1.html

:handshake

风子 发表于 2017-8-21 09:44:41

大神的帖子含精量妥妥的

辉常可乐 发表于 2017-8-21 10:35:25

谢谢分享

zero99 发表于 2017-8-21 13:46:26

风子 发表于 2017-8-21 09:44
大神的帖子含精量妥妥的

难得冒个泡啊

jcx0324 发表于 2017-8-22 10:02:23

好贴,赞一个            

w0130160 发表于 2019-9-13 20:13:09

谢谢分享!!
页: [1]
查看完整版本: 【F769IDISCOVERY评测】UCSOIII+LwIP 移植