Presentation is loading. Please wait.

Presentation is loading. Please wait.

Linux Device Driver 2009/04/08. Reference Book Another Reference Book Embedded Linux Primer: A Practical, Real-World Approach By Christopher Hallinan.

Similar presentations


Presentation on theme: "Linux Device Driver 2009/04/08. Reference Book Another Reference Book Embedded Linux Primer: A Practical, Real-World Approach By Christopher Hallinan."— Presentation transcript:

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


Download ppt "Linux Device Driver 2009/04/08. Reference Book Another Reference Book Embedded Linux Primer: A Practical, Real-World Approach By Christopher Hallinan."

Similar presentations


Ads by Google