chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

OpenHarmony HDF平臺驅(qū)動框架及驅(qū)動適配介紹

OpenAtom OpenHarmony ? 來源:OpenAtom OpenHarmony ? 作者: 楊海舟 ? 2021-09-24 11:16 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

開源項目 OpenHarmony是每個人的 OpenHarmony

OpenHarmony系統(tǒng)平臺驅(qū)動概述

OpenHarmony系統(tǒng)平臺驅(qū)動(PlatformDriver),即平臺設備驅(qū)動,它用于驅(qū)動平臺設備(PlatformDevice),為系統(tǒng)及外設驅(qū)動提供訪接口。這里的平臺設備,泛指I2C/UART等總線、以及GPIO/RTC等SOC片內(nèi)硬件資源。

OpenHarmony系統(tǒng)平臺驅(qū)動框架是OpenHarmony系統(tǒng)驅(qū)動框架的重要組成部分,它基于HDF驅(qū)動框架、操作系統(tǒng)適配層(OSAL, operating system abstraction layer)以及驅(qū)動配置管理機制,為各類平臺設備驅(qū)動的實現(xiàn)提供標準模型。

OpenHarmony系統(tǒng)平臺驅(qū)動框架為外設提供了標準的平臺設備訪問接口,使其不必關(guān)注具體硬件及OS平臺;同時為平臺設備驅(qū)動提供統(tǒng)一的適配接口,使其只關(guān)注自身硬件的控制。

為實現(xiàn)這個目標,OpenHarmony系統(tǒng)平臺驅(qū)動框架滿足如下特性:

統(tǒng)一的平臺設備訪問接口:對平臺設備操作接口進行統(tǒng)一封裝,屏蔽不同SOC平臺硬件差異以及不同OS形態(tài)差異。

統(tǒng)一的平臺驅(qū)動適配接口:為平臺設備驅(qū)動提供統(tǒng)一的適配接口,使其只關(guān)注自身硬件的控制,而不必關(guān)注設備管理及公共業(yè)務流程。

提供設備注冊、管理、訪問控制等與SOC無關(guān)的公共能力。

OpenHarmony系統(tǒng)平臺驅(qū)動框架目前支持的設備類型包括但不限于:I2C/SPI/UART/MIPI_DSI/SDIO/GPIO/PWM/WATCHDOG/RTC/DMA

OpenHarmony平臺驅(qū)動框架介紹

OpenHarmony系統(tǒng)平臺驅(qū)動框架組成

OpenHarmony系統(tǒng)平臺驅(qū)動框架主要由平臺接口層、平臺核心層以及平臺適配層三個部分組成。

aa3b5eb2-10b0-11ec-8fb8-12bb97331649.png

1)平臺接口層以API的形式提供標準的平臺設備訪問接口。

平臺接口層以設備句柄加配套API的形式對外提供統(tǒng)一的、標準的訪問接口。

設備句柄是DevHandle類型的實例,通過不同設備模塊提供的Open/Close方法進行獲取、釋放。成功獲取設備句柄后,即可使用相應的API執(zhí)行設備操作。例如通過I2cTransfer完成一次I2C數(shù)據(jù)傳輸。

這是一種代理模式,即接口層API不直接引用實際設備對象,而是通過DevHandle作為代理,間接訪問設備;而所有來自外設驅(qū)動的訪問,都建議走接口層,以獲得最佳的穩(wěn)定性。

不同類型設備的API使用,請參考如下官方文檔的平臺驅(qū)動章節(jié):

https://device.OpenHarmony系統(tǒng).com/cn/docs/develop/drive/oem_drive_hdfdev-0000001051715456

2)平臺核心層提供平臺設備模型及公共業(yè)務框架。

提供統(tǒng)一適配接口:定義了標準的設備對象模型,驅(qū)動程序僅需關(guān)注標準對象模型的適配。

抽取公共業(yè)務框架:將不同設備模塊的公共流程、算法加以抽取,使得具體設備驅(qū)動更加輕薄。

設備管理:設備注冊、注銷、設備查找、訪問控制。

3)平臺適配層提供特定平臺設備的適配驅(qū)動,并遵守核心層約束。

驅(qū)動具體平臺設備硬件,并創(chuàng)建對應的設備模型對象,注冊到核心層納入統(tǒng)一管理。

平臺接口層分析

前面說過,在接口層,我們用DevHandle類型的設備句柄表示一個平臺設備對象,然后針對不同類型設備提供一套標準的API方法用于設備訪問。那么設備句柄和真實的設備對象如何關(guān)聯(lián)呢?

查看DevHandle的定義,發(fā)現(xiàn)它就是一個void類型指針:

/**

* @brief Defines the common device handle of the platform driver.

*

* The handle is associated with a specific platform device and is used as the

* first input parameter for all APIs of the platform driver.

*

* @since 1.0

*/

typedef void* DevHandle;

