Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

I've been enjoying deploying FreeRTOS+TCP (from the labs) on a STM32F103 + enc28j60 and have found a few gotchas along the way. I'm rating FreeRTOS+TCP a hole-in-one for an IP stack on micros - a great improvement over the two leading alternatives. Thankfully the findings are all relatively minor.

  1. The docs for BufferManagement_1.c don't mention the need to implement vNetworkInterfaceAllocateRAMToBuffers
  2. The network buffers returned to BufferManagement_1.c must be 8-byte aligned. Which if not leads to next bug:
  3. If a buffer is not aligned to 8-byte boundary, the DHCP buffer alloc fails (pxUDPPayloadBuffertoNetworkBuffer returns null), but when vReleaseNetworkBufferAndDescriptor is called (from FreeRTOS_ReleaseUDPPayloadBuffer in prvSendDHCPRequest), there is no null check and so vReleaseNetworkBufferAndDescriptor crashes.
  4. configASSERT_VOID in a couple of files but with no def.

FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

Thank you for your valuable feedback. I would be extremely grateful if you could post your code to the FreeRTOS Interactive site - I have just created a forum for this, a link to which is below. If you are unable to post the project then please at least post the driver files. Thanks.

http://interactive.freertos.org/forums/21211265-FreeRTOS-TCP

The docs for BufferManagement_1.c don't mention the need to implement vNetworkInterfaceAllocateRAMToBuffers

I will fix.

The network buffers returned to BufferManagement_1.c must be 8-byte aligned.

Hein - can you please confirm and if so we can add an assert() into the code to catch this, and so bring peoples attention to it immediately without having to debug first. I will also then add it to the documentation.

If a buffer is not aligned to 8-byte boundary, the DHCP buffer alloc fails (pxUDPPayloadBuffertoNetworkBuffer returns null), but when vReleaseNetworkBufferAndDescriptor is called (from FreeRTOS_ReleaseUDPPayloadBuffer in prvSendDHCPRequest), there is no null check and so vReleaseNetworkBufferAndDescriptor crashes.

Again I think there needs to be some documentation on this point, and some asserts will help to. Sometimes it is necessary to add an offset into the network buffer at the driver level - that may or may not be related.

configASSERT_VOID in a couple of files but with no def.

I think I have that one already.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

Just writing the documentation for vNetworkInterfaceAllocateRAMToBuffers() now, and it occurs to me the function would be better named vNetworkInterfaceAllocateRAMToDescriptors(), as that is what it is doing.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on November 26, 2014

Hi Robert,

a great improvement

Thanks. We were all hoping that FreeRTOS+TCP will be simple (to use, to adopt) and at least equally powerful. It has the great advantage that it is build on top of FreeRTOS. This makes the code a lot simpler.

deploying FreeRTOS+TCP (from the labs) on a STM32F103 + enc28j60

Please share, in return you will get valuable feedback :-)

Maybe we should make a check-list for "Writing a NIC driver for FreeRTOS+TCP". I'm thinking of these options, I'm sure you've seen them all:

  • The choice between BufferManagement_1 / 2 Version 1 is indeed preferred if your system has enough memory Provide an allocation function for version 1.

  • Optional: ipconfigUSE_LLMNR : add the LLMNR multicast MAC address 01:00:5E:00:00:FC to the list of MAC-addresses. LLMNR is very useful for name resolution on a LAN, especially when using DHCP. All browsers use LLMNR as a preferred way to find names (without a dot)

  • Optional: ipconfigDRIVERINCLUDEDTXIPCHECKSUM

  • Optional: ipconfigDRIVERINCLUDEDRXIPCHECKSUM The NIC driver calculates the TX and/or RX checksum, either automatically within the EMAC peripheral, in which case it is called "checksum offloading". Or by calling usGenerateChecksum().

  • Optional: ipconfigETHERNETDRIVERFILTERSPACKETS If you want to filter incoming messages within the NIC driver, enable this option. The advantage: you might want to stop many UDP broadcast messages as early as possible. W32, discovery protocols, PnP, simple network maintenance and other inventions can occupy quite some resources: allocate a buffer, send it to the IP-task, which will analyse and drop it. See FreeRTOSSockets.c:

~~~~~
/* Function returns true if there is a UDP socket bound to the given port number. */ BaseTypet xPortHasUdpSocket( uint16t usPortNr ) ~~~~~

  • Optional: ipconfigPACKETFILLERSIZE This option is a bit tricky: it makes sure that all 32-bit fields in the network packets are 32-bit aligned. This means that the 14-byte Ethernet header should start at a 16-bit offset. Therefore ipconfigPACKETFILLERSIZE is defined a 2 (bytes). I think that most EMAC's have an option to set this 2-byte offset for both incoming and outgoing packets.

  • Optional: ipconfigUSELINKEDRX_MESSAGES An optimisation: Collect received packets in a loop and link them through a pointer called 'pxNextBuffer'. Several messages will be forwarded to the IP-stack within a single 'eNetworkRxEvent' message to the IP-stack

  • Optional: what I would do is check the Link-Status continuously. As long as the LS is low, it doesn't make sense to send messages. Check the PHY frequently, to have a quick response once it gets connected. As long as LS is high, check it e.g. every 15 seconds, unless packets are received, which already proves that the Link-Status is high.

I'm repeating the word "Optional". All these points aren't necessary, but they can all improve the performance.

I will come back on the "8-byte alignment" issue, thanks for reporting that.

'configASSERT_VOID' was my not-so-useful invention, the idea was:

#define configASSERT_VOID(statement)	if( ( statement ) == pdFALSE ) return

used in functions returning 'void'.

Regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

Hi, Thanks for the reply. I will contribute the driver once it's done also. The buffer alignment issue wasn't completely fixed by aligning to 8-byte boundaries, rather the buffer is rejected after the UDP offset is applied (ipUDPPAYLOADOFFSET) which unfortunately is a non-8-byte size (42) so the buffer is never going to end up 8-byte aligned. Is there a fix for this yet? I'm wondering why there is even the requirement to align to 8-byte boundaries for the packet? On the CM3 8-byte alignment is only required for stack pointers, no? Hein might have found something similar with what he's referring to re the ipconfigPACKETFILLERSIZE

Regards, Robert


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

Hi guys, I don't suppose there's a git repo from which I can pull latest updates?


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

I'm starting to get a bit suspicious as to why the problem I'm having hasn't been seen before, and assume it's due to some combo of settings + Buffer_1 that hasn't been tested before. I'm on a STM32F103, and the crash is happening right during the first time through the prvIPTask, long before any packets are sent/received, during the first sending (attempt) of a DHCP packet.


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

Hi guys, I don't suppose there's a git repo from which I can pull latest updates?

Currently the sources are in a private SVN repository - although they will be moved into the main FreeRTOS SVN repository at some point. You have have noticed both the source code directory structure and the web pages are organised to fit with the standard model.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

I'm starting to get a bit suspicious as to why the problem I'm having hasn't been seen before, and assume it's due to some combo of settings + Buffer_1 that hasn't been tested before. I'm on a STM32F103, and the crash is happening right during the first time through the prvIPTask, long before any packets are sent/received, during the first sending (attempt) of a DHCP packet.

You could be right of course, although when Hein and I work on this Hein uses Buffer1 and I use Buffer2. Likewise Hein uses big endian and I use little endian. That way we are using both of both options all the time.

Your comments about this being related to UDP make me suspect your problem could be related to padding bytes that are required at the start of the frame. I will look through my notes on that, it might take a while to find (I have a lot of notes!).

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on November 26, 2014

Hi Robert,

If you like you send what you have now to info at freertos point org. Then we can have a look at it (without revealing any code).

Or maybe this text will contain a hint:

The 'ipconfigPACKETFILLERSIZE' may indeed be a bit confusing. It corresponds to what is named 'ETHPADSIZE' in lwIP.

~~~~~ uint8_t *pucBuffer; ~~~~~

What is sizeof( pucBuffer ) on your platform ? If it is 64-bits then indeed the (internal) function like 'pxUDPPayloadBuffertoNetworkBuffer' will only work with 8-byte aligned buffers. At the other hand, the library is not yet prepared for 64-bit pointers.

Every network buffer descriptor has this memory:

~~~~~ 0x00 4 bytes pointer to the network buffer descriptor 0x04 4 bytes reserved for flags 0x08 2 bytes Alignment filler (ipconfigPACKETFILLERSIZEbytes) 0x0a 'ipTOTALETHERNETFRAME_SIZE' bytes Here the packet begins with 'xDestinationAddress'

#define ipTOTAL_ETHERNET_FRAME_SIZE  ( ipconfigNETWORK_MTU + \
    ipSIZE_OF_ETH_HEADER + ipSIZE_OF_ETH_CRC_BYTES + \
    ipSIZE_OF_ETH_OPTIONAL_802_1Q_TAG_BYTES )

~~~~~

Please note that the packet data:

~~~~~ uint8_t *pucEthernetBuffer ~~~~~

points to offset 0x0a (== ipBUFFER_PADDING) in the allocated space.

In your NetworkInterface.c you should allocate 'ipTOTALETHERNETFRAMESIZE + ipBUFFERPADDING' bytes per network buffer.

~~~~~ #define UNITSIZE ( ipTOTALETHERNETFRAMESIZE + ipBUFFERPADDING ) /* Here the aligned(8) attribute is used because DMA likes it. */ static unsigned char networkpackets[ ipconfigNUMNETWORKBUFFERDESCRIPTORS * UNITSIZE ] attribute ((aligned (8)));

void vNetworkInterfaceAllocateRAMToBuffers( pxNetworkBuffers[ ] )
{
unsigned char *ucRamBuffer = network_packets;
int x;
    for (x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++) {
        /* Add the 10 bytes */
        pxNetworkBuffers[ x ].pucEthernetBuffer = ucRamBuffer + ipBUFFER_PADDING;
        /* Set the pointer to the network buffer descriptor */
        *((unsigned*)ucRamBuffer) = (unsigned)(&pxNetworkBuffers[x]);
        /* and point to the next space to assign. */
        ucRamBuffer += UNIT_SIZE;
    }
}

} ~~~~~

Regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

Am I able to have read access to the SVN repo? Of course it it's an internal-only repo then no problem :-)


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

Am I able to have read access to the SVN repo? Of course it it's an internal-only repo then no problem :-)

Unfortunately not at the moment as there are some other new, and as yet confidential, developments in the same repository. We should aim to expedite moving the TCP code into the public SVN repository, but I'm somewhat hesitant as having it separate means we can change it rapidly - rather than just between FreeRTOS releases.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 26, 2014

Ahh that buffer allocation looks like it might be promising. What I have at present does not allow for the padding: ~~~~~~ static uint8t ucBuffers[ipconfigNUMNETWORKBUFFERDESCRIPTORS][ipTOTALETHERNETFRAME_SIZE] attribute((aligned(8)));

