让调试器中断 SerialPort Write 命令

Getting debugger break on SerialPort Write command

我为设备构建了一个固件更新应用程序,主机应用程序通过串行连接连接到设备。该应用程序一直在开发小型应用程序 (~18KB),我最近将固件大小增加到~200KB。

现在主机应用程序 (C#) 在串行端口写入时挂起,在调试中暂停程序会显示调试器中断。

下图的代码逐行读取 .HEX 文件(未显示)并使用 UART(串行通信)一次写入一个字节的 256 字节块。在 256 字节之后,为该块发送校验和,并留下循环以设置下一次传输。

应用程序挂起写入命令的原因可能是什么?是否有一些端口或缓冲区维护必须在块之间完成?我可以看到块的字节计数器(0 到 255)并且它没有挂在相同的字节数上。

此应用正在连接到 STM32F417IGT 开发板上的 ARM 处理器。

感谢您的帮助!

完成写入功能,在代码中:

    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

更改了代码以写入一个 256 字节的块。它现在写入两个块并且不会写入第三个块。程序执行到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;
                }

我最终让这个应用程序运行,但它运行的确切原因尚不清楚。以下是我查看的内容和所做的更改:

从传输单个字节,然后在 256 字节末尾传输校验和,切换到将 256 放入缓冲区,然后一次传输所有字节,然后传输校验和。这种方法起初失败了,但结果证明比以前的方法更快。

更改了处理十六进制代码行和检查块是否已准备好发送的顺序(参见下面的代码)。差异很小,但似乎最重要的是让整个事情顺利进行。之前,它检查要发送的 256 个字节,发送它,然后将一行中的数据放入下一个 256 块中。我单步执行了代码,没有看到任何会导致它失败的东西,但它一定已经完成了东西。

从那时起,该应用程序运行良好,我对在嵌入式设备上使用 .NET SerialPort class 不再有任何疑虑。

// 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