FreeRTOS+LWIP+STM32F CUBEMX心得

近段时间有个项目,需要用到操作系统。之前用过ucos,但是经过多方考虑后,还是决定使用Freerots。

项目需要用到以太网,处理器决定使用STM32F。ST做得还是不错的,STM32CubeMX解决了很多底层的问题,但是因为之前我用的基本库,没有用到HAL库,所以在使用HAL库的时候也遇到了不少问题,还好都一一化解。唯一最大的问题是LWIP,之前用的1.4.1版本的,前后台系统,用起来很顺畅,也没出现问题。而STM32CubeMX只支持2.0的,那就用2.0的呗。结果出现了很多问题,例如死机,网络中断等等。先总结如下:

1.  第一次使用Freertos的话,因为对该系统不是很熟,所以,务必使用串口打印系统所有任务的信息,这样子对所有任务一目了然,容易发现问题。一开始我没去做这件事情,有个TCP端口的任务总是在跑了一两天后出问题,然后一头转到LWIP协议栈是找问题,结果浪费了很多时间,也没能解决。最后把任务打印出来后,发现任务异常,堆栈不够,调整好堆栈就解决了,很冤。

TaskName  Status  Priority   Availiable TaskId 
Sts_Task       R 3 178 6
IDLE           R 0 106 19
Beep_Task       B 3 98 8
uartTask4       B 3 102 4
uartTask3       B 3 132 3
uartTask2       B 3 132 2
ADC_Task       B 3 50 11
dido_Task       B 3 98 10
LinkThr         B 3 222 22
tcpip_thread   B 3 878 20
KEY_Task       B 3 100 7
Led_Task       B 3 98 9
uartTask1       B 3 224 1
defaultTask     B 3 174 5
httpd_Task     S 3 248 12
Tcp5_Task       S 3 244 18
Tcp2_Task       S 3 196 15
Tcp1_Task       S 3 72 14
EthIf           S 3 288 21
Tcp4_Task       S 3 204 17
Tcp3_Task       S 3 238 16
Telnet_Task     S 3 284 13


TaskName  RunCounts  CpuRate
Sts_Task       3898 1%
IDLE           353364 94%
tcpip_thread   739 <1%
uartTask4       1305 <1%
dido_Task       264 <1%
uartTask3       1272 <1%
uartTask2       1585 <1%
Beep_Task       43 <1%
KEY_Task       6 <1%
Led_Task       8 <1%
uartTask1       3 <1%
ADC_Task       6627 1%
LinkThr         66 <1%
defaultTask     3788 1%
Tcp5_Task       195 <1%
Tcp2_Task       84 <1%
Tcp1_Task       93 <1%
EthIf           249 <1%
Tcp4_Task       182 <1%
Tcp3_Task       196 <1%
Telnet_Task     0 <1%
httpd_Task     509 <1%


System Heap Available: 10880

2. LWIP2.0相对于1.0来讲,增加了很多功能,但是有些问题还是没有彻底解决,例如在某种阶段情况下,可能会卡在CLOSE_WAIT状态无法退出,导致占用端口,占用内存等。


3. 官方提供的例程,“udptcp_echo_server_netconn”,它只是一个例程,只能用于入门使用,毕竟NETCOMM写得不够完善,需要自己增加条件去做些维护,确保在异常、极端情况下不会导致端口无法通信。例如下方红色部分,如果端口不是正常关闭的话,对导致TCP内存得不到释放,久而久之内存就不够导致死机。



/*-----------------------------------------------------------------------------------*/
static void tcpecho_thread(void *arg)
{
  struct netconn *conn, *newconn;
  err_t err;


  LWIP_UNUSED_ARG(arg);


  /* Create a new connection identifier. */
  conn = netconn_new(NETCONN_TCP);
  
  if (conn!=NULL)
  {  
    /* Bind connection to well known port number 7. */
    err = netconn_bind(conn, NULL, 7);
    
    if (err == ERR_OK)
    {
      /* Tell connection to go into listening mode. */
      netconn_listen(conn);
    
      while (1) 
      {
        /* Grab new connection. */
        newconn = netconn_accept(conn);
    
        /* Process the new connection. */
        if (newconn) 
        {
          struct netbuf *buf;
          void *data;
          u16_t len;
      
          while ((buf = netconn_recv(newconn)) != NULL) 
          {
            do 
            {
              netbuf_data(buf, &data, &len);
              netconn_write(newconn, data, len, NETCONN_COPY);
          
            } 
            while (netbuf_next(buf) >= 0);
          
            netbuf_delete(buf);
          }
        
          /* Close connection and discard connection identifier. */
          netconn_close(newconn);     //调用该函数,如果客户端已经不存在的话,内存或端口将得不到释放
          netconn_delete(newconn);

        }
      }
    }
    else
    {
      printf(" can not bind TCP netconn");
    }
  }
  else
  {
    printf("can not create TCP netconn");
  }
}


发布了106 篇原创文章 · 获赞 143 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/shjhuang/article/details/79994995
今日推荐