背景:
该问题发生在调试正点原子例程:beep。
基于教程上一章节LED的内容,本以为简单修改设备树和驱动文件即可(替换名字)。同时想添加自己的想法,对与函数位置也做了修改。
现象:
现象1:
使用modprob加载驱动显示modprobe: can't load module beep.ko (beep.ko): Invalid argument,如下图所示:
很明显,我加载我之前写好的LED驱动就不会显示无效参数这个报错,但是加载BEEP就会显示无效函数报错。
现象2:
多次加载和退出内核文件后,显示CPU报错,如下图:
原因:
原因1:
对于使用modprob加载驱动显示Invalid argument,排查下来是因为打开设备树获取端口名字发生错误。
例如在设备树中如下配置:
gpiobeep{
compatible = "alientek, gpiobeep";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_gpiobeep>;
status = "okay";
beep-gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
};
需要着重注意参数:beep-gpios,它的名字需要与函数: of_get_named_gpio(gpiobeep.nd, "beep-gpios", 0);中的字符串形参一致。
我犯的问题就是设备树中写的是led-gpios,而of_get_named_gpio函数中字符串形参写的是beep-gpios,从而导致显示Invalid argument。
请求端口可以不注意形参名字,参考如下:
截图正点原子教程视频, gpio_request函数中形参就自定义了。
原因2:
对于多次加载和退出内核文件后,显示CPU报错。需要注意如下几点:
1、退出函数中删除cdev、释放设备号、摧毁类、摧毁设备需要有先后顺序,否则会提示CPU报错。参考如下退出函数:
static void __exit gpiobeep_exit(void)
{
gpio_set_value(gpiobeep.beep_gpio, 1);
cdev_del(&gpiobeep.cdev);
unregister_chrdev_region(gpiobeep.devid, GPIOBEEP_CNT);
device_destroy(gpiobeep.class, gpiobeep.devid);
class_destroy(gpiobeep.class);
gpio_free(gpiobeep.beep_gpio);
}
2、在初始化函数中需要注意如果申请成功了,在退出函数中也要及时退出。例如在init函数中申请类成功了,那么exit函数中就要及时释放类,否则也会报错。
备注:
错误发生后记得重启设备,防止影响下一次加载驱动。否则可能上一次报错会影响后续的驱动加载。