xiaoshen-372360 发表于 2019-1-28 10:01:02

关于STM32+LWIP通信12次无法再次通信的问题【已解决】

本帖最后由 xiaoshen-372360 于 2019-4-19 13:45 编辑

各位大佬,小弟在尝试移植LWIP+FREERTOS的时候出现了如下问题,请各位大佬帮忙看看是哪里的问题,我用了FreeRTOS+LWIP做ModbusTCP时出现了链接出现通信12次然后通信中断,并且再也没法ping 通的问题,表现的现象是进不去以太网中断,导致 ethernetif_input()接收不到数据
移植过程是这样的:(STM32F407+DP83848)

1:首先移植RTOS+固件库,移植成功,并且跑了几个串口通信的任务,测试大概两三天的样子,并没有出现问题。
2:移植LWIP1.4.1 (从ST官网下载的那个网页的例程,修改引脚定义后跑在板子上没问题,确认硬件没问题)
3:将ST官网的LWIP1.4.1 的例子(关于LWIP的部分)移植到步骤1 的FreeRTOS 系统的工程里面,只是添加LWIP初始化的任务,并没有调用任何接口的情况下可以Ping 通 而且长时间Ping 也没问题。
4:调用一个连接,编写函数,将受到的数据发送回去,出现了通信12次就没法在通信的问题(发12次,收12次,通信数据包无论长短,都是12次)而且ping 也ping 不通了。
5:自己写了Modbus-TCP的代码,也是同样的通信12次,也没法通信了,
请教各位大佬,有遇到过类似的情况吗?

查了寄存器,发现PHY寄存器所有状态正常,查看DMA的寄存器,发现以太网DMA状态寄存器存在以下问题


然后查了ST的参考手册,手册的解释是这样的,






尝试解决方法:
1:关于LWIPethernetif_input 的问题,网上的解决方式已经尝试过了,这个地方也修改了,

void ethernetif_input( void * pvParameters )
{
struct pbuf *p;

for( ;; )
{
if (xSemaphoreTake( s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE)
{
TRY_GET_NEXT_FRAGMENT:
p = low_level_input( s_pxNetIf );
if(p!=NULL)
{
if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf))
{
pbuf_free(p);
p=NULL;
}
else
{
xSemaphoreTake(s_xSemaphore,0);
goto TRY_GET_NEXT_FRAGMENT;
}
}
}
}
} 主程序代码是这个样子的
void Modbus_TCP_Tasks(void * pvParameters)
{

struct netconn *conn, *newconn;
int i=0;
err_t err, accept_err;
struct netbuf *buf;
void *data;
u16_t len;
unsigned char *tmpP=NULL;
err_t recv_err;
//--初始化---LWIP协议栈---
ETH_BSP_Config();
LwIP_Init();
MB_TCP_Data_Init();//--协议栈初始化--
// LWIP_UNUSED_ARG(arg);
/* Create a new connection identifier. */
conn = netconn_new(NETCONN_TCP);
err = netconn_bind(conn, NULL, 502);
netconn_listen(conn);
accept_err = netconn_accept(conn, &newconn);
netconn_delete(conn); //删除侦听的连接。
while (1)
{
recv_err = netconn_recv(newconn, &buf);
if ( recv_err == ERR_OK)
{
do
{
netbuf_data(buf, &data, &len);
//--netconn_write(newconn, data, len, NETCONN_COPY);
}
while (netbuf_next(buf) >= 0);
//--拷贝数计--以及数据长度
for(i=0;buf->p!=NULL;buf->p=buf->p->next)//--非空则继续--
{
memcpy((unsigned char *)&TCP_Data,buf->p->payload,buf->p->len);
i=i+buf->p->len;
}
netbuf_delete(buf);
{
//--正式开始处理Modbus-TCP 数据--
if((TCP_Data==0)&&(TCP_Data==0))//--查看该数据帧是否为Modbus-TCP数据--
{
MB_TCP_Struct.MB_TCP_Rx_Len=len;//--获取数据长度--
for(i=0;i<6;i++)
{
MB_TCP_Struct.MB_MBAP_Data=TCP_Data;
}
//--开始数据拷贝的工作 拷贝的数据应当从第7个数据开始,
for(i=0;i<(MB_TCP_Struct.MB_TCP_Rx_Len-6);i++)
{
MB_TCP_Struct.MB_RxData=TCP_Data;
}
MB_TCP_Struct.MB_TCP_Rx_Len=i;
//--开始计算CRC
MB_TCP_Struct.CRC_Data=usMBCRC16(MB_TCP_Struct.MB_RxData,MB_TCP_Struct.MB_TCP_Rx_Len );
MB_TCP_Struct.MB_RxData = (MB_TCP_Struct.CRC_Data&0xff);
MB_TCP_Struct.MB_RxData = ((MB_TCP_Struct.CRC_Data>>8)&0xff);
MB_TCP_Struct.MB_RxData_Len=MB_TCP_Struct.MB_TCP_Rx_Len+2;//--加上CRC的数据长度--

MB_TCP_Process(&MB_TCP_Struct);
//--然后完成TCP的组包工作---最后发送--需要消除CRC校验-2-
//--待添加---
//--填充TCP的MBAP数据--按照协议标准是需要直接复制前 4位
for(i=0;i<6;i++)
{
MB_TCP_Struct.MB_TCP_TxData=MB_TCP_Struct.MB_MBAP_Data;
}
MB_TCP_Struct.MB_TCP_TxData=((MB_TCP_Struct.MB_TxData_Len>>8)&0xff);
MB_TCP_Struct.MB_TCP_TxData=(MB_TCP_Struct.MB_TxData_Len&0xff);
//--开始复制数据--
for(i=0;i<MB_TCP_Struct.MB_TxData_Len-2;i++)
{
MB_TCP_Struct.MB_TCP_TxData=MB_TCP_Struct.MB_TxData;
}
//--修改TCP的数据发送长度--需要减去CRC的数据--
MB_TCP_Struct.MB_TCP_Tx_Len=MB_TCP_Struct.MB_TxData_Len+4;
//--TCP 发送---
netconn_write(newconn, MB_TCP_Struct.MB_TCP_TxData, MB_TCP_Struct.MB_TCP_Tx_Len, NETCONN_COPY);
}
else//--释放内存--
{
free(TCP_Data);
}
}


}
/* Close connection and discard connection identifier. */
// netconn_close(newconn);
// netconn_delete(newconn);
}
}

