RT-Thread傳感器設備驅動框架介紹

2020-12-16 RTThreadIoT作業系統

背景與概述

Sensor 是物聯網重要的一部分,「Sensor 之於物聯網」相當於「眼睛之於人類」。人沒有眼睛就看不到這大千的花花世界,物聯網沒有了 Sensor 更是不能感知這變化萬千的世界。

現在,為物聯網開發的 Sensor 已經很多了,有加速度計(Accelerometer),磁力計(Magnetometer),陀螺儀(Gyroscope),光感計(Ambient light sensor),接近光(Proximity),氣壓計(Barometer/pressure),溼度計(Humidometer)等等。這些傳感器,世界上的各大半導體廠商都有出產,雖然增加了市場的可選擇性,同時也加大了應用程式開發的難度。因為不同的傳感器廠商、不同的傳感器都需要配套自己獨有的驅動才能運轉起來,這樣在開發應用程式的時候就需要針對不同的傳感器做適配,自然加大了開發難度。為了降低應用開發的難度,增加傳感器驅動的可復用性,我們設計了 Sensor 驅動框架。

Sensor 驅動框架的作用是:為上層提供統一的操作接口,提高上層代碼的可重用性;簡化底層驅動開發的難度,只要實現簡單的 ops(operations: 操作命令) 就可以將傳感器註冊到系統上。

整體框架

Sensor 驅動框架的整體架構圖如下:

sensor

它為上層提供的是標準 device 接口

open/close/read/write/control

,為底層驅動提供的是簡單的 ops 接口:

fetch_data/control

。並且框架支持 module(模塊),為底層存在耦合的傳感器設備提供服務。

工作原理

Sensor 設備其實是對標準設備

rt_device

的一個豐富,是在原有標準設備的基礎上增加了 Sensor 自己獨有的一部分

屬性

控制命令

,如下圖所示:

sensor

整個 Sensor 設備包括兩個部分:

繼承自標準設備的一些特性,包括:標準的控制接口 、回調函數device_id 等。Sensor 設備獨有的部分,包括:Sensor 的類型相關的信息特有的控制命令ops、以及一些 數據的結構sensor 的結構體

Sensor 設備的結構體如下所示:

1struct rt_sensor_device2{ 3 struct rt_device parent; /* The standard device */ 4 5 struct rt_sensor_info info; /* The sensor info data */ 6 struct rt_sensor_config config; /* The sensor config data */ 7 8 void *data_buf; /* The buf of the data received */ 9 rt_size_t data_len; /* The size of the data received */1011 const struct rt_sensor_ops *ops; /* The sensor ops */1213 struct rt_sensor_module *module; /* The sensor module */14};15typedef struct rt_sensor_device *rt_sensor_t;

Sensor 的信息

struct rt_sensor_info info 裡存儲的是一些與 Sensor 自身相關的信息,在 Sensor 設備註冊的時候提供,在使用的過程中不應修改其內容。具體成員如下所示。

1struct rt_sensor_info2{ 3 rt_uint8_t type; /* The sensor type */ 4 rt_uint8_t vendor; /* Vendor of sensors */ 5 const char *model; /* model name of sensor */ 6 rt_uint8_t unit; /* unit of measurement */ 7 rt_uint8_t intf_type; /* Communication interface type */ 8 rt_int32_t range_max; /* maximum range of this sensor's value. unit is 'unit' */ 9 rt_int32_t range_min; /* minimum range of this sensor's value. unit is 'unit' */10 rt_uint32_t period_min; /* Minimum measurement period,unit:ms. zero = not a constant rate */11 rt_uint8_t fifo_max; /* Maximum depth of fifo */12};

Sensor 的類型暫時只有以下幾種,如果有新的傳感器類型,可以提 PR 添加上。

1#define RT_SENSOR_CLASS_ACCE (1) /* Accelerometer */2#define RT_SENSOR_CLASS_GYRO (2) /* Gyroscope */ 3#define RT_SENSOR_CLASS_MAG (3) /* Magnetometer */ 4#define RT_SENSOR_CLASS_TEMP (4) /* Temperature */ 5#define RT_SENSOR_CLASS_HUMI (5) /* Relative Humidity */ 6#define RT_SENSOR_CLASS_BARO (6) /* Barometer */ 7#define RT_SENSOR_CLASS_LIGHT (7) /* Ambient light */ 8#define RT_SENSOR_CLASS_PROXIMITY (8) /* Proximity */ 9#define RT_SENSOR_CLASS_HR (9) /* Heart Rate */10#define RT_SENSOR_CLASS_TVOC (10) /* TVOC Level */11#define RT_SENSOR_CLASS_NOISE (11) /* Noise Loudness */12#define RT_SENSOR_CLASS_STEP (12) /* Step sensor */

