树莓派内核驱动配置
cat /proc/cpu/nfo可查看cpu信息。pi3 pi4cpu型号不同,起始地址不同。pi3是BCM2835 PI4是BCM2711.
查看cpu起始物理地址的c文件。Pi4 pi3 起始地址不同。bcm_host.h头文件须链接库
gcc addrBase.c -I /opt/vc/include -L /opt/vc/lib -lbcm_host
#include <stdio.h>
#include <bcm_host.h>
void main()
{
unsigned t;
t = bcm_host_get_peripheral_address();
printf("baseadd = %x\n",t);
}

pi4基地址参考博文:https://blog.csdn.net/chenchengwudi/article/details/121902861

这是驱动框架
#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 devise声明 #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"; //模块名 //led_open函数 static int pin4_open(struct inode *inode,struct file *file) { printk("pin4_open\n"); //内核的打印函数和printf类似 return 0; } //led_write函数 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, }; int __init 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"); //用代码在dev自动生成设备 pin4_class_dev =device_create(pin4_class, NULL, devno, NULL, module_name); //创建设备文件 return 0; } void __exit pin4_drv_exit(void) { device_destroy(pin4_class, devno); class_destroy(pin4_class); unregister_chrdev(major, module_name); //卸载驱动 } module_init(pin4_drv_init); //入口,内核加载该驱动(insmod)的时候,这个宏被使用 module_exit(pin4_drv_exit); MODULE_LICENSE("GPL v2");
ioremap函数原型:
void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
1. copy_from_user函数的目的是从用户空间拷贝数据到内核空间
这是pi4亲测有效驱动pin21的程序:
#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 devise声明 #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 = "pin21"; //模块名 volatile unsigned int *GPFSEL2 = NULL; volatile unsigned int *GPSET0 = NULL; volatile unsigned int *GPCLR0 = NULL; //led_open函数 static int pin4_open(struct inode *inode,struct file *file) { printk("pin4_open\n"); //内核的打印函数和printf类似 *GPFSEL2 &= ~(0x3 << 4); *GPFSEL2 |= (0x1 << 3); return 0; } //led_write函数 static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos) { int usrnum; printk("pin4_write\n"); copy_from_user(&usrnum,buf,count); if(usrnum == 1){ *GPSET0 |= (0x1 << 21); }else if(usrnum == 0){ *GPCLR0 |= (0x1 << 21); }else{ printk("ubdo\n"); } return 0; } static struct file_operations pin4_fops = { .owner = THIS_MODULE, .open = pin4_open, .write = pin4_write, }; int __init pin4_drv_init(void) //真实驱动入口 { int ret; printk("dp init\n"); devno = MKDEV(major, minor); //创建设备号 ret = register_chrdev(major, module_name, &pin4_fops); //注册驱动 告诉内核,把这个驱动加入到内核驱动的链表中 pin4_class=class_create(THIS_MODULE, "myfirstdemo"); //用代码在dev自动生成设备 pin4_class_dev =device_create(pin4_class, NULL, devno, NULL, module_name); //创建设备文件 GPFSEL2 = (volatile unsigned int*)ioremap(0xFE200008,4); GPSET0 = (volatile unsigned int*)ioremap(0xFE20001C,4); GPCLR0 = (volatile unsigned int*)ioremap(0xFE200028,4); printk("%p\n",GPFSEL2); return 0; } void __exit pin4_drv_exit(void) { iounmap(GPFSEL2); iounmap(GPSET0); iounmap(GPCLR0); device_destroy(pin4_class, devno); class_destroy(pin4_class); unregister_chrdev(major, module_name); //卸载驱动 } module_init(pin4_drv_init); //入口,内核加载该驱动(insmod)的时候,这个宏被使用 module_exit(pin4_drv_exit); MODULE_LICENSE("GPL v2");
driver.c cp 到linux/drivers/ach(或者drivers下其他文件夹,到哪个文件夹就改哪个文件夹下的Makefile)
vi Makefile -m表示模块化编译 驱动文件名.o(这是模仿他这里面的文件写的)

ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7l make modules(此命令要在源码起始目录进行,不然报错no rules。)
得到.ko文件到树莓派。scp .... pi@192.168.0.23:/home/pi

sudo insmod qudong2.ko 加载内核驱动
ls /dev/pin4 -l查看有无驱动:
sudo chmod 666 /dev/pin4给权限
运行test.c

dmesg看驱动打印在内核的信息
sudo rmmod +驱动名(不需要写ko)将驱动卸载。

浙公网安备 33010602011771号