我为设备构建了固件更新程序应用程序,主机应用程序通过串行连接连接到设备。该应用程序一直在处理小型应用程序(约18KB),最近我将固件大小提升到了大约200KB。
现在主机应用程序(C#)挂起串口写入并在调试中暂停程序显示调试器中断。
下图所示的代码逐行读取.HEX文件(未图示),并使用UART(串行通信)一次写入一个字节的256字节块。在256字节之后,为该块发送校验和,并留下循环以设置下一次传输。
应用程序挂起write命令的原因是什么?是否需要在块之间进行一些端口或缓冲区维护?我可以看到块的字节计数器(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字节的块。它现在写入两个块,不会写第三个块。程序执行到写入行,字节缓冲区已满,但不会启动写入。
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;
}
答案 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());
}
}
}