代碼版本:openharmony 3.2 release
主要內(nèi)容
- ? ? ? ? HDF框架基礎(chǔ)知識(shí)
- ? ? ? ? HDF驅(qū)動(dòng)框架的開發(fā)
- ? ? ? ? HDF驅(qū)動(dòng)框架的應(yīng)用
HDF框架基礎(chǔ)知識(shí)?
HDF(Hardware Driver Foundation)驅(qū)動(dòng)框架,為驅(qū)動(dòng)開發(fā)者提供驅(qū)動(dòng)框架能力,包括驅(qū)動(dòng)加載、驅(qū)動(dòng)服務(wù)管理和驅(qū)動(dòng)消息機(jī)制。旨在構(gòu)建統(tǒng)一的驅(qū)動(dòng)架構(gòu)平臺(tái),為驅(qū)動(dòng)開發(fā)者提供更精準(zhǔn)、更高效的開發(fā)環(huán)境,力求做到一次開發(fā),多系統(tǒng)部署。
HDF驅(qū)動(dòng)框架架構(gòu)圖:
HDF驅(qū)動(dòng)架構(gòu)主要組成部分:
-
HDI(Hardware Device Interface,硬件設(shè)備統(tǒng)一接口)層:通過規(guī)范化的設(shè)備接口標(biāo)準(zhǔn),為系統(tǒng)提供統(tǒng)一、穩(wěn)定的硬件設(shè)備操作接口。
-
HDF驅(qū)動(dòng)框架:提供統(tǒng)一的硬件資源管理、驅(qū)動(dòng)加載管理、設(shè)備節(jié)點(diǎn)管理、設(shè)備電源管理以及驅(qū)動(dòng)服務(wù)模型等功能,需要包含設(shè)備管理、服務(wù)管理、DeviceHost、PnPManager等模塊。
-
統(tǒng)一的配置界面:支持硬件資源的抽象描述,屏蔽硬件差異,可以支撐開發(fā)者開發(fā)出與配置信息不綁定的通用驅(qū)動(dòng)代碼,提升開發(fā)及遷移效率,并可通過HC-Gen等工具快捷生成配置文件。
-
操作系統(tǒng)抽象層(OSAL,Operating System Abstraction Layer):提供統(tǒng)一封裝的內(nèi)核操作相關(guān)接口,屏蔽不同系統(tǒng)操作差異,包含內(nèi)存、鎖、線程、信號(hào)量等接口。
-
平臺(tái)驅(qū)動(dòng):為外設(shè)驅(qū)動(dòng)提供Board硬件(如:I2C/SPI/UART總線等平臺(tái)資源)操作統(tǒng)一接口,同時(shí)對(duì)Board硬件操作進(jìn)行統(tǒng)一的適配接口抽象以便于不同平臺(tái)遷移。
-
外設(shè)驅(qū)動(dòng)模型:面向外設(shè)驅(qū)動(dòng),提供常見的驅(qū)動(dòng)抽象模型,主要達(dá)成兩個(gè)目的,提供標(biāo)準(zhǔn)化的器件驅(qū)動(dòng),開發(fā)者無需獨(dú)立開發(fā),通過配置即可完成驅(qū)動(dòng)的部署;提供驅(qū)動(dòng)模型抽象,屏蔽驅(qū)動(dòng)與不同系統(tǒng)組件間的交互,使得驅(qū)動(dòng)更具備通用性
以上的基礎(chǔ)知識(shí)我也是從官方gitee中復(fù)制過來的,想具體了解的訪問下面網(wǎng)址即可:
docs: OpenHarmony documentation | OpenHarmony開發(fā)者文檔 - Gitee.comhttps://gitee.com/openharmony/docs/tree/master/zh-cn/device-dev/driver
HDF驅(qū)動(dòng)框架的開發(fā):
基于HDF框架的驅(qū)動(dòng)開發(fā)主要分為三個(gè)部分:實(shí)例化驅(qū)動(dòng)入口、驅(qū)動(dòng)編譯配置和驅(qū)動(dòng)配置屬性。詳細(xì)開發(fā)流程如下所示:
2.1、實(shí)例化驅(qū)動(dòng)入口:
驅(qū)動(dòng)入口必須為HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量,且moduleName要和device_info.hcs中保持一致。HDF框架會(huì)將所有加載的驅(qū)動(dòng)的HdfDriverEntry對(duì)象首地址匯總,形成一個(gè)類似數(shù)組的段地址空間,方便上層調(diào)用。
一般在加載驅(qū)動(dòng)時(shí)HDF會(huì)先調(diào)用Bind函數(shù),再調(diào)用Init函數(shù)加載該驅(qū)動(dòng)。當(dāng)Init調(diào)用異常時(shí),HDF框架會(huì)調(diào)用Release釋放驅(qū)動(dòng)資源并退出。
在//drivers/hdf_core/adapter/khdf/linux目錄下新建個(gè)名為sample_test目錄,再創(chuàng)建一個(gè)驅(qū)動(dòng)入口代碼。
static int32_t HdfSampleDriverDispatch(
struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
HDF_LOGI("%{public}s: received cmd %{public}d", __func__, id);
if (id == SAMPLE_WRITE_READ) { //接收用戶的命令參數(shù)
const char *readData = HdfSbufReadString(data); //驅(qū)動(dòng)讀取用戶的數(shù)據(jù)
if (readData != NULL) {
HDF_LOGE("%{public}s: read data is: %{public}s", __func__, readData);
}
if (!HdfSbufWriteInt32(reply, INT32_MAX)) { //驅(qū)動(dòng)返回給用戶的數(shù)據(jù)
HDF_LOGE("%{public}s: reply int32 fail", __func__);
}
return HdfDeviceSendEvent(client->device, id, data);
}
return HDF_FAILURE;
}
static void HdflDriverRelease(struct HdfDeviceObject *deviceObject)
{
// release resources here
return;
}
static int HdfDriverBind(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
return HDF_FAILURE;
}
static struct IDeviceIoService testService = {
.Dispatch = HdfSampleDriverDispatch,
};
deviceObject->service = &testService;
return HDF_SUCCESS;
}
static int HdfDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("%{public}s::ptr is null!", __func__);
return HDF_FAILURE;
}
HDF_LOGI("Sample driver Init success");
return HDF_SUCCESS;
}
static struct HdfDriverEntry DriverEntry = {
.moduleVersion = 1,
.moduleName = "sample_test",
.Bind = HdfDriverBind,
.Init = HdfDriverInit,
.Release = HdflDriverRelease,
};
HDF_INIT(DriverEntry);
2.2、驅(qū)動(dòng)編譯配置:
完成驅(qū)動(dòng)入口編寫后,在驅(qū)動(dòng)文件當(dāng)前目錄下添加一個(gè)Makefile文件,把驅(qū)動(dòng)調(diào)用的頭文件添加進(jìn)來,然后再將所要編譯的文件寫進(jìn)去,我沒有用config配置的方式直接用的-y,這樣比較簡單些。
include drivers/hdf/khdf/platform/platform.mk
obj-y += sample_tset.o
還要將上一個(gè)目錄的的文件的編譯加進(jìn)編譯系統(tǒng)里面去,在當(dāng)前驅(qū)動(dòng)文件的上一級(jí)目錄(//drivers/hdf_core/adapter/khdf/linux)中的Makefile中添加進(jìn)這樣一句話,為了避免麻煩還是選擇-y的方式編譯。
obj-y += sample_test/
2.3、驅(qū)動(dòng)配置屬性
在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息:
device_sample_test :: device { // sample_test設(shè)備
device0 :: deviceNode { // sample_test設(shè)備下的具體某個(gè)設(shè)備節(jié)點(diǎn)的配置
policy = 2; // 驅(qū)動(dòng)服務(wù)發(fā)布策略
priority = 110; // 驅(qū)動(dòng)啟動(dòng)優(yōu)先級(jí)
permission = 0644; // 驅(qū)動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)權(quán)限
moduleName = "sample_test"; // 驅(qū)動(dòng)名稱,必須和驅(qū)動(dòng)入口結(jié)構(gòu)的moduleName值一致
serviceName = "sample_test_service"; // 驅(qū)動(dòng)對(duì)外發(fā)布服務(wù)的名稱,必須唯一
}
}
成員名 值 policy 驅(qū)動(dòng)服務(wù)發(fā)布的策略,I2C管理器具體配置為2,表示驅(qū)動(dòng)對(duì)內(nèi)核態(tài)和用戶態(tài)都發(fā)布服務(wù) priority 驅(qū)動(dòng)啟動(dòng)優(yōu)先級(jí)(0-200),值越大優(yōu)先級(jí)越低。I2C管理器具體配置為50 permission 驅(qū)動(dòng)創(chuàng)建設(shè)備節(jié)點(diǎn)權(quán)限,I2C管理器具體配置為0664 moduleName 驅(qū)動(dòng)名稱,I2C管理器固定為HDF_PLATFORM_I2C_MANAGER serviceName 驅(qū)動(dòng)對(duì)外發(fā)布服務(wù)的名稱,I2C管理器服務(wù)名設(shè)置為HDF_PLATFORM_I2C_MANAGER deviceMatchAttr 驅(qū)動(dòng)私有數(shù)據(jù)匹配的關(guān)鍵字,I2C管理器設(shè)置為hdf_platform_i2c_manager
以上步驟操作完之后,再次編譯的時(shí)候就會(huì)將sample_test.c編譯為sample_test.o,將固件燒錄進(jìn)系統(tǒng)里面在/dev目錄下就會(huì)有一個(gè)名為sample_test的設(shè)備
HDF框架的應(yīng)用
應(yīng)用程序通過服務(wù)名綁定驅(qū)動(dòng)程序,和驅(qū)動(dòng)建立聯(lián)系,建立完之后就可以對(duì)這個(gè)驅(qū)動(dòng)設(shè)備進(jìn)行操作了,此處的sample_test_NAME要和上文2.3中的serviceName保持一致。文章來源:http://www.zghlxwxcb.cn/news/detail-829013.html
#define sample_test_NAME "sample_test_service"
serv = HdfIoServiceBind(sample_test_NAME );
if(serv == NULL){
printf("fail to get service %s \n", sample_test_NAME );
return HDF_FAILURE;
}
static int SendEvent(struct HdfIoService *serv, char *eventData)
{
int ret = 0;
struct HdfSBuf *data = HdfSbufObtainDefaultSize(); //獲取data緩沖區(qū)
if (data == NULL) {
HDF_LOGE("fail to obtain sbuf data");
return 1;
}
struct HdfSBuf *reply = HdfSbufObtainDefaultSize(); //獲取reply緩沖區(qū)
if (reply == NULL) {
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
}
if (!HdfSbufWriteString(data, eventData)) { //將eventData寫入data緩沖區(qū)
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
}
//調(diào)用 Dispatch 將數(shù)據(jù)發(fā)送給驅(qū)動(dòng),SAMPLE_WRITE_READ為傳入的命令參數(shù)
ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS) {
HDF_LOGE("fail to send service call");
goto out;
}
int replyData = 0;
if (!HdfSbufReadInt32(reply, &replyData)) { //讀取驅(qū)動(dòng)的返回值
HDF_LOGE("fail to get service call reply");
ret = HDF_ERR_INVALID_OBJECT;
goto out;
}
HDF_LOGI("Get reply is: %{public}d", replyData);
out:
HdfSbufRecycle(data);
HdfSbufRecycle(reply);
return ret;
}
編譯應(yīng)用的Build.gn文件:文章來源地址http://www.zghlxwxcb.cn/news/detail-829013.html
include_dirs = [
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/master/include",
"$HDF_FRAMEWORKS/include/platform",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"http://third_party/bounds_checking_function/include",
"$HDF_ADAPTER/uhdf/posix/include",
"$HDF_ADAPTER/khdf/linux/osal/include",
"http://base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
]
public_deps = [ "http://third_party/bounds_checking_function:libsec_shared" ]
deps = [
"$HDF_ADAPTER/uhdf/manager:hdf_core",
"$HDF_ADAPTER/uhdf/posix:hdf_posix_osal",
"http://base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
]
cflags = [
"-Wall",
"-Wextra",
"-Wno-format",
"-Wno-format-extra-args",
]
output_dir = "$root_out_dir/"
到了這里,關(guān)于OpenHarmony中基于HDF框架的驅(qū)動(dòng)開發(fā)和使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!