wake-up-neo.net

Was macht request_mem_region () eigentlich und wann wird es benötigt?

Ich lerne das Schreiben von Embedded-Linux-Treibern und habe beschlossen, ein paar GPIOs zu starten, um sicherzustellen, dass ich das Buch (LDD3, Kap. 9.4.1) richtig verstehe.

Ich kann die richtigen GPIO-Pins wie vorgesehen steuern (indem ich sie hoch und niedrig stelle, habe ich sie mit einem Multimeter abgetastet). Ich habe jedoch 2 Codeteile getestet, eines mit request_mem_region() und eines ohne. Ich erwarte, dass das ohne scheitern wird, aber beide funktionieren einwandfrei.

Code mit 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...

Code ohne 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...

Der einzige Unterschied, den ich in beiden Fällen feststellen kann, ist das Ergebnis der Ausführung eines cat /proc/iomem. Bei der Ausführung mit request_mem_region() wird eine zusätzliche Zeile mit 49056000-49056097 : GPIO3 angezeigt.

Meine Frage ist, warum request_mem_region() benötigt wird, da ich nur mit ioremap() noch mit der Hardwareadresse kommunizieren kann? Wann müssen wir also eigentlich request_mem_region() verwenden?

Vielen Dank für alle Antworten!

22

request_mem_region teilt dem Kernel mit, dass Ihr Treiber diesen Bereich von E/A-Adressen verwenden wird. Dadurch wird verhindert, dass andere Treiber über request_mem_region überlappende Aufrufe derselben Region durchführen. Dieser Mechanismus führt keine Art von Zuordnung durch, sondern ist ein reiner Reservierungsmechanismus, der darauf beruht, dass alle Gerätetreiber des Kernels Nice sein müssen und request_mem_region aufrufen, den Rückgabewert überprüfen und sich im Fehlerfall ordnungsgemäß verhalten müssen.

Es ist also völlig logisch, dass Ihr Code ohne request_mem_region funktioniert, es entspricht lediglich den Kernel-Codierungsregeln.

Ihr Code entspricht jedoch nicht dem Kernel-Codierstil. Außerdem gibt es eine vorhandene Infrastruktur für GPIOs mit dem Namen gpiolib, die Sie verwenden sollten, anstatt Ihre GPIO-Bankregister manuell neu zuzuordnen. An welcher Plattform arbeitest du gerade?

36

Die Verwendung von request_mem_region () und ioremap () in Gerätetreibern ist Jetzt veraltet. Sie sollten stattdessen die folgenden "verwalteten" Funktionen Verwenden, die die Treibercodierung und die Fehlerbehandlung vereinfachen:

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 Folie 276

0
jordi oliva