搜索
bottom↓
回复: 21

[2016-04-12已解决,芯片BUG]Lwip RAW模式TCP发送数据阻塞

[复制链接]

出0入0汤圆

发表于 2016-3-23 23:38:34 | 显示全部楼层 |阅读模式
本帖最后由 xivisi 于 2016-4-12 16:18 编辑

2016-04-12:
终于发现问题所在,使用的处理器有缺陷,外置SDRAM居然不允许ARM核和DMA同时访问(仅内置SRAM支持,日了狗了),芯片缺陷手册居然没有对应描述。调整软件构架、精简内存占用,已解决。

2016-04-07:
昨晚继续进行测试,刚刚发现连接断开,经查,PCB出现了死循环:



、==================================================================

2016-04-06:
        仅协议栈和协议栈相关层代码的情况下:回环、单发、单收均无问题,一加上同事的应用层代码,就出现之前的问题(我的代码几乎没有任何修改)。目前只能判定,同事的代码有问题;
        
===========================================================================================================

目前在调一个 LWIP RAW TCP发送代码,  单词发送的数据量比较大,目前48KB;

目前故障现象:发送成功一个包之后,发现该pcb的发送缓存一直满,再也不能发送数据,求助

以下是发送函数的代码:
  1. <i>err_t app_net_connect_send(connect_t *connect)
  2. {
  3.         err_t                                 result;
  4.         connect_txdata_t        *txdata;
  5.         uint32_t                        buf_len, ipc_len, tx_send, write_len;
  6.         struct tcp_pcb                 *tpcb;

  7.         txdata = connect->tx_work;        //获取正在发送的数据块
  8.         if(txdata == NULL)                        //如果没有正在发送的数据
  9.         {
  10.                 //从等待发送的链表中取出一个数据块
  11.                 txdata = (connect_txdata_t*)list_fifo_remove(&connect->tx_ready);
  12.                 if(txdata) //如果数据块存在
  13.                 {
  14.                         //标记为正在发送的数据块
  15.                         connect->tx_work = txdata;
  16.                         //预先放入完成队列,由TCP接收回调函数处理
  17.                         list_fifo_insert(&connect->tx_finish, &txdata->link);
  18.                 }
  19.                 else return ERR_OK;
  20.         }
  21.         //取出pcb
  22.         tpcb = connect->pcb;
  23.         assert(tpcb == NULL);
  24.         //计算剩余发送数据的长度
  25.         ipc_len = txdata->length;
  26.         tx_send = txdata->tx_send;
  27.         write_len = ipc_len - tx_send;
  28.         
  29.         if(write_len)
  30.         {
  31.                 //使发送数据的长度不超过,TCP发送缓存
  32.                 buf_len = tcp_sndbuf(tpcb);
  33.                 if(write_len > buf_len) write_len = buf_len;
  34.                 //数据加入发送队列
  35.                 result = tcp_write(tpcb, &txdata->data[tx_send], write_len, 1);
  36.                 if(result != ERR_OK) return result;
  37.                 //强制数据立即发送
  38.                 tcp_output(connect->pcb);
  39.                 tx_send += write_len;
  40.         }
  41.         //如果所有数据已交给协议栈,认为当前数据块已发送完毕
  42.         if(tx_send == txdata->length) connect->tx_work= NULL;
  43.         //否则只记录发送数据大小
  44.         else txdata->tx_send = tx_send;
  45.         
  46.         return ERR_OK;
  47. }</i>
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2016-3-24 09:23:56 | 显示全部楼层
更换老版本lwip1.3.2问题依旧,  代码操作问题,或配置不正确的可能性比较大
相关配置如下:
  1. #ifndef __LWIPOPTS_H__
  2. #define __LWIPOPTS_H__


  3. #define SYS_LIGHTWEIGHT_PROT                                    0
  4. #define NO_SYS                                                  1
  5. #define NO_SYS_NO_TIMERS                                        1
  6. #define MEM_ALIGNMENT                                                  4
  7. //#define ETH_PAD_SIZE                                                        2

  8. #define MEM_LIBC_MALLOC                                       1
  9. #if !MEM_LIBC_MALLOC
  10.         #define MEM_USE_POOLS                                                0
  11.         #if MEM_USE_POOLS
  12.                 #define MEM_USE_POOLS_TRY_BIGGER_POOL        0
  13.                 #define MEM_USE_CUSTOM_POOLS                         0
  14.                 #define MEMP_USE_CUSTOM_POOLS                        0
  15.                 #define MEMP_SEPARATE_POOLS                                0
  16.         #else
  17.                 #define MEM_SIZE                        (4*1024*1024)
  18.         #endif
  19. #endif

  20. #define MEMP_NUM_PBUF                   4096
  21. #define MEMP_NUM_UDP_PCB                4
  22. #define MEMP_NUM_SYS_TIMEOUT        300

  23. #define PBUF_POOL_SIZE                  512
  24. #define PBUF_POOL_BUFSIZE               1536

  25. #define LWIP_RAW                        1
  26. #define LWIP_NETIF_HOSTNAME             1
  27. #define LWIP_BROADCAST_PING             1

  28. #define LWIP_TCP                        1
  29. #define MEMP_NUM_TCP_PCB                32
  30. #define MEMP_NUM_TCP_PCB_LISTEN         2
  31. #define MEMP_NUM_TCP_SEG                (TCP_SND_QUEUELEN+64)
  32. #define TCP_TTL                         255
  33. #define TCP_QUEUE_OOSEQ                 0
  34. #define TCP_MSS                         (1460)
  35. #define TCP_SND_BUF                     (8*TCP_MSS)
  36. #define TCP_SND_QUEUELEN             ((16*(TCP_SND_BUF)+(TCP_MSS-1))/(TCP_MSS))

  37. #define LWIP_ICMP                   1
  38. #define LWIP_DHCP                       0

  39. #define LWIP_UDP                                1
  40. #define UDP_TTL                         255

  41. #define LWIP_SOCKET                 0
  42. #define LWIP_NETCONN                0
  43. #define LWIP_STATS                  0
  44. #define LINK_STATS                  0
  45. #define LWIP_STATS_DISPLAY          0

  46. #define LWIP_PROVIDE_ERRNO                         1
  47. #define LWIP_NETIF_LINK_CALLBACK    0
  48. #define LWIP_NETCONN                0
  49. #define LWIP_SOCKET                 0

  50. #include <stdlib.h>

  51. #define LWIP_DEBUG                        0
  52. #define TCP_OUTPUT_DEBUG         LWIP_DBG_OFF

  53. #endif /* __LWIPOPTS_H__ */
