0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

rt-thread 驱动篇(七)GPIO驱动

出出 来源:出出 作者:出出 2022-06-13 09:48 次阅读

前言

一提 GPIO 可能会让很多人觉得不屑,这么简单的东西有什么可说的,也就是一个拉低拉高,谁不会呢。

今天我们不讲推挽开漏、不提上拉下拉。大家来头脑风暴一下 GPIO 相关的几个问题。笔者说的不一定对,仅代表个人的一点儿小想法。

提出两个问题

有两个问题,需要考虑一下:
1. pin 设备驱动框架存在的必要性。
2. gpio 底层驱动使用官方提供的 api 还是直接寄存器操作?

单片机里,pin 引脚操作往往很简单,写一个寄存器就成。但是在一个操作系统里,为了方便移植、便于阅读,对 pin 进行封装,在不同芯片上使用同一套 api 也还是有必要的。而这也正是一个操作系统的职责之一。

第二个问题,留着大家自己想吧。

pin 驱动框架

我们大家都知道,在我们使用 pin 的时候,没有谁先用 `rt_device_find` 查找 pin 设备,然后使用用 `rt_device_open` `rt_device_read` `rt_device_write` 去控制芯片引脚。而都是直接调用的 `rt_pin_xxx` c 函数簇。

pin 驱动框架,先把所有的 gpio 看作一个设备进行注册,然后提供了三个 `rt_pin_mode` `rt_pin_read` `rt_pin_write` c 函数,而不是 `rt_device_xxx` api 去访问某个 pin。
`rt_pin_mode` `rt_pin_read` `rt_pin_write` 这一套函数,可以不用考虑当前使用的是什么芯片,不用考虑芯片厂商提供的外设驱动库 api 是怎么写的。但是,真的是这样吗?

可以把驱动框架删掉,`rt_pin_xxx` 函数直接对接底层驱动吗?

当笔者阅读模拟 iic 驱动源码时,看到在控制 SCL SDA 高低电平切换时使用的 `rt_pin_write` 操作,一时间脑子一阵晕眩。为什么?我们先捋顺一下拉低 SDA 的函数调用过程。

以 `SDA_L` 为例
1. `SDA_L` 宏是 `ops->set_sda(ops->data, val)` 通过操作符指针调用底层接口
2. `set_sda` 调用 `rt_pin_write`
3. `rt_pin_write` 通过 pin 设备执行 `_hw_pin.ops->pin_write` 调用的 pin 底层接口
4. 在 stm32 平台上 `_hw_pin.ops->pin_write` 等于调用 `stm32_pin_write` 函数
5. `stm32_pin_write` 调用 `HAL_GPIO_WritePin`
6. `HAL_GPIO_WritePin` 函数写寄存器。

弯弯绕绕,想控制 pin 引脚电平变化还真是煞费苦心了。

可以压缩上述调用过程吗?
`SDA_L` 宏直接定义调用 `stm32_pin_write` ,`stm32_pin_write` 内部直接操作寄存器。

soft iic 驱动

软件模拟 iic 驱动需要软件代码控制 SCL SDA 两根线时序,如前所述,拉低 SDA 线的过程被繁冗化了。

裸机能达到的 iic 时钟速度,在使用 rt-thread 的模拟 iic 时根本达不到,在多级指针和函数调用过程中,效率被极大降低了。

有没有一种策略,使 `SDA_L` 宏直接定义成 `stm32_pin_write` 或者 `gd32_pin_write` 等等。

笔者尝试把 i2c-bit-ops.c 文件和 drv_soft_i2c.c 两个文件进行合并,省掉了一级 `struct rt_i2c_bit_ops`,然后 `SDA_L` 也不使用 `rt_pin_write` 又跳过了多次指针调用。目前感觉良好。

GET_PIN

有哪位能告诉大家, `rt_pin_write(17, PIN_HIGH)` 这句代码有明确的语义吗?

函数调用中的第一个参数值 “17” 表示了什么?
可能啥也不代表。
首先,它肯定不是芯片引脚编号。
大多数芯片,GPIO 编码采用的类似如下方式:
- 以端口编码,一颗芯片上的 GPIO 可以分成若干个端口,用字母 A B C ... 命名(也有 1 2 3 编号命名的,比如 RA6M4)。我们称之为 PA PB PC ...
- 每个端口有8/16个 io 。分别编码 0-7 或者 0-15。有些芯片上的某个端口只有 15 个 io ,那就只有 0-14 有效。我们称之为 PA0 PA15

