OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 17960|回复: 20

LWIP数据量大时出现的问题

[复制链接]

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
发表于 2017-8-7 16:28:22 | 显示全部楼层 |阅读模式
10金钱
用的例程移植LWIP时在测试速度上限,设置的TCP_TMR_INTERVA也就是发送间隔是1ms,然后每次发送4000个字节来测试速度和稳定性,2000多字节的时候还好,但超过3000之后就开始各种出错了,发送速度也就止于1.4M左右了。

Assertion "tcp_write: arg == NULL (programmer violates API)" failed at line 382 in ..\LWIP\lwip-1.4.1\src\core\tcp_out.c
Assertion "pbuf_free: p->ref > 0" failed at line 650 in ..\LWIP\lwip-1.4.1\src\core\pbuf.c

出现上面这些错误必定会丢数据;
Assertion "pbuf_take: invalid buf" failed at line 974 in ..\LWIP\lwip-1.4.1\src\core\pbuf.c
出现这句错误传输必定会终止,但又能ping通。


这个问题困扰我很久了,尝试过在释放内存和分配内存时加关中断保护,可速度再上升之后还是会出错。
也尝试过修改opt.h和lwipopts.h里的参数,效果也不大甚至更差。

现请求各位熟读LWIP的同志们指点一下,谢谢了!

QQ截图20170807161953.png
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2017-8-7 16:31:21 | 显示全部楼层
而且当我传输数据的时候,掉电前的几次传输中,第一次传输是必定会出现
Assertion "pbuf_free: p->ref > 0" failed at line 650 in ..\LWIP\lwip-1.4.1\src\core\pbuf.c

Assertion "tcp_write: arg == NULL (programmer violates API)" failed at line 382 in ..\LWIP\lwip-1.4.1\src\core\tcp_out.c
错误的,但第二第三次就是偶尔会出现的,也就是说在运行过程第一次数据传输必定丢包,但全部传输完后执行第二和第三次的传输就是概率性丢包
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165352
金钱
165352
注册时间
2010-12-1
在线时间
2108 小时
发表于 2017-8-8 01:44:10 | 显示全部楼层
帮顶
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2016-4-22
在线时间
37 小时
发表于 2017-8-8 14:11:08 | 显示全部楼层
看看你其他的地方,有没有处理的不太好的,导致的错误,我觉得还是你的发送间隔太短了,上一次的数据还没有发送完成,就发送下一下的。改大一点试试呢
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2017-8-8 14:32:13 | 显示全部楼层
huoyancool 发表于 2017-8-8 14:11
看看你其他的地方,有没有处理的不太好的,导致的错误,我觉得还是你的发送间隔太短了,上一次的数据还没有 ...

改大了速度就降下来了,也就满足不了速度的要求;
当然改大了间隔同时也可以提升每次发送的数据大小来维持速度,但数据太大了似乎内存又不分配的不够,目前我也没有找出正确的分配内存或者修改参数的方法来保证每次可以发送足够大的数据。
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2017-8-8 14:36:44 | 显示全部楼层
huoyancool 发表于 2017-8-8 14:11
看看你其他的地方,有没有处理的不太好的,导致的错误,我觉得还是你的发送间隔太短了,上一次的数据还没有 ...

给你看一下我的iwipopts.h的配置以及内存配置,lwipopts.h里的MEM_SIZE设置稍微再大一点后在程序开始进行内存分配时就会出现分配错误,暂时还没搞懂为何。
2011111111.png
202222222222.png
303333333333.png
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2016-4-22
在线时间
37 小时
发表于 2017-8-8 14:44:56 | 显示全部楼层
大量发送数据的话,看用的什么函数 然后通过改变lwipopts.h 进行优化,我也是这么做的。这个还得看具体情况进行更改,我的参数跟你差别很大,我也是提升速度上尽力了
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2016-4-22
在线时间
37 小时
发表于 2017-8-8 14:46:16 | 显示全部楼层
本帖最后由 huoyancool 于 2017-8-8 14:47 编辑

#define MEM_SIZE                4096      
#define MEMP_NUM_PBUF           100              
#define MEMP_NUM_TCP_PCB        10            
#define MEMP_NUM_TCP_PCB_LISTEN 6            
#define MEMP_NUM_TCP_SEG        15               
//MEMP_NUM_TCP_SEG should > TCP_SND_QUEUELEN
#define MEMP_NUM_SYS_TIMEOUT    8               


