Ada 具有动态选择的记录聚合

Ada 具有动态选择的记录聚合,ada,Ada,我需要在硬件寄存器中写入一个由所有0组成的值,除了bitbit,其中寄存器有点像 type Bit_Number is range 0 .. 31; type Bits_1 is array (Bit_Number) of Boolean with Component_Size => 1, Size => 32; Register_1 : Bits_1 with Volatile, Address => System'To_Address (16#

我需要在硬件寄存器中写入一个由所有
0
组成的值,除了bit
bit
,其中寄存器有点像

type Bit_Number is range 0 .. 31;
type Bits_1 is array (Bit_Number) of Boolean
with
  Component_Size => 1,
  Size => 32;

Register_1 : Bits_1
  with
    Volatile,
    Address => System'To_Address (16#1234_5678#);
Register_1
(Atmel的ATSAM3X8E中的典型寄存器,如Arduino Due中的寄存器)被定义为仅写,未指定读取时返回的内容,也未指定访问宽度是否合法;我们所知道的是,当我们写入寄存器时,只有
1
位起作用。(顺便说一句,这意味着特定于GNAT的方面
Volatile\u Full\u Access
或中建议的更改不会有帮助)

在GPIO外围设备中启用管脚涉及在多个寄存器中设置其
。由于我无法更改()的原因,每个寄存器都有自己的
Bits_1
数组类型

我想写作

procedure Set_Bit (Bit : Bit_Number) is
begin
   Register_1 := (Bit => True, others => False);
   Register_2 := (Bit => True, others => False);
   ...
end Set_Bit;
但是编译器说

19.    procedure Set_Bit (Bit : Bit_Number) is
20.    begin
21.       Register_1 := (Bit => True, others => False);
                         |
    >>> dynamic or empty choice in aggregate must be the only choice
指的是,

数组\u组件\u关联的离散\u选项\u列表允许具有离散\u选项,该离散\u选项是非静态选项\u表达式,或者是定义非静态或空范围的子类型\u指示或范围,前提是它是其离散\u选项\u列表的单个离散\u选项,在数组集合中只有一个数组分量关联

我可以解决这个问题

procedure Set_Bit (Bit : Bit_Number) is
begin
   declare
      B : Bits_1 := (others => False);
   begin
      B (Bit) := True;
      Register_1 := B;
   end;
   ... ad nauseam
end Set_Bit;

但这似乎很笨拙!还有其他建议吗?

它必须是数组吗? 另一种选择是:

with Interfaces;
procedure Set_Bit is
   Register : Interfaces.Unsigned_32;
begin
   for J in 0..31 loop
      Register := 2**J;
   end loop;
end Set_Bit;

我认为这可能有点麻烦,但如果您需要一个数组,可以使用串联切片聚合将其作为一个整体进行初始化:

    for J in 0 .. 31 loop
       Register := Bits'(others => False)(0..J-1) &
                   True & Bits'(others => False)(J+1..31);
    end loop;

它看起来像一个函数的候选者:

函数单位(设置:位号中)返回位为
开始
返回结果:位_1:=(其他=>False)do
结果(集合):=真;
末端返回;
端部单刀位;
然后:

Register_1:=单个_位(Set=>Some_位);
寄存器_2:=单个_位(Set=>另一个_位);
这将使用该操作

带有Ada.Integer\u Text\u IO;使用Ada.Integer\u Text\u IO;
使用Ada.Text_IO;使用Ada.Text\u IO;
使用Ada.u转换;
有接口;使用接口;
主要测试程序如下:
函数1_位(索引:Natural)返回的无符号_32为(左移位(1,索引));
类型位\u数组\u 32\u索引的范围为0。。31;
类型位数组索引范围为0。。16;
类型Bit_Array_32是布尔型数组(Bit_Array_32_Index),其分量_Size=>1,Size=>32;
类型Bit_Array_17是布尔型数组(Bit_Array_17_Index),其分量_Size=>1,Size=>17;
--对于每个新的数组类型,实例化一个convert函数。
函数转换是新的Ada.Unchecked_转换(无符号_32,位_数组_32);
函数转换是新的Ada.Unchecked_转换(无符号_32,位_数组_17);
B32:具有易失性的位_数组_32;
B17:具有易失性的位_数组_17;
开始
B17:=转换(一位(2))或转换(一位(5));
B32:=转换(一个_位(2)或一个_位(5));
对于B17回路的E
Put(布尔位置(E),1);
端环;
新线;
对于B32环路的E
Put(布尔位置(E),1);
端环;
结束;
结果 警告
这使用操作,但使用泛型