为了不使用魔数 “17” ,这种模棱两可,含义不明的写法,rt-thread 针对每种芯片要求定义一个 `GET_PIN` 宏,它可以从一种直观的引脚编号写法中返回一个数字。比如 `GET_PIN(G, 1)` 的结果是 97。

使用 `GET_PIN` `rt_pin_write(17, PIN_HIGH)` 可以写成 `rt_pin_write(GET_PIN(B, 1), PIN_HIGH)` ,这样是不是更直观了?

但是,有一种情况,不允许我们用 `GET_PIN` 。那就是在 menuconfig 或者 RT-Studio 的 Settings 里配置模拟 iic 两个引脚号的时候。它只支持输入数字,这个时候我们必须知道 `GET_PIN` 的数学含义,心算把 `GET_PIN(B, 1)` 转成 17 。

`GET_PIN` 的数学含义是确定的吗?是放之四海而皆准的吗?在每一款芯片上可以使用同一个数学公式演算吗?

**这个可以是,但实际却不是**。

另类的 AB32 RA6M4 N32

我们仍然以 17 这个编号为例,下面来看看 AB32 RA6M4 上面它分别代表哪个 GPIO 。

AB32 上应该是 PE4。
AB32 版 `GET_PIN` 是这样的:

#define __AB32_PORT(port)   GPIO##port
#define __AB32_GET_PIN_A(PIN)  PIN
#define __AB32_GET_PIN_B(PIN)  8 + PIN
#define __AB32_GET_PIN_E(PIN)  13 + PIN
#define __AB32_GET_PIN_F(PIN)  21 + PIN

几个端口不通用,各自为战

RA6M4 上不存在。因为 RA6M4 的 P100 对应的是 256 ;P015 对应的是 15 。没有 17 这个编号。
AB32 版 `GET_PIN` 未实现。

还有 N32,上面笔者说了句“它肯定不是芯片引脚编号”。但是,我又发现在 N32 的drv_gpio.c 中,定义成了芯片引脚号。打脸了...
N32 版 `GET_PIN` 也未实现。

还有其它芯片是上述三种情况之外的吗?欢迎大家讲出来。

明确的应用层语义

不失一般性,假设可能存在某芯片端口编号不是连续的,中间缺失端口B。同时端口 A 也只有 12 个 io。我们把所有的端口和 io 进行排序编号。PA0 是 0 号、PA1 是 1 号 ... PA11 是 11 号。那么,PC0 编号是多少?12吗?

假如有一同系列芯片,它是有端口 B 的。那么 PB0 编号该定义成多少合适呢?也是 12 吗?

> 或者,干脆我们就假定所有的芯片端口都是连续无缺失的,每个端口也是满满当当 16 个 io 。这样 PB0 总是 16,PC0 总是 32。

从理论上讲,所有的芯片 gpio 编号系统是可以用一个公式实现的,这个公式可以在 rt-thread 使用宝典(2022-0516更新)中找到。

RA6M4 上,应用程序层可以使用 17 表示 P101,因为它的端口编号从 0 开始;
N32 上,应用程序层可以使用 17 表示 PB01,因为它的端口编号从 A 开始;
STM32 上,应用程序层可以使用 17 表示 PB01,因为它的端口编号从 A 开始;
AB32 上,应用程序层可以使用 17 表示 PB01,因为它的端口编号从 A 开始

无论用的哪家芯片,无论是哪个系列芯片,无论是哪款型号,它有多少引脚。我们希望 17 这个值能对应一个明确的引脚名。不会因为某系列芯片中某子型号因为其中某个端口 io 数量少一个导致后面所有 io 的编号都变了。又或者同样的 PB01 在不同子型号不同封装下的编号也不一样。

结束语

大家有什么意见和想法,一块儿聊聊啊。

> 把不同芯片的差异性进行封装,提供给应用层语义明确的接口,是一个操作系统的职责之一。
复杂事情简单化,简单的事情保留那一点儿纯粹。这也是封装的基本原则。
写应用程序代码时,我们不想关心底层的实现,这是另一个操作系统的职责之一。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • GPIO
    +关注

    关注

    16

    文章

    1133

    浏览量

    50565
  • PIN
    PIN
    +关注

    关注

    1

    文章

    298

    浏览量

    23674
  • RT-Thread
    +关注

    关注

    31

    文章

    1148

    浏览量

    38867
  • 驱动框架
    +关注

    关注

    0

    文章

    14

    浏览量

    4004
