将固定大小的数组转换为相同大小的记录

convert fixed size array to record of same size

这可能是一个简单的问题,但作为一个新手,我无法理解它。

我有一个返回固定大小数组的函数。我正在尝试将此数组转换为相同大小的记录

函数签名是这样的:

type Control is new UInt8_Array (1 .. 2);
function readControl (Command : Control) return Control;

我正在尝试将两个字节 (UInt8) 放入记录 Contro_Status_Bytes 中,定义如下:

 type Control_Status_MSB is
  record
     RES_UP     : Boolean;
     QMAX_UP    : Boolean;
     BCA        : Boolean;
     CCA        : Boolean;
     CALMODE    : Boolean;
     SS         : Boolean;
     WDRESET    : Boolean;
     SHUTDOWNEN : Boolean;
  end record;

for Control_Status_MSB use
  record
     RES_UP     at 0 range 0 .. 0;
     QMAX_UP    at 0 range 1 .. 1;
     BCA        at 0 range 2 .. 2;
     CCA        at 0 range 3 .. 3;
     CALMODE    at 0 range 4 .. 4;
     SS         at 0 range 5 .. 5;
     WDRESET    at 0 range 6 .. 6;
     SHUTDOWNEN at 0 range 7 .. 7;
  end record;


type Control_Status_LSB is
  record
     VOK       : Boolean;
     RUP_DIS   : Boolean;
     LDMD      : Boolean;
     SLEEP     : Boolean;
     HIBERNATE : Boolean;
     INITCOMP  : Boolean;
  end record;

for Control_Status_LSB use
  record
     VOK at 0 range 1 .. 1;
  end record;

type Control_Status_Bytes is
  record
     HighByte : Control_Status_MSB;
     LowByte  : Control_Status_LSB;
  end record;

我认为一定可以在不进行未经检查的转换的情况下将数组转换为记录,反之亦然。但目前我错过了一些东西。

更新:这可能是一个有效的answer/way,我是在阅读@Simons 的回答后想到的。

function readControl (Command : Control) return Control_Status_Bytes is
  CSB : Control_Status_Bytes;
begin
  -- do stuff return UInt8_Array of size 2 as response
  CSB.HighByte := response'First;
  CSB.LowByte  := response'Last;
  return CSB;
end readControl;

未经检查的转换是通常的方式。

但是对于 MCU(Atmel AVR、MSP430 等)中的 I/O 端口和外围寄存器,可以将其作为数字或布尔数组(或可能是记录)进行寻址,这是一个黑客...

   p1in                   : constant unsigned_8;     --  Port 1 Input 
   Pragma Volatile(p1in);
   Pragma Import(Ada, p1in);      -- see ARM C.6 (13)
   For p1in'Address use   16#20#;

   p1in_bits              : constant Byte;           --  Port 1 Input  Bits
   Pragma Volatile(p1in_bits);
   Pragma Import(Ada, p1in_bits);
   For p1in_bits'Address use   16#20#;

这将来自 I/O 端口 1 的输入映射到相同的地址,被视为 8 位无符号或字节(8 个布尔值的数组)。

你的情况相当于

For Control_Status_Record'Address use Control_Status_Array`Address;

请注意,您可能需要将 "pragma volatile" 附加到两个视图,如此处所示,这样对一个视图的更改不会丢失,因为另一个视图缓存在寄存器中。

总而言之,我推荐 Unchecked_Conversion 而不是这种方法。它专为工作而设计,避免与 Volatile 混淆。

这必须取决于 readControl 内部发生的情况,但是您不能直接将其 return 设为您想要的类型吗?

function readControl (Command : Control) return Control_Status_Bytes;

(我希望 Command 实际上也有一些结构?)。

顺便说一句,你只定义了一个组件(VOK)在Control_Status_LSB中的位置,剩下的交给编译器。

@Simon Wright 的提示为我指明了正确的方向。

这是现在正在使用的并且有效:

function convert (ResponseArray : Control) return Control_Status_Bytes is
   Result : Control_Status_Bytes with
     Import, Convention => Ada, Address => ResponseArray'Address;
begin
   return Result;
end convert;