mdz2011 发表于 2013-11-2 20:42:06

裸机STM32+LWIP1.3.2+DM9000A数据收发一段时间后卡住的问题

一、硬件平台及配置情况
CPU:STM32F103ZET
ETH:DM9000A
LWIP版本:1.3.2
开发板运行TCP服务端,IP为192.168.1.10端口为1026,PC运行TCP客户端,IP为192.168.1.2。
PC端测试软件为:网络调试助手 V3.7
软件运行时选择tcpclient模式,连接到服务器的IP为192.168.1.10端口为1026,能够连接成功。
然后以十六进制数据流(发送间隔500ms)发送0xaa 0x01 0x02 0x03,没法送一次以上数据,接收端就会收到4096字节数据。

二、问题描述
问题是运行几分钟后就只有发送没有接收了,也ping不通了。

三、上代码

//-----------------------------------------------------------------------------
// 入口
//-----------------------------------------------------------------------------
int main(void)
{
        SystemInit();
        LED_Config();
        InitUsart(115200);
        LwIpInit();
        LED_Loop();
        Tcp_Server_Init();
        SysTick_Config(72000000/1000);
        printf(        "Lwip TcpServer Started
"\n                        "Server IP:192.168.1.10
"\n                        "Server Port:1026

"
                  );
        while (1)
        {
                ethernetif_input(&netif);// 读取eth的数据包
                LwIP_Periodic_Handle(SystermTime);// tcp老化处理(250ms跟5000ms的tcp老化程序)
                if(1 == ETH_RX_CMP)
                {
                        ETH_RX_CMP = 0;
                        Eth_Data_Handle();
                }
        }
}

//-----------------------------------------------------------------------------
// 接收到数据解析
//-----------------------------------------------------------------------------
static void Eth_Data_Handle(void)
{
        if(eth_rev_buff == 0x01)
        {
                if(eth_send_ok == 1)
                {
                        Eth_Send(eth_send_buff,4096);
                        eth_send_ok = 0;
                }
        }
        th_rev_buff = 0;
}

//-----------------------------------------------------------------------------
// 初始化
//-----------------------------------------------------------------------------
void Tcp_Server_Init(void)
{
   struct tcp_pcb *pcb;

   /* Create a new TCP control block*/
   pcb = tcp_new();
   
   /* Bind the pcb to the port */
   /* Using IP_ADDR_ANY allow the pcb to be used by any local interface */
   tcp_bind(pcb, IP_ADDR_ANY, 1026);
                                                                                     
   pcb = tcp_listen(pcb);                                // 将此tcp连接移至侦听tcp队列中去      
   tcp_accept(pcb, tcp_server_accept);        // 初始化pcb->accept
}

//-----------------------------------------------------------------------------
// 回调函数 连接响应
//-----------------------------------------------------------------------------
err_t tcp_server_accept(void *arg, struct tcp_pcb *pcb,err_t err)
{
        tcp_server_pcb = pcb;                                // 将此PCB保存
        tcp_setprio(pcb,TCP_PRIO_MIN);
        tcp_recv(pcb,tcp_server_recv);
        tcp_write(pcb,Connect_data,sizeof(Connect_data),0);
        tcp_output(pcb);                                        // 立即发送数据
        tcp_sent(tcp_server_pcb,tcp_sended);// 发送成功后本函数的回调函数会被调用
        err = ERR_OK;
        return err;
}

//-----------------------------------------------------------------------------
// 回调函数 接收数据
//-----------------------------------------------------------------------------
err_t tcp_server_recv(void *arg, struct tcp_pcb *pcb,struct pbuf *p,err_t err)
{
        unsigned int i;
        tcp_server_pcb = pcb;                                // 将此PCB保存
        if(p != NULL)
        {
                eth_rev_len = p->len;
                if(eth_rev_len <= 1024)
                {
                        for(i=0;i<eth_rev_len;i++)
                        {
                                eth_rev_buff=*((char *)p->payload+i);
                        }                       
                        tcp_recved(pcb,eth_rev_len);
                        ETH_RX_CMP = 1;        // 收到数据了
                }   
        }
        pbuf_free(p);                         // 释放PBUF
        err = ERR_OK;
        return err;
}

//-----------------------------------------------------------------------------
// 回调函数 数据发送成功
//-----------------------------------------------------------------------------
err_t tcp_sended(void *arg, struct tcp_pcb *pcb,u16_t len)
{
//        printf("Data Sended Len = %d
",len);
        Init_Data();
        eth_send_ok = 1;
        return ERR_OK;
}

//-----------------------------------------------------------------------------
// ETH发送
//-----------------------------------------------------------------------------
void Eth_Send(unsigned char *p,unsigned int len)
{
        tcp_write(tcp_server_pcb,p,len,0);                // 放入队列 最大字节在“lwipopt.h”中设置
        tcp_output(tcp_server_pcb);                                // 立即发送
        tcp_sent(tcp_server_pcb,tcp_sended);        // 发送成功后本函数的回调函数会被调用
}

