это правильно,.. если вы используете 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
Да, это то, чего я хочу достичь. Аппаратное обеспечение гарантирует, что значение, которое я прочитаю, не изменится, пока я не выполню синхронизацию. Я не могу найти правильный способ использовать указатели для указания HW-адреса I хочу, как я могу это сделать? – Leo
Ada делает указатели PITA, потому что безопасно использовать их PITA. Но иногда они нужны. –
Ну да, я понимаю это, но не могли бы вы указать мне в правильном направлении? Должен ли я использовать var доступа? – Leo