FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [January 2017 Threads] FreeRTOS+TCP logs: crc swap: 0000Posted by yanvasilij on January 27, 2017 Hello,
I use FreeRTOS+TCP on my STM32F429. I created project with modbus TCP slave and start to poll data from my PC. Sometimes I get modbus errors (time out). I turned on FreeRTOS+TCP logs and found there the follows:
usGenerateProtocolChecksum[TCP]: crc swap: 0000
What does mean this logs?
Regards,
Vasilij
FreeRTOS+TCP logs: crc swap: 0000Posted by rtel on January 27, 2017 I think that is telling you a TCP checksum was correct (worked out to be
0). Not sure that is an error.
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on January 28, 2017 Do you think that the modbus errors occur at the moment that the TCP checksum equals to zero?
Beside logging, the code says:
~~~~
if( usChecksum == 0u )
{
usChecksum = ipCORRECTCRC; /* which is equal to 0xffff. */
}
else
{
usChecksum = FreeRTOShtons( usChecksum );
}
~~~~
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on January 29, 2017 The reason that 0x0 was transmitted as 0xffff is because of the UDP rule, see rfc768 :
If the computed checksum is zero, it is transmitted as all ones (the
equivalent in one's complement arithmetic). An all zero transmitted
checksum value means that the transmitter generated no checksum
(for debugging or for higher level protocols that don't care)
But if I'm not mistaken, for other protocols this should not apply and thus:
~~~~
if( ( usChecksum == 0u ) && ( ucProtocol == ( uint8t ) ipPROTOCOLUDP ) )
{
#if( ipconfigHASDEBUGPRINTF != 0 )
{
if( xOutgoingPacket != pdFALSE )
{
FreeRTOSdebugprintf( ( "usGenerateProtocolChecksum[%s]: crc swap: %04Xn", pcType, usChecksum ) );
}
}
#endif /* ipconfigHASDEBUGPRINTF != 0 /
/ In case of UDP, a calculated checksum of 0x0000 is transmitted
as 0xffff. A value of zero would mean that the checksum is not used. */
usChecksum = ( uint16t )0xffffu;
}
else
{
usChecksum = FreeRTOShtons( usChecksum );
}
~~~~
Does that stop the modbus errors?
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on January 30, 2017 I did test the above change but I forgot that my board is calculating all checksums in hardware :-(
The change to usGenerateProtocolChecksum() is a bit more complex than in the sketch here above. The translation from 0x0 to 0xffff should take place in two cases:
● When checking a CRC on an incoming packet.
● When the CRC of an UDP packet turns out to be zero
Please find attached 'protocol_checksum.c' which contains the entire function usGenerateProtocolChecksum() .
Regards.
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on February 1, 2017 Hi Vasilij,
I just tried out the original CRC method for TCP-packets which have a CRC of zero and trigger this message:
~~~~
usGenerateProtocolChecksum[TCP]: crc swap: 0000
~~~~
so the CRC's are sent as 0xFFFF.
It was not a fatal error, but it did trigger a warning in Wireshark: "TCP CHECKSUM 0xFFFF".
I sent the TCP packets to both my Linux machine and a Windows-10 laptop. The packet were accepted by both OS's.
Do you have any news? If you still get stuck, if you want, send me your current NetworkInterface.c for STM32F429.
FreeRTOS+TCP logs: crc swap: 0000Posted by yanvasilij on February 1, 2017 Hello Hein Tibosch,
I still have a problem. I figured out the follows: sometimes (about once in 2-4 minutes) tcp-response for request comes with big delay (it can be 100 ms, once a had delya 1500 ms!). Because of that reason ModbusPoll gets timeout error occurs, but tcp response comes. I turned off all task except freertos+tcp and network driver. Here my NetworkInterface.c.
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on February 1, 2017 Hi Vasilij,
Would it also be possible that you send a PCAP of the communication?
If the data is not to be made publicly, you may also send a PCAP to my email asdress (h point tibosch at freertos point org).
I would like to see the packets from the beginning of a connection (SYN), if possible.
FreeRTOS+TCP logs: crc swap: 0000Posted by yanvasilij on February 1, 2017 Attachmentspcap.pcap (5678937 bytes)
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on February 1, 2017 Hi Vasilij,
When I download your PCAP, it stops after 5,678,937 bytes. Is that the actual size? I wouldn't mind if you compress it next time :-)
Within this PCAP, I don't see any delays yet?
Within a TCP/Modbus connection, is it really necessary to poll so often? Why doesn't the client report when it has some news? Or at least report zero's after a longer period of time?
FreeRTOS+TCP logs: crc swap: 0000Posted by yanvasilij on February 3, 2017 Hello Hein Tibosch,
Sorry for big pcap - my fault. I promise to compress next time )).
There is difficult to see time-outs in pcap because there is too much request. There is about one 100 ms time-out in about 100k-200k requests/response pairs. So I wrote simple python script that sends modbus request to my modbus slave and measures delay between request and response. If delay is bigger than 50 ms it write delay value to text file (delay value in seconds). So the log in attachments.
Within a TCP/Modbus connection, is it really necessary to poll so often?
Yes it is. There is nothing I can do with it.
By the way. Here code with socket processing. May something wrong there:
~~~
static void createSockets (void * eMBRegInputCB, void * eMBRegHoldingCB,
void * eMBRegCoilsCB, void * eMBRegDiscreteCB)
{
mbPollActivate = xSemaphoreCreateBinary();
/* task for all sockets are created and never deleted.
* They just blocks when sokets are closed /
for (u32 i = 0; i < NUMOFSOCKETS; i++)
{
socketTaskParams[i].queue = xQueueCreate (1, sizeof(Sockett));
modbusTcp[i].eMBRegInputCB = (RegInputCBType)eMBRegInputCB;
modbusTcp[i].eMBRegHoldingCB = (RegHoldingCBType)eMBRegHoldingCB;
modbusTcp[i].eMBRegCoilsCB = (RegCoilsCBType)eMBRegCoilsCB;
modbusTcp[i].eMBRegDiscreteCB = (RegDiscreteCBType)eMBRegDiscreteCB;
socketTaskParams[i].modbusTcp = &modbusTcp[i];
socketTaskParams[i].modbusTcp->port.buf = socketTaskParams[i].buf;
socketTaskParams[i].isOppened = 0;
socketTaskParams[i].socketNum = i;
DEBUGLOG(("creating socket task %drn", socketTaskParams[i].socketNum ));
xTaskCreate( socketTask, "socketTask",
configMINIMALSTACKSIZE10, &socketTaskParams[i], 2, &socketTaskHandle[i]);
}
}
/* sockets processing task /
static void socketTask (void *p)
{
static const TickTypet xReceiveTimeOut = pdMSTOTICKS( 5000 );
static const TickTypet xSendTimeOut = pdMSTOTICKS( 5000 );
int32t inlen;
Sockett socket;
SocketTaskParams * params;
params = (SocketTaskParams)p;
u8 connectionIsOppened = 0;
DEBUGLOG(("socket %d task statedrn", params->socketNum));
for(;;)
{
xQueueReceive(params->queue, &socket, portMAXDELAY);
FreeRTOSsetsockopt( socket, 0, FREERTOSSORCVTIMEO, &xReceiveTimeOut,
sizeof( xReceiveTimeOut ) );
FreeRTOSsetsockopt( socket, 0, FREERTOSSOSNDTIMEO, &xSendTimeOut,
sizeof( xReceiveTimeOut ) );
DEBUGLOG(("Socket %d oppened!rn", params->socketNum));
connectionIsOppened = 1;
while (connectionIsOppened)
{
params->modbusTcp->port.tcpInit(MBTCPPORT);
params->modbusTcp->port.addTcpSocket(socket);
inlen = FreeRTOSrecv(socket, params->modbusTcp->port.buf, MAXMODBUSTCPFRAMELEN, 0);
if (inlen)
{
params->modbusTcp->port.bufLen = inlen;
params->modbusTcp->event.post( EVFRAMERECEIVED );
u8 tmp[50];
memset(tmp, 0, 50);
// I just emulate response for 20 holding register request (so here no modbus stack processing at all)
tmp[0] = params->modbusTcp->port.buf[0];
tmp[1] = params->modbusTcp->port.buf[1];
tmp[2] = 0x00;
tmp[3] = 0x00;
tmp[4] = 0x00;
tmp[5] = 0x2B;
tmp[6] = 0x01;
tmp[7] = 0x03;
tmp[8] = 0x28;
FreeRTOSsend( socket, tmp, 49, 0);
}
if (inlen < 0)
{
connectionIsOppened = 0;
break;
}
}
FreeRTOSshutdown( socket, FREERTOSSHUTRDWR );
do
{
if(FreeRTOSrecv(socket, params->modbusTcp->port.buf, MAXMODBUSTCPFRAMELEN, 0)<0)
break;
} while( 1 );
FreeRTOSclosesocket( socket );
params->isOppened = 0;
DEBUG_LOG(("Socket %d closed!rn", params->socketNum));
}
}
/* listenning task */
static void listeningTask (void *p)
{
static const TickTypet timeOut = portMAXDELAY;
struct freertossockaddr bindAddress, clientParams;
Sockett listenSocket, connectedSocket;
socklen_t clientParamsSize = sizeof( clientParams );
WinProperties_t xWinProps;
/* Fill in the buffer and window sizes that will be used by the socket. */
xWinProps.lTxBufSize = 300;
xWinProps.lTxWinSize = 2;
xWinProps.lRxBufSize = 300;
xWinProps.lRxWinSize = 2;
listenSocket = FreeRTOS_socket(FREERTOS_AF_INET, FREERTOS_SOCK_STREAM,
FREERTOS_IPPROTO_TCP);
FreeRTOS_setsockopt( listenSocket, 0,
FREERTOS_SO_RCVTIMEO, &timeOut, sizeof(timeOut) );
FreeRTOS_setsockopt( listenSocket, 0, FREERTOS_SO_WIN_PROPERTIES,
( void * ) &xWinProps, sizeof( xWinProps ) );
bindAddress.sin_port = MB_TCP_PORT;
bindAddress.sin_port = FreeRTOS_htons( bindAddress.sin_port );
FreeRTOS_bind( listenSocket, &bindAddress, sizeof( bindAddress ) );
/* When connection established corresponding task is unblocked */
FreeRTOS_listen( listenSocket, NUM_OF_SOCKETS );
for (;;)
{
connectedSocket = FreeRTOS_accept (listenSocket, &clientParams,
&clientParamsSize);
runSocketTask (connectedSocket);
taskYIELD();
}
}
void initModbusTcpTask (void * eMBRegInputCB, void * eMBRegHoldingCB,
void * eMBRegCoilsCB, void * eMBRegDiscreteCB)
{
createSockets (eMBRegInputCB, eMBRegHoldingCB, eMBRegCoilsCB, eMBRegDiscreteCB);
xTaskCreate( listeningTask, "listeningTask", configMINIMALSTACKSIZE*10, NULL, 1, NULL);
}
~~~
FreeRTOS+TCP logs: crc swap: 0000Posted by heinbali01 on February 5, 2017 Hi Vasilij,
Your code looks OK now.
Only two thing:
- When an API returns negative, you can look-up this value in
errno.h . A return value of -pdFREERTOS_ERRNO_EAGAIN is not fatail.
- You write the TCP server and you will never actively close a connection. Therefore you never have to call
shutdown() .
~~~~
- if (inlen < 0)
+ if ((inlen < 0) && (inlen != pdFREERTOSERRNOEAGAIN))
{
connectionIsOppened = 0;
break;
}
}
- FreeRTOSshutdown( socket, FREERTOSSHUTRDWR );
- do
- {
- if(FreeRTOSrecv(socket, params->modbusTcp->port.buf, MAXMODBUSTCPFRAMELEN, 0)<0)
- break;
- } while( 1 );
~~~~
Now about the time-outs:
I would think of missing or dropped packets. Please keep on checking uxGetMinimumFreeNetworkBuffers() : it should not drop below e.g. 3. It can be useful to study the time-outs: see if there were many other messages. See if those messages were broadcasts. Did the EMAC complain about overflows? Was there a temporary shortage of DMA descriptors?
The speed of polling can not be the problem: every 15 ms should be easy. Even if you have several simultaneous connections like this.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|