//-----------------------------------------------------------------------------
// 生成数据
//-----------------------------------------------------------------------------
void Init_Data(void)
{
        unsigned int i;

        for(i=0;i<4096;i++)
        {
                eth_send_buff = i;
        }
        eth_send_buff = 0xAA;
        eth_send_buff = 0xAA;
        eth_send_buff = 0x10;
        eth_send_buff = 0x00;
}

//-----------------------------------------------------------------------------
// 系统滴答
//-----------------------------------------------------------------------------
void SysTick_Handler(void)
{
        SystermTime++;       
}

//-----------------------------------------------------------------------------
// TCP老化
//-----------------------------------------------------------------------------
void LwIP_Periodic_Handle(__IO uint32_t localtime)
{
        /* TCP periodic process every 250 ms */
        if ((localtime - TCPTimer) >= 250)//TCP_TMR_INTERVAL)               
        {
            TCPTimer =localtime;
//                printf("TCPTimer = %d\n",TCPTimer);
            tcp_tmr();
                        /* ARP periodic process every 5s */
                  if ((localtime - ARPTimer) >= 5000)//ARP_TMR_INTERVAL)
                  {
                  ARPTimer =localtime;
//                        printf("ARPTimer = %d\n",ARPTimer);
                  etharp_tmr();
                  }
        }
}

mdz2011 发表于 2013-11-3 14:10:14

希望我的帖子不要沉了

lyzhangxiang 发表于 2013-11-4 08:35:10

楼主你的tcp老化是什么意思

收发都是靠eth_send_buff、eth_rev_buff吗   

建议驱动参考rtt的,那个驱动写的还可以我移植过freertos下lwip很稳定的说

mdz2011 发表于 2013-11-4 12:55:05

lyzhangxiang 发表于 2013-11-4 08:35 static/image/common/back.gif
楼主你的tcp老化是什么意思

收发都是靠eth_send_buff、eth_rev_buff吗   


1、TCP老化是指每250ms 调用tcp_tmr();每5000ms调用etharp_tmr();
2、收发都是用的eth_send_buff、eth_rev_buff,不拷贝。

image056 发表于 2013-11-10 22:10:24

请问 我做的 Dm9000AEP为什么读取MRCMDX中的数据数据帧的长度信息是高地址在前,低地址在后?   可是从数据手册上看是低地址在前呀?

qftek 发表于 2013-11-11 05:56:00

建议使用MICREL KSZ8851SNL 。

做2个实验:
1. 不插网线,系统启动完成之后,插网线,拔网线,连续插拔100次,看看网络link 成功次数。
2. 2KV 4KV静电打击测试

比较一下你使用的芯片与MICRELSMSC公司网络接口芯片的区别。

qftek 发表于 2013-11-13 07:13:23

研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl,SPI 接口,线路简单,接口稳定性好。或者选用SMSC LAN9221之类的。
在稳定性及可用性方面比台系芯片强很多。并且相应的软件资源更丰富.

做出来的产品4KV 静电干扰测试,台系芯片抗静电性能与美系芯片性能比较?
不插网线,系统加电启动完成后,再插网线,看是否能正常连接,反复插拔网线,看看哪一家芯片每次都可以正常连接 ?

工控产品选美系的绝对是节约成本,减少系统维护成本。

fengyunyu 发表于 2013-11-13 09:40:51

qftek 发表于 2013-11-13 07:13 static/image/common/back.gif
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl,SPI 接口,线路简单,接口稳定性好。或 ...

micrel ksz8851snl,选工业级的话,有点贵。

qftek 发表于 2013-11-14 10:51:40

fengyunyu 发表于 2013-11-13 09:40 static/image/common/back.gif
micrel ksz8851snl,选工业级的话,有点贵。

工业级选哪家的会便宜呢 ? 再说台系的所谓工业级芯片根本就是与商用芯片同一条产品线生产出来的,你实际测试真的能达到工业级吗 ?

美系芯片 工业级一定是工业级,不会忽悠的。

严重建议:
MICREL KSZ8851SNL 性能、价格比台系芯片强很多,特别插拔不能link的bug不存在。另外SPI接口,硬件线路及软件驱动都容易。

WIZNET W5500 ,硬件集成TCP/IP协议栈。不要哪么费心费力去调试uIP lwIP之类的东东,硬件SPI接口,线路简单。

还有SMSC的相关芯片,性能超强。

哪些用台系芯片的,要好好考虑一下芯片BUG,及原厂及代理商是否能出质量承诺书,及硬件软件的复杂程度。有更好的,为什么选它 ?

mfkqqw 发表于 2015-9-2 10:22:42

qftek 发表于 2013-11-13 07:13
研究学习用台系芯片可以,但真正做产品,推荐用micrel ksz8851snl,SPI 接口,线路简单,接口稳定性好。或 ...

我用的是DM9000,4KV 静电干扰测试OK了,100次插拔也可以PING ,系统上电后再插也OK。求给个解释。
页: [1]
查看完整版本: 裸机STM32+LWIP1.3.2+DM9000A数据收发一段时间后卡住的问题