#define PBUF_POOL_SIZE          20           
#define PBUF_POOL_BUFSIZE       2048      
//PBUF_POOL_SIZE * (PBUF_POOL_BUFSIZE - protocol headers) should >TCP_WND


#define LWIP_TCP                1                 
#define TCP_TTL                 255            

#undef TCP_QUEUE_OOSEQ
#define TCP_QUEUE_OOSEQ         0                 

#undef TCPIP_MBOX_SIZE
#define TCPIP_MBOX_SIZE         MAX_QUEUE_ENTRIES   

#undef DEFAULT_TCP_RECVMBOX_SIZE
#define DEFAULT_TCP_RECVMBOX_SIZE       MAX_QUEUE_ENTRIES  

#undef DEFAULT_ACCEPTMBOX_SIZE
#define DEFAULT_ACCEPTMBOX_SIZE         MAX_QUEUE_ENTRIES  


#define TCP_MSS                 (1500 - 40)                 
#define TCP_SND_BUF             (4*TCP_MSS)            
#define TCP_SND_QUEUELEN        (2* TCP_SND_BUF/TCP_MSS)      
#define TCP_WND                 (20*TCP_MSS)         
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2017-8-8 14:57:27 | 显示全部楼层
huoyancool 发表于 2017-8-8 14:46
#define MEM_SIZE                4096      
#define MEMP_NUM_PBUF           100              
#def ...

那你能稳定在多少的速度呢?
我用的是原子的网口例程中来发送数据的,程序有点多,不方便贴上来。
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2016-4-22
在线时间
37 小时
发表于 2017-8-8 15:06:32 | 显示全部楼层
这个我没有测过,应该是比你的慢,因为我中间对发送数据进行了处理,并行通信等,我的大致方法就是改lwipopts.h,然后看你的发送函数,数据是不是拷贝的,提高速度尽量减少拷贝
回复

使用道具 举报

9

主题

53

帖子

0

精华

初级会员

Rank: 2

积分
165
金钱
165
注册时间
2016-4-22
在线时间
37 小时
发表于 2017-8-8 15:09:02 | 显示全部楼层
原子例程中的函数用的是netconn_write(newconn ,SDataBuff,1026,NETCONN_COPY);我觉得这个参数可以用别的试试,我的暂时还能满足要求,所以没有继续调试,你有时间可以试一下,然后改下lwipopts.h中的参数试试
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2017-8-8 16:58:24 | 显示全部楼层
huoyancool 发表于 2017-8-8 15:09
原子例程中的函数用的是netconn_write(newconn ,SDataBuff,1026,NETCONN_COPY);我觉得这个参数可以用别的试 ...

这是例程源码


//lwIP tcp_poll的回调函数
err_t tcp_client_poll(void *arg, struct tcp_pcb *tpcb)
{
        err_t ret_err;
        struct tcp_client_struct *es;
        es=(struct tcp_client_struct*)arg;
        if(es!=NULL)  //连接处于空闲可以发送数据
        {
                if(tcp_client_flag&(1<<7))        //判断是否有数据要发送
                {
                        es->p=pbuf_alloc(PBUF_TRANSPORT, tcp_tsize,PBUF_POOL);
                        pbuf_take(es->p,(char*)tcp_client_sendbuf,tcp_tsize);        //暂时设置固定的1024字节,为了测试TCP读取SD卡传输速度
                        tcp_client_senddata(tpcb,es);//将tcp_client_sentbuf[]里面复制给pbuf的数据发送出去
                        tcp_client_flag&=~(1<<7);        //清除数据发送标志
                        if(es->p!=NULL)
                                if(es->p)pbuf_free(es->p);        //释放内存
                }else if(es->state==ES_TCPCLIENT_CLOSING)
                {
                        tcp_client_connection_close(tpcb,es);//关闭TCP连接
                }
                ret_err=ERR_OK;
        }else
        {
                tcp_abort(tpcb);//终止连接,删除pcb控制块
                ret_err=ERR_ABRT;
        }
        return ret_err;
}



//lwIP tcp_sent的回调函数(当从远端主机接收到ACK信号后发送数据)
err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
        struct tcp_client_struct *es;
        LWIP_UNUSED_ARG(len);
        es=(struct tcp_client_struct*)arg;
        if(es->p)tcp_client_senddata(tpcb,es);//发送数据
        return ERR_OK;
}




