Как исправить ошибку сегментации?

Мне нужно прочитать интерфейс асинхронной внешней памяти (AEMIF), используя a TMS320DM368 во встроенной среде Linux на пользовательском оборудовании. На самом деле у меня еще нет аппаратного обеспечения, поэтому я тестирую код vala (ниже) на Leopardboard 368. 1-й AEMIF используется загрузчиком для чтения nand flash. Мой код пытается использовать 2-й AEMIF для чтения SRAM, которой нет на Leopardboard, но будет на пользовательском аппаратном обеспечении. Я подозреваю, что ошибка сегментации вызвана тем, что я пытаюсь получить доступ к защищенной памяти. Фактический пользовательский HW будет иметь несколько M SRAM, которые необходимо прочитать, но я пытаюсь заставить этот тестовый код читать 256 байтов. Как я могу исправить ошибку сегментации, вызванную приведенным ниже тестовым кодом? Нужно ли добавлять драйвер в ядро? Я бы предпочел не связываться с ядром, если это возможно. Существует ли встроенный в Linux метод для настройки или объявления определенных диапазонов адресов незащищенными?

uint8 * source = (uint8 *)0x04000000; // AEMIF Data (CE1)
uint32 * pA2CR = (uint32 *)0x01D10014; // AEMIF 2 Config Reg (CS3 space)
const uint32 READ_SETUP = 1; // Read setup: EMIF clock cycles - 1
*pA2CR = (READ_SETUP << 13);
const size_t size = 256;
var dest = new uint8[size];
memset(dest, 0, size);
memcpy(dest, source, size);

person jacknad    schedule 11.09.2012    source источник
comment
Segfault может быть не нарушением защиты, а просто доступом к пользовательской памяти, которая не сопоставлена ​​с физической памятью. Краткосрочным решением является mmap() файл вместо SRAM. Обратите внимание, что mmap() может быть предоставлен виртуальный адрес для использования или будет возвращать виртуальный адрес. Кстати, если у вас есть кастомное аппаратное обеспечение, вам придется возиться с ядром. Также см. stackoverflow.com/questions/11500291 /   -  person sawdust    schedule 12.09.2012
comment
@sawdust Пользовательский HW почти идентичен Leopoardboard, этот SRAM IF может быть единственным отклонением. Если мне придется изменить ядро, я это сделаю.   -  person jacknad    schedule 12.09.2012
comment
Всего несколько небольших замечаний со стороны Vala: вам не нужен memset (Vala инициализирует новые буферы до 0 для вас). Кроме того, вероятно, было бы проще просто сделать что-то вроде unowned uint8[] source = (uint8[]) 0x04000000;, тогда вы могли бы просто использовать нарезку массива для получения нужных данных (например, var dest = source[0:256];). Вам действительно почти никогда не нужно использовать необработанные указатели в Vala, хотя некоторые привязки (особенно libxml2 и posix) будут искушать вас сделать это.   -  person nemequ    schedule 12.09.2012
comment
Что именно вы пытаетесь сделать? Доступ к адресу памяти, которого нет на вашем устройстве? или попытаться издеваться над доступом к нему?   -  person auselen    schedule 12.09.2012
comment
@auselen Доступ к внешней памяти. Внешнее устройство на самом деле представляет собой ПЛИС, запрограммированную так, чтобы выглядеть как двухпортовая SRAM. DM368 должен читать его, но не должен записывать в него. Для этого идеально подходит AEMIF на DM368, так DM368 считывает флэш-память NAND во время загрузки.   -  person jacknad    schedule 12.09.2012
comment
Значит, этот адрес существует на устройстве? В системе на базе Linux всякий раз, когда мне нужно получить доступ к физическому адресу, я использую devmem2. Это может помочь вам проверить, можете ли вы получить доступ к адресу и написать аналогичный код. (вы можете найти его здесь: elinux.org/images/a/aa/ Devmem2.c)   -  person auselen    schedule 12.09.2012
comment
Ядро Linux не позволяет пользовательскому процессу просто пойти и изменить любое место в физической памяти, которое вы хотите. Вам либо нужно написать драйвер устройства, либо карту памяти в диапазоне ввода/вывода для устройства (если ваше ядро ​​это поддерживает). Но сделать последнее проблематично, так как нет хорошего способа контролировать доступ к области ввода/вывода. Таким образом, вы можете столкнуться с чем-то еще, что происходит, и вызвать всевозможные проблемы. Вы действительно должны делать это из ядра.   -  person John Szakmeister    schedule 12.09.2012
comment
К сожалению, некоторые программисты встраиваемых систем рассматривают средства защиты, предлагаемые Linux, как препятствия, которые необходимо либо демонтировать, либо обойти. Если ваш встроенный продукт действительно имеет ограниченный пользовательский интерфейс (например, ручную/визуальную панель управления) и стабильную микропрограмму, то хаки, подобные devmen2.c, скорее всего, не поставят под угрозу безопасность. Но если ваш продукт также имеет электронные интерфейсы, такие как последовательная консоль и/или сетевой интерфейс, то следует приложить все усилия для поддержки концепций безопасности Linux, как упоминает @jszakmeister.   -  person sawdust    schedule 12.09.2012
comment
@опилки Да. Пользовательский интерфейс ограничен USB и реагирует только на пользовательские команды.   -  person jacknad    schedule 12.09.2012
comment
Кстати, вместо того, чтобы жестко задавать начальный адрес и длину этой области памяти, элегантный метод заключается в параметризации этих значений. Еще лучше, если вы проверите HW на наличие этих значений в U-Boot до включения MMU. Я также использовал переменную среды U_Boot, чтобы переопределить результаты проверки. См. большой объем двоичных данных от загрузки до ядра Linux"> stackoverflow.com/questions/11580285/   -  person sawdust    schedule 12.09.2012


Ответы (1)


С DM386 не знаком, но работал на DM6446. В DM6446, но я ожидаю, что то же самое будет и в DM368, физические адреса переназначаются.

Я не знаю вашего сценария, но я думаю, вы могли бы написать драйвер с помощью miscdevice и предложить поддержку операций чтения и записи для вашей программы пользовательского пространства.

В своих модулях ядра я использую макрос IO_ADDRESS для переназначения и доступа к регистрам. Чтобы дать вам пример:

#define REG_PINMUX1     (*((volatile unsigned long *) (IO_ADDRESS(PINMUX1))))

а затем в коде у меня есть такие команды, как

REG_PINMUX0 &= ~(0x01000000);

Поэтому я думаю, что вы получаете segfault, потому что у вас неправильный указатель. И попытка доступа к аппаратным регистрам из пользовательской программы без модуля ядра не является хорошей стратегией.

person Ottavio Campana    schedule 13.09.2012