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

??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??
接下來我們需要學(xué)習(xí)下如何開發(fā)一個(gè)驅(qū)動(dòng)應(yīng)用。
HDF框架簡介
HDF(Hardware Driver
Framework)是OpenHarmony的驅(qū)動(dòng)子系統(tǒng),包括驅(qū)動(dòng)框架,配置管理,配置解析,驅(qū)動(dòng)通用框架模型,硬件通用平臺(tái)能力接口等。下圖是一副標(biāo)準(zhǔn)系統(tǒng)的框架模型,但是在小型或者輕量級(jí)系統(tǒng)使用的時(shí)候時(shí)候沒有VFS也沒有這么復(fù)雜的分層。
![#沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個(gè)簡單的LED驅(qū)動(dòng)-開源基礎(chǔ)軟件社區(qū) #沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個(gè)簡單的LED驅(qū)動(dòng)-開源基礎(chǔ)軟件社區(qū)](https://dl-harmonyos.51cto.com/images/202210/075887107015ec99029435721c30ce49ca77a0.png?x-oss-process=image/resize,w_820,h_691)
![#沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個(gè)簡單的LED驅(qū)動(dòng)-開源基礎(chǔ)軟件社區(qū) #沖刺創(chuàng)作新星# #跟著小白一起學(xué)鴻蒙# [九] 寫個(gè)簡單的LED驅(qū)動(dòng)-開源基礎(chǔ)軟件社區(qū)](https://dl-harmonyos.51cto.com/images/202210/097a43f84535a5764f44548f581df74d1f2361.png?x-oss-process=image/resize,w_654,h_456)
詳細(xì)的內(nèi)容介紹在一下鏈接內(nèi)可以看到官方的說明:
參考鏈接:https://gitee.com/openharmony/drivers_hdf_core
此樣例參考小熊派設(shè)計(jì),使用小熊派HM_Micro開發(fā)板進(jìn)行驗(yàn)證
Driver開發(fā)流程
graph LR
編寫driver --> 編寫驅(qū)動(dòng)配置 --> 編寫私有配置 --> 添加驅(qū)動(dòng)應(yīng)用 --> 編譯生成
- 編寫driver: led.c, BUILD.gn
//實(shí)現(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ū)動(dòng)入口注冊(cè)到HDF框架中
HDF_INIT(g_ledDriverEntry);
- 實(shí)現(xiàn)對(duì)應(yīng)的方法:初始化
//Led設(shè)備結(jié)構(gòu)體
struct TestLed {
uint32_t gpioNum;
};
static struct TestLed g_testLed;
// 讀取驅(qū)動(dòng)私有配置
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ū)動(dòng)初始化
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;
}
- 實(shí)現(xiàn)對(duì)應(yīng)的方法:初始化
//HDF框架:驅(qū)動(dòng)綁定
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;
}
- 實(shí)現(xiàn)對(duì)應(yīng)的方法:驅(qū)動(dòng)資源釋放
// HDF框架:驅(qū)動(dòng)資源釋放
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ū)動(dòng)配置。
在鴻蒙源碼目錄下vendor目錄里是不同廠家的開發(fā)板,之下有hdf_config目錄,里面有對(duì)應(yīng)的device_info.hcs設(shè)備硬件配置文件,在此文件里增加以下內(nèi)容。
device_led :: device { // led設(shè)備節(jié)點(diǎn)
device0 :: deviceNode { // led驅(qū)動(dòng)的DeviceNode節(jié)點(diǎn)
policy = 2; // policy字段是驅(qū)動(dòng)服務(wù)發(fā)布的策略,在驅(qū)動(dòng)服務(wù)管理章節(jié)有詳細(xì)介紹
priority = 10; // 驅(qū)動(dòng)啟動(dòng)優(yōu)先級(jí)(0-200),值越大優(yōu)先級(jí)越低,建議默認(rèn)配100,優(yōu)先級(jí)相同則不保證device的加載順序
preload = 1; // 驅(qū)動(dòng)按需加載字段
permission = 0777; // 驅(qū)動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)權(quán)限
moduleName = "HDF_LED"; // 驅(qū)動(dòng)名稱,該字段的值必須和驅(qū)動(dòng)入口結(jié)構(gòu)的moduleName值一致
serviceName = "hdf_led"; // 驅(qū)動(dòng)對(duì)外發(fā)布服務(wù)的名稱,必須唯一
deviceMatchAttr = "st_stm32mp157_led"; //
驅(qū)動(dòng)私有數(shù)據(jù)匹配的關(guān)鍵字,必須和驅(qū)動(dòng)私有數(shù)據(jù)配置表中的match_attr值相等
}
}
同時(shí)在同級(jí)目錄里也需要增加led_config.hcs文件。
root {
LedDriverConfig {
led_gpio_num = 13;
match_attr = "st_stm32mp157_led";
//該字段的值必須和device_info.hcs中的deviceMatchAttr值一致
}
}
同時(shí)在同級(jí)目錄里也需要修改hdf.hcs文件,增加以下代碼:
#include "led/led_config.hcs"
編譯生成。
./build.sh --product-name PRODUCT_NAME
//看到success則為編譯成功,可以通過find out/[PRODUCT_NAME] -name "my_led"看到對(duì)應(yīng)的應(yīng)用
總結(jié)
device_info.hcs文件中的moduleName必須要和驅(qū)動(dòng)文件中的moduleName字段匹配,這樣驅(qū)動(dòng)才會(huì)加載起來。
device_info.hcs文件中的deviceMatchAttr的字段必須和私有配置文件中l(wèi)ed_config.hcs的match_attr的字段匹配,這樣私有配置才能生效。
??想了解更多關(guān)于開源的內(nèi)容,請(qǐng)?jiān)L問:??
??51CTO 開源基礎(chǔ)軟件社區(qū)??
??https://ost.51cto.com??。