void vNetworkInterfaceAllocateRAMToBuffers(xNetworkBufferDescriptort pxNetworkBuffers[ipconfigNUMNETWORKBUFFERDESCRIPTORS]) { BaseType_t x;

for (x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++)
{
	pxNetworkBuffers[x].pucEthernetBuffer = &(ucBuffers[x][0]);
}

} ~~~~~~

After not finding any example of vNetworkInterfaceAllocateRAMToBuffers in FreeRTOS+TCP, I happened to find that snippet in FreeRTOS8.1.2 FreeRTOS-Plus-UDP/portable/NetworkInterface/WinPCap/NetworkInterface.c

I will try the changes in ~12 hours and reply. Thanks for the support guys


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 26, 2014

The 'ipconfigPACKETFILLERSIZE' may indeed be a bit confusing.

Just checking this page: http://www.freertos.org/FreeRTOS-Plus/FreeRTOSPlusTCP/TCPIPConfiguration.html

I find that constant is not even mentioned. We need to add it in asap and update the buffer_1 documentation pages accordingly. I updated them today once already following Robert's feedback.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on November 27, 2014

You were still missing some things, like the 'ipBUFFER_PADDING':

~~~~~~

define UNITSIZE ( ipTOTALETHERNETFRAMESIZE + ipBUFFER_PADDING )

// The 10 bytes of ipBUFFER_PADDING should be added // so the declaration becomes:

static uint8t ucBuffers[ ipconfigNUMNETWORKBUFFERDESCRIPTORS ] [ UNIT_SIZE ] attribute((aligned(8))); ~~~~~~

It doesn't make much sense to align the first buffer only, so let's round up the size of each buffer:

~~~~~~

define UNITSIZE1 ( ipTOTALETHERNETFRAMESIZE + ipBUFFERPADDING )
define UNITSIZE8 ( ( UNITSIZE1 + 7 ) & ~7 )

static uint8t ucBuffers[ ipconfigNUMNETWORKBUFFERDESCRIPTORS ] [ UNITSIZE8 ] attribute((aligned(8)));

// And finally make the double link, from descriptor to buffer and from // buffer to descriptor:

void vNetworkInterfaceAllocateRAMToBuffers2( xNetworkBufferDescriptort pxNetworkBuffers[] ) { BaseTypet x;

for (x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++)
{
	/* Not like this: */

/* pxNetworkBuffers[ x ].pucEthernetBuffer = &(ucBuffers[ x ][ 0 ] ); / / But like this: */ pxNetworkBuffers[ x ].pucEthernetBuffer = &(ucBuffers[ x ][ ipBUFFERPADDING ] ); /* And set a pointer back to the descriptor: */ *( ( uint32t * ) &ucBuffers[ x ][ 0 ] ) = ( uint32_t ) &pxNetworkBuffers[x]; } } ~~~~~~

There is no requirement to have the actual buffers 8-byte aligned, 4-byte is enough. But some DMA peripherals do like an 8-byte alignment or higher. A better alignment may lead to a higher throughput.

Regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 27, 2014

Hi Hein - I think there is scope to make this easier for the end user. For example, setting the pointer back to the descriptor as:

*( ( uint32_t * ) &ucBuffers[ x ][ 0 ] ) = ( uint32_t ) &pxNetworkBuffers[x];

could be done inside BufferAllocation1.c (in fact I thought it was!). Ideally we don't want the end user to know anything about how the space is used, that should be hidden. In fact even the use of ipBUFFERPADDING could be hidden by providing a different constant that has the padding already added. Something like:

define ipBUFFERSIZE ( ipTOTALETHERNETFRAMESIZE + ipBUFFER_PADDING )

except using a more descriptive name than 'BUFFERSIZE', then the user can use the BUFFERSIZE constant without even knowing ipBUFFER_PADDING has been added.

Lets try and do this before the next labs release.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 27, 2014

Bingo, that was it. I first sorted the ipBUFFER_PADDING which made satisfied the alignment, but then hit the snag of no reference back to the descriptor. The above post fixed it. Definitely let me know when you bundle up the next labs release :-) Thanks guys. Will continue code stepping...


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on November 29, 2014

Hi Robert,

Bingo, that was it.

I'm glad to hear.

I first sorted the ipBUFFER_PADDING which made satisfied the alignment, but then hit the snag of no reference back to the descriptor.

This mechanism was already present in the earlier FreeRTOS+UDP. The double pointers are necessary for the ZERO_COPY feature. It allows to pass around a "const char*" whereas in fact it is NetworkBuffer.

In the next release, the double pointers and also the ipBUFFERPADDING + ipconfigPACKETFILLER_SIZE defines will be totally hidden, i.e. moved to the library.

The network driver will only supply a pointer to a space big enough to hold all Network Buffers.

Definitely let me know when you bundle up the next labs release :-)

You will be the first one to hear it :-)

Note that the current release (141019) is not a first try-out. The development already started more than a year ago and this library has already been applied in commercial applications.

It will remain in FreeRTOS Labs as long as: "... we are still refining its design, and the source code and documentation do not yet meet Real Time Engineers Ltd's strict quality standards".

To be expected in the new release:

- Sockets in listening mode, using the
  'FREERTOS_SO_REUSE_LISTEN_SOCKET', can now also
  be used with select() and accept().
  The reuse option means that the same instance of
  the listening socket will get connected.

- The above change: hiding the PADDING and FILLING
  bytes and setting the double links with pointers.

