This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C1294NCPDT: ethernet connection break down after 2/3 hours sending data

Part Number: TM4C1294NCPDT

Hello All,

I have been trying to send data over ethernet to tcp server from my device/gateway. After one time connection  with server and my device, I am sending data without close connection. I got the socket information in tcp_echoclient_connected like es2 and tpcbSa. After I got the socket info, I use this info in the tcp_echoserver_send3 function. thus I am able to send all data every 5second. But After 2/3 hours wr_err returns ERR_MEM. and then stop sending data. I want to send data over ethernet without stopping every 5 second. I thought after returned ERR_MEM, I send request with tcp_write function. but it didnt work out.

So,

-why wr_err returns ERR_MEM after 2/3 hours? how to I avoid this?

or

-after return ERR_MEM, what should I do to return ERR_OK or continue to send data?

Do you have any idea or advice to solve this problem?

thank you 

BR 

Bekir

        //
        //  Connect to host address
        //
        if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_2 )
        {
            tcp_echoclient_connect(Gateway.Host_Address,Gateway.Remote_Port_Number);
        }
        else if(ETH_Ctrl.eth_data_repeat == ETH_REPEAT_1)
        {
            memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length);

            tcp_echoserver_send3(tpcbSa, (unsigned char*)data, sizeof(data), es2);
        }

void tcp_echoclient_connect(char* IP_ARR,char* PORT_NUM)
{
    {
        /* create new tcp pcb */
        echoclient_pcb = tcp_new();
        if (echoclient_pcb != NULL)
        {
            ETH_Ctrl.eth_data_repeat = ETH_REPEAT_1;
            ipaddr_aton((const char *)IP_ARR,&DestIPaddr);
            DestPORTAddr = atoi(PORT_NUM);

            /* connect to destination address/port */
            tcp_connect(echoclient_pcb,&DestIPaddr,DestPORTAddr,tcp_echoclient_connected);
        }
    }
}


/**
 * @brief Function called when TCP connection established
 * @param tpcb: pointer on the connection contol block
 * @param err: when connection correctly established err should be ERR_OK
 * @retval err_t: returned error
 */
static err_t tcp_echoclient_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    struct echoclient *es = NULL;

    if (err == ERR_OK)
    {
        /* allocate structure es to maintain tcp connection informations */
        es = (struct echoclient *)mem_malloc(sizeof(struct echoclient));

        if (es != NULL)
        {
            es->state = ES_CONNECTED;
            es->pcb = tpcb;

            tpcbSa = tpcb;
            if(ETH_Ctrl.connectTYPE == ETHERNET_POST)
            {
                 memcpy(data,Gateway.tcp_message,Gateway.tcp_message_length); //1024 tcp message datanın ilk 792 adet datası databuffer içine kaydedilir

                /* allocate pbuf */
                es->p_tx = pbuf_alloc(PBUF_TRANSPORT, sizeof(data) , PBUF_POOL); //burası gönderilen buffer ile aynı ozellikte bos bir buffer yaratıyor
                es2=es;

                return ERR_OK;
                
            }
        }
        else
        {
            {
                /* close connection */
                tcp_echoclient_connection_close(tpcb, es);

                /* return memory allocation error */
                return ERR_MEM;
            }
        }
    }
    else
    {
        /* close connection */
        tcp_echoclient_connection_close(tpcb, es);
    }
    return err;
}

void tcp_echoserver_send3(struct tcp_pcb *tpcb, unsigned char *Source, unsigned int Size, struct echoclient * es)
{
    err_t wr_err = ERR_OK;

    /* enqueue data for transmission */
    wr_err = tcp_write(tpcb, Source, Size, 1); //TCP_WRITE_FLAG_COPY

    if(wr_err == ERR_OK)
    {
        if(es->p_tx != NULL)
        {
             /* increment reference count for es->p */
             pbuf_ref(es->p_tx);
        }
    }

    else
    {
        if(wr_err == ERR_MEM)
        {
            tcp_write(tpcb, Source, Size, 1);

            if (sizeof(data) > tcp_sndbuf(tpcb))
            {
               usb_printf("Not enough memory. Could not send data buffer\n", 50);
            }
        }
       else
        {

        }
    }
}

  • In reverse order:

    1) If you get an ERR_MEM from tcp_write, it is not appropriate to immediately call tcp_write again, since (with high probability) it will just fail again. Instead, save away what you were doing and try again in your tcp_sent() or tcp_poll() callback function.

    2) When the system is operating normally, ERR_MEM is a form of flow control -- it means you're sending data too fast, and so should pause until the TCP stack lets you know you can continue (see (1) above).

    3) If the ERR_MEM persists, that implies that you've lost ("leaked") buffers, presumably pbufs, i.e. you're allocating but not freeing the buffers. That pbuf_ref() stands out as something that could lead to a leak, since I don't see a matching pbuf_free. Can you explain the purpose of that pbuf_ref call?