Monday, June 27, 2011

Adding a Linux device driver for Target Board

Adding a Linux device driver

On Linux systems, device drivers are typically distributed in one of three forms:

* A patch against a specific kernel version
* A loadable module
* An installation script that applies appropriate patches

The most common of all these is the patch against a specific kernel version. These patches can in most cases be applied with the following procedure:2

# cd /usr/src/linux ; patch -p1 < patch_file Diffs made against a different minor version of the kernel may fail, but the driver should still work. Here, we cover how to manually add a network "snarf" driver to the kernel. It's a very complicated and tedious process, especially when compared to other operating systems we've seen. By convention, Linux kernel source resides in /usr/src/linux. Within the drivers subdirectory, you'll need to find the subdirectory that corresponds to the type of device you have. A directory listing of drivers looks like this: % ls -F /usr/src/linux/drivers Makefile cdrom/ i2o/ nubus/ sbus/ telephony/ acorn/ char/ isdn/ parport/ scsi/ usb/ ap1000/ dio/ macintosh/ pci/ sgi/ video/ atm/ fc4/ misc/ pcmcia/ sound/ zorro/ block/ i2c/ net/ pnp/ tc/ The most common directories to which drivers are added are block, char, net, usb, sound, and scsi. These directories contain drivers for block devices (such as IDE disk drives), character devices (such as serial ports), network devices, USB devices, sound cards, and SCSI cards, respectively. Some of the other directories contain drivers for the buses themselves (e.g., pci, nubus, and zorro); it's unlikely that you will need to add drivers to these directories. Some directories contain platform-specific drivers, such as macintosh, acorn, and ap1000. Some directories contain specialty devices such as atm, isdn, and telephony. Since our example device is a network-related device, we will add the driver to the directory drivers/net. We'll need to modify the following files: * drivers/net/Makefile, so that our driver will be compiled * drivers/net/Config.in, so that our device will appear in the config options * drivers/net/Space.c, so that the device will be probed on startup After putting the .c and .h files for the driver in drivers/net, we'll add the driver to drivers/net/Makefile. The lines we'd add (near the end of the file) follow. ifeq ($(CONFIG_SNARF),y) L_OBJS += snarf.o else ifeq ($(CONFIG_SNARF),m) M_OBJS += snarf.o endif endif This configuration adds the snarf driver so that it can be either configured as a module or built into the kernel. After adding the device to the Makefile, we have to make sure we can configure the device when we configure the kernel. All network devices need to be listed in the file drivers/net/Config.in. To add the device so that it can be built either as a module or as part of the kernel (consistent with what we claimed in the Makefile), we add the following line: tristate 'Snarf device support' CONFIG_SNARF The tristate keyword means you can build the device as a module. If the device cannot be built as a module, use the keyword bool instead of tristate. The next token is the string to display on the configuration screen. It can be any arbitrary text, but it should identify the device that is being configured. The final token is the configuration macro. This token needs to be the same as that tested for with the ifeq clause in the Makefile. The last file we need to edit to add our device to the system is drivers/net/Space.c. Space.c contains references to the probe routines for the device driver, and it also controls the device probe order. Here, we'll have to edit the file in two different places. First we'll add a reference to the probe function, then we'll add the device to the list of devices to probe for. At the top of the Space.c file are a bunch of references to other probe functions. We'll add the following line to that list: extern int snarf_probe(struct device *); Next, to add the device to the actual probe list, we need to determine which list to add it to. A separate probe list is kept for each type of bus (PCI, EISA, SBus, MCA, ISA, parallel port, etc.). The snarf device is a PCI device, so we'll add it to the list called pci_probes. The line that says struct devprobe pci_probes[] __initdata = { is followed by an ordered list of devices. The devices higher up in the list are probed first. Probe order does not usually matter for PCI devices, but some devices are sensitive. Just to be sure the snarf device is detected, we'll add it to the top of the list: struct devprobe pci_probes[] __initdata = { #ifdef CONFIG_SNARF snarf_probe, 0}, #endif The device has now been added to the Linux kernel. When we next configure the kernel, the device should appear as a configuration option under "network devices." Adding new kernel module to linux source tree Posted on October 24, 2010 by Ravi Teja G Kernel modules in linux are important programs that can be loaded and unloaded at wish without having to compile them into linux kernel image itself. All the device drivers are written using these loadable modules. Let us add a very basic sample kernel module. Add this file to drivers/misc directory in linux kernel source. drivers/misc/hello_world.c view source print? 01 #include
02 #include
03
04 static int __init hello_world_module_init(void)
05 {
06 printk("Hello World, sample module is installed!\n");
07 return 0;
08 }
09
10 static void __exit hello_world_module_cleanup(void)
11 {
12 printk("Good-bye, sample module was removed!\n");
13 }
14
15 module_init(hello_world_module_init);
16 module_exit(hello_world_module_cleanup);
17 MODULE_LICENSE("GPL");

Next we have to add configuration settings, so that our module can be enabled or disabled. Add these lines to drivers/misc/Kconfig file,
view source
print?
1 config HELLO_WORLD_MODULE
2 tristate "hello world module"
3 depends on ARM
4 default m if ARM
5 help
6 hello world module.

Line 3 states that this option can only be enabled if CONFIG_ARM is enabled and Line 4 states that this option should be enabled as default when CONFIG_ARM is enabled. Next We have to inform kernel to compile hello_world.c when HELLO_WORLD_MODULE configuration is enabled. Add this line to drivers/misc/Makefile,
view source
print?
1 obj-$(CONFIG_HELLO_WORLD_MODULE)+= hello_world.o

We have successfully added a new module to linux kernel. Now let us compile and test our new module. We have to start from “make defconfig” so that our changes to configuration files take effect.

$ export CROSS_COMPILE=arm-none-linux-gnueabi-
$ export ARCH=arm
$ make clean
$ make mini2440_defconfig
$ make menuconfig

Enable our newly added module from Device Drivers —> Misc devices —> hello world module. Now start compiling modules.

$ make modules
$ make modules_install INSTALL_MOD_PATH=$ROOTFS

Here $ROOTFS is the target file system. Now to test our new module,

$ modprobe hello_world
Hello World, sample module is installed !
$ rmmod hello_world
Good-bye, sample module was removed!

No comments:

Post a Comment