Ада Изменение адреса переменной во время выполнения - PullRequest
1 голос
/ 02 ноября 2010

У меня есть массив и переменная, объявленная следующим образом

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 указывает на регистры HW, к которым вы обращаетесь через PCI нашей платы. NextPacketRegister использует значение этого регистра + 16 # A000_0000 #

Дело в том, что каждый раз, когда я получаю доступ к NextPacketRegister, за сценой я выполняю доступ по PCI, этот доступ очень медленный, и мы пытаемся снять это ограничение.

Но, похоже, я не могу найти способ изменить NextPacketRegister'Address во время выполнения (я бы хотел прочитать ОДНАЖДЫ регистр PacketBufferPointer и затем добавить это значение + 16 # A000_0000 # только один раз, чтобы мне не пришлось выполнять доступ PCI каждый раз.

Я оглянулся, но понятия не имею, как мне этого добиться.

Ответы [ 2 ]

3 голосов
/ 02 ноября 2010

Это правильно;если вы используете for ...'address use для наложения объекта по определенному адресу, вы не сможете изменить его позже.

Обычно я стараюсь избегать наложений.То, что вы показываете, является одним из недостатков для них.Другое состоит в том, что если в объекте есть какие-либо части, требующие инициализации, они будут инициализироваться каждый раз при разработке объекта.

Хотя мне нужно кое-что спросить заранее: это похоже на драйвер устройства.Если вам не нравится переход на шину PCI, хорошо.Разумеется, очевидный способ решить вашу проблему - просто прочитать объект во временную переменную и использовать его, когда вы не хотите подключаться к шине PCI.Но очевидно, что когда вы это делаете, вы больше не читаете напрямую с устройства и, следовательно, не увидите изменений, которые оно внесло в свои регистры с отображением в памяти (и ваши изменения не будут направлены непосредственно на эти регистры с отображением в памяти).Это то, что вы хотите, верно?Ада не содержит магии, позволяющей вам получать данные на шине 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 голос
/ 08 ноября 2010

Создайте структуру (массив буферов?), Которая будет выглядеть так, как выглядит ваш набор буферов пакетов, и расположите ее по адресу начала массива.

считывает индекс массива из регистра.

Вы можете написать C на любом языке, даже на Ada.

По крайней мере, это сработает, и вы получите некоторые разумные проверки границ.

...