lwIP UDP消息传递-在PBUF#uPool#u大小乘以PBUF#x27之后,接收器停止工作;他们被释放了

lwIP UDP消息传递-在PBUF#uPool#u大小乘以PBUF#x27之后,接收器停止工作;他们被释放了,udp,stm32f4,lwip,Udp,Stm32f4,Lwip,我在STM32芯片上使用lwIP来实现UDP回波。(我从DHCP模块复制了很多代码,它似乎工作得很好。)我有一个简单的Python脚本作为ECHO服务器 我在NO_SYS模式下运行-所有东西都是从主循环调用的 在发送请求后,服务器会做出响应(我在wireshark中看到了这一点),但接收到的数据包根本不会被lwIP接收到 N可以通过更改配置变量PBUF_POOL_SIZE可靠地进行更改,因此您可能认为PBUF在使用后没有被释放,因此池将耗尽。但事实似乎并非如此 我正在使用的实现(与DHCP一样)

我在STM32芯片上使用lwIP来实现UDP回波。(我从DHCP模块复制了很多代码,它似乎工作得很好。)我有一个简单的Python脚本作为ECHO服务器

我在NO_SYS模式下运行-所有东西都是从主循环调用的

在发送请求后,服务器会做出响应(我在wireshark中看到了这一点),但接收到的数据包根本不会被lwIP接收到

N可以通过更改配置变量PBUF_POOL_SIZE可靠地进行更改,因此您可能认为PBUF在使用后没有被释放,因此池将耗尽。但事实似乎并非如此

我正在使用的实现(与DHCP一样)是使用相同的pcb和pbuf对进行发送和接收。代码如下所示:

   
typedef enum SIGNAL_STATE {
    SIGNAL_STATE_IDLE,          // 0
    SIGNAL_STATE_WAIT_ACK,      // 1
} SIGNAL_STATE;

void send_app_broadcast_msg(char *msg);
static void app_inc_pcb_refcount(void);
static void app_dec_pcb_refcount(void);
void rcv_app_msg(void *arg, struct udp_pcb *pcb, struct pbuf *p,
        const ip_addr_t *addr, u16_t port);

SIGNAL_STATE signal_state = SIGNAL_STATE_IDLE;

// allocation and ref counting, copied from DHCP code
static struct udp_pcb *pcb_out = NULL;
struct pbuf *p_out = NULL;
static u8_t app_pcb_refcount = 0;
static char *msg = "MSG #17";
static uint32_t rx_flag = 0;
static uint32_t timeout_ctr = 0;

void app_send_signal(void)
{
    // send "button" was pressed, what to do?
    switch (signal_state) {
    case SIGNAL_STATE_IDLE :
        rx_flag = 0;
        send_app_broadcast_msg(msg);
        signal_state = SIGNAL_STATE_WAIT_ACK;
        break;
    case SIGNAL_STATE_WAIT_ACK:
        // double press, ignore
        break;
    default:
        // illegal state, fatal error!
        fatal_error("%s : Illegal State: %d\n", __func__, signal_state);
        break;
    }
}

void app_check_timeouts(void){
    // this is called every half second by the main loop
    uint8_t c = 0;
    uint32_t end_flag = 0;
    // handle msg response and timeout
    switch (signal_state) {
        case SIGNAL_STATE_IDLE :
        // do nothing
            break;
        case SIGNAL_STATE_WAIT_ACK:
            timeout_ctr++;
            if (rx_flag){
                xprintf("OK\n");
                end_flag = 1;
            } else if ( timeout_ctr > PIXEE_TIMEOUT ) {
                xprintf("TIMED OUT\n");
                end_flag = 1;
            }
            if (end_flag)
            {
                c = pbuf_free(p_out);
                xprintf("p_out=%d ref=%d, c=%d\n", p_out, p_out->ref, c);
                app_dec_pcb_refcount();
                p_out = NULL;
                pcb_out = NULL;
                timeout_ctr = 0;
                rx_flag = 0;
                signal_state = SIGNAL_STATE_IDLE;
            }
            break;
        default:
            // illegal state, fatal error!
            fatal_error("%s : Illegal State: %d\n", __func__, signal_state);
            break;
    }
}

