HDF(Hardware Driver Framework)是OpenHarmony的驅(qū)動子系統(tǒng),包括驅(qū)動框架,配置管理,配置解析,驅(qū)動通用框架模型,硬件通用平臺能力接口等。

??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??
接下來我們需要學(xué)習(xí)下如何開發(fā)一個驅(qū)動應(yīng)用。
HDF框架簡介
HDF(Hardware Driver
Framework)是OpenHarmony的驅(qū)動子系統(tǒng),包括驅(qū)動框架,配置管理,配置解析,驅(qū)動通用框架模型,硬件通用平臺能力接口等。下圖是一副標準系統(tǒng)的框架模型,但是在小型或者輕量級系統(tǒng)使用的時候時候沒有VFS也沒有這么復(fù)雜的分層。
![#沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個簡單的LED驅(qū)動-開源基礎(chǔ)軟件社區(qū) #沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個簡單的LED驅(qū)動-開源基礎(chǔ)軟件社區(qū)](https://dl-harmonyos.51cto.com/images/202210/075887107015ec99029435721c30ce49ca77a0.png?x-oss-process=image/resize,w_820,h_691)
![#沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個簡單的LED驅(qū)動-開源基礎(chǔ)軟件社區(qū) #沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個簡單的LED驅(qū)動-開源基礎(chǔ)軟件社區(qū)](https://dl-harmonyos.51cto.com/images/202210/097a43f84535a5764f44548f581df74d1f2361.png?x-oss-process=image/resize,w_654,h_456)
詳細的內(nèi)容介紹在一下鏈接內(nèi)可以看到官方的說明:
參考鏈接:https://gitee.com/openharmony/drivers_hdf_core
此樣例參考小熊派設(shè)計,使用小熊派HM_Micro開發(fā)板進行驗證
Driver開發(fā)流程
graph LR
編寫driver --> 編寫驅(qū)動配置 --> 編寫私有配置 --> 添加驅(qū)動應(yīng)用 --> 編譯生成
- 編寫driver: led.c, BUILD.gn
//實現(xiàn)Hdf結(jié)構(gòu)體,HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量
struct HdfDriverEntry g_ledDriverEntry = {
.moduleVersion = 1,
.moduleName = "HDF_LED",
.Bind = HdfLedDriverBind,
.Init = HdfLedDriverInit,
.Release = HdfLedDriverRelease,
};
// 調(diào)用HDF_INIT將驅(qū)動入口注冊到HDF框架中
HDF_INIT(g_ledDriverEntry);
//Led設(shè)備結(jié)構(gòu)體
struct TestLed {
uint32_t gpioNum;
};
static struct TestLed g_testLed;
// 讀取驅(qū)動私有配置
static int32_t LedReadDrs(struct TestLed *led, const struct
DeviceResourceNode *node)
{
int32_t ret;
struct DeviceResourceIface *drsOps = NULL;
drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
if (drsOps == NULL || drsOps->GetUint32 == NULL) {
HDF_LOGE("%s: invalid drs ops!", __func__);
return HDF_FAILURE;
}
/* 讀取led.hcs里面led_gpio_num的值 */
ret = drsOps->GetUint32(node, "led_gpio_num", &led->gpioNum,
0);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: read led gpio num fail!", __func__);
return ret;
}
return HDF_SUCCESS;
}
// HDF框架:驅(qū)動初始化
int32_t HdfLedDriverInit(struct HdfDeviceObject *device)
{
struct TestLed *led = &g_testLed;
int32_t ret;
if (device == NULL || device->property == NULL) {
HDF_LOGE("%s: device or property NULL!", __func__);
return HDF_ERR_INVALID_OBJECT;
}
/* 讀取hcs私有屬性值 */
ret = LedReadDrs(led, device->property);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: get led device resource fail:%d", __func__, ret);
return ret;
}
/* 將GPIO管腳配置為輸出 */
ret = GpioSetDir(led->gpioNum, GPIO_DIR_OUT);
if (ret != 0)
{
HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
return ret;
}
HDF_LOGD("Led driver Init success");
return HDF_SUCCESS;
}
//HDF框架:驅(qū)動綁定
int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver bind failed!");
return HDF_ERR_INVALID_OBJECT;
}
static struct IDeviceIoService ledDriver = {
.Dispatch = LedDriverDispatch,
};
deviceObject->service = (struct IDeviceIoService *)(&ledDriver);
HDF_LOGD("Led driver bind success");
return HDF_SUCCESS;
}
- 實現(xiàn)對應(yīng)的方法:驅(qū)動資源釋放
// HDF框架:驅(qū)動資源釋放
void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver release failed!");
return;
}
HDF_LOGD("Led driver release success");
return;
}
import("http://drivers/adapter/khdf/liteos/hdf.gni")
hdf_driver("hdf_led") {
sources = [
"led.c",
]
}
驅(qū)動配置。
在鴻蒙源碼目錄下vendor目錄里是不同廠家的開發(fā)板,之下有hdf_config目錄,里面有對應(yīng)的device_info.hcs設(shè)備硬件配置文件,在此文件里增加以下內(nèi)容。
device_led :: device { // led設(shè)備節(jié)點
device0 :: deviceNode { // led驅(qū)動的DeviceNode節(jié)點
policy = 2; // policy字段是驅(qū)動服務(wù)發(fā)布的策略,在驅(qū)動服務(wù)管理章節(jié)有詳細介紹
priority = 10; // 驅(qū)動啟動優(yōu)先級(0-200),值越大優(yōu)先級越低,建議默認配100,優(yōu)先級相同則不保證device的加載順序
preload = 1; // 驅(qū)動按需加載字段
permission = 0777; // 驅(qū)動創(chuàng)建設(shè)備節(jié)點權(quán)限
moduleName = "HDF_LED"; // 驅(qū)動名稱,該字段的值必須和驅(qū)動入口結(jié)構(gòu)的moduleName值一致
serviceName = "hdf_led"; // 驅(qū)動對外發(fā)布服務(wù)的名稱,必須唯一
deviceMatchAttr = "st_stm32mp157_led"; //
驅(qū)動私有數(shù)據(jù)匹配的關(guān)鍵字,必須和驅(qū)動私有數(shù)據(jù)配置表中的match_attr值相等
}
}
同時在同級目錄里也需要增加led_config.hcs文件。
root {
LedDriverConfig {
led_gpio_num = 13;
match_attr = "st_stm32mp157_led";
//該字段的值必須和device_info.hcs中的deviceMatchAttr值一致
}
}
同時在同級目錄里也需要修改hdf.hcs文件,增加以下代碼:
#include "led/led_config.hcs"
編譯生成。
./build.sh --product-name PRODUCT_NAME
//看到success則為編譯成功,可以通過find out/[PRODUCT_NAME] -name "my_led"看到對應(yīng)的應(yīng)用
總結(jié)
device_info.hcs文件中的moduleName必須要和驅(qū)動文件中的moduleName字段匹配,這樣驅(qū)動才會加載起來。
device_info.hcs文件中的deviceMatchAttr的字段必須和私有配置文件中l(wèi)ed_config.hcs的match_attr的字段匹配,這樣私有配置才能生效。
??想了解更多關(guān)于開源的內(nèi)容,請訪問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??。