IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux 驱动开发-杂烩 -> 正文阅读

[系统运维]linux 驱动开发-杂烩

里面图片上传不了,完整的见 上传的附件

Linux drv 一篇杂烩

一 ?平台设备总线:

  1. 平台设备总线是一条虚拟总线,就是把一个设备驱动依照实际需要可以一分为二,分为platform_drv 和platform_dev 。并且可以继续一分为二。

drv通用代码 dev 硬件资源。

比如i2c-bus:

2.

平台设备驱动和直接采用字符设备file_operaiton的写法的区别:

  1. 直接 注册写file_operaiton ?操作硬件的哪个引脚 是直接写死的。
  2. Hello_driver 操作哪个引脚是由hello_dev 传入的参数决定。

分层dev和drv 引脚资源获取

----- hello_dev

static struct resource hello_dev_res[] = {

{

.start = 2, /* pin2 */

.end ??= 2, /* pin2 */

.flags = IORESOURCE_TYPE_BITS,

},

};

static struct platform_device hello_dev = {

????????.name = "100ask_hello",

????????.dev = {

????????????????.release = hello_dev_release,

?????????},

????????.num_resources = 1,

????????.resource ?????= hello_dev_res,

};

----hello_drv

static int hello_probe(struct platform_device *pdev)

{

printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);

/* 1. 获得资源 */

pin = pdev->resource[0].start;

/* 2. 注册file_operatoins */

major = register_chrdev(0, "hello_drv", &hello_fops);

????return 0;

}

static struct platform_driver hello_driver = {

????.probe ?????= hello_probe,

????.remove ????= hello_remove,

????.driver ????= {

????????.name ??= "100ask_hello",

????},

};

  1. ?Plaform_dev 和plaform_drv 的匹配方法(常用 总共5种)
  1. 比较name

Return (strcmp(pdev->name,drv->name)==0)

  1. 比较id_idtable

If(pdev->id_table)

return platform_match_id(pdev->id_table,pdev)!=NULL;

  1. 设备找驱动和驱动找设备

当一个设备接入进来,设备会放入bus的设备链表,然后与bus的drv链表一一比较,直到找到匹配的驱动为止。

当一个驱动接入进来,驱动会放入bus的drv链表,然后与bus的drv会一一比较bus的dev链表,是否能枚举该设备。

一个dev只能由一个drv来匹配,但是一个drv可以支持多个设备。比如一个usb鼠标驱动可以支持多个鼠标,但是一个鼠标只需要一个驱动支持。

?????????????????????

??????????????????.probe

??????????????????????????比较

?????????????????????不匹配,比较下一个

????????????????????????????????????????????????????????????????????????

新接入dev 匹配过程。

  1. Linux驱动 = 框架 + ?硬件操作

  1. dev_set_drvdata

static void dev_set_drvdata(struct device *dev,void *data)

{

??dev->driver_data=data;

}

  1. ?平台设备驱动调试

modprobe led_device //加载设备模块

modprobe led_driver //加载驱动模块

驱动加载成功后,

ls ?/sys/bus/platform/drivers ???查看是否生成平台设备驱动

ls ?/sys/bus/platform/devices ???查看总线下的设备

匹配成功就会调用 driver 的 .probe 函数.

查看设备相关情况

Ls /dev/

Ls /dev/100as*_led

cd /sys/

Ls

输出:blocks bus class dev devices firemaware fs hypervisor kernel module ?power

根据不同类型的设备 可以进一步进入到 bus ?class dev ?devices 等模块进一步查看设备驱动信息。

Insmod -f led_driver.ko ????-f 表示强制加载。

  1. 问:在设备树增加节点后,在 /sys/xxx 什么目录下查看这个节点?创建设备节点后,目录又在哪?
  1. /sys/firmware/devicetree/base
  2. 某个节点 -> platform_device -> /sys/bus/paltform/devices
  3. 某个节点-> i2c_client ?-> /sys/bus/i2c/devices
  4. 某个节点-> spi_dev ?-> /sys/bus/spi/devices

  1. 为什么要引入设备树?

随着接入的硬件设备种类越来越多,,linus本人也越来越难以忍受。各大厂商不停地往linux内核里面注入,导致linux系统变得越来越臃肿,并且有很多可能会重复和冗余而不是精简高效的。

用hardcode方式将HW 配置信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。

缺点:?1. ?代码巨大

  1. ????????修改麻烦

采用dts ?:

?配置文件和内核分开。 易于维护和修改。

查看设备树:

  1. 查看 .dtb 文件 可以通过find 命令查找
  2. Ls ?/sys/firmware/devicetree/base

10 单片机和linux 分层区别

图2为补充图1

在文件中搜索 grep gpio-leds?* -nr/nwr

  1. ?Lcd 接线框图

11 Dts 文件常规知识:

Gpiob:gpio@5003000{

Gpio-controller;

Gpio-cells=<2> ?//cells 表示 用几个int 类型来描述。

}

Led0:cpu{

Label=”cpu”;

Gpios=<&gpio5 3 GPIO_ACTIVE_LOW>; ?如上所述 这里的gpio 采用了两个int来描述的。

...

}

@I2C3{

Clock-frequency=<100000>;

Compatible=sil,sii9022;

Reg=<0x40>;

Reset-gpios=<&gpiob_10_GPIO_ACTIVE_LOW> //GPIO_ACTIVE_LOW表示低电平有效。

}

对于pinctrl 信息,厂家都有提供gui工具生成。

Grep sai2?* -nwr | grep imx6ull

