Você está na página 1de 27

Software for Embedded Systems IS C424

KCS Murti

Device drivers

Overview
A function of the OS is to provide arbitrated shared access to I/O devices in the system. Applications do not directly interact with the I/O devices Device driver provides an abstraction that allows the device to be written generically regardless of the resources allocated to the device. A software component within the kernel that directly interact with a hardware device. software layer that lies between the applications and the actual device

General classification of devices


Character accessed as a stream of bytes open, close, read, and write system calls Block devices accessed by filesystem nodes in the /dev directory. can host a filesystem Network interfaces a device that is able to exchange data with other hosts. interface is a hardware or pure software device

Kernel module
Runs in kernel space kernel module registers itself in order to serve future requests Exit function unloads the module. function calls and function pointers are used in a module to add new functionality to a running kernel insmod, loads a module into the kernel
#include <linux/init.h> #include <linux/module.h> MODULE_LICENSE("Dual BSD/GPL"); static int hello_init(void) { printk(KERN_ALERT "Hello, world\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "Goodbye, cruel world\n"); } module_init(hello_init); module_exit(hello_exit);

Device Driver Relationships.

Role of device driver


Roles: Abstracts the hardware. Manages privilege. Enables multiplexed access. Martials data to and from an applications process space to kernel space. Provides security. driver provides services to other modules within the operating system. entry to the device driver often provides a reentrant API. ensure safe concurrent access to the actual device or data. Manage the memory associated with the payload being sent or received from the device. Provide separation for security and robustness. Driver is running in kernel process space has direct access to the buffer Defect free as this works in kernel space.

Low-Level Data Path(TX)

Low-Level Data Path(RX)

DMA approach

Bus Drivers
Provide a mechanism to scan the bus at runtime and identify what devices are attached to the bus. (Enumeration) Bus driver handles the enumeration provides services to each of the devices attached Ex: PCI bus driver Scans the PCI configuration space for devices. Saves the device ID Identifies the memory size requested by each of the base address registers Allocates the memory space for the device. Assigns an interrupt(s) to the device. initializes a device driver registered for the specific device ID.

static int __devinit device_probe(struct pci_dev *pdev, const struct pci_device_id *ent);

Network devices

Typical API
Load/Unload services to load a dynamic driver. Send/Packet Transmit Sends a buffer in the network stack format to be transmitted to on the network interface IOCTL I/o control interface . A generic control API for the driver. Device Stop/Start enable or disable the device

Packet arrivals
On arrival of a packet on the network interface, the network device sends the packet via DMA into a receive buffer interrupts the processor to indicate that a packet has arrived. The network driver then sends an event or notification to a deferred work task. When the deferred task wakes up to process the packet arrival event. makes a call to submit the packet to the IP stack. Linux calls send a packet from the driver up into the TCP/IP network stack netif_rx(struct sk_buff *skb) netif_receive_skb (struct sk_buff *skb)

Storage File systems


abstract mechanism to open and close a storage device read and write to a storage device. Many different file systems Windows: NTFS,FAT32 Linux: EXT3/4 Embedded systems: JFFS2, TFAT, CRAMFS etc.. Steps: application performs a write to the file system. file system allocates blocks on the storage device Writes the required contents Into the allocated blocks An asynchronous operation without blocking file system drivers will at some point reflect the write in the file system Journalling system maintains a record of updates or deltas to the existing state of the mass storage device.(EXT3) Non-journalling performs all updates directly to the file system management structures(FAT32)

Character Driver Model


referenced through special files in the file system. typically placed in the /dev folder major number typically indicates a device driver type minor number indicates an instance The user space application can perform the traditional open/close/read/write and ioctl calls to interact with the device. read()read data from the device. write()write data to the device. ioctl()generic control function that can be used to pass setup information and configuration information to a device. Synchronous/asynchronous drivers

root@ubuntu:/dev# ls -l crw------- 1 root root 5, 1 2011-05-14 20:31 console crw-rw-rw- 1 root tty 5, 0 2011-06-02 07:13 tty crw--w---- 1 root root 4, 0 2011-05-14 20:31 tty0 crw------- 1 root root 4, 1 2011-05-14 20:31 tty1

A character driver
// Makefile for simple driver. obj-m += ex_kernel_drv.o //Header files required for the driver 1 #include <linux/module.h> 2 #include <linux/moduleparam.h> 3 #include <linux/init.h> 4 #include <linux/kernel.h> 5 #include <linux/fs.h> 6 #include <linux/errno.h> 7 #include <asm/uaccess.h> //Define major device number 11 #define MAJOR_DEVICE_NUMBER 42 12 char *kernel_data; 13 int ret_count; 15 int drv_open(struct inode *inode, struct file *filep) 16 { 17 printk("Example driver open\n"); 18 ret_count 0; 19 return 0; 20 } 21 int drv_close(struct inode *inode,struct file *filep) 22 { 23 printk("Example driver close\n"); 24 return 0; 25 }

