Ada在运行时修改变量地址

时间:2010-11-02 14:06:15

标签: hardware ada

我有一个数组和一个像这样声明的变量

NextPacketRegister     : array (1 .. Natural (Size)) of Unsigned_32;  
PacketBufferPointer    : Unsigned_32;  

for PacketBufferPointer'Address use To_Address (SPW_PORT_0_OUT_REG_ADDR);

for NextPacketRegister'Address use To_Address (16#A000_0000# + Integer_Address (PacketBufferPointer));

PacketBufferPointer指向您通过我们的主板PCI访问的HW寄存器。 NextPacketRegister使用此寄存器的值+ 16#A000_0000#

每次我访问NextPacketRegister时,在执行PCI访问的场景后面,这些访问速度非常慢,我们正试图消除此限制。

但是我似乎找不到在运行时修改NextPacketRegister'Address的方法(我想读取ONCE的PacketBufferPointer寄存器,然后只添加一次这个值+ 16#A000_0000#,所以我没有必要每次都进行PCI访问。

我环顾四周,但我不知道如何才能实现这一目标。

2 个答案:

答案 0 :(得分:3)

这是正确的;如果您使用for ...'address use覆盖特定地址的对象,则以后无法对其进行更改。

通常我会尽量避免叠加。你展示的是他们的一个缺点。另一个原因是,如果对象有任何需要初始化的部分,那么每次完成对象时都会重新初始化它们。

我有一件事需要提前询问:这看起来像是一个设备驱动程序。如果你不喜欢去PCI总线的打击,那很好。解决问题的显而易见的方法是将对象读入临时变量,并在不想使用PCI总线时使用它。但显然当你这样做时,你不再直接从设备读取,因此不会看到它对其内存映射寄存器所做的更改(并且你的更改不会直接进入那些内存映射寄存器)。这就是你想要的,对吧? Ada没有任何魔力允许您在不使用PCI总线的情况下在PCI总线上获取数据。

看起来你好像想到这一行:

for NextPacketRegister'Address use To_Address (16#A000_0000# + Integer_Address (PacketBufferPointer));

表示:“每次访问NextPacketRegister时,请找到PacketBufferPointer的值并将其覆盖在恰好位于当前的位置”。事实并非如此。 处理声明时只会发生一次 。此后,对NextPacketRegister[12]等内容的每次访问都会转到同一个地方,而无法访问PacketBufferPointer

另一种方法是使用指针和Unchecked_Conversion。这通常是我首选的叠加解决方案。它看起来更干,但你正在做的是毛茸茸的,所以它应该看起来那样。此外,它不会对重叠的内存区域执行初始化。我想如果依靠那些,那可能是件坏事。当然,如果你愿意,以这种方式覆盖可以导致PacketBufferPointer的访问权限。您可以根据编码方式控制它。

由于你询问了指针,在这种情况下,我认为你有一个非常有效的案例来使用包System.Address_to_Access_Conversions。我没有编译器方便,但我认为它会像这样:

type Next_Packet_Array is array (1 .. Natural (Size)) of Unsigned_32;
package Next_Packet_Array_Convert is new System.Address_To_Access_Conversions
   (Next_Packet_Array);
Synced_Next_Packet_Address : System.Address;

现在,当你“同步”时,我想你想要点击PacketBufferPointer获取寄存器值(作为SYSTEM.ADDRESS),并将其保存到变量中供以后使用:

Synced_Next_Packet_Address = 16#A000_0000# + Integer_Address (PacketBufferPointer);

当您想要访问Next_Packet_Array时,它将是这样的:Next_Packet_Array_Convert.To_Pointer (Synced_Next_Packet_Address).all

答案 1 :(得分:1)

创建一个结构(缓冲区数组?),这是你的数据包缓冲区集合的样子,并且位于数组开头的地址。

从寄存器中读取数组索引。

你可以用任何语言写C,甚至是Ada。

至少它有效,你得到一些合理的界限检查。