0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

rt-thread 驅(qū)動(dòng)篇(七)GPIO驅(qū)動(dòng)

出出 ? 來(lái)源:出出 ? 作者:出出 ? 2022-06-13 09:48 ? 次閱讀

前言

一提 GPIO 可能會(huì)讓很多人覺(jué)得不屑,這么簡(jiǎn)單的東西有什么可說(shuō)的,也就是一個(gè)拉低拉高,誰(shuí)不會(huì)呢。

今天我們不講推挽開(kāi)漏、不提上拉下拉。大家來(lái)頭腦風(fēng)暴一下 GPIO 相關(guān)的幾個(gè)問(wèn)題。筆者說(shuō)的不一定對(duì),僅代表個(gè)人的一點(diǎn)兒小想法。

提出兩個(gè)問(wèn)題

有兩個(gè)問(wèn)題,需要考慮一下:
1. pin 設(shè)備驅(qū)動(dòng)框架存在的必要性。
2. gpio 底層驅(qū)動(dòng)使用官方提供的 api 還是直接寄存器操作?

單片機(jī)里,pin 引腳操作往往很簡(jiǎn)單,寫一個(gè)寄存器就成。但是在一個(gè)操作系統(tǒng)里,為了方便移植、便于閱讀,對(duì) pin 進(jìn)行封裝,在不同芯片上使用同一套 api 也還是有必要的。而這也正是一個(gè)操作系統(tǒng)的職責(zé)之一。

第二個(gè)問(wèn)題,留著大家自己想吧。

pin 驅(qū)動(dòng)框架

我們大家都知道,在我們使用 pin 的時(shí)候,沒(méi)有誰(shuí)先用 `rt_device_find` 查找 pin 設(shè)備,然后使用用 `rt_device_open` `rt_device_read` `rt_device_write` 去控制芯片引腳。而都是直接調(diào)用的 `rt_pin_xxx` c 函數(shù)簇。

pin 驅(qū)動(dòng)框架,先把所有的 gpio 看作一個(gè)設(shè)備進(jìn)行注冊(cè),然后提供了三個(gè) `rt_pin_mode` `rt_pin_read` `rt_pin_write` c 函數(shù),而不是 `rt_device_xxx` api 去訪問(wèn)某個(gè) pin。
`rt_pin_mode` `rt_pin_read` `rt_pin_write` 這一套函數(shù),可以不用考慮當(dāng)前使用的是什么芯片,不用考慮芯片廠商提供的外設(shè)驅(qū)動(dòng)庫(kù) api 是怎么寫的。但是,真的是這樣嗎?

可以把驅(qū)動(dòng)框架刪掉,`rt_pin_xxx` 函數(shù)直接對(duì)接底層驅(qū)動(dòng)嗎?

當(dāng)筆者閱讀模擬 iic 驅(qū)動(dòng)源碼時(shí),看到在控制 SCL SDA 高低電平切換時(shí)使用的 `rt_pin_write` 操作,一時(shí)間腦子一陣暈眩。為什么?我們先捋順一下拉低 SDA 的函數(shù)調(diào)用過(guò)程。

以 `SDA_L` 為例
1. `SDA_L` 宏是 `ops->set_sda(ops->data, val)` 通過(guò)操作符指針調(diào)用底層接口,
2. `set_sda` 調(diào)用 `rt_pin_write`
3. `rt_pin_write` 通過(guò) pin 設(shè)備執(zhí)行 `_hw_pin.ops->pin_write` 調(diào)用的 pin 底層接口
4. 在 stm32 平臺(tái)上 `_hw_pin.ops->pin_write` 等于調(diào)用 `stm32_pin_write` 函數(shù)
5. `stm32_pin_write` 調(diào)用 `HAL_GPIO_WritePin`
6. `HAL_GPIO_WritePin` 函數(shù)寫寄存器。

彎彎繞繞,想控制 pin 引腳電平變化還真是煞費(fèi)苦心了。

可以壓縮上述調(diào)用過(guò)程嗎?
`SDA_L` 宏直接定義調(diào)用 `stm32_pin_write` ,`stm32_pin_write` 內(nèi)部直接操作寄存器。

soft iic 驅(qū)動(dòng)

軟件模擬 iic 驅(qū)動(dòng)需要軟件代碼控制 SCL SDA 兩根線時(shí)序,如前所述,拉低 SDA 線的過(guò)程被繁冗化了。

裸機(jī)能達(dá)到的 iic 時(shí)鐘速度,在使用 rt-thread 的模擬 iic 時(shí)根本達(dá)不到,在多級(jí)指針和函數(shù)調(diào)用過(guò)程中,效率被極大降低了。