12 对于声卡 有的接口是SAI接口 既有SAI 又有I2C接口

在 内核搜索 grep wm8960?* -nr 查看别人写的dts。

Cd ?linux-4.9.88/arch/arm/arm/boot/dts grep grep wm8960?* -nr

grep fsl,imx6ul-evk-wm8960* -nr

驱动只提供能力,不提供策略。策略由APP决定。

13 ?App读取按键的4种方式:

举例:妈妈照看小孩

  1. 查询方式 ?????简单,累。

(2)休眠-唤醒方式 ?妈妈陪小孩一起睡,小孩醒了会吵醒,但是妈妈干不了活了。

(3)poll方式 ???定个闹钟。妈妈要么是被吵醒要么是被闹钟唤醒。

(4)异步通知方式 ?妈妈小孩互不干扰。

14 中断

Dtb反汇编生成.dts文件

dtc -I dtb -0 dts

中断分级:

14.1

Static int gpio_key_probe(参数...)

{

Irq=platform_get_resource(pdev,IORESOURCE_IRQ,0);

Resquest_irq(...);

}

14.2 获取中断资源。

If(!pdev->dev.of_node) ?// 没有采用了dts

{

??Res=platform_get_resource(pdev,IORESOURCE_IRQ,0);

Irq=res->start

}

Else

{

??Irq=of_irq_get(pdev->dev.of_node,0); ?//从dts获取资源。

}

Err=Resquest_irq(...);

Poll_wait 不休眠,只是在队列中放入当前进程。

设备树:

Sr501

{

??.compatible = 100as*,sr501?;一般是公司名、设备名这样命名。

}

Dht11温湿度传感器:

Static int dht11_probe()

{

??Dht11_data_pin=gpiod_get(&pdev->dev,NULL,GPIOD_OUT_LOW);

}

在采用dth11 捕获中断时,中断里面只做数据记录,在中断底半步或者工作队列中做计算。

Copytouser的应用 可以拷贝多个字节。

获取ns

Ktime_get_boot_ns(); 校准。

Ktime_get_bootime_ns(); 芯片不一样可能版本就不一样。

Irq=gpiod_to_irq(hs00038_echo);

背景说明:
??在Linux设备树(linux 3.x版本引入)中, 设备的中断号不再在"irq.h"中硬编码定义, 而是在需要时自己手动去申请获得对应的硬件中断的软件中断号.( 前提是GPIO的相关模块已经被编入内核 )

通过GPIO号得到对应的软件中断号, 该中断号是request_irq()函数的第一个参数.

I2C 框架

I2cdetect -y 0

address-cells 和 #size-cells 描述子节点应如何编写 reg 属性值,一般 reg 属性是某个外设的寄存器地址范围信息。

Aips1:aips-bus@2000000{

.compatible=fsl,aips-bus;

#address-cell =<1>;

#size-cell=<1>;

Reg=<0x02000000 0x100000> ; reg区域

}

  • #address-cells,用来描述子节点"reg"属性的地址表中用来描述首地址的cell的数量
  • #size-cells,用来描述子节点"reg"属性的地址表中用来描述地址长度的cell的数量

有了这两个属性,子节点中的"reg"就可以描述一块连续的地址区域。

Input_report_rel();

Input_report_rel();

Input_report_rel();

Input_sync(); 表示这一轮上报已经结束。上报同步。

Hexdump ??/dev/input/event0

Lcd 原理

Lcd 有屏幕自带 缓冲的 有不带的。

怎么写framebuffer驱动?

答: 分配fb_info ->设置 fb_info fb_var ??fb_fix ?->注册fb_info ->硬件操作。

Ls /dev/fb*

Fb-test /dev/fb2

Oled用的是有的用的是SPI接口。也有i2c接口

LCD接口

RGB:(DPI)RGB565/RGB666/RGB888

MCU:I8080/M6800(8/9/16/18/24bit)

SPI:3line/4line

MIPI-DSI:Data_N/P、Clock_P/N

总结写驱动的三种方法:

  1. 资源和驱动写在同一个文件里。File_operation
  2. ?资源用platform_device指定,驱动在platform_driver实现。
  3. ?资源用dts指定。

工作队列:

中断的下半部采用tasklet,它们都是在中断上下文中执行,它们无法休眠。当要处理更复杂的事情时,往往更耗时,这些更耗时的操作放在定时器或者下半部中,会导致系统很卡;并且循环等待某件事情完成也很浪费cpu资源。

如果使用线程来处理耗时的工作,那就可以解决系统卡顿的问题。因为线程可以休眠。

在内核中我们并不需要自己去创建线程,可以使用“工作队列”,内核初始化工作队列,就会为他创建了内核线程。以后我们使用“工作队列”,只需要把“工作”放入“工作队列中”,对应的内核线程就会取出“工作”,执行里面的函数。

工作队列的使用场景:耗时,甚至可能需要休眠,那么可以使用工作队列。

缺点:多个工作是在某个内核线程中依序执行的,前面函数执行很慢,会影响后面的函数。在多cpu下,一个工作队列可以有多个内核线程,可以在一定程度上缓解这个问题。

设备树常用 OF 操作函数

要使用 of 函数,必须先配置内核 CONFIG_OF = y,其实内核默认已经使能,所以内核移植时不需要配置这个选项。

疑问:

ls ?/sys/bus/platform/drivers

ls ?/sys/bus/platform/devices

Ls ?/sys/devices/platform/

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-05-19 12:06:11  更:2022-05-19 12:07:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:54:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码