个人笔记 android 嵌入式开发 驱动层 编写

123 阅读1分钟

驱动层 主要修改的新增3个文件夹 修改1处地方

Krenel:驱动层文件夹
Krenel/arch/arm64/boot/dts/rockchip/xxxxxx.DTSI :设备树文件夹  这里选中的是 rk3399-android.dtsi

dtsi 类似json 这种文本 是解析给  驱动层看的  可以写 也可以不写  写的话 以后维护舒服  不写也能继续下去

DTSi文件:找个你看的顺眼的文件夹内添加

PWm_demo:PWm_demo{
	status = "okay";
	compatible = "Pwm_demo_data";
	pwm_id = <1>;
	Min_preiod = <0>; //最小  周期
	Max_preiod = <10000>;//最大周期
	duty_Ns  = <5000>;//激活时常
 };

   

kerenel下 新建一个文件夹Pai_driver 内 然后新建三个文件

   Makefile   Pwm_driver.c  Kconfig

Makefile:

    KERNELDIR := /home/share/samba/RK3399-Android8.1/kernel/
    PWD := $(shell pwd)
    all:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    clean:
        $(MAKE) -C $(KERNELDIR) M=$(PWD) clean
    obj-m := Pai_pwm_driver.o

这段代码劝你手打 复制容易出错

Kconfig

 config HELLO
 tristate "Hello Android Driver"
 default n
 help
 This is the hello android driver.
 

Pwm_dirver.c

#include "../2/config.h"
#include <linux/pwm.h>

#define DEV_NAME     "Pwm_demo"
#define DEV_COUNT    1

/*设备结构体*/
struct embededplatform_dev1{
dev_t devid;                /* 设备号 */
struct embededplatform_dev dev;
struct  pwm_device *pwm_device;  
int dev_stats; /* 设备状态,0 ,设备未使用;>0, 设备已经被使用 */
int Pwm_id;
unsigned int Max_Duty;
unsigned int Min_Duty;

};

struct Pai_pwm_driver
{
int Pwm_id;
unsigned int Max;
unsigned int Duty;
};




//设备结构体实例
struct embededplatform_dev1 embededplatform_dev_er;

static int embeded_platform_open (struct inode *node, struct file *filp){
    printk("embeded_platform_open\n");
    return 0;
}

static ssize_t embeded_platform_write (struct file *filp, const char __user *buf, size_t count, loff_t *off)
{	

 /* unsigned int  Key =  0; */
 struct  Pai_pwm_driver  Key;
 if (copy_to_user(&Key,buf,sizeof(struct Pai_pwm_driver)))
 {
     switch (Key.Duty)
     {
     case 0:
            pwm_disable(embededplatform_dev_er.pwm_device);
        break;
     
     default:
          pwm_config(embededplatform_dev_er.pwm_device,Key.Duty,Key.Max);
          pwm_enable(embededplatform_dev_er.pwm_device);
        break;
     }
 }
 



    return 0;
}

ssize_t embeded_platform_read(struct file *filp, char __user *ubuf, size_t count, loff_t *ppos)
{

    return 0;
}

static int embeded_platform_release (struct inode *node, struct file *filp){
printk("embeded_platform_release \n");
return 0;
}

static struct file_operations embeded_file_ops = {
 .owner = THIS_MODULE,
 .open  = embeded_platform_open,
 .write = embeded_platform_write,
 .read  = embeded_platform_read,
 .release = embeded_platform_release,
};

static int Init_Class(void)
{

int ret = 0;
/* 申请设备号 */
ret = alloc_chrdev_region(&embededplatform_dev_er.devid, 0, DEV_COUNT, DEV_NAME);
if (ret < 0) {
    printk("embededplatform_dev_er chrdev_region err!\r\n");
    goto fail_devid;
}

/* 注册字符设备 */
cdev_init(&embededplatform_dev_er.dev.cdev, &embeded_file_ops);
ret = cdev_add(&embededplatform_dev_er.dev.cdev, embededplatform_dev_er.devid, DEV_COUNT);
if (ret < 0) {
    goto fail_cdev;
}

/* 自动创建设备节点 */
embededplatform_dev_er.dev.class = class_create(embeded_file_ops.owner, DEV_NAME);
if (IS_ERR(embededplatform_dev_er.dev.class)) {
    ret = PTR_ERR(embededplatform_dev_er.dev.class);
    goto fail_class;
}

embededplatform_dev_er.dev.device = device_create(embededplatform_dev_er.dev.class, NULL, 
embededplatform_dev_er.devid, NULL, DEV_NAME);
if (IS_ERR(embededplatform_dev_er.dev.device)) {
    ret = PTR_ERR(embededplatform_dev_er.dev.device);
    goto fail_device;
}

return 1;
fail_device:
    class_destroy(embededplatform_dev_er.dev.class);
fail_class:
    cdev_del(&embededplatform_dev_er.dev.cdev);
fail_cdev:
    unregister_chrdev_region(embededplatform_dev_er.devid, DEV_COUNT);
fail_devid:
    return ret;

}