有沒(méi)有一種策略,使 `SDA_L` 宏直接定義成 `stm32_pin_write` 或者 `gd32_pin_write` 等等。

筆者嘗試把 i2c-bit-ops.c 文件和 drv_soft_i2c.c 兩個(gè)文件進(jìn)行合并,省掉了一級(jí) `struct rt_i2c_bit_ops`,然后 `SDA_L` 也不使用 `rt_pin_write` 又跳過(guò)了多次指針調(diào)用。目前感覺(jué)良好。

GET_PIN

有哪位能告訴大家, `rt_pin_write(17, PIN_HIGH)` 這句代碼有明確的語(yǔ)義嗎?

函數(shù)調(diào)用中的第一個(gè)參數(shù)值 “17” 表示了什么?
可能啥也不代表。
首先,它肯定不是芯片引腳編號(hào)。
大多數(shù)芯片,GPIO 編碼采用的類似如下方式:
- 以端口編碼,一顆芯片上的 GPIO 可以分成若干個(gè)端口,用字母 A B C ... 命名(也有 1 2 3 編號(hào)命名的,比如 RA6M4)。我們稱之為 PA PB PC ...
- 每個(gè)端口有8/16個(gè) io 。分別編碼 0-7 或者 0-15。有些芯片上的某個(gè)端口只有 15 個(gè) io ,那就只有 0-14 有效。我們稱之為 PA0 PA15

為了不使用魔數(shù) “17” ,這種模棱兩可,含義不明的寫法,rt-thread 針對(duì)每種芯片要求定義一個(gè) `GET_PIN` 宏,它可以從一種直觀的引腳編號(hào)寫法中返回一個(gè)數(shù)字。比如 `GET_PIN(G, 1)` 的結(jié)果是 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 兩個(gè)引腳號(hào)的時(shí)候。它只支持輸入數(shù)字,這個(gè)時(shí)候我們必須知道 `GET_PIN` 的數(shù)學(xué)含義,心算把 `GET_PIN(B, 1)` 轉(zhuǎn)成 17 。

`GET_PIN` 的數(shù)學(xué)含義是確定的嗎?是放之四海而皆準(zhǔn)的嗎?在每一款芯片上可以使用同一個(gè)數(shù)學(xué)公式演算嗎?

**這個(gè)可以是,但實(shí)際卻不是**。

另類的 AB32 RA6M4 N32

我們?nèi)匀灰?17 這個(gè)編號(hào)為例,下面來(lái)看看 AB32 RA6M4 上面它分別代表哪個(gè) GPIO 。

AB32 上應(yīng)該是 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

幾個(gè)端口不通用,各自為戰(zhàn)

RA6M4 上不存在。因?yàn)?RA6M4 的 P100 對(duì)應(yīng)的是 256 ;P015 對(duì)應(yīng)的是 15 。沒(méi)有 17 這個(gè)編號(hào)。
AB32 版 `GET_PIN` 未實(shí)現(xiàn)。

還有 N32,上面筆者說(shuō)了句“它肯定不是芯片引腳編號(hào)”。但是,我又發(fā)現(xiàn)在 N32 的drv_gpio.c 中,定義成了芯片引腳號(hào)。打臉了...
N32 版 `GET_PIN` 也未實(shí)現(xiàn)。

還有其它芯片是上述三種情況之外的嗎?歡迎大家講出來(lái)。

明確的應(yīng)用層語(yǔ)義

不失一般性,假設(shè)可能存在某芯片端口編號(hào)不是連續(xù)的,中間缺失端口B。同時(shí)端口 A 也只有 12 個(gè) io。我們把所有的端口和 io 進(jìn)行排序編號(hào)。PA0 是 0 號(hào)、PA1 是 1 號(hào) ... PA11 是 11 號(hào)。那么,PC0 編號(hào)是多少?12嗎?

假如有一同系列芯片,它是有端口 B 的。那么 PB0 編號(hào)該定義成多少合適呢?也是 12 嗎?

> 或者,干脆我們就假定所有的芯片端口都是連續(xù)無(wú)缺失的,每個(gè)端口也是滿滿當(dāng)當(dāng) 16 個(gè) io 。這樣 PB0 總是 16,PC0 總是 32。

從理論上講,所有的芯片 gpio 編號(hào)系統(tǒng)是可以用一個(gè)公式實(shí)現(xiàn)的,這個(gè)公式可以在 rt-thread 使用寶典(2022-0516更新)中找到。