實際上,在內(nèi)核態(tài),這個指針可以直接指向?qū)嶋H設備對象,但是對于某些類型的平臺設備,我們需要在用戶態(tài)提供同樣的DevHandle類型及配套API,而實際設備對象在內(nèi)核空間,我們無法直接獲取和使用內(nèi)核空間的地址。

我們的解決辦法是將平臺設備對象實現(xiàn)為一個HDF設備服務,這樣借助HDF DeviceManager的設備服務機制,可以在用戶態(tài)、內(nèi)核態(tài)同時獲取到設備服務,而用戶態(tài)同內(nèi)核態(tài)通信的問題交由HDF DeviceManager處理。此時,DevHandle只需要關(guān)聯(lián)到這個設備服務即可,而void*類型保證了足夠的靈活性。

根據(jù)DevHandle和設備對象關(guān)聯(lián)方式的不同,接口層的設計有三種模式,下面將一一講解。

1.獨立服務模式

aa5d017a-10b0-11ec-8fb8-12bb97331649.png

這種模式用于需要在用戶態(tài)和內(nèi)核態(tài)同時提供API的設備類型,DevHandle同設備對象的關(guān)聯(lián)方式為:

用戶態(tài):關(guān)聯(lián)到平臺設備對應的設備服務

內(nèi)核態(tài)度:關(guān)聯(lián)到實際平臺設備對象或其設備服務(在內(nèi)核態(tài)兩者可互相轉(zhuǎn)換)

這樣,每一個設備對象,會獨立發(fā)布一個設備服務,來處理外部訪問,服務收到API的訪問請求之后,通過提取請求參數(shù),并調(diào)用實際設備對象的相應內(nèi)部方法。

這種方式的優(yōu)點是管理比較簡單,因為它借助了HDF DeviceManager的服務管理能力;但是缺點是需要為每一個設備對象配置設備節(jié)點,以便發(fā)布設備服務。

這種模式的典型實踐是UART模塊,這在后面介紹驅(qū)動適配時會詳細介紹。

2.統(tǒng)一服務模式

aaa6b59a-10b0-11ec-8fb8-12bb97331649.png

有時候,同一類型的設備對象可能會很多,例如I2C模塊,可能同時有十幾個控制器。如果采用獨立服務的模式,每一個控制器,作為一個平臺設備,為其創(chuàng)建一個設備服務,那么將會有十幾個服務被創(chuàng)建,不光要配置很多設備節(jié)點,而且這些服務還會占用內(nèi)存資源。

這時,我們可以為一類設備對象,創(chuàng)建一個平臺設備管理器(PlatformManager)對象,并同時對外發(fā)布一個管理器服務,由這個管理器服務來統(tǒng)一處理外部訪問。當用戶需要打開某個設備時,先通過HDF DeviceManager獲取到管理器服務,然后管理器服務根據(jù)用戶指定參數(shù)查找到指定設備,并返回一個設備描述符,而這個描述符仍然可以由DevHandle類型表示。

這種模式的實踐代表是I2C模塊,PlatformManager實現(xiàn)為I2cManager,而PlatformDevice則是I2cCntlr,感興趣的讀者可以閱讀一下drivers/framework下的i2c_if.c/i2c_core.c一探究竟。

3.無服務模式

aab7f1b6-10b0-11ec-8fb8-12bb97331649.png

這種模式用于不需要在用戶態(tài)提供API的設備類型或者沒有用戶態(tài)、內(nèi)核區(qū)分的OS系統(tǒng),其關(guān)聯(lián)方式是DevHandle直接指向設備對象內(nèi)核態(tài)地址。而PlatformManager的實現(xiàn)比較自由,它不需要實現(xiàn)設備服務,只需做好某種類型的設備管理即可,甚至在C語言中,由于無法進行OOP編程,很多模塊直接將這個功能面向過程化了,使得沒有一個具體的結(jié)構(gòu)體與之對應。但是,我們?nèi)匀粡娬{(diào)PlatformManager這個概念,也期望隨著后續(xù)平臺驅(qū)動框架的演進,逐步完善、規(guī)范化,形成更加統(tǒng)一的編程風格。

平臺核心層分析

平臺核心層的作用是承上啟下,其主要內(nèi)容包括:

提供適配接口:為具體的平臺設備驅(qū)動提供統(tǒng)一的適配接口

平臺驅(qū)動框架為不同設備類型,定義了標準的設備對象模型,具體設備驅(qū)動只需要關(guān)注標準設備對象的適配即可

提供設備管理:提供設備的注冊、注銷、查找等功能、訪問控制等能力

核心層會提供一系列內(nèi)部方法,用于設備的注冊、注銷,設備對象的查找、獲取、釋放,以及處理多線程訪問。例如當我們向核心層注冊一個I2C控制器對象時,使用I2cCntlrAdd;當希望獲取一個I2C控制器對象時,通過I2cCntlrGet并指定控制器編號;當不再使用這個對象時,還需要通過I2cCntlrPut釋放。這樣做的好處是將每一個具體的操作步驟高度抽象化,減小同平臺接口層及平臺適配層的耦合面,便于業(yè)務解耦、演進。如果后續(xù),我們由于業(yè)務需求需要對I2cCntlr對象進行引用計數(shù),那么只需要修改I2cCntlrGet/Put這對方法的實現(xiàn)即可,并不會影響平臺接口層和平臺適配層。

公共業(yè)務實現(xiàn):抽取公共的業(yè)務流程、算法

凡是跟特定硬件無關(guān)的業(yè)務邏輯,都會被抽取到核心層,例如RTC時鐘的時間格式轉(zhuǎn)換算法,GPIO模塊的線程中斷實現(xiàn)等等。


平臺適配層實現(xiàn)

適配層提供具體平臺硬件設備的驅(qū)動,按照核心層定義的模型創(chuàng)建設備對象,并完成對象的初始化(包括必要的成員變量初始化以及鉤子方法掛接,以及相關(guān)的硬件初始化操作),最后使用核心層提供的注冊方法將設備對象注冊到核心層納入統(tǒng)一管理。


OpenHarmony系統(tǒng)平臺驅(qū)動適配介紹

下面以uart/i2c/gpio三個典型模塊為例介紹平臺驅(qū)動適配的一般方法

UART模塊的適配

UART模塊適配的核心環(huán)節(jié),是UartHost對象的創(chuàng)建、初始化及注冊。

UART模塊采用的是獨立服務模式,要求每一個UartHost對象關(guān)聯(lián)一個HDF設備服務,因此:

1).device_info.hcs中為每一個UART控制器配置一個HDF設備節(jié)點

