obj-$(CONFIG_EXAMPLES) += hello1.o
Adding the menu item to the kernel configuration utility is a little more involved. Listing 8-2 contains a patch that, when applied to the .../drivers/char/Kconfig file from a recent Linux release, adds the configuration menu item to enable our examples configuration option. For those readers not familiar with the diff / patch format, each line in Listing 8-1 preceded by a single plus (+) character is inserted in the file between the indicated lines (those without the leading + character).
Listing 8-2. Kconfig Patch for Examples
diff -u ~/base/linux-2.6.14/drivers/char/Kconfig ./drivers/char/Kconfig
--- ~/base/linux-2.6.14/drivers/char/Kconfig
+++ ./drivers/char/Kconfig
@@ -4,6 +4,12 @@
menu "Character devices"
+config EXAMPLES
+ tristate "Enable Examples"
+ default M
+ ---help---
+ Enable compilation option for driver examples
+
config VT
bool "Virtual terminal" if EMBEDDED
select INPUT
When applied to Kconfig in the .../drivers/char subdirectory of a recent Linux kernel, this patch results in a new kernel configuration option called CONFIG_EXAMPLES. As a reminder from our discussion on building the Linux kernel in Chapter 4, "The Linux KernelA Different Perspective," the configuration utility is invoked as follows (this example assumes the ARM architecture):
$ make ARCH=ARM CROSS_COMPILE=xscale_be- gconfig
After the configuration utility is invoked using a command similar to the previous one, our new Enable Examples configuration option appears under the Character devices menu, as indicated in the patch. Because it is defined as type tristate, the kernel developer can choose from three choices:
(N) No. Do not compile examples.
(Y) Yes. Compile examples and link with final kernel image.
(M) Module. Compile examples as dynamically loadable module.
Figure 8-1 shows the resulting gconfig screen with the new configuration option added. The dash (-) in the check box selects (M)odule, as indicated in the M column on the right. A check mark in the check box selects (Y)es, indicating that the driver module should be compiled as part of the kernel proper. An empty check box indicates that the option is not selected.
Figure 8-1. Kernel configuration with Examples module
Now that we have added the configuration option to enable compiling our examples device driver module, we need to modify the makefile in .../drivers/char to instruct the build system to descend into our new examples subdirectory if the configuration option CONFIG_EXAMPLES is present in our configuration. Listing 8-3 contains the patch for this against the makefile in a recent Linux release.
Listing 8-3. Makefile Patch for Examples
diff -u ~/base/linux-2.6.14/drivers/char/Makefile ./drivers/char/Makefile
--- ~/base/linux-2.6.14/drivers/char/Makefile
+++ ./drivers/char/Makefile
@@ -88,6 +88,7 @@
obj-$(CONFIG_DRM) += drm/
obj-$(CONFIG_PCMCIA) += pcmcia/
obj-$(CONFIG_IPMI_HANDLER) += ipmi/
+obj-$(CONFIG_EXAMPLES) += examples/
obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o
The patch in Listing 8-3 adds the single line (preceded by the + character) to the makefile found in .../drivers/char. The additional lines of context are there so that the patch utility can determine where to insert the new line. Our new examples directory was added to the end of the list of directories already being searched in this makefile, which seemed like a logical place to put it. Other than for consistency and readability, the location is irrelevant.
Having completed the steps in this section, the infrastructure is now in place to build the example device driver. The beauty of this approach is that the driver is built automatically whenever a kernel build is invoked. As long as the configuration option defined in Listing 8-3 is selected (either M or Y), the driver module is included in the build.
Building for an arbitrary ARM system, the command line for building modules might look like this:
$ make ARCH=arm CROSS_COMPILE=xscale_be- modules
Listing 8-4 shows the build output after a typical editing session on the module (all other modules have already been built in this kernel source tree.)
Listing 8-4. Module Build Output
$ make ARCH=arm CROSS_COMPILE=xscale_be- modules
CHK include/linux/version.h
make[1]: 'arch/arm/kernel/asm-offsets.s' is up to date.
make[1]: 'include/asm-arm/mach-types.h' is up to date.
CC [M] drivers/char/examples/hello1.o
Building modules, stage 2.
MODPOST
LD [M] drivers/char/examples/hello1.ko
8.1.5. Installing Your Device Driver
Now that this driver is built, we can load and unload it on a running kernel to observe its behavior. Before we can load the module, we need to copy it to an appropriate location on our target system. Although we could put it anywhere we want, a convention is in place for kernel modules and where they are populated on a running Linux system. As with module compilation, it is easiest to let the kernel build system do that for us. The makefile target modules_install automatically places modules in the system in a logical layout. You simply need to supply the desired location as a prefix to the default path.
In a standard Linux workstation installation, you might already know that the device driver modules live in /lib/modules//... ordered in a manner similar to the device driver directory hierarchy in the Linux kernel tree. [62] This path is used by Red Hat and Fedora distributions, and is also required by the File System Hierarchy Standard referenced at the end of this chapter. Other distributions might use different locations in the file system for kernel modules.
The string is produced by executing the command uname -r on your target Linux system. If you do not provide an installation prefix to the kernel build system, by default, your modules are installed in your own workstation's /lib/modules/... directory. This is probably not what you had intended. You can point to a temporary location in your home directory and manually copy the modules to your target's file system. Alternatively, if your target embedded system uses NFS root mount to a directory on your local development workstation, you can install the modules directly to the target file system. The following example assumes the latter.
$ make ARCH=arm CROSS_COMPILE=xscale_be- \
INSTALL_MOD_PATH=/home/chris/sandbox/coyote-target \
modules_install
This places all your modules in the directory coyote-target, which on this example system is exported via NFS and mounted as root on the target system. [63] Hosting a target board and NFS root mount are covered in detail in Chapter 12, "Embedded Development Environment".
8.1.6. Loading Your Module
Having completed all the steps necessary, we are now in a position to load and test the device driver module. Listing 8-5 shows the output resulting from loading and subsequently unloading the device driver on the embedded system.
Читать дальше