RA6M4 上,應(yīng)用程序?qū)涌梢允褂?17 表示 P101,因?yàn)樗亩丝诰幪?hào)從 0 開(kāi)始;
N32 上,應(yīng)用程序?qū)涌梢允褂?17 表示 PB01,因?yàn)樗亩丝诰幪?hào)從 A 開(kāi)始;
STM32 上,應(yīng)用程序?qū)涌梢允褂?17 表示 PB01,因?yàn)樗亩丝诰幪?hào)從 A 開(kāi)始;
AB32 上,應(yīng)用程序?qū)涌梢允褂?17 表示 PB01,因?yàn)樗亩丝诰幪?hào)從 A 開(kāi)始

無(wú)論用的哪家芯片,無(wú)論是哪個(gè)系列芯片,無(wú)論是哪款型號(hào),它有多少引腳。我們希望 17 這個(gè)值能對(duì)應(yīng)一個(gè)明確的引腳名。不會(huì)因?yàn)槟诚盗行酒心匙有吞?hào)因?yàn)槠渲心硞€(gè)端口 io 數(shù)量少一個(gè)導(dǎo)致后面所有 io 的編號(hào)都變了。又或者同樣的 PB01 在不同子型號(hào)不同封裝下的編號(hào)也不一樣。

結(jié)束語(yǔ)

大家有什么意見(jiàn)和想法,一塊兒聊聊啊。

> 把不同芯片的差異性進(jìn)行封裝,提供給應(yīng)用層語(yǔ)義明確的接口,是一個(gè)操作系統(tǒng)的職責(zé)之一。
復(fù)雜事情簡(jiǎn)單化,簡(jiǎn)單的事情保留那一點(diǎn)兒純粹。這也是封裝的基本原則。
寫應(yīng)用程序代碼時(shí),我們不想關(guān)心底層的實(shí)現(xiàn),這是另一個(gè)操作系統(tǒng)的職責(zé)之一。