A character device driver


26 ssize_t drv_read(struct file *filep,char *user_buf, size_t count,loff_t *offp ) 28 { 29 printk("Example driver read: size:%d\n",count); 30 if ( ret_count >= strlen(kernel_data)) 31 { 32 printk("Example driver read: ret_count = %d", ret_count); 34 return 0; 35 } 36 if ( 37 copy_to_user(user_buf,kernel_data,strlen(kernel_data)) != 0 ) 39 printk("Kernel to user copy failed\n"); 40 ret_count += strlen(kernel_data); 41 return (strlen(kernel_data)); 42 }

A character device driver


43 ssize_t drv_write(struct file *filep, const char *user_buf, size_t count,loff_t *offp ) 46 { 47 printk("Example driver write:Count:%d\n",count); 48 if ( copy_from_user(kernel_data,user_buf,count) !=0 ) 49 printk("User to kernel copy failed\n"); 50 *(kernel_data+count)=NULL; 51 return count; 52 }

A character device driver


53// The device operations structure. 57 static struct file_operations drv_ops = { 58 .owner =THIS_MODULE, 59 .open = drv_open, 60 .read =drv_read, 61 .write =drv_write, 62 .release = drv_close, 63 /* .ioctl = drv_ioctl */ 64 }; 67 static int __init example_drv_init(void) 68 { 69 printk("Example driver init\n"); 70 kernel_data =kmalloc(132,GFP_KERNEL); 71 strcpy(kernel_data, "Kernel data string not yet written to\n"); 73 if ( register_chrdev( MAJOR_DEVICE_NUMBER, "example_dev", &drv_ops)) 77 printk("Device registration failed"); 78 printk("Example driver init complete\n"); 79 return 0; 80 }

A character device driver


82 static void __exit example_drv_exit(void) 83 { 84 printk("Example driver exit\n"); 85 unregister_chrdev(MAJOR_DEVICE_NUMBER, "example_device"); 87 kfree(kernel_data); 88 }

90 module_init(example_drv_init); 91 module_exit(example_drv_exit);

A character device driver


Compile the kernel modules make -C /usr/src/linux-source-2.6.38/ M=$PWD modules Next, create the device node in the /dev file system. mknod /dev/new_device c 42 0 Now, load the kernel module (you can verify it was loaded by issuing the lsmod command). insmod ex_kernel_drv.ko Perform a number of reads and writes to the device. cat /dev/example_device Kernel data string not yet written to. echo "Hello world driver" > /dev/example_device cat /dev/example_device Hello world driver. echo "New string" > /dev/example_device cat /dev/example_device Debug messages from the module can be displayed using: dmesg [46306.157051] Example driver init complete [46309.165205] Example driver open [46309.165317] Example driver read: size:32768 [46309.165465] Example driver read: size:32768 [46309.165482] Example driver read: ret_count 38 [46309.165510] Example driver close

PCI device driver


kernel identifies all hardware on the system associates it automatically with the appropriate driver Kernel module indicates list of devices supported using pci_device_table
static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) ={ PCI_DEVICE(0x8086, 0x1000), PCI_DEVICE(0x8086, 0x1000), {0,} }; MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);

static int __devinit e1000_probe (struct pci_dev *pdev, const struct pci_device_id *ent)

static struct pci_driver e1000_driver = { .name =e1000_driver_name, .id_table = e1000_pci_tbl, .probe =e1000_probe, .remove = __devexit_p(e1000_remove), #ifdef CONFIG_PM /* Power Managment Hooks */ .suspend = e1000_suspend, .resume = e1000_resume, #endif .shutdown = e1000_shutdown, .err_handler = &e1000_err_handler }; pci_register_driver(&e1000_driver);

the structure responsible for driver

Interrupt Handling
Device driver should respond to interrupts created by device Legacy Interrupts; wire-based interrupts. Each wire is usually shared between multiple devices, each device can only generate a single interrupt type Message Signal Interrupts: system to allocate a number of interrupt vectors to the device. special system message that is directed to the CPUs APIC Message Signal Interrupts eXtension Vectors assigned to a device do not need be contiguous each vector allocated can be directed to a targeted core. driver assigns the vectors to callback routines request_irq(IRQ Number, callback function handler, irq_flags, name, data);

Deferred work
defer work to a kernel task context to perform the remainder of the interrupt work (bottom-half handling ) softIRQs, tasklets, and work queues softIRQs 32 defined in the system statically configured at compile time cannot be created dynamically. Tasklets: A function that is added to a linked list and then called when the softIRQ executes. must run to completion and should not block Only one instance of a given tasklet is guaranteed to execute at any one time. Work queue: executed in the context of a kernel thread. runs as a process that is scheduled

Interrupt flow

References
Chap (7,8) Modern Embedded computing by Peter Barry Linux device drivers by Corbet,Rubini

Você também pode gostar