RT-Thread Pin 設備驅動框架快速對接

爲什麼需要 Pin 設備驅動框架

  • 跨平臺可移植應用
  • 操作簡單

試想下面這個場景:
你基於 STM32 MCU 編寫了一個包含很多 GPIO 操作的應用程序,GPIO 控制函數使用的是 HAL 庫。
後面,由於某種原因,MCU 需要更換,使用的是 NXP 的芯片,不支持 HAL 庫,那你怎麼辦?

通常,你會查找所有 GPIO 操作相關的接口,然後替換成 NXP 提供的 GPIO 驅動函數,如果 GPIO 的編排方式不一樣(有的有 GPIOA 這樣的分組,有的沒有),那就更加的麻煩。這樣,你就維護了兩個版本的應用程序。

那麼,有了 Pin 驅動框架能解決這個問題嗎?
當然,Pin 只能解決應用層代碼不需要變動的問題,但需要將 GPIO 驅動對接到 Pin 驅動框架上。
另外,RT-Thread Pin 設備驅動框架採用了統一 GPIO 號編排的方式,從 0 開始向上計數,每一個 GPIO 對應一個 pin 號。這樣做的好處是,應用程序無需關心該 GPIO 屬於哪一個組(GPIOA,還是 GPIOB),也無需關心相關 GPIO 的時鐘初始化、中斷等。因爲,Pin 設備驅動框架都幫你抽象好了。

在這裏插入圖片描述

怎麼對接到 Pin 設備框架

首先了解下文件結構

PIN 設備框架對應文件:

  • pin.h
  • pin.c
    源文件路徑: components/drivers/misc/pin.c

對接到 PIN 設備框架的驅動代碼需要我們自行實現(如果官方沒有現成的 BSP 可以使用),爲了保持驅動實現的一致性,這裏有一些潛在規則:

  • RT-Thread 通常將對接設備框架的驅動相關文件存放在對應 bsp 的 drivers 目錄下
  • 驅動程序文件命名採用 drv_ 前綴加驅動名稱的方式

當然,並不是所有的 BSP 對接 rt-thread 設備框架的驅動程序文件都存放在 drivers 目錄下,如 STM32 新 BSP 中的驅動實現在 rt-thread/bsp/stm32/libraries/HAL_Drivers 目錄下。

由此,本次我們需要實現的 GPIO 驅動如下:

GPIO 驅動對應文件:

  • drv_gpio.h
  • drv_gpio.c

PIN 驅動框架和 GPIO 驅動對接

在這裏插入圖片描述
從上圖可以直觀地看到 Pin 設備驅動框架和 GPIO 驅動是如果對接到一起的。
如上圖所示:

  • 左側爲 Pin 設備驅動框架封裝的 API 接口,向上提供給應用層使用;
  • 右側爲具體芯片平臺對接 Pin 設備的驅動程序,與 Pin 設備框架提供的 API 接口一一對應,通過 rt_pin_ops 結構體關聯到一起,驅動框架層接口最終會回調驅動層接口;
  • 最後通過 rt_device_pin_register 函數接口,將底層驅動與 Pin 設備框架綁定到一起,註冊到 RT-Thread 的設備框架中。

在對接 RT-Thread Pin 設備框架的時候,僅需要實現上圖右側 rt_pin_ops 結構體中的所有 callback 回調函數即可,然後通過 rt_device_pin_register 註冊到系統,最後使用 rt_hw_pin_init 調用以進行初始化。
rt_hw_pin_init 在系統啓動過程中被 rt_hw_board_init 調用。

注意:
需要注意的是 rt_pin_attach_irq 接口的使用,其函數原型如下:

rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
                             void (*hdr)(void *args), void  *args)

該函數的功能是,爲指定的 pin 腳綁定中斷回調函數 hdr,並設置對應的中斷模式 mode 。該函數是唯一的從應用層,通過 Pin 設備框架向下註冊到 GPIO 驅動層的 API 接口。
用戶在實現 rt_pin_attach_irq 對應的 pin_attach_irq 回調函數時,記得將 hdr 回調函數應用到對應 pin 腳的外部中斷 Handler 中。

如何使用

RT-Thread 官方的文檔中心中 Pin 設備給出了一個基本的測試例程,這裏做引用,如下所示:

以下內容引用自 RT-Thread 文檔中心,地址:https://www.rt-thread.org/document/site/programming-manual/device/pin/pin/

PIN 設備的具體使用方式可以參考如下示例代碼,示例代碼的主要步驟如下:

  • 設置蜂鳴器對應引腳爲輸出模式,並給一個默認的低電平狀態
  • 設置按鍵 0 和 按鍵1 對應引腳爲輸入模式,然後綁定中斷回調函數並使能中斷
  • 按下按鍵 0 蜂鳴器開始響,按下按鍵 1 蜂鳴器停止響

代碼如下:

/*
 * 程序清單:這是一個 PIN 設備使用例程
 * 例程導出了 pin_beep_sample 命令到控制終端
 * 命令調用格式:pin_beep_sample
 * 程序功能:通過按鍵控制蜂鳴器對應引腳的電平狀態控制蜂鳴器
*/

#include <rtthread.h>
#include <rtdevice.h>

/* 引腳編號,通過查看設備驅動文件drv_gpio.c確定 */
#ifndef BEEP_PIN_NUM
    #define BEEP_PIN_NUM            35  /* PB0 */
#endif
#ifndef KEY0_PIN_NUM
    #define KEY0_PIN_NUM            55  /* PD8 */
#endif
#ifndef KEY1_PIN_NUM
    #define KEY1_PIN_NUM            56  /* PD9 */
#endif

void beep_on(void *args)
{
    rt_kprintf("turn on beep!\n");

    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
}

void beep_off(void *args)
{
    rt_kprintf("turn off beep!\n");

    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}

static void pin_beep_sample(void)
{
    /* 蜂鳴器引腳爲輸出模式 */
    rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
    /* 默認低電平 */
    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);

    /* 按鍵0引腳爲輸入模式 */
    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    /* 綁定中斷,下降沿模式,回調函數名爲beep_on */
    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
    /* 使能中斷 */
    rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);

    /* 按鍵1引腳爲輸入模式 */
    rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    /* 綁定中斷,下降沿模式,回調函數名爲beep_off */
    rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
    /* 使能中斷 */
    rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
}
/* 導出到 msh 命令列表中 */
MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章