審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • GPIO
    +關(guān)注

    關(guān)注

    16

    文章

    1189

    瀏覽量

    51837
  • PIN
    PIN
    +關(guān)注

    關(guān)注

    1

    文章

    303

    瀏覽量

    24174
  • RT-Thread
    +關(guān)注

    關(guān)注

    31

    文章

    1261

    瀏覽量

    39839
  • 驅(qū)動(dòng)框架
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    4020
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    RT-Thread NUC97x 移植 LVGL

    不涉及 rt-thread 驅(qū)動(dòng),但是它是 LVGL 和 rt-thread 的接口。LVGL 在 rt-thread 上運(yùn)行的基石。
    發(fā)表于 07-08 09:37 ?1460次閱讀

    基于RT-Thread的SPI通訊

    驅(qū)動(dòng)層的驅(qū)動(dòng)。(rt-thread的設(shè)備 I/O 模型有設(shè)備管理層、設(shè)備驅(qū)動(dòng)框架層、設(shè)備驅(qū)動(dòng)層),我寫過(guò)一
    的頭像 發(fā)表于 08-22 09:28 ?1632次閱讀

    RT-Thread ssd1306驅(qū)動(dòng)

    RT-Thread 驅(qū)動(dòng)ssd1306
    的頭像 發(fā)表于 04-21 10:08 ?26.4w次閱讀
    <b class='flag-5'>RT-Thread</b> ssd1306<b class='flag-5'>驅(qū)動(dòng)</b>

    【靈動(dòng)微】FTHR-G0140開(kāi)發(fā)板移植RT-Thread驅(qū)動(dòng)

    靈動(dòng)微G0140移植RT-Thread驅(qū)動(dòng)
    的頭像 發(fā)表于 06-05 13:45 ?21.7w次閱讀
    【靈動(dòng)微】FTHR-G0140開(kāi)發(fā)板移植<b class='flag-5'>RT-Thread</b><b class='flag-5'>驅(qū)動(dòng)</b>

    RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南基礎(chǔ)—以先楫bsp的hwtimer設(shè)備為例

    RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南》書籍是RT-thread官方出品撰寫,系統(tǒng)講解RT-thread IO設(shè)備驅(qū)動(dòng)開(kāi)發(fā)方法,從三方面進(jìn)行講解
    的頭像 發(fā)表于 02-20 16:01 ?1564次閱讀
    <b class='flag-5'>RT-Thread</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)指南基礎(chǔ)<b class='flag-5'>篇</b>—以先楫bsp的hwtimer設(shè)備為例

    RT-Thread驅(qū)動(dòng)開(kāi)發(fā)指南進(jìn)階-動(dòng)手驅(qū)動(dòng)先楫未適配的外設(shè)LCD

    經(jīng)過(guò)上一的《《RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南》基礎(chǔ)--以先楫bsp的hwtimer設(shè)備為例》闡述,可以大致了解到RT-thread設(shè)
    的頭像 發(fā)表于 02-25 11:04 ?2234次閱讀
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)指南進(jìn)階<b class='flag-5'>篇</b>-動(dòng)手<b class='flag-5'>驅(qū)動(dòng)</b>先楫未適配的外設(shè)LCD

    【原創(chuàng)精選】RT-Thread征文精選技術(shù)文章合集

    rt-thread 驅(qū)動(dòng)(六)serialX弊端及解決方法rt-thread 驅(qū)動(dòng)
    發(fā)表于 07-26 14:56

    RT-Thread上的CAN總線介紹以及驅(qū)動(dòng)編寫

    昨晚很榮幸邀請(qǐng)到李工在RT-Thread微信群進(jìn)行RT-Thread上的CAN驅(qū)動(dòng)和應(yīng)用講座。小編整理了講座內(nèi)容,特發(fā)出講義以供享用。
    的頭像 發(fā)表于 09-25 10:16 ?2.4w次閱讀

    簡(jiǎn)要分析Thread的通用GPIO設(shè)備驅(qū)動(dòng)

    為了給用戶提供操作GPIO的通用API,方便應(yīng)用程序開(kāi)發(fā),RT-Thread中引入了通用GPIO設(shè)備驅(qū)動(dòng)。并提供類似Arduino風(fēng)格的API用于操作
    發(fā)表于 11-13 14:57 ?1465次閱讀

    RT-Thread Studio驅(qū)動(dòng)SD卡

    RT-Thread Studio驅(qū)動(dòng)SD卡前言一、創(chuàng)建基本工程1、創(chuàng)建Bootloader2、創(chuàng)建項(xiàng)目工程二、配置RT-Thread Settings三、代碼分析1.引入庫(kù)2.讀入數(shù)據(jù)四、效果驗(yàn)證
    發(fā)表于 12-27 19:13 ?20次下載
    <b class='flag-5'>RT-Thread</b> Studio<b class='flag-5'>驅(qū)動(dòng)</b>SD卡

    RT-Thread開(kāi)源作品秀】基于RT-Thread的星務(wù)平臺(tái)研究

    本作品為了驗(yàn)證星務(wù)軟件在RT-Thread系統(tǒng)運(yùn)行的可行性,底層是否能夠驅(qū)動(dòng)星務(wù)軟件,同時(shí)擴(kuò)展RT-Thread應(yīng)用范圍。ART-Pi作為衛(wèi)星下位機(jī),...
    發(fā)表于 01-25 18:26 ?6次下載
    【<b class='flag-5'>RT-Thread</b>開(kāi)源作品秀】基于<b class='flag-5'>RT-Thread</b>的星務(wù)平臺(tái)研究

    RT-Thread文檔_RT-Thread 簡(jiǎn)介

    RT-Thread文檔_RT-Thread 簡(jiǎn)介
    發(fā)表于 02-22 18:22 ?5次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> 簡(jiǎn)介

    RT-Thread文檔_RT-Thread SMP 介紹與移植

    RT-Thread文檔_RT-Thread SMP 介紹與移植
    發(fā)表于 02-22 18:31 ?9次下載
    <b class='flag-5'>RT-Thread</b>文檔_<b class='flag-5'>RT-Thread</b> SMP 介紹與移植

    RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南》基礎(chǔ)--以先楫bsp的hwtimer設(shè)備為例

    一、概述(一)RT-Thread設(shè)備驅(qū)動(dòng)RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南》書籍是RT-thread官方出品撰寫,系統(tǒng)講解
    的頭像 發(fā)表于 02-24 08:16 ?1314次閱讀
    《<b class='flag-5'>RT-Thread</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)指南》基礎(chǔ)<b class='flag-5'>篇</b>--以先楫bsp的hwtimer設(shè)備為例

    【好書推薦】RT-Thread設(shè)備驅(qū)動(dòng)開(kāi)發(fā)指南

    近年來(lái)國(guó)內(nèi)芯片產(chǎn)業(yè)和物聯(lián)網(wǎng)產(chǎn)業(yè)的快速崛起,行業(yè)發(fā)展迫切需要更多人才,尤其需要掌握嵌入式操作系統(tǒng)等底層技術(shù)的人才。隨著RT-Thread被更廣泛地應(yīng)用于行業(yè)中,開(kāi)發(fā)者對(duì)嵌入式驅(qū)動(dòng)開(kāi)發(fā)的需求越來(lái)越
    的頭像 發(fā)表于 08-01 08:35 ?484次閱讀
    【好書推薦】<b class='flag-5'>RT-Thread</b>設(shè)備<b class='flag-5'>驅(qū)動(dòng)</b>開(kāi)發(fā)指南