device_uart :: device {

device0 :: deviceNode {

policy = 1;

priority = 40;

permission = 0644;

moduleName = "HDF_PLATFORM_UART";

serviceName = "HDF_PLATFORM_UART_0";

deviceMatchAttr = "hisilicon_hi35xx_uart_0";

}

device1 :: deviceNode {

policy = 2;

permission = 0644;

priority = 40;

moduleName = "HDF_PLATFORM_UART";

serviceName = "HDF_PLATFORM_UART_1";

deviceMatchAttr = "hisilicon_hi35xx_uart_1";

}

}

服務policy大于等于1(如需對用戶態(tài)可見為2,僅內(nèi)核態(tài)可見為1);

moduleName需要與驅(qū)動Entry中moduleName 保持一致;

ServiceName必須要按照HDF_PLATFORM_UART_X的格式,X為UART控制器編號

deviceMatchAttr用于配置控制器私有數(shù)據(jù),要與uart_config.hcs中對應控制器保持一致,如不需要則忽略

2).uart_config.hcs中為每一個UART控制器配置私有數(shù)據(jù)

如果控制器需要配置一些私有數(shù)據(jù),例如寄存器基地址,初始化波特率等等,可以在uart_config.hcs中配置,該文件將在產(chǎn)品配置目錄的hdf.hcs中導入,具體路徑可由產(chǎn)品自由配置。

root {

platform {

template uart_controller {

match_attr = "";

num = 0;

baudrate = 115200;

fifoRxEn = 1;

fifoTxEn = 1;

flags = 4;

regPbase = 0x120a0000;

interrupt = 38;

iomemCount = 0x48;

}

controller_0x120a0000 :: uart_controller {

match_attr = "hisilicon_hi35xx_uart_0";

}

controller_0x120a1000 :: uart_controller {

num = 1;

baudrate = 9600;

regPbase = 0x120a1000;

interrupt = 39;

match_attr = "hisilicon_hi35xx_uart_1";

}

}

要注意的一點是每個控制器要獨立配置一個uart_controller節(jié)點,并且其match_attr要與device_info.hcs中的deviceMatchAttr一致。

3).驅(qū)動的Entry結(jié)構(gòu)需要有Bind方法,用于綁定服務

struct HdfDriverEntry g_hdfUartDevice = {

.moduleVersion = 1,

.moduleName = "HDF_PLATFORM_UART",

.Bind = HdfUartDeviceBind,

.Init = HdfUartDeviceInit,

.Release = HdfUartDeviceRelease,

};

HDF_INIT(g_hdfUartDevice);

注意:在Bind方法中,要使用UartHostCreate創(chuàng)建控制器對象并完成服務綁定。

static int32_t HdfUartDeviceBind(struct HdfDeviceObject *device)

{

HDF_LOGI("%s: entry", __func__);

if (device == NULL) {

return HDF_ERR_INVALID_OBJECT;

}

return (UartHostCreate(device) == NULL) ? HDF_FAILURE : HDF_SUCCESS;

}

4).UartHostCreate的實現(xiàn)屏蔽了一些細節(jié)

struct UartHost *UartHostCreate(struct HdfDeviceObject *device)

{

struct UartHost *host = NULL;

host = (struct UartHost *)OsalMemCalloc(sizeof(*host));

host->device = device;

device->service = &(host->service);

host->device->service->Dispatch = UartIoDispatch;

OsalAtomicSet(&host->atom, 0);

host->priv = NULL;

host->method = NULL;

return host;

}

