1。历史的车轮总是向前,技术更替。在linus 同学发出那句 WFK 后内核进入了设备树时代(站在驱动工程师角度)。

前几天我已经被mach-imx 中的文件折磨的夜不能眠。我终于在一个清晨,喝完一杯咖啡后决定放弃蹩脚的传统device描述方式。

这里我先不讨论内核实现流程的源代码,简单描述下语法,和我的第一个test_platform_device

设备树文件 arch\arm\boot\dts 在修改dst文件后要make dtbs,

http://www.xuebuyuan.com/2128963.html 这篇文章可以恶补下设备书的基础

如图是一个完整节点

Documentation\devicetree\bindings 文件夹中有很多的样例可以供开发人员参考

2。 我的测试

我在我的设备树中添加如下代码(这里我把一个ds18b20做成platform设备,仅仅为了练习)

    my-ds18b20 {compatible = "ds18b20";gpios = <&gpio2 3 1>;   //有更改,以这里为准};

我ds18b20使用的是GPIO2_3 管脚。

这里的gpios = <&gpio2 3 0>; 在 imx6qdl.dtsi 文件中定义

然后执行 # make dtbs

生成的dtbs文件在dts文件同一目录,烧写 内核 和 DTBS 文件

编写ds18b20的driver 端(为了使结构简单明了,我屏蔽了其他代码,留下了骨架)

#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/ethtool.h>
#include <linux/dm9000.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/slab.h>#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>static int ds18b20_probe(struct platform_device *pdev)
{struct resource *addr_res = NULL;   /* resources found */printk("probe!!!!!!!!!! \n");addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (addr_res == NULL) printk("get_re error");return 0;
}static int ds18b20_drv_remove(struct platform_device *pdev)
{return 0;
}static const struct of_device_id ds18b20_of_matches[] = {{ .compatible = "my-ds18b20", },    //和dts文件中名字匹配{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ds18b20_of_matches);static struct platform_driver ds18b20_driver = {.driver = {.name    = "ds18b20",       //可以与dts文件中名字不同.owner   = THIS_MODULE,.of_match_table = of_match_ptr(ds18b20_of_matches),},.probe   = ds18b20_probe,.remove  = ds18b20_drv_remove,};module_platform_driver(ds18b20_driver);MODULE_LICENSE("GPL");

编译,拷贝,加载模块

/************************以下为完全测试*************************/


成功获取到温度,有个小bug就是第一获取时温度有问题

以下是完全代码

#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/interrupt.h>
#include <linux/skbuff.h>
#include <linux/spinlock.h>
#include <linux/crc32.h>
#include <linux/mii.h>
#include <linux/of.h>
#include <linux/of_gpio.h>#include <linux/of_net.h>
#include <linux/ethtool.h>
#include <linux/dm9000.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/irq.h>
#include <linux/slab.h>#include <asm/delay.h>
#include <asm/irq.h>
#include <asm/io.h>int ds18_gpio = -1;#define GPIO_DS18B20    ds18_gpio#define DS18B20_IO_UP   gpio_set_value(GPIO_DS18B20, 1)
#define DS18B20_IO_DOWN     gpio_set_value(GPIO_DS18B20, 0)#define DS18B20_OUT     gpio_direction_output(GPIO_DS18B20, 1)
#define DS18B20_IN      gpio_direction_input(GPIO_DS18B20)static void ds18_write(uint16_t data )
{uint8_t i, temp;DS18B20_OUT;for(i=0; i<8; i++){temp = data & 0x01;data = data >> 1;if(temp)         //写1{DS18B20_IO_DOWN;udelay(6); DS18B20_IO_UP;udelay(64); }           else{DS18B20_IO_DOWN;udelay(60);DS18B20_IO_UP;udelay(10);}}}static uint8_t ds18_read(void)   //读位
{uint8_t data;DS18B20_OUT;DS18B20_IO_DOWN;udelay(6);DS18B20_IO_UP;DS18B20_IN;udelay(9);if(gpio_get_value(GPIO_DS18B20)==1){data =1;}else{data =0;}udelay(45);return data;
}static uint8_t ds18_reads(void){uint8_t i = 0,temp = 0,mydata = 0;for(i=0;i<8;i++){temp = ds18_read();mydata = mydata | (temp<<i); }udelay(2);return mydata;}static uint8_t ds18_reset(void){DS18B20_OUT;DS18B20_IO_DOWN;udelay(300);udelay(300);DS18B20_IO_UP;DS18B20_IN;  // 600 usudelay(100);if (gpio_get_value(GPIO_DS18B20) == 0){printk("reset bingo \n");return 0;}printk("reset fail \n");return -1;}static long ds18b20_ctl(struct file * file,unsigned int cmd,unsigned long num)
{uint8_t tp_msb = 0,tp_lsb = 0;uint32_t data;if(cmd){    //readprintk("star read \n");if (ds18_reset() != 0)goto error1;ds18_write(0xCC);udelay(1);ds18_write(0x44);     //转换温度//mdelay(100);//ssleep(1);if (ds18_reset() != 0)goto error1;ds18_write(0xCC);udelay(1);ds18_write(0xBE);   //读取温度tp_lsb=  ds18_reads();udelay(1);tp_msb=  ds18_reads();data = tp_msb<<8;data = data | tp_lsb;if( data < 0 )      data = (~data+1) * 625;    elsedata = data * 625;  printk("tmp = %d \n", data);}return 0;error1:printk("read error \n");return -1;}struct file_operations ds18b20_fops = {.unlocked_ioctl= ds18b20_ctl,};struct miscdevice  ds18b20_misc={.minor = 200,.name = "misc_ds18b20",.fops = &ds18b20_fops,};static int ds18b20_probe(struct platform_device *pdev)
{struct resource *addr_res = NULL;   /* resources found */int re = -1;printk("probe!!!!!!!!!! \n");ds18_gpio = of_get_named_gpio(pdev->dev.of_node, "gpios", 0);printk("%d\n", ds18_gpio);re = gpio_request(ds18_gpio, "ds18b20");if (re != 0) return -1;if (ds18_gpio > 0){gpio_direction_output(ds18_gpio, 1);}re = ds18_reset();            //检测是否存在if (!re){printk("finded ds18b20 \n");misc_register(&ds18b20_misc);return 0;}else{gpio_free(GPIO_DS18B20);printk("no find ds18b20 \n");return -1;}return 0;
}static int ds18b20_drv_remove(struct platform_device *pdev)
{gpio_free(ds18_gpio);return 0;
}static const struct of_device_id ds18b20_of_matches[] = {{ .compatible = "ds18b20", },{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ds18b20_of_matches);static struct platform_driver ds18b20_driver = {.driver = {.name    = "ds18b20",.owner   = THIS_MODULE,.of_match_table = of_match_ptr(ds18b20_of_matches),},.probe   = ds18b20_probe,.remove  = ds18b20_drv_remove,};module_platform_driver(ds18b20_driver);MODULE_LICENSE("GPL");

3.X内核下设备树–platform设备驱动相关推荐

  1. i.MX6ULL终结者Linux设备树DTS设备树语法结构

    文章目录 1 dtsi头文件 2 设备节点信息 3 设备节点及label的命名 4 标准属性 5 根节点compatible属性 6 在设备节点中添加或修改内容 一般情况下,我们不会从头编写一个完整的 ...

  2. Linux利用platform_driver和设备树实现PWM驱动

    Linux利用platform_driver和设备树实现PWM驱动 字符设备PWM驱动 一.PWM驱动的硬件资源 1.PWM工作原理 2.PWM电路原理 3.PWM内部结构 二.具体代码 1.设备树 ...

  3. Linux驱动学习记录-6.设备树的LED驱动

    这一章使用第五章的设备树知识来写led驱动 1.修改设备树 在根节点下面添加子节点 alphaled {#address-cells = <1>;#size-cells = <1&g ...

  4. 【基于Linux系统设备树的SPI驱动编写方法】

    文章目录 前言 一.SPI驱动编写 1.修改设备树  a.设备树文件是什么?  b.设备树怎么改? 2.编写驱动 二.完善和测试 1.编译和应用程序  a.编译 && 拷贝到开发板命令 ...

  5. 第五十四讲 设备树实现RGB驱动

    第五十四讲 设备树实现RGB驱动 文章目录 第五十四讲 设备树实现RGB驱动 一.基础知识 1.GPIO Write Mode 2.硬件连接 3.重要寄存器(参考IMXULL用户手册) RGB_R R ...

  6. linux设备和驱动匹配的方法,Linux使用设备树的i2c驱动与设备匹配方式

    Linux使用设备树的i2c驱动与设备匹配有3种方式: of_driver_match_device acpi_driver_match_device i2c_match_id 源码: static ...

  7. linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...

    Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...

  8. 正点原子 linux led 驱动之 设备树 + platform

    设备树代码 leds {#address-cells = <1>;#size-cells = <1>;compatible = "atkalpha-gpioled&q ...

  9. 设备树的引进与体验_使用设备树时的驱动编程

    目录 1 驱动程序中的设备树机制 2 写代码 2.1 设备树文件 2.2 led_drv.c 2.3 ledtest.c 2.4 Makefile 3 代码优化改进 3.1 设备树文件 3.2 led ...

最新文章

  1. C++ 判断某个变量是某一种类型
  2. Chrome 74 Beta 发布,Windows 10 支持暗色主题
  3. vim进阶之202007命令记录
  4. 复用 TensorFlow 模型
  5. python svg转png_Python实现批量把SVG格式转成png、pdf格式的代码分
  6. js封装函数_JavaScript基础-如何封装函数来改变元素的位置
  7. html 元素的属性
  8. mysql 删除版本信息_linux 删除mysql
  9. python设计模式7-桥接模式
  10. 网络协议从入门到底层原理(11)网络爬虫、无线网络、HTTP缓存、即时通信、流媒体
  11. 拉普拉斯算子属于卷积方法吗_论文笔记 - 图卷积神经网络综述
  12. 复试c语言笔试题,考研计算机复试(C语言复试笔试题)(精华题选)
  13. galaxy s8 android pc,【三星GALAXYS8评测】DeX套件替代PC办公环境_三星 GALAXY S8_手机评测-中关村在线...
  14. 灰度思维,黑白决策(下)
  15. navicat的使用技巧
  16. 商业的本质 + 社交电商思考
  17. cad画直线长度与实际不符_cad测量直线长度(CAD测量长度与实际画线长度不符)...
  18. 关于memset函数和赋值0x3f,2021-5-5
  19. EFT4 生成实体类
  20. JAVA-TOMCAT环境变量的设置方法

热门文章

  1. iOS屏幕适配方案-Auto Layout
  2. 数据分析真的能驱动用户快速增长吗?
  3. Swift 学习- 02 -- 基础部分2
  4. Google Bigtable
  5. 网站后台admin修改故事
  6. 全文检索技术介绍与使用方法
  7. 艾伟_转载:.NET 4.0新特性-- Corrupted State Exceptions
  8. 银行家舍入VS四舍五入(下):.NET发现之旅(四)
  9. 在多线程中使用UDP
  10. 谁来理解外来工的孩子的心理健康?