- Extending the zero-copy option for TCP: the sending
  routine may pass all packet buffers directly to the DMA,
  in stead of first copying it.

- Adapted documentation

Thanks guys. Will continue code stepping...

Same to you.

Btw are you still stepping through the code or running it by now?

Regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on November 30, 2014

Hi guys, New update: have a polled version of the enc28j60 driver working sweetly. UDP loop tests are showing about 1Mb/s performance before packets start dropping. It's pretty crude in that it currently has to poll the chip (SPI transaction) to check if a received packet is waiting. I'm midst enabling interrupts and DMA. Transferring a 1500 byte packet over 10MHz SPI really is screaming for DMA! The more hardware peripheral features I pull in (SPI, GPIO Interrupt & DMA) the more my frustration rises at keeping things moderately portable. I started out using libmaple with it's plethora of cpp libs and have been slowly FreeRTOS-ing them.

Just a quick thing I noticed, in the porting examples, the basic packet receiving example doesn't set the xNetworkBufferDescriptor_t.xDataLength with xBytesReceived.

Cheers guy, Robert


FreeRTOS+TCP minor bug-finds

Posted by rtel on November 30, 2014

Just a quick thing I noticed, in the porting examples, the basic packet receiving example doesn't set the xNetworkBufferDescriptor_t.xDataLength with xBytesReceived.

Fixed!

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on December 1, 2014

Another documentation question: Is it ok to call vReleaseNetworkBufferAndDescriptor from an ISR? The documentation page for it only mentions "pxGetNetworkBufferWithDescriptor() must not be called from an interrupt service routine (ISR)", bur doesn't say vReleaseNetworkBufferAndDescriptor can't be. Copy and paste error?


FreeRTOS+TCP minor bug-finds

Posted by rtel on December 1, 2014

If you are using BufferAllocation_2.c then this is not same to use from an ISR - although you could modify the memory allocation functions to make it safe I would not recommend it. It is best instead to defer the processing to a task. The next FreeRTOS version introduces a new feature that makes that faster and easier (does not require a semaphore).

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on December 1, 2014

Same thoughts: try to defer all buffer processing to a normal task.

In one of the ports (for Xilinx/Zynq) you will find:

~~~~~

/* Three ISR's for TX, RX and error handling: */

void emac_send_handler(void *arg)
{
xemacpsif_s   *xemacpsif;
long xHigherPriorityTaskWoken = pdFALSE;

    xemacpsif = (xemacpsif_s *)(arg);

    /* In this port for FreeRTOS+TCP, the EMAC interrupts
    will only set a bit in "isr_events". The task in
    NetworkInterface will wake-up and do the necessary work. */

    xemacpsif->isr_events |= EMACPS_TX_EVENT;
    xemacpsif->txBusy = pdFALSE;

    if( xEMACEventSemaphore != NULL )
    {
        xSemaphoreGiveFromISR( xEMACEventSemaphore,
            &xHigherPriorityTaskWoken );
    }

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}

void emac_recv_handler(void *arg)
{
    /* Same as above, setting the RX flag */
    xemacpsif->isr_events |= EMACPS_RX_EVENT;
    ...
}

void emac_error_handler(void *arg)
{
    /* Same as above, setting the ERR flag */
    xemacpsif->isr_events |= EMACPS_ERR_EVENT;
    ...
}

~~~~~

The task handling the NIC will do the actual work:

~~~~~

for( ; ; ) { if( ( xemacpsif->isrevents & EMACPSALL_EVENT ) == 0 ) { xSemaphoreTake( xEMACEventSemaphore, 100 ); }

if( ( xemacpsif->isr_events & EMACPS_RX_EVENT ) != 0 )
{
    xemacpsif->isr_events &= ~EMACPS_RX_EVENT;
    xResult = emacps_check_rx( xemacpsif );
}

if( ( xemacpsif->isr_events & EMACPS_TX_EVENT ) != 0 )
{
    xemacpsif->isr_events &= ~EMACPS_TX_EVENT;
    emacps_check_tx( xemacpsif );
}

if( ( xemacpsif->isr_events & EMACPS_ERR_EVENT ) != 0 )
{
    xemacpsif->isr_events &= ~EMACPS_ERR_EVENT;
    emacps_check_errors( xemacpsif );
}
check_phy_link_status( );

}

~~~~~

Note that sending messages always happens from the IP-task.

FreeRTOS+TCP is 100% thread-safe, not interrupt-safe. As you most probably know, there is a very small delay between calling xSemaphoreGiveFromISR() and the waking up from xSemaphoreTake().

The above approach has the advantage that the configured priorities govern the processing, and not the hardware :-)

Personally, I tend to give the highest priority to the NIC task. We don't want to miss packets due to an RX overflow. The above routine emacpscheckrx() will only put received messages in a queue, and free the DMA buffers.

The second highest priority is for the IP-task, and all other tasks get a lower priority.

Good luck, Hein


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on December 4, 2014

Hi guys, When dealing with link up/down events, I call FreeRTOS_NetworkDown[FromISR] and then indicate network back up from xNetworkInterfaceInitialise. Is it recommended to block for long periods in xNetworkInterfaceInitialise while waiting for the link to come up?


FreeRTOS+TCP minor bug-finds

Posted by rtel on December 4, 2014

I don't think that should be necessary as the IP task will itself delay in between calls to xNetworkInterfaceInitialise(). Search FreeRTOSIP.c for ipINITIALISATIONRETRY_DELAY to see where this is done. Let us know if that is not what you meant, or think it should be done in some other way.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on December 8, 2014

