RTT(RT-Thread)IO設備模型

目錄

IO設備模型

模型框架原理

IO設備類型

創建和注冊IO設備

RTT設備管理程序實現原理

訪問IO設備

查找設備

初始化設備

打開設備

關閉設備

?控制設備

?讀寫設備

數據收發回調

數據接收回調

數據發送回調

設備模型實例


IO設備模型

????????RT-Thread 提供了一套簡單的 I/O 設備模型框架,如下圖所示,它位于硬件和應用程序之間,共分成三層,從上到下分別是 I/O 設備管理層、設備驅動框架層、設備驅動層。

  • 應用程序通過 I/O 設備管理接口獲得正確的設備驅動,然后通過這個設備驅動與底層 I/O 硬件設備進行交互。
  • I/O 設備管理層實現了對設備驅動程序的封裝
  • 設備驅動框架層是對同類硬件設備驅動的抽象,將不同廠家的同類硬件設備驅動中相同的部分抽取出來,將不同部分留出接口,由驅動程序實現。
  • 設備驅動層是一組驅使硬件設備工作的程序,實現訪問硬件設備的功能。

簡單設備的注冊不經過設備驅動框架層,直接將設備注冊到I/O設備管理器中

  • 設備驅動根據設備模型定義,創建出具備硬件訪問能力的設備實例,將該設備通過rt_device_register()接口注冊到 I/O 設備管理器中
  • 應用程序通過 rt_device_find()接口查找到設備,然后使用 I/O 設備管理接口來訪問硬件

模型框架原理

圖中:在左邊是應用層代碼,在右邊是設備驅動代碼,設備驅動層是與硬件最接近的(用于直接訪問硬件)。而設備驅動和應用程序通過同一的IO設備管理器來統一管理起來。

如何去管理呢?設備驅動在要操作硬件的時候,要向IO設備管理器去注冊,一旦注冊完之后,設備管理器就知道了哪個設備的驅動注冊到系統里面了。當注冊成功以后,當應用層想要訪問硬件的時候,通過調用rt_device_find函數來找到相應的設備驅動,一旦找到以后,就可以打開設備,接著進行讀寫操作,最后要記得關閉設備。

應用層想要去訪問硬件的時候,只需要查找到相應的設備驅動,然后調用統一的接口就能對硬件設備進行操作,不需要關注硬件的實現原理。而對應硬件驅動來講,我們只需要提供對硬件的訪問方法。具體如何去訪問,以及訪問到的數據如何去處理也跟設備驅動沒有關系。也就是說將不同的事情交給不同的層去完成,實現解耦(高內聚、低耦合)

對于一些復雜設備,需要使用到對應的設備驅動框架層,進行注冊,它們擁有自己專屬的注冊函數 如:看門狗定時器

  • 看門狗設備驅動程序根據看門狗設備模型定義,創建出具備硬件訪問能力的看門狗設備實例,并將該看門狗設備通過特定的函數 rt_hw_watchdog_register()接口注冊到看門狗設備驅動框架中
  • 看門狗設備驅動框架通過 rt_device_register()接口將看門狗設備注冊到 I/O 設備管理器中
  • 應用程序通過 I/O 設備管理接口來訪問看門狗設備硬件

IO設備類型

  • RT-Thread 支持多種 I/O 設備類型,主要設備類型如下所示

RT_Device_Class_Char = 0, /**< character device */

RT_Device_Class_Block, /**< block device */

RT_Device_Class_NetIf, /**< net interface */

RT_Device_Class_MTD, /**< memory device */

RT_Device_Class_CAN, /**< CAN device */

RT_Device_Class_RTC, /**< RTC device */

RT_Device_Class_Sound, /**< Sound device */

RT_Device_Class_Graphic, /**< Graphic device */

RT_Device_Class_I2CBUS, /**< I2C bus device */

RT_Device_Class_USBDevice, /**< USB slave device */

RT_Device_Class_USBHost, /**< USB host bus */

RT_Device_Class_SPIBUS, /**< SPI bus device */

RT_Device_Class_SPIDevice, /**< SPI device */

RT_Device_Class_SDIO, /**< SDIO bus device */

RT_Device_Class_Timer, /**< Timer device */

RT_Device_Class_Miscellaneous, /**< misc device */

RT_Device_Class_Sensor, /**< Sensor device */

RT_Device_Class_Touch, /**< Touch device */

RT_Device_Class_Unknown /**< unknown device */

創建和注冊IO設備

  • 驅動層負責創建設備實例,并注冊到 I/O 設備管理器中
/*** This function creates a device object with user data size.** @param type, the kind type of this device object.* @param attach_size, the size of user data.** @return the allocated device object, or RT_NULL when failed.*/
rt_device_t rt_device_create(int type, int attach_size)
  • 當一個動態創建的設備不再需要使用時可以通過如下函數來銷毀
/*** This function destroy the specific device object.** @param dev, the specific device object.*/
void rt_device_destroy(rt_device_t dev)
  • 設備被創建后,需要實現它訪問硬件的操作方法
struct rt_device_ops
{/* common device interface */rt_err_t  (*init)   (rt_device_t dev);rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);rt_err_t  (*close)  (rt_device_t dev);rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
};
  • 設備被創建后,需要注冊到 I/O 設備管理器中,應用程序才能夠訪問
/*** This function registers a device driver withspecified name.** @param dev the pointer of device driverstructure* @param name the device driver's name* @param flags the capabilities flag ofdevice   設備模式標志** @return the error code, RT_EOK oninitialization successfully.*/
rt_err_t rt_device_register(rt_device_t dev,const char *name,rt_uint16_t flags)#define RT_DEVICE_FLAG_RDONLY 0x001/*只讀*/
#define RT_DEVICE_FLAG_WRONLY 0x002/*只寫*/
#define RT_DEVICE_FLAG_RDWR 0x003 /*讀寫*/
#define RT_DEVICE_FLAG_REMOVABLE0x004 /*可移除*/
#define RT_DEVICE_FLAG_STANDALONE0x008 /*獨立*/
#define RT_DEVICE_FLAG_SUSPENDED0x020 /*掛起*/
#define RT_DEVICE_FLAG_STREAM 0x040/*流模式*/
#define RT_DEVICE_FLAG_INT_RX 0x100/*中斷接收*/
#define RT_DEVICE_FLAG_DMA_RX 0x200/*DMA接收*/
#define RT_DEVICE_FLAG_INT_TX 0x400/*中斷發送*/
#define RT_DEVICE_FLAG_DMA_TX 0x800/* DMA發送*/
  • 設備注銷后的,設備將從設備管理器中移除,也就不能再通過設備查找搜索到該設備。注銷設備不會釋放設備控制塊占用的內存
/*** This function removes a previouslyregistered device driver** @param dev the pointer of device driverstructure** @return the error code, RT_EOK onsuccessfully.*/
rt_err_t rt_device_unregister(rt_device_t dev)

RTT設備管理程序實現原理

當我們創建一個設備的時候,系統會使用一個結構體描述這個設備的所有信息。當我們創建并注冊多個設備的時候,系統就會通過列表的方式將這些結構體統一管理起來。當我們應用層想要找到某個設備的時候,就會調用find函數來找到列表頭來根據name遍歷查找,找到以后就會調用相應的方法來操作設備。當設備不用的時候,調用unregister函數來移除(將結構體變量從列表中移除),但結構體的空間依然存在,如果我們想要將結構體的空間釋放掉,就需要調用destroy函數來進行刪除釋放。

訪問IO設備

應用程序通過 I/O 設備管理接口來訪問硬件設備,當設備驅動實現后,應用程序就可以訪問該硬件,I/O 設備管理接口與 I/O 設備的操作方法的映射關系下圖所示

相應接口函數在設備句柄結構體中

使用應用層接口前,首先要查找到設備

查找設備

返回值為設備句柄指針

/*** This function finds a device driver byspecified name.** @param name the device driver's name** @return the registered device driver onsuccessful, or RT_NULL on failure.*/
rt_device_t rt_device_find(const char*name)

操作接口如下:

初始化設備

/*** This function will initialize the specified device** @param dev the pointer of device driver structure** @return the result*/
rt_err_t rt_device_init(rt_device_t dev)

打開設備

/*** This function will open a device** @param dev the pointer of device driver structure* @param oflag the flags for device open** @return the result*/
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflag)

注:RT_DEVICE_FLAG_STREAM:流模式用于向串口終端輸出字符串:當輸出的字符是 "\n"(對應 16 進制值為 0x0A)時,自動在前面輸出一個 "\r"(對應 16 進制值為 0x0D)做分行。

流模式 RT_DEVICE_FLAG_STREAM 可以和接收發送模式參數使用或 “|” 運算符一起使用

關閉設備

/*** This function will close a device** @param dev the pointer of device driver structure** @return the result*/
rt_err_t rt_device_close(rt_device_t dev)

?控制設備

/*** This function will perform a variety of control functions on devices.** @param dev the pointer of device driver structure* @param cmd the command sent to device* @param arg the argument of command** @return the result*/
rt_err_t rt_device_control(rt_device_t dev, int cmd, void *arg)

?讀寫設備

/*** This function will read some data from adevice.** @param dev the pointer of device driverstructure* @param pos the position of reading* @param buffer the data buffer to save read data* @param size the size of buffer** @return the actually read size onsuccessful, otherwise negative returned.** @note since 0.4.0, the unit of size/pos is ablock for block device.*/
rt_size_t rt_device_read(rt_device_tdev,rt_off_t    pos,void       *buffer,rt_size_t   size)
/*** This function will write some data to adevice.** @param dev the pointer of device driverstructure* @param pos the position of written* @param buffer the data buffer to be writtento device* @param size the size of buffer** @return the actually written size onsuccessful, otherwise negative returned.** @note since 0.4.0, the unit of size/pos is ablock for block device.*/
rt_size_trt_device_write(rt_device_t dev,rt_off_t    pos,const void *buffer,rt_size_t   size)

數據收發回調

當硬件設備收到數據時,可以通過如下函數回調另一個函數來設置數據接收指示,通知上層應用線程有數據到達

原理:通過設置數據的收發回調來通知我們的應用層某個線程來接收數據。這樣就不需要再接收數據的時候寫一個while循環一直去讀。讓它在沒有數據的時候去休眠阻塞,一旦有數據的時候,這個函數就會被回調去通知相應線程喚醒去讀寫,這樣可以減少系統的調用,提高系統調用效率。

數據接收回調

/*** This function will set the receptionindication callback function. * This callback function* is invoked when this device receives data.** @param dev the pointer of device driverstructure* @param rx_ind the indication callbackfunction** @return RT_EOK*/
rt_err_t
rt_device_set_rx_indicate(rt_device_tdev,rt_err_t (*rx_ind)(rt_device_t dev, rt_size_t size))

數據發送回調

/*** This function will set the indicationcallback function when device has* written data to physical hardware.** @param dev the pointer of device driverstructure* @param tx_done the indication callbackfunction** @return RT_EOK*/
rt_err_t
rt_device_set_tx_complete(rt_device_tdev,rt_err_t (*tx_done)(rt_device_t dev,void *buffer))

設備模型實例

(1)首先在drivers下創建一個drv_demo.c的驅動文件

(2)然后刷新工程目錄,打開drv_demo.c

(3)我們可以參考drv_wdt.c的設備驅動模型來寫

在文件最后我們可以發現有一個板級初始化的導出函數:我們使用INIT_BOARD_EXPORT宏將rt_wdt_init函數導出,那么在板級初始化的時候就會調用rt_wdt_init函數

我們再drv_demo.c中導出自己的設備初始化函數,并編寫設備初始化函數

(4)接著我們創建設備,使用rt_device_create函數

第一個參數是設備類型,這里用字符設備

第二個參數是用戶的數據大小,如果要傳入用戶數據的話,我們就根據用戶數據的大小來傳參。因為我們不需要傳入用戶數據,因此大小可以隨便寫一個,如32。

返回值為指針類型rt_device_t

(5)設備創建成功以后,我們需要對設備編寫相應的接口函數,我們以init、open、close為例

我們可以按F3跳轉到rt_device_t中,并將相應接口函數指針復制到我們自己的設備驅動文件下

(6)將函數進行簡單完善

并對接口進行賦值

(7)然后我們以讀寫的方式注冊我們的設備模型

(8)最后我們在main函數中使用,首先查找設備,如果查找成功,返回一個設備對象指針,如果查找失敗,我們返回錯誤:變量無效

然后調用相應的應用層接口函數

(10)編譯之后發現有一個警告LOG_E未定義

我們需要將添加調試頭文件#include

(11)運行結果

通過列舉設備,可以查看到demo是我們自己創建的設備;uart2是用來監控當前STM32單片機的,用作用戶的調試接口;pin是GPIO引腳。(其中要注意串口也是屬于字符設備類型的)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/35483.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35483.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35483.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡編程(TFTP協議實驗)

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <head.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h>#define PORT 69 //端口號&#xf…

網絡安全威脅與防御策略

第一章&#xff1a;引言 隨著數字化時代的快速發展&#xff0c;網絡已經成為人們生活和工作中不可或缺的一部分。然而&#xff0c;網絡的廣泛應用也引發了一系列嚴峻的網絡安全威脅。惡意軟件、網絡攻擊、數據泄露等問題層出不窮&#xff0c;給個人和企業帶來了巨大的風險。本文…

mysql基礎之觸發器的簡單使用

1.建立學生信息表 -- 觸發器 -- 建立學生信息表 create table s1(id int unsigned auto_increment,name varchar(30),score tinyint unsigned,dept varchar(50),primary key(id) );2.建立學生補考信息表 -- 建立學生補考信息表 create table s2 like s1;3.建立觸發器&#xf…

java 自定義xss校驗注解實現

自定義一個注解Xss。名字隨意 import javax.validation.Constraint; import javax.validation.Payload; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Targe…

深入理解與運用Android Jetpack ViewModel

在Android開發中&#xff0c;數據與界面的分離一直是一項重要的挑戰。為了解決這個問題&#xff0c;Google推出了Android Jetpack組件之一的ViewModel。ViewModel是一種用于管理UI相關數據的架構組件&#xff0c;它能夠幫助開發者實現優雅的數據驅動和生命周期管理。本文將深入…

C字符串練習題(6.3.1)

編寫一個程序&#xff0c;從鍵盤上讀入一個小于1000的正整數&#xff0c;然后創建并輸出一個字符串&#xff0c;說明該整數的值。例如&#xff0c;輸入941&#xff0c;程序產生的字符串是“Nine hundred and forty one”。 #include<stdlib.h> #include<string.h>…

前端HTML入門基礎

階段目標&#xff1a;掌握HTML、CSS常用布局技巧&#xff0c;能夠獨立制作網頁。 day01&#xff1a;HTML 基礎 目標&#xff1a;掌握標簽基本語法&#xff0c;能夠獨立布局文章頁。 01-今日課程介紹 今日目標&#xff1a;掌握標簽基本語法&#xff0c;能夠獨立布局文章頁。 核心…

SQL中CONVERT函數格式:CONVERT(data_type,expression[,style])

sqlserver convert()函數的使用方法_convert sqlserver_qq_37528515的博客-CSDN博客 SQL中CONVERT函數格式:CONVERT(data_type,expression[,style]) 說明&#xff1a; data_type:目標系統所提供的數據類型&#xff0c;如果轉換時沒有指定數據類型的長度&#xff0c;則 SQL Serv…

Maven基礎總結

前言 Maven 是一個項目管理工具&#xff0c;可以對 Java 項目進行構建、依賴管理。 基本要求掌握 配置Maven環境直接查。 得會在IDEA創建Maven的java項目吧、會創建Maven的web項目吧、會創建多模塊項目吧。 得會配置插件pligin、依賴dependency吧 一、Maven四大特性 1、…

CSS:服務器字體 與 響應式布局(用法 + 例子 + 效果)

文章目錄 服務器字體定義 服務器字體使用例子 響應式布局設備類型設備特性例子 服務器字體 解決字體不一致而產生的。 首先&#xff0c;在網上把字體下載好。 定義 服務器字體 font-face{font-family:字體名稱;src:url(字體資源路徑); }使用 在需要使用的選擇器里加上 font…

數學建模(一)前繼概念