該方法中將UartHost對象同HdfDeviceObject進行了關(guān)聯(lián):關(guān)鍵環(huán)節(jié)是為HdfDeviceObject的service成員進行賦值,使其指向UartHost的IDeviceIoService類型的成員對象;同時為service成員的Dispatch方法賦值。這樣:

為HdfDeviceObject對象綁定了IDeviceIoService類型的服務對象

UartHost和其IDeviceIoService類型的成員對象service可以相互轉(zhuǎn)換

通過UartHost對象即可獲取HdfDeviceObject對象

通過HdfDeviceObject對象即可間接獲取UartHost對象(先獲取service再轉(zhuǎn)為host)

5).在Init方法中完成UartHost對象的初始化

int32_t HdfUartDeviceInit(struct HdfDeviceObject *device)

{

int32_t ret;

struct UartHost *host = NULL;

host = UartHostFromDevice(device);

ret = Hi35xxAttach(host, device);

host->method = &g_uartHostMethod;

return ret;

}

這里通過UartHostFromDevice從HdfDeviceObject對象獲取之前關(guān)聯(lián)的UartHost對象,然后調(diào)用Hi35xxAttach方法完成host對象的初始化

最后為host對象掛接鉤子方法,這里不再一一分析這些鉤子方法,建議讀者直接去查看源碼。

struct UartHostMethod g_uartHostMethod = {

.Init = Hi35xxInit,

.Deinit = Hi35xxDeinit,

.Read = Hi35xxRead,

.Write = Hi35xxWrite,

.SetBaud = Hi35xxSetBaud,

.GetBaud = Hi35xxGetBaud,

.SetAttribute = Hi35xxSetAttribute,

.GetAttribute = Hi35xxGetAttribute,

.SetTransMode = Hi35xxSetTransMode,

.pollEvent = Hi35xxPollEvent,

};

總結(jié)

UART適配的關(guān)鍵是要在驅(qū)動Entry的Bind方法中創(chuàng)建UartHost對象,而且是使用UartHostCreate創(chuàng)建。這個創(chuàng)建動作同時也是注冊的動作,因為它將UartHost以HDF設備服務的形式同HdfDeviceObject進行綁定,這樣就完成了服務的發(fā)布,HDF Manager對設備服務的管理也就是對UartHost的管理,核心層可以通過HDF提供的服務獲取接口來訪問UartHost。

UART適配采用獨立服務模式,每一個UartHost對象同時也是一個設備服務,其優(yōu)點是可以直接利用HDF Manager進行管理;缺點是需要在device_info.hcs為每一個UartHost對象定義設備節(jié)點。

說明

UART模塊適配涉及到的代碼示例片段來自device/hisilicon/drivers/uart/

I2C模塊適配

I2C模塊適配的核心環(huán)節(jié)是I2cCntlr對象的創(chuàng)建、初始化及注冊。

I2C采用的是統(tǒng)一服務模式,需要一個設備服務來作為I2C模塊的管理器,統(tǒng)一處理外部訪問。

1、device_info.hcs配置

device_i2c :: device {

device0 :: deviceNode {

policy = 2;

priority = 50;

permission = 0644;

moduleName = "HDF_PLATFORM_I2C_MANAGER";

serviceName = "HDF_PLATFORM_I2C_MANAGER";

deviceMatchAttr = "hdf_platform_i2c_manager";

}

device1 :: deviceNode {

policy = 0;

priority = 55;

permission = 0644;

moduleName = "hi35xx_i2c_driver";

serviceName = "HI35XX_I2C_DRIVER";

deviceMatchAttr = "hisilicon_hi35xx_i2c";

}

}

首先第一個設備節(jié)點必須是I2C管理器,其各項參數(shù)必須如上一樣設置。其中:

policy:這個同UART,具體配置為1或2取決于是否對用戶態(tài)可見

moduleName:固定為HDF_PLATFORM_I2C_MANAGER

serviceName:固定為HDF_PLATFORM_I2C_MANAGER

deviceMatchAttr:沒有使用,可忽略

而從第二個設備節(jié)點開始,配置具體I2C控制器信息。這里device1 并不表示某一路I2C控制器,而是一個資源性質(zhì)設備,用于描述一類I2C控制器的信息。

服務policy等于0,不需要發(fā)布服務;

moduleName用于指定驅(qū)動成語,需要與期望的驅(qū)動Entry中的moduleName一致;

ServiceName不需要使用,可忽略;

deviceMatchAttr用于配置控制器私有數(shù)據(jù),要與i2c_config.hcs中對應控制器保持

同樣,具體的控制器信息在i2c_config.hcs中,由具體產(chǎn)品在hdf.hcs中導入。

2、i2c_config.hcs中可配置多個控制器信息

root {

platform {

i2c_config {

match_attr = "hisilicon_hi35xx_i2c";

template i2c_controller {

bus = 0;

reg_pbase = 0x120b0000;

reg_size = 0xd1;

irq = 0;

freq = 400000;

clk = 50000000;

}

controller_0x120b0000 :: i2c_controller {

bus = 0;

}

controller_0x120b1000 :: i2c_controller {

bus = 1;

reg_pbase = 0x120b1000;

}

}

}

}

