Snippet - XMODEM for Full .NET Framework on PC

I just posted XMODEM for Full .NET Framework on PC on Codeshare. Feel free to discuss and make suggestions here.

4 Likes

Hi Iggmoe
thank you for your very useful application.
Which boudrates can be reached on the FEZ-devices for file transfers when using packets and checksums. Is the speed much decreased by the overhead?

Hi, RoSchmi. XMODEM is a rather old and slow protocol, and the overhead is related to the chosen data packet size. The official standard accommodates packet sizes of 128 or 1024 bytes. You can override this by specifying a custom value for “Packet128NominalSize” (if using XModem-Classic or XModem-CRC) or “Packet1024NominalSize” (if using XModem-1K). Theoretically, larger packet sizes should reduce the overhead and result in higher throughput.

Here’s some performance data I collected by transferring a file between a PC and a G120 and measuring the time required to finish the file at 115200 baud. You will notice that the file transmission from the G120 to the PC does not improve much with increasing packet sizes and actually gets worse later on. I think this might be due to memory limitations on the G120. The PC to G120 times also hit a wall, likely due to the bottleneck imposed by a 115200 serial baud rate. Using a higher baud rate will likely improve those times.

File Size = 331776 Bytes


“XModem-1K” Packet Size = 1024 Data Bytes
PC to G120 = 42.6705599 sec
G120 to PC = 69.5956203 sec


“XModem-1K” Packet Size = 4096 Data Bytes
PC to G120 = 38.2124109 sec
G120 to PC = 62.2301480 sec


“XModem-1K” Packet Size = 8192 Data Bytes
PC to G120 = 38.8360436 sec
G120 to PC = 78.7747362 sec


“XModem-1K” Packet Size = 16384 Data Bytes
PC to G120 = 38.2297193 sec
G120 to PC = 87.9607345 sec

Thanks,
I didn’t expect that the Baudrate is as high: average around 70 kbits/sec from G120 to PC and around 40 kbits/sec in the other direction.
By the way, I don’t consider the X-modem protocol the be rather old, it was born in 1977!

I was 12 then! :slight_smile:

Interesting point though. What alternatives are there for transfer over RS232?

With the advent of the Internet and other serial protocols, RS232 serial is not used so often these days except in industrial interfacing. Not many devices come native with it anymore.

Where I work, RS232 still reigns supreme. For simple “it just works” reliability (usually), it’s hard to beat serial. For those who are curious, I rolled this XModem implementation so I can perform in-field update on a G120 that did not have any connections to the outside world except for RS232. The IFU works amazingly well!

Of course there’s also YModem and ZModem, but at much greater programming complexity.

Can I send a hex file using this? (Xmodem checksum)
Thanks.

hi Sidhs, welcome to the forum.

you can send a hex file without this, but this is a higher level protocol that assists in the integrity of that transfer. I’m sure you could use this, but what’s your use case?

@ sidhs1991 - Hi and welcome! This snippet can transfer a hex file. In fact, that’s the reason why I wrote this – to perform in-field update on a G120 through serial. Even if you connect and disconnect your serial cable mid-transfer, the protocol recovers gracefully, which is what it’s intended for.

Hi,

Can this do xmodem-1k crc?

I’d like to do a MS .net 2012 plugin for it, so that it automagically appears as part of the toolbox! But is there perhaps any features or bug fixes that I should work on first?

Thanks!

Hi blipton, this version can do CRC-1K. There are no glaring bugs that I’m aware of, but if you find anything please let me know.

Hi,

I am using a TCP/IP configuration. Will this work with such a system?

@ quang319 - I’m not a TCP/IP expert, but the concensus I’ve seen is that XModem is redundant when used over TCP/IP, since TCP already is a much more robust protocol. For data integrity, FTP would blow XModem away.

But if you really still want to use XModem, I would hunt for all the SerialPort methods in my snippet and override those with equivalent socket methods.

Great. Thank you very much!

