全志orangepi-zero2驱动编写

编译内核

编写驱动之前先去官网下载,手册,跳到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

这里作为一个拓展吧,每个内核编译都可能不同,具体找商家手册来看

驱动编写框架

驱动两种加载方式:

  • *编译进内核 zImage包含了驱动
  • M 模块方式生成驱动文件xxx.ko 系统启动后,通过命令inmosd xxx.ko 加载

驱动框架

#include <linux/fs.h>				//file_operations声明
#include <linux/module.h>			//module_init module_exit声明
#include <linux/init.h>				//__init__exit 宏声明
#include <linux/device.h>			//class device 声明
#include <linux/uaccess.h>			//copy_from_user的头文件
#include <linux/types.h>			//设备号dev_t类型声明
#include <asm/io.h>					//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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

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即可)

在这里插入图片描述
保存退出wq

使用命令编译

回到内核源码这里的路径进行编译

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 文件//卸掉驱动

成功;

结束

如有问题欢迎提出,共同进步

猜你喜欢

转载自blog.csdn.net/qq_52749711/article/details/132409329