2010-11-02 6 views
1

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

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

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

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

ответ

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

+0

Да, это то, чего я хочу достичь. Аппаратное обеспечение гарантирует, что значение, которое я прочитаю, не изменится, пока я не выполню синхронизацию. Я не могу найти правильный способ использовать указатели для указания HW-адреса I хочу, как я могу это сделать? – Leo

+0

Ada делает указатели PITA, потому что безопасно использовать их PITA. Но иногда они нужны. –

+0

Ну да, я понимаю это, но не могли бы вы указать мне в правильном направлении? Должен ли я использовать var доступа? – Leo

1

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

прочитайте индекс массива из регистра.

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

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

+0

Собственно, в этом случае вы можете написать C * better * в Ada, так как язык позволяет вам понять, как другая сторона кладет вещи и поместите свои поля записи ** точно ** там, что C не может действительно сделать. –

+0

Да, вот почему я потрудился дать ответ. –

Смежные вопросы