void send_app_broadcast_msg(char *msg)
{
    uint32_t sz = strlen(msg);
    if ( sz > APP_MAX_MSG_SIZE )
    {
        fatal_error("%s : requested message too large (%d, %d) \n", __func__, sz, APP_MAX_MSG_SIZE);
    }

    xprintf("sending broadcast msg \"%s\"... ", msg);
    pixee_inc_pcb_refcount();
    if ( pcb_out == NULL )
    {
        fatal_error("%s : could not allocate out pcb\n", __func__);
    }
    ip_set_option(pcb_out, SOF_BROADCAST);
    udp_bind(pcb_out, IP4_ADDR_ANY, APP_PORT_NUM);
    udp_connect(pcb_out, IP4_ADDR_ANY, APP_PORT_NUM);
    udp_recv(pcb_out, rcv_app_msg, NULL);

    p_out = pbuf_alloc(PBUF_TRANSPORT, sz, PBUF_RAM);
    if ( p_out == NULL )
    {
        fatal_error("%s : could not allocate out pbuf of %d\n", __func__, sz);
    }
    p_out->payload = msg;

    udp_sendto(pcb_out, p_out, IP_ADDR_BROADCAST, APP_PORT_NUM);
}


static void app_inc_pcb_refcount(void)
{
  if (app_pcb_refcount == 0) {
      if ( pcb_out != NULL )
      {
          fatal_error( "%s : memory leak\n", __func__ );
      }


    pcb_out = udp_new();

    if (pcb_out == NULL)
    {
        fatal_error( "%s : could not allocate pcb\n", __func__ );
    }

    udp_bind(pcb_out, IP4_ADDR_ANY, APP_PORT_NUM);
    udp_connect(pcb_out, IP4_ADDR_ANY, APP_PORT_NUM);
    udp_recv(pcb_out, rcv_app_msg, NULL);
  }

  pixee_pcb_refcount++;

  return;
}

static void app_dec_pcb_refcount(void)
{
    if (!(app_pcb_refcount > 0))
    {
        fatal_error( "%s : refcount error\n", __func__ );
    }

  app_pcb_refcount--;

  if (app_pcb_refcount == 0) {
    udp_remove(pcb_out);
    pcb_out = NULL;
  }
}


void rcv_app_msg(void *arg, struct udp_pcb *pcb, struct pbuf *p,
        const ip_addr_t *addr, u16_t port)
{
    // callback from the ISR
    rx_flag = 1;
}


 
我怎么知道相同的pbuf不断被重复使用?以下是xprintf()的控制台输出:

在这个过程中,PBUF_POOL_SIZE=5。如果我把它改为8,我将得到8次良好的运行,然后超时。如您所见,“c”是被释放的pbuf的数量,它始终是1,并且每次调用指向pbuf的指针都是相同的。因此,似乎同一个pbuf被反复使用

(为了记录在案,我还尝试了一个单独的pcb和pbuf用于发送和接收的版本-我根本无法接收到它。)

有什么想法吗


sending broadcast msg "MSG #17"... OK                                   
p_out=536900484 ref=0, c=1                                                      
sending broadcast msg "MSG #17"... OK                                   
p_out=536900484 ref=0, c=1                                                      
sending broadcast msg "MSG #17"... OK                                   
p_out=536900484 ref=0, c=1                                                      
sending broadcast msg "MSG #17"... OK                                   
p_out=536900484 ref=0, c=1                                                      
sending broadcast msg "MSG #17"... OK                                   
p_out=536900484 ref=0, c=1                                                      
sending broadcast msg "MSG #17"... TIMED OUT                            
p_out=536900484 ref=0, c=1