zoukankan      html  css  js  c++  java
  • linux:驱动开发的预备知识

    前言:linux是gnu系统的内核;ubuntu系统是一个linux内核的桌面系统;再详细我也不会了,就这样吧,先定个义;

    1 对于单片机而言,代码可以随便访问单片机的各种外设和资源,效率极高;

      但是对于Linux系统而言,如果所有的程序都可以访问和更改寄存器和CPU的各种参数,系统就会不稳定;所以linux给自己分成了两个空间:内核空间和用户空间

      1.1 用户空间:用户空间的代码可以通过一些库函数与内核空间进行数据交互;

      1.2 内核空间:内核空间的代码可以访问和修改各种外设及CPU;linux驱动的代码运行在内核空间中;

      1.3 空间的交互

       常用的方式有API函数,系统调用C库的open函数等;(称之为软中断或陷入)

       C库的系统调用函数在arch/arm64/include/asm/unistd32.h里对两个空间的函数使用软中断进行了映射;

        1.3.1 copy_from_user(kernelBuff, userBuff, sizeof(len));  将用户空间userbuff的数据拷贝len字节,到内核空间;

        1.3.2copy_to_user(userBuff, kernelBuff, sizeof(len));  将内核kernelbuff地址的数据拷贝len字节,到用户空间;

          buff的位置都是当前意思的(*to,*from,len);linux函数大部分成功返回0,失败返回失败的字节数或负数;

    2 驱动开发

      linux觉得直接操作寄存器太繁琐,效率低下;所以linux下的驱动开发使用驱动框架开发,

      只要把驱动的硬件信息告诉框架,然后就可以使用框架提供的函数与硬件通信,省去了操作寄存器;

      单片机驱动也具有模块开发的特点,只是单片机系统较小,并没有像linux那样分工明确,模块与模块之间严格分层,逻辑清晰;

      2.1 驱动类型

        linux下的驱动类型主要分为三类驱动设备进行开发

        2.1.1 字符设备:为顺序数据流传递类型的设备,目的是为了通信;比如uart、usb、键盘、显示器等;

        2.1.2 块设备:以单位块大小来传递数据的设备,目的是为了存储数据;比如硬盘、u盘、flash等;

        2.1.3 网络设备:收发数据帧的设备,比如蓝牙、wifi、ethenet等;

      2.2 驱动设备的分层编写

        2.2.1 硬件层 是设备的硬件信息device:通过设备树从../mach-XXX下读取;设备的硬件信息可以保存到设备树.dts内;

           接口层 是统一的API接口bus:内核启动时总线会自动匹配,总线通过设备树的.compatible适配属性或match函数匹配;

           驱动层 是设备的操作函数driver:应该就是module里的各种读写开关文件probe等。

        2.2.2 有些外设没有总线的概念,便使用虚拟的platform总线来驱动。

          device和driver对应为platform_device和platform_driver;

          总线为bus_type结构体,位置:/include/linux/device.h;而虚拟出来的platform位于:/device/base/platform.c中。

      2.3 驱动编译的两种方式

        2.3.1 同源码一起编译到内核里;

          2.3.1.1 在kernel/drivers/char下新建目录chardev_test;chardev_test目录下新建.c源文件,Kconfig,Makefile文件;

          2.3.1.2 修改char文件夹下的Makefile和Kconfig,包含新建chardev_test进编译;

    #kernel/drivers/char目录
    #Makefile文件结尾:表示将chardev_test目录下的文件编译进源码;chardev_test下的编译规则由chardev_test下的Makefile决定;
    obj-y    +=chardev_test/
    
    #Kconfig文件结尾:表示包含递归目录下的Kconfig文件;
    source "char/chardev_test/Kconfig"

          2.3.1.3 chardev_test文件下的Kconfig文件和Makefile文件

    #Kconfig文件:作用是配置config菜单显示的内容,配置.config中的变量CONFIG_XXX
    config CHARDEV_TEST
        tristate "This shows on config menu for CHARDEV_TEST config"
        help
        here help is jie shi for this config
    
    #Makefile文件:作用是告诉编译器怎么编译源文件;
    #此处的CONFIG_CHARDEV_TEST是由Kconfig文件中的config CHARDEV_TEST决定的;
    obj-$(CONFIG_CHARDEV_TEST)    +=kernel_driver.o

          配置文件Kconfig会生成配置菜单给用户选择,然后用户选择完之后会生成顶层目录下的.config文件,CONFIG_XXX是在.config中定义的,由Kconfig文件决定;

        2.3.2 单独编译为.ko文件,然后通过insmod命令加载到模块中;

          具体可见https://www.cnblogs.com/caesura-k/p/12627835.html 3.1小节

    3 字符设备

      3.1 字符设备的编写主要就是对/include/linux/fs.h文件内file_operation结构体的重新编写;

        在module_init(xxxdev_init)中指定模块的初始化函数,在模块初始化函数xxxdev_init()中注册一个设备;然后配置好该设备的操作函数即可;

        应用程序如果想操作设备,需要传入设备节点告诉内核想要使用的驱动设备文件;那么设备号dev_t和设备节点node有什么不同呢?

          设备号是内核用来区分驱动设备的,设备号是驱动设备的主要属性之一。

          设备节点是应用程序用来告诉内核我想操作什么驱动设备的。对于同一个驱动设备来说他们是相等的,设备节点存储在/dev/下。

  • 相关阅读:
    二维数组 A[m][n] 按行优先和按列优先的 下标地址转换公式
    服务器的公网ip 和内网ip
    剑指offer 23.二叉搜索树的后序遍历序列
    剑指offer 22. 从上往下打印二叉树 & 102. 二叉树的层序遍历
    剑指offer 21.栈的压入、弹出序列 & leetcode 剑指 Offer 31. 栈的压入、弹出序列
    剑指offer 4. 重建二叉树 & leetcode 剑指 Offer 07. 重建二叉树 & leetcode hot 100 105. 从前序与中序遍历序列构造二叉树
    Linux配置Nginx+Tomcat负载均衡
    yum安装apache及问题解决
    Linux高级文本处理命令
    JMeter:生成漂亮的多维度的HTML报告
  • 原文地址:https://www.cnblogs.com/caesura-k/p/12704239.html
Copyright © 2011-2022 走看看