背景
触摸屏作为人机交互的关键设备之一,其稳定性对设备的使用至关重要,通常触摸屏的驱动会编进内核中,但是这会导致一个问题,如果触摸芯片概率性工作不正常会导致触摸驱动加载失败,影响设备的使用,所以需要将触摸驱动改成以模块的形式加载,那又引出另外一个问题:如何在开机之后加载触摸驱动?
开机后自动加载驱动的方式无非就是两种:
1、通过脚本加载
通过脚本加载有一个好处就是可定制化强,不依赖特定的策略和规则,例如,
- 如果触摸驱动加载失败可以通过脚本控制重复加载
- 如果在设备使用过程中触摸失灵,可以通过脚本控制触摸驱动重新加载
- 等等,其他情况
2、通过udev加载
使用udev的方式加载,从项目整体视角来看有益于标准化,减少重复造轮子,
本次调试的触摸芯片为: ili2131,触摸驱动的版本为:ilitek_limv5_9_0_2
修改内核配置,生成内核驱动模块,为了快速验证,直接修改Makefile:
//修改前
ccflags-y += -Wall
obj-y += ilitek.o
ilitek-y += ilitek_main.o \
ilitek_platform_init.o \
ilitek_update.o \
ilitek_tool.o \
ilitek_protocol.o \
ilitek_mp.o
//修改后
ccflags-y += -Wall
obj-m += ilitek.o
ilitek-y += ilitek_main.o \
ilitek_platform_init.o \
ilitek_update.o \
ilitek_tool.o \
ilitek_protocol.o \
ilitek_mp.o
根据设备树配置修改udev规则,设备树配置 i2c 第三通道 地址 0x41 :
/* touch */
&i2c3 {
clock_frequency = <400000>;
pinctrl-names = "default";
status = "okay";
ili2131: ili2131@41 {
compatible = "tchip,ilitek";
reg = <0x41>;
pinctrl-names = "default";
pinctrl-0 = <&ilitek_ili2131_pins>;
interrupt-parent = <&gpio4>;
interrupts = <1 IRQ_TYPE_EDGE_FALLING>;
ilitek,irq-gpio = <&gpio4 1 IRQ_TYPE_EDGE_FALLING>;
ilitek,reset-gpio = <&gpio1 12 GPIO_ACTIVE_HIGH>;
ilitek,name = "ilitek_i2c";
touchscreen-swapped-x-y;
touchscreen-revert-y;
touchscreen-lcm-resolution;
touchscreen-lcm-resolution-x = <800>;
touchscreen-lcm-resolution-y = <1280>;
};
};
udev动态加载规则文件:/lib/udev/rules.d/80-drivers.rules
//修改前
root@myd-imx8mm:/lib/udev/rules.d# cat 80-drivers.rules
# do not edit this file, it will be overwritten on update
ACTION!="add", GOTO="drivers_end"
ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms"
SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block"
SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block"
SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev"
KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl"
LABEL="drivers_end"
root@myd-imx8mm:/lib/udev/rules.d#
//添加规则
root@myd-imx8mm:/lib/udev/rules.d# cat 80-drivers.rules
# do not edit this file, it will be overwritten on update
ACTION!="add", GOTO="drivers_end"
ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd"
SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="MS", RUN{builtin}+="kmod load tifm_ms"
SUBSYSTEM=="memstick", RUN{builtin}+="kmod load ms_block mspro_block"
SUBSYSTEM=="i2o", RUN{builtin}+="kmod load i2o_block"
SUBSYSTEM=="module", KERNEL=="parport_pc", RUN{builtin}+="kmod load ppdev"
KERNEL=="mtd*ro", ENV{MTD_FTL}=="smartmedia", RUN{builtin}+="kmod load sm_ftl"
SUBSYSTEM=="i2c" KERNEL=="2-0041" RUN{builtin}+="kmod load i2c:ilitek_ts"
SUBSYSTEM=="i2c" KERNEL=="2-0041" RUN{program}+="/bin/mkdir /home/root/i2c -p"
LABEL="drivers_end"
root@myd-imx8mm:/lib/udev/rules.d#
其中,SUBSYSTEM=="i2c" KERNEL=="2-0041" RUN{program}+="/bin/mkdir /home/root/i2c -p" 为测试规则,测试匹配规则是否生效,同时也可以使用udevadm 测试:
root@myd-imx8mm:/lib/udev/rules.d# udevadm test /sys/bus/i2c/devices/2-0041
This program is for debugging only, it does not run any program
specified by a RUN key. It may show incorrect results, because
some values may be different, or not available at a simulation run.
Load module index
Skipping empty file: /etc/systemd/network/99-default.link
Created link configuration context.
Reading rules file: /etc/udev/rules.d/10-imx.rules
Configuration file /etc/udev/rules.d/40-libgphoto2.rules is marked executable. Please remove executable permission bits. Proceeding anyway.
Reading rules file: /etc/udev/rules.d/40-libgphoto2.rules
Reading rules file: /lib/udev/rules.d/50-udev-default.rules
Reading rules file: /lib/udev/rules.d/60-block.rules
Reading rules file: /lib/udev/rules.d/60-cdrom_id.rules
Reading rules file: /lib/udev/rules.d/60-drm.rules
Reading rules file: /lib/udev/rules.d/60-evdev.rules
Reading rules file: /lib/udev/rules.d/60-input-id.rules
Reading rules file: /lib/udev/rules.d/60-persistent-alsa.rules
Reading rules file: /lib/udev/rules.d/60-persistent-input.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage-tape.rules
Reading rules file: /lib/udev/rules.d/60-persistent-storage.rules
Reading rules file: /lib/udev/rules.d/60-persistent-v4l.rules
Reading rules file: /lib/udev/rules.d/60-sensor.rules
Reading rules file: /lib/udev/rules.d/60-serial.rules
Reading rules file: /lib/udev/rules.d/64-btrfs.rules
Reading rules file: /lib/udev/rules.d/70-joystick.rules
Reading rules file: /lib/udev/rules.d/70-mouse.rules
Reading rules file: /lib/udev/rules.d/70-power-switch.rules
Reading rules file: /lib/udev/rules.d/70-touchpad.rules
Reading rules file: /lib/udev/rules.d/70-uaccess.rules
Reading rules file: /lib/udev/rules.d/71-seat.rules
Reading rules file: /etc/udev/rules.d/71-weston-drm.rules
Reading rules file: /lib/udev/rules.d/73-seat-late.rules
Reading rules file: /lib/udev/rules.d/75-net-description.rules
Reading rules file: /lib/udev/rules.d/75-probe_mtd.rules
Reading rules file: /lib/udev/rules.d/78-sound-card.rules
Reading rules file: /lib/udev/rules.d/80-drivers.rules
Reading rules file: /lib/udev/rules.d/80-libinput-device-groups.rules
Reading rules file: /lib/udev/rules.d/80-net-setup-link.rules
Reading rules file: /lib/udev/rules.d/89-alsa-ucm.rules
Reading rules file: /lib/udev/rules.d/90-alsa-restore.rules
Reading rules file: /lib/udev/rules.d/90-libinput-fuzz-override.rules
Reading rules file: /lib/udev/rules.d/90-pulseaudio.rules
Reading rules file: /lib/udev/rules.d/90-vconsole.rules
Reading rules file: /lib/udev/rules.d/97-hid2hci.rules
Reading rules file: /lib/udev/rules.d/99-systemd.rules
Reading rules file: /etc/udev/rules.d/automount.rules
Reading rules file: /etc/udev/rules.d/autonet.rules
Reading rules file: /etc/udev/rules.d/localextra.rules
Reading rules file: /etc/udev/rules.d/touchscreen.rules
DEVPATH=/devices/platform/soc@0/soc@0:bus@30800000/30a40000.i2c/i2c-2/2-0041
OF_NAME=ili2131
OF_FULLNAME=/soc@0/bus@30800000/i2c@30a40000/ili2131@41
OF_COMPATIBLE_0=tchip,ilitek
OF_COMPATIBLE_N=1
MODALIAS=of:Nili2131T(null)Ctchip,ilitek
ACTION=add
SUBSYSTEM=i2c
USEC_INITIALIZED=9611258939
run: 'kmod load of:Nili2131T(null)Ctchip,ilitek'
Unload module index
Unloaded link configuration context.
如此可以通过udev自动匹配加载驱动
3、修改/etc/modprobe.d,可参考ubuntu系统配置文件如:
richard@ubuntu24:~$ cat /etc/modprobe.d/alsa-base.conf
# autoloader aliases
install sound-slot-0 /sbin/modprobe snd-card-0
install sound-slot-1 /sbin/modprobe snd-card-1
install sound-slot-2 /sbin/modprobe snd-card-2
install sound-slot-3 /sbin/modprobe snd-card-3
install sound-slot-4 /sbin/modprobe snd-card-4
install sound-slot-5 /sbin/modprobe snd-card-5
install sound-slot-6 /sbin/modprobe snd-card-6
install sound-slot-7 /sbin/modprobe snd-card-7
# Cause optional modules to be loaded above generic modules
install snd /sbin/modprobe --ignore-install snd $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-ioctl32 ; /sbin/modprobe --quiet --use-blacklist snd-seq ; }
#
# Workaround at bug #499695 (reverted in Ubuntu see LP #319505)
install snd-pcm /sbin/modprobe --ignore-install snd-pcm $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-pcm-oss ; : ; }
install snd-mixer /sbin/modprobe --ignore-install snd-mixer $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-mixer-oss ; :; }
install snd-seq /sbin/modprobe --ignore-install snd-seq $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-seq-midi ; /sbin/modprobe --quiet --use-blacklist snd-seq-oss ; : ; }
#
install snd-rawmidi /sbin/modprobe --ignore-install snd-rawmidi $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-seq-midi ; : ; }
# Cause optional modules to be loaded above sound card driver modules
install snd-emu10k1 /sbin/modprobe --ignore-install snd-emu10k1 $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-emu10k1-synth ; }
install snd-via82xx /sbin/modprobe --ignore-install snd-via82xx $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist snd-seq ; }
# Load saa7134-alsa instead of saa7134 (which gets dragged in by it anyway)
install saa7134 /sbin/modprobe --ignore-install saa7134 $CMDLINE_OPTS && { /sbin/modprobe --quiet --use-blacklist saa7134-alsa ; : ; }
# Prevent abnormal drivers from grabbing index 0
options bt87x index=-2
options cx88_alsa index=-2
options saa7134-alsa index=-2
options snd-atiixp-modem index=-2
options snd-intel8x0m index=-2
options snd-via82xx-modem index=-2
options snd-usb-audio index=-2
options snd-usb-caiaq index=-2
options snd-usb-ua101 index=-2
options snd-usb-us122l index=-2
options snd-usb-usx2y index=-2
# Ubuntu #62691, enable MPU for snd-cmipci
options snd-cmipci mpu_port=0x330 fm_port=0x388
# Keep snd-pcsp from being loaded as first soundcard
options snd-pcsp index=-2
# Keep snd-usb-audio from beeing loaded as first soundcard
options snd-usb-audio index=-2
mkdir /etc/modprobe.d
touch /etc/modprobe.d/ilitek.conf
echo "ilitek" >>ilitek.conf
4、通过systemd-udev加载模块,查看/usr/lib/systemd/system/systemd-modules-load.service服务:
# SPDX-License-Identifier: LGPL-2.1-or-later
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Load Kernel Modules
Documentation=man:systemd-modules-load.service(8) man:modules-load.d(5)
DefaultDependencies=no
Conflicts=shutdown.target
Before=sysinit.target shutdown.target
ConditionCapability=CAP_SYS_MODULE
ConditionDirectoryNotEmpty=|/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/lib/modules-load.d
ConditionDirectoryNotEmpty=|/usr/local/lib/modules-load.d
ConditionDirectoryNotEmpty=|/etc/modules-load.d
ConditionDirectoryNotEmpty=|/run/modules-load.d
ConditionKernelCommandLine=|modules-load
ConditionKernelCommandLine=|rd.modules-load
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/lib/systemd/systemd-modules-load
TimeoutSec=90s
在lib/modules-load.d等文件中添加要加载的模块即可
5、参考 /lib/systemd/system/rc-local.service,修改/etc/rc.local即可。
6、通过启动参数加载
除了配置文件,systemd-modules-load.service还支持识别以下的内核引导选项:
modules_load=, rd.modules_load=
上述选项通过接受一个内核模块列表,表示在系统启动的早期,无条件的加载这些内核模块。以 “rd.” 作为前缀的选项仅作用于 initial RAM disk 环境。