This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TMS570LS3137:lwIP 演示在大约60个 UDP 数据包之后停止

Guru**** 2587365 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1130212/tms570ls3137-lwip-demo-halts-after-about-60-udp-packets

器件型号:TMS570LS3137

我正在尝试使用 lwIP Demo 4.0.0作为新固件的基础。 但是,在向其发送大约60个 UDP 数据包后,由于 CURR_BD->NEXT 中的 NULL 指针(CURR_BD 是 hdkif[0]->state->rxch->active_head),中断处理程序中的代码会更精确地在函数 hdkif_rx_inthandler 处停止。 尝试在函数循环中检查该指针可防止中断、但不会再发出中断。

我目前正在 将 CCS 11.1.0.00011与 TI 编译器 v20.2.7.LTS 搭配使用。 为方便参考、我将粘贴以下中断处理程序、并进行了一些修改以尝试隔离问题:

/**
 * Handler for Receive interrupt. Packet processing is done in this
 * interrupt handler itself.
 *
 * @param netif the lwip network interface structure for this ethernetif
 * @return none
 */
uint32 last_curr_bd, last_next_bd;
uint32 no_prob_last = 1;
void
hdkif_rx_inthandler(struct netif *netif) {
  struct hdkif *hdkif;
  struct rxch *rxch;
  volatile struct emac_rx_bdp *curr_bd, *processed_bd, *curr_tail, *last_bd;
  volatile struct pbuf *pbuf, *q, *new_pbuf;
  uint32 ex_len = 0, len_to_alloc = 0;
  uint16 tot_len;

  hdkif = netif->state;
  rxch = &(hdkif->rxch);

  /* Get the bd which contains the earliest filled data */
  curr_bd = rxch->active_head;
  last_bd = rxch->active_tail;


  /**
   * Process the descriptors as long as data is available
   * when the DMA is receiving data, SOP flag will be set
  */
  while((hdkif_swizzle_data(curr_bd->flags_pktlen) & EMAC_BUF_DESC_SOP)
        && (curr_bd != NULL)) {
    ex_len = 0;
    len_to_alloc = 0;

    /* Start processing once the packet is loaded */
    if((hdkif_swizzle_data(curr_bd->flags_pktlen) & EMAC_BUF_DESC_OWNER)
       != EMAC_BUF_DESC_OWNER) {

      if(rxch->free_head == NULL) {
        /* this bd chain will be freed after processing */
        rxch->free_head = curr_bd;
      }

      /* Get the total length of the packet. curr_bd points to the start
       * of the packet.
       */
      tot_len = hdkif_swizzle_data(curr_bd->flags_pktlen) & 0xFFFF;

      /* Get the start of the pbuf queue */
      q = curr_bd->pbuf;

      do {
        /* Get the pbuf pointer which is associated with the current bd */
        pbuf = curr_bd->pbuf;

        /* If the earlier pbuf ended, update the chain */
        if(pbuf->next == NULL) {
          pbuf->next = (struct pbuf*)hdkif_swizzle_rxp(curr_bd->next)->pbuf;
        }

        len_to_alloc += pbuf->len;
        /* Update the len and tot_len fields for the pbuf in the chain*/
        pbuf->len = hdkif_swizzle_data(curr_bd->bufoff_len) & 0xFFFF;
        pbuf->tot_len = tot_len - ex_len ;
        processed_bd = curr_bd;
        ex_len += pbuf->len;

        /* if(hdkif_swizzle_rxp(curr_bd->next) == NULL){ */
        /*     break; */
        /* }else{ */
            curr_bd = hdkif_swizzle_rxp(curr_bd->next);
        /* } */
      } while((hdkif_swizzle_data(processed_bd->flags_pktlen) & EMAC_BUF_DESC_EOP)
              != EMAC_BUF_DESC_EOP);

      /**
       * Close the chain for this pbuf. A full packet is received in
       * this pbuf chain. Now this pbuf can be given to upper layers for
       * processing. The start of the pbuf chain is now 'q'.
      */
      pbuf->next = NULL;

      /* Adjust the link statistics */
      LINK_STATS_INC(link.recv);

      /* Process the packet */
      if(ethernet_input((struct pbuf *)q, netif) != ERR_OK) {
        /* Adjust the link statistics */
        LINK_STATS_INC(link.memerr);
        LINK_STATS_INC(link.drop);
      }

      /* Acknowledge that this packet is processed */
      EMACRxCPWrite(hdkif->emac_base, 0, (unsigned int)processed_bd);

      rxch->active_head = curr_bd;

      /**
       * The earlier pbuf chain is freed from the upper layer. So, we need to
       * allocate a new pbuf chain and update the descriptors with the pbuf info.
       * To support chaining, the total length freed by the upper layer is tracked.
       * Care should be taken even if the allocation fails.
       */
      /**
       * now len_to_alloc will contain the length of the pbuf which was freed
       * from the upper layer
       */
      rxch->freed_pbuf_len += len_to_alloc;
      new_pbuf = pbuf_alloc(PBUF_RAW, (rxch->freed_pbuf_len), PBUF_POOL);

      /* Write the descriptors with the pbuf info till either of them expires */
      if(new_pbuf != NULL) {
        curr_bd = rxch->free_head;

        for(q = new_pbuf; (q != NULL) && (curr_bd != rxch->active_head); q = q->next) {
          curr_bd->bufptr = hdkif_swizzle_data((uint32)(q->payload));

          /* no support for buf_offset. RXBUFFEROFFEST register is 0 */
          curr_bd->bufoff_len = hdkif_swizzle_data((q->len) & 0xFFFF);
          curr_bd->flags_pktlen = hdkif_swizzle_data(EMAC_BUF_DESC_OWNER);

          rxch->freed_pbuf_len -= q->len;

          /* Save the pbuf */
          curr_bd->pbuf = q;
          last_bd = curr_bd;
          curr_bd = hdkif_swizzle_rxp(curr_bd->next);
        }

        /**
         * At this point either pbuf expired or no rxbd to allocate. If
         * there are no, enough rx bds to allocate all pbufs in the chain,
         * free the rest of the pbuf
         */
        if(q != NULL) {
          pbuf_free((struct pbuf *)q);
        }

        curr_tail = rxch->active_tail;
        last_bd->next = NULL;

        curr_tail->next = hdkif_swizzle_rxp(rxch->free_head);

        /**
         * Check if the reception has ended. If the EOQ flag is set, the NULL
         * Pointer is taken by the DMA engine. So we need to write the RX HDP
         * with the next descriptor.
         */
        if(hdkif_swizzle_data(curr_tail->flags_pktlen) & EMAC_BUF_DESC_EOQ) {
          EMACRxHdrDescPtrWrite(hdkif->emac_base, (uint32)(rxch->free_head), 0);
        }

        rxch->free_head  = curr_bd;
        rxch->active_tail = last_bd;
      }
    }
    curr_bd = rxch->active_head;
  }

  EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);
  EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_TX);
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好!

    您是否正在处理 UDP 接收数据包?
    由于接收到的缓冲区溢出、问题看起来很像。

    调用示例: 按 如下方式调用 udp_recv (struct udp_pcb * pcb、udp_recv_fn recv、void * recv_arg)函数。
    (void) udp_recv (PCB、OWNUDPReceive, NULL);


    其中 PCB 是
    struct udp_pcb* pcb;
    其中 OWNUDPReceive 是处理 UDP 数据包的用户函数、

    静态空 OWNUDPReceive (void *arg、struct udp_pcb * PCB、struct pbuf * p、struct ip_addr * addr、u16_t port)

    PROCESS (p->PAYLOAD);//PAYLOAD 是保存实际数据所在基地址的成员。
    pbuf_free (p);//别忘了调用此函数。

    其中 process()可以定义如下。
    空进程(uint8 *ptR)


    如果我们处理接收到的 UDP 数据包并连续释放缓冲区、那么我们可能不会以处理程序中的暂停结束。

    --

    谢谢、

    Jagadish。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢! 事实上,问题是缺乏释放 pbuf。

    为了添加更多上下文、为了帮助隔离之前的问题、我从回调函数内部移除了大部分有效负载、并释放了 pbuf。 现在一切似乎都运行良好。 谢谢!