I3MPS - Exercise 7: LDD With Timer

Introduction
In this exercise an interrupt service routine is added to the SYS_LED4 driver from I3MPS - Exercise 5: LDD with GPIO. The implemented interrupt routine has to wake up the read method, so that applications blocked while calling read, are released.

Important header files and methods
Extra header files:
 * 1) include 
 * 2) include "common.h"

Added a new file operation: static struct file_operations my_fops = {    ...     .unlocked_ioctl = device_unlocked_ioctl, ...  };

Added the header file common.h, which include the magic number that specifies which driver the ioctl command is aiming at and some commands that are used to send form user space to kernel space.

//Linux Device Drivers page 138 - it is just some 8 bit number //For numbers already used have a look at ioctl-numbers.txt //COMMANDS used with the ioctl function //They have to be known in both kernel and user space
 * 1) include 
 * 1) define TEST_IOC_MAGIC 'k'
 * 1) define TEST_IOCTL_COMMAND_ONE _IOWR(TEST_IOC_MAGIC, 0, int)
 * 2) define TEST_IOCTL_COMMAND_TWO _IOWR(TEST_IOC_MAGIC, 1, int)
 * 3) define TEST_IOCTL_COMMAND_THREE _IOWR(TEST_IOC_MAGIC, 2, int)

SYS_LED4 toggle Device Driver w. ioctl interface
The SYS_LED4 driver from exercise 5, used a write call to turn on or off an LED. In this exercise it will be modified to toggle the LED, on and off, at a specific frequency. 2 ioctl calls will be implemented to start/stop and to modify the frequency between toggles.

Subexercise Description
Implement an ioctl call in the driver and make a small test application. Have it print a message to the kernel, using printk, when ioctl is called.

Solution
The ioctl call. Test programmet.

Testing on Devkit8000
The last lines from dmesg after installing the driver and running the test program [ 449.186523] Opening SYS_LED4 Device [major], [minor]: 248, 0 [ 449.196533] IOCTL COMMAND ONE HAS BEEN CHOSENReleasing SYS_LED4 Device [major], [minor]: 248, 0

Running the program gives the following output in the console window. root@beagleboard:~# ./ioctl_test_prog 2000 Jan 1 00:07:25 beagleboard [  449.196533] IOCTL COMMAND ONE HAS BEEN CHOSENReleasing SYS_LED4 Device [major], [minor]: 248, 0 /dev/sys_led4: open returned fd=3

We have observed that sometimes the text written using printk in the kernel module ends up being written in the console. As to why that happens and why it only happens sometimes is still under investigation.

Subexercise Description
Implement a timer. Make it toggle sys_led4. Use ioctl calls to start/stop and modify the frequency.

Solution
The ioctl call.

The timer function.

The test program

Testing on Devkit8000
The last lines of dmesg after installing the driver and running the test program:

[ 190.668426] Opening SYS_LED4 Device [major], [minor]: 248, 0 [ 190.680603] IOCTL COMMAND ONE START LED TOGGLER [ 210.687561] IOCTL COMMAND TWO STOP LED TOGGLER [ 215.703979] IOCTL COMMAND ONE START LED TOGGLER [ 235.716644] IOCTL COMMAND TWO STOP LED TOGGLERReleasing SYS_LED4 Device [major], [minor]: 248, 0

Console window: root@beagleboard:~# ./ioctl_test_prog_with_ARG 2000 Jan 1 00:03:27 beagleboard [  190.680603] IOCTL COMMAND ONE START LED TOGGLER 2000 Jan 1 00:03:32 beagleboard [  210.687561] IOCTL COMMAND TWO STOP LED TOGGLER 2000 Jan 1 00:03:52 beagleboard [  215.703979] IOCTL COMMAND ONE START LED TOGGLER 2000 Jan 1 00:03:52 beagleboard [  235.716644] IOCTL COMMAND TWO STOP LED TOGGLERReleasing SYS_LED4 Device [major], [minor]: 248, 0

Visual confirmation:

It was observed that the LED was turned on and off for some time with approx. 1 sec between toggles, it then turned off completely for a while and then started toggling with about 2 secs between toggles.

Subexercise description
When running the program from part b, try to find out how much cpu time the program takes. This can be done using the top command.

Solution
The timer function.

Testing on Devkit8000
Running the program ioctl_test_prog_with_ARG in a seperate thread and the running top gives the following:

Mem: 33952K used, 70584K free, 0K shrd, 2332K buff, 15628K cached Mem: 33980K used, 70556K free, 0K shrd, 2332K buff, 15632K cached CPU:  0% usr   1% sys   0% nic  97% idle   0% io   0% irq   0% sirq Load average: 0.33 0.26 0.11 1/59 1526 PID PPID USER     STAT   VSZ %VSZ %CPU COMMAND 1526 1520 root     R     2288   2%   1% top 1517    1 root     S     2540   2%   0% /usr/sbin/dropbear -i -r /etc/dropbear/dropbear_rsa_host_key -p 22 712    2 root     SW       0   0%   0% [kworker/0:2] 941    1 root     S     6060   6%   0% /usr/sbin/syslog-ng -F 934    1 avahi    S     3048   3%   0% avahi-daemon: running [beagleboard.local] 1525 1520 root     S     2912   3%   0% ./ioctl_test_prog_with_ARG

General comments to the exercise
Writing the wiki made us think that perhaps the we misunderstood the subexercise b). What we have done is to use a ioctl call to start the LED toggle timer and using another ioctl call to stop it. Another to go about it would have been to have an ioctl call to start and stop the timer, the parameter/argument given with it would then tell if the LED toggler/timer would be turned on or off. The other ioctl call would then be used to set the amount of time (or frequency if you will) and only that. So that making an ioctl call to change the frequency of the toggling LED had nothing to do with the toggling being active or not. That would probably been a better way to do it. In part c the delay is made in an odd way that locks the processor. It should have been made in a way so it was only the jiffies counting part that was exchanged with a wait command.

Source code
-Remember to put in links to source codes on other pages.-