Это правильно;если вы используете 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