Morse char driver 2012
From Vertubleu
Linux kernel drivers intruction - labs
Contents |
Objectives
Apply the concept of kernel module and character driver, by implementing a simple character driver on pandaboard that outputs morse code on one of the Pandaboard LEDs
Summary
- Create and test a simple "hello world" kernel module (in kernel tree)
- Add character driver interface to communicate with the kernel module from user-space
- Add control of the Pandaboard LED and make it blink in morse code
0 - pre-requisites
- cross-compilation toolchain installed on a Linux host
ex: gcc-arm-linux-gnueabi package on oneiric (add following ppa on Natty: deb http://ppa.launchpad.net/linaro-maintainers/toolchain/ubuntu natty main)
- a 3.3-rc* based kernel sources, built using omap2plus_defconfig (older shall be ok while it boots on Pandaboard)
ex:
CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm make omap2plus_defconfig CROSS_COMPILE=arm-linux-gnueabi- ARCH=arm make uImage
- Bootloaders for Pandaboard
- any file-system allowing the kernel to boot on a Pandaboard
ex: http://omappedia.org/wiki/OMAP_Ubuntu_Core
- a pandaboard (a serial cable for traces, a power supply or USB cable)
- ressources:
- OMAP4430 TRM: http://focus.ti.com/pdfs/wtbu/OMAP4430_ES2.x_PUBLIC_TRM_vO.zip
- Pandaboard info (schematics, docs, ...): http://pandaboard.org/content/resources/references
1 - Create and test a simple "hello world" kernel module (in tree)
- edit a new source file in drivers/misc/morse.c, and add the minimum to create a kernel module (init and exit function, module owner, ...). Your module shall just print something in its init and its exit functions (printk).
- edit the drivers/char/Kconfig and drivers/char/Makefile files to make your new module configure-able and build-able. Create a new CONFIG_MORSE flag
- edit your kernel configuration (make menuconfig), find and make sure your new MORSE config is enabled as a module
- re-build your kernel and its modules, copy the generated drivers/misc/morse.ko file to your file-system, try to load it and see what happens ('dmesg' to look at the kernel log). Try to unload it and re-load it.
2 - Add character driver interface to communicate with the kernel module from user-space
- we will use a fixed device major number for our morse device (that'll be easier for testing. For a production driver, we would rather use a dynamic allocation and have to take care of the device node creation - maybe relying on udev). So find a free char device number.
- register your module as a character driver in the init function using your static device number
- think of un-registering your driver in the exit function!
- implement just the write() file operation. To make the 'write' function simple, implement a loop reading one char at a time and printk a message indicating the char you just read (that's the only processing required now).
- boot your file-system, and create a node in /dev to access your driver (mknod...)
- test your char driver by writing to its device file, and look at what happends
3 - Add control of the Pandaboard LED and make it blink in morse
Here we will add features to our driver. Instead of printing the chars that are received through the character interface, we will control the Pandaboard LED and make it blink in morse code. This is the 'fun' part of the driver :).
Note: here we will take shortcuts to have something simple and working quicky. This is good for learning and checking our concepts are functional, but this is not the way to do clean and upstream Linux kernel code. Here we shall probably define a platform device and register our driver as a platform driver. Another option may be to implement and register a new service through the LEDs framework. We will bypass this to make things more simple to implement as a first approach, but the counter part is that our driver will contain board-dependant code, making it specific to pandaboard, and non-upstream-able.
- The pandaboards LEDs are already handled in the upstream kernel. So first, we need to unregister the LED we want to use for our driver.
=> Edit arch/arm/mach-omap2/board-omap4panda.c and remove the second entry in the gpio_leds array (the one which name is pandaboard::status2)
- The Pandaboard LEDs are controled by GPIOs. In your driver's init function, register the GPIO 8 for the 2nd status LED. Add following code in the driver's init function:
gpio_request_one(PANDA_GPIO_LED, GPIOF_OUT_INIT_LOW, "Panda LED2"); gpio_export(PANDA_GPIO_LED, 0);
- and its related header file
#include <linux/gpio.h>
- It would be wise to check in the board file that the GPIO 8 is no being used (it's not the case in 3.3-rc1, but that may change with the kernel). Another way to check that the GPIO 8 is not already registered through the GPIO framework is to look at the content of this file:
cat /sys/kernel/debug/gpio
=> Have a look at this file content before and after registering GPIO 8 for your usage
- add a set_led function, programming the GPIO either up or down (to control the LED):
static void set_led(int status)
{
gpio_set_value(8, status);
}
- now implement a function taking a char as parameter, and controlling the LED to generate morse code, using the set_led function to control when to switch on / off the LED. Here are some pointers to follow :
- msleep for waiting
- the jiffies global variable to get the current time (also look for HZ)
- you'll probably need to implement a small state machine to handle the character being transmitted, ...
- last advice: use google! There are some already existing implementations of morse code that you may re-use in part: do not re-invent the wheel when possible!