收藏 人收藏

    评论

    相关推荐

    RT-Thread NUC97x 移植 LVGL

    不涉及 rt-thread 驱动,但是它是 LVGL 和 rt-thread 的接口。LVGL 在 rt-thread 上运行的基石。
    发表于 07-08 09:37 1284次阅读

    RT-Thread ssd1306驱动

    RT-Thread 驱动ssd1306
    的头像 发表于 04-21 10:08 26.4w次阅读
    <b class='flag-5'>RT-Thread</b> ssd1306<b class='flag-5'>驱动</b>

    RT-Thread Studio上配置rtthread CANFD驱动来控制M3508电机

    本文旨在RT-Thread Studio上配置rtthread CANFD驱动来控制M3508电机,不涉及任何原理 开发环境:RT-Thread Studio v2.2.6
    发表于 10-08 11:44 557次阅读
    在<b class='flag-5'>RT-Thread</b> Studio上配置rtthread CANFD<b class='flag-5'>驱动</b>来控制M3508电机

    RT-Thread设备驱动开发指南基础篇—以先楫bsp的hwtimer设备为例

    RT-Thread设备驱动开发指南》书籍是RT-thread官方出品撰写,系统讲解RT-thread IO设备驱动开发方法,从三方面进行讲解
    的头像 发表于 02-20 16:01 821次阅读
    <b class='flag-5'>RT-Thread</b>设备<b class='flag-5'>驱动</b>开发指南基础篇—以先楫bsp的hwtimer设备为例

    【原创精选】RT-Thread征文精选技术文章合集

    rt-thread 驱动(六)serialX弊端及解决方法rt-thread 驱动
    发表于 07-26 14:56

    如何使用RT-Thread的通用GPIO设备驱动

    摘要本应用笔记描述了如何使用 RT-Thread 的通用 GPIO 设备驱动,包括驱动的配置、相关 API 的应用。并给出了在正点原子 STM32F4 探索者开发板上验证的代码示例。本
    发表于 08-18 10:44

    如何在RT-Thread中使用通用GPIO设备驱动从而操作GPIO

    摘要本应用笔记描述了如何使用 RT-Thread 的通用 GPIO 设备驱动,包括驱动的配置、相关 API 的应用。并给出了在正点原子 STM32F4 探索者开发板上验证的代码示例。本
    发表于 10-25 11:17

    RT-Thread上的CAN总线介绍以及驱动编写

    昨晚很荣幸邀请到李工在RT-Thread微信群进行RT-Thread上的CAN驱动和应用讲座。小编整理了讲座内容,特发出讲义以供享用。
    的头像 发表于 09-25 10:16 2.3w次阅读

    简要分析Thread的通用GPIO设备驱动

    为了给用户提供操作GPIO的通用API,方便应用程序开发,RT-Thread中引入了通用GPIO设备驱动。并提供类似Arduino风格的API用于操作
    发表于 11-13 14:57 1310次阅读

    RT-Thread Studio驱动SD卡

    RT-Thread Studio驱动SD卡前言一、创建基本工程1、创建Bootloader2、创建项目工程二、配置RT-Thread Settings三、代码分析1.引入库2.读入数据四、效果验证
    发表于 12-27 19:13 20次下载
    <b class='flag-5'>RT-Thread</b> Studio<b class='flag-5'>驱动</b>SD卡

    RT-Thread开源作品秀】基于RT-Thread的星务平台研究

    本作品为了验证星务软件在RT-Thread系统运行的可行性,底层是否能够驱动星务软件,同时扩展RT-Thread应用范围。ART-Pi作为卫星下位机,...
    发表于 01-25 18:26 5次下载
    【<b class='flag-5'>RT-Thread</b>开源作品秀】基于<b class='flag-5'>RT-Thread</b>的星务平台研究

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 7次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植

    送《RT-Thread设备驱动开发指南》,手慢无!

    过程中的第一选择!本书 也是RT-Thread第8本相关书籍了,本期我们将抽奖送给大家! 抽奖请移步文末↓↓↓ 随着RT-Thread被更广泛地应用于行业中,开发者对嵌入式驱动开发的需求越来越强烈,他们
    的头像 发表于 03-19 23:00 1045次阅读

    RA6M3 RT-Thread* LVGL HMI Board开发实践指南-GPIO实践

    RT-Thread即将发布一系列RA6M3外设驱动的实践指南,我们将使用瑞萨RA6M3 HMI-Board 开发板,带领大家上手RT-Thread设备驱动, 本篇文章将介绍
    的头像 发表于 11-30 19:05 514次阅读
    RA6M3 <b class='flag-5'>RT-Thread</b>* LVGL HMI Board开发实践指南-<b class='flag-5'>GPIO</b>实践