Kernel Exercise
Exercise gives bonus marks for Assignment 4 and practices topics required for Quiz 4.
Exercise must be done individually.
Learning Outcomes
- Building a specific version of the Linux kernel.
- Creating, cross-compiling, loading, and unloading, printing-to and reading-from a misc driver.
- Working with user data in
read()
andwrite()
functions. - Creating and controlling an LED trigger.
Overview
- Create a "misc" Linux kernel driver (module) that will load on the BBG.
- The module must be named
waveform.ko
. - The module must create the
/dev/waveform
file for read/write operations. - The module must create an LED trigger named
waveform
. - You may include any kernel
printk()
messages you like. Must be customized to your driver (and not say it's the "demo_misc" driver or something!).
write()
- The user, in user space, can write a string to the driver via its
/dev/waveform
file. - It will process the characters in order in the input string:
'-'
: A dash turns the LED on for 250ms;
'_'
: An underscore turns the LED off 250ms
Anything other character is ignored. - When it finishes processing the string, it should turn the LED off.
- Example:
- Turn on the LED for 1s:
(bbg) $ echo '----' | sudo tee /dev/waveform
- Turn on/off/on/off; total 2s:
(bbg) $ echo '--__--__' | sudo tee /dev/waveform
- Leave the LED off:
(bbg) $ echo '' | sudo tee /dev/waveform
(bbg) $ echo 'abcdefg' | sudo tee /dev/waveform
- Turn on the LED for 1s:
- NOTE: To delay in the kernel, use
usleep_range()
instead ofmsleep()
because it's much more accurate. For example, to sleep for 100 ms, use:
usleep_range(100000, 100001);
- Timing:
- Use
time
program to see how long it's taking, such as:
(bbg) $ time echo '--__--__' | sudo tee /dev/waveform
- You are likely to find that each syscall has ~100ms overhead, so displaying
"-_-_"
is likely to take 1.100s +/- 150ms.
- Use
- Must return an error for invalid pointers or invalid memory accesses from the user-space. It must not generate a kernel panic.
read()
- Fills the user's buffer with a multi-line string of the following form:
# times high: 0 # times low: 0 Longest high: 0 Longest low: 0
- "# times high": The number of times the LED has been turned to "on".
- Being on for multiple consecutive characters
"--"
counts as one on, so"--_--_------_"
is 3 high, and 3 low. - Count the start of each "on block", even if the last time the
write()
function was called it ended on a'-'
. For example, writing"---"
and then writing"-----"
counts as 2 high. - Characters other than
'-'
and'_'
are ignored, so"a-b-c donteuh-.^@$^-"
still counts as one "on".
- Being on for multiple consecutive characters
- "# times low": The number of times the LED has been turned to "off".
- Like above counting for on.
- Turning the LED off at the end of an output does not count, so
"----"
counts as 0 for low. - Turning the LED off at the start of an output does count, even though the LED should already be off. For example,
"___"
counts for 1, and"___--___----_"
counts for 3.
- "Longest high": The number of
'-'
characters in the longest single high part of waveforms written so far.- The value persists between multiple calls; however, it does not continue counting between writes, so:
writing"----"
and then"--"
has a longest high of 4; writing"----"
and then"------"
has a longest high of 6. - Ignores garbage characters, so writing
"-t52nth5OEutnhirc;QJ> <.p>- 52"
has a longest high of 2.
- The value persists between multiple calls; however, it does not continue counting between writes, so:
- "Longest low": Same as longest high, but for
'_'
. - General
- All values initialize to 0 each time the module is loaded.
- Code must work for all buffer sizes, such as 0, 1, 5, 10, 100, 10000.
- Output must be exactly as shown: no leading spaces, lined up numbers (left-aligned, using spaces), and a
\n
at the end of each line, no extra spaces. - Must detect and return an error for bad pointers or bad memory accesses from the user-space.
Marking
Worth up to 15 bonus marks of assignment 4.
[5] Correct LED operation and timing
[5] Correct read() behaviour
[2] Correct read with different buffer sizes
[3] Correctly return errors for bad pointers / memory access issues
Sample Output
debian@BeagleBone:/mnt/remote/drivers$ sudo insmod ./waveform.ko
debian@BeagleBone:/mnt/remote/drivers$ echo waveform > /sys/class/leds/beaglebone\:green\:usr0/trigger
debian@BeagleBone:/mnt/remote/drivers$ time echo "" | sudo tee /dev/waveform
real 0m0.108s
user 0m0.030s
sys 0m0.057s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 0
# times low: 0
Longest high: 0
Longest low: 0
debian@BeagleBone:/mnt/remote/drivers$ time echo "----" | sudo tee /dev/waveform
----
real 0m1.107s
user 0m0.035s
sys 0m0.053s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 1
# times low: 0
Longest high: 4
Longest low: 0
debian@BeagleBone:/mnt/remote/drivers$ time echo "______" | sudo tee /dev/waveform
______
real 0m1.612s
user 0m0.038s
sys 0m0.052s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 1
# times low: 1
Longest high: 4
Longest low: 6
debian@BeagleBone:/mnt/remote/drivers$ time echo "-_-_-_-" | sudo tee /dev/waveform
-_-_-_-
real 0m1.860s
user 0m0.034s
sys 0m0.056s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 5
# times low: 4
Longest high: 4
Longest low: 6
debian@BeagleBone:/mnt/remote/drivers$ time echo "abc-def-hij-klm-nop-qrs-t" | sudo tee /dev/waveform
abc-def-hij-klm-nop-qrs-t
real 0m1.612s
user 0m0.041s
sys 0m0.047s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 6
# times low: 4
Longest high: 6
Longest low: 6
debian@BeagleBone:/mnt/remote/drivers$ time echo "----____----____----____----____----____" | sudo tee /dev/waveform
----____----____----____----____----____
real 0m10.121s
user 0m0.032s
sys 0m0.062s
debian@BeagleBone:/mnt/remote/drivers$ sudo cat /dev/waveform
# times high: 11
# times low: 9
Longest high: 6
Longest low: 6
debian@BeagleBone:/mnt/remote/drivers$