日常阅读:linux 设备驱动开发详解

代码就是硬件的 时序逻辑命令逻辑

驱动工程师 完成了 硬件对 应用工程师的透明。 他们是面向 应用程序员编程 提供 机制,提供文件按操作函数指针

驱动:就是驱使硬件设备动作  硬件操作函数指针。

终极操作:就是 读写 相关 寄存器 , 时序 和 命令 完成对 硬件的操作 形成  函数指针。

操作系统下: 应用工程师 就 通过 标准接口(系统调用)去调用驱动工程师完成的机制。

无操作系统:驱动工程师 自行定义接口。 有操作系统 必须按照相应的框架 自行定义  驱动工程师 必须按照相应的标准 设计  面向应用工程师编程。

无操作系统的 设备驱动  单任务架构 可以完成比较好的 需求 。

一个无限循环 夹杂着 对 设备中断 的检测 或 对 设备的轮询 是对这种 系统中软件的典型架构。

// 应用开发工程师

int main()

{

       if(seriaInt == 1)

       {

           // 中断处理函数 

           // 清空中断标志位

       }

      int status = Check();

       switch( )

      {

          

      }

}            必定包含硬件驱动 。

裸板驱动 中 每一个模块 都会定义成一个 .c 和 .h 文件 

每个模块都会是下面这种格式:

serialinit  //初始化串口 

serialSend  //串口发送 

serialRecv //串口接受

serialIsr // 串口中断处理函数 

驱动程序的接口 被直接暴露给 应用工程师进行使用。

应用软件 -> 设备驱动 ->  硬件。

 

在存在操作系统的内核中,驱动变成了 内核 连接硬件的桥梁。

没有操作系统 完成多任务并发  是很困难的。

操作系统每个进程都享有独立的4G 地址空间。 操作系统管理了内存。

操作系统通过给驱动制造麻烦 给应用层访问提供了 便利   应用开发者不需要知道 硬件。通过系统调用就能访问硬件 来操作硬件的目的

硬件主要由 CPU 外设 内存组成 。

CPU 内部就集成了 外设控制器 SPI IIC USB 音视频编解码。

字符 块 网络。

字符设备就是必须按照串行必须访问的设备。 

linux 设备驱动工程师  有很高的要求 必须懂硬件 

1、懂 SRAM SDRAM Flash  磁盘的读写方式。URART IIC  USB  轮询中断 DMA的原理 

2、有非常好的C语言功底。

3、有一定的内核基础。 明白 内核 和 驱动的 交互的接口。 块设备  网络设备 flash 设备 串口设备等复杂网络设备。

4、多任务并发 和 复杂控制的基础  驱动中大量使用自旋锁  信号量  等待队列 等并发 同步机制。

经验值的获取并非一朝一夕的事。足够的恒心  和 毅力。

动手进行验证和测试永远是学习任何软件开发的最好的方法。 

LED 一般由 GPIO 通用可编程IO 进程控制 

GPIO 一般由2组 寄存器 进程控制   数据寄存器 和  控制寄存器

GPIO  通过控制 状态 寄存器 设置 输入 输出 两种方式。  输入  读数据数据寄存器 可知 高低 电平 

输出 读数据寄存器  可知  高低电平  输出。

 

硬件学习

通用处理器:

soc  芯片设计方法 硬件描述语言  soc 内电路实现的 

各种组件 类似堆积木的方法 组合在一起 。

 

存储器:

地址总线 和 数据总线。  DSP 数字信号处理。

ROM flash RAM  光/磁介质存储器 

EPROM 可擦除rom 

NOR 或非  SRAM 接口 不需要增加额外的控制电路  芯片内执行 NOR上可以跑代码

NAND  与非 CPU接口必须控制电路装欢 以块的方式访问 不支持 芯片内执行。

 

uart 通用串行总线。   // 总线通信协议 

RS232 RS485 RS422 

 

IIC 2线制通行接口。 SDA  SCL //  // 总线通信协议 

SPI 四线制 同步通信   // 总线通信协议 

 

USB // 总线通信协议 

芯片手册的阅读方法 是 定位相关信息 精准阅读 忽略其他信息。

linux 驱动编程 本质就是 linux 内核编程 

 

主控 SPI 作为主机  其他作为从机。

linux 内核 剖析 

1、arch 

包含对每种不同硬件平台的代码支持  内存管理  进程调度 中断支持等。

2、driver  硬件支持  重点 

3、ipc 进程间通讯的代码 

4、kernel 定时器 进程调度相关 

内核做到 driver 和  arch 架构 分离 driver 

不包含板级信息 kernel 的通用部分 定时器  fs 文件系统  ipc  net 等 与 驱动 和 arch 分离。

linux 内核 总纲:SCHED  MM  VFS  NET  IPC  5个通用子系统   arm  板级硬件支持 和  driver 