Sweet, I've got a nicely running stack. DMA & Interrupt driven, it achieves ~3.8Mb which I figure isn't that for a 10Mb NIC on a 9MHz SPI and no IP checksum offloading. Are you guys ready to NIC drivers for FreeRTOS+TCP?


FreeRTOS+TCP minor bug-finds

Posted by rtel on December 8, 2014

Excellent! You can have the honour of being the first person to upload a driver (hopefully a build project showing how to use the driver ;o) to the +TCP forum in the Interactive site: http://interactive.freertos.org/forums/21211265-FreeRTOS-TCP

Regards.


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on December 16, 2014

Good call. I'm midst refactoring the code to try decouple hardware peripheral dependencies. I'll then post to the forum


FreeRTOS+TCP minor bug-finds

Posted by rwt33 on December 17, 2014

I'm having a few issues now with the link going up/down. Before I start digging into my driver, have you guys done much testing with links going up & down? Specifically I'm having problems when the link has been up, goes down and then comes back up. If the link is there at startup it's fine, or if the link is missing at startup xNetworkInterfaceInitialise polls until the link comes up. It's only if the link has been up, goes down and then comes back up that I'm having problems. Of course there's a very high chance it's my driver also. Just wondering if you've done much exploration in that area. Cheers guys


FreeRTOS+TCP minor bug-finds

Posted by rtel on December 17, 2014

Hi Robert,

There is some reliance on the driver here to inform the stack that the link has gone down. When the driver tells the stack the link has gone down the stack should then loop, periodically attempting to re-initialise. Re-initialising should then start the DHCP process again. We can have a look, but in the mean time if you see anything that needs changing let us know.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on December 17, 2014

Hi Robert,

If your device runs on a battery and if it is being plugged-in and out, yes I would have it run DHCP again. The new network might be totally different.

At the other hand, if the device has a fixed place and a fixed power supply, I would just poll the Link Status of the PHY. As long as the LS is high, you rarely poll it, may after not receiving any packet for e.g. 5 seconds.

While the LS is low, just discard outgoing messages. I would poll the LS status frequently (at least every second) just to see when it comes up again.

When I get a chance I will try the first option: a reinitialisation including HDCP after the Link Status comes up again.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by hmf55 on February 26, 2015

Hi, I'm reading this thread having the same issue. I'm using the download 141019 not knowing if this bug is already fixed. I'm porting to the RX63N from renesas (Trying to get the zero Copy DMA running).

The problem I'figurured out is in "FreeRTOSIP.c" in Function 'pxUDPPayloadBufferto_NetworkBuffer' (line 916)

test for buffer alignment:

if( ( ( ( uint32t ) pvBuffer ) & portBYTEALIGNMENT_MASK ) == 0 )

this could not work since "pvBuffer" is misaligned since "sizeof( xUDPPacket_t )" is not 32 bit aligned.

I've changed that to

if( ( ( ( uint32t ) (pucBuffer + ipBUFFERPADDING) ) & portBYTEALIGNMENTMASK ) == 0 )

wich works for me.

Thanks.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on February 26, 2015

Hi,

Thanks for letting us know. There was indeed a typo in the mentioned function:

~~~~~ - if( ( ( ( uint32t ) pvBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 ) + if( ( ( ( uint32t ) pucBuffer ) & ( sizeof( pucBuffer ) - 1 ) ) == 0 ) ~~~~~

I'm porting to the RX63N from Renesas

Wow great! +TPC hasn't been ported to that part yet. If you like, please share your work (i.e. NetworkInterface.c) with the community. In return you may get an "early adopter status". Please drop an email to FreeRTOS if you want to know more about this.

Regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by hmf55 on March 3, 2015

Hi, I think I found the next bug: in "FreeRTOS_Sockets.c" in Line 788 the port is set with out considering the endianess:

Instead of

pxNetworkBuffer->usPort = pxDestinationAddress->sin_port;

I use this

pxNetworkBuffer->usPort = FreeRTOShtons(pxDestinationAddress->sinport);

which worked for me.

How can I share my work? Drop the files here?


FreeRTOS+TCP minor bug-finds

Posted by rtel on March 3, 2015

That's interesting - we are testing with both endians so I'm curious how we have missed that. I would be grateful if you could either attach the effected file to the post, or maybe better still (so there are not too many versions floating around the internet) send the file to me. I think you have my email address already - otherwise use the "business contact" link on http://www.FreeRTOS.org/contact and just mark it for my attention.

Regards (Richard).


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 3, 2015

Hi,

Thanks a lot for reporting, but it doesn't look like a bug.

This is the function you wrote about:

~~~~~ int32t FreeRTOSsendto( xSockett xSocket, const void *pvBuffer, sizet xTotalDataLength, uint32t ulFlags, const struct freertossockaddr *pxDestinationAddress, socklent xDestinationAddressLength ) { .... pxNetworkBuffer->usPort = pxDestinationAddress->sinport; .... pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr; .... } ~~~~~

The fields of pxDestinationAddress must be set before calling sendto(), for instance as follows:

~~~~~ /* FreeRTOSinetaddr() returns an IP address in network-byte-order: */ pxDestinationAddress->sinaddr = FreeRTOSinet_addr( "192.168.1.110" );

/* This would have the same effect: */
pxDestinationAddress->sin_addr = FreeRTOS_htonl( 0xC0A8016E );

pxDestinationAddress->sin_port = FreeRTOS_htons( 10000 );

~~~~~

When BSD sockets were first invented, everyone agreed that all values must be stored internally in the network-byte-order.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by hmf55 on March 4, 2015

oh sorry, one should - RTFM - first. Many Thanks.

Am 03.03.2015 um 19:13 schrieb Hein Tibosch: > Hi, > > Thanks a lot for reporting, but it doesn't look like a bug. > > This is the function you wrote about: > > int32t FreeRTOSsendto( xSockett xSocket, const void *pvBuffer, > sizet xTotalDataLength, uint32t ulFlags, > const struct freertossockaddr pxDestinationAddress, > socklent xDestinationAddressLength ) > { > .... > pxNetworkBuffer->usPort = pxDestinationAddress->sinport; > .... > pxNetworkBuffer->ulIPAddress = pxDestinationAddress->sin_addr; > .... > } > > The fields of |pxDestinationAddress| must be set before calling |sendto()|, for instance as follows: > > / FreeRTOSinetaddr() returns an IP address in network-byte-order: / > pxDestinationAddress->sinaddr = FreeRTOSinet_addr( "192.168.1.110" ); > > / This would have the same effect: */ > pxDestinationAddress->sinaddr = FreeRTOShtonl( 0xC0A8016E ); > > pxDestinationAddress->sinport = FreeRTOShtons( 10000 ); > > When BSD sockets were first invented, everyone agreed that all values must be stored internally in the network-byte-order. > > Regards. > > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ > > FreeRTOS+TCP minor bug-finds https://sourceforge.net/p/freertos/discussion/382005/thread/5591a1a9/?limit=25&page=1#3048 > > ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ > > Sent from sourceforge.net because you indicated interest in https://sourceforge.net/p/freertos/discussion/382005/ https://sourceforge.net/p/freertos/discussion/382005 > > To unsubscribe from further messages, please visit https://sourceforge.net/auth/subscriptions/ https://sourceforge.net/auth/subscriptions >


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 4, 2015

oh sorry, one should - RTFM - first.

Haha, I don't blame you, the forced network byte order is very confusing :-)

I have never understood why, on a little-endian machine, port-numbers and IP-addresses must be stored 'the other way around'. The swapping could also have remained hidden, somewhere in the driver.

E.g. HTTP is at port 80 (0x50), and when you inspect sin_addr you will see port 20480 (0x5000).

Within the +TCP library you'll see several fields and variables that are in native endianness, such as these socket fields:

~~~~~ uint32t xIPTcpSocket::ulRemoteIP; /* IP address of remote machine */ uint16t xIPTcpSocket::usRemotePort; /* Port on remote machine / uint16t xFreeRTOSSocket_t::usLocPort; / Local port on this machine */ ~~~~~

The reason was that it made debugging a lot easier.

Good luck!


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 4, 2015

Perhaps not a 'bug' as such, but I struggled with DHCP until I cleared the 'BROADCAST' flag from the flags field of the DHCP message.

i.e. in FreeRTOS_DHCP.C:prvCreatePartDHCPMessage() replace pxDHCPMessage->usFlags = dhcpBROADCAST; with pxDHCPMessage->usFlags = 0;

More detail in section 3.1.1 of RFC1542 http://tools.ietf.org/html/rfc1542 which implies that it should only be set exceptionally.

As an aside, I hope to make available an example project using FreeRTOS+TCP+CLI, built using LPCXpresso/LPCOpen and running on the Embedded Artists LPC4088 OEM + Base board.

Andy McC


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 5, 2015

Hi Andy,

Thanks for reporting this.

I just tried out both settings, with and without the DHCP BROADCAST flag.

pxDHCPMessage->usFlags = dhcpBROADCAST;
+TCP : 0.0.0.0      255.255.255.255  ..:ff:ff:ff  DHCP Discover
DHCP : 192.168.2.3  255.255.255.255  ..:ff:ff:ff  DHCP Offer
+TCP : 0.0.0.0      255.255.255.255  ..:ff:ff:ff  DHCP Request
DHCP : 192.168.2.3  255.255.255.255  ..:ff:ff:ff  DHCP ACK


pxDHCPMessage->usFlags = 0;
+TCP : 0.0.0.0      255.255.255.255  ..:ff:ff:ff  DHCP Discover
DHCP : 192.168.2.3  192.168.2.125    ..:a3:94:22  DHCP Offer
+TCP : 0.0.0.0      255.255.255.255  ..:ff:ff:ff  DHCP Request
DHCP : 192.168.2.3  192.168.2.125    ..:a3:94:22  DHCP ACK

The difference is that the DHCP server will 'unicast' the Offer and ACK responses.

Is your device able to receive broadcast messages?

Register: RXFILTERCTRL at address 0x2008 4200
Bit:      1 ABE AcceptBroadcastEn. When set to 1,
          all broadcast frames are accepted. 0

It might be an idea to use 'unicast' in the first instance, and only if that fails start 'Discover' with the BROADCAST flag.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 5, 2015

Hi Hein,

In desperation, I had set my device to accept anything, but nothing was coming in. It didn't help that I couldn't see any BOOTP/DHCP messages with Wireshark. In the end I went step by step through a working lwip implementation, comparing it with the +TCP (the BOOTP/DHCP packets for this didn't show up in Wireshark either).

I guess it has something to do with the way the network here is set up.

Would it be an idea to control the use of the dhcpBROADCAST flag with an ipcofigUSE_BLAHBLAH define, or alternatively build 'fallover' logic into the DHCP implementation?

Cheers,


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 5, 2015

I think I have found a possible bug in FreeRTOS_Sockets.c

In function FreeRTOS_recvfrom(),

if( pxSourceAddress != NULL )
{
	pxSourceAddress->sin_port = pxNetworkBuffer->usPort;
	pxSourceAddress->sin_addr = pxNetworkBuffer->ulIPAddress;
}

occurs after the non zero copy option has called vReleaseNetworkBufferAndDescriptor( pxNetworkBuffer ) I see no problem with moving it up to before the

if( ( ulFlags & FREERTOS_ZERO_COPY ) == 0 )

test

It is probable that the contents of pxNetworkBuffer->usPort and pxNetworkBuffer->ulIPAddress remain valid for long enough for the assignment to work as it is, but I wouldn't want to rely on it.

Opinions?


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 5, 2015

Would it be an idea to control the use of the dhcpBROADCAST flag with an ipcofigUSE_BLAHBLAH define, or alternatively build 'fallover' logic into the DHCP implementation?

Yes sure that is possible.

I was thinking of :

#define ipconfigDHCP_USES_UNICAST       1

And maybe this can even become '1' by default. I don't think it will hurt any existing setup as unicast works better than broadcast.

I will respond to your other message later,

Thanks, Hein


FreeRTOS+TCP minor bug-finds

Posted by rtel on March 5, 2015

Yes sure that is possible.

I was thinking of :

define ipconfigDHCPUSESUNICAST 1

Actually - I don't think that is a suitable solution because the firmware in a product would need to change depending on the network it was plugged in to. Something more adaptive would be more robust - either try uni cast first, then broadcast on the retry, then unicast on the next retry, etc. Or alternative start by sending both a unicast and a broadcast, if the DHCP server is not upset by such a thing.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 5, 2015

Hi Andy,

~~~~~ if( pxSourceAddress != NULL ) { pxSourceAddress->sinport = pxNetworkBuffer->usPort; pxSourceAddress->sinaddr = pxNetworkBuffer->ulIPAddress; } ~~~~~

occurs after the non zero copy option has called

Well seen, thanks!

Opinions?

Yes: assign earlier, before deleting the buffers.

Regards.


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 6, 2015

This may not be a bug, but I think it worth noting:

My PC is on a different sub-net to the IP address obtained by my development board. This makes it appear as a "remote" host when vARPRefreshCacheEntry() is called as part of processing a received UDP packet.

If ipconfigARP_STORES_REMOTE_ADDRESSES is 0 (in my case, it wasn't even defined, so I have since added it to FreeRTOSIPConfig.h), then no entry is made in the ARP table. When it comes to replying there is an ARP cache miss, so the outgoing UDP packet is turned into an ARP request to the obtained gateway IP address. A short burst of these appear on the network then my application runs off into the weeds (which might be my failure to handle the problem in my UDP server task; I wasn't able to catch exactly what happened).

If ipconfigARP_STORES_REMOTE_ADDRESSES is non-zero, the ARP entry is made, and there are 'happy bunnies' all round.

I now have a working LPC4088GCC version of the 'FreeRTOSPlusTCPandCLIWindows_Simulator' demo. I have rewritten vTCPNetStat() to take a buffer pointer as a parameter, which it fills with the formatted output. The call from prvIPTask() now passes xReceivedEvent.pvData as the pointer and FreeRTOS_netstat() sets up the buffer and passes the pointer in the IPStackEvent struct to xSendEventStructToIPTask(). Why did I do this? So that the demo prvNetStatCommand() could return the data to the calling CLI client by calling xSendEventStructToIPTask() with the pcWriteBuffer as the .pvData member.

Everything is a bit messy at the moment, so it's not quite ready for public consumption, but soon, soon. It will be good discipline for me to tidy up before moving on to Telnet, FTP, etc.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 6, 2015

Hi Andy,

Appreciate your feedback.

The classical idea about the netmask is: if an IP address is outside the netmask, it is a strange address and it is assumed to go through a router.

As you can read somewhere in the documentation, ipconfigARP_STORES_REMOTE_ADDRESSES was introduced to remember the MAC-address of all packets, also from devices that are outside the netmask (maybe from the Internet). Modern networks can have many different routers / gateways, not just one.

Glad to hear that defining ipconfigARP_STORES_REMOTE_ADDRESSES = 1 helps to solve your problem.

Actually I thing we should solve the kind of problem you're facing by adding routing rules.

Just curious: why isn't your laptop on the same netmask as your embedded devices? Aren't they both using the same DHCP server?

I have rewritten vTCPNetStat() to take a buffer pointer as a parameter

I'm sure Richard will like that too. It is much more in-line with the listings of tasks (uxTaskGetSystemState), that also works by providing a buffer and a buffer length.

All of my embedded projects have logging, and also the output of FreeRTOS_printf() will be added to that logging. The logging can be seen by making a telnet connection. Every logging-line is preceded by a time-stamp and a task number.

Here is an example of the 'netstat' command:

~~~~~ 321.682.673 [1]: netstat 321.682.773 [5]: Prot Port IP-Remote : Port R/T Status Alive tmout Child 321.682.905 [5]: TCP 8001 0.0.0.0 : 0 0/0 eTCPLISTEN 317646 0 0/12 321.683.041 [5]: TCP 8000 0.0.0.0 : 0 0/0 eTCPLISTEN 317646 0 0/12 321.683.122 [5]: TCP 21 0.0.0.0 : 0 0/0 eTCPLISTEN 317647 0 3/12 321.683.254 [5]: TCP 8021 0.0.0.0 : 0 0/0 eTCPLISTEN 317646 0 0/12 321.683.387 [5]: TCP 2402 192.168.2.3 : 2800 1/1 eESTABLISHED 1 20000 321.683.515 [5]: TCP 23 0.0.0.0 : 0 0/0 eTCPLISTEN 317642 0 0/3 321.683.651 [5]: TCP 80 0.0.0.0 : 0 0/0 eTCPLISTEN 317241 0 13/16 321.683.783 [5]: TCP 8080 0.0.0.0 : 0 0/0 eTCP_LISTEN 317241 0 0/16 321.683.917 [5]: TCP 80 192.168.2.3 : 2817 1/1 eESTABLISHED 3450 16532 321.684.049 [5]: TCP 80 192.168.2.3 : 2820 1/1 eESTABLISHED 4108 15858 321.684.124 [5]: TCP 21 192.168.2.3 : 2840 1/1 eESTABLISHED 5350 17058 321.684.251 [5]: TCP 21 192.168.2.3 : 2845 1/1 eESTABLISHED 2654 19836 321.684.384 [5]: TCP 21 192.168.2.3 : 2846 1/1 eESTABLISHED 2825 19664 321.684.511 [5]: TCP 80 192.168.2.3 : 3017 1/1 eESTABLISHED 4232 15732 321.684.639 [5]: TCP 80 192.168.2.3 : 3018 1/1 eESTABLISHED 3373 16611 321.684.772 [5]: TCP 80 192.168.2.3 : 3019 1/1 eESTABLISHED 3369 16615 321.684.898 [5]: TCP 80 192.168.2.3 : 3020 1/1 eESTABLISHED 142 62 321.685.123 [5]: TCP 80 192.168.2.3 : 3037 1/1 eESTABLISHED 106 96 321.685.250 [5]: TCP 80 192.168.2.3 : 3038 1/1 eESTABLISHED 3498 16585 321.685.382 [5]: TCP 80 192.168.2.3 : 3039 1/1 eESTABLISHED 3593 16481 321.685.510 [5]: TCP 80 192.168.2.3 : 3040 1/1 eESTABLISHED 4255 15904 321.685.643 [5]: TCP 80 192.168.2.3 : 3041 1/1 eESTABLISHED 3428 16755 321.685.771 [5]: TCP 80 192.168.2.3 : 3042 1/1 eESTABLISHED 3421 16763 321.685.903 [5]: TCP 80 192.168.2.3 : 3043 1/1 eESTABLISHED 3501 16983 321.685.938 [5]: UDP Port 30718 321.685.969 [5]: UDP Port 2000 321.686.005 [5]: UDP Port 30717 321.686.026 [5]: UDP Port 123 ~~~~~

Keep in mind that the resulting string of the 'netstat' command may become quite large.

Regards


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 6, 2015

Glad to hear that defining ipconfigARP_STORES_REMOTE_ADDRESSES = 1 helps to solve your problem.

Me too ;) though I'm still a little concerned that it fell over so badly without it.

Just curious: why isn't your laptop on the same netmask as your embedded devices? Aren't they both using the same DHCP server?

I'm not sure, they are plugged into the same network: the PC is on the 10.16.255.255 subnet and the dev board on 10.186.0.255

I have rewritten vTCPNetStat() to take a buffer pointer as a parameter

I'm sure Richard will like that too. It is much more in-line with the listings of tasks (uxTaskGetSystemState), that also works by providing a buffer and a buffer length.

I provide the size of the buffer (in the first sizeof(size_t) bytes of the buffer (I should perhaps create a struct with .length and .payload members)) and I check within vTCPNetStat() for potential overflow, returning if a newly snprintf()ed line will not fit in the remaining buffer. A refinement would be to be able to make multiple calls to get all of a large block of data, or deliberately restrict it to one line at a time. I'm not sure if that would be in danger of filling up the xNetworkEventQueue; probably not if subsequent calls for data wait for previous ones to finish, which is the likely case.

I'll include the modified +TCP source when I 'publish' next week.


FreeRTOS+TCP minor bug-finds

Posted by heinbali01 on March 6, 2015

This is my favorite way to respect the buffer size:

~~~~~ int iLength = 0;

pcBuffer[ 0 ] = '\0';
for( ;; )
{
    /* This method assumes that snprintf() will always
    leave the the buffer null-terminated. */
    iLength += snprintf( pcBuffer + iLength, iMaxLength - iLength, "xxx\n");
}

~~~~~

the PC is on the 10.16.255.255 subnet and the dev board on 10.186.0.255

Normally, with a 10.x.x.x address, the netmask should be set at 255.0.0.0. Likewise a 192.168.x.x address normally has a netmask of 255.255.255.0 In your case, both devices should be on a 10.255.255.255 network.

But, as these IP-ranges are private, you're entirely free to use whatever netmask you like.

In a meanwhile, I will start thinking about some simple routing rules. In a later stage, the possibility of multiple NIC's should be added to +TCP and that will ask for routing.

regards, Hein


FreeRTOS+TCP minor bug-finds

Posted by andymcc0 on March 13, 2015

I wrote: > As an aside, I hope to make available an example project using FreeRTOS+TCP+CLI, built using LPCXpresso/LPCOpen and running on the Embedded Artists LPC4088 OEM + Base board.

DONE, it can now be found at:

http://interactive.freertos.org/entries/80118239-FreeRTOS-TCP-Labs-port-and-demo-for-Embedded-Artists-LPC4088-Dev-Kit

Andy McC


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS