Download presentation
Presentation is loading. Please wait.
1
Embedded Systems Programming Writing Device Drivers
2
Writing a new device driver When writing a device driver you can either –Create a new, bespoke driver from scratch Or –Port an existing driver Generally pick option 2 unless –The hardware is so new to make porting impossible –You are really experienced in device driver writing –The driver has to do something really special or diffferent
3
Linux Execution Environment
4
Linux Execution Paths Execution paths
5
Kernel Modules Kernel modules are inserted and unloaded dynamically –Kernel code extensibility at run time –insmod / lsmod/ rmmod commands. Look at /proc/modules –Kernel and servers can detect and install them automatically, for example, cardmgr (pc card services manager) Modules execute in kernel space –Access to kernel resources (memory, I/O ports) and global variables ( look at /proc/ksyms) –Export their own visible variables, register_symtab (); –Can implement new kernel services (new system calls, policies) or low level drivers (new devices, mechanisms) –Use internal kernel basic interface and can interact with other modules (pcmcia memory_cs uses generic card services module) –Need to implement init_module and cleanup_module entry points, and specific subsystem functions (open, read, write, close, ioctl …)
6
#include #define DRIVER_AUTHOR "craig duffy craig.duffy@uwe.ac.uk" #define DRIVER_DESC "FPGA DIO driver" #define LED_ADDRESS 0xf2400680 #define RGGG 0xf000 static int fpga_dio_init(void) { static int fpga_j; static short unsigned pattern; printk(KERN_ALERT "fpga dio loaded\n"); pattern=RGGG; pattern = pattern >> 4; for ( fpga_j=0; fpga_j != 16 ; fpga_j++) { printk("pattern %x\n",pattern); udelay(400); writew(pattern,LED_ADDRESS); pattern = pattern >> 8; pattern--; pattern = pattern << 8; }*/ return 0; } static void fpga_dio_exit(void) { printk(KERN_ALERT "fpga dio unloaded\n"); } module_init(fpga_dio_init); module_exit(fpga_dio_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_SUPPORTED_DEVICE("fpga_dio");
7
Linking a module to the kernel (from Rubini’s book)
8
Module programming Be careful: a kernel fault is fatal to the current process and sometimes the whole system Modules should support concurrency (support calls by different processes). Distinct data structures for each process (since the same code is executed) to ensure data is not corrupted. Driver code must be reentrant: keep status in local (stack allocated) variables or dynamic memory allocation: kmalloc / kfree This allows the process executing to suspend (e.g., wait for pcmcia card interrupt) and other processes to execute the same code. It is not a good idea to assume your code won’t be interrupted. Sleep_on(wait_queue) or interruptible_sleep_on(wait_queue) to yield the cpu to another process /proc/ioports contains information about registered ports. /proc/iomem contains info about I/O memory
9
Register Capability You can register a new device driver from the kernel: –int register_chrdev(unsigned int major, const char *name, struct file_operations *fops); –A negative return value indicates an error, 0 or positive indicates success. –major: the major number being requested (a number < 128 or 256). –name: the name of the device (which appears in /proc/devices). –fops: a pointer to a global jump table used to invoke driver functions. Then give to the programs a name by which they can request the driver through a device node in /dev –To create a char device node with major 254 and minor 0, use: mknod /dev/memory_common c 254 0 –Minor numbers should be in the range of 0 to 255.
10
Finding a device driver Obviously you need to be able to categorise the device –Some Linux categories are not clear You can look at other open systems – for example NetBSD –This is useful as they may have ported the driver themselves Get as much reliable information about the device –Data sheets, tested, stand alone code
11
Example of a Parallel port It is quite often useful to use a parallel port as an interface to some specialised hardware. There are a number of approaches you could take to controlling such hardware from Linux –A simple, low level kernel device driver –Porting the parallel port package, ppdev, –Writing a full blown device driver through the file system –Writing a driver through the /procfs interface
12
A simple low level kernel driver Under Linux it is always possible to write directly to the hardware This uses some low level calls to read and write data –inb(), outb(), inw(), outw() The areas of memory are maped by the kernel and ioremap/iounmap shopuld be used Data has to be copied to and from user space unto kernel space
13
Problems with low level driver It is a good idea to use to test the hardware but isn’t a long term solution for driver development –Requires root access to run the kernel No file system interface –Will be very limited functionality –Can’t use the kernel very effectively –Isn’t portable –Can crash the kernel
14
Porting an existing device With the parallel port one can use ppdev This give a high level interface into the file system through /dev/parport0-n –Don’t need root access Can have well structured driver Should be ported (in-time) with new kernel releases Less likely to cause kernel panics
15
Problems with ppdev Unless it is a very standard parallel port application it is likely to be difficult to get the correct level of functionality Will require understanding a lot of details of parallel port and the driver which won’t be useful for your app
16
Writing a device driver This allows you to create a new device in the system Uses VFS calls to access the drive –Can open, read, write and close –Uses ioctl calls Driver can be a module –Only loaded when needed –Easier development
17
Problems
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.