《Linux驱动开发(一)—环境搭建与hello world》
《Linux驱动开发(二)—驱动与设备的分离设计》
《Linux驱动开发(三)—设备树》
《Linux驱动开发(四)—树莓派内核编译》
继续宣传一下韦老师的视频
70天30节Linux驱动开发快速入门系列课程【实战教学、技术讨论、直播答疑】
为了继续学习设备树的驱动开发,必须把这块功能在树莓派上弄清楚。
开启ubuntu的ssh许可root用户登录,因为我这里的编译用的都是root权限。
安装vim,系统自带的vi是有问题的
apt install vim
重设root密码
sudo passwd root
修改ssh的配置
sudo vim /etc/ssh/sshd_config
重启ssh服务
sudo service ssh restart
然后就可以通过winscp,登录root用户,进行文件传输拷贝了。
入门自然helloworld,先试试能不能编译出模块。
#include
#include
#include
static int __init hello_init(void)
{
printk("hello world\n");
return 0;
}
static void __exit hello_exit(void)
{
printk("byebye world\n");
}
module_init(hello_init);
module_exit(hello_exit);
MODULE_LICENSE("GPL");
hellowrold.c先放入linux/drivers/char下,然后修改该目录下Makefile
最后编译,命令是
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules
然后将编译出的ko文件。上传到树莓派的板子上。
在开发板上加载模块
参考前文的分离思想,测试一下代码
《Linux驱动开发(二)—驱动与设备的分离设计》
编译还是参考前面的方式,修改Makefile,会得到两个ko文件
在树莓派上测试一下。
pgg@raspberrypi:~/work/dirver $ sudo insmod led_drv.ko
pgg@raspberrypi:~/work/dirver $ sudo insmod led_dev.ko
pgg@raspberrypi:~/work/dirver $ dmesg
[10692.141994] drivers/char/led_drv.c led_init line 141
[10698.157100] drivers/char/led_dev.c led_dev_init 47
[10698.157516] drivers/char/led_drv.c led_probe 83
莫得问题。顺利进行了probe函数操作
增加上用户侧的程序
int main(int argc, char **argv)
{
int fd;
char status;
/* 1. 判断参数 */
if (argc != 3)
{
printf("Usage: %s \n" , argv[0]);
return -1;
}
/* 2. 打开文件 */
fd = open(argv[1], O_RDWR);
if (fd == -1)
{
printf("can not open file %s\n", argv[1]);
return -1;
}
/* 3. 写文件 */
if (0 == strcmp(argv[2], "on"))
{
status = 1;
write(fd, &status, 1);
}
else
{
status = 0;
write(fd, &status, 1);
}
close(fd);
return 0;
}
pgg@raspberrypi:~/work/dirver $ gcc -o usertest ledtest.c
pgg@raspberrypi:~/work/dirver $ sudo ./usertest /dev/100ask_led0 on
pgg@raspberrypi:~/work/dirver $ sudo ./usertest /dev/100ask_led0 off
pgg@raspberrypi:~/work/dirver $ dmesg
[10692.141994] drivers/char/led_drv.c led_init line 141
[10698.157100] drivers/char/led_dev.c led_dev_init 47
[10698.157516] drivers/char/led_drv.c led_probe 83
[10884.356502] drivers/char/led_drv.c led_drv_open line 59
[10884.356535] init led pin 0x301 as output
[10884.356560] drivers/char/led_drv.c led_drv_write line 46
[10884.356573] set led pin 0x301 as 1
[10888.891303] drivers/char/led_drv.c led_drv_open line 59
[10888.891335] init led pin 0x301 as output
[10888.891360] drivers/char/led_drv.c led_drv_write line 46
[10888.891373] set led pin 0x301 as 0
怎么一点难度没有呢
首先找到设备使用的设备树文件,感觉起来有点像它,因为是3b+的板子,并且它也编译成了dtb文件
修改它,增加一个设备节点,代码均借鉴与韦东山老师的例子。
然后我们重新编译一下dtb
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make dtbs
root@ubuntu:/home/pgg/shumeipai/linux# ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make dtbs
DTC arch/arm/boot/dts/bcm2710-rpi-3-b-plus.dtb
然后我们参考前文,将dbts拷贝到SD卡上,重启设备。
插卡,挂载
mkdir -p /home/pgg/mnt
mkdir -p /home/pgg/mnt/fat32
mkdir -p /home/pgg/mnt/ext4
sudo mount /dev/sdb1 /home/pgg/mnt/fat32
sudo mount /dev/sdb2 /home/pgg/mnt/ext4
拷贝
sudo cp -f arch/arm/boot/dts/*.dtb /home/pgg/mnt/fat32/
sudo cp -f arch/arm/boot/dts/overlays/*.dtb* /home/pgg/mnt/fat32/overlays/
sudo cp -f arch/arm/boot/dts/overlays/README /home/pgg/mnt/fat32/overlays/
卸载
sudo umount /home/pgg/mnt/fat32
sudo umount /home/pgg/mnt/ext4
重启设备,一气呵成。
通过下面命令
ls /proc/device-tree
参考本系列第三章的内容,增加of_match_table
static const struct of_device_id dts_device_ids[] = {
{ .compatible = "100ask,led", },
{/* sentinel */}
};
/* A. 实现platform_driver */
static struct platform_driver led_driver = {
.probe = led_probe,
.remove = led_remove,
.driver = {
.name = "100ask_led",
.of_match_table = dts_device_ids,
},
};
并且读取数据的时候,与普通device区分开
重新编译模块,然后上传开发板,装在模块的时候,会执行到probe函数,成功了。
pgg@raspberrypi:~/work/dirver $ sudo insmod led_drv.ko
pgg@raspberrypi:~/work/dirver $ sudo dmesg
[ 7008.409062] drivers/char/led_drv.c led_init line 151
[ 7008.409380] drivers/char/led_drv.c led_probe 85
[ 7008.409392] pin = gpio5_3
pgg@raspberrypi:~/work/dirver $ ls /dev/100ask_led0
/dev/100ask_led0
还是通过前面的用户侧代码
pgg@raspberrypi:~/work/dirver $ gcc -o usertest ledtest.c
pgg@raspberrypi:~/work/dirver $ sudo ./usertest /dev/100ask_led0 on
pgg@raspberrypi:~/work/dirver $ dmesg
[ 7434.344304] drivers/char/led_drv.c led_drv_open line 60
[ 7434.344341] init led pin 0x3 as output
[ 7434.344369] drivers/char/led_drv.c led_drv_write line 47
[ 7434.344384] set led pin 0x3 as 1
pgg@raspberrypi:~/work/dirver $ sudo ./usertest /dev/100ask_led0 off
pgg@raspberrypi:~/work/dirver $ dmesg
[ 7434.344304] drivers/char/led_drv.c led_drv_open line 60
[ 7434.344341] init led pin 0x3 as output
[ 7434.344369] drivers/char/led_drv.c led_drv_write line 47
[ 7434.344384] set led pin 0x3 as 1
[ 7446.053860] drivers/char/led_drv.c led_drv_open line 60
[ 7446.053896] init led pin 0x3 as output
[ 7446.053924] drivers/char/led_drv.c led_drv_write line 47
[ 7446.053939] set led pin 0x3 as 0
至此,通过设备树提供设备信息,配合驱动创建节点的功能已经完成。
今天的学习真的好舒畅,没有坎坷,至少,没有让你们看到
最近的天气是真的热,感觉不开空调都难受的慌,以前公司在四川的总部,都会有有高温假,以前觉得还挺好,其实也是怕员工出事。最近开始流行一个词,热射病,其实就是以前的中暑而已,尤其是在南方,空气湿度大的时候,身体热量散发不出去,很容易中暑。
不过看了一篇介绍热射病的文章,令我意外的是评论:
他说好的工作可以选择,通过努力,学习可以选择到舒服的环境。倒退二十年,我也许会觉得这个说法对,但是现在看起来,也不尽然。
100份工作,可能只有1份是舒服的,9份是不会中暑的,我们要追求的,是不是拼命内卷,踩过别人得到那九分之一?至于那舒服的一份,可能是普通人看都看不到的生活,而且,他还决定着其他90份工作,会不会中暑。
我们只是可以庆幸,能够通过学习得到了一份吹空调的工作,但不要说别人不努力,外卖小哥,建筑工人,流水线的张全蛋们,谁不是在努力的活着。
文章结尾有一段话,可能也是我们唯一能为这种情况做出的一点改善
但是有一件事,可以号召。那就是如果你生活在高温高湿的地区,这么热的天,叫了外卖,可以顺手塞给师傅一瓶水,最好是冰箱里的冰水。
你打赏,五块起,而且他未必舍得买水,你从冰箱里拿瓶水给他,批发来的成本才一两块钱。
他拿了水不可能转手卖掉,所以一定会喝,或许,这就是你救了他。