可以看到,這里配置了多個控制器的信息,而這些信息將在驅(qū)動程序員進行逐一解析、處理,生成對應的I2cCntlr對象。

3、I2C管理器服務的驅(qū)動由核心層實現(xiàn)

struct HdfDriverEntry g_i2cManagerEntry = {

.moduleVersion = 1,

.Bind = I2cManagerBind,

.Init = I2cManagerInit,

.Release = I2cManagerRelease,

.moduleName = "HDF_PLATFORM_I2C_MANAGER",

};

HDF_INIT(g_i2cManagerEntry);

驅(qū)動適配人員無需關(guān)注這個驅(qū)動的實現(xiàn),有興趣的可以去閱讀源碼。

drivers/framework/support/platform/src/i2c_core.c

4、適配驅(qū)動Entry只需要實現(xiàn)Init方法

struct HdfDriverEntry g_i2cDriverEntry = {

.moduleVersion = 1,

.Init = Hi35xxI2cInit,

.Release = Hi35xxI2cRelease,

.moduleName = "hi35xx_i2c_driver",

};

HDF_INIT(g_i2cDriverEntry);

static int32_t Hi35xxI2cInit(struct HdfDeviceObject *device)

{

int32_t ret;

const struct DeviceResourceNode *childNode = NULL;

ret = HDF_SUCCESS;

DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) {

ret = Hi35xxI2cParseAndInit(device, childNode);

if (ret != HDF_SUCCESS) {

break;

}

}

return ret;

}

在Init方法中會將i2c_config.hcs中定義的每一個節(jié)點取出,分別進行初始化

5、Hi35xxI2cParseAndInit里面很自由

static int32_t Hi35xxI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)

{

int32_t ret;

struct Hi35xxI2cCntlr *hi35xx = NULL;

(void)device;

hi35xx = (struct Hi35xxI2cCntlr *)OsalMemCalloc(sizeof(*hi35xx));

ret = Hi35xxI2cReadDrs(hi35xx, node);

hi35xx->regBase = OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);

Hi35xxI2cCntlrInit(hi35xx);

hi35xx->cntlr.priv = (void *)node;

hi35xx->cntlr.busId = hi35xx->bus;

hi35xx->cntlr.ops = &g_method;

hi35xx->cntlr.lockOps = &g_lockOps;

(void)OsalSpinInit(&hi35xx->spin);

ret = I2cCntlrAdd(&hi35xx->cntlr);

....

}

Hi35xxI2cParseAndInit會處理一個具體的I2C控制器的初始化工作,包括:

1)I2cCntlr對象的分配,Hi35xxI2cCntlr頭部內(nèi)嵌了一個I2cCntlr,這是一種繼承。

struct Hi35xxI2cCntlr {

struct I2cCntlr cntlr;

OsalSpinlock spin;

volatile unsigned char *regBase;

uint16_t regSize;

int16_t bus;

uint32_t clk;

uint32_t freq;

uint32_t irq;

uint32_t regBasePhy;

};

2)在Hi35xxI2cReadDrs中完成節(jié)點屬性的讀取,并填充進hi35xx對象

3)映射寄存器基地址OsalIoRemap(hi35xx->regBasePhy, hi35xx->regSize);

4)調(diào)用Hi35xxI2cCntlrInit完成控制器的初始化

5)I2cCntlr對象的填充及調(diào)用I2cCntlrAdd注冊

這里唯一形式化約束是必須創(chuàng)建一個合法的I2cCntlr并調(diào)用I2cCntlrAdd注冊到核心層。其他Hi35xx開頭的函數(shù)都是驅(qū)動適配者自由封裝的,并無形式化要求。

總結(jié)

采用統(tǒng)一服務模式,其優(yōu)點是不用為每一個I2C控制器定義一個設備節(jié)點,控制器對象的創(chuàng)建和注冊比較自由;而缺點是要創(chuàng)建一個I2C管理器服務,以及一個虛擬的資源描述設備。


說明

I2C模塊適配涉及到的代碼示例片段來自device/hisilicon/drivers/i2c/


GPIO模塊適配

GPIO模塊由于目前不向用戶態(tài)提供能力,所以不需要發(fā)布設備服務。其hcs配置同uart相似,這里不再贅述,唯一不同是device_info.hcs中設備節(jié)點的policy為0,表示不發(fā)布設備服務。

device_gpio :: device {

device0 :: deviceNode {

policy = 0;

priority = 10;

permission = 0644;

moduleName = "hisi_pl061_driver";

deviceMatchAttr = "hisilicon_hi35xx_pl061";

}

}

同樣的原因,GPIO的驅(qū)動Entry不需要實現(xiàn)Bind方法,僅需要在Init方法中創(chuàng)建并初始化一個GpioCntlr,再調(diào)用GpioCntlrAdd完成注冊即可。

struct HdfDriverEntry g_gpioDriverEntry = {

.moduleVersion = 1,

.Bind = Pl061GpioBind,

.Init = Pl061GpioInit,

.Release = Pl061GpioRelease,

.moduleName = "hisi_pl061_driver",

};

