使用 FreeRtos、netconn API 和 stm32f2 的 HAL 库的 TCP 服务器中的线程删除问题

问题描述 投票:0回答:0

我正在做一个定制板项目:

  1. 将按照客户端-服务器模型通信将 PC 主机(客户端应用程序)连接到此板。
  2. 会收到请求数据的请求包
  3. 写入/读取 io 微控制器引脚状态(mcu = stm32f207zg)
  4. 将发送包含有关这些操作的数据的答案

目标是获得一个固件版本,实现一个 TCP 服务器处理多个客户端连接,最多 10 个,通过相同的应用程序端口。

首先,我保留了演示项目结构(应用笔记上说这个结构是正确的方式)DemoApp_AN。然后我自定义了这个线程,添加了发送应答的操作(从服务器到客户端应用程序)。它在“服务器 - 只有一个客户端”模式下工作正常。

所以,考虑如何创建多客户端线程,我在每个新连接到达时创建了另一个线程。我按照这个方案实施:

服务器线程和客户端句柄线程实现(我的):

/**extern global**/

extern uint8_t BWR_FLAG;
extern uint8_t SWR_FLAG;
extern uint8_t tcpBufferWRL[20];
extern uint8_t tcpBufferWRS[5];
extern uint8_t enableBlink[16];
extern uint8_t BytesRD[16];
extern uint8_t Length;
extern sPins gpio_inputs[MAX_IN_PINS];
extern sPins gpio_outputs[MAX_OUT_PINS];
extern sPins gpio_adr[MAX_ADR_PINS];
struct netif gnetif;

static void tcpecho_thread(void *arg)
{
    struct netconn *conn, *newconn;
    err_t err, accept_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, 43808);//todo: magic number

        if (err == ERR_OK)
        {
            /* Tell connection to go into listening mode. */
            netconn_listen(conn);

            while (1)
            {
                /* Grab new connection. */
                accept_err = netconn_accept(conn, &newconn);

                /* Process the new connection. */
                if (accept_err == ERR_OK)
                {
                    // new connected client thread  
                    sys_thread_new("ActiveConn_thread", ActiveConn_thread, (void*)newconn, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO );
                }
            }
        }
        else
        {
          netconn_delete(newconn);
        }
    }
}
/*-----------------------------------------------------------------------------------*/

void tcpecho_init(void)
{
  sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO );
}
/*-----------------------------------------------------------------------------------*/

/*Here is the client thread with their actions once 
packet is received up to the answer and closing connection*/

static void ActiveConn_thread(void *arg)
{
    struct netconn *newconn = arg;
    struct netbuf *buf;
    void *data;

    u16_t len;
    uint8_t pp[20];
    uint8_t *buffer = NULL ;
    uint8_t nPin = 0;
    /* get new client connection reiceved buffer */
    while (netconn_recv(newconn, &buf) == ERR_OK) //buf = netbuf = packet buffer from netconn
    {
        do
        {
            netbuf_data(buf, &data, &len);//Get the data pointer and length of the data inside a netbuf = buf = paquet rebut.
            buffer = (uint8_t*)data;
            Length = len-1;

            //*get bytes
            for (uint8_t i = 0; i<=len;i++)
            {
                pp[i]=buffer[i];

            }
            if(pp[0] == 0xC1)
            {

              len = 16;
              for (uint8_t i = 0; i<len;i++)
              {

                  BytesRD[i] = ML_GPIO_GetState(gpio_inputs[i].tPort,gpio_inputs[i].tPin);
                  if (BytesRD[i] == 0) BytesRD[i] = 1;
                  else BytesRD[i] = 0;
              }

              /* answer*/
              data = (void*)BytesRD;
              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);

    vTaskDelete( NULL );
}

问题:

这似乎工作正常,直到客户端数量达到 5 的值,如果第 6 个客户端尝试连接此服务器,连接就会丢失。当我断开同一个客户端时,也会发生同样的情况。当连接数达到此数量时,新线程客户端的创建将停止。因此,没有完成新的客户端连接。

所以寻找问题我调试了 LwIP 文件,我注意到这些事情:

  • 在第 6 次连接执行按预期工作后,直到实现此语句:
while (netconn_recv(newconn, &buf) == ERR_OK) //buf = netbuf = packet buffer from netconn

  • 如果我进入内部,逐步模式,netconn 函数(可以在 api_lib.c 文件中找到)返回一个 ERR_MEM
  • 还有一个语句返回这个错误代码,因为这个动作返回一个值=0:
   buf = (struct netbuf *)memp_malloc(MEMP_NETBUF);

看到,似乎内存问题是问题所在。这可能是错误的多客户端线程创建、错误的任务删除、LwIP 错误配置等的结果

所以我继续进行一些检查,发现服务器无法创建超过 6 个线程。这让我怀疑 Rtos 问题。我意识到也许我需要增加 FreeRtosconfig 文件上的内存堆。

改进尝试:

我也采取了这些行动:

  • 我确保我启用了 freertos RAM 编写器而不是应用程序编写器。

  • 然后我增加了堆大小,

  • 所以在这个动作之后,服务器线程可以创建的客户端任务的数量从 5 增加到 18.

这是一个改进,但主要问题仍未解决:如果在同一个创建的线程中调用,资源释放操作似乎不适用于 terminatetask(id) 操作。我已经了解到,如果在 RTOS 配置为在 RAM 上写入 freeRtos 时调用终止函数,资源将自动释放。

问题:

如果删除任务没有释放被删除线程的内存资源,之前是否需要做其他事情?如何做呢?我要求建议或任何相关信息。


发帖:

根据评论,我尝试搜索FreeRtos中间件在我的项目中有什么样的内存管理,我看到了这个:

我猜这意味着项目正在使用 pvPortMalloc 而不是 malloc。如果我错了,请告诉我。

c stm32 tcpclient freertos lwip
© www.soinside.com 2019 - 2024. All rights reserved.