Download presentation
Presentation is loading. Please wait.
Published byHenry Lewis Modified over 9 years ago
1
Linux Device Driver 2009/04/08
2
Reference Book
3
Another Reference Book Embedded Linux Primer: A Practical, Real-World Approach By Christopher Hallinan Publisher: Prentice Hall Pub Date: September 18, 2006 Print ISBN-10: 0-13- 167984-8 Print ISBN-13: 978-0-13- 167984-9 Pages: 576
4
Website http://wiki.openwrt.org http://www.linuxsir.org http://www-128.ibm.com/developerworks/ http://lwn.net
5
Task of Device Driver Device initialization Hardware operation and management Data transfer between kernel space and user space Data exchange between hardware and kernel space
6
Function of device driver Hardware Device Driver Application Buffer User space Kernel Space
7
User space vs Kernel Space program ——From the point of view of CPU mode reg. memory address mapping memory address mapping memory access surveillance memory access surveillance Execution core Execution core Memory address data INT
8
User space vs Kernel Space program ——From the point of view of CPU 用户应用程序 内核程序 Kernel schedule/ Kernel API 用户应用程序 User space program 内核程序 Kernel space program Mode reg. Scheduler, change mode reg. to enter different mode Soft interrupt
9
Address Mapping and accessing of the physical address Physical Address space User processs1 User processs2 User process 3 Virtual address mapping user program access virtual using pointers physical address of IO device cannot be accessed by user program directly Virtual address mapping Virtual address mapping
10
Basic operation of device driver Device controller is often mapped into memory address D Q Device circuits Data bus Address matching circuit Address matching circuit Address bus CPU
11
Basic operation of device driver D Q Data bus Address matching circuit Address matching circuit Address bus CPU Device circuits
12
User space vs Kernel Space program User space program Limited priority Virtual run environment –Logic address –Key resource access is difficult User invoke function directly Kernel Space program Highest priority Physical run environment –Virtual address –Access all resource Kernel invoke function
13
Direct memory access(/dev/kmem) kmfd = open("/dev/kmem", O_RDONLY ); lseek( kmfd, offset, SEEK_SET ); read( kmfd, byteArray, byteArrayLen ); close(kmfd); memory is mapped into device file, and can be accessed by file read/write Can access kernel address ( virtual address of kernel ) Most started from 0xC0000000 memory offset
14
Access Physical address directly(/dev/mem) mem_fd = open("/dev/mem", O_RDONLY ); b=mmap(0, 0x10000, PROT_READ|PROT_WRITE,MAP_SHARED, mem_fd,0xA0000) … close(memfd); 0xA0000 0xB0000 Pointer b mmap mapping data in file into array Physical memory ( accessed by special file /dev/mem ) s mapped into array pointed by b Note that value of B may not be 0xA0000, its value is a virtual address coressponding to the physical address 0xA0000 under Linux, /dev/mem is for special memory access, such as video memory May not bye memory device file
15
Directly access IO port(/dev/port) port_fd = open("/dev/port", O_RDWR); lseek(port_fd, port_addr, SEEK_SET); read(port_fd, …); write(port_fd, …); close(port_fd); Note, not use fopen/fread/fwrite/fclose, because data operation by these function is not fulfilled immediately (buffered)
16
outb()/outw()/inb()/inw() Function #include #define BASEPORT 0x378 // printer int main() { ioperm(BASEPORT, 3, 1));// get access permission outb(0, BASEPORT); usleep(100000); printf("status: %d\n", inb(BASEPORT + 1)); ioperm(BASEPORT, 3, 0));// give up exit(0); } ioperm(from,num,turn_on) port address that can be obtained from ioperm is 0x000~0x3FF , use iopl() can obtain all port address must run as root use “gcc -02 –o xxx.elf xxx.c” to compile outb(value, port); inb(port); // 8-bit outw(value, port); inw(port); // 16-bit access time is about 1us
17
Access memory directly by user space program ——why we need device driver Share devices INT management
18
Safe device access method —— Using Linux device driver Device driver can access device address by pointer device driver also use virtual address but more ‘real’ than user application(device address mapping can be found in transplanting Linux Kernel) Physical address space Device Driver Virtual address mapping Device address Space Device address mapping Device Driver Virtual address mapping Device address mapping
19
Direct access IO port vs Using device driver Direct IO Access User space simple poll mode, slow (response time) difficult to share devices Access by device driver Kernel space difficult to debug and programming can use fast INT mode, realtime easy to implement device sharing (managed by OS)
20
Device Classification in Linux Character device –Mouse 、 Serial port 、 joystick Block device –Printer, hard disk Network device –Access by BSD Socket
21
Character device vs Block device Character device Read/write operation is fulfilled immediately data buffer is optional ADC/DAC 、 button 、 LED 、 sensor Block device need data buffer to reduce device write/read operation For slow device such as hard disk
22
Dynamically installable device vs static linked device driver Static linked device driver –Change configuration file, re-compile and install kernel Dynamically instable device driver –insmodinstall –rmmodremoval –lsmodquery
23
Abstraction of devices under Linux Device file Open/Close/Read/Write Example –/dev/mouse –/dev/lp0 universal IF
24
Device Driver and File Device driver Device File Create by command mknod installed by command insmod (or statically compiled into kernel) Application Access by open/read/write/close API Find real device river by major device number Similar method
25
User space Device Driver and File Kernel Space Deevice Driver read() write() open() close() User application read() write() open() close() Device File device ID Name of device file name of vice file
26
Structure of Device Driver Register and unregister device file operation function (API) (*open)() (*write)() (*flush)() (*llseek)() … ISR
27
Example of LED device driver CPU
28
struct file_operations LED_fops = { read: LED_read, write: LED_write, open: LED_open, release: LED_release, }; int LED_init_module(void) { SET_MODULE_OWNER(&LED_fops); LED_major = register_chrdev(0, "LED", &LED_fops); LED_off(); LED_status=0; return 0; } void LED_cleanup_module(void) { unregister_chrdev(LED_major, "LED"); } module_init(LED_init_module); module_exit(LED_cleanup_module); Program list (1) pointers of functions invoked when device is installed invoked when device is uninstalled Tell kernel the name of function to be invoked when install or uninstall device driver
29
program ( 2 ) int LED_open(struct inode *inode, struct file *filp) { printk("LED_open()\n"); MOD_INC_USE_COUNT; return 0; } int LED_release(struct inode *inode, struct file *filp) { printk(“LED_release()\n“); MOD_DEC_USE_COUNT; return 0; } new vision Linux doesn’t use this Macro
30
Program List ( 3 ) ssize_t LED_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) { int i; for (i=0; i<count; i++) *((char*)(buf+i)) = LED_Status; return count; } ssize_t LED_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { int i; for (i=0; i<count; i++) if (*((char*)(buf+i))) LED_on(); else LED_off(); return count; } (*((volatile unsigned int *)(0xXXXXXXXX))) |= MASK; (*((volatile unsigned int *)(0xXXXXXXXX))) &=~MASK;
31
#ifndef __KERNEL__ #define __KERNEL__ #endif #ifndef MODULE #define MODULE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include MODULE_AUTHOR("Rendong Ying"); int LED_major, LED_status; Program List ( 4 ) Header Device ID, uer can manually write the number or use automatically assigned number by kernel
32
Compile ( Makefile ) CC = arm-elf-linux-gcc LD = arm-elf-linux-ld INCLUDE = /usr/local/src/bspLinux/include LIB_INC = /usr/local/lib/gcc-lib/arm-elf-linux/2.95.3/include CFLAGS = -O6 -Wall -DCONFIG_KERNELD -DMODULE -D__KERNEL__ -DLinux -nostdinc -I- -I. -I$(INCLUDE) -idirafter $(LIB_INC) LED.o: LED.c $(CC) $(CFLAGS) -c LED.c clean: rm -f LED.o generate *.o
33
install device driver and create device file chmod +x /tmp/LED.o /sbin/insmod -f./LED.o cat /proc/devices get device ID instralled into the memory mknod /dev/Lamp c Num1 Num2 Num1 major device ID Num2 Minor device ID force install, ignore version checking assigned in the program: LED_major can be any value
34
User space install device driver Kernel Space Device Driver read() write() open() close() /sbin/insmod -f./LED.o
35
User space Create device file Kernel Space Device Driver read() write() open() close() cat /proc/devices obtain major device ID mknod /dev/Lamp c Num1 Num2 Num1 Major device ID Num2 Minor device ID Device File Device ID device ID
36
Test and use device driver command echo 8 > /proc/sys/kernel/printk cat /dev/Lamp cat > /dev/Lamp program void main() { int fd=open(“/dev/Lamp, O_RDWR); write(fd, &data, 1); close(fd); } open printk , you may read log information in /var/log/messages
37
User space Use of device driver Kernel Space Device Driver read() write() open() close() Device File void main() { int fd=open(“/dev/Lamp, O_RDWR); write(fd, &data, 1); close(fd); }
38
Uninstall device /sbin/rmmod LED remove device driver rm -f /dev/Lamp delete device file Function of MOD_INC_USE_COUNT; MOD_DEC_USE_COUNT;
39
User space Uninstall device Kernel Space Device Driver read() write() open() close() Device File /sbin/rmmod LED x x rm -f /dev/Lamp
40
Complex Device Driver register and unregister ( device and INT ) Divice operation API(function) (*open)() (*write)() (*flush)() (*llseek)() … ISR Kernel space buffer Data in user space
41
Complex Device Driver (USB Device) Application of IRQ if (request_irq(USB_INTR_SOURCE1, usb_ep1_int, SA_INTERRUPT, "USB EP1", 0) < 0) printk("Int. req. failed !\n"); free_irq(USB_INTR_SOURCE0, 0); cat /proc/interrupts check register INT point to ISR INT number, determined by hardware , kernel find INT number from INT status reg. Then call registed function on that number mask same INT INT ID ISR pointer Name
42
ISR No return value Fats and small void usb_ep1_int(int irq, void *dev_id, struct pt_regs *regs) { //… } Specific format for function declaration
43
ISR that receive data void usb_ep1_int(int irq, void *dev_id, struct pt_regs *regs) { read_data_from_hardware_FIFO(); send_data_to_buffer(); }
44
ISR that send data void usb_ep2_int(int irq, void *dev_id, struct pt_regs *regs) { read_data_from_buffer(); send_data_to_hardware_FIFO (); }
45
read function ssize_t usb_ep1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) { if (data_buffer_empty()) return 0; else copy_data_to_user_space(); return data_copyed; } copy_to_user(user_buf, device_driver_buf, size);
46
read function (blocking mode) ssize_t usb_ep1_read (struct file *filp, char *buf, size_t count, loff_t *f_pos) { while(device_driver_buf_empty()) { if (wait_event_interruptible(q_ep2, device_driver_buf_not_empty)) return -ERESTARTSYS; } copy_data_to_user_space(); return data_copyed; } wait_queue_head_t rq_EP2; init_waitqueue_head(&rq_EP2); queue when multiple user application access this device
47
write function ssize_t usb_ep2_write (struct file *filp, char *buf, size_t count, loff_t *f_pos) { if (data_buffer_full()) return 0; else copy_data_to_device_driver_buf(); if (no_transmission_now) send_1 st _data(); return data_copyed; } copy_from_user(device_driver_buf, user_buf, size);
48
Memory allocation by device driver malloc ? kmalloc kfree vmalloc vfree
49
Prevent open device several times int LED_flag; int LED_init_module(void) { LED_flag=0; … } int LED_open(struct inode *inode, struct file *filp) { if (LED_flag=0) { LED_flag=1; MOD_INC_USE_COUNT; return 0; } else return -ENODEV; } int LED_release(struct inode *inode, struct file *filp) { LED_flag=0; MOD_DEC_USE_COUNT; return 0; } need semphora to avoid access conflict
50
Manage several device by one device driver Serial Port Device Driver UART 0 Application
51
User space Create device file Kernel Space Device Driver read() write() open() close() cat /proc/devices Obtain device ID mknod /dev/Lamp c Num1 Num2 Num1 Major device ID Num2 Minor device ID Device File device file Device File Minor dev. ID is used to identify devices that is opened
52
Manage several device by one device driver int dev_open(struct inode *inode, struct file *filp) { int minor = MINOR(inode->i_rdev); filp->private_data=sub_dev_dat[minor]; … } ssize_t dev_write(struct file *filp, const char *buf, size_t count, loff_t *f_pos) { switch(*(filp->private_data)) { … } } Allocate data space for each device use data space allocated for the opened device
53
Debug of Character device driver Kernel Device Driver Device Read Device Write Device Open Device Close Debug Read Debug Write Debug Open Debug Close 设备文件 1 设备文件 2 Application ( using device ) debug and monitor Virtual Serial port, canbe access by minicom
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.