Невозможно получить доступ к Znyq AXI BRAM из Linux
В моем проекте данные записываются в BRAM (сгенерированный с помощью IP-генератора Block Ram) с пользовательского IP-адреса. Затем я использую контроллер AXI BRAM, чтобы связать память с шиной AXI и сделать ее доступной для Linux, работающего на ARM.
Базовый адрес для контроллера - 0x4200_0000 с диапазоном 8K (до 0x4200_1FFF). Память также имеет 8K позиций, каждая шириной 32 бита.
Чтобы убедиться, что проблема доступа не связана с данными, сгенерированными в моем настраиваемом IP-адресе, я инициализирую память, просто нумеруя каждый из 8К-адресов (таким образом, адрес 1 содержит 0x01 и т. Д. До 0x1fff).
Проблема возникает при попытке прочитать эти значения из Linux. С помощью devmem 0x42000001
в командной строке возвращает 0x04000000 и следующее:
Alignment trap: devmem (1257) PC=0x0001ca94 Instr=0xe7902005 Address=0xb6f9d2fd FSR 0x011
Похоже, что Linux ожидает, что каждое значение адреса будет отображаться в байте, а не в 32-битном слове. Выравнивание ловушек происходит до devmem 0x42000004
, который возвращает 0x00000004, правильное значение для четвертого направления, но значения в адресах, не кратных 4, не могут быть доступны. devmem 0x42000002
возвращает 0x00040000 (обратите внимание на смещение 0x04), а также ловушку выравнивания. Я обнаружил проблему с моим оригинальным скриптом Python, который использует mmap для отображения /dev/mem: мне нужно прочитать каждые 4 значения адреса, так как каждый отдельный адрес отображается в байт, но это означает, что я получаю только одно из каждых четырех значений.
Любые идеи о том, как правильно взаимодействовать с контроллером AXI и памятью за ним?
******* Редактировать, чтобы уточнить проблему, которая у меня есть. Если сомневаетесь, добавьте картинку:
1 ответ
Похоже, что Linux ожидает, что каждое значение адреса будет сопоставлено с байтом
Это стандартное отображение во всех современных процессорах. Когда вы используете AXI с шиной данных шире, чем на 8 бит, нижние биты адреса выбирают байт из шины данных AXI. Перейдите на веб-сайт ARM и загрузите спецификацию AXI.
Базовый адрес для контроллера - 0x4200_0000 с диапазоном 8K (до 0x4200_1FFF). Память также имеет 8K позиций, каждая шириной 32 бита.
Это неправильно, 8K из 32 битов имеют диапазон адресов 8K*4 = 0x0000 .. 0x7FFF.
Я предлагаю вам пересобрать BRAM, но использовать другие параметры для генератора Block Ram IP.
Я изменил RAM так, чтобы порт, выставленный контроллеру AXI, работал с 8 битами......
Ваша шина Zynq AXI, вероятно, имеет ширину 32 бита. Таким образом, стандартная подключенная память должна иметь ширину 32 бита, где вы должны иметь возможность побайтовой записи.
Если вы подключите 8-битную память к 32-битной шине и не измените адрес или неправильно адаптируете его, вы можете потерять 3 из 4 байтов.
Что мне не понятно, так это поведение, которое вы точно хотите.
- Стандартная 8Kx32 битная память с байтовым доступом
или же - 8kx8 битная память, где у вас есть байт 0x0, 0x4, 0x8 и т. Д.
В случае 2 вы должны использовать адрес AXI по-другому: вы должны сдвинуть биты адреса вверх на две позиции, чтобы каждый байт занимал 4 адреса. Вы также должны решить, где разместить байт:
Только позиция LS: привязать 24 бита MS к нулю
Только положение MS: привязать биты LS 24 к нулю
Повторяется во всех 4 местах: повторить байт четыре раза по 32 битам.
Что бы ты ни думал. (Это ваше оборудование, вы можете делать то, что вы хотите.)
Помните, что для любого модуля, который вы подключаете к шине AXI, предыдущие разделители AXI должны быть настроены так, чтобы охватывать правильный диапазон адресов. Но я предполагаю, что у вас нет ничего из этого.