一篇带给你GPIO 软件框架

系统 Linux
我们研究 GPIO 的软件部分,分别从单片机平台和 Linux 平台来研究。单片机平台编写 GPIO 口程序,以 STM32F103 为例,有三种模式:库函数、HAL库、寄存器。

[[431681]]

GPIO 八种工作模式详解

接着上一篇的讲,我们上一篇研究了 GPIO 的硬件结构,其来源于 STM32 官方手册,研究了 GPIO 的八种工作模式和推挽输出及开漏输出原理,接下来我们研究 GPIO 的软件部分,分别从单片机平台和 Linux 平台来研究。

1、单片机平台

单片机平台编写 GPIO 口程序,以 STM32F103 为例,有三种模式:库函数、HAL库、寄存器。

使用库函数的方式操控 GPIO 方式如下:

  1. void LED_Init(void) 
  2.     GPIO_InitTypeDef GPIO_InitStructure; 
  3.  
  4.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//使能 PB 端口时钟 
  5.  
  6.     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; 
  7.     //PB5 端口配置 
  8.     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出 
  9.     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO 口速度 
  10.     GPIO_Init(GPIOB, &GPIO_InitStructure); //根据设定参数初始化 GPIOB.5 
  11.     GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高 

上述代码就是使用库函数来初始化 STM32 的一个 IO 为输出功能,可以看出上述初始化代码中重点要做的事情有一下几个:

①、使能指定 GPIO 的时钟。

②、初始化 GPIO,比如输出功能、上拉、速度等等。

③、STM32 有的 IO 可以作为其它外设引脚,也就是 IO 复用,如果要将 IO 作为其它外设引脚使用的话就需要设置 IO 的复用功能。

④、最后设置 GPIO 输出高电平或者低电平。

STM32 的 GPIO 初始化就是以上四步,使用库函数操作 GPIO 还是很简单的。但是我们知道 STM32F1 系列是有库函数的,但是 STM32F7 系列就没有库函数了,ST 公司没有出,STM32F7 只有 HAL 库和寄存器两种操作方式。

2、嵌入式 Linux 平台

先总结一句:不管是单片机还是高端 ARM 平台,最底层都是寄存器,硬件之上就是寄存器,任何封装形式到最底层就是操作寄存器。

对于上了 Linux 系统的平台,我们有其他方法,让它可以像单片机一样简单的操作 IO 口,这得益于各路 Linux 大神对系统底层的封装。

在 Linux 中有 pinctrl 和 gpio 子系统,它们提供了 API 接口给你使用,让你方便的操控 GPIO 口。

Linux 内核针对 PIN 的配置推出了 pinctrl 子系统,对 GPIO 的配置推出了 gpio 子系统。

上面这句话很重要,我详细解释一下:这里是将 pin 脚和控制 IO 口输入输出分离。

pinctrl 子系统管理 200 个 IO 口的上拉下拉电阻,电流驱动能力,是硬件底层的存在。如果 pinctrl 将某个 pin 脚初始化成了普通 GPIO 而不是 IIC 或者 SPI,那么接下来我们就可以使用 gpio 子系统的 API 去操作 IO 口输出高低电平。

传统的配置 pin 的方式就是直接操作相应的寄存器,但是这种配置 方式比较繁琐、而且容易出问题(比如 pin 功能冲突)。pinctrl 子系统就是为了解决这个问题而引入的,pinctrl 子系统主要工作内容如下:

①、获取设备树中 pin 信息。

②、根据获取到的 pin 信息来设置 pin 的复用功能

③、根据获取到的 pin 信息来设置 pin 的电气特性,比如上/下拉、速度、驱动能力等。

对于我们使用者来讲,只需要在设备树里面设置好某个 pin 的相关属性即可,其他的初始化工作均由 pinctrl 子系统来完成,pinctrl 子系统源码目录为 drivers/pinctrl。

注意,pinctrl 子系统也是一个标准的 platform 驱动,当设备和驱动匹配的时候,probe 函数会执行,只是 pinctrl 子系统采用的 arch_initcall 去声明,而不是 module_init(device_initcall),所以在系统起来的时候它会先加载。(具体原因看下面这篇文章)

Linux 驱动挂载顺序分析

pinctrl 和 gpio 子系统软件框架如下:

pinctrl

 

gpio

可以看出其实两者软件框架一样的,主要是 HW Abstract layer 具体实现不一样。

你以为两者是分离的,实际上不是的,gpio 子系统是基于 pinctrl 子系统的,gpio 的 API 接口的实现很多都是基于 pinctrl 子系统的函数。

 

责任编辑:姜华 来源: 嵌入式Linux系统开发
相关推荐

2021-07-12 06:11:14

SkyWalking 仪表板UI篇

2021-07-08 07:30:13

Webpack 前端Tree shakin

2022-02-25 15:50:05

OpenHarmonToggle组件鸿蒙

2023-03-13 09:31:04

2021-04-14 07:55:45

Swift 协议Protocol

2021-05-08 08:36:40

ObjectString前端

2021-04-23 08:59:35

ClickHouse集群搭建数据库

2022-07-06 07:57:37

Zookeeper分布式服务框架

2022-03-01 13:55:27

TektonKubernetes集群

2022-03-08 08:32:43

Tekton云原生开源

2021-05-06 09:41:33

Linux 系统硬件操作系统

2021-06-28 10:04:12

SpringCloudSleuth微服务

2021-09-22 08:37:02

pod源码分析kubernetes

2021-03-18 08:53:44

MySQL数据库索引

2023-04-09 21:39:48

JavaScript开源

2021-09-13 07:46:06

Kubectl Kubernetes 工具

2022-01-07 07:49:07

Apache APISKubernetesAPISIX

2022-03-24 12:28:03

React 17React 18React

2021-05-08 09:02:48

KubeBuilderOperatork8s

2022-03-29 08:18:32

位图算法索引技术
点赞
收藏

51CTO技术栈公众号