Linux 内核:GPIO子系统(1)软件框架

背景

在很多驱动开发中,GPIO用得很多,因此学习一下;也会顺便看看pinctrl 子系统。

原文(有删改):http://www.wowotech.net/gpio_subsystem/io-port-control.html/comment-page-2#comments

前言

虽然GPIO子系统相关的硬件比较简单,没有复杂的协议,不过,对于软件抽象而言,其分层次的软件思想是每个嵌入式软件工程师需要掌握的内容。

我更倾向使用GPIO系统这个名字来代替GPIO driver这个名字,GPIO driver仅仅包含了pin signal状态控制和读取的内容,而GPIO系统包括了pin multiplexing、pin configuration、GPIO control、GPIO interrupt control等内容。

本文主要是以3.14内核作为例子,讲述linux kernel中GPIO系统的软件框架。

GPIO相关硬件有哪些差异

嵌入式工程师总是要处理各种各样的target board,每个target board上的GPIO总是存在不同。

和CPU的连接方式不同

对于ARM的嵌入式硬件平台,SOC本身可以提供大量的IO port,SOC上的GPIO controller是通过SOC的总线(AMBA)连接到CPU的。

对于嵌入式系统而言,除了SOC的IO port,一些外设芯片也可能会提供IO port,例如:

(1)有些key controller芯片、codec或者PMU的芯片会提供I/O port

(2)有些专用的IO expander芯片可以扩展16个或者32个GPIO

从硬件角度看,这些IO和SOC提供的那些IO完全不同,CPU和IO expander是通过I2C(也有可能是SPI等其他类型的bus)连接的,在这种情况下,访问这些SOC之外的GPIO需要I2C的操作,而控制SOC上的GPIO只需要写寄存器的操作。

不要小看这个不同,写一个SOC memory map的寄存器非常快,但是通过I2C来操作IO就不是那么快了,甚至,如果总线繁忙有可能阻塞当前进程,这种情况下,内核同步机制必须有所区别(如果操作GPIO可能导致sleep,那么同步机制不能采用spinlock)。

访问方式不同

SOC片内的GPIO controller和SOC片外的IO expander的访问当然不一样,不过,即便都是SOC片内的GPIO controller,不同的ARM芯片,其访问方式也不完全相同,例如:有些SOC的GPIO controller会提供一个寄存器来控制输出电平。向寄存器写1就是set high,向寄存器写0就是set low。但是有些SOC的GPIO controller会提供两个寄存器来控制输出电平。向其中一个寄存器写一就是set high,向另外一个寄存器写一就是set low。

配置方式不同

即便是使用了同样的硬件(例如都使用同样的某款SOC),不同硬件系统上GPIO的配置不同。

在一个系统上配置为输入,在另外的系统上可能配置为输出。

GPIO特性不同

这些特性包括:

(1)是否能触发中断。对一个SOC而言,并非所有的IO port都支持中断功能,可能某些处理器只有一两组GPIO有中断功能。

(2)如果能够触发中断,那么该GPIO是否能够将CPU从sleep状态唤醒

(3)有些有软件可控的上拉或者下拉电阻的特性,有的GPIO不支持这种特性。在设定为输入的时候,有的GPIO可以设定debouce的算法,有的则不可以。

5、多功能复用

有的GPIO就是单纯的作为一个GPIO出现,有些GPIO有其他的复用的功能。例如IO expander上的GPIO只能是GPIO,但是SOC上的某个GPIO除了做普通的IO pin脚,还可以是SPI上clock信号线。

硬件功能分类

ARM based SOC的datasheet中总有一个章节叫做GPIO controller(或者I/O ports)的章节来描述如何配置、使用SOC的引脚。

虽然GPIO controller的硬件描述中充满了大量的寄存器的描述,但是这些寄存器的功能大概分成下面三个类别:

1、有些硬件逻辑是和IO port本身的功能设定相关的,我们称这个HW block为pin controller。软件通过设定pin controller这个硬件单元的寄存器可以实现:

(1)引脚功能配置。例如该I/O pin是一个普通的GPIO还是一些特殊功能引脚(例如memeory bank上CS信号)。

(2)引脚特性配置。例如pull-up/down电阻的设定,drive-strength的设定等。

2、如果一组GPIO被配置成SPI,那么这些pin脚被连接到了SPI controller,如果配置成GPIO,那么控制这些引脚的就是GPIO controller。通过访问GPIO controller的寄存器,软件可以:

(1)配置GPIO的方向

(2)如果是输出,可以配置high level或者low level

(3)如果是输入,可以获取GPIO引脚上的电平状态

3、如果一组gpio有中断控制器的功能,虽然控制寄存器在datasheet中的I/O ports章节描述,但是实际上这些GPIO已经被组织成了一个interrupt controller的硬件block,它更像是一个GPIO type的中断控制器,通过访问GPIO type的中断控制器的寄存器,软件可以:

(1)中断的enable和disable(mask和unmask)

(2)触发方式

(3)中断状态清除

Linux是如何通过软件抽象来掩盖GPIO在硬件差异的

传统的GPIO driver是负责上面三大类的控制,而新的linux kernel中的GPIO subsystem则用三个软件模块来对应上面三类硬件功能:

(1)pin control subsystem。驱动pin controller硬件的软件子系统。

(2)GPIO subsystem。驱动GPIO controller硬件的软件子系统。

(3)GPIO interrupt chip driver。这个模块是作为一个interrupt subsystem中的一个底层硬件驱动模块存在的。

本文主要描述前两个软件模块,具体GPIO interrupt chip driver以及interrupt subsystem请参考本站其他相关文档。

pin control subsystem block diagram

下图描述了pin control subsystem的模块图:

底层的pin controller driver是硬件相关的模组,初始化的时候会向pin control core模块注册pin control设备(通过pinctrl_register这个bootom level interface)。

pin control core模块是一个硬件无关模块,它抽象了所有pin controller的硬件特性,仅仅从用户(各个driver就是pin control subsystem的用户)角度给出了top level的接口函数,这样,各个driver不需要关注pin controller的底层硬件相关的内容。

GPIO subsystem block diagram

下图描述了GPIO subsystem的模块图:

基本上这个软件框架图和pin control subsystem是一样的,其软件抽象的思想也是一样的,当然其内部具体的实现不一样,我们会在后续的文章中描述。

