当前位置:网站首页>uIP1. 0 actively sent problem understanding

uIP1. 0 actively sent problem understanding

2022-04-23 19:29:00 ToneChip

Recently LPC1768 Debugging uIP1.0 Network protocol code , The setting configures the mode of sending without subcontracting , The number of bytes originally intended to be sent and returned should not be too large , I have locally customized protocols . When debugging later , Find out TCP The agreement actually has the problem of sticking and unpacking

The problem of sticking bags is the most annoying , Originally, this light protocol stack has been out for many years , Now many people have found that they don't play this embedded thing , Looking for one uIP The protocol stack was not found , Finally, only the only slightly valuable article can be found on AMO Forum

Because it is used on the device side uIP Of TCP Server configuration , After the upper computer is connected to the device, it sends the specified protocol , But I found something on the device side TCP The server cannot actively send !!!! This is very annoying . Originally a duplex communication , Live into a single job

The problem is that

1. UI End send 14 Byte packet request to device , Device reply 56 byte , The equipment uIP The cache is 56*10 byte , That is, a single time uIP At most, I can only reply to 10 A frame . So if TCP Send sticky packets ,, Like, all of a sudden 20 individual 14 Byte request , Then the device will not respond at one time !!!!! The problem is coming , Need reply 20 When I get a bag uIP Not so much , You can only reply to 10 individual , So the rest 10 What can I do ???

2. The solution to the above problem is to do it on the device side ack Respond to , Reply first 10 A bag for UI,UI This time will reply to a ACK Give the equipment , Equipment received ACK Then process the remaining packages .

3. good , Follow the above ideas , Now there's another problem , Namely UI End send 14 Byte requests are a continuous process , Then it's possible UI First time received 10 When I get a bag , The second time is just about to be sent 14 byte , that TCP The agreement will put this ACK Flag Put it in 14 Bytes of TCP Send to the device together on the protocol ( In this way, the equipment cannot determine whether it is going to deal with ACK still newdata), Normally, it should be handled first ack My bag , Processing returned , To deal with newdata, This requires the device to store the received data as a cache ,. There is still a problem with sitting in a circular cache like this , Is that when UI After sending fast , The cache on the device side will still be full !

4. Suddenly thought of another idea

because uIP Now the default receive cache and send cache are the same memory , So let me make a distinction here , Receive cache settings 14*4 * 2 byte , The returned cache is set to 56*8 byte , In this case, can I guarantee that I can communicate symmetrically on the network ? Because the device's receive cache , Never more than 14*4 * 2 Byte receive , In this way, the returned value is 56*4*2 byte !!

Debug the code in the evening to test the idea ? Update later if feasible

2022 year 2 month 23 Update it every day

There is still a problem with the above idea , If uIP The send cache and receive cache are set to different memory segments , I found that there is still a lot to change , The final solution is to adjust the upper computer UI End TCP Sending speed , Turned out to be 13ms once , Change the back to 20ms I found that the probability of sticking bags is greatly reduced , Simultaneous coordination ACK Write code according to the rule of multiple returns, so that the sticky package can be basically handled

That's the problem , I am already in 48SP The processor is used on the project , Subsequent preparation, test and acceptance

Finally, this part of the debugging code in the previous paragraph

Very central !!!! It is the essence of years of work.