//此函数用来发送数据
void tcp_client_senddata(struct tcp_pcb *tpcb, struct tcp_client_struct * es)
{
        struct pbuf *ptr;
        err_t wr_err=ERR_OK;
        while((wr_err==ERR_OK)&&es->p&&(es->p->len<=tcp_sndbuf(tpcb))) //将要发送的数据加入到发送缓冲队列中
        {
                ptr=es->p;
                wr_err=tcp_write(tpcb,ptr->payload,ptr->len,1);
                if(wr_err==ERR_OK)
                {  
                        es->p=ptr->next;                        //指向下一个pbuf
                        if(es->p)pbuf_ref(es->p);        //pbuf的ref加一
                        pbuf_free(ptr);                                //释放ptr
                }else if(wr_err==ERR_MEM)es->p=ptr;
                tcp_output(tpcb);                //将发送缓冲队列中的数据立即发送出去****************
        }
}

回复

使用道具 举报

1

主题

10

帖子

0

精华

新手上路

积分
33
金钱
33
注册时间
2017-10-17
在线时间
3 小时
发表于 2018-1-2 11:09:44 | 显示全部楼层
你好  我想问问怎么测试速度上限
回复

使用道具 举报

4

主题

32

帖子

0

精华

初级会员

Rank: 2

积分
102
金钱
102
注册时间
2017-7-18
在线时间
29 小时
 楼主| 发表于 2018-1-3 17:28:15 | 显示全部楼层
xiarou123 发表于 2018-1-2 11:09
你好  我想问问怎么测试速度上限

我没有使用专门的软件或者工具或者程序测试,仅仅只是调整发送间隔、发送数据量来尝试性的摸出它的最大速度
回复

使用道具 举报

2

主题

7

帖子

0

精华

新手上路

积分
30
金钱
30
注册时间
2018-12-23
在线时间
8 小时
发表于 2019-1-8 10:16:38 | 显示全部楼层
楼主LWIP 用的是STM32F4系列吗?速度是1.2MB/s还是1.2Mbps?
回复

使用道具 举报

4

主题

28

帖子

0

精华

初级会员

Rank: 2

积分
86
金钱
86
注册时间
2019-1-9
在线时间
20 小时
发表于 2019-1-19 19:08:04 | 显示全部楼层
这个问题解决了吗,我现在H7上遇到了同样的问题
回复

使用道具 举报

13

主题

69

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
237
金钱
237
注册时间
2016-6-22
在线时间
50 小时
发表于 2019-2-22 21:47:43 | 显示全部楼层
可以修改PBUF_POOL_BUFSIZE大一些试试。
回复

使用道具 举报

1

主题

5

帖子

0

精华

新手上路

积分
23
金钱
23
注册时间
2019-6-9
在线时间
5 小时
发表于 2019-6-11 23:37:17 | 显示全部楼层
你们好 有谁知道Assertion "tcp_write: arg == NULL (programmer violates API)" failed at line 382 in ..\..\net\lwip\src\core\tcp_out.c这个打印输出的错误是什么原因引起的吗??
回复

使用道具 举报

2

主题

17

帖子

0

精华

新手上路

积分
29
金钱
29
注册时间
2016-1-15
在线时间
12 小时
发表于 2020-1-6 14:07:24 | 显示全部楼层
不拷贝数据,把buf开大些,这不就减少了SRAM的浪费了,就可以放更多的数据,能放更多数据,才可以提高速度。同时又避免了数据拷贝的时间,这也是间接的提高速度。

不用拷贝数据的方式,谁搞定了吗?

贴出代码来看看吧
回复

使用道具 举报

1

主题

2

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2020-2-10
在线时间
15 小时
发表于 2020-3-6 10:27:44 | 显示全部楼层
lr6410 发表于 2020-1-6 14:07
不拷贝数据,把buf开大些,这不就减少了SRAM的浪费了,就可以放更多的数据,能放更多数据,才可以提高速度 ...

我用了判断(发送完成后)才开始释放pbufs,这样不会出现pbuf_free 上的错误,但是会出现pbuf_take 的错误。
回复

使用道具 举报

22

主题

108

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
429
金钱
429
注册时间
2016-5-23
在线时间
118 小时
发表于 2020-10-9 14:02:35 | 显示全部楼层
GZW123 发表于 2020-3-6 10:27
我用了判断(发送完成后)才开始释放pbufs,这样不会出现pbuf_free 上的错误,但是会出现pbuf_take 的错误 ...

怎么判断发送完成,有代码吗
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-24 15:27

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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