HDF_INIT(g_gpioDriverEntry);

這里雖然給Bind方法賦值,但其實現(xiàn)為空。

static int32_t Pl061GpioInit(struct HdfDeviceObject *device)

{

int32_t ret;

struct Pl061GpioCntlr *pl061 = &g_pl061;

ret = Pl061GpioReadDrs(pl061, device->property);

pl061->regBase = OsalIoRemap(pl061->phyBase, pl061->groupNum * pl061->regStep);

ret = Pl061GpioInitCntlrMem(pl061);

pl061->cntlr.count = pl061->groupNum * pl061->bitNum;

pl061->cntlr.priv = (void *)device->property;

pl061->cntlr.ops = &g_method;

pl061->cntlr.device = device;

ret = GpioCntlrAdd(&pl061->cntlr);

}

Init方法里面注意是對GpioCntlr的初始化,以及通過GpioCntlrAdd完成注冊。這里Pl061GpioCntlr內(nèi)嵌了一個GpioCntlr,又是繼承。

GpioCntlr的鉤子方法實現(xiàn),請感興趣的讀者自己去閱讀源碼,這里僅對每個鉤子方法作用做簡單注釋:

static struct GpioMethod g_method = {

.request = NULL, //暫時不用

.release = NULL, //暫時不用

.write = Pl061GpioWrite, //寫管腳

.read = Pl061GpioRead, //讀管腳

.setDir = Pl061GpioSetDir, //設置管腳方向

.getDir = Pl061GpioGetDir, //獲取管腳方向

.toIrq = NULL, //暫時不用

.setIrq = Pl061GpioSetIrq, //設置管腳中斷段,如不具備此能力可忽略

.unsetIrq = Pl061GpioUnsetIrq, //取消管腳中斷設置,如不具備此能力可忽略

.enableIrq = Pl061GpioEnableIrq, //使能管腳中斷,如不具備此能力可忽略

.disableIrq = Pl061GpioDisableIrq, //禁止管腳中斷,如不具備此能力可忽略

};

總結(jié)

GPIO適配在hcs配置及驅(qū)動Entry編寫上比I2C/UART都簡單,但是無法向用戶態(tài)提供能力支撐。

最后,對于其他模塊的適配,基本都是這三種方式之一,讀者可集合核心層代碼及現(xiàn)有驅(qū)動案例對號入座,采取相應的適配方式。

說明:GPIO模塊適配涉及到的代碼示例片段來自device/hisilicon/drivers/gpio/

OpenHarmony系統(tǒng)平臺驅(qū)動適配Linux內(nèi)核

不知道讀者有沒有思考過,如果在Linux內(nèi)核下,我們?nèi)绾芜m配一個平臺設備呢?因為HDF驅(qū)動框架是跨平臺的,所以我們?nèi)匀豢梢园凑涨懊娼榻B的方式進行驅(qū)動適配。但是,Linux內(nèi)核有大量現(xiàn)存驅(qū)動,它們一起支撐著大量SOC芯片,如果要將這些驅(qū)動按照HDF的方式重新適配,且不說難度,就工作量來說是巨大的。

那么有沒有辦法將這些現(xiàn)存驅(qū)動利用起來呢?答案就是適配器模式,它可以將一個類的接口轉(zhuǎn)換成用戶希望的另外一個接口,通過增加一點點工作量,使得現(xiàn)有對象在新環(huán)境中應用起來。在Linux內(nèi)核,HDF驅(qū)動框架時新環(huán)境,而Linux原生的設備對象,例如i2c_adapter, spi_dev,gpio_chip等等,都是舊對象,我們需要通過適配器模式,將其適配成HDF平臺驅(qū)動框架定義的I2cCntlr、SpiCntlr、GpioCntlr等新對象,從而快速將其應用起來。

具體的適配方式是,針對Linux內(nèi)核每一種平臺設備,提供一個適配驅(qū)動,將Linux原生設備對象封裝成HDF平臺驅(qū)動框架定義的設備對象,其他流程同正常硬件驅(qū)動適配一樣,由于是直接基于現(xiàn)有對象封裝,硬件初始化工作,甚至hcs配置都可以省略。

以I2C為例,在Linux下,我們將I2cCntlr直接關(guān)聯(lián)到i2c_adapter,而其鉤子方法的實現(xiàn)也是通過調(diào)用i2c_adapter相應的配套方法實現(xiàn)的,其對應關(guān)系如下:

HDF平臺驅(qū)動 Linux內(nèi)核 說明
I2cCntlr i2c_adapter 通過I2cCntlr的priv成員關(guān)聯(lián)
I2cTransfer i2c_transfer
I2cMsg i2c_msg 需要進行參數(shù)轉(zhuǎn)換

有興趣的讀者,可以通過閱讀下面的源碼,來了解Linux內(nèi)核下對各類平臺設備的適配。

drivers/adapter_del/khdf/linux/platform

總結(jié)與展望