課程推薦&#xff1a;數學建模老哥_嗶哩嗶哩_bilibili 目錄 一、什么是數學建模&#xff1f; 二、數學建模的一般步驟 三、數學建模賽題類型 1.預測型 2. 評價類 3.機理分析類 4. 優化類 一、什么是數學建模&#xff1f; 數學建模是利用數學方法解決實際問題的一種實踐。…

什么是多線程?進程和線程的區別是什么?如何使用Java實現多線程?

文章目錄 前言我們為什么要使用線程而不是進程來實現并發編程什么是線程進程和線程的區別如何使用Java實現多線程創建線程1.創建一個繼承 Thread 類的線程類2.實現 Runnable 接口匿名內部類方式實現 Runnable 接口lambda 表達式實現 Runnable 接口 Thread 類的常見構造方法Thre…

T113-S3-RTL8211網口phy芯片調試

目錄 前言 一、RTL8211介紹 二、硬件連接 三、設備樹配置 四、內核配置 五、phy芯片配置 六、調試問題 總結 前言 在嵌入式系統開發中&#xff0c;網絡連接是至關重要的一部分。T113-S3開發板搭載了RTL8211系列的網口PHY芯片&#xff0c;用于實現以太網連接。在開發過程…

C++ QT(二)

目錄 Qt 控件按鈕QPushButton控件簡介用法示例運行效果 QToolButton控件簡介用法示例運行效果 QRadioButton控件簡介用法示例運行效果 QCheckBox控件簡介用法示例運行效果 QCommandLinkButton控件簡介用法示例運行效果 QDialogButtonBox控件簡介用法示例運行效果 輸入窗口部件Q…

用 React+ts 實現無縫滾動的走馬燈

一、走馬燈的作用 走馬燈是一種常見的網頁交互組件&#xff0c;可以展示多張圖片或者內容&#xff0c;通過自動播放或者手動切換的方式&#xff0c;讓用戶能夠方便地瀏覽多張圖片或者內容。 本次實現的不是輪播圖而是像傳送帶一樣的無限滾動的形式。 二、需求梳理 走馬燈可設…

Go Gin 中使用 JWT

一、JWT JWT全稱JSON Web Token是一種跨域認證解決方案&#xff0c;屬于一個開放的標準&#xff0c;它規定了一種Token實現方式&#xff0c;目前多用于前后端分離項目和OAuth2.0業務場景下。 二、為什么要用在你的Gin中使用JWT 傳統的Cookie-Sesson模式占用服務器內存, 拓展性…

uniapp實現自定義導航內容高度居中(兼容APP端以及小程序端與膠囊對齊)

①效果圖如下 1.小程序端與膠囊對齊 2.APP端內容區域居中 注意&#xff1a;上面使用的是colorui里面的自定義導航樣式。 ②思路&#xff1a; 1.APP端和小程序端走不同的方法&#xff0c;因為小程序端要計算不同屏幕下右側膠囊的高度。 2.其次最重要的要清晰App端和小程序端…

【數學建模】清風數模更新5 灰色關聯分析

灰色關聯分析綜述 諸如經濟系統、生態系統、社會系統等抽象系統都包含許多因素&#xff0c;系統整體的發展受各個因素共同影響。 為了更好地推動系統發展&#xff0c;我們需要清楚哪些因素是主要的&#xff0c;哪些是次要的&#xff0c;哪些是積極的&#xff0c;哪些是消極的…

網絡基礎——網絡的由來與發展史

作者&#xff1a;Insist-- 個人主頁&#xff1a;insist--個人主頁 作者會持續更新網絡知識和python基礎知識&#xff0c;期待你的關注 目錄 一、網絡的由來 二、計算機網絡的發展史 1、第一階段 2、第二階段 3、第三階段 前言 每天都是使用網絡&#xff0c;那么你知道網絡…

FPGA----Vivado SDK創建并使用靜態鏈接庫(C/C++代碼移植)

1、在進行SoC開發時&#xff0c;PS端的C/C代碼可能涉及到核心算法需要移植操作&#xff0c;為此&#xff0c;本文講述了如何將C/C代碼打包為.a文件供程序調用 2、文章以我的程序為例&#xff0c;逐步講述代碼生成靜態鏈接庫并調用的方法。 下面是我程序的目錄結構&#xff0c…