Что на самом деле делает request_mem_region () и когда это необходимо? - PullRequest
23 голосов
/ 07 октября 2011

Я учусь писать встроенный драйвер linux и решил запустить несколько GPIO, чтобы убедиться, что я правильно понимаю книгу (LDD3, chap9.4.1) .

Я могу управлять правильными выводами GPIO, как и предполагалось (делая это на высоком и низком уровне, я проверял мультиметром); Тем не менее, я протестировал 2 кода, один с request_mem_region(), а другой без. Я ожидаю, что один без сбоев, но оба работают просто отлично.

Код с request_mem_region:

if( request_mem_region( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "GPIO_140_141_conf_phys error:%s: unable to obtain I/O memory address 0x%08llX\n",
            DEVICE_NAME, PIN3_CONF_PHYS );

    return -EBUSY;
  }

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
//-----------------------------------------------------------------
if( request_mem_region( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5,DEVICE_NAME ) == NULL )
  {
    printk( KERN_ALERT
            "error:%s: unable to obtain I/O memory address 0x%08llX\n",
            DEVICE_NAME, GPIO_BANK5_PHYS );

    return -EBUSY;
  }

gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );

//some iowrite32() functions continue...

Код без request_mem_region():

pin3_conf = (u32)ioremap( PIN3_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin4_conf = (u32)ioremap( PIN4_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin5_conf = (u32)ioremap( PIN5_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
pin6_conf = (u32)ioremap( PIN6_CONF_PHYS, MAPPED_SIZE_GPIO_CONF);
gpio_virt = (u32)ioremap( GPIO_BANK5_PHYS, MAPPED_SIZE_GPIO_5 );
//some iowrite32() functions continue...

Единственное отличие, которое я могу наблюдать в обоих случаях, это результат выполнения cat /proc/iomem, в котором с request_mem_region() появится дополнительная строка, показывающая 49056000-49056097 : GPIO3.

У меня вопрос, зачем нужен request_mem_region(), так как я все еще могу общаться с аппаратным адресом только с ioremap()? Так когда же нам нужно использовать request_mem_region()?

Спасибо за любые ответы!

Ответы [ 2 ]

37 голосов
/ 12 октября 2011

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

Так что вполне логично, что ваш код работает без request_mem_region, просто он не соответствует правилам кодирования ядра.

Однако ваш код не соответствуетстиль кодирования ядра.Кроме того, существует существующая инфраструктура для обработки GPIO, называемая gpiolib, которую вы должны использовать вместо того, чтобы вручную переназначать свои банковские регистры GPIO.На какой платформе вы работаете?

0 голосов
/ 12 июля 2018

Использование request_mem_region () и ioremap () в драйверах устройств теперь не рекомендуется.Вместо этого следует использовать перечисленные ниже «управляемые» функции, которые упрощают кодирование драйвера и обработку ошибок:

devm_ioremap()
devm_iounmap()
devm_ioremap_resource(), Takes care of both the request and remapping operations

https://bootlin.com/doc/training/linux-kernel/linux-kernel-slides.pdf slide 276

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...