OpenHarmony系統(tǒng)平臺驅(qū)動框架基于HDF驅(qū)動框架,為外設驅(qū)動提供標準的平臺設備訪問接口,同時為平臺設備驅(qū)動提供統(tǒng)一的適配接口,使得外設驅(qū)動僅需“關(guān)心”自身業(yè)務,而使設備驅(qū)動僅“關(guān)心”自身硬件。

為此,平臺驅(qū)動框架采用平臺接口層、平臺核心層、平臺適配層的三層結(jié)構(gòu),并抽象出平臺設備(PlatformDevice)、平臺設備管理器(PlatformManager)、等概念,形成平臺驅(qū)動框架特有的編程風格和設計思想。然而有些概念和思想,在框架實現(xiàn)中并不明顯,隨著架構(gòu)的演進,有些概念將會越來越明確,他們包括:

統(tǒng)一的平臺設備對象模型:目前各類型的設備對象模型,由各模塊自己定義,例如I2cCntlr、UartHost,他們并沒有公共的父類型,而這一公共類型,是必要的。所以,將來會抽象出PlatformDevice這一公共設備對象模型。

設備管理器:每一類設備有自己的管理器,它即充當容器,也充當管理者,在需要用戶態(tài)支持的情況下,還充當設備服務。雖然目前沒有明確的數(shù)據(jù)結(jié)構(gòu)與之對應,但是隨著架構(gòu)演進,這個概念的體現(xiàn)一定會愈加明確。

引用計數(shù):設備對象需要進行生命周期管理,設備的獲取和釋放需要計數(shù),雖然當前沒有實現(xiàn)這個機制,但是我們要求每一類設備的獲取通過Get/Put方法實現(xiàn),以便后續(xù)擴展引用計數(shù)機制

編輯:jq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • C語言
    +關(guān)注

    關(guān)注

    183

    文章

    7646

    瀏覽量

    146096
  • 編程
    +關(guān)注

    關(guān)注

    90

    文章

    3723

    瀏覽量

    97424
  • OOP
    OOP
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    9038
  • 驅(qū)動框架
    +關(guān)注

    關(guān)注

    0

    文章

    14

    瀏覽量

    4288
  • OpenHarmony
    +關(guān)注

    關(guān)注

    33

    文章

    3970

    瀏覽量

    21339

原文標題:OpenHarmony HDF 平臺驅(qū)動框架介紹及驅(qū)動適配指導

