PIC32MX795 and FreeRTOS TCP/IP Stack

swissembedded wrote on Friday, December 04, 2015:

Hi
does anybody have a port yet for the PIC32 starter kit to the new FreeRTOS stack?
Best regards
Dani

rtel wrote on Friday, December 04, 2015:

I’m not aware of anybody using this part. We would be happy to assist as much as we could via this forum and email exchange if you were to create a port provided the result was uploaded to the FreeRTOS interactive site once complete.

Regards.

swissembedded wrote on Friday, December 04, 2015:

Thanks, that is certainly worth to thing about.

tlafleur wrote on Friday, December 04, 2015:

I’ve used this part in three project, with the standard demo as a start…
Was easy to bring up and make changes for my hardware… Also used the MZ
in a project, again was easy to make work…

swissembedded wrote on Thursday, December 10, 2015:

Sorry for being fuzzy, I’m talking about the TCP/IP Stack, PIC32 port is working fine…

We have the MAC/PHY combo now working, but problem with DHCP client. Can we expect that the DHCP implementation is functional and has been tested in the latest release?

rtel wrote on Thursday, December 10, 2015:

Yes - the DHCP has been tested with a lot of different network
configurations.

Can you post a WireShark capture of the DHCP transactions?

swissembedded wrote on Thursday, December 10, 2015:

it only send dhcp discover request, but for some reason there is no response from the server. We will look into details, server should work, it responds to microchip dhcp request, so I expected something to be wrong in the freertos request…

rtel wrote on Thursday, December 10, 2015:

Ok - a wireshark caption could still be helpful, so we can inspect the
suspect packet, and see if Wireshark can decode it, or highlight any
potential issues with it.

swissembedded wrote on Thursday, December 10, 2015:

Looks like Freertos sends discorver as unicast, should be broadcast…

heinbali01 wrote on Friday, December 11, 2015:

Hi Dani,

Looks like Freertos sends discorver as unicast, should be broadcast…

The DHCP client will try both methods: without and with the BROADCAST flag set.

The discovery and all other messages will always be sent to the UDP broadcast address 255.255.255.255

Does your DHCP server allow any client to apply for an IP address? No MAC address filtering?

I attached a PCAP file to this post of a +TCP device booting in a LAN.


  /* My DHCP server was switched off here: */
  1   0.000  DHCP Discover - unicast
  4   5.249  DHCP Discover - broadcast
  6  15.498  DHCP Discover - unicast

 /* Device uses IP 192.168.2.114, answers to ping. */
 20  62.475  +TCP device replies as 192.168.2.114
 21  62.475  PING request
 
  /* Switched on the DHCP server: */
 38  99.550  Discover - unicast
 39  99.550  Offer
 40  99.552  Request
 41  99.552  ACK

If you doubt, please post some PCAP files.

Do other things already work? UDP? TCP?

Regards,
Hein

swissembedded wrote on Friday, December 11, 2015:

ok, we got it working with the pic. it uses much memory, can you pls give me a config file with the bare minimum settings for memory consumption?

swissembedded wrote on Friday, December 11, 2015:

@Hein, thanks we found the DHCP problem, there has been a problem with checksum settings.

The rx tx buffers are set in the socket command. Is there a way to set this other then the default for each socket? For example some sockets require only require small rx or tx buffer. Best would be if this could be tuned at runtime…

rtel wrote on Friday, December 11, 2015:

Not at my computer at the moment so I can’t provide a direct link, but if you look on the FreeRTOS+TCP web pages, the tree menu on the left has a page describing how to configure either for performance or to reduce memory usage.

swissembedded wrote on Friday, December 11, 2015:

yes you can, just use FreeRTOS_setsockopt to adjust buffers at runtime.

swissembedded wrote on Friday, December 11, 2015:

usBacklog sets the number of sockets that are created when a new messages arrives. It does also use the setsockopt settings, not the default?

heinbali01 wrote on Saturday, December 12, 2015:

Hi Dani,

About the memory use of FreeRTOS +TCP

“Network Buffer Descriptors” are the objects that hold the network messages. They normally have a short life, after a few ms they are delivered to their destination.

The UDP protocol uses discrete messages. Therefore these message will stay in their ‘Network Buffer Descriptors’ while waiting to be picked up by FreeRTOS_recvfrom().

When TCP receives new data, the contents of the ‘Network Buffer Descriptors’ is copied to an RX stream buffer. Outgoing data (FreeRTOS_send()) will be copied a the TX stream buffer.
The advantage is that if you send many small messages, they will end up into a single contiguous buffer, and sent-out in maximum-size packets (MSS).

So every connected TCP socket will get a TX and RX stream buffer. Once a stream buffer is created, its size is fixed.

The default stream buffer sizes are defined with:

/* Define the size of Rx buffer for TCP sockets. */
#define ipconfigTCP_RX_BUF_LEN			( 3 * 1460 )

/* Define the size of Tx buffer for TCP sockets. */
#define ipconfigTCP_TX_BUF_LEN			( 2 * 1460 )

But indeed they can be adjusted at runtime, see:

http://www.freertos.org/FreeRTOS-Plus/FreeRTOS_Plus_TCP/API/setsockopt.html

Probably the easiest way is to use is FREERTOS_SO_WIN_PROPERTIES. It will overwrite the above defaults in a single call.

Set the window properties before a socket gets connected: the listening socket that will accept() a new connection, or a client socket that will connect() to a remote one.

Note that when accept() succeeds, all socket properties will be inherited by the new child socket, including stream buffer sizes (and also the local port number will be the same as its parent socket).

Using BufferAllocation 1 or 2 ?

Have you seen the difference between BufferAllocation_1 and BufferAllocation_2?

Both modules will provide this number of Network Buffer Descriptors:


    #define ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS    ??

Version 1 is more efficient, it reserves all buffer space by calling the user-provided vNetworkInterfaceAllocateRAMToBuffers() right after start-up.
The advantage of version 1 is that all network buffer descriptors are guaranteed to be available and no more calls to pvPortMalloc() are necessary.

In version 2 only the Descriptors are allocated at start-up, and the actual Buffers will be malloc’d when needed. Small messages will use small buffers.

In general: platforms with more than enough (SD)RAM will use BufferAllocation_1.c.

About the backlog parameter in listen()

Looking at http://linux.die.net/man/2/listen :

int listen(int sockfd, int backlog);

The official meaning of backlog is the following:

“The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow.”

FreeRTOS is typically running on a smaller system with less resources and the definition is slightly (only slightly) different:

“The backlog argument defines the maximum of connections that can be established to the socket simultaneously.”

It is important to let +TCP send keep-alive messages in an idle connection:


    /* Include support for TCP keep-alive messages. */
    #define ipconfigTCP_KEEP_ALIVE				( 1 )
    #define ipconfigTCP_KEEP_ALIVE_INTERVAL		( 20 ) /* in seconds */

Otherwise a service might become unreachable because of ‘dead’ connections.
A TCP connection becomes dead if the remote device is switched off suddenly without properly closing the connection.
If keep-alive messages are being used, +TCP device will quickly detect that the remote end doesn’t respond any more.

An alternative to the above is it send keep-alive message at the user level. In a Telnet client for instance you could send empty lines (CR/LF) regularly to keep the remote end happy.

Enough text for now. I hope it clarifies things, and if not, please ask!

Regards

swissembedded wrote on Tuesday, December 22, 2015:

Thank you Hein for the explanations.

swissembedded wrote on Thursday, December 31, 2015:

We are sending packets smaller than mss to optimize memory footpring. Looks like Nagle Algorithm is not implemented, we see 200ms delay between the outgoing packets on our http server implementation. There is one outgoing paket per ack.
We use browser on microsoft pc
https://support.microsoft.com/en-us/kb/214397/

heinbali01 wrote on Friday, January 01, 2016:

Hi Dani,

The Nagle algorithm has indeed not been implemented in the +TCP stack. Many real-time programmers tend to disable this feature because they want their messages to be delivered instantly.

Can you make an estimate of how many packets of what size you expect to be sending?

Normally the delayed ACK of 200 ms (on the remote end) shouldn’t bother you. And if it does bother, you’d have to look at the following:

  1. The default size of the socket TX buffer:
  /* Define the size of Tx buffer for TCP sockets. */
  #define ipconfigTCP_TX_BUF_LEN			( 2 * 1460 )
  1. Or maybe you’ve set it manually:
  The socket option 'FREERTOS_SO_SNDBUF'
  1. Or you can set both the buffer- and WIN-sizes in a single call to FreeRTOS_setsockopt() :
  Or the socket option 'FREERTOS_SO_WIN_PROPERTIES'

Explanation:

Suppose that your TX buffer size is very small, 1000 bytes. You send 1000 bytes and the remote end delays the ACK for 200 ms.

What you can do (without changing buffer sizes), is send 2 times 500 bytes. As there is no Nagle algorithm, the packets will be sent immediately and the remote end will reply with an ACK after the second packet.

Regards.

heinbali01 wrote on Monday, January 04, 2016:

Hi Daniel,

we see 200ms delay between the outgoing packets on our http
server implementation. There is one outgoing paket per ack.

I already proposed a solution for the 200ms ACK problem in an email, I will repeat it here so that other users can also read it:

Use the socket option ‘FREERTOS_SO_WIN_PROPERTIES’, because it allows you to set both the buffer size and WIN (as a multiple of MSS).

This post has two attachments in a ZIP file:

html_one.pcap : page loads in 9.3 seconds using a 730-byte buffer :

    #define ipconfigTCP_MSS ( 730 )
    xWinProps.lTxBufSize = ipconfigTCP_MSS;
    xWinProps.lTxWinSize = 1;

This is when WIN == 1 * MSS, very ineffective. +TCP must wait for 200 ms after every packet.

html_two.pcap : page loads in 0.3 seconds using a 1072-byte buffer :

    #define ipconfigTCP_MSS ( 536 )
    xWinProps.lTxBufSize = ( 2 * ipconfigTCP_MSS );
    xWinProps.lTxWinSize = 2;

Now WIN == 2 * MSS and the communication is pretty efficient.

Regards.