其他的幾個成員,分別是廠商、model(如:"mpu6050")、傳感器數據的單位、通信接口類型、測量的最大範圍、測量的最小範圍、最小測量周期、硬體 FIFO 的最大深度。

Sensor 的配置

Sensor 驅動框架抽象出了一些公共的配置選項,這些可配置的選項置於

struct rt_sensor_config

裡, 成員如下:

1struct rt_sensor_config2{3 struct rt_sensor_intf intf; /* sensor interface config */4 struct rt_device_pin_mode irq_pin; /* Interrupt pin, The purpose of this pin is to notification read data */5 rt_uint8_t mode; /* sensor work mode */6 rt_uint8_t power; /* sensor power mode */7 rt_uint16_t odr; /* sensor out data rate */8 rt_int32_t range; /* sensor range of measurement */9};

這些配置項中的 intf 和 irq_pin 是為了將傳感器和硬體解耦而抽象出來的,通過在底層初始化的時候傳入

struct rt_sensor_config

這個參數,完成了通信接口的解耦。

1struct rt_sensor_intf2{3 char *dev_name; /* The name of the communication device */4 rt_uint8_t type; /* Communication interface type */5 void *user_data; /* Private data for the sensor. ex. i2c addr,spi cs,control I/O */6};

其餘的一些配置項是用 Sensor 特有控制命令控制的,如下所示:

1#define RT_SENSOR_CTRL_GET_ID (0) /* 讀設備ID */2#define RT_SENSOR_CTRL_GET_INFO (1) /* 獲取設備信息 */3#define RT_SENSOR_CTRL_SET_RANGE (2) /* 設置傳感器測量範圍 */4#define RT_SENSOR_CTRL_SET_ODR (3) /* 設置傳感器數據輸出速率,unit is HZ */5#define RT_SENSOR_CTRL_SET_MODE (4) /* 設置工作模式 */6#define RT_SENSOR_CTRL_SET_POWER (5) /* 設置電源模式 */7#define RT_SENSOR_CTRL_SELF_TEST (6) /* 自檢 */

結合 ops 中的 control 接口使用,就可以完成傳感器的配置了。

Sensor 數據的存儲

為了方便數據的解析,規定每一個類型的 Sensor 都有自己獨有的數據結構,這些成員之間使用

共用體

以減少代碼量。

1/* 3-axis Data Type */2struct sensor_3_axis 3{ 4 rt_int32_t x; 5 rt_int32_t y; 6 rt_int32_t z; 7}; 8struct rt_sensor_data 9{10 rt_uint32_t timestamp; /* The timestamp when the data was received */11 rt_uint8_t type; /* The sensor type of the data */12 union13 {14 struct sensor_3_axis acce; /* Accelerometer. unit: mG */15 struct sensor_3_axis gyro; /* Gyroscope. unit: mdps */16 struct sensor_3_axis mag; /* Magnetometer. unit: mGauss */17 rt_int32_t temp; /* Temperature. unit: dCelsius */18 rt_int32_t humi; /* Relative humidity. unit: permillage */19 rt_int32_t baro; /* Pressure. unit: pascal (Pa) */20 rt_int32_t light; /* Light. unit: lux */21 rt_int32_t proximity; /* Distance. unit: centimeters */22 rt_int32_t hr; /* Heat rate. unit: HZ */23 rt_int32_t tvoc; /* TVOC. unit: permillage */24 rt_int32_t noise; /* Noise Loudness. unit: HZ */25 rt_uint32_t step; /* Step sensor. unit: 1 */26 } data;27};

特有的 ops

ops(操作函數)包含兩個函數指針, 一個的作用是獲取傳感器數據(fetch_data),另一個的作用是通過控制命令控制傳感器(control)。

1struct rt_sensor_ops2{3 rt_size_t (*fetch_data)(struct rt_sensor_device *sensor, void *buf, rt_size_t len);4 rt_err_t (*control)(struct rt_sensor_device *sensor, int cmd, void *arg);5};

註冊方式

傳感器驅動框架提供了一個 Sensor 註冊函數,通過傳入 Sensor 的控制塊,名稱,標誌位和私有數據,就可以完成傳感器設備的註冊。

1int rt_hw_sensor_register(rt_sensor_t sensor,2 const char *name,3 rt_uint32_t flag,4 void *data);