//TCP Callback function : Processing data from the network 
void TCP_Server_AppCall(void)
{
    int i = 0;
    // Serial port data processing ,g_u8Uart0RxDataMem Is the total cache of data received when running this function 
    unsigned char *pUart0RxDataMem = (unsigned char * )g_u8Uart0RxDataMem;
    unsigned char u8UartParaBuf[UART0_FRAME_MAX_LEN] = {0};     // Temporary variable , Process one frame of data at a time 
    unsigned char u8DataLen = 0;
    unsigned short u16TempRxStartIndex = 0;

    if(pUart0RxDataMem == NULL)
    {
        return ;
    }

    int nLen = 0;
    unsigned char *pUIPData = (unsigned char * )uip_appdata;
    unsigned short u16UIPDataSendLen = 0;
    unsigned short u16UIPOneFrameOutLen = 0;

    if(uip_connected())
    {
        guIPRxByteNum = 0;    // First connection 
    }

    if(uip_newdata())   // Received data from the server   Data exists uip_appdata[] Array 
    {
        nLen = gEmacTcpPocketLen;    //gEmacTcpPocketLen Changes with each reception 
        pUIPData = (unsigned char * )uip_appdata;

        if(nLen <= 0)       // If the received data is less than 0, Don't deal with 
        {
            nLen = nLen + 1;   // Debugging with 
            return ;
        }

        // uip_newdata  New data storage g_u8uIPDataBuff In cache , Copy by copy 
        for(i = 0; i < nLen; i++)
        {
            pUart0RxDataMem[gUart0RxIndex % UART0_RX_BUFF_LEN] = pUIPData[i];
            gUart0RxIndex = (gUart0RxIndex + 1) % UART0_RX_BUFF_LEN;

            guIPRxByteNum++;    // Number received plus 1

            if(guIPRxByteNum > UART0_RX_BUFF_LEN)     // Too much data to process 
            {
                guIPRxByteNum = guIPRxByteNum;
            }
        }

        // Start parsing data 
        while(guIPRxByteNum >= 3)
        {
            while(guIPRxByteNum >= 3)     // If the received data length is greater than 3 Bytes , You can perform frame header 0x55AA The judgment of the 
            {
                // Use the complete byte of the frame header to judge , One byte is error prone 
                if((pUart0RxDataMem[gUart0RxStartIndex] == 0x55) &&
                   (pUart0RxDataMem[(gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN] == 0xAA))
                {
                    u8DataLen = pUart0RxDataMem[((gUart0RxStartIndex + 2) % UART0_RX_BUFF_LEN)];// The first 3 The length of this frame in bytes , Take it out and judge whether it is 14 perhaps 56

                    if((UART_RX_PROTOCOL_SIZE == u8DataLen) ||
                       (UART_RX_ExPROTOCOL_SIZE == u8DataLen) )    // The loop ends when the specified protocol length is detected 
                    {
                        break;
                    }
                }

                // If the frame length is not equal to 14 perhaps 56, Then set the first byte of the frame header to 0, Remove a byte , Recycling judgment , Until it's detected 0x55AA Just jump out of the loop 
                pUart0RxDataMem[gUart0RxStartIndex % UART0_RX_BUFF_LEN] = 0;
                gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;  //gUart0RxStartIndex The size of is always 0~UART0_RX_BUFF_LEN Between , Prevent overflow 
                guIPRxByteNum--;          // Subtract the total number of bytes received 1
                guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 

            }

            // So let's go over here , Indicates that... Was detected 0x55AA
            if((guIPRxByteNum >= u8DataLen) && (u8DataLen > 0))     // If the number of bytes received is greater than the frame length in the protocol 
            {
                // Take out the data first (gUart0RxStartIndex The read offset remains unchanged ) Make a check 
                u16TempRxStartIndex = gUart0RxStartIndex;

                for(i = 0; i < u8DataLen; i++)
                {
                    u8UartParaBuf[i] = pUart0RxDataMem[u16TempRxStartIndex];// Check by taking out the data and storing it in u8UartParaBuf
                    u16TempRxStartIndex = (u16TempRxStartIndex + 1) % UART0_RX_BUFF_LEN;
                }

                if(CheckReciveDataCRC(u8UartParaBuf, u8DataLen))// If the verification is correct, the corresponding number of bytes can be cleared from the original cache and the data can be extracted according to the protocol 
                {
                    // How to judge whether this is an effective processing or an invalid processing 
                    u16UIPOneFrameOutLen = ProcessingProtocolData(u8UartParaBuf, u8DataLen);

                    if(NETWORK_RETURN_BUFLEN - u16UIPDataSendLen >= u16UIPOneFrameOutLen)
                    {
                        // Copy to uIP cache , What is different from the serial port is here 
                        memcpy(&pUIPData[u16UIPDataSendLen], u8UartParaBuf, u16UIPOneFrameOutLen * sizeof(unsigned char));
                        u16UIPDataSendLen += u16UIPOneFrameOutLen;
                        guIPOutFrameCount++;

                        for(i = 0; i < u8DataLen; i++)      // Clear the extracted data 
                        {
                            pUart0RxDataMem[gUart0RxStartIndex] = 0;
                            gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;
                            guIPRxByteNum--;
                            guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 
                        }
                    }
                    else
                    {
                        // The data here indicates that the returned memory is full , I can't save any more 
                        uip_send(pUIPData, u16UIPDataSendLen);
                        return;
                    }
                }
                else
                {
                    // If the check is wrong , The previous data has been cleared to 0, So the frame data is discarded 
                    pUart0RxDataMem[gUart0RxStartIndex] = 0;    // Just clear one byte and let while Cycle to clear other data 
                    gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;
                    guIPRxByteNum--;
                    guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 
                }
            }
        }

        uip_send(pUIPData, u16UIPDataSendLen);

    }

    //2022.02.19 Use ACK As a judgment, there are still BUG, Because when UI When the host computer sends data too fast and pastes packets, the return cache of packets that have not been processed in time still exceeds 
    // In this way, the new data will have ACK Sign a , In this way, we need to process the last data , It also needs to be dealt with newdata, It can cause packet loss 
    if(uip_acked())    // The received response indicates that the previous packet has been sent , Start processing the next package 
    {
        // Start parsing data 
        while(guIPRxByteNum >= 3)
        {
            while(guIPRxByteNum >= 3)     // If the received data length is greater than 3 Bytes , You can perform frame header 0x55AA The judgment of the 
            {
                // Use the complete byte of the frame header to judge , One byte is error prone 
                if((pUart0RxDataMem[gUart0RxStartIndex] == 0x55) &&
                   (pUart0RxDataMem[(gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN] == 0xAA))
                {
                    u8DataLen = pUart0RxDataMem[((gUart0RxStartIndex + 2) % UART0_RX_BUFF_LEN)];// The first 3 The length of this frame in bytes , Take it out and judge whether it is 14 perhaps 56

                    if((UART_RX_PROTOCOL_SIZE == u8DataLen) ||
                       (UART_RX_ExPROTOCOL_SIZE == u8DataLen) )    // The loop ends when the specified protocol length is detected 
                    {
                        break;
                    }
                }

                // If the frame length is not equal to 14 perhaps 56, Then set the first byte of the frame header to 0, Remove a byte , Recycling judgment , Until it's detected 0x55AA Just jump out of the loop 
                pUart0RxDataMem[gUart0RxStartIndex % UART0_RX_BUFF_LEN] = 0;
                gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;  //gUart0RxStartIndex The size of is always 0~UART0_RX_BUFF_LEN Between , Prevent overflow 
                guIPRxByteNum--;          // Subtract the total number of bytes received 1
                guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 

            }

            // So let's go over here , Indicates that... Was detected 0x55AA
            if((guIPRxByteNum >= u8DataLen) && (u8DataLen > 0))     // If the number of bytes received is greater than the frame length in the protocol 
            {
                // Take out the data first (gUart0RxStartIndex The read offset remains unchanged ) Make a check 
                u16TempRxStartIndex = gUart0RxStartIndex;

                for(i = 0; i < u8DataLen; i++)
                {
                    u8UartParaBuf[i] = pUart0RxDataMem[u16TempRxStartIndex];// Check by taking out the data and storing it in u8UartParaBuf
                    u16TempRxStartIndex = (u16TempRxStartIndex + 1) % UART0_RX_BUFF_LEN;
                }

                if(CheckReciveDataCRC(u8UartParaBuf, u8DataLen))// If the verification is correct, the corresponding number of bytes can be cleared from the original cache and the data can be extracted according to the protocol 
                {
                    u16UIPOneFrameOutLen = ProcessingProtocolData(u8UartParaBuf, u8DataLen);

                    if(NETWORK_RETURN_BUFLEN - u16UIPDataSendLen >= u16UIPOneFrameOutLen)
                    {
                        // Copy to uIP cache , What is different from the serial port is here 
                        memcpy(&pUIPData[u16UIPDataSendLen], u8UartParaBuf, u16UIPOneFrameOutLen * sizeof(unsigned char));
                        u16UIPDataSendLen += u16UIPOneFrameOutLen;
                        guIPOutFrameCount++;

                        for(i = 0; i < u8DataLen; i++)      // Clear the extracted data 
                        {
                            pUart0RxDataMem[gUart0RxStartIndex] = 0;
                            gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;
                            guIPRxByteNum--;
                            guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 
                        }
                    }
                    else
                    {
                        // The data here indicates that the returned memory is full , I can't save any more 
                        uip_send(pUIPData, u16UIPDataSendLen);
                        return;
                    }
                }
                else
                {
                    // If the check is wrong , The previous data has been cleared to 0, So the frame data is discarded 
                    pUart0RxDataMem[gUart0RxStartIndex] = 0;    // Just clear one byte and let while Cycle to clear other data 
                    gUart0RxStartIndex = (gUart0RxStartIndex + 1) % UART0_RX_BUFF_LEN;
                    guIPRxByteNum--;
                    guIPRxByteNum = ( guIPRxByteNum <= 0) ? 0 : guIPRxByteNum;    // Prevent negative number processing 
                }
            }
        }

        uip_send(pUIPData, u16UIPDataSendLen);
    }

}

版权声明
本文为[ToneChip]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231923488424.html