linux sürücü geliştirme (linux device driver development)
TRANSCRIPT
1/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Hoşgeldiniz
GNU/Linux İşletim Sistemi
için Sürücü Yazılımı Geliştirme
(GNU/Linux Device Driver Development)
Özgür Yazılım ve Linux Günleri ’15
Abdulkadir YAŞAR Yazılım Tasarım Mühendisi
Aselsan Inc.
2/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Konu Dışı
Linux Kernel
Konfigürasyon
Derleme ve Geliştirme araçları
Donanım
Elektronik altyapı (USB nasıl çalışır?)
Network (TCP/IP)
Yazılım
C/C++
Algoritmalar ve Veri Yapıları
Yardımcı Kütüphaneler
3/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
# cat ~/agenda.txt
Giriş
Sürücü Yazılımı nedir? Ne işe yarar?
Sürücü Tipleri
Linux Kernel ve Sürücü Desteği
Karakter Sürücüler
Linux Sürücü Modeli
Sürücü Örnekleri
I2C Sürücü Altyapısı
Linux Sürücü Özellikleri
Linux Kernel API (ABI)
Özgür ve Özgün örnek Sürücü Geliştirimi
4/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Sözlük
English Türkçe
Linux Kernel Linux Kernel
Device Aygıt
Device Driver Aygıt Sürücü
Controller/Adapter Kontrolcü/Adaptör
Microprocessor Mikroişlemci
System on Chip (SoC) System on Chip (SoC)
Bus Bus
Register (noun) Yazmaç
Register (verb) Kayıtlanma
Framework Framework
Subsystem Altsistem
Interface Arayüz
5/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Giriş
Sürücü Yazılımı nedir?
İşletim sisteminin donanım desteğini gerçekleyen parçası
Kimler sürücü yazılımı geliştirir?
Sistem geliştiriciler ve destekleyiciler
Donanım geliştiriciler
Sürücü tipleri
Karakter (Character): Mouse, klavye, UART, ..
Blok (Block): USB Disk, IDE, SATA, SCSI, ..
Network: TCP/IP, ieee802.11, ieee802.15 (Bt), PPP, ..
open(), read(), write(), close(), ioctl()
socket(), bind(), listen()
6/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
GNU/Linux Kernel
Uygulama katmanı
(userspace) # cat /dev/random
Kernel katmanı
(kernelspace)
7/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
GNU/Linux Kernel
arch/ - mimari bağımlı kaynak kodlar
arm/ - işlemci (cpu) mimarisi
arm/mach-omap2 - işlemci üreticisine ait kaynaklar (BSP)
drivers/ - Sürücülerle ilgili bütün kaynaklar
i2c/ input/ usb/ video/ tty/ ….
usb/core - USB sınıfına ait kernel framework ü
usb/storage – USB depolama protokolü ile ilgili kaynaklar
include/ - Veri tanımları, prototipler, makrolar…
Documentation/ - Linux Kernel’daki framework ve API lerle ilgili bilgiler
i2c/ usb/
8/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Karakter Sürücü
Karakter tabanlı erişim sağlanan sürücülerdir (input, seriport, fb, ..)
Linux 2.6 öncesi standart sürücü desteği
struct file_operations veriyapısı kullanıcı uygulamaları ve kernel
arasındaki soyutlamayı sağlar (include/linux/fs.h)
Bütün sürücülere dosya gibi erişim
struct file_operations { ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); ssize_t (*write) (struct file *, const char __user *, size_t,
loff_t *); int (*readdir) (struct file *, void *, filldir_t); unsigned int (*poll) (struct file *, struct poll_table_struct *); int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned
long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct inode *, struct file *); int (*release) (struct inode *, struct file *); [...]
};
9/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Karakter Sürücü
register_chrdev() / unregister_chrdev() yordamı karakter
sürücüsünün Linux Kernel’a eklenmesini/kaldırılmasını sağlar
(include/linux/fs.h)
static dev_t aselsan_dev = MKDEV(202,128); static struct cdev aselsan_cdev; static int __init aselsan_init (void) {
register_chrdev (aselsan_dev, 1, “aselsan-captouch"); cdev_init (&aselsan_cdev, &aselsan_fops ); cdev_add (&aselsan_cdev, aselsan_dev, aselsan_count);
} static void __exit aselsan_exit (void) {
cdev_del (&aselsan_cdev); unregister_chrdev (aselsan_dev, 1);
} module_init (aselsan_init); module_exit (aselsan_exit);
10/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Karakter Sürücü
Sürücü dosya işlemleri (struct file_operations) ile uygulama
katmanı için soyutlama sağlanır
Kullanıcı uygulamalarında sürücü kullanımı
Kernel space de sürücü işlemleri
fd = open("/dev/aselsan-captouch", O_RDWR); ret = read(fd, buf, bufsize); ret = write(fd, buf, bufsize);
static ssize_t aselsan_captouch_write (struct file *f, …) { …. } static ssize_t aselsan_captouch_read (struct file *f, …) {
…. } static struct file_operations aselsan_captouch_fops = { .read = aselsan_captouch_read, .write = aselsan_captouch_write };
11/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Sürücü Modeli
Standart Sürücü Dosya işlemleri (struct file_operations) bütün sürücü
tiplerini tanımlamak ve sürmek için yetersizdir
Linux 2.6 dan itibaren birçok sürücü direkt karakter ya da blok sürücü olarak
kayıtlanmak yerine belli bir framework altında tanımlanırlar
Framebuffer, Serial, USB, MMC, Input…
12/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Sürücü Modeli
Linux Sürücü Modeli (Linux v2.6)
Platform bağımsız sürücü yazılımı
Framework donanım özellikleri kullanıcı
katmanı için soyutlar
USB, I2C, Serial, Input, ..
Bus Infrastructure donanım
algılama/tanıma ve altyapı erişim desteğini
sağlar
read()
i2c_read()
i2c_read_xfer()
13/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Sürücü Modeli
Sürücü modeli tanımları ve ilişkileri include/linux/device.h
14/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Framebuffer Sürücüsü
Framebuffer (ekran) sürücüsü için framework drivers/video/
Framebuffer sürücü sınıfı (device class)
struct fb_ops yordamları (include/linux/fb.h)
struct fb_info Linux a kayıtlanacak
struct fb_ops { int (*fb_blank)(int blank, struct fb_info *info);
/* pan display */ int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info); /* Draws a rectangle */ void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect); /* Copy data from area to another */ void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region); /* Draws a image to the display */ void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
…. }
int register_framebuffer (struct fb_info *fb_info);
int unregister_framebuffer (struct fb_info *fb_info);
15/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Seri Port Sürücüsü
Seri port (UART) için framework: drivers/tty/serial
struct uart_ops yordamları (include/linux/serial_core.h)
struct uart_driver Linux a kayıtlanacak
struct uart_ops { unsigned int(*tx_empty)(struct uart_port *); void(*set_mctrl)(struct uart_port *, unsigned int mctrl); unsigned int(*get_mctrl)(struct uart_port *); void(*stop_tx)(struct uart_port *); void(*start_tx)(struct uart_port *); void(*send_xchar)(struct uart_port *, char ch); void(*stop_rx)(struct uart_port *); ….
}
int uart_register_driver (struct uart_driver *uart);
void uart_unregister_driver (struct uart_driver *uart);
16/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
I2C (SMBus) Sürücüsü
17/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
I2C Sürücüsü
Linux kernel altsistemleri (subsystem) sürücü ekleme/çıkarma ve
diğer yönetim yordamlarını sürücü geliştirimi için sağlar
I2C framework yordamları yardımıyla sisteme yeni sürücü eklenir
Sürücünün aktifleştirilmesi için probe() yordamının işletilmesi gerekir
Sürücü veri tanımlarını yapar
struct i2c_driver { … /* Standard driver model interfaces */ int (*probe)(struct i2c_client *, const struct i2c_device_id *); int (*remove)(struct i2c_client *); … … struct device_driver driver; const struct i2c_device_id *id_table; …
};
18/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
I2C Sürücüsü
static struct i2c_driver aselsan_i2c_driver = { .probe = aselsan_i2c_probe, .remove = aselsan_i2c_remove, .driver = { .name = "aselsan-i2c", .owner = THIS_MODULE, }
}; static int __init aselsan_init(void) {
int ret = 0; if ((ret = i2c_register_driver(&aselsan_i2c_driver))) pr_err(“Device registration failed. (%d)\n", ret); return ret;
} static void __exit aselsan_exit(void) { i2c_del_driver(&aselsan_i2c_driver); } module_init(aselsan_init); module_exit(aselsan_exit);
19/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
I2C Sürücüsü
Sürücünün yanında sürücüye ait bilgilerin de sisteme tanıtılması
gerekmektedir (I2C bus no, I2C adres, IRQ no, …)
Board-file çalışması (non-DeviceTree)
I2C için struct i2c_board_info (include/linux/i2c.h)
I2C sürücülerinin sisteme eklenmesi ve çalıştırılmasını sağlanır
static struct i2c_board_info am335x_i2c2_boardinfo[] = { {
I2C_BOARD_INFO("atmel_i2c_ts", 0x20), .irq = <interrupt irq no>,
}, {
I2C_BOARD_INFO(“aselsan_touchkey”, 0x29), .platform_data= &aselsan_i2c_data, .irq = <interrupt irq no>,
}, }; … i2c_register_board_info(1, aselsan_i2c2_boardinfo, ARRAY_SIZE(aselsan_i2c2_boardinfo));
20/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Sürücü Özellikleri
Sürücü donanımına ait bilgileri (clock, irq, konfigürasyon, ..) saklar
driver-specific data structure
Yardımcı yordamları (helper functions – irq_handler) tanımlar
Sürücünün kayıtlanacağı framework (i2c, usb, fb, ..) sistemi ile ilgili
yordamları tanımlar
probe() donanım ilkleme, üst katmanlara kayıtlanma
remove(), suspend(), resume(), enable(), disable()
Sürücünün kullanacağı bus altsistemine kayıtlanır
Örn. i2c_register(), usb_register()
Uygulama katmanı için ilgili dosya sistemlerini ayarlar
Sysfs, procfs, debugfs
21/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Kernel API (ABI)
Hata ayıklama (debugging)
printk()
dmesg (/proc/kmsg)
kdb – kernel debugger
Debugfs
Kernel configuration: DEBUG_FS
sudo mount -t debugfs none /sys/kernel/debug
Procfs
Sysfs (device classes)
22/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Kernel API
Bellek yönetimi
kmalloc(), kzalloc(), vmalloc()
kfree() – (kernel memory leakage = kernel crash)
Kesilme (interrupt) yönetimi
IRQ numara tanımlama
IRQ servis yordamı request_irq()
23/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Kernel API
Zamanlama (timing)
udelay()
struct timer_list my_time; (Documentation/timers)
Eşzamanlı erişim (Concurrency)
spin_lock(), spin_unlock() (bekleme)
mutex_lock(), mutex_unlock()
Kernel servisleri
kernel_thread()
workqueue
24/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Linux Kernel ABI (API)
Kernel veriyapıları
Linked List (struct list_head) (include/linux/list.h)
Hash List, Binary Tree, Red-black tree
Bildirim Zinciri (Notifier Chains)
Observer design pattern
Uygulama katmanı sürücü bilgilendirme
udev - Hotplug/Softplug
Firmware yükleme (download_firmware())
Kernel modül (module)
insmod, rmmod
25/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Örnek Sürücü Geliştirimi
Beaglebone
Rev.a3
Open Hardware
ARM cortex-a8
TI am335x işlemci
26/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Örnek Sürücü Geliştirimi
Dokunmatik Tuş Sensörünün Linux I2C altsistemine entegrasyonu
i2c-core.c i2c-dev.c I2C framework dosyaları drivers/i2c/
Adaptör/Kontrol Sürücü
(Adapter/Controller driver) drivers/i2c/busses/omap-i2c.c /dev/i2c-X
Aygıt Sürücü (Device driver) drivers/*/aselsan-captouch.c
27/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Örnek Sürücü Geliştirimi
Uygulama katmanından I2C sürücümüze erişim
i2c-tools
i2cset, i2cget, i2cdump
#include <linux/i2c.h> #define I2C_ADDR 0x29 int main () {
int value; int fd;
if ((fd = open ("/dev/i2c-2", O_RDWR)) < 0) { printf("Error opening file: %s\n", strerror(errno));
return 1; } if (ioctl (fd, I2C_SLAVE, I2C_ADDR) < 0) { printf("ioctl error: %s\n", strerror(errno)); return 1; } write (fd, 0xFF, 1); read (fd, &value, 1) return 0;
}
Uygulama katmanı
karakter sürücüsü
28/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Örnek Sürücü Geliştirimi
Peki Uygulama katmanı nasıl erişip kullanacak?
Sürücünün uygulama katmanı açısından fonksiyonu nedir?
29/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Örnek Sürücü Geliştirimi
Linux Kernel input altsistemi
Uygulama katmanı
struct input_dev { const char *name; ... unsigned long evbit[BITS_TO_LONGS(EV_CNT)]; unsigned long keybit[BITS_TO_LONGS(KEY_CNT)]; int (*getkeycode)(struct input_dev *dev, struct input_keymap_entry *ke); int (*open)(struct input_dev *dev); int (*event)(struct input_dev *dev,...);
}; int input_register_device (struct input_dev *); void input_unregister_device (struct input_dev *);
fd = open("/dev/input/eventX", O_RDWR); ret = read(fd, buf, bufsize); ret = write(fd, buf, bufsize);
30/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Daha Fazlası
31/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
Aselsan
www.aselsan.com.tr
Profesyonel Haberleşme Cihazları
32/30 Kadir Yaşar :: Linux Sürücü Yazılımı Geliştirme :: Özgür Yazılım ve Linux Günleri ’15 :: 27.03.15
TEŞEKKÜRLER
Many resources and tricks in the Internet you will find, but solutions to all technical issues in the Source lie.
Use the Source, Luke
HİÇ ÇEKİNME SOR
Abdulkadir Yaşar
Aselsan A.Ş.
Ankara, Turkey
Donanım destekleri için Tugser Kutlu’ya
Kaynak destekleri için Thomas Petazzoni’ye teşekkürler.. StackOverflow