带有Ada.Text\u IO;使用Ada.Text\u IO;
使用Ada.u转换;
有接口;使用接口;
主要程序是
包Unsigned_32_IO是新的Ada.Text_IO.Modular_IO(Unsigned_32);
类型位\u数组\u 32\u索引的范围为0。。31;
类型位数组索引范围为0。。16;
类型Bit_Array_32是布尔型数组(Bit_Array_32_Index),其分量_Size=>1,Size=>32;
类型Bit_Array_17是布尔型数组(Bit_Array_17_Index),其分量_Size=>1,Size=>32;
通用的
Ⅰ型为();
类型T是布尔型数组(I);
程序通用输入(项目:T;宽度:字段;基数:数字);
程序通用输入(项目:T;宽度:字段;基数:数字)
函数Convert_To_Unsigned_32是新的Ada.Unchecked_转换(T,Unsigned_32);
开始
未签名的IO.Put(将未签名的IO.Put转换为未签名的IO.Put(项目),宽度,基址);
结束;
通用的
Ⅰ型为();
类型T是布尔型数组(I);
函数Generic_Shift_Left(值:Unsigned_32;金额:Natural)返回T;
函数Generic_Shift_Left(值:Unsigned_32;金额:Natural)返回T为
函数Convert_To_Bit_Array_32是新的Ada.Unchecked_转换(Unsigned_32,T);
开始
返回Convert_To_Bit_Array_32(Interfaces.Shift_Left(Value,Amount));
结束;
函数Shift_Left是新的通用_Shift_Left(位数组索引,位数组索引);
函数Shift_Left是新的通用_Shift_Left(位_数组_17索引,位_数组_17);
过程Put是新的通用Put(位\u数组\u 32\u索引,位\u数组\u 32);
过程Put是新的通用Put(位\u数组\u 17索引,位\u数组\u 17);
B32:具有易失性的位_数组_32;
B17:具有易失性的位_数组_17;
开始
B32:=左移(1,2)或左移(1,5);
B17:=左移(1,2)或左移(1,5);
Put(B17,0,2);
新线;
Put(B32,0,2);
结束;
结果
gprbuild-v 问题 它在big endian机器上工作吗?
我还没有测试。请参见

我假设您不只是执行
寄存器(J):=True,而且还显式地将其他字段设置为
False
,这是有原因的。除此之外,我想不出更优雅的解决方案;我以为我把问题抽象出来是有帮助的,但我做得太过分了。这会有用的。。我会试试看是否可以忍受!这当然是一种可能性,因为SVD2Ada实际上生成了数组视图和未签名视图的未经检查的并集。这就是我采用的解决方案。在不同的情况下可能会更好。这是一个很好的建议;在我的上下文中,问题是SVD2Ada用自己的数组类型声明每个寄存器!我认为这可能在big endian机器上不起作用。您的编译器没有在不同大小的对象之间发出UC警告吗?@Simon
00100100000000000
00100100000000000000000000000000
main.adb:21:04: warning: types for unchecked conversion have different sizes
main.adb:21:04: warning: size of "Unsigned_32" is 32, size of "Bit_Array_17" is 17
main.adb:21:04: warning: 15 high order bits of source will be ignored
2#100100#
2#100100#
GPRBUILD GPL 2015 (20150428) (i686-pc-mingw32)