硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1228|回复: 4
收起左侧

[以太网] h743动态网页卡死的故障

[复制链接]

12

主题

26

回帖

62

积分

初级会员

积分
62
发表于 2021-11-16 13:52:01 | 显示全部楼层 |阅读模式
本帖最后由 szttg 于 2021-11-16 14:24 编辑

原来在F407上运行的工程,迁移到h743后,发现动态网页无法显示,静态网页没有问题。
具体表现是在服务端给PC端传输网页的时候,有一个分段的包没有发出。这是在F407上抓的包,分为5段发出,网页显示正常。

407.png

这是在H743上抓的包,前2个段正常,第3个段没有发出,Wireshark提示前面的段没有捕捉到。

743.png



请大家指教,问题可能出在什么地方。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107338
QQ
发表于 2021-11-16 15:29:21 | 显示全部楼层
动态网页,你数说的是tcpnet里面的那种ajax吗
回复

使用道具 举报

12

主题

26

回帖

62

积分

初级会员

积分
62
 楼主| 发表于 2021-11-16 16:39:22 | 显示全部楼层
eric2013 发表于 2021-11-16 15:29
动态网页,你数说的是tcpnet里面的那种ajax吗

不是,就是带了些标签处理(SSI),需要用实际数据去替换。
打开调试信息,发现是是TCP的发送队列给填满了,达到了50项,每项4个字节。不知道哪来的这么多发送项,还在找。
回复

使用道具 举报

12

主题

26

回帖

62

积分

初级会员

积分
62
 楼主| 发表于 2021-11-17 14:20:20 | 显示全部楼层
确认是因为处理标签导致不正常,把标签功能关闭掉(定义LWIP_HTTPD_SSI为0),网页就可以正常显示。打开SSI功能后,就不正常。
回复

使用道具 举报

12

主题

26

回帖

62

积分

初级会员

积分
62
 楼主| 发表于 2021-11-19 09:09:05 | 显示全部楼层
本帖最后由 szttg 于 2021-11-19 09:17 编辑

找到问题所在了。我这个LWIP是1.3.1的版本,在 http_send_data() 函数中处理SSI标签时,多次调用http_write()写入内容,http_write() 调用 tcp_write() 往发送缓冲区写入时, 由tcp_euqueue()函数放入队列,都要分配 一个pbuf进行链接,虽然 总体长度不超过MSS(Max segment size), 但链拉的pbuf数量达几十个之多。正是这么多的pbuf导致 low_level_output函数判断pbuf超出DMA发送描述符数量 ,没有发出这个数据包,导致数据包缺失。
下面是low_level_output 的常见写法,这种处理方式,要求pbuf链的数量不能超过发送描述符数量。一旦超过,就直接返回,不进行发送。
err_t low_level_output(struct netif *netif, struct pbuf *p)
{
    uint32_t i=0;
    struct pbuf *q;
    err_t errval=ERR_OK;
    ETH_BufferTypeDef Txbuffer[ETH_TX_DESC_CNT];
        
          memset(Txbuffer, 0 , ETH_TX_DESC_CNT*sizeof(ETH_BufferTypeDef));
  
    for(q=p;q!=NULL;q=q->next)
    {
        if(i>=ETH_TX_DESC_CNT)       // 此句导致pbuf数量超出DMA发送描述符数量时直接返回
            return ERR_IF;

   
        Txbuffer.buffer=q->payload;
     Txbuffer.len=q->len;
                                 
        if(i>0)
        {
            Txbuffer[i-1].next=&Txbuffer;
        }
   
        if(q->next == NULL)
        {
            Txbuffer.next=NULL;
        }
        i++;
    }

    TxConfig.Length = p->tot_len;
    TxConfig.TxBuffer=Txbuffer;
                        

    SCB_CleanInvalidateDCache();    //无效化并清除Dcache
               
    errval = HAL_ETH_Transmit(D_Handle,&TxConfig, 20);
    if(HAL_OK != errval )
    {
         printf("low_level_output error: %d\r\n",errval);
     }
               
    return errval;
}

下面是改进后的写法,把所有的pbuf都拷贝进一个发送缓冲区内,这样就不会有任何问题了。uint8_t Tx_Buff[ETH_RX_BUFFER_SIZE];  // 发送缓冲区
static err_t low_level_output(struct netif *netif, struct pbuf *p)
{
    u16 total_len = 0;
    struct pbuf *q = p;
    err_t errval=ERR_OK;
    ETH_BufferTypeDef Txbuffer = {Tx_Buff, 0, 0};
               
      for (; q != NULL; q = q->next)
    {
      memcpy(&Tx_Buff[total_len], q->payload, q->len);
      total_len += q->len;
    }
               
   Txbuffer.len = total_len;
               
     TxConfig.Length = total_len;
    TxConfig.TxBuffer = &Txbuffer;
                        
    SCB_CleanInvalidateDCache();    //无效化并清除Dcache
               
    errval = HAL_ETH_Transmit(D_Handle,&TxConfig, 20);
    if(HAL_OK != errval )
  {
        printf("low_level_output error: %d\r\n",errval);
   }
               
    return errval;
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-27 02:21 , Processed in 0.242043 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表