Hi Thanks for the code, very useful.
I have spotted a small bug which causes _TotalUserDataBytesSent to be incremented incorrectly if the number of bytes added to the packet is not equal to the packet size.
here is the corrected code:

 dataToSend)
    {
        // Tracks the number of user data bytes that have been successfully sent during this method invocation
        int numUnpaddedDataBytesSentThisCall = 0;

        // Ensure that the Send() method is first called before this method
        if (SenderInitialized == false)
        {
            throw new ArgumentException("The XMODEM.Send() method must first be called before XMODEM.AddToOutboundPacket() is used.");
        }

        int dataOffset = 0;
        while (dataOffset < dataToSend.Length && TerminateSend == false)
        {

            // Instantiate outbound data packet if empty
            if (DataPacketToSend == null)
            {
                if (_Variant == Variants.XModem1K)
                    DataPacketToSend = new byte[_Packet1024NominalSize];
                else
                    DataPacketToSend = new byte[_Packet128NominalSize];

                Array.Copy(SenderDataPacketMasterTemplate, DataPacketToSend, DataPacketToSend.Length);
            }

            int numUnparsedDataBytes = dataToSend.Length - dataOffset;
            int numPacketDataBytesNeeded = DataPacketToSend.Length - NumUserDataBytesAddedToCurrentPacket;

            int numBytesToAdd;
            if (numPacketDataBytesNeeded >= numUnparsedDataBytes)
                numBytesToAdd = numUnparsedDataBytes;
            else
                numBytesToAdd = numPacketDataBytesNeeded;

            Array.Copy(dataToSend, dataOffset, DataPacketToSend, NumUserDataBytesAddedToCurrentPacket, numBytesToAdd);

            NumUserDataBytesAddedToCurrentPacket += numBytesToAdd;
            dataOffset += numBytesToAdd;
            _TotalUserDataBytesPacketized += numBytesToAdd;

            if (NumUserDataBytesAddedToCurrentPacket >= DataPacketToSend.Length)
            {
                TransmitPacket();

                // Determine if packet transmission was successful, or the maximum number of retries has been exhausted:
                if (PacketSuccessfullySent == true)
                {
                    // If packet successfully transmitted, keep a running tally of data bytes sent out.
                    // Only count actual user-provided data. Padding bytes are not counted.

                    //_TotalUserDataBytesSent += numBytesToAdd;//LEET1 removed 2016-01-11
                    //numUnpaddedDataBytesSentThisCall += numBytesToAdd;//LEET1 removed 2016-01-11

                    _TotalUserDataBytesSent += NumUserDataBytesAddedToCurrentPacket;//LEET1 added 2016-01-11
                    numUnpaddedDataBytesSentThisCall += NumUserDataBytesAddedToCurrentPacket;//LEET1 added 2016-01-11
                    // Reset control variables
                    NumUserDataBytesAddedToCurrentPacket = 0;

                    // Re-initialize a new packet
                    DataPacketToSend = null;
                }
                else if (TerminateSend == false)
                {
                    // Terminal condition if ACK not received even after multiple attempts
                    Abort();
                    _TerminationReason = TerminationReasonEnum.TooManyRetries;
                    break;
                }
            }
        }

        return numUnpaddedDataBytesSentThisCall;
    }

@ TomLee - Thanks. I will review and revise accordingly.

Many thanks for this. I’ve made the necessary changes to use this in netmf 4.3 and it’s working well.

:slight_smile:

@ wolfbuddy - Not sure if the file you used was for the PC, but there’s also a version that’s written specifically for NETMF (albeit for 4.2).

Sorry, it was the NETMF version that I was thanking you for. I had them both open so posted in the wrong thread.

Did you look at the changes that @ TomLee suggests? Are they relevant to the NETMF version?

Thanks again…For both versions :wink:

@ wolfbuddy - I folded @ TomLee’s suggestions into Version 3 of the code, in both NETMF and PC versions.

1 Like