浅谈驱动开发

2023-05-16

驱动开发没那么高大上

驱动开发在很多人眼中都是一项极具挑战性的任务,可当你真正去开发一个驱动时,你也许会发现它并没有看上去那样困难,可对大多数人而言驱动开发是八竿子打不着的话题,故而更增强了驱动开发在许多人心中的神秘感。

驱动是操作系统控制硬件的接口,它直接与硬件及操作系统打交道。下面我将从硬件与操作系统两个方面描述驱动开发的大致内容。

1. 驱动与硬件

驱动中对于硬件的控制主要通过配置寄存器来完成。这一过程可能十分复杂却不见得有多大的挑战,更不会有太多的自由发展空间。它无疑是驱动开发中最枯燥无味的环节,然而你一旦忽视,那配置中即便只有一个小小的问题,硬件可能也会罢工,你就得重新梳理,比对寄存器配置,直至找到问题。

配置寄存器以驱动硬件

配置寄存器时的参考资料是芯片手册与官方 demo。如果芯片手册写得比较清楚,那么配置起来便少了许多压力,如果芯片手册写得让人摸不着头脑,那么寄存器配置也会让你头大。或许参考下官方 demo 能够减轻你的压力,只是这种条件并不是任何时候都能够具备。

确认配置生效

当寄存器配置完成后,你需要调试来确认寄存器是否真的按照代码逻辑进行了配置。你常常会先入为主的认为代码中写的逻辑没有太大问题,可实际的执行结果并不一定能够达到你的预期。即便你配置的是正确的也有可能不能正常工作,你还需要考虑编译器优化可能造成的问题。也许你会说一个 volatile 便能够解决大多数的问题,可这样的处理方式并不被建议。那么你需要去研究屏障的使用。你要确认编译屏障、内存屏障该使用在怎样的时机。哎!配个寄存器都会横生枝节,写到这里我也长长的叹了口气!

排除硬件问题

完成了初始化配置后可以写一个简单的中断服务程序进行测试,如果不能正常工作,那么可以进一步查看引脚波形,使用示波器来打一下使用的引脚,从波形可以看出一些端倪,这也是最客观的证据。

其实更客观的步骤应该是先用万用表来确认下引脚是否真的连通,确认没有问题后再使用示波器来进一步分析。只是我们很多时候都不会这样去做。一旦真的遇到这样的问题,那么可能要绕好几圈才能够想起这些问题。

寄存器配置的总结

也许寄存器配置也并非是个难题。只是它是与芯片高度耦合,不同的芯片之间可能会有很大的差异。这也就意味着你在某一个芯片上开发驱动所积累的经验很大一部分不能应用到新的芯片上。其实类似功能硬件的大致工作流程倒也相差不多,只是寄存器配置又得重新学习。

2.驱动与操作系统

驱动与操作系统的之间主要是软件问题。中断服务程序是一个核心。不同的平台中中断处理的过程不尽相同,不同的处理过程所带来的实时性问题也需要考虑。

中断服务程序应该写的尽可能简短。甚至可以将中断服务程序的处理过程进行分离,只在中断服务程序中处理最紧急的操作,其它的操作可以延后处理。linux 中的上半部分与下半部分的处理就是一个很好的实例。

2.1 中间层

中间层是一个抽象的软件层。它向上层提供服务的同时也规定了驱动中的接口。中间层的意义在于更灵活的控制驱动,提供调用驱动的统一接口,同时降低驱动开发的难度。

对于具有中间层的平台,驱动需要适配中间层,需要实现中间层依赖的底层函数,这些函数一般会填充到虚函数表中,通过注册来导入。

中间层可能会特别复杂。驱动开发人员实际开发中并不需要对中间层的逻辑完全了解,只需要专注于实现中间层规定的接口。

2.2 阻塞与非阻塞调用

阻塞与非阻塞的调用一般都由中间层实现。

当用户任务调用 api 接口读取数据时,阻塞方式会在没有数据处理时挂起用户进程,非阻塞方式则会立刻返回。对于阻塞方式,用户进程被挂起意味着内核需要提供某种唤醒机制来在设定的条件达到时唤醒用户进程。常见的方式有信号量、信号、消息队列等。

假设驱动中使用了 linux 内核提供的软中断功能。在中断服务程序中处理最紧急的部分,然后激活软中断,按照设定的优先级调度执行。由于这种下半部分处理机制的优先级仅次于中断处理程序,因此在激活后通常能够很快得到执行。在执行的这段预先注册的内核函数中,判断上层的请求是否完成,完成则唤醒用户进程,这样便完成了一次阻塞的调用过程。如果不使用下半部分的处理机制,这一过程可以在中断服务程序中完成。

2.3 共享变量的保护

在适配中间层时,需要对驱动与中间层共享的变量进行保护,防止数据不一致问题的产生。开发者必须清楚哪些变量不需要保护便能直接访问,哪些变量必须要进行保护。

保护的方法是调用操作系统提供的锁,如自旋锁、互斥锁、读写锁等。尽可能减少共享变量的数量,同时将对共享变量的操作聚合,这样有利于控制锁的范围。至于需要使用什么锁,应该根据实际情况选择。

总结

本文描述了驱动开发中涉及到的硬件与软件部分。限于篇幅与经验,仅仅摘取了主要的部分。麻雀虽小,五脏俱全。希望能让读者对驱动开发中涉及的知识有基本的认识,以拉下驱动开发神秘的面纱。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

浅谈驱动开发 的相关文章