通信现象:
1:没有使用Modbus-PULL 链接之前 Ping通没问题(不是都在1ms以内,不止是否有问题)偶尔ping的时间会比较长,但是从来没掉过包。


2:使用Modbus-Pull链接,通信12次之后无法Ping通,



无论是使用Modbus-Pull 还是开始说的只是来回发送数据都是这个样子,都是通信12次都没法在通信了,而且Ping也显示超时,请问格纹大佬,有遇到过这个问题么?还望大佬指教一二,小弟不胜感激!!!!!


fjasio 发表于 2019-1-29 10:11:54

断开连接,然后释放内存 试试

fjasio 发表于 2019-1-29 10:16:55

tcp连接有长连接和短连接:长连接的话,建立一次连接就行,以后只发送数据;短连接,每次数据发送完,都需要释放内存(控制块)

xiaoshen-372360 发表于 2019-1-30 11:36:01

fjasio 发表于 2019-1-29 10:16
tcp连接有长连接和短连接:长连接的话,建立一次连接就行,以后只发送数据;短连接,每次数据发送完,都需 ...

我是使用的长连接模式,建立连接之后就不再侦听端口了,然后就是每次读取完了之后我都释放了接受的缓存了的。但是还是这个样子,

fjasio 发表于 2019-1-31 10:44:48

xiaoshen-372360 发表于 2019-1-30 11:36
我是使用的长连接模式,建立连接之后就不再侦听端口了,然后就是每次读取完了之后我都释放了接受的缓存了 ...

460189483,可以加到这个群问问,记得代码贴出来

xiaoshen-372360 发表于 2019-4-9 11:08:46

自己顶一下,还是没解决啊!!!

wofei1314 发表于 2019-4-15 16:13:51

xiaoshen-372360 发表于 2019-4-9 11:08
自己顶一下,还是没解决啊!!!

自己移植的吗?(section(".RxDecripSection")有没有设置sct文件中对应的地方

xiaoshen-372360 发表于 2019-4-15 16:46:39

wofei1314 发表于 2019-4-15 16:13
自己移植的吗?(section(".RxDecripSection")有没有设置sct文件中对应的地方

这个只是移植了LWIP加RTOS系统的东西,也没有涉及到改SCT文件,除非你需要做IAP,需要修改Flash地址之外,还需要修改中断向量表对应的地址。

wofei1314 发表于 2019-4-15 21:57:15

xiaoshen-372360 发表于 2019-4-15 16:46
这个只是移植了LWIP加RTOS系统的东西,也没有涉及到改SCT文件,除非你需要做IAP,需要修改Flash地址之外 ...

RW_IRAM2 0x24000000 0x00080000{; RW data
   .ANY (+RW +ZI)
}
RW_DMARxDscrTab 0x30040000 0x60 {
*(.RxDecripSection)
}
RW_DMATxDscrTab 0x30040060 0x140 {
*(.TxDecripSection)
}
RW_Rx_Buffb 0x30040200 0x1800 {
*(.RxArraySection)
}

xiaoshen-372360 发表于 2019-4-16 09:01:09

wofei1314 发表于 2019-4-15 21:57


这个是在C文件定义RAM空间导致的,ETH的接受和发送缓存都是在固定RAM地址区间进行的。
页: [1] 2
查看完整版本: 关于STM32+LWIP通信12次无法再次通信的问题【已解决】