這樣看來 Sensor 驅動框架依託於標準的設備框架,只要將傳感器驅動對接到 Sensor 的 ops 上,並通過調用

rt_hw_sensor_register

函數註冊為 Sensor 設備就可以通過標準的設備接口控制傳感器了。

module支持

module 的定義是解決底層有耦合的兩個傳感器而出現的,有些傳感器既有加速度計的功能又有陀螺儀的功能,並且他們的FIFO是共用的,在 FIFO 模式下,只能將兩個類型的傳感器的數據同時讀出,這就說明他們的數據是耦合的。

為了解決這個問題,我們定義了 module 的類型

1struct rt_sensor_module2{3 rt_mutex_t lock; /* The module lock */45 rt_sensor_t sen[RT_SENSOR_MODULE_MAX]; /* The module contains a list of sensors */6 rt_uint8_t sen_num; /* Number of sensors contained in the module */7};

裡面包含有耦合的傳感器的設備控制塊指針,通過這個功能就可以在讀取陀螺儀的數據的時候,同時更新加速度計的值,解決了底層耦合的問題。

相關焦點

  • RT-Thread設備框架使用指南——I2C 總線設備
    rt_i2c_transfer()傳輸數據查找 I2C 總線設備 在使用 I2C 總線設備前需要根據 I2C 總線設備名稱獲取設備句柄,進而才可以操作 I2C 總線設備,查找設備函數如下所示,1rt_device_t rt_device_find(const char* name);參數描述
  • RT-Thread I2C總線設備學習筆記
    這是RTT官方設計的一個軟體框架,學習一個新東西,還是一樣,我個人主張帶著需求去學習,而不是漫無目的的去學,有了需求驅動,並且是一個努力付出就可以擁有的成果,那麼這還不容易嘛!如何看懂時序圖(以SPI/I2C為例)淺談總線通信機制(通信基礎+串口+I2C)我們接下來將基於小熊派開發平臺進行實踐。
  • RT-Thread ADC設備學習筆記
    學習一個新東西,還是一樣,我個人主張帶著需求去學習,而不是漫無目的的去學,有了需求驅動,並且是一個努力付出就可以擁有的成果,那麼這還不容易嘛!我們接下來將基於小熊派開發平臺進行實踐。2.1 硬體原理圖參考這篇文章:基於小熊派氣體傳感器MQ-2綜合實踐2.2 軟體功能實現根據官方給出的文檔可以分為這麼幾步操作:查找設備 rt_device_t rt_device_find(const char* name);參數描述nameADC 設備名稱返回--設備句柄查找到對應設備將返回相應的設備句柄RT_NULL沒有找到設備使能設備rt_err_t rt_adc_enable
  • RT-Thread低功耗組件用戶手冊(1)
    為了適應IoT的這種需求,RT-Thread提供了電源管理框架。電源管理框架的理念是儘量透明,使得產品加入低功耗功能更加輕鬆。下載IoT Board資料下載ENV工具然後將 RT-Thread 源碼中的rt-thread/examples/pm/timer_app.c拷貝到 IoT Board 的 PM 例程的 application 目錄裡。
  • RT_Thread系統使用總結
    //定義線程控制塊Static struct rt_thread led1_thread;4.    初始化線程線程三要素:線程主體函數,線程棧,線程控制塊,最後通過線程初始化函數rt_thread_init()將這些聯繫起來。
  • 第3期:RT-Thread實戰入門學習營,報名了!看看上期學員怎麼說?
    第二周就涉及到傳感器驅動的開發了。在學習營正式開始前一周,我開始準備硬體,主要就是傳感器。我選擇的是攀藤三合一的傳感器,採用TTL串口驅動。在這一周,我主要根據自己的傳感器建立線程模型,並且將共享內存和串口線程這一塊實際跑了一下,收穫不小,還是那句話,紙上得來終覺淺,絕知此事要躬行。 第三周主要是實現異步日誌,並將整個系統跑起來。
  • 【RT-Thread Studio入門】使用輪詢法檢測按鍵
    = RT_NULL) 3    rt_err = rt_thread_startup(key_thread); 4else 5    rt_kprintf("key thread create failure !!!
  • RT-Thread Studio V1.1 新版本發布
    【官網下載地址】https://www.rt-thread.org/page/studio.html(或點擊文末閱讀原文下載) 亮點功能2: RT-Thread配置功能包括框架配置和樹形配置兩種配置方式,在框架配置下可以通過軟體包中心添加軟體包同時可以直接通過點擊組件圖標啟用相關組件
  • RT-Thread 自動初始化詳解
    官網文檔提及到了,(他們的文檔在這裡:https://www.rt-thread.org/document/site/programming-manual/basic/basic/#rt-thread_3),但是寫的只是概念層面上的,看完後會使用但原理還是不太清楚。之前研究過,今天把它總結下,寫出來分享。
  • RT-Thread的finsh在nRF52840上的使用
    它的工作模式是用戶由設備埠輸入命令行,finsh 通過對設備輸入的讀取,解析輸入內容,然後自動掃描內部段(內部函數表),尋找對應函數名,執行函數後輸出回應。finsh的數據流結構如圖18-1所示。
  • RT-Thread面向對象編程思路淺析
    在rtthread中所有的類型的上帝就是rt_object。對象有對應的名稱,類型,標識以及下一個的鍊表。比如說ipc,消息間的通信機制這些都是基於rt_ipc_object的基類集成的。所以rt-thread的程序設計中,大量的用到了這種面向對象的思想進行設計。
  • RT-Thread教程一之Linux下開發環境及QEMU配置
    RT-Thread原始碼Linux下安裝git後在工程目錄下(比~/Workplace)執行git clone https://github.com/RT-Thread/rt-thread我們看一下樹目錄結構rt-thread
  • RT-Thread移植到nRF52840
    /document/site/submodules/rtthread-manual-doc/README/)以及火哥的《RT-Thread 內核實現與應用開發實戰—基於STM32》(本公眾號後臺回覆:野火RT-Thread 即可下載),本書的重點還是側重藍牙理論和實戰。
  • RT-Thread AT 組件應用筆記 - 客戶端篇
    AT 組件的使用包括客戶端的和伺服器,對於嵌入式設備而言,更多的情況下設備使用 AT 組件作為客戶端連接伺服器設備,所以本文將為大家介紹 AT 組件中客戶端的原理、移植方式和主要功能使用,並介紹在客戶端的基礎上實現標準 BSD Socket API,使用 AT 命令進行網絡通訊。
  • (4)RT-Thread 多線程學習總結
    關於多線程的使用和管理,RT-Thread官方提供了比較豐富的文檔作為參考,具體內容可以查看以下連結:https://www.rt-thread.org/document/site/programming-manual/thread/thread/本文是對RT-Thread多線程學習後的總結,並嘗試從如圖所示的以下幾個方面進行總結。
  • linux字符設備驅動基本框架
    對於Linux的驅動程序,需要遵循一定的框架結構。嵌入式Linux的學習其實並不難,只要深入理解Linux的框架,寫起來也可以得心應手。1.linux函數調用過程1.1 系統函數調用的意義在Linux的中,有一個思想比較重要:一切皆文件。也就是說,在應用程式中,可以通過open,write,read等函數來操作底層的驅動。
  • RT-Thread 2.1.0 beta 發布,下一方向:物聯網
    後續還會在智龍v2開發板上與開源龍芯進行多項合作,包括硬體驅動、內核優化、功能擴展等功能,希望能夠成為龍芯處理器平臺上的專用安全、硬實時作業系統版本。另外一份新加的移植是針對新的ARM Cortex-M7晶片(stm32f7-disco)移植。這份移植最初由小農提交,後經過Arda和bernard的整理而成。
  • RT-Thread 軟體包介紹
    ;Wiced WiFi:Wiced 接口的 WiFi 驅動;CoAP:移植 libcoap 的 CoAP 通信軟體包;nopoll:移植的開源 WebSocket 通信軟體包;netutils:實用的網絡調試小工具集合,包括:ping、TFTP、iperf、NetIO、NTP、Telnet 等;OneNet:與中國移動 OneNet
  • i.MX RT1052晶片的核心板,性能和代碼詳細資料概述
    先介紹介紹RT-Thread物聯網作業系統(以下簡稱rtt),作業系統是輕量級的,利用很小的資源完成實時作業系統的工作。 ,再做rtt的啟動 int rtthread_startup(void) { rt_hw_interrupt_disable(); /* board level initalization * NOTE: please initialize heap inside board initialization.
  • RT-Thread Studio V1.0.2 發布,物聯網作業系統一站式開發工具
    RT-Thread Studio 下載地址:https://www.rt-thread.org/page/studio.htm新版亮點:完美暗黑主題最新版Studio還推出了的完美的暗黑主題了,對於習慣於用暗黑主題的粉絲1.0.2版本簡直就是福音了