This is a HowTo article for developing embedded Linux device drivers as kernel modules. All the content of this article can be run on a Raspberry Pi.
-1st time: Build environment preparation and simple kernel module creation -Second time: System call handler and driver registration (static method) -Third time: System call handler and driver registration (dynamic method) -4th: Read / write implementation and memory story -5th time: Implementation of GPIO driver for Raspberry Pi -6th time: Implementation of ioctl -7th time: Interface for procfs -8th time: Interface for debugfs -9th time: Call a function of another kernel module / Use GPIO control function -10th time: Create a device driver using I2C -11th time: Add I2C device to device tree --__ 12th time: Load the created device driver at startup <---------------- ----- Contents of this time __
So far, I've made device drivers, but I've manually insmoded them every time. This may be fine during development, but when actually incorporating it into the product, I want it to be automatically loaded when the kernel is started.
So far, I've built the MyDeviceModule.ko file in my development directory. Copy this to the official location of the kernel module. This location depends on the kernel version, so get it with ʻuname. After that, you need to update the kernel module dependency information. To do this, use the
depmod` command.
sudo cp MyDeviceModule.ko /lib/modules/$(uname -r)/kernel/drivers/.
sudo depmod -ae
With the copy and settings above, you can now load the device driver created with modprobe MyDeviceModule
from anywhere. It is OK if you describe this in the script that is executed at startup (for example, rc script). I think that there are various environment dependencies, but in Raspberry Pi, it seems that the module name should be described in /etc/modules-load.d/modules.conf
. Actually, I think that it is decided by considering the dependency with other modules and how fast you want it to load according to the product specifications.
sudo bash -c 'echo MyDeviceModule >> /etc/modules-load.d/modules.conf'
If you reboot and look at the log with dmesg, you can see that this device driver is loaded at startup.
dmesg
[ 7.595531] sd 0:0:0:0: Attached scsi generic sg0 type 0
[ 7.955417] usb 1-1.3: reset high-speed USB device number 4 using dwc_otg
[ 8.097012] ieee80211 phy0: rt2x00_set_rt: Info - RT chipset 5390, rev 0502 detected
[ 8.124187] MyDeviceModule: loading out-of-tree module taints kernel.
[ 8.131765] mydevice_i2c_probe
[ 8.131785] slave address = 0x18
[ 8.132270] id = 0x33
[ 8.173190] ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 5370 detected
[ 8.224829] ieee80211 phy0: Selected rate control algorithm 'minstrel_ht'
[ 8.231902] usbcore: registered new interface driver rt2800usb
[ 11.534982] Adding 102396k swap on /var/swap. Priority:-1 extents:1
In the case of the device driver that supports the device tree created last time, the kernel will automatically load MyDeviceModule.ko without editing /etc/modules-load.d/modules.conf
and explicitly loading it. I will. It seems that this is because the kernel automatically searches for and loads the device driver corresponding to the device registered in the device tree.
Finally it's over! !! I'm glad I finished this year ~
For some reason, I suddenly thought about it and have posted articles about Linux device drivers 12 times in total for about 10 days. I intend to make the content so that beginners, including myself, can understand it while actually trying it. Rather, it is a record of what the beginner himself has studied in the last two weeks.
Therefore, I think there are various missing parts. For example, exclusive control should be used when accessing variables, but it has been omitted. Also, before address translation, I should check if the address can be accessed, but I omitted that as well. These have been intentionally omitted for clarity of code and description. However, besides that, I think there are many mistakes that I am missing due to my lack of knowledge and understanding. I hope you can point out more and more in the comments.
The content described in this series is just one part of the Linux device driver. Also, the implementation method and rules are changing every day. You still need to read the Linux source code and documentation to get the latest information right. We hope that this series will serve as a stepping stone to take such a next step.
Finally, we would like to express our deep gratitude to Yutaka Hirata, who wrote "Linux Device Driver Programming". It is often said that you can read the source code and the documents, but at the beginning, the books that are explained in Japanese in an easy-to-understand manner were very useful.
http://elixir.free-electrons.com/linux/v4.14/source https://people.freedesktop.org/~narmstrong/meson_drm_doc/index.html
Recommended Posts