文章出處:【微信號:gh_e4f28cfa3159,微信公眾號:OpenAtom OpenHarmony】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

    寬電壓適配型吸塵器無刷電機驅(qū)動板設計與實現(xiàn)

    隨著吸塵器產(chǎn)品形態(tài)多元化,手持鋰電機型(DC 18V~25.2V)與臺式市電機型(AC 220V 整流后 DC 300V~320V)并行發(fā)展,用戶對 “單驅(qū)動適配多供電場景” 的需求日益迫切。傳統(tǒng)
    的頭像 發(fā)表于 04-14 14:31 ?43次閱讀

    RT-Thread 中設備樹的適配方法 | 技術(shù)集結(jié)

    關(guān)鍵驅(qū)動適配方法。目錄前提產(chǎn)品介紹準備開始移植DM移植要素查看需要移植的驅(qū)動開始移植驅(qū)動啟動地址工具鏈配置Earlycon配置啟動開始啟動
    的頭像 發(fā)表于 04-04 18:05 ?2935次閱讀
    RT-Thread 中設備樹的<b class='flag-5'>適配</b>方法 | 技術(shù)集結(jié)

    RK?平臺?SPI?開發(fā)完全指南(驅(qū)動?+?配置?+?測試?+?優(yōu)化)

    Linux 平臺 SPI 驅(qū)動已形成完善的開發(fā)體系,支持 Master/Slave 雙模式、多速率適配及靈活配置。本文基于 Rockchip 官方開發(fā)指南,從功能特性、驅(qū)動配置、測試
    的頭像 發(fā)表于 01-30 22:35 ?1112次閱讀
    RK?<b class='flag-5'>平臺</b>?SPI?開發(fā)完全指南(<b class='flag-5'>驅(qū)動</b>?+?配置?+?測試?+?優(yōu)化)

    一個面向單片機、事件驅(qū)動的嵌入式開發(fā)平臺介紹

    EventOS,是一個面向單片機、事件驅(qū)動的嵌入式開發(fā)平臺。它主要有兩大技術(shù)特色:一是事件驅(qū)動,二是超輕量。EventOS以及其母項目EventOS,目標是開發(fā)一個企業(yè)級的嵌入式開發(fā)平臺
    發(fā)表于 12-05 06:26

    深入解析?RK?平臺顯示驅(qū)動:格式支持、處理流程與實現(xiàn)原理

    ? ? 在嵌入式領(lǐng)域,顯示驅(qū)動是連接硬件與視覺體驗的核心橋梁。瑞芯微( Rockchip )平臺的顯示驅(qū)動以其兼容性強、適配場景廣著稱,廣泛應用于智能終端、物聯(lián)網(wǎng)設備等領(lǐng)域。本文將從支
    的頭像 發(fā)表于 12-02 07:10 ?497次閱讀
    深入解析?RK?<b class='flag-5'>平臺</b>顯示<b class='flag-5'>驅(qū)動</b>:格式支持、處理流程與實現(xiàn)原理

    分享一個驅(qū)動開發(fā)工程師學習路線圖

    框架”的演進規(guī)劃。 跨領(lǐng)域融合能力:打通驅(qū)動與上層系統(tǒng)的技術(shù)壁壘,如結(jié)合AI技術(shù)優(yōu)化驅(qū)動自適應能力(動態(tài)調(diào)整參數(shù)適配不同硬件),結(jié)合云平臺
    發(fā)表于 11-12 10:44

    【精選直播】手把手教你做PC第十二課:WIFI 驅(qū)動框架適配

    《手把手教你做PC》系列直播課再度開播!《KaihongOS筆記本電腦開發(fā)實戰(zhàn)第十二課:WIFI驅(qū)動框架適配》將于07月02日19:00開播↑掃碼入群,領(lǐng)課程講義資料包↑深開鴻資深工程師親臨直播間
    的頭像 發(fā)表于 07-01 08:08 ?688次閱讀
    【精選直播】手把手教你做PC第十二課:WIFI <b class='flag-5'>驅(qū)動</b><b class='flag-5'>框架</b><b class='flag-5'>適配</b>

    迅為RK3568開發(fā)板實操-HDF驅(qū)動配置UART

    對于不同的平臺,需要在對應的平臺目錄修改對應的 hcs 文件,接下來示例為在 rk3568下新增 uart4 uart9 uart7 的修改方法。 修改 vendor/hihope/rk3568
    的頭像 發(fā)表于 06-27 15:58 ?673次閱讀

    ArkUI-X平臺差異化

    邏輯不同,或使用了不支持跨平臺的API,就需要根據(jù)平臺不同進行一定代碼差異化適配。當前僅支持在代碼運行態(tài)進行差異化,接下來詳細介紹場景及如何差異化
    發(fā)表于 06-10 23:08

    迅為RK3568開發(fā)板實操-HDF驅(qū)動配置UART-修改HCS配置

    deviceMatchAttr 的值表示驅(qū)動的私有配置信息 5 serviceName 表示服務名稱,服務加載成功之后會在開發(fā)板的/dev/目錄下生成節(jié)點。例如 HDF_PLATFORM_UART_9 后面跟著的數(shù)據(jù) 9 是 UartOpen()的端口號
    發(fā)表于 05-22 11:32

    明晚七點!手把手教你做PC第九課:全功能TypeC驅(qū)動框架適配

    《手把手教你做PC》系列直播課再度開播!《KaihongOS筆記本電腦開發(fā)實戰(zhàn)第九課:全功能TypeC驅(qū)動框架適配》將于5月21日19:00開播↑掃碼入群,領(lǐng)課程講義資料包↑深開鴻資深工程師親臨直播
    的頭像 發(fā)表于 05-20 08:07 ?682次閱讀
    明晚七點!手把手教你做PC第九課:全功能TypeC<b class='flag-5'>驅(qū)動</b><b class='flag-5'>框架</b><b class='flag-5'>適配</b>

    KaihongOS筆記本電腦開發(fā)實戰(zhàn)第九節(jié):全功能TypeC驅(qū)動框架適配

    《手把手教你做PC》系列直播課再度開播 !《 KaihongOS筆記本電腦開發(fā)實戰(zhàn)第九節(jié)九:全功能TypeC驅(qū)動框架適配》將于5月21日19:00開播 ↑掃碼入群,領(lǐng)課程講義資料包↑ 深開鴻資深
    發(fā)表于 05-19 18:29

    ArkUI-X跨平臺框架接入指南

    ArkUI跨平臺框架(ArkUI-X)進一步將ArkUI開發(fā)框架擴展到了多個OS平臺:目前支持OpenHarmony、Android、 iO
    發(fā)表于 05-18 18:21

    如何成為一名合格的KaihongOS南向驅(qū)動開發(fā)工程師

    為新的平臺設備適配KaiHongOS驅(qū)動時,可使用KaiHongOS平臺驅(qū)動框架提供的標準模型和
    發(fā)表于 04-23 08:02

    周三晚19:00,手把手教你做PC第七課:Audio 音頻驅(qū)動框架適配

    《手把手教你做PC》系列直播課再度開播!《KaihongOS筆記本電腦開發(fā)實戰(zhàn)⑦:Audio音頻驅(qū)動框架適配》將于4月23日19:00開播↑掃碼入群,領(lǐng)課程講義資料包↑深開鴻資深工程師親臨直播間依托
    的頭像 發(fā)表于 04-22 08:05 ?665次閱讀
    周三晚19:00,手把手教你做PC第七課:Audio 音頻<b class='flag-5'>驅(qū)動</b><b class='flag-5'>框架</b><b class='flag-5'>適配</b>