Как работает адресация ввода-вывода с памятью?

Как работает адресация ввода-вывода с памятью?

Я пытаюсь понять образец, предоставленный I2S: любой получил его работает? .

Настройка часов:

#define BCM2708_PERI_BASE        0x20000000
#define CLOCK_BASE               (BCM2708_PERI_BASE + 0x101000) /* Clocks */

Сначала он отображает код так ...

clk_map = (unsigned char *)mmap(
      (caddr_t)clk_mem,
      MAP_BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      CLOCK_BASE
   );

Затем он что-то делает ...

 // Always use volatile pointer!
   clk = (volatile unsigned *)clk_map;

И когда он ссылается на эти нечетные дополнения 0x26 & 0x27, что это значит?

 printf("Disabling I2S clock\n");
 *(clk+0x26) = 0x5A000000;
 *(clk+0x27) = 0x5A000000;

 usleep(10);

 printf("Confiure I2S clock\n");
 *(clk+0x26) = 0x5A000001;
 *(clk+0x27) = 0x5A000000 | 3<<12 | 1<<9; // divider: 3.125==0b11.001

 usleep(10);
 printf("Enabling I2S clock\n");
 *(clk+0x26) = 0x5A000011;

Глядя на техническое описание, я вижу, где у них есть некоторые из этих значений, например, базовый адрес, но я изо всех сил пытаюсь понять других. Где определяется CLOCK_BASE и что происходит?

28 голосов | спросил Dog Ears 22 J0000006Europe/Moscow 2012, 03:20:31

2 ответа


18

На компьютере вы записываете указанный адрес памяти. Этот адрес распознается системой как аппаратный адрес, и соответствующее оборудование получает или отправляет соответствующее значение.

В большинстве аппаратных систем есть много разных регистров, которые могут быть установлены или прочитаны. У некоторых может быть несколько, у некоторых может быть много. Эти регистры будут сгруппированы в непрерывный диапазон. Базовый указатель указывает на первый в диапазоне, и вы пишете, например, второй порт с base_pointer + 1. Вам не обязательно, вы можете писать прямо на указатель, но использование смещения облегчает работу с.

Малина Pi распознает массивный набор аппаратных регистров по адресу 0x20000000. Доступ к диапазону регистров, управляющих системами синхронизации, осуществляется от BCM2708_PERI_BASE + 0x101000. Регистры, которые управляют часами I2S, являются 38-м и 39-м регистрами в этом блоке, написанными для использования BCM2708_PERI_BASE + 0x101000 + 0x26 и 0x27

Вы не можете просто изменить значения часов, но вам нужно отключить часы, изменить значения и перезапустить их.

Если этот ответ слишком прост, мои извинения. В этом случае ваш вопрос действительно хардкор, удачи. Вы можете найти эту ссылку полезную

Обновление: зачем использовать mmap и не записывать непосредственно в память?

Когда программа запускает адреса памяти, она считает, что она не является реальными адресами, они сопоставляются с реальными адресами диспетчером памяти. Это не позволяет одной программе воздействовать на другую. Два процесса могут читать и записывать на свой собственный адрес 1234 совершенно счастливо, и диспетчер памяти будет полностью разделять эти два местоположения.

Аппаратные порты, однако, находятся на абсолютных физических адресах. Но вы не можете писать им напрямую, потому что менеджер памяти возьмет ваш адрес и отобразит его в вашу личную область памяти.

В Linux /dev /mem есть файл символьного устройства, который является образом основная память компьютера

Если вы откроете это как файл, вы можете читать и писать ему, как файл. В поставляемом образце mem_fd - это дескриптор файла, который возник в результате открытия /dev /mem

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

Итак, в этом примере код создает дескриптор физической памяти, как если бы это был файл на диске, а затем просил систему обрабатывать его, как если бы это была память. Немного запутанный, но необходимый, чтобы обойти диспетчера виртуальной памяти и записать на фактический физический адрес. Значение 0x20000000, похоже, немного красная селедка. Код предлагает этот адрес как подсказку, системе не нужно отображать /dev /mem здесь, хотя это, вероятно, и делает. Обычно значение null будет передано, и система будет сопоставлять дескриптор файла по любому адресу, который, по его мнению, лучше всего.

Теперь физическая память отображается в виртуальную память процессов, а чтение и запись идут туда, где вы ожидаете.

Литература:

http: //www.kernel .org /док /человеко-страниц /онлайн /страницы /man2 /mmap.2.html

http: //www.raspberrypi .org /phpBB3 /viewtopic.php F = 44 & амп;? Т = 8496 & амп; р = 104359

https://superuser.com/questions/71389/what-is-dev-mem

ответил David Sykes 24 J0000006Europe/Moscow 2012, 00:51:22
1

@AlexChamberlain это связано с структурой ОС. Вы можете обойтись без mmap, но объявлен пейджинг, следовательно, нет прямого доступа. В режиме ядра вы можете обойтись без mmap, например, вставив ваш драйвер в качестве модуля ядра без необходимости mmap. Кроме того, в простейшем случае ОС, где не используется память таблицы страниц, вы можете получить доступ без mmap, то есть. прямой доступ к физическому адресу.

ответил Manoj Singh 23 Jpm1000000pmSat, 23 Jan 2016 21:21:33 +030016 2016, 21:21:33

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132