Dezvoltare drivere pentru Linux

De la YO3ITI
Sari la navigare Sari la căutare

Aceste pagini conțin o colecție de informații necesare în special celor care doresc să programeze diverse pe Linux (sau Raspberry – fiindcă e același lucru). Am început să adun această documentație pentru dezvoltarea driverelor de care am nevoie pentru diferitele proiecte electronice pe Raspberry.

Pe măsură ce le adun, o să le și structurez mai bine.

Dezvoltare drivere pentru Linux (Raspberry)

Pregătiri

Cazul platformei mele este un Raspberry Pi 4, versiunea c03112 cu un kernel versiunea 5.4.51-v7l+ (pentru lista completă de coduri de versiuni, vezi aici):

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ uname -a
Linux rpi-yo3iti 5.4.51-v7l+ #1327 SMP Thu Jul 23 11:04:39 BST 2020 armv7l GNU/Linux

Sau, prin /proc/version:

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ cat /proc/version
Linux version 5.4.51-v7l+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1327 SMP Thu Jul 23 11:04:39 BST 2020

Sau prin dmesg:

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ dmesg |grep Linux
[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 5.4.51-v7l+ (dom@buildbot) (gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) #1327 SMP Thu Jul 23 11:04:39 BST 2020
[    1.126787] usb usb1: Manufacturer: Linux 5.4.51-v7l+ xhci-hcd
[    1.128576] usb usb2: Manufacturer: Linux 5.4.51-v7l+ xhci-hcd
[   19.684585] mc: Linux media interface: v0.10
[   19.719580] videodev: Linux video capture interface: v2.00

În mod normal, header-ele kernel, pentru dezvoltare, trebuie să se potrivească cu versiunea de kernel:

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ apt search linux-header*
Sorting... Done
Full Text Search... Done
aufs-dkms/stable 4.19+20190211-1 all
  DKMS files to build and install aufs

linux-headers-4.18.0-3-common/stable 4.18.20-2+rpi1 all
  Common header files for Linux 4.18.0-3

linux-headers-4.18.0-3-common-rt/stable 4.18.20-2+rpi1 all
  Common header files for Linux 4.18.0-3-rt

linux-headers-4.9.0-6-all/stable 4.9.82-1+deb9u3+rpi2 armhf
  All header files for Linux 4.9 (meta-package)

linux-headers-4.9.0-6-all-armhf/stable 4.9.82-1+deb9u3+rpi2 armhf
  All header files for Linux 4.9 (meta-package)

[...]

... sper să nu avem probleme. :D Mai întâi trebuie instalate header-ele pentru kernel:

sudo rpi-update stable

Apoi:

apt get install raspberrypi-kernel-headers

Link-uri externe

Primul exemplu super simplu

#include <linux/module.h> /* necesar tuturor modulelor */
#include <linux/kernel.h> /* necesar KERN_INFO */

int init_module(void)
{
        printk(KERN_INFO "Hello world 1.\n");

        /*
         * A non 0 return means init module failed; module can't be loaded
         */
        return 0;
}

void cleanup_module(void) 
{
        printk(KERN_INFO "Goodbye world 1.\n");
}

Un fișier Makefile simplu:

obj-m += hello-1.o

all:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Apoi:

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ make
make -C /lib/modules/5.4.51-v7l+/build M=/home/tom/c/drivere/Salzman/01 modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.51-v7l+'
  CC [M]  /home/tom/c/drivere/Salzman/01/hello-1.o
  Building modules, stage 2.
  MODPOST 1 modules
WARNING: modpost: missing MODULE_LICENSE() in /home/tom/c/drivere/Salzman/01/hello-1.o
see include/linux/module.h for more information
  CC [M]  /home/tom/c/drivere/Salzman/01/hello-1.mod.o
  LD [M]  /home/tom/c/drivere/Salzman/01/hello-1.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.51-v7l+'

Odată cu versiunea 2.6 de kernel este adoptată o nouă convenție pentru denumirea fișierelor: modulele kernel au extensia .ko în locul extensiei vechi .o pentru a fi diferențiate de fișierele-obiect clasice. Modulele kernel conțin o secțiune .modinfo suplimentară, unde este păstrată informația despre modul. Informația poate fi accesată cu comanda modinfo hello-*.ko:

tom@rpi-yo3iti:~/c/drivere/Salzman/01 $ modinfo hello-1.ko
filename:       /home/tom/c/drivere/Salzman/01/hello-1.ko
srcversion:     140276773A3090F6F33891F
depends:        
name:           hello_1
vermagic:       5.4.51-v7l+ SMP mod_unload modversions ARMv7 p2v8

Al doilea exemplu

Metoda modernă de definire pentru metodele init și exit este dată mai jos:

/*
 * hello-2.c - demo pentru module_init() și module_exit()
 * Metoda mai nouă, preferată pentru init_module() și cleanup_module()
 */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>

static int __init hello_2_init(void)
{
        printk(KERN_INFO "Hello, world 2\n");
        return 0;
}

static void __exit hello_2_exit(void)
{
        printk(KERN_INFO "Goodbye, world 2\n");
}

module_init(hello_2_init);
module_exit(hello_2_exit);

Acum avem două module kernel. Fișierul Makefile arată așa (pentru ambele module):

obj-m += hello-1.o
obj-m += hello-2.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Compilarea:

tom@rpi-yo3iti:~/c/drivere/Salzman/02 $ ls -lsa
total 20
4 drwxr-xr-x 2 tom  tom  4096 Jul 28 19:25 .
4 drwxr-xr-x 4 tom  tom  4096 Jul 28 19:16 ..
4 -rw-r--r-- 1 root root  335 Jul 28 19:25 hello-1.c
4 -rw-r--r-- 1 root root  448 Jul 28 19:23 hello-2.c
4 -rw-r--r-- 1 root root  176 Jul 28 19:25 Makefile
tom@rpi-yo3iti:~/c/drivere/Salzman/02 $ make
make -C /lib/modules/5.4.51-v7l+/build M=/home/tom/c/drivere/Salzman/02 modules
make[1]: Entering directory '/usr/src/linux-headers-5.4.51-v7l+'
  CC [M]  /home/tom/c/drivere/Salzman/02/hello-1.o
  CC [M]  /home/tom/c/drivere/Salzman/02/hello-2.o
  Building modules, stage 2.
  MODPOST 2 modules
WARNING: modpost: missing MODULE_LICENSE() in /home/tom/c/drivere/Salzman/02/hello-1.o
see include/linux/module.h for more information
WARNING: modpost: missing MODULE_LICENSE() in /home/tom/c/drivere/Salzman/02/hello-2.o
see include/linux/module.h for more information
  CC [M]  /home/tom/c/drivere/Salzman/02/hello-1.mod.o
  LD [M]  /home/tom/c/drivere/Salzman/02/hello-1.ko
  CC [M]  /home/tom/c/drivere/Salzman/02/hello-2.mod.o
  LD [M]  /home/tom/c/drivere/Salzman/02/hello-2.ko
make[1]: Leaving directory '/usr/src/linux-headers-5.4.51-v7l+'