Linux静态驱动编写流程——aio-rk3399j开发板

一、设备树

  修改linux/kernel/arch/arm64/boot/dts/rockchip文件夹下rk3399.dtsi文件,在根节点下添加你的设备。注意compatble属性的值,用于和驱动文件中的compatible匹配。

gpio_cst{
	status = "okay";
	compatible = "gpio_cst";
	firefly-gpio = <&gpio_0 12 GPIO_ACTIVE_HIGH>;  /* GPIO_B4 */
}

二、驱动

1.添加驱动文件

  在drivers文件夹下添加自己的驱动文件夹gpio_cst,并修改本目录下的Makefile文件、Kconfig文件和上级目录中的Makefile文件。

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>		
#include <asm/io.h>
#include <linux/platform_device.h>
#include <linux/version.h>
#include <linux/delay.h> 
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>

#define DEV_NAME	"gpio"		

struct gpiopin_dev
{
	struct 	cdev 	dev;
	dev_t			dev_id;
	struct class 	*dev_class;
	struct device_node *nd;
	int 			gpio;
};

struct gpiopin_dev  gpio;


static int gpio_open(struct inode *inode, struct file *pfile) 
{ 
	int ret = 0;

	pfile->private_data = &gpio;
	
	return ret;
} 

static ssize_t gpio_read(struct file *pfile, char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpiopin_dev *p;
	char level = 0;
	
	p = pfile->private_data;

	level = gpio_get_value(p->gpio);
	ret = copy_to_user(buf, &level, sizeof(level));
	
    return ret; 
} 


static ssize_t gpio_write(struct file *pfile, const char __user *buf, size_t size, loff_t *offset) 
{ 
	int ret = 0;
	struct gpiopin_dev *p;
	char level = 0;
	
	p = pfile->private_data;

	ret = copy_from_user(&level, buf, size);
	gpio_set_value(p->gpio, level);
	
    return ret; 
} 

static int gpio_release(struct inode * inode , struct file * pfile) 
{ 
     return 0; 
} 

static struct file_operations gpio_fops = { 
     .owner = THIS_MODULE, 
     .open  = gpio_open,
     .read  = gpio_read,
     .write = gpio_write, 
     .release = gpio_release,
}; 
   
static int gpio_probe(struct platform_device *pdev)  
{     
    struct device *dev; 
	
	int ret = -1;
	dev_t	id = 0;
	
	gpio.nd = of_find_node_by_path("/gpio_cst");
	gpio.nd =  pdev->dev.of_node;
	if(gpio.nd == NULL)
	{
		printk("***************gpio_cst get node failed*****************\n");
		return -1;
	}
	printk("*****************gpio_cst get node successfully******************\n");
	gpio.gpio = of_get_named_gpio(gpio.nd, "firefly-gpio", 0);
	if(gpio.gpio < 0)
	{
		printk("*****************gpio_cst get gpio failed**************\n");
		return -1;
	}
	printk("*****************gpio_cst get gpio successfully*****************\n");
	ret = gpio_request(gpio.gpio, "firefly-gpio");		/* 申请GPIO */
	if(ret < 0)
	{
		printk("*************gpio_cst gpio request failed*************\n");
		return ret;
	}
	printk("************gpio_cst gpio request successfully**************\n");
	ret = gpio_direction_output(gpio.gpio, 0);	/* output,low default */
	if(ret<0)
	{
		printk("*******************gpio_cst gpio set failed*************\n");
		gpio_free(gpio.gpio);
		return ret;
	}
	printk("*************gpio_cst gpio set successfully********************\n");
	ret = alloc_chrdev_region(&id, 0, 1, DEV_NAME); 
	if (ret)
	{
		printk("*************gpio_cst alloc dev-id failed.******************\n");
		return ret;
	}
	printk("***************gpio_cst alloc dev-id successfully.*************\n");
	gpio.dev_id = id; 
   	cdev_init(&gpio.dev, &gpio_fops);
	ret = cdev_add(&gpio.dev, gpio.dev_id, 1);
	if (ret)
	{
	unregister_chrdev_region(gpio.dev_id, 1);
	printk("***************gpio_cst cdev add failed.*************\n");
	return ret;
	}
	
	gpio.dev_class = class_create(THIS_MODULE, "gpio_class");
	if (IS_ERR(gpio.dev_class)) 
	{
		printk("***************gpio_cst class_create failed.******************\n");
		cdev_del(&gpio.dev);
		ret = -EIO;
		return ret;
	}
	printk("***************gpio_cst class_create successfully.***************\n");
	dev = device_create(gpio.dev_class, NULL, gpio.dev_id, NULL, DEV_NAME);
	if (IS_ERR(dev))   
	{   
         return PTR_ERR(dev);    
	}
	
   	return 0; 
} 
  
static int gpio_remove(struct platform_device *pdev) 
{ 
	gpio_free(gpio.gpio);
	device_destroy(gpio.dev_class, gpio.dev_id);
	class_destroy(gpio.dev_class);
	cdev_del(&gpio.dev);
	unregister_chrdev_region(gpio.dev_id, 1);

	return 0; 
} 
  
  
static struct of_device_id of_gpio_ids[] = {
   {.compatible = "gpio_cst"},
   { }   
 };
 
static struct platform_driver gpio_driver = { 
	.driver   = { 
	.owner    = THIS_MODULE, 
	.name     = DEV_NAME, 
	.of_match_table = of_match_ptr(of_gpio_ids),
	}, 
	.probe 	  = gpio_probe, 
	.remove   = gpio_remove, 
};

module_platform_driver(gpio_driver);

MODULE_LICENSE("GPL"); 

2.生成.config文件

  kernel目录下make menuconfig
  选择Device Drivers,再找到自己写的驱动名称,按空格键使得名称前面为[*],Save产生.config文件,再一路退出。

3.编译内核

  ./build.sh kernel (实习的环境用这条命令,自己搞的话在kernel同级目录下make。编译全部的话,用./build.sh all)

4.烧写系统

  sudo ./rkflash.sh boot
  别忘了开发板要进入maskroom模式,以及双usb头线连接。
  查看设备树或驱动:
    ls /sys/firmware/devicetree/base
    ls /proc/device-tree
    ls /proc/devices
    ls /sys/bus/platform/drivers
    ls /sys/bus/platform/devices

5.编写测试程序或使用官方测试方法

   1.编写测试程序时 ./rkflash.sh boot别忘了开发板要进入maskroom模式,以及双usb头线连接
   2.官方测试方法:sudo cat /sys/kernel/debug/gpio

6.编译测试程序

   交叉编译生成可执行文件。

7.测试

   运行可执行文件,查看结果。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值