linux驱动开发, 有特定的模式, 在我看来linux驱动只做了一件事,
将设备统一转换成了统一的3类虚拟设备
分别是:
1. 字符设备
2. 块设备
3. 网络设备
linux驱动开发, 需要在Ubuntu系统中
(一般是在Ubuntu下开发, 然后编译. 当然也可以在windows下交叉编译, 但是为了避免横生事端, 一般都是在Ubuntu下面开发. )
环境准备
开发的时候需要先下载 linux SDK
压缩包目前是15GB, 解压需要11GB,(What? 越压缩越大?)
为啥需要 Linux SDK? 因为里面包含调用 Linux所需要的各种头文件.c++写的.做linux驱动开发得会c++, 虽然我不会c++只会c, 但是看了驱动开发之后, 反而让我学会了c++. 我看的视频教程是 正点原子提供的视频. 对于新手来讲最好先学会c并且会用c语言的 struct 和指针. 然后在看linux驱动开发, 你的c++功底会更上一层楼. 否则有可能让你崩溃.
开发步骤.
linux驱动程序的文件形式
1. linux驱动程序可以编译到kernel 中, 也就是zimage文件中,
2.也可以单独编译成 .ko文件,测试的时候只需要加载ko文件即可
驱动加载
驱动编译好之后文件扩展名为.ko, 有两种命令可以加载模块,insmod和modprobe
insmod led.ko
或者
modprobe led
两种方法的区别
modprobe和insmod类似,都是用来动态加载驱动模块的,区别在于modprobe可以解决load module时的依赖关系,它是通过/lib/modules/#uname -r/modules.dep(.bb)文件来查找依赖关系的;而insmod不能解决依赖问题。
也就是说,如果你确定你要加载的驱动模块不依赖其他驱动模块的话,既可以insmod也可以modprobe,当然insmod可以在任何目录下执行,更方便一些。而如果你要加载的驱动模块还依赖其他ko驱动模块的话,就只能将模块拷贝到上述的特定目录,depmod后再modprobe。
模型加载之前要先执行一下:
depmod
depmod 会在/lib/modules/#uname -r#/目录下生成modules.dep和modules.dep.bb文件,表明模块的依赖关系
然后执行命令,加载led.ko驱动
modprobe led
lsmod 是用来查询有哪些驱动.
lsmod
卸载驱动
modprobe -r led.ko
或者
rmmod led.ko
以上是准备工作, 下面开始正式开始写驱动
经过1天的测试发现, Firefly-RK3399pro开发板和正点原子讲的不一样.
遇到各种问题, 这些问题就不一一列举了, 直接上正确的代码和步骤.
第一步下载Linux SDK, 我是下载的 Firefly提供的Linux SDK
开发环境的准备, 参照 Firefly 编译 Ubuntu 固件 ( GPT )
官方给的文档写的不清楚.
我这里重新修正一下
搭建 SDK 编译环境
sudo apt-get update
sudo apt-get install repo git-core gitk git-gui gcc-arm-linux-gnueabihf u-boot-tools device-tree-compiler \
gcc-aarch64-linux-gnu mtools parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools \
linaro-image-tools gcc-arm-linux-gnueabihf libssl-dev liblz4-tool genext2fs lib32stdc++6 \
gcc-aarch64-linux-gnu g+conf autotools-dev libsigsegv2 m4 intltool libdrm-dev curl sed make \
binutils build-essential gcc g++ bash patch gzip bzip2 perl tar cpio python unzip rsync file bc wget \
libncurses5 libqt4-dev libglib2.0-dev libgtk2.0-dev libglade2-dev cvs git mercurial rsync openssh-client \
subversion asciidoc w3m dblatex graphviz python-matplotlib libssl-dev texinfo fakeroot \
libparse-yapp-perl default-jre patchutils swig chrpath diffstat gawk time expect-dev
我这里还遇到了需要安装openssl和另外一个压缩工具lz4,建议直接执行下面两个命令
sudo apt-get install libssl-dev
sudo apt-get install liblz4-tool
注意: Ubuntu17.04 或者更高的系统还需要如下依赖包:
sudo apt-get install lib32gcc-7-dev g++-7 libstdc++-7-dev
下载 Firefly_Linux_SDK 分卷压缩包
由于 Firefly_Linux_SDK 源码包比较大,部分用户电脑不支持4G以上文件或单个文件网络传输较慢, 所以我们采用分卷压缩的方法来打包SDK。用户可以通过如下方式获取 Firefly_Linux_SDK源码包:Firefly_Linux_SDK源码包
下载完成后先验证一下 MD5 码:
$ md5sum rk3399pro_linux_release_v2.5.1_20210304_split_dir/*firefly_split*
结果应该如下
743e23a6119eb83b1f877db815c5031c rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file0
3bb8b245377e659b225019dfcedce7a9 rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file1
88c368a0b62058dbe500cc626bd8b01f rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file2
3b7b379da70e2fee785117e1ae2610bf rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file3
eaccf65d80c8f70ad781d2b876361e34 rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file4
81eaafd1e511e29474fe4445e78d2862 rk3399pro_linux_release_v2.5.1_20210304_firefly_split.file5
解压 Firefly_Linux_SDK 分卷压缩包
md5校验无误后可以解压.
cat rk3399pro_linux_release_v2.5.1_20210304_split_dir/*firefly_split* | tar -xzv
# 本SDK文件夹内包含一个 .repo 目录,解压之后,在当前目录下执行以下操作
cd rk3399pro_linux_release_v2.5.1_20210304
ls -al
.repo/repo/repo sync -l
.repo/repo/repo sync -c --no-tags
.repo/repo/repo start firefly --all
更新 Firefly_Linux_SDK
后续可以使用以下命令更新 SDK
.repo/repo/repo sync -c --no-tags
Linux_SDK 目录介绍
├── linux_sdk
│ ├── app
│ ├── buildroot buildroot 根文件系统的编译目录
│ ├── build.sh -> device/rockchip/common/build.sh 全自动编译脚本
│ ├── device 编译相关配置文件
│ ├── distro debian 根文件系统生成目录
│ ├── docs 文档
│ ├── envsetup.sh -> buildroot/build/envsetup.sh
│ ├── external
│ ├── kernel 内核
│ ├── Makefile -> buildroot/build/Makefile
│ ├── mkfirmware.sh -> device/rockchip/common/mkfirmware.sh rockdev链接更新脚本
│ ├── prebuilts
│ ├── rkbin
│ ├── rkflash.sh -> device/rockchip/common/rkflash.sh 烧写脚本
│ ├── rootfs debian根文件系统编译目录
│ ├── tools 烧写、打包工具
│ └── u-boot
到此为止, 环境基本上是准备好了. 官方给的文档里面, 后面还有一些乱七八糟的说明, 可以分别编译kernel,u-boot,recovery , rootfs. 有需要的朋友可以去官网看. 但是这不是本文的重点. 我们要的是如何编写驱动程序 . 下面开始介绍如何开始编写自己的驱动.
我采取的是make 一个ko文件, 然后把ko文件复制到板子上, 然后在板子上加载驱动. 这样的套路户比较简单一些. 不需要全部重新烧写. 我担心烧写会搞坏了我写好的东西. 毕竟很多代码都在上面呢.
下文主要是参考了 Firefly-RK3399 第一个驱动程序编制 这篇文章
正式开始编写驱动
新建一个自己的文件夹, 放在自己的项目目录下, 不需要放在Linux SDK目录下.
编写主驱动程序 led.c
#include
#include
static int __init led_init(void){
printk("led_init ");
return 0;
}
static void __exit led_exit(void){
printk("led_exit ");
return ;
}
module_init(led_init);
module_exit(led_exit);
MODULE_LICENSE("GPL");
编写Makefile
注意这里的makefile中最大的问题, 可能是KERNELDIR 一定要指定到kernel 目录下.才行.
#!/bin/bash
# CROSS_COMPILE:= aarch64-linux-gnu-
# ARCH:= arm64
# CC:= $(CROSS_COMPILE)gcc
# LD:= $(CROSS_COMPILE)ld
PWD :=$(shell pwd)
obj-m += led.o
KERNELDIR :=/home/roota/Desktop/AI/LinuxSDK/rk3399pro_linux_release_v2.5.1_20210304/kernel
all:
make -C $(KERNELDIR) M=$(PWD) modules
rm -f *.o
rm -f *.symvers
rm -f *.order
rm -f *.mod.c
rm -f .led.ko.cmd
rm -f .led.mod.o.cmd
rm -f .led.o.cmd
clean:
# $(MAKE) -C $(KERNELDIR) M=$(CURRENT_DIR) clean
rm -f *.o
rm -f *.symvers
rm -f *.order
rm -f *.ko
rm -f *.mod.c
rm -f .led.ko.cmd
rm -f .led.mod.o.cmd
rm -f .led.o.cmd
# ————————————————
# 版权声明:本文为CSDN博主「八喜.王」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
# 原文链接:https://blog.csdn.net/zwwang2014/article/details/88394210
编译
make
编译程序结果会出现led.ko
执行
把led.ko文件复制到开发板上.
加载模块
sudo insmod led.ko
查看模块
cat /proc/modules
或
lsmod
卸载模块
sudo rmmod led
提高开发效率
编译的时候makefile中会将编译好的led.ko文件自动复制到ftp目录下
cp led.ko /home/ftp/led.ko
然后开发板上执行下面的脚本就可以做到自动更新驱动.
优化的加载更新驱动的脚本sh文件, 运行在开发板上.
AutoUpdateDriver.sh
rmmod led
wget ftp://roota:[email protected]/ftp/led.ko -P /lib/modules/`uname -r`
sudo mkdir /lib/modules/`uname -r`
cd /lib/modules/`uname -r`
sudo depmod -a
sudo modprobe led #这个执行可能会出错. 执行下面的这个也可以.
sudo insmod led.ko
sudo lsmod
另外firefly 给推进了一个比较不错的视频教程.
https://dev.t-firefly.com/thread-100207-1-1.html