Article directory
Compile kernel
Before writing the driver, go to the official website to download the manual, skip to 5. First compile the kernel and follow
the manual, no problem. (The article said that the source of Tsinghua University needs to be switched) (I did not switch) (On the contrary, many errors occurred when switching)
Kernel compilation and driver writing are required, and a compiled kernel is required.
After the compilation is successful, you will see that there is vmlinux in the source tree directory. If it fails, there will be no such file.
To expand, there are several ways to compile the kernel for other boards (you don’t need to look at it): The following is the kernel compilation for the Raspberry Pi board
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
指定ARM架构 指定编译器 树莓派 主要核心指令
第一种方式:
cp 厂家.config .config
第二种方式:
make menuconfig 一项项配置,通常是基于厂家的config来配置
第三种方式:
完全自己来
Compile :
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
After the compilation is successful, you will see that there is vmlinux in the source tree directory. If it fails, there will be no such file.
After success, the target zImage image will be under arch/arm/boot.
Package zImage into xxx.img available for Raspberry Pi
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
Let’s use this as an extension. Each kernel compilation may be different. Please check the merchant’s manual for details.
Driver writing framework
There are two ways to load the driver:
- * Compiled into the kernel zImage includes the driver
- Generate the driver file xxx.ko in M module mode. After the system is started, load it through the command inmosd xxx.ko
driver framework
#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");
This framework needs to cooperate with functions such as open in user mode. If you need to know the Linux kernel block diagram, you can
directly put the code here to cooperate with the driver framework.
#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);
}
Here are two files, first put them into the virtual machine for cross-compilation.
The driver code needs to be compiled into a module by the kernel, and then uploaded to the development board using scp.
After the ordinary code is compiled, it can also be uploaded to the development board.
Compile into module method:
使用aarch64-none-linux-gnu-先设置环境变量
cd ~
vi .bashrc
最后一行添加export PATH = $PATH: /……/bin//aarch64-none-linux-gnu-命令所在地位置
(在内核编译完成之后个toolchain文件夹在里面找)
In this folder, put your driver code
orangepi-build-main/kernel/orange-pi-4.9-sun50iw9/drivers/char
Modify the Makefile
vi Makefile
Add the driver we wrote
obj-m +=pin4Dev.o(文件名是啥就写啥后缀为.o即可)
Save and exit wq
Compile using command
Go back to the path here in the kernel source code to compile.
orangepi-build-main/kernel/orange-pi-4.9-sun50iw9
input the command
ARCH=arm64 CROSS_COMPILE=aarch64-none-linux-gnu- KERNEL=kernel make modules
Put the .ko file (if there is no ko, there is a problem with the kernel compilation, recompile it)
Cooperate with the following command
sudo insmod 文件.ko //加载驱动
//加载驱动以后,在/dev/pin4就会看到
//但是此时运行我们的测试代码是打不开的,需要添加权限
sudo chmod 666 /dev/pin4 //所有用户可读可写
./a.out//测试文件,看到打开成功
//如果看不到输出信息可以输入
dmesg |grep pin4//可查看内核态输出信息
lsmod //查看驱动
sudo rmmod 文件//卸掉驱动
success;
Finish
If you have any questions, you are welcome to ask them and make progress together.