在SerialPort Write命令

时间:2017-07-28 17:28:17

标签: c# debugging serial-port hang

我为设备构建了固件更新程序应用程序,主机应用程序通过串行连接连接到设备。该应用程序一直在处理小型应用程序(约18KB),最近我将固件大小提升到了大约200KB。

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

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

应用程序挂起write命令的原因是什么?是否需要在块之间进行一些端口或缓冲区维护?我可以看到块的字节计数器(0到255),它不会挂在相同的字节数上。

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

感谢您的帮助!

code block showing debug break on serialPort Write

完整的写入功能,代码:

    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字节的块。它现在写入两个块,不会写第三个块。程序执行到写入行,字节缓冲区已满,但不会启动写入。

    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;
                }

1 个答案:

答案 0 :(得分:0)

我最终得到了这个应用程序,但其工作的确切原因尚不清楚。以下是我看到的内容以及我所做的更改:

从传输单个字节开始,然后在256字节结束时进行校验和,将256放入缓冲区,然后一次性传输,然后是校验和。这种方法最初失败了,但结果比前一种方法更快。

更改了HEX代码的处理行的顺序并检查块是否准备好发送(参见下面的代码)。差异很小,但比任何事情似乎都让整个事情发挥作用。之前,它正在检查要发送的256个字节,发送它然后将数据放在256的下一个块中的一行中。我逐步完成代码并且没有看到任何会使其失败的内容,但它必须已经做了一些事情。

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

            string first = user1.FirstName;
            string last = user1.LastName;
            string ticket = user1.Ticket;
            string age = Convert.ToString(user1.Age);
            string command = Convert.ToString(("Insert into [TicketingVoting].dbo.Registration1 (FirstName,LastName,Age,Ticket) VALUES ('{0}','{1}','{2}','{3}');", first, last, age, ticket));
            try
            {
                SqlConnection conn = new SqlConnection("Data source=(local); Database=TicketingVoting;User Id=****;Password=****");
                conn.Open();

                SqlCommand insertdata = new SqlCommand(command, conn);
                insertdata.ExecuteReader();
                Console.WriteLine("Inserting Data Successfully");
                conn.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception Occur while creating table:" + e.Message + "\t" + e.GetType());
            }
        }
    }