编写驱动之前先去官网下载,手册,跳到5.几章先弄好内核编译
照着手册来,没问题。(文章说需要切换清华的源)(我没切换)(反而切换出了很多错误)
http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/service-and-support/Orange-Pi-Zero-2.html
必须内核编译,驱动编写,需要一个编译好的内核
编译成功后,看到源码树目录多了vmlinux,失败则无此文件
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
指定ARM架构 指定编译器 树莓派 主要核心指令
第一种方式:
cp 厂家.config .config
第二种方式:
make menuconfig 一项项配置,通常是基于厂家的config来配置
第三种方式:
完全自己来
编译:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
编译成功后,看到源码树目录多了vmlinux,失败则无此文件
成功后,目标zImage镜像arch/arm/boot底下
打包zImage成树莓派可用的xxx.img
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
这里作为一个拓展吧,每个内核编译都可能不同,具体找商家手册来看
驱动两种加载方式:
#include //file_operations声明
#include //module_init module_exit声明
#include //__init__exit 宏声明
#include //class device 声明
#include //copy_from_user的头文件
#include //设备号dev_t类型声明
#include //ioremap iounmap的头文件
static struct class *pin4_class;
static struct device *pin4_class_dev;
static dev_t devno; //设备号
static int major =231; //主设备号
static int minor =0; //次设备号
static char *module_name="pin4"; //模块名
//ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
static ssize_t pin4_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
printk("pin4_read\n");
return 0;
}
static int pin4_open(struct inode *inode,struct file *file)
{
printk("pin4_open\n"); //内核打印函数,和printf类似
return 0;
}
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{
printk("pin4_write\n");
return 0;
}
static struct file_operations pin4_fops = {
.owner = THIS_MODULE,
.open = pin4_open,
.write = pin4_write,
.read = pin4_read,
};
//static int __init
static int pin4_drv_init(void)
{
int ret;
devno = MKDEV(major,minor);
ret = register_chrdev(major, module_name,&pin4_fops);
pin4_class=class_create(THIS_MODULE,"myfirstdemo");
pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);
return 0;
}
static void pin4_drv_exit(void)
{
device_destroy(pin4_class,devno);
class_destroy(pin4_class);
unregister_chrdev(major, module_name);
}
module_init(pin4_drv_init);
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");
这个框架需要和用户态的open等函数进行配合,需要知道linux内核框图可明白
这里直接放上代码,去和驱动框架进行配合
#include
#include
#include
#include
#include
int main()
{
int fd;
fd = open("/dev/pin4",O_RDWR);
if(fd < 0){
printf("open fail\n");
}else {
printf("open success\n");
}
fd = write(fd,'1',1);
}
这里俩个文件,放入先放入虚拟机交叉编译。
驱动代码需要内核编译成模块,再用scp上传开发板。
普通代码编译完,也上传到开发板就可以。
编译成模块方法:
使用aarch64-none-linux-gnu-先设置环境变量
cd ~
vi .bashrc
最后一行添加export PATH = $PATH: /……/bin//aarch64-none-linux-gnu-命令所在地位置
(在内核编译完成之后个toolchain文件夹在里面找)
在这个文件夹下,放入你的驱动代码
orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char
修改Makefile文件
vi Makefile
添加咱们写的驱动
obj-m +=pin4Dev.o(文件名是啥就写啥后缀为.o即可)
使用命令编译
回到内核源码这里的路径进行编译
orangepi-build-main/kernel/orange-pi-4.9-sun50iw9
输入命令
ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- KERNEL=kernel make modules
将.ko文件放到(没有ko就是内核编译有问题,重新编译去)
通过以下命令配合
sudo insmod 文件.ko //加载驱动
//加载驱动以后,在/dev/pin4就会看到
//但是此时运行我们的测试代码是打不开的,需要添加权限
sudo chmod 666 /dev/pin4 //所有用户可读可写
./a.out//测试文件,看到打开成功
//如果看不到输出信息可以输入
dmesg |grep pin4//可查看内核态输出信息
lsmod //查看驱动
sudo rmmod 文件//卸掉驱动
成功;
如有问题欢迎提出,共同进步