SCHED: 进程调度 task 结构体 管理 6种状态 优先级 算法 

MM: 内存管理  页管理 完成 虚拟地址 到 物理地址的 的映射  通过操作 虚拟地址 来操作物理地址。

虚拟文件系统:linux 虚拟文件系统 隐藏了硬件实现的各种细节。为 所有设备提供了 接口。 对各种文件提供

提供了一种抽象。

kernal_pthread_

 

网络接口:提供对 网络标准的存取 和  各种网络硬件的支持 

IPC: 进程间通信的 各种机制  Android 添加了 binder 机制

进程间 调度(SCHED) 第一步就是 把 代码 装载到 内存当中 (MM)

虚拟文件系统 通过网络接口 支持 NFS 网络文件系统  

通过内存管理 来 支持 RAMDISK  设备。

arm 处理器的工作模式:

1、usr

2、fiq 高速数据传输  或 通道处理 

3、irq 通用中断处理 

4、svc 系统保护模式 

5、数据中止访问模式 abt 

6、系统模式 sys 

linux驱动的开发者 必须牢牢的  掌握 linux 内核的 编译方法 和  构建 linux 内核 镜像

#make config 传统的配置界面 

#make menuconfig  基于文本菜单的 配置界面 

运行 make menuconfig 等时 配置工具 首先分析 与 体系结构对应的 

/arch/xxx/Kconfig 文件, 文件种包含一些和 体系结构相关的配置项 和 配置菜单以外  

source 语句 引入 一系列Kconifg 文件 而 这些 Kconfig 可能会引入 各种 kconfig文件.

1、在linux 内核种 增加程序 需要完成 以下3项 工作 

将编写的源代码 复制到 linux 内核源代码的相应目录中。

在目录的Kconfig 文件中增加关于新源代码 对应的项目编译选项 

在目录的makefile文件中 增加对新源代码的编译条目。 

Y N M 描述了 3态  1、可编入内核  2、 可编程 模块 3、不编入内核 

1、在 driver 子目录 添加 .c 文件  和 config 目录 添加 Kconfig 配置项 和 Makefile 中的编译选项。

 

Linux 内核引导过程

SOC 内嵌了 bootrom  bootloader  最著名的 bootloader 就是 Uboot 

http://git.denx.de/u-boot.git/

init busybox init  SysVinit systmd 等 他们职责类似  

把系统启动 看成  一颗进程树 。

Linux 缩进 采用 tab  缩进。

linux 内核编程 是linux driver驱动编程的 先决条件。

 一个linux 内核模块 主要由 如下几个部分的组成 

模块加载  

模块卸载 

模块许可声明   

模块可选参数  可选

模块导出符号  可选

模块作者  可选 

EXPORT_SYMBOL( 符号名);

EXPORT_SYMBOL_GPL(符号名);

Linux 下 一切皆文件  意思就是 硬件就是文件。

 

filp  <-> inode 两个重要的结构体 对 驱动文件进行管理 。

filp  打开文件时创建 并传递 给在文件上操作的 任何函数  文件关闭后 释放这个结构体 。

f_path  fpath.dentry  f_inode  file_operations  void* private_data 

大多只想 被设备自定义 用于描述设备的结构体。

 

VFS 中  inode  包含文件访问的权限 属主 组 大小 生成文件 访问时间  最后修改时间 

linux 管理文件系统的最小基本 单位   文件系统连接到 任务子目录 文件的 桥梁 

struct inode {

i_mode  uid  gid  rdev  i_size  ic_dev / ib_cdev / i_pipe;.

// rdev  高 12位  rdev 低20位 

 }

 

devfs 

register_chrdev() 传递0可以获取可用的主设备号

sys fs 把连接在系统的设备 和 总线 组织成 一个分级的文件。

block 所有块设备  

bus 所有总线类型 

dev 所有

只需按照 填鸭式 地 填充 xxx. driver 的各种回调函数 

bus_type  device_driver  device  3个结构体。

设备 和 驱动的注册时 分开的。

设备和驱动各种 涌向 内核 ,它会去寻找自己的另外一半。

match 成员函数   设备和驱动就是 红尘中 漂浮的男女 

bus_type match 就是牵线的月老。 识别 什么驱动 和 什么设备配对。

一旦配对 成功  driver probe 就被执行  总线  驱动 设备  最终落实为 sysfs 中的1个目录。

struct bus_ type{

      int match (struct dev,  strucet drv );

}

struct device_driver {

     struc bus_type;

    int (probe)(dev);

    int remove(dev); 

}

struct device  {

  bus_type;

  devier_drv;

}

 

设备树 驱动需要在.dts 中描述的设备节点进行匹配 

从而使驱动的 probe() 函数执行  新的驱动 设备的

设备的匹配 变成了设备树节点的 兼容属性 和 设备驱动中 

的 OF 匹配表的匹配。

platform_data 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦幽风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值