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.

TCPIP data transfer with LWIP

Equipment: BBB, CCSv6, TI XDSv2 USB Emulator, Windows7, AM335X_StarterWare_02_00_01_01


Hi,

the aim is to send large blocks of data periodically via TCP/IP using LWIP. Lets say the period is 50ms.
Therefore I modified the enetEcho code example from AM335X_StarterWare_02_00_01_01 and after the connection has been established

    if(ptSES_tcp_pcb->snd_buf) {       		// if there is send buffer available
    	Tx.StartAdr = (DWORD)&Tx.Hd;
    	Tx.Len = 0x9cf0;                   // this is what I would like to send, but the send buffer 
                                            // available is only 12000 bytes at a maximum
    	err = tcp_write(ptSES_tcp_pcb, (BYTE *)Tx.StartAdr, ptSES_tcp_pcb->snd_buf, TCP_WRITE_FLAG_COPY);
    }

is called periodically (50ms) to transfer as many bytes as possible. (Where ptSES_tcp_pcb->snd_buf is the available buffer space for sending (in bytes).)

If there is no free send buffer, tcp_write() is not called.

The problem is that only after 200ms (4 periods) there is send buffer available. And after tcp_write() has been called 5
times ( with 200ms between each call) no send buffer is available any longer (ptSES_tcp_pcb->snd_buf == 0).

The connection is for 100MBit/s( that is what enetEcho reports). So let's assume the effective speed is only 50MBit/s
(because buffers are copied internally for instance). Then 12000 bytes should be transferred within 1.92ms, I would expect.

What might be the reason for this behaviour? Is the client (Hercules in this case) responsible because it does not handle the data quick enough?
The WhireShark protocol however does not seem to contain any retransmission requests.
Or do I have to free any buffers somewhere? What is the recommended procedure for sending datat?

Can anybody help?

Every comment is very much appreciated.

Thank you.

Regards,
Martin H.

  • When you use the (really crappy and poor implemented) lwIP-examples from Starterware I'd guess the problems is caused by your method to send the data periodically.

    lwIP itself is not thread/IRQ-context safe. Means all has to be done out of same context. For Starterware-examples this means, receiving is done in IRQ-context, same has to be done for sending of data. In these examples this is solved by sending the answer out of the receive-function (which automatically uses right context). But when you set up a timer or send your data out of main loop periodically you are not in the same interrupt-context and behaviour of lwIP is undefined.

    For such purposes lwIP uses a poll-function which is called periodically and which could be used to retrieve some data and send them in correct context. But (and that's what I blame the Starterware-developers for): in all lwIP-examples polling is disabled. This means you are alone in the dark now...

  • Hello,

    that is interesting as I did not find a remark about this behaviour anywhere. Thanks for your response.
    So I will see what I can do with polling.
    What springs to mind is enabling polling when data shall be sent (with a small polling interval) and disabling it when
    transfer is over. That doesn't sound good, I know. But I need to find a way to send data when sampling has finished, not while sampling is in progress.
    I suppose this thread/IRQ unsafety applies to UDP transfers as well?

    Thank you.

    Regards,
    Martin H.

  • Martin H. said:
    What springs to mind is enabling polling when data shall be sent (with a small polling interval) and disabling it when transfer is over.

    Normally you can leave pollign enabled all the time - it is a standard feature of lwIP. Only in Starterware it is disabled for some unknown reasons - and TI's support gave only an answer to this question that is ... hm ... useless: http://e2e.ti.com/support/embedded/starterware/f/790/t/370462.aspx

    So you can try enabling it and see what happens...any feedback regarding the result would be interesting for me too :-)

    Martin H. said:
    I suppose this thread/IRQ unsafety applies to UDP transfers as well?

    Yes, that's true for lwIP in general.

  • Having been busy with other things, I recently again turned towards lwIP to create an active tcp_pcb (sending data).
    But I must admit that I could not yet solve the problem.

    What I read about polling is that it is meant to be used for maintenance purposes when lwIP is idle. But it doesn't seem to be possible to use that function at a defined point in the mainloop just once.

    But I found 2 interesting sources:
    - rawapi.txt (which comes with Starterware) and
    - http://lwip.wikia.com/wiki/Raw/TCP#Sending_TCP_data

    I followed the instructions to create an active connection, but neither the callback function "Connected() nor "Err" ever where invoked.

    What came to mind ist that tcp_tmr() is not used in the enetEcho excample. Is it not necessary?
    According to wikia.com  it must be called periodically (sys_check_timeouts() does not seem to exist in lwIP version 1.4.0
    that comes with Starterware).

    I also posted a question in the  lwIp forum  but so far I did not get any feedback yet.

    Is there anybody who would like to share his initialization sequence for an active tcp_pcb?
    Or can anybody give an advice how to overcome that problem?
    All hints are very welcome.

    Regards,
    Martin H.

  • Martin H. said:
    What I read about polling is that it is meant to be used for maintenance purposes when lwIP is idle. But it doesn't seem to be possible to use that function at a defined point in the mainloop just once.

    No, you never can use it out of main-loop. The idea is to store the data you want to send in queue/buffer/whatever and then check out of the periodically-called poll-function if there are some data available in this queue/buffer/whatever. If yes, poll-function can send the data out of the lwIP-IRQ context correctly.

    Martin H. said:
    What came to mind ist that tcp_tmr() is not used in the enetEcho excample. Is it not necessary?

    It is necessary but it is disabled in Starterware examples. With it the poll-functionality is disabled too. Unfortunately TI's support is not able to answer why it is disabled.

    And exactly this disabled feature is the reason why it does not work for you.