Linux 内核:GPIO子系统(1)软件框架的更多相关文章

  1. 浅谈 Linux 内核无线子系统

    浅谈 Linux 内核无线子系统 本文目录 1. 全局概览 2. 模块间接口 3. 数据路径与管理路径 4. 数据包是如何被发送? 5. 谈谈管理路径 6. 数据包又是如何被接收? 7. 总结一下 L ...

  2. Linux 内核无线子系统

    Linux 内核无线子系统 浅谈 Linux 内核无线子系统 Table of Contents 1. 全局概览 2. 模块间接口 3. 数据路径与管理路径 4. 数据包是如何被发送? 5. 谈谈管理 ...

  3. (转)浅谈 Linux 内核无线子系统

    前言 Linux 内核是如何实现无线网络接口呢?数据包是通过怎样的方式被发送和接收呢? 刚开始工作接触 Linux 无线网络时,我曾迷失在浩瀚的基础代码中,寻找具有介绍性的材料来回答如上面提到的那些高 ...

  4. 【linux】gpio子系统

    目录 前言 linux子系统 gpio子系统 gpio子系统实战-系统调用 前言 目前不涉及驱动源码 参考链接 linux子系统 在 Linux 系统中 绝大多数硬件设备都有非常成熟的驱动框架 驱动工 ...

  5. 嵌入式Linux内核I2C子系统详解

    1.1 I2C总线知识 1.1.1  I2C总线物理拓扑结构     I2C总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成.通信原理是通过对SCL和SDA线高 ...

  6. 【原创】解BUG-xenomai内核与linux内核时间子系统之间存在漂移

    版权声明:本文为本文为博主原创文章,转载请注明出处.如有问题,欢迎指正.博客地址:https://www.cnblogs.com/wsg1100/ 一.问题起源 何为漂移?举个例子两颗32.768kH ...

  7. Linux内核管理子系统和进程管理子系统

    内核管理子系统职能:1.管理虚拟地址与物理地址的映射 2.物理内存的分配 程序:存放在磁盘上的一系列代码和数据的可执行映像,是一个静止的实体. 进程:是一个执行中的程序,它是动态的实体 进程四要素: ...

  8. linux内核I2C子系统学习(三)

    写设备驱动: 四部曲: 构建i2c_driver 注册i2c_driver 构建i2c_client ( 第一种方法:注册字符设备驱动.第二种方法:通过板文件的i2c_board_info填充,然后注 ...

  9. linux内核input子系统解析【转】

    转自:http://emb.hqyj.com/Column/Column289.htm 时间:2017-01-04作者:华清远见 Android.X windows.qt等众多应用对于linux系统中 ...

  10. Linux内核的LED设备驱动框架【转】

    /************************************************************************************ *本文为个人学习记录,如有错 ...

随机推荐

  1. k3s安装---适配边缘计算场景的轻量级的k8s(二)

    三.安装k8s k3s官网:https://k3s.io 文档: github:https://github.com/k3s-io/k3s 3.1 安装基础环境 # 安装基础环境 1.安装yum源 c ...

  2. 实验8 #第8章 Verilog有限状态机设计-1 #Verilog #Quartus #modelsim

    8-1 流水灯控制器 1. 实验要求:采用有限状态机设计彩灯控制器,控制LED灯实现预想的演示花型. 2. 实验内容: (1)功能:设计彩灯控制器,要求控制18个LED灯实现如下的演示花型: 从两边往 ...

  3. Git实战技巧:恢复被强制push -f失踪的代码

    前言 Git是一个易学难精的分布式版本控制系统,被我们码农常用于代码的管理.如果你还不了解Git,建议先通过廖雪峰的Git教程进行了解,再来看本文,因为本文以使用技巧为主,不会在基础名词上做过多解释. ...

  4. Fast Möbius Transform 学习笔记 | FMT

    小 Tips:在计算机语言中 \(\cap\) = & / and, \(\cup\) = | / or First. 定义 定义长度为 \(2^n\) 的序列的 and 卷积 \(A = B ...

  5. golang计时器

    timer 计时器 用于在指定的Duration类型时间后调用函数或计算表达式. 如果只是想指定时间之后执行,使用time.Sleep() 使用NewTimer(),可以返回的Timer类型在计时器到 ...

  6. ETSI GS MEC 014,UE 标识 API

    目录 文章目录 目录 版本 功能理解 UML UE Identity tag registration UE Identity tag de-registration API Definition U ...

  7. Java中CAS算法的集中体现:Atomic原子类库,你了解吗?

    一.写在开头 在前面的博文中我们学习了volatile关键字,知道了它可以保证有序性和可见性,但无法保障原子性,结局原子性问题推荐使用synchronized.Lock或者AtomicInteger: ...

  8. 基于webapi的websocket聊天室(番外二)

    我比较好奇的是webapi服务器怎么处理http请求和websocket请求.有了上一篇番外的研究,这里就可以试着自己写个非常简易的webapi服务器来接收这两种请求. 效果 http请求 消息打印 ...

  9. 【ESP32】制作 Wi-fi 音箱(HTTP + I2S 协议)

    用 Wifi 来传输音频数据,会比蓝牙更好.使用蓝牙方式,不管你用什么协议,都会对数据重新编码,说人话就是有损音质,虽然不至于全损.而使用 Wifi 就可以将 PCM 数据直接传输,无需再编码和压缩. ...

  10. Java 中 hashCode 和 equals 方法是什么?它们和 == 各有什么区别?

    在 Java 中,hashCode 和 equals 方法都是 Object 类的方法.它们的作用分别如下: hashCode 方法返回对象的哈希码,用于支持基于哈希表的集合,如 HashMap.Ha ...