Ein Beispiel, um den Prozess der Implementierung eines einfachen Treibers über das HDF-Framework von Openharmony zu verstehen

Was ist HDF?

Offizielle Beschreibung:

Das HDF-Treiber-Framework (Hardware Driver Foundation) bietet Treiber-Framework-Funktionen für Treiberentwickler, einschließlich Treiberladen, Treiberdienstverwaltung und Treibernachrichtenmechanismus. Ziel ist der Aufbau einer einheitlichen Treiberarchitekturplattform, um Treiberentwicklern eine genauere und effizientere Entwicklungsumgebung zu bieten, und strebt eine einmalige Entwicklung und eine Bereitstellung auf mehreren Systemen an.

Im Folgenden wird die einfachste Routine zum Verständnis von HDF verwendet und erläutert, wie der Openharmony-Plattformgerätetreiber (Platform Device) über das HDF-Framework entwickelt wird, um Zugriffsschnittstellen für System- und Peripherietreiber bereitzustellen.

1. Erstellen Sie einen Beispieltreiber für den Kernel-Modus-Treiber (KHDF).

In diesem Beispiel wird ein KHDF-Treiber in der V3.1-Version von Openharmony erstellt.

1.1 KHDF-Projekt erstellen

Die Schritte zum Erstellen eines KHDF-Treibers sind wie folgt:

  • Verzeichnis hinzufügen: Erstellen Sie das Verzeichnis newdevice in //driver/adapter/khdf/linux

  • Dateien hinzufügen: //driver/adapter/khdf/newdevice Dateien test_newdevice.c und Makefile hinzufügen

  • Konfiguration hinzufügen: //vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs

  • Kompilieren und brennen:

1.2 Treiberimplementierung test_newdevice.c

Registrieren Sie den Treibereintrag im HDF-Framework über HDF_INIT. Beim Laden des Treibers ruft das HDF-Framework zuerst die Bind-Funktion und dann die Init-Funktion auf, um den Treiber zu laden. Wenn die Init-Aufrufausnahme auftritt, ruft das HDF-Framework Release auf um die Treiberressourcen freizugeben und zu beenden.


// driver/adapter/khdf/newdevice/test_newdevice.c
#include "hdf_device_desc.h"
#include "hdf_dlist.h"
#include "hdf_log.h"
....
struct HdfDriverEntry g_test_newdevice = {
    .moduleVersion = 1,
    .moduleName = "test_hdf_newdevice",		// 通过此模块名匹配hcs配置文件中模块名
    .Init = HdfNewdeviceInit,				// 驱动自身业务初始的接口
    .Bind = HdfNewdeviceBind,				// 驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
    .Release = HdfNewdeviceRelease,			// 驱动资源释放的接口
};
HDF_INIT(g_test_newdevice);					// 注册到HDF框架

1.2.1 Fahrereingang

Durch die Angabe von Bind bindet HdfNewdeviceBind die relevante Dienstschnittstelle an das HDF-Framework und verarbeitet die Nachrichten von Benutzermodusanwendungen über Dispatch.


// driver/adapter/khdf/newdevice/test_newdevice.c
...
int32_t HdfNewdeviceIoServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    ...
}

int32_t HdfNewdeviceBind(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("enter %s", __func__);
    static struct IDeviceIoService newdeviceService = {
        //.Open = HdfNewdeviceDriverOpen,
        .Dispatch = HdfNewdeviceIoServiceDispatch,	// 驱动服务通过此函数进行分发处理
        //.Release = HdfnewdeviceDriverClose,
    };
    deviceObject->service = &newdeviceService;
}
...

1.2.2 Implementieren Sie die Dispatch-Methode

Definieren Sie die cmdId-Nummer von TEST_WRITE_DATA, drucken Sie die geschriebenen Daten und geben Sie die Antwortdaten zurück. HdfDeviceSendEvent kann cmdId-Nachrichten von allen Listener-HdfDevEventlistener-Objekten empfangen, die über die HdfDeviceRegisterEventListener-Methode auf der Anwendungsseite registriert wurden. HdfDevEventlistener wird auf der Anwendungsseite erläutert.


// driver/adapter/khdf/newdevice/test_newdevice.c
...
#define TEST_WRITE_DATA 1234
int32_t HdfNewdeviceIoServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
{
	HDF_LOGD("enter %s: received cmd %d", __func__, cmdId);
    if (cmdID == TEST_WRITE_DATA) {
        const char *readData = HdfSbufReadString(data);
        if (readData != NULL) {
            HDF_LOGD("%s: read data is: %s", __func__, readData);
        }
        
        if (HdfSbufWriteString(reply, "I am driver's reply string!")) {
            return HdfDeviceSendEvent(client->device, cmdId, data);
        }
    }
    HDF_LOGE("%s: return fail", __func__);
    return HDF_FAILURE;
}
...

1.2.3 Initialisierung und Freigabe des Hardware-Geschäfts

HdfNewdeviceInit implementiert die Schnittstelle, die seine eigene Geschäftsinitialisierung steuert

HdfNewdeviceRelease implementiert die Schnittstelle, die die Ressourcenfreigabe steuert


