platform与设备树
一,设备树下的platform
在设备树引入后,platform结构中的 platform_device 就可以用设备树去代替了。设备树下的 platform驱动相较于原始的 platform驱动,还需要把platform_device中描述的设备信息放到设备树中,同时修改paltform_drvier中对资源的读取方法即可。
二,在设备树中描述设备信息
使用 platform_device 时,我们可以通过name字段或者id_table来匹配或设备和驱动,当platform_device变成设备树时,则使用of_match_table方法来匹配。of_match_table对于设备树来说,要做的事,就是保证设备节点的compatible属性和platform_driver中的 compatible 保持一致。
alinxled
{compatible = "alinx-led";pinctrl-names = "default";pinctrl-0 = <&pinctrl_led_default>;alinxled-gpios = <&gpio0 0 0>;
};
of_match_table:
paltform_drvier 中的 compatible 属性设置,compatible 位于paltform_drvier->device_driver->of_device_id->compatible,保证和设备树中的 compatible 字段一致即可。of_device_id结构体在paltform_drvier结构体中的成员名为 of_match_table,of 匹配表。 初始化示例如下:
static const struct of_device_id led_of_match[] =
{/* compatible 字段和设备树中保持一致 */{ .compatible = "alinx-led" },{/* Sentinel */}
};
pinctrl 子系统和gpio 子系统下的设备树,写法都是一样的,直接用 就行了。叧要注意设备节点中的compatible属性,要和platform_driver 中的compatible保持一致。
amba
{……slcr@f8000000 {pinctrl@700 {pinctrl_led_default: led-default {mux {groups = "gpio0_0_grp";function = "gpio0";};conf {pins = "MIO0";io-standard = <1>;bias-disable;slew-rate = <0>;};};};};
};alinxled
{compatible = "alinx-led";pinctrl-names = "default";pinctrl-0 = <&pinctrl_led_default>;alinxled-gpios = <&gpio0 0 0>;
};
三,驱动程序
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of_gpio.h>
#include <linux/semaphore.h>
#include <linux/timer.h>
#include <linux/irq.h>
#include <linux/wait.h>
#include <linux/poll.h>
#include <linux/fs.h>
#include <linux/fcntl.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/io.h>/* 设备节点名称 */
#define DEVICE_NAME "gpio_leds"
/* 设备号个数 */
#define DEVID_COUNT 1
/* 驱动个数 */
#define DRIVE_COUNT 1
/* 主设备号 */
#define MAJOR_AX
/* 次设备号 */
#define MINOR_AX 0
/* LED点亮时输入的值 */
#define ALINX_LED_ON 1
/* LED熄灭时输入的值 */
#define ALINX_LED_OFF 0/* 把驱动代码中会用到的数据打包进设备结构体 */
struct alinx_char_dev{dev_t devid; //设备号struct cdev cdev; //字符设备struct class *class; //类struct device *device; //设备struct device_node *nd; //设备树的设备节点int ax_led_gpio; //gpio号
};
/* 声明设备结构体 */
static struct alinx_char_dev alinx_char = {.cdev = {.owner = THIS_MODULE,},
};/* open函数实现, 对应到Linux系统调用函数的open函数 */
static int gpio_leds_open(struct inode *inode_p, struct file *file_p)
{ /* 设置私有数据 */file_p->private_data = &alinx_char; return 0;
} /* write函数实现, 对应到Linux系统调用函数的write函数 */
static ssize_t gpio_leds_write(struct file *file_p, const char __user *buf, size_t len, loff_t *loff_t_p)
{ int retvalue;unsigned char databuf[1]; /* 获取私有数据 */struct alinx_char_dev *dev = file_p->private_data;/* 获取用户数据 */retvalue = copy_from_user(databuf, buf, len); if(retvalue < 0) {printk("alinx led write failed\r\n");return -EFAULT;} if(databuf[0] == ALINX_LED_ON){/* gpio_set_value方法设置GPIO的值, 使用!!对0或者1二值化 */gpio_set_value(dev->ax_led_gpio, !!1);}else if(databuf[0] == ALINX_LED_OFF){gpio_set_value(dev->ax_led_gpio, !!0);}else{printk("gpio_test para err\n");}return 0;
} /* release函数实现, 对应到Linux系统调用函数的close函数 */
static int gpio_leds_release(struct inode *inode_p, struct file *file_p)
{ return 0;
} /* file_operations结构体声明, 是上面open、write实现函数与系统调用函数对应的关键 */
static struct file_operations ax_char_fops = { .owner = THIS_MODULE, .open = gpio_leds_open, .write = gpio_leds_write, .release = gpio_leds_release,
};/* probe函数实现, 驱动和设备匹配时会被调用 */
static int gpio_leds_probe(struct platform_device *dev)
{ /* 用于接受返回值 */u32 ret = 0;/* 获取设备节点 */alinx_char.nd = of_find_node_by_path("/alinxled");if(alinx_char.nd == NULL) {printk("gpioled node nost find\r\n");return -EINVAL;}/* 获取节点中gpio标号 */alinx_char.ax_led_gpio = of_get_named_gpio(alinx_char.nd, "alinxled-gpios", 0);if(alinx_char.ax_led_gpio < 0) {printk("can not get alinxled-gpios\r\n");return -EINVAL;}/* 申请gpio标号对应的引脚 */ret = gpio_request(alinx_char.ax_led_gpio, "alinxled");if(ret != 0){printk("can not request gpio\r\n");}/* 把这个io设置为输出 */ret = gpio_direction_output(alinx_char.ax_led_gpio, 1);if(ret < 0){printk("can not set gpio\r\n");}/* 注册设备号 */alloc_chrdev_region(&alinx_char.devid, MINOR_AX, DEVID_COUNT, DEVICE_NAME);/* 初始化字符设备结构体 */cdev_init(&alinx_char.cdev, &ax_char_fops);/* 注册字符设备 */cdev_add(&alinx_char.cdev, alinx_char.devid, DRIVE_COUNT);/* 创建类 */alinx_char.class = class_create(THIS_MODULE, DEVICE_NAME);if(IS_ERR(alinx_char.class)) {return PTR_ERR(alinx_char.class);}/* 创建设备节点 */alinx_char.device = device_create(alinx_char.class, NULL, alinx_char.devid, NULL, DEVICE_NAME);if (IS_ERR(alinx_char.device)) {return PTR_ERR(alinx_char.device);}return 0;
}static int gpio_leds_remove(struct platform_device *dev)
{/* 注销字符设备 */cdev_del(&alinx_char.cdev);/* 注销设备号 */unregister_chrdev_region(alinx_char.devid, DEVID_COUNT);/* 删除设备节点 */device_destroy(alinx_char.class, alinx_char.devid);/* 删除类 */class_destroy(alinx_char.class);return 0;
}/* 初始化of_match_table */
static const struct of_device_id led_of_match[] = {/* compatible字段和设备树中保持一致 */{ .compatible = "alinx-led" },{/* Sentinel */}
};/* 声明并初始化platform驱动 */
static struct platform_driver led_driver = {.driver = {/* name字段需要保留 */.name = "alinx-led",/* 用of_match_table代替name匹配 */.of_match_table = led_of_match,},.probe = gpio_leds_probe,.remove = gpio_leds_remove,
};/* 驱动入口函数 */
static int __init gpio_led_drv_init(void)
{/* 在入口函数中调用platform_driver_register, 注册platform驱动 */return platform_driver_register(&led_driver);
}/* 驱动出口函数 */
static void __exit gpio_led_dev_exit(void)
{/* 在出口函数中调用platform_driver_register, 卸载platform驱动 */platform_driver_unregister(&led_driver);
}/* 标记加载、卸载函数 */
module_init(gpio_led_drv_init);
module_exit(gpio_led_dev_exit);/* 驱动描述信息 */
MODULE_AUTHOR("Alinx");
MODULE_ALIAS("gpio_led");
MODULE_DESCRIPTION("PLATFORM DT LED driver");
MODULE_VERSION("v1.0");
MODULE_LICENSE("GPL");
四,应用
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>int main(int argc, char **argv)
{int fd;char buf;/* 验证输入参数个数 */if(3 != argc){printf("none para\n");return -1;}/* 打开输入的设备文件, 获取文件句柄 */fd = open(argv[1], O_RDWR);if(fd < 0){/* 打开文件失败 */printf("Can't open file %s\r\n", argv[1]);return -1;}/* 判断输入参数, on就点亮led, off则熄灭led */if(!strcmp("on",argv[2])){printf("ps_led1 on\n");buf = 1;write(fd, &buf, 1);}else if(!strcmp("off",argv[2])){printf("ps_led1 off\n");buf = 0;write(fd, &buf, 1);}else{/* 输入参数错误 */printf("wrong para\n");return -2;}/* 操作结束后关闭文件 */close(fd);return 0;
}
platform与设备树相关推荐
- platform和设备树驱动蜂鸣器
目录 1.plat_fom介绍: 2.设备树介绍: 3.实现过程: 1.设备树:(以exynos-fs4412为例) 2.平台驱动: 3.驱动的启动函数: 4.驱动卸载 1.platform介绍: 从 ...
- 设备树下的platform 驱动编写
目录 设备树下的platform 驱动简介 硬件原理图分析 实验程序编写 修改设备树文件 platform 驱动程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 上一章我们详细的 ...
- 3.X内核下设备树–platform设备驱动
1.历史的车轮总是向前,技术更替.在linus 同学发出那句 WFK 后内核进入了设备树时代(站在驱动工程师角度). 前几天我已经被mach-imx 中的文件折磨的夜不能眠.我终于在一个清晨,喝完一杯 ...
- Linux 设备驱动开发 —— 设备树在platform设备驱动中的使用
关与设备树的概念,我们在Exynos4412 内核移植(六)-- 设备树解析 里面已经学习过,下面看一下设备树在设备驱动开发中起到的作用 Device Tree是一种描述硬件的数据结构,设备树源(De ...
- 驱动程序开发:无设备树和有设备树的platform驱动
1.Linux 驱动的分离与分层 对与对IO进行最简单的读写操作,无需考虑太多的怎么使它重用性强,而像I2C. SPI.LCD 等这些复杂外设的驱动,Linux 系统要考虑到驱动的可重用性,因此提 ...
- 设备树下的 platform 驱动开发框架
1. 设备树下的platform驱动开发 platform驱动框架分为总线.设备和驱动,其中总线是由Linux内核提供,在编写驱动时只要关注于设备和驱动的具体实现即可.Linux下的platform驱 ...
- Linux 设备树下的 platform 驱动实验基于正点原子IMX6ULL开发板
1 设备树下的 platform 驱动简介 platform 驱动框架分为总线.设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是 Linux 内核提供的,我们在编写驱动的时候只要关注于设备和 ...
- Linux 设备树下的 platform 驱动示例
1.简介 基于总线.设备和驱动这样的驱动框架,Linux 内核提出来 platform 这个虚拟总线,相应的也有 platform 设备和 platform 驱动. Linux 总线设备和驱动模式 2 ...
- 设备树下的platform驱动编写
文章目录 一.设备树下的platform驱动简介 1.在设备树中创建设备节点 2.编写 platform 驱动的时候要注意兼容属性 3.编写platform驱动 二.硬件原理图分析 三.实验程序编写 ...
最新文章
- 利用多个域名来存储网站资源
- 数据结构和算法之时间复杂度
- “睡服”面试官系列第五篇之proxy(建议收藏学习)
- 东软 软件工程1 软件危机 软件工程 软件生命周期
- 分类和目标检测的性能评价指标【转载】
- CactiEZ的使用
- urllib、requests库整理
- 派生类对基类成员的访问控制之公有继承
- Fabric环境配置
- Advertising on Instagram 如何在Instagram上发布广告 Lynda课程中文字幕
- 制作产品原型时要注意什么?
- 如何做公司网站设计,有哪些步骤?
- linux终端设备:pty设备初始化、创建过程
- QT 调用 百度翻译API 写的在线翻译程序
- sql 处理数据字段为空 如果为空转换成别的值
- 2019 南昌网络赛D FFT多个多项式相乘
- 遥感技术在城市监测中的作用有哪些?
- 计算机技术与软件(初级、中级、高级)考试(软考)是什么?软考的时间安排是什么时候?
- 01.软件项目管理与敏捷方法——敏捷项目生命周期详解笔记
- iOS适配iPhoneX/iphone11/iphone12 导航栏高度 (刘海屏幕)