2017-08-11 61 views
2

我正在使用VisualStudio 2015在C#中开发固件升级应用程序。该应用程序使用基于XAML的表单和C#代码。固件升级的目标是运行STM32F417处理器(ARM Cortex M4)的定制板。 C#代码与417连接,使417跳转到其引导加载程序(出厂安装),并使用引导加载程序API加载新固件。.NET串行端口写入()添加字符和移动字节

在每次传输256字节(允许的最大传输)之后,将发送数据校验和和字节数,并从417收到一个ACK字节,以显示检查出该传输的所有内容。在传输256个数据块并测试传输后,传输将失败,我将C#代码设置为只传输.hex文件,而不进行任何其他检查。

我设置了将更新的固件作为.hex文件传输的代码。逐行。它将数据写入串行线路并在超级终端中作为文本捕获。 我实现它为256个字节写:

 byte[] buffer256 = new byte[256]; 

     // Read the file and process one line at a time 
     System.IO.StreamReader file = new System.IO.StreamReader(path); 
     while ((line = file.ReadLine()) != null) 
     { 
      line = line.Substring(1, line.Length - 1); 

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

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

      // BLOCK WRITE TO MEMORY 
      if (type == 0) // data type 
      { 
       length = bytes[0]; 

       if (byteCounter >= 255) 
       { 
        _serialPort.Write(buffer256, 0, 256); 

        Array.Clear(buffer256, 0, buffer256.Length); 
        byteCounter = 0; 
       } 

       for (int i = 0; i < length; i++) 
       { 
        buffer256[byteCounter++] = bytes[4 + i]; 
       } 
      } // end BLOCK WRITE TO MEMORY 

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

     file.Close(); 

同时也可作为单字节写:

 byte[] buffer256 = new byte[256]; 

     // Read the file and process one line at a time 
     System.IO.StreamReader file = new System.IO.StreamReader(path); 
     while ((line = file.ReadLine()) != null) 
     { 
      line = line.Substring(1, line.Length - 1); 

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

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

      if (type == 0) 
      { 
       length = bytes[0]; 

       for (int i = 0; i < length; i++) 
       { 
        _serialPort.Write(bytes, 4 + i, 1); 

       } // end FOR loop 

      }// end SINGLE BYTE WRITING 

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

     file.Close(); 

在这两种情况下,十六进制文件是通过使用SerialPort类写它改变。我尝试了各种其他方法,包括构建SerialPort类的BaseStream类中的WriteAsync(覆盖Stream方法)。

这里是一个样品相比所接收到的数据中的原始.hex文件的(8个字)(仅数据):

Original: 
00F8012B 002AF9D1 18467047 70B50646 
2DF0FEFC 04680546 0A220021 304600F0 

Received: 
00F8012B 002AF9D1 18464670 4770B506 
462DF0FE FC046805 460A2200 21304600 

这些线49和50出来的13391.校验对于一些这些街区也被检查并出错。我非常确定这就是固件升级失败的原因 - 引导加载程序正在根据接收的内容计算校验和,并将其与C#应用程序计算和发送的校验和进行比较时失败。

我的问题是:如果SerialPort(和基础流)不可靠,应该如何替换它以及如何?是否有可能只用一个C++类来替换SerialPort类?或者用C++或其他东西重写整个应用程序会更好吗?

+0

你可以包含'GetBytesFromByteString'的源代码吗? – Biscuits

+0

当GetBytesFromByteString遇到CR/LF字符时,可能会返回一个错误的(前一个)值? – Biscuits

+0

您是发送“hex文件”的可打印的十六进制内容还是在某个点处理二进制翻译?最后,我听说STM32工厂引导程序仅使用二进制协议,但也许有更新的版本。如果你的串行代码正在破坏文本,你就有一个非常基本的问题 - 如果你通过它发送每日人类语言会发生什么? –

回答

1

SerialPort类本身并不是不可靠的。我已经在桌面和众多CE设备上成功使用了它。问题可能是硬件在任一端,其中一个操作系统,一些繁琐的配置值或其中任何一个组合。

它也可能是你的代码。我不确定你做错了什么,但使用ReadLine将二进制数据读入字符串对我来说似乎很奇怪。你在调试器中验证了字节[]是否正确?

PS - 如果其中一个硬件问题与时间有关,切换到C++可能会有帮助。互操作对于这样的事情是非常痛苦的,所以我不会打扰重写整个应用程序,但我不知道你的情况,所以不能肯定地说。

+0

我只是在看昨天使用Interop的C++写函数。我计划使用的串行类有四个.cpp文件,我可以将它们放入DLL中?我不确定那部分。在C#方面,我提到了写入功能。现在我只需要将我的字节数组更改为与const void *兼容的东西。 该设置的任何输入都会有帮助,因为它对我来说是未知的领域。 – Gordon

+0

https://msdn.microsoft.com/en-us/library/55d3thsc.aspx检查出来。我建议通过COM互操作的pinvoke路径。所以标准的C DLL,并确保你的函数是......__ stdcall,我想说?无论如何,确保它们匹配。这很容易,但很难调试:) – zzxyz

+0

作为一种编辑,如果您非常熟悉将COM对象放在C++中,那么该路径使得C#端成为一个完全不成问题的工具。虽然我不喜欢这种方法,但ATL/MFC/COM足够生锈。因人而异 – zzxyz