复制代码

出0入0汤圆

 楼主| 发表于 2016-3-24 11:48:33 | 显示全部楼层
自己顶                           

出0入0汤圆

 楼主| 发表于 2016-3-29 11:20:18 | 显示全部楼层
回环模式:接收时拷贝到接收队列,在大循环中调用楼主位发送函数;测试发送 600K的文件,无问题;

但是取消回环模式,加上应用代码(确认应用数据已加入发送队列),立马歇菜。

出0入0汤圆

 楼主| 发表于 2016-3-29 12:56:11 | 显示全部楼层
更改回环模式:只要接收到任意数据,则持续不断向外每次发送100K数据(相对于发送缓冲,对应于connect->tx_ready这个fifo队列),测试无问题……

出0入0汤圆

发表于 2016-3-29 14:04:22 | 显示全部楼层
不用tcp_output试试,因为raw模式下延时到了自己会发送数据,而tcp_output很可能在协议栈的回调函数里操作协议栈的流程,我认为很可能就会破坏协议的完整性

出0入0汤圆

 楼主| 发表于 2016-3-29 14:10:57 | 显示全部楼层
myxiaonia 发表于 2016-3-29 14:04
不用tcp_output试试,因为raw模式下延时到了自己会发送数据,而tcp_output很可能在协议栈的回调函数里操作 ...

我不是在回调函数里面调用 tcp_output

出0入0汤圆

 楼主| 发表于 2016-3-29 14:28:03 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-29 14:30 编辑




抓包,传输终止的地方,没看出异常……

LWIP:192.168.1.115
PC        : 192.168.1.107

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

 楼主| 发表于 2016-3-29 14:42:44 | 显示全部楼层
修改发送缓冲大小、增大对应的pbuf数量,目前不阻塞于发送函数tcp_write;
但是,在发送完成函数中(由tcp_sent指定的回调函数),并没有收到对应数量的应答。LWIP 未收到  ACK响应?

出0入0汤圆

发表于 2016-3-29 15:31:23 | 显示全部楼层
xivisi 发表于 2016-3-29 14:10
我不是在回调函数里面调用 tcp_output

你以上所发的函数不是发送回调函数吗 这个函数是在什么情况下调用的

出0入0汤圆

 楼主| 发表于 2016-3-29 15:34:49 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-29 15:36 编辑
myxiaonia 发表于 2016-3-29 15:31
你以上所发的函数不是发送回调函数吗 这个函数是在什么情况下调用的


