提问人:Ingar Hjelle 提问时间:1/25/2023 最后编辑:Guru StronIngar Hjelle 更新时间:1/25/2023 访问量:152
在 ARM 上使用 Span<T> 会给出“System.DataMisalignedException:”
Using Span<T> on ARM gives "System.DataMisalignedException:"
问:
我正在尝试读取数据并使用 .NET 7 从 Modbus RTU 传感器转换数据。一切都在我的 Linux-x64 机器上工作,但当我尝试在 RevPi 核心 S linux-arm 上运行它时,情况就不一样了......
我正在使用 FluentModbus 版本 5.0.2:
fluentClient = new ModbusRtuClient()
{
BaudRate = 9600,
Parity = Parity.None,
StopBits = StopBits.One
};
fluentClient.Connect("/dev/ttyUSB" + port, ModbusEndianness.LittleEndian);
Console.WriteLine("Reading Calibration");
var calibration = fluentClient.ReadHoldingRegisters(1, 8704, 4);
var hexCalibration = Convert.ToHexString(calibration);
foreach (var item in calibration)
{
Console.Write(item);
}
foreach (var item in hexCalibration)
{
Console.Write(item);
}
//The code below works perfect on my machine running Ubuntu 22.04(linux-x64) but does not work //on RevPi Core running Debian custom Buster image (Linux-arm).
var floatCalibration = fluentClient.ReadHoldingRegisters<float>(1, 8704, 4);
Console.WriteLine("calibration K: " + floatCalibration[0]);
Console.WriteLine("calibration B: " + floatCalibration[1]);
终端输出 我的电脑:
Reading Calibration
000631541535764
0000003F9A993940
calibration K: 0.5
calibration B: 2.9
终端输出 RevPi Core:
Reading Calibration
000631541535764
0000003F9A993940
Unhandled exception. System.DataMisalignedException: A datatype misalignment was detected in a load or store instruction.
at exsys.Program.Main(String[] args) in /home/user/FunctionTest/Program.cs:line 179
Aborted
这是第 179 行: Console.WriteLine("calibration K: " + floatCalibration[0]);
是不是不能使用.Net7 Span<float> 在 linux Arm 上?我尝试了不同的设置,但还没有运气。也许其他人遇到了这个问题?
尝试将 dotnet publish 发布到独立的 linux-x64,一切正常。我只有在编译到 linux-arm 并运行它时才会收到错误。 尝试了不同的转换设置,但没有运气。 我已经更新了 2022 年 11 月发布的 RevPi Core S 上的映像,但它没有帮助。 尝试首先在 .NET 6 上运行,现在在 .NET 7 上运行。两者的错误相同。
答:
FluentModbus 在这里打破了对齐:
- https://github.com/Apollo3zehn/FluentModbus/blob/master/src/FluentModbus/Client/ModbusClient.cs#L155
然后调用这在 ARM 上是一个问题,因为文档说MemoryMarshal.Cast
此方法仅在支持未对齐内存访问的平台上或通过其他方式对齐内存块时受支持。
ARM 不是一个支持未对齐内存访问的平台。
一个好的解决方法是分配一个 ,调用返回的版本 ,然后调用 。float[]
ReadHoldingRegisters
Span<byte>
CopyTo(MemoryMarshal.AsBytes(destFloatArray))
评论
var calibration = fluentClient.ReadHoldingRegisters(1, 8704, 4); float[] destFloatArray = new float[2]; calibration.CopyTo(MemoryMarshal.AsBytes<float>(destFloatArray)); Console.WriteLine("calibration K: " + destFloatArray[0]); Console.WriteLine("calibration B: " + destFloatArray[1]);
评论
Span
memcpy
Buffer.BlockCopy