随机推荐

  • FreeRTOS学习(六) 时间片调度

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 对于FreeRTOS 允许同等任务优先级存在 那么对于多个同等优先级的任务运行 情况的是如何 FreeRTOS 的机制就是对于同等优先级任务来说
  • FreeRTOS学习(十) 信号量

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 二值信号量 二值信号量 通常用于互斥访问 或同步 大多数用于同步 任务与任务 或 任务 与中断的同步 和队列一样 信号量API函数允许设置一个阻
  • Arduino 操控 12v 电压控制电磁铁 (线性振动马达?

    在此记录一下制作过程 xff0c 以作日后参考 效果 xff1a 线性震动马达 xff1f 大概思路 xff1a 通过L298N xff0c 用外接12v电源给电磁铁进行12v供电 xff0c 给arduino进行5v供电 一个电磁铁的供电
  • Dijkstra算法详解

    1 dijkstra算法简介 Dijkstra算法是由E W Dijkstra于1959年提出 xff0c 又叫迪杰斯特拉算法 xff0c 它应用了贪心算法模式 xff0c 是目前公认的最好的求解最短路径的方法 算法解决的是有向图中单个源点
  • C++建立动态二维数组

    C 43 43 建立动态二维数组主要有两种方法 xff1a 1 使用数组指针 xff0c 分配一个指针数组 xff0c 将其首地址保存在b中 xff0c 然后再为指针数组的每个元素分配一个数组 int b 61 new int row 分配
  • 理解负载均衡

    什么是平均负载 xff1f 单位时间内 xff0c 系统处于可运行状态和不可中断状态的平均进程数 xff0c 也就是平均活跃进程数 xff0c 它和CPU使用率并没有直接关系 所谓可运行状态的进程 xff0c 是指正在使用CPU或者等待CP
  • 理解CPU使用率和CPU上下文切换

    1 CPU使用率 1 1 CPU使用率查看 当发现服务或机器卡的时候 xff0c 我们都是先通过top命令查看服务器CPU使用率 默认每3秒刷新一次 top top 18 10 58 up 1216 days 7 38 4 users lo
  • 自动驾驶概述

    1 自动化能力定义 对自动驾驶能力有多个定义标准 xff0c 比较常用的是SAE International关于自动化层级的定义 具体是 L0 驾驶员完全掌控车辆 L1 自动系统有时能够辅助驾驶员完成某些驾驶任务 L2 自动系统能够完成某些
  • 2014百度校招笔试题之动态链接库&静态链接库详解

    1 什么是静态连接库 xff0c 什么是动态链接库 静态链接库用通俗的话讲 静态库就是将代码编译到一个二进制文件下 通常扩展名为 LIB 然后客户端调用程序 只需要包含相关的 h文件及LIB库文件一起链接到exe文件中 可执行程序发布后 不
  • @武汉人民,请收好这份名单

    1月27日 xff0c 武汉本地众多商户联合阿里巴巴旗下饿了么口碑 盒马 飞猪等业务 xff0c 从衣食住行各个角度 xff0c 为武汉一线医护人员提供安全 高品质的餐品及生活配套服务 首批100家餐厅已准备就绪 其中麦当劳 华莱士 大米先
  • java遍历泛型的方法

    一 List遍历 Java中List遍历有三种方法来遍历泛型 xff0c 主要为 xff1a 1 for循环遍历 2 iterator遍历 3 foreach遍历 package com gmail lsgjzhuwei import ja
  • java web文件下载功能实现

    需求 xff1a 实现一个具有文件下载功能的网页 xff0c 主要下载压缩包和图片 两种实现方法 xff1a 一 xff1a 通过超链接实现下载 在HTML网页中 xff0c 通过超链接链接到要下载的文件的地址 lt DOCTYPE htm
  • java创建线程的三种方式及其对比

    Java中创建线程主要有三种方式 xff1a 一 继承Thread类创建线程类 xff08 1 xff09 定义Thread类的子类 xff0c 并重写该类的run方法 xff0c 该run方法的方法体就代表了线程要完成的任务 因此把run
  • 'hibernate.dialect' must be set when no Connection available

    今天碰到的这个问题 xff0c 很无厘头 xff0c 网上搜索了很多 xff0c 都不靠谱 xff0c 还是靠自己 解决方法是在hibernate cfg xml中添加 lt property name 61 34 dialect 34 g
  • javascript动态插入html元素

    主要有是两种方案 xff1a 1 使用DOM span class hljs comment 使用createElement创建元素 span span class hljs keyword var span dialog 61 docum
  • python中switch语句用法

    python中是没用switch语句的 xff0c 这应该是体现python大道至简的思想 xff0c python中一般多用字典来代替switch来实现 coding utf 8 from future import division d
  • ROS的 sudo rosdep init 的报错终极解决方案

    ROS的 sudo rosdep init 的报错解决方案 安装ROS时sudo rosdep init指令报错 xff1a ERROR span class token operator span cannot download span
  • 图解Word2vec

    作者 xff1a 龙心尘 时间 xff1a 2019年4月 出处 xff1a https blog csdn net longxinchen ml article details 89077048 审校 xff1a 龙心尘 作者 xff1a
  • api 功能与实现的些许感想

    api 功能与实现 对于 api 功能的了解 xff0c 通过学习源码的实现便能做到 反之 xff0c 通过研究源码 xff0c 也能对api 功能有所了解 api 功能与实现的这种相互联系意味着我们不应该将 api 的功能与实现切割开 x
  • 浅谈驱动开发

    驱动开发没那么高大上 驱动开发在很多人眼中都是一项极具挑战性的任务 xff0c 可当你真正去开发一个驱动时 xff0c 你也许会发现它并没有看上去那样困难 xff0c 可对大多数人而言驱动开发是八竿子打不着的话题 xff0c 故而更增强了驱