发送回调函数是由tcp_sent(pcb, app_net_connect_sent);设置的,我的
回调函数是:app_net_connect_sent;
发送函数是:app_net_connect_send,这个很明显是其他任务产生的数据进,在大循环了调用(与 sys_check_timeouts() 平齐);

  1. err_t app_net_connect_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
  2. {
  3.         uint32_t                        tx_sent;
  4.         connect_t                        *connect;
  5.         connect_txdata_t        *txdata;
  6.         error_t                                result;
  7.        
  8.         connect = (struct connect_t *)arg;
  9.         assert(connect == NULL);
  10.        
  11.         txdata = (connect_txdata_t*)list_fifo_get_first(&connect->tx_finish);
  12.         assert(txdata == NULL);
  13.        
  14.         tx_sent = txdata->tx_sent;
  15.         tx_sent += len;
  16.         while(tx_sent >= txdata->length)
  17.         {
  18.                 result = app_ipc_net_tx_finish(connect->id, txdata->data, txdata->length, tx_sent);
  19.                 if(result == ERR_NORMAL)
  20.                 {
  21.                         list_fifo_remove(&connect->tx_finish);
  22.                         list_single_insert_first(&net.list_free, &txdata->link);
  23.                 }
  24.                 tx_sent -= txdata->length;
  25.                 txdata = (connect_txdata_t*)list_fifo_get_first(&connect->tx_finish);
  26.         }
  27.        
  28.         if(txdata) txdata->tx_sent = tx_sent;

  29.         return ERR_OK;
  30. }
复制代码


出0入0汤圆

发表于 2016-3-29 15:44:19 | 显示全部楼层
app_net_connect_sent只有list操作吗  我没有看到真实的发送操作

一般lwip的raw流程,都是要在lwip协议里通过回调函数的形式操作的,你可以看看rtt的lwip的netio程序,那里就是完全的此类做法

出0入0汤圆

 楼主| 发表于 2016-3-29 16:06:08 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-29 16:09 编辑
myxiaonia 发表于 2016-3-29 15:44
app_net_connect_sent只有list操作吗  我没有看到真实的发送操作

一般lwip的raw流程,都是要在lwip协议里 ...


如果像你说的那样,那发送数据的回调函数怎么触发???
操作队列的目的是,保证发送的数据被对方接收到之后,释放对应的内存。

出0入0汤圆

 楼主| 发表于 2016-3-30 10:41:38 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-30 10:47 编辑
myxiaonia 发表于 2016-3-29 15:44
app_net_connect_sent只有list操作吗  我没有看到真实的发送操作

一般lwip的raw流程,都是要在lwip协议里 ...


死马当活马医,更改了操作模式,依然有些问题;
并且速度暴降到原来的1/10

出0入0汤圆

 楼主| 发表于 2016-3-30 12:33:19 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-30 12:34 编辑

抓取到一个错误,但是可恢复:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入0汤圆

发表于 2016-3-30 13:10:29 | 显示全部楼层
xivisi 发表于 2016-3-29 16:06
如果像你说的那样,那发送数据的回调函数怎么触发???
操作队列的目的是,保证发送的数据被对方接收到 ...

lwip有个帮助文件,rawapi.txt 貌似是这个

发送回调函数什么时候调用,那里有讲解,一般会在发送缓冲区有空的时候,也就是收到对方确认应答后自动回调  
也可以调用tcp_write发送,不过要保证协议完整性,协议栈的函数基本上都是不可重入的你得有这个前提
裸机模式下在中断中调用就必须小心,带os的话通过api把此函数调用推入到lwip线程执行

出0入0汤圆

 楼主| 发表于 2016-3-30 13:17:43 | 显示全部楼层
本帖最后由 xivisi 于 2016-3-30 13:21 编辑
myxiaonia 发表于 2016-3-30 13:10
lwip有个帮助文件,rawapi.txt 貌似是这个

发送回调函数什么时候调用,那里有讲解,一般会在发送缓冲区 ...


4楼已说明,在主程序大循环调用。

对于接收数据也是在大循环里调用,没有使用任何中断,没有使用操作系统。

回调函数仅处理已发送数据,这样实现异步逻辑,加快发送速度。非回调函数调用 tcp_write 需要调用tcp_output实现立即发送。

出0入0汤圆

 楼主| 发表于 2016-3-31 09:04:06 | 显示全部楼层
调整配置选项,TCP层无用。后来找默认配置里面,IP层发送相关配置,成功。昨晚跑了一晚上OK!

出0入0汤圆

 楼主| 发表于 2016-4-6 17:36:45 | 显示全部楼层
问题,又出现了。。。。。。。

出0入0汤圆

 楼主| 发表于 2016-4-7 09:53:59 | 显示全部楼层
抓到BUG一只

出0入0汤圆

 楼主| 发表于 2016-4-12 16:19:05 | 显示全部楼层
已解决         

出0入0汤圆

发表于 2019-9-3 10:42:57 | 显示全部楼层
请问是什么BUG,如何解决,我也遇到了和你一样的现象
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 12:47

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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