static int Init_Pwm(struct device_node *led_node)
{
    int ret = 0;
    //查找 pwm_id 子字节的u32参数  如果没写dtsi 这一大段可以不写
ret =  of_property_read_u32(led_node, "pwm_id", &embededplatform_dev_er.Pwm_id);
if (ret < 0)
{
     printk("---pwm_id ERR  %d!\n",embededplatform_dev_er.Pwm_id);
     goto fail_GPIO;
    
}
ret =  of_property_read_u32(led_node, "Min_preiod", &embededplatform_dev_er.Min_Duty);
if (ret < 0)
{
     printk("---pwm_id ERR  %d!\n",embededplatform_dev_er.Min_Duty);
     goto fail_GPIO;
    
}
ret =  of_property_read_u32(led_node, "Max_preiod", &embededplatform_dev_er.Max_Duty);
if (ret < 0)
{
     printk("---pwm_id ERR  %d!\n",embededplatform_dev_er.Max_Duty);
     goto fail_GPIO;
    
}
printk("---Max_preiod   %d!\n",embededplatform_dev_er.Max_Duty);
printk("---Min_preiod   %d!\n",embededplatform_dev_er.Min_Duty);
printk(" ---pwm_id :    %d !\n", embededplatform_dev_er.Pwm_id);
/* 申请 pwm使用   如果没有写dtsi  下面就需要自己写入实数了*/
embededplatform_dev_er.pwm_device =  pwm_request(embededplatform_dev_er.Pwm_id,"Pwm_demo");
if(IS_ERR(embededplatform_dev_er.pwm_device)){
	
	printk("pwm_request err %ld\n",PTR_ERR(embededplatform_dev_er.pwm_device));
    goto fail_GPIO;
}
/* 配置pwm */
ret = pwm_config(embededplatform_dev_er.pwm_device,embededplatform_dev_er.Min_Duty,embededplatform_dev_er.Max_Duty);
if (ret < 0)
{
    printk("pwm_config err %ld\n",PTR_ERR(embededplatform_dev_er.pwm_device));
   goto Del_Pwm;
}
/* 停止使能pwm */
pwm_disable(embededplatform_dev_er.pwm_device);
return 1;
Del_Pwm:
pwm_free(embededplatform_dev_er.pwm_device);
fail_GPIO:       
class_destroy(embededplatform_dev_er.dev.class);
cdev_del(&embededplatform_dev_er.dev.cdev);
unregister_chrdev_region(embededplatform_dev_er.devid, DEV_COUNT);

return ret;
}
static int embeded_platform_probe(struct platform_device *pdev)
{
int ret = 0;
struct device_node *led_node = pdev->dev.of_node;
printk("Init  ALL  Config\n");
if (Init_Class() < 0)goto fail_Class;     //创建字符串设备
if (Init_Pwm(led_node) < 0)goto fail_Class;    // 初始化pwm io口设置

printk("--------------ALL  Ok----------\n");
return 0;

fail_Class:
return ret;
}

static int embeded_platform_remove(struct platform_device *pdev)
{
printk("embeded_platform_exit\r\n");
/* 删除字符设备 */
cdev_del(&embededplatform_dev_er.dev.cdev);
/* 释放字符设号 */
unregister_chrdev_region(embededplatform_dev_er.devid, DEV_COUNT);
/* 摧毁设备 */
device_destroy(embededplatform_dev_er.dev.class, embededplatform_dev_er.devid);
/* 摧毁类 */
class_destroy(embededplatform_dev_er.dev.class);
/* 销毁 pwm */
pwm_free(embededplatform_dev_er.pwm_device);

return 0;
}

static struct of_device_id embeded_match_table[] = {
{ .compatible = "Pwm_demo_data"},
{},
};

static struct platform_driver embeded_platform_driver = {
.driver = {
    .name = DEV_NAME,
    .owner = THIS_MODULE,
    .of_match_table = embeded_match_table,
},
.remove     = embeded_platform_remove,
.probe      = embeded_platform_probe,

};

static int embeded_platformdriver_init(void)
{
return platform_driver_register(&embeded_platform_driver);
}


static void embeded_platformdriver_exit(void)
{
platform_driver_unregister(&embeded_platform_driver);
}

module_init(embeded_platformdriver_init);
module_exit(embeded_platformdriver_exit);

MODULE_AUTHOR("embeded");
MODULE_DESCRIPTION("embeded platform driver");
MODULE_LICENSE("GPL");