Getting debugger break on SerialPort Write command

0

I built a firmware updater app for a device and the host app connects to the device via a serial connection. The app has been working on small apps (~18KB) and I recently upped the firmware size to ~200KB.

Now the host app (C#) hangs on a serial port write and pausing the program in debug shows a Debugger Break.

The code pictured below reads a .HEX file line by line (not pictured) and writes blocks of 256 bytes one byte at a time using UART (serial comm). After 256 bytes, a checksum is sent for the block, and the loop is left to set up the next transfer.

What could be the reason for the app to hang on the write command? Is there some port or buffer maintenance that has to be done between blocks? I can see the byte counter for the block (0 to 255) and it doesn't hang on the same byte number.

This app is connecting to an ARM processor on a STM32F417IGT dev board.

Thanks for your help!

code block showing debug break on serialPort Write

Complete write function, in code:

    public void WriteNewAppToFlash(SerialPort _serialPort)
    {
        int byte_read = 0;
        long checksum = 0;
        var ff = new byte[] { 0xFF };

        // ------------------------------------------------------------------------------
        // -------- WRITE MEMORY --------------------------------------------------------
        // ------------------------------------------------------------------------------

        // for Address
        int baseAddress = 0x08004000;
        int offset = 0;

        // for string from HEX file
        string line;
        int length;
        int type;
        int hexChecksum = 0;

        bool sendAddress = true;

        int counter = 0;            // Counting the number of lines in the file
        int byteCounter = 0;        // Counting nmumber of bytes in the current block

        // Read the file and process one line at a time
        System.IO.StreamReader file = new System.IO.StreamReader(path);
        while ((line = file.ReadLine()) != null)
        {
            if (sendAddress == true)
            {
                /* 
    -------------------------------------------------------------------------------------------------------
                    SEND WRITE COMMAND
    -----------------------------------------------------------------------------------------------------*/

                // Send 0x43 (erase memory) and 0xBC
                var writeMem = new byte[] { 0x31 };
                var ce = new byte[] { 0xCE };

                _serialPort.Write(writeMem, 0, 1);
                //Console.WriteLine("writeMem = 0x" + BitConverter.ToInt32(writeMem, 0).ToString("X"));

                _serialPort.Write(ce, 0, 1);
                //Console.WriteLine("CE = 0x" + BitConverter.ToInt32(writeMem, 0).ToString("X"));

                // Receive ACK byte
                byte_read = _serialPort.ReadByte();
                //Console.WriteLine("ACK = 0x" + byte_read.ToString("X"));
                //Console.WriteLine("");

                 if (byte_read == NACK)
                {
                    //Console.WriteLine("NACK received for WRITE MEMORY start");
                    //Console.WriteLine("");
                }


                // -- end SEND 0x31 and 0xCE and wait for ACK -----------------------------------------


    -------------------------------------------------------------------------------------------------------
                SEND CURRENT ADDRESS AND CHECKSUM TO FLASH MEMORY
    -----------------------------------------------------------------------------------------------------*/

                Byte[] currentAddr = BitConverter.GetBytes(baseAddress + offset);

                // Increment offset by 0x100 (256 bytes)
                offset = offset + 0x00000100;

                //int msb;

                // Reset Checksum and XOR address
                checksum = 0;
                foreach (byte b in currentAddr)
                {
                    checksum ^= b;
                }

                //Console.WriteLine("cksum = " + checksum);

                Byte[] cksum = BitConverter.GetBytes(checksum);

                // Send address, MSB first, LSB last
                _serialPort.Write(currentAddr, 3, 1);
                _serialPort.Write(currentAddr, 2, 1);
                _serialPort.Write(currentAddr, 1, 1);
                _serialPort.Write(currentAddr, 0, 1);

                // Send checksum of address bytes
                _serialPort.Write(cksum, 0, 1);

                // Receive ACK byte
                byte_read = _serialPort.ReadByte();
                //Console.WriteLine("ACK = 0x" + byte_read.ToString("X"));
                //Console.WriteLine("");

                if (byte_read == NACK)
                {
                    //Console.WriteLine("NACK received for WRITE MEMORY address received");
                    //Console.WriteLine("");
                }
                // -- end addr or increment --------------------------------------------------------- 

                sendAddress = false;

                // Send number of bytes, always 256, the last group will be padded with 0xFF
                _serialPort.Write(ff, 0, 1);

                hexChecksum = 0;

            } // end IF for WRITE COMMAND and ADDRESS
            /* 
            -------------------------------------------------------------------------------------------------------
            WRITE 256 BYTES FROM HEX FILE TO FLASH MEMORY
            -----------------------------------------------------------------------------------------------------*/
            // FIRST CHARACTER in HEX FILE
            // The colon indicates the start of a "record"
            // Remove colon from beginning of string
            line = line.Substring(1, line.Length - 1);
            //Console.WriteLine(line);

            // Create byte array from string
            var bytes = GetBytesFromByteString(line).ToArray();

            // Assign values to variables from byte array
            type = bytes[3];

            /* Next TWO CHARACTERS in HEX FILE       00-data
               are the record type:                  01-EOF
                                                     02-   
                                                     03-   
                                                     04-    
                                                     05-                              */

            // Check type for data = 00
            if (type == 0)
            {
                // The first two characters represent the number of data bytes for the record
                // Obtain length, convert to int (counter for sending data)

                length = bytes[0];

                for ( int i = 0; i < length; i++ )
                {
                    // Send individual characters to device
                    _serialPort.Write(bytes, 4 + i, 1);

                    //Thread.Sleep(100);

                    // increment counter
                    byteCounter++;

                    if( byteCounter % 32 == 0 )
                    {
                        Thread.Sleep(40);
                    }

                    // Add byte to checksum
                    hexChecksum ^= bytes[4 + i];
                    //Console.WriteLine("cum checksum = " + hexChecksum);


                    // If counter == 256, reset counter, send checksum
                    if (byteCounter == 256)
                    {
                        sendAddress = true;
                        byteCounter = 0;
                        //Console.WriteLine("checksum = " + hexChecksum.ToString("X"));

                        // Convert checksum to a byte value and send
                        hexChecksum = hexChecksum ^ 0xFF;
                        byte csByte = Convert.ToByte(hexChecksum);
                        //Console.WriteLine("CSBYTE = " + Convert.ToInt32(csByte));

                        Byte[] csByte_arr = BitConverter.GetBytes(csByte);
                        _serialPort.Write(csByte_arr, 0, 1);


                        // Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        //Console.WriteLine("ACK = 0x" + byte_read.ToString("X"));
                        //Console.WriteLine("");

                        if (byte_read == NACK)
                        {
                            //Console.WriteLine("NACK received for write memory DATA received");
                            //Console.WriteLine("");
                        }
                    } // end IF byteCounter == 256

                    //Console.WriteLine(byteCounter);

                } // end FOR loop

            }
            else if (type == 5)
            {
                // Address thingy
                //Console.WriteLine("Hit address thingy");
                //Console.WriteLine("");
            }
            else if (type == 1)  // Check for end of file
            {
                // End of file

                while (byteCounter != 0)
                {

                    // Send individual bytes to device
                    _serialPort.Write(ff, 0, 1);

                    // increment counter
                    byteCounter++;

                    // Add byte to checksum
                    hexChecksum ^= 0xFF;
                    //Console.WriteLine("cum checksum = " + hexChecksum);

                    if (byteCounter == 256)
                    {
                        byteCounter = 0;
                        hexChecksum = hexChecksum ^ 0xFF;
                        byte csByte = Convert.ToByte(hexChecksum);
                        //Console.WriteLine("CSBYTE = " + Convert.ToInt32(csByte));

                        Byte[] csByte_arr = BitConverter.GetBytes(csByte);
                        _serialPort.Write(csByte_arr, 0, 1);

                        // Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        //Console.WriteLine("ACK = 0x" + byte_read.ToString("X"));
                        //Console.WriteLine("");

                        if (byte_read == NACK)
                        {
                            //Console.WriteLine("NACK received for write memory DATA received");
                            //Console.WriteLine("");
                        }
                    }
                }
            } // end ELSE if TYPE == 1

            counter++;
        } // end WHILE loop for loading hex file

        file.Close();
        //System.Console.WriteLine("There were {0} lines.", counter);
        //Console.WriteLine("");

       // -- end WRITE MEMORY ------------------------------------------------------

    }  // end  WriteNewAppToFlash

Changed the code to write a block of 256 bytes. It now writes two blocks and will not write the third block. The program executes to the Write line, the byte buffer is full, but it will not initiate the write.

    if (byteCounter >= 255)
                {

                    // Convert checksum to a byte value
                    hexChecksum = hexChecksum ^ 0xFF;
                    byte csByte = Convert.ToByte(hexChecksum);
                    Byte[] csByte_arr = BitConverter.GetBytes(csByte);

                    do
                    {
                        // send byte array
                        _serialPort.Write(buffer256, 0, 256);
                        Thread.Sleep(70);

                        // send checksum
                        _serialPort.Write(csByte_arr, 0, 1);

                        // Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        Thread.Sleep(100);

                        if (byte_read == NACK)
                        {
                            //Console.WriteLine("NACK received for write memory DATA received");
                            //Console.WriteLine("");
                        }
                    } while (byte_read != ACK);     

                    // Clear buffer, reset byte count, set flag to send write cmd and send new addr
                    Array.Clear(buffer256, 0, buffer256.Length);
                    byteCounter = 0;
                    sendAddress = true;
                }
c#
debugging
serial-port
freeze
asked on Stack Overflow Jul 28, 2017 by Gordon • edited Aug 9, 2017 by Gordon

1 Answer

0

I eventually got this app to work, but the exact reason for it working is unclear. Here is what I looked at and what changes I made:

Switched from transmitting single bytes and then a checksum at the end of 256 bytes, to placing 256 in a buffer and then transmitting all at once, followed by the checksum. This method was failing at first, but turned out to be faster than the previous method.

Changed the order of processing lines of HEX code and checking that a block is ready to send (see code below). The difference is small, but that more than anything seems to have allowed the whole thing to work. Before, it was checking for 256 bytes to send, sending it and then putting the data from a line in the next block of 256. I stepped through the code and didn't see anything that would make it fail, but it must have done something.

Since then the app has worked great and I no longer have any qualms about using the .NET SerialPort class with embedded devices.

// BLOCK WRITE TO MEMORY
            if (type == 0)
            {
                // Length of line is stored at byte 0, in this case 0x10, or 16 bytes of data
                length = bytes[0];

                // Add data from current line to buffer of 256 bytes
                for (int i = 0; i < length; i++)
                {
                    // Stuff all bytes from line into buffer of 256 bytes
                    buffer256[byteCounter++] = bytes[4 + i];

                    // Add byte to checksum
                    hexChecksum ^= bytes[4 + i];
                }

                // When buffer is full, send block of 256 bytes and checksum, reset variables for next block
                if (byteCounter >= 255)
                {

                    // Convert checksum to a byte value
                    hexChecksum = hexChecksum ^ 0xFF;
                    byte csByte = Convert.ToByte(hexChecksum);
                    Byte[] csByte_arr = BitConverter.GetBytes(csByte);

                    // Send byte array
                    _serialPort.Write(buffer256, 0, 256);

                    // For testing
                    // Console.WriteLine("block number [{0}]", ++blockCount);

                    //send checksum
                    _serialPort.Write(csByte_arr, 0, 1);

                    //Receive ACK byte
                    byte_read = _serialPort.ReadByte();
                    Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);

                    while (byte_read != ACK)
                    {
                        Array.Clear(buffer256, 0, buffer256.Length);
                        hexChecksum = 0;
                        lineCount = 0;

                        // reprocess the previous 16 lines stored in the line buffer
                        for ( int j = 0; j < 16; j++ )
                        {
                            line = lineBuffer[j];

                            line = line.Substring(1, line.Length - 1);
                            var bytesLocal = GetBytesFromByteString(line).ToArray();

                            length = bytesLocal[0];
                            for (int i = 0; i < length; i++)
                            {
                                buffer256[byteCounter++] = bytesLocal[4 + i];
                                hexChecksum ^= bytesLocal[4 + i];
                            }
                        }

                        // Convert checksum to a byte value
                        hexChecksum = hexChecksum ^ 0xFF;
                        byte csByteLocal = Convert.ToByte(hexChecksum);
                        Byte[] csByte_arrLocal = BitConverter.GetBytes(csByteLocal);

                        // Send byte array
                        _serialPort.Write(buffer256, 0, 256);

                        //send checksum
                        _serialPort.Write(csByte_arrLocal, 0, 1);

                        //Receive ACK byte
                        byte_read = _serialPort.ReadByte();
                        Console.WriteLine("block/ACK = [{0}] | {1}", ++blockCount, byte_read);

                    }

                    // Clear buffer, reset byte count, clear checksum, set flag to send write cmd/send new addr
                    Array.Clear(buffer256, 0, buffer256.Length);
                    byteCounter = 0;
                    hexChecksum = 0;
                    lineCount = 0;
                    sendAddress = true;
                }

            }  // end BLOCK WRITE TO MEMORY
answered on Stack Overflow Sep 1, 2017 by Gordon

User contributions licensed under CC BY-SA 3.0