1 / 17

Embedded Systems Programming

Embedded Systems Programming. Writing Device Drivers. 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

kory
Download Presentation

Embedded Systems Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  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 <linux/delay.h> #include <linux/module.h> #include <linux/ioport.h> #include <asm/io.h> #include <asm/arch/io.h> #include <asm/arch/hardware.h> #include <asm/uaccess.h> #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 fatalto the current process and sometimes the whole system • Modules should support concurrency (support calls by different processes). Distinct data structuresfor 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/ioportscontains information about registered ports. /proc/iomemcontains 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

More Related