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.

lwIP on Concerto help

Hi,

my concerto application is almost running nicely but the lwIP is still giving me some headache, and I reckon it's a little ordering on the calls that is missing.

There's no web-server or file server. The "protocol" I'm using is based on some very simple commands using cmdline.c util and the MCU will receve commands such as READ_EEPROM, READ_PROCESS or CMD 1, CMD 2 and I know those works cause it works through the UART.

on the lwipopts.h I tried disabling a lot of unecessary stuff and open the memory to 16K and got S4 to S7 to .bss to be able to allocate all that. With that I hope to be able to transfer all the data from my responseBuffer directly to the lwIP in just one go and not need to transfering in a later call.

I'm checking the amount of memory available on the lwIP as u16_t buff_size = tcp_sndbuf(pcb); I'm not sure if that is correct.
I've seen a bunch of calls to pbuf_free(p); on the examples and I'm not sure if I was to be doing anything about it, or it was just for the files it was sending with headers, etc, etc. 

At the moment it boots fine and I can manually send some commands and it replies the way it should, but then when my desktop application connects to it and starts it's sequence of Connect-> Send Command -> Receive Response -> Disconnect every 500ms... the thing gets a bit crazy and some connetion start polling indefinitely, even if I call tcp_close(pcb), it just keeps polling and stops responding

so I have the logic separated in the usual callbacks, below is the simplified code, it shows all the calls to the lwIP API but to keep it short, it hides some pointers creation, NULL/error checking

Initialisation:

void ethHandler_init(void) {

struct tcp_pcb *pcb;
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, 83);
pcb = tcp_listen(pcb);
tcp_accept(pcb, ethHandler_accept);

}

Accept New Connection:

static err_t ethHandler_accept(void *arg, struct tcp_pcb *pcb, err_t err) {

// allocate a struct ethHandler_conn_state and call those as per examples
tcp_arg(pcb, conn);
tcp_recv(pcb, ethHandler_recv);

tcp_err(pcb, ethHandler_conn_err);
tcp_poll(pcb, ethHandler_poll, 4);
tcp_sent(pcb, ethHandler_sent); 

}

On receive data:

static err_t ethHandler_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) {

// Tells lwIP that we read this info and process it
tcp_recved(pcb, p->tot_len);

data = p->payload;

int response = cmdline_parse(data, responseBuffer);

if (response > 0) {

// do a nice scheme to post as much data as possible, but not too much and calls
tcp_write(pcb, ptr->message, buff_size, TCP_WRITE_FLAG_COPY);
tcp_output(pcb);

}else{

tcp_write(pcb, "Bad Command", sizeof("Bad Command"), TCP_WRITE_FLAG_COPY);
tcp_output(pcb);

}

On Sent ok:

static err_t ethHandler_sent(void *arg, struct tcp_pcb *pcb, u16_t len) {

// Do a little checking if there's more data to sent and sent more tcp_write() and tcp_output() if there is or
tcp_close(pcb); // if there's nothing more to send 

}

On Poll: (to be honest I'm not sure when or how this poll is supposed to happen)

static err_t ethHandler_poll(void *arg, struct tcp_pcb *pcb) {

// So I'm repeating here kind of the same thing from Sent, if more to send tcp_write() and tcp_output() if there's nothing more to send
if (conn->poll_count++ > 5) {

UARTprintf(UART_DEBUG, " and closing");
tcp_close(pcb);

}

}


please help!!


edit:

I just double checked and whenever the MCU starts polling for ever, after the 5 polls and my code calls tcp_close(pcb); my desktop application gives me a timeout exception, trying to reconnect to the MCU.

but I still don't know what is causing this pooling, why is causing it, and if I should just ignore instead of cancelling.

  • Ronaldo,

    from what I remember, there should be a TCP connection closing timer counter. The server after it receives the FIN packet from client siezes to send any packets to client but is open to receive any packets from client until the timer expires. You should probably take a look at this.

    you can also try resetting the connection if it fails to close?

     

    Best Regards

    Santosh

  • Hi Santosh,

    You're always up to help. Thanks mate. It's good to know that you at TexasI are there to help us.
    I've also noticed the help always come the moment I leave the office, 5PM UK time, and I imagine it is 8AM texas time... LOL... funny!

    Regarding the problem, the FIN packet is a good point but from what I've seen on the examples, none of them handle them directly, so I assume it's done in the background by the library itself once issued the tcp_close(pcb); that explains why you should check if arg == NULL during the OnReceived callback. If it is, it's a received pack from the remote host after you called the connection, but probably just garbage data and it can be discarded.

    At the end, following the server example and the echo example I found on lwIP website I noticed I was not freeing the packet buffer memory and it's what was causing the problem, the first few would work, but after the memory was gone the thing would freeze.

    in case anyone programming it, at the end my on_receive and closeConnection looks like:

    OnReceived:

    struct ethHandler_conn_state *conn;
    conn = arg;

    if (p == NULL) { // No data?

    CloseConnection(pcb, conn);
    return ERR_OK;

    }

    else if (err != ERR_OK) { // Error?

    pbuf_free(p);
    return err;

    }

    else { // Parse Command

    char *data = p->payload;

    // *** Parse data and process the response here *** //

    tcp_recved(pcb, p->tot_len); // Tell the library that we've read this pack
    pbuf_free(p); // Free the memory from the packet
    return ethHandler_SendData(pcb, conn); // Send the reply

    }

    CloseConnection:

    if (conn)
    mem_free(conn);
    tcp_arg(pcb, NULL);
    tcp_recv(pcb, NULL);
    tcp_err(pcb, NULL);
    tcp_poll(pcb, NULL, 0);
    tcp_sent(pcb, NULL);
    return tcp_close(pcb);

    Remember that my application is 100% secure that an incoming data will never use more than ONE pack. If anyone is copying from those code, you should add extra code to handle multiple packs (incoming data > 1500 bytes)

  • Hi Ronaldo,

    Thanks, I welcome your comments. We are very much excited about Concerto and so far from what I understand your use case is one of the best so far on Concerto, please feel free to share more details as you see fit.

    Ronaldo Pace said:
    I noticed I was not freeing the packet buffer memory and it's what was causing the problem, the first few would work, but after the memory was gone the thing would freeze.

    Regarding above, not freeing memory in tcp_close is a valid error, I did have that scenario once. It works for a while and then freezes up as there is no more memory for the packets.

    good luck.

    Best Regards

    Santosh

  • Santosh Athuru said:
     Thanks, I welcome your comments. We are very much excited about Concerto and so far from what I understand your use case is one of the best so far on Concerto, please feel free to share more details as you see fit.

    Oh wow... thanks! Sincerely.
    That's the 1st embedded device that I'm programming all by myself since the beginning and the reason I chose the Concerto is because you guys promised it does have the muscle to take the load we'll throw at it. If you're interested, I can provide you (whenever it's ready) the details about the machine (marketing material, release date, target clients, etc) .