// driver/adapter/khdf/newdevice/test_newdevice.c
...
int32_t HdfNewdeviceInit(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("enter %s", __func__);
    return 0;
}
void HdfNewdeviceRelease(struct HdfDeviceObject *deviceObject)
{
    HDF_LOGD("enter %s", __func__);
}
...

1.3 Makefile

obj-y += test_newdevice.o
ccflags-y += -I$(srctree)/include/hdf \
			 -I$(srctree)/include/hdf/osal \
			 -I$(srctree)/include/hdf/utils \
			 -I$(srctree)/drivers/hdf/framework/utils/include \
			 -I$(srctree)/drivers/hdf/khdf/osal/include \
			 -I$(srctree)/bounds_checking_function/include \
			 -I$(srctree)/drivers/hdf/framework/include/core \
			 -I$(srctree)/drivers/hdf/framework/core/common/include/host \
			 -I$(srctree)/drivers/framework/core/host/include

1.4 Treiberkonfiguration

Die Konfigurationsdatei besteht aus zwei Teilen:

  • Beschreibung des Treibergeräts: Zeigt den Ladeinformationsinhalt des Treibers an. erforderlich

  • Private Treiberkonfiguration: Konfigurieren Sie die Hardwarekonfigurationsinformationen des Treibers. Optional

1.4.1 Beschreibung des Antriebsgeräts

Die vom HDF-Framework zum Laden des Treibers erforderlichen Informationen stammen aus der vom HDF-Framework definierten Treibergerätebeschreibung. Daher muss der auf Basis des HDF-Frameworks entwickelte Treiber die entsprechende Gerätebeschreibung in der vom HDF definierten Konfigurationsdatei device_info.hcs hinzufügen Framework. Die Gerätebeschreibung des Treibers wird wie folgt ausgefüllt:

// vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
 root {
 ...
     test_newdevice :: host {
     	hostName = "test_newdevice";// host名称,host节点是用来存放某一类驱动的容器
     	device_sample :: device {        // sample设备节点
     		device0 ::deviceNode {
     			policy = 2;		
     			priority = 10;	
     			preload = 0;
     			permission = 0664;
     			moduleName = "test_hdf_newdevice";
     			serviceName = "test_hdf_newdevice1";
     			deviceMatchAttr = "sample_config"; 
 			}
 		}
 	}
 ...
 }

Das Richtlinienfeld ist die Richtlinie für die Freigabe von Treiberdiensten, die im Kapitel „Openharmony-Treiberdienstverwaltung“ ausführlich beschrieben wird .

Das Prioritätsfeld steuert die Startpriorität (0-200). Je größer der Wert, desto niedriger die Priorität. Es wird empfohlen, standardmäßig 100 festzulegen. Wenn die Priorität gleich ist, ist die Ladereihenfolge des Geräts nicht garantiert.

Der Preload-Feldtreiber lädt Felder bei Bedarf

Das Berechtigungsfeld steuert die Erstellung von Geräteknotenberechtigungen

Geben Sie im Feld „moduleName“ den Treibernamen ein. Der Wert dieses Felds muss mit dem Wert „moduleName“ der Treibereintragsstruktur übereinstimmen

Das Feld „serviceName“ steuert den Namen des extern veröffentlichten Dienstes. Er muss eindeutig sein. Der Name kann in /dev des Geräts angezeigt werden.

Das Schlüsselwort für den Abgleich privater Treiberdaten im Feld „deviceMatchAttr“ muss mit dem Wert „match_attr“ in der Konfigurationstabelle für private Treiberdaten übereinstimmen

1.4.2 Private Treiberkonfiguration

Wenn der Treiber über eine private Konfiguration verfügt, können Sie eine Treiberkonfigurationsdatei hinzufügen, um einige der Standardkonfigurationsinformationen des Treibers auszufüllen. Wenn das HDF-Framework den Treiber lädt, ruft es die entsprechenden Konfigurationsinformationen über Bind ab und speichert sie in der Eigenschaft in HdfDeviceObject und Init werden an den Treiber übergeben. Beispiele für Treiberkonfigurationsinformationen sind wie folgt:

// vendor/hihope/rk3568/hdf_config/khdf/hdf.hcs
root {
    ...
    SampleDriverConfig {
        sample_version = 1;
        sample_bus = "";
        match_attr = "sample_config";//该字段的值必须和device_info.hcs中的deviceMatchAttr值一致
    }
}

Nachdem die Konfigurationsinformationen definiert wurden, muss die Konfigurationsdatei zur Konfigurationseintragsdatei hdf.hcs auf Platinenebene hinzugefügt werden.

1.5 Zusammenstellung und Brenneffekt

  • Führen Sie ./build.sh --product-name rk3568 --ccache im Stammverzeichnis aus

  • Kompilieren Sie den Kernel separat: Wechseln Sie in das Verzeichnis out/kernel/src_tmp/linux-5.10 und führen Sie ./make-ohos.sh TB-RK3568X0 aus

  • Geben Sie das Verzeichnis /dev im Entwicklungsboard ein und Sie können das Gerät test_hdf_newdevice1 anzeigen

おすすめ

転載: blog.csdn.net/procedurecode/article/details/128906246