uboot引入了驅動模型(driver model),這種驅動模型為驅動的定義和訪問接口提供了統一的方法;提高了驅動之間的兼容性以及訪問的標準型。
###
uboot的DM主要有四個組成部分:
* udevice - 簡單就是指設備對象,可以理解為kernel中的device。
* driver - udevice的驅動,可以理解為kernel中的device\_driver。和底層硬件設備通信,并且為設備提供面向上層的接口。
* uclass - 使用相同方式的操作集的device的組。相當于是一種抽象。uclass為那些使用相同接口的設備提供了統一的接口。
* uclass\_driver - 對應uclass的驅動程序。主要提供uclass操作時,如綁定udevice時的一些操作。
調用關系如下:

###
DM的模型支持源碼在:include/dm

###
幾個關鍵數據結構的說明:
### **1.uclass id**
在uclass-id.h中定義了相關的id,部分列舉如下:

###
比如我們串口用到uclass的ID就是UCLASS\_SERIAL。
### **2.uclass**
同一類設備屬于同一個uclass,擁有相同的uclass ID。比如說RTC芯片,
市面上RTC芯片很多,由不同的廠家生產,其內存寄存器定義甚至訪問接口都不一樣,所以RTC的driver肯定是不一樣的,但是從功能的角度來說,他們都是用來記錄時間的,所他們都屬于rtc-class。?uclass從層級結構來講,起到非常好的承上啟下的作用,它既能屏蔽具體設備個體間的差異性,向用戶提供統一的接口,又能為同一類的設備定義統一的處理函數,具體的設備驅動只需要實現這些處理函數即可,從而簡化的設備驅動的開發。
###
我們可以在uclass.h中找到uclass的定義如下:
從設備的角度來看,同一類的設備(比如RTC)擁有相同的uclass ID,并全部掛在該uclass下;從驅動的角度來看,uclass driver實現通用的處理邏輯。
### **3.uclass\_driver**
同樣我們可以在uclass.h中找到struct uclass\_driver的定義,這個結構體定義了一組我們訪問uclass的接口:

```
post_bind // 在udevice被綁定到該uclass之后調用
pre_unbind // 在udevice被解綁出該uclass之前調用
pre_probe // 在該uclass的一個udevice進行probe之前調用
post_probe // 在該uclass的一個udevice進行probe之后調用
pre_remove // 在該uclass的一個udevice進行remove之前調用
child_post_bind // 在該uclass一個udevice的一個子設備被綁定到該udevice之后調用
child_pre_probe // 在該uclass的一個udevice的一個子設備進行probe之前調用
init // 安裝該uclass的時候調用
destroy // 銷毀該uclass的時候調用
```
###
### **4.udevice**
我們可以在device.h中找到定義:

###
```
const struct driver *driver; // 該udevice對應的driver
const char *name; // 設備名
void *platdata; // 該udevice的平臺數據
void *parent_platdata; // 提供給父設備使用的平臺數據
void *uclass_platdata; // 提供給所屬uclass使用的平臺數據
int of_offset; // 該udevice的dtb節點偏移,代表了dtb里面的這個節點node
ulong driver_data; // 驅動數據
struct udevice *parent; // 父設備
void *priv; // 私有數據的指針
struct uclass *uclass; // 所屬uclass
void *uclass_priv; // 提供給所屬uclass使用的私有數據指針
void *parent_priv; // 提供給其父設備使用的私有數據指針
struct list_head uclass_node; // 用于連接到其所屬uclass的鏈表上
struct list_head child_head; // 鏈表頭,連接其子設備
struct list_head sibling_node; // 用于連接到其父設備的鏈表上
uint32_t flags; // 標識
```
### **5.driver**
同樣我們可以在device.h中找到定義:

```
char *name; // 驅動名
enum uclass_id id; // 對應的uclass id
const struct udevice_id *of_match; //用于和device tree里面的設備節點匹配
(*bind) // 用于綁定目標設備到該driver中
(*probe) // 用于probe目標設備,激活
(*remove) // 用于remove目標設備。禁用
(*unbind) // 用于解綁目標設備到該driver中
(*ofdata_to_platdata) // probe之前,解udevice的dts節點,轉化成udevice的數據
(*child_post_bind) // 如果目標設備的一個子設備被綁定之后,調用
(*child_pre_probe) // 在目標設備的一個子設備被probe之前,調用
(*child_post_remove) // 在目標設備的一個子設備被remove之后,調用
int priv_auto_alloc_size; //需要分配多少空間作為其udevice的私有數據
int platdata_auto_alloc_size; //需要分配多少空間作為其udevice的平臺數據
int per_child_auto_alloc_size; //每個子設備需要多少私有數據
int per_child_platdata_auto_alloc_size; //每個子設備需要多少平臺數據
const void *ops; // 操作集,提供給uclass用,格式具體由uclass決定
uint32_t flags; // 一些標志位
```
- 《嵌入式Linux開發指南——面向IoT領域》
- 源代碼與開發軟件
- 配套開發套件
- 前言
- 起始部分:準備篇
- 硬件開發平臺簡介
- 安裝 Xshell 7 調試工具
- 安裝必要的驅動
- 配置安裝ADB
- 配置安裝cmder
- 第一部分:基礎篇
- 第1章 開發環境及交叉編譯鏈的搭建
- 本章學習目標
- 1.1 開發服務器的搭建
- 1.1.1 VMware導入開發服務器
- 1.1.2 Samba網絡服務
- 1.1.3 SSH網絡服務
- 1.1.4 交叉編譯鏈
- 1.2 硬件資源介紹
- 第2章 Linux基本命令
- 2.1 常用命令
- 2.1.1 ls
- 2.1.2 cd
- 2.1.3 pwd
- 2.1.4 mkdir
- 2.1.5 touch
- 2.1.6 mv
- 2.1.7 cp
- 2.1.8 rm
- 2.1.9 file
- 2.1.10 cat
- 2.1.11 tree
- 2.1.12 find
- 2.1.13 clear
- 2.1.14 chmod
- 2.1.15 sudo
- 2.1.16 su
- 2.1.17 ping
- 2.2 補充命令
- 2.2.1 ln
- 2.2.2 grep
- 2.2.3 diff
- 2.2.4 patch
- 第3章 嵌入式C基礎
- 3.1 數據類型
- 3.1.1 類型定義
- 3.1.2 類型格式化
- 3.2 變量
- 3.2.1 可執行程序存儲區
- 3.2.2 動態類型
- 3.2.3 類型轉換
- 3.3 指針
- 3.3.1 指針與堆
- 3.3.2 多階指針
- 3.3.3 通用類型指針
- 3.4 主函數(main)參數列表
- 3.5 可變參數
- 3.5.1 基本用法
- 3.5.2 擴展用法之日志輸出
- 3.6 頭文件
- 3.6.1 兼容C++
- 3.6.2 日志功能實例
- 3.6.3 C++源文件測試
- 第4章 嵌入式Shell基礎
- 4.1 基本語法
- 4.1.1 第一個程序
- 4.1.2 日志輸出
- 4.1.3 變量
- 4.1.4 分支控制ifelse
- 4.1.5 for循環
- 4.1.6 while循環
- 4.1.7 case分支語句
- 4.1.8 循環控制
- 4.1.9 變量運算符
- 4.2 函數
- 4.2.1 基本格式及調用
- 4.2.2 函數參數
- 4.2.3 腳本傳參
- 第5章 嵌入式系統基礎
- 5.1 固件基本組成
- 5.1.1 硬件系統結構
- 5.1.2 分區
- 5.1.2 軟件結構
- 5.2 內核設備樹
- 5.2.1 結構
- 5.2.2 節點語法
- 5.2.3 屬性語法
- 第6章 嵌入式C++基礎
- 第二部分:系統篇
- 第1章 固件分區和燒錄
- 1.1 準備工作
- 1.1.1 硬件連接說明
- 1.1.2 配置燒錄工具
- 1.2 固件燒錄
- 1.2.1 固件說明
- 1.2.2 進行燒錄
- 1.3 簡化固件
- 第2章 系統交叉編譯
- 2.1 Uboot
- 2.2 Kernel
- 2.3 Rootfs
- 2.4 APPs
- 第3章 Uboot串口交互終端
- 3.1 硬件連接
- 3.2 波特率配置
- 3.3 調試
- 3.4 Driver Model(DM)模型
- 3.5 串口驅動程序及DTS
- 3.5.1 驅動程序
- 3.5.2 設備樹
- 第4章 Kernel串口2做交互終端
- 4.1 驅動源碼
- 4.2 內核設備樹
- 4.3 補丁更新
- 第5章 內核Config
- 5.1 menuconfig
- 5.2 選項類型
- 5.3 部分General setup實例
- 5.4 生效配置
- 第6章 U盤掛載
- 6.1 配置選項說明
- 6.2 應用
- 第7章 SD卡掛載
- 7.1 內核設備樹
- 7.2 應用
- 第8章 WiFi-STA工作模式
- 8.1 內核配置
- 8.2 內核設備樹
- 8.3 wpa_supplicant
- 8.3.1 基礎
- 8.3.2 應用測試
- 8.3.3 配置文件連接
- 第9章 WiFi-AP工作模式
- 9.1 hostapd
- 9.1.1 基礎
- 9.1.2 應用測試
- 第10章 RGB調色燈三路PWM驅動
- 10.1 硬件基礎
- 10.2 內核設備樹
- 10.3 應用
- 第11章 ADC按鍵驅動
- 11.1 硬件基礎
- 11.2 設備樹節點
- 11.3 應用
- 11.3.1 了解IIO子系統
- 11.3.2 按鍵測試
- 第12章 串口1與ZigBee主控鏈路
- 12.1 設備樹節點
- 12.2 應用測試
- 第13章 可讀寫根文件系統
- 13.1 簡述
- 13.2 內核配置樹修改
- 第14章 用戶數據區
- 14.1 根文件系統區和用戶區的區別
- 14.2 用戶數據區
- 14.2.1 分區說明
- 14.2.2增加分區
- 14.2.3 分區內容制作
- 14.2.4 分區掛載
- 第三部分:應用篇
- 第1章 http網絡服務及文件傳輸
- 1.1 搭建服務
- 1.2 下載文件
- 第2章 TCP鏈路
- 2.1 IP通信
- 2.2 TCP特點和應用
- 2.2.1 特點
- 2.2.2 服務器建立
- 2.2.3 客戶端建立
- 2.3 實例
- 第3章 epoll機制
- 3.1 什么是epoll
- 3.2 實例
- 第4章 JSON格式及開源庫cJSON的移植
- 4.1 什么是JSON格式
- 4.2 cJSON庫
- 4.3 cJSON庫裁剪
- 4.4 創建JSON實例
- 4.5 解析JSON實例
- 第5章 jsoncpp的移植
- 5.1 創建JSON實例
- 5.2 解析JSON實例
- 第6章 TCP數據轉發服務器
- 6.1 link
- 6.2 linker
- 6.3 基本應用
- 6.2.1 服務器
- 6.2.2 客戶端
- 6.4 代理服務器
- 6.5 補充說明
- 第四部分:項目篇
- 項目篇的說明
- 第1章 串口通信協議設計
- 1.1 設計基礎
- 1.2 協議格式
- 第2章 zb_msg
- 2.1 串口通信類serial
- 2.2 協議處理zb_msg
- 2.3 交叉編譯測試
- 第3章 開源庫常見許可證
- 第4章 libevent異步事件庫的移植
- 4.1 什么是libevent
- 4.2 交叉編譯libevent
- 第5章 ev_base及ev_proxy
- 5.1 ev_base
- 5.2 ev_proxy
- 5.3 應用實例
- 第6章 openssl庫移植
- 6.1 什么是openssl
- 6.2 openssl的交叉編譯
- 第7章 基于libevent&openssl的https服務
- 7.1 重新交叉編譯libevent
- 7.2 httpd
- 7.3 應用實例
- 第8章 libmosquitto移植
- 8.1 什么是mosquitto
- 8.1.1 什么是MQTT
- 8.1.2 mosquitto
- 8.2 mosquitto的交叉編譯
- 第9章 AES加解密
- 9.1 簡介
- 9.2 應用實例
- 第10章 mqtter(支持AES加解密)
- 10.1 接口說明
- 10.2 源碼說明
- 10.3 應用實例
- 版權與免責聲明
- 版權聲明與免責聲明