Introduction to OpenHarmony HDF Framework


Introduction to OpenHarmony HDF Framework

The HDF driver framework of the OpenHarmony system is constructed using the C language object-oriented programming model. Through platform decoupling and kernel decoupling, it achieves the purpose of being compatible with different kernels and unifying the platform base, thereby helping developers realize the effect of one-time driver development and multi-system deployment. .

In order to achieve such a goal, the HDF driver framework of the OpenHarmony system provides:
Operating system adaptation layer (OSAL): uniformly encapsulates the kernel operating system-related interfaces, and shields the operation interfaces of different systems
; : i2c, spi, uart bus and other platform resources) support, and at the same time carry out a unified adaptation interface abstraction for the Board hardware operation, so that developers only need to develop a new hardware abstraction interface, and then they can obtain the newly added Board part driver support. Driver model:
for Device driver, providing a common driver abstraction model, mainly for two purposes:
providing a standardized device driver model, developers do not need to develop independently, and the driver deployment can be completed through configuration
Provide driver model abstraction, shield the relationship between the driver and different system components The interaction makes the driver more versatile.

The HDF driver framework of the OpenHarmony system is mainly composed of:

  • Driver base framework
  • driver
  • driver configuration file
  • driver interface

These four parts are composed.

  1. The HDF driver infrastructure provides unified hardware resource management, driver loading management, and device node management. The driver framework adopts the master-slave mode setting and consists of device manager and device host. The device manager provides unified driver management. When the device manager starts, it loads the corresponding driver device host according to the driver device information provided by the device information, and controls the host to complete the driver loading. The device host provides the environment for the driver to run, and at the same time, the preset host framework cooperates with the device manager to complete the driver loading and calling. According to business requirements, device host can have multiple instances.
  2. The driver implements the specific functions of the driver. Each driver is composed of one or more drivers, and each driver corresponds to a driver entry. driver entry mainly completes the initialization of the driver and the binding function of the driver interface;
  3. The driver configuration file (.hcs) is mainly composed of device information and device resource. The device information completes the configuration of device information (such as configuration interface release strategy, driver loading method, etc.). device resource Complete the configuration of device resources (such as GPIO pins, registers and other resource information configuration, etc.);
  4. The driver interface (HDI) provides standardized interface definition and implementation, and the driver framework provides IO services and IO dispatcher mechanisms, so that the driver interface tends to be consistent in different deployment forms.

insert image description here

HDF driver framework block diagram

The HDF framework puts a class of device drivers in the same host, and developers can also develop and deploy the driver functions independently in layers, supporting multiple nodes for one driver. The HDF framework management driver model is shown in the following figure:

insert image description here

How the HDF Driver Framework works

The device manager provides a unified driver loading management mechanism and a driver interface publishing mechanism.
When the device host environment is loaded, the device manager requests the host to load the corresponding driver according to the device information information, and the device host performs the following operations when receiving the request:

  • Load device information according to the request, find and load the driver image under the specified path or find the driver entry from the specified section address (section)
  • Find the driver device descriptor and match the corresponding device driver
  • When the driver matching is successful, load the specified driver image
  • After the driver image is successfully loaded, the host framework calls the binding interface and initialization interface of the driver entry to realize binding with the service object of the driver and initialize the device driver at the same time
  • When the service policy in the device information configuration requires external exposure of the driver interface, the driver framework will add the driver's service object to the list of service objects published externally, and external client programs can query and access the corresponding service through this list interface.

Block diagram of the working principle of the HDF driver framework:

insert image description here

HDF driver loading process analysis

OpenHarmony system driver has two driver loading methods according to the different ways of driver deployment:

  • Dynamic loading method: using the traditional so (shared library) loading method, the driver finds the driver function entry and loads it by specifying the symbol method
  • Static loading method: Compile the driver program to the specified section through scatter, and then find the driver function entry to load by accessing the address corresponding to the specified section.

The following combines a sample code to explain the driver loading process, focusing on the analysis of the kernel mode driver loading process in the static loading mode.

HDF driver loading process analysis - driver implementation 1

In the HDF driver framework, the HdfDriverEntry object is used to describe a driver implementation:

struct HdfDriverEntry{
    int32_t    moduleVersion;
    const char *moduleName;
    int32_t    (*Bind)(struct HdfDeviceObject *deviceObject);
    int32_t    (*Init)(struct HdfDeviceObject *deviceObject);
    void     (*Release)(struct HdfDeviceObject *deviceObject);
}
  • Bind interface: realize the instantiation and binding of the driver interface. If the driver interface needs to be published, it will be called during the driver loading process, and the driver service of the interface will be instantiated and bound to the deviceobject;
  • Init interface: realize the initialization of the driver, returning an error will stop the driver loading process;
  • Release interface: realize the unloading of the driver, and release the software and hardware resources of the driver instance in this interface.

HDF driver loading process analysis - driver implementation 2

int SampleDriverBind(struct HdfDeviceObject *deviceObject)
intSampleDriverInit(struct HdfDeviceObject *deviceObject)
intSampleDriverRelease(struct HdfDeviceObject *deviceObject)

struct HdfDriverEntry g_sampleDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "sample_driver",
    .Bind = SampleDriverBind,
    .Init = SampleDriverInit,
    .Release = SampleDriverRelease
};

HDF_INIT(g_sampleDriverEntry);

Expand the HDF_INIT macro:

#define HDF_SECTION    __attribute__((section(".hdf.driver")))
#define HDF_DRIVER_INIT(module)    \
const size_t    USED    ATTR    module##HdfEntry HDF SECTION = (size_t)(&(module))

insert image description here

It can be seen that HDF_INITthe macro defines a symbol of "driver module name + HdfEntry" and places it in “.hdf.driver”the section where the symbol points to. The memory address pointed to by the symbol is the address of the driver entry structure. This special section will be used to find device drivers at boot time.

HDF driver loading process analysis - get the driver list

insert image description here

The HDF driver framework realizes the indexing of the driver by storing the address of the driver entry symbol in a special section. Two special symbols _hdf_drivers_start and _hdf_drivers_end are inserted at the beginning and end of this section to mark the scope of this section. The data between the two special symbols is the driver implementation pointer.

HDF driver loading process analysis - get device list

insert image description here

After the configuration text is compiled, it will become a configuration file in binary format, in which device-related information is stored in a device_info configuration block marked with "hdf_manager". host name, boot priority, and device list information. The moduleName field in the device information will be used to match the moduleName in the driver entry, so as to match the correct driver for the device.

Analysis of HDF driver loading process - match between device and driver

When the system starts, the driver framework starts first (device manager, device host), obtains the device list by parsing the configuration file, reads the driver list by reading the ".hdf.drivers" section, and then traverses the device list and driver The list is matched, and the matching driver is loaded. The driver framework has two core managers:

  • device managerResponsible for device management, including device-related functions such as device loading, unloading, and query
  • device service managerResponsible for managing the interface services released by the device, and providing functions such as publishing and querying interface services

The driver loading is mainly led by the device manager. First, the device manager needs to parse the host list in the configuration file, and instantiate the corresponding host object according to the information in the host list. The host parses the file to obtain the associated device list, and traverses the device list to obtain the corresponding The matching driver name, and then traverse the aforementioned hdf.driver section to get the driver address based on the driver name.

HDF driver loading process analysis - loading process flow chart

insert image description here

The device manager traverses the device list, and when it finds the corresponding driver, it creates a device object instance for the device. If the policy field in the device configuration is a driver interface that needs to be released to the outside world, the bind interface of the driver will be called first to associate the device with the device. service instance. Then the driver's Init interface will be called to complete the related initialization work of the driver. If the driver is unloaded or the Init interface returns failure due to hardware and other reasons, Release will be called to release various resources requested by the driver.

Analysis of HDF driver loading process - driver framework startup
The driver framework is started by late_initcall

static init __init DeviceManagerInit(void)
{
    int ret;
    ret = DeviceManagerStart();
    return ret;
}

late_initcall(DeviceManagerInit);

late_initcall macro expansion
insert image description here

Macro meaning:

  1. Declare a function pointer of type initcall)_t named __initcall_DeviceManagerInit
  2. Initialize this function pointer as DeviceManagerInit
  3. When compiling, you need to place this function pointer variable in the section named ".initcall7.init", the essence is to place the first address of the function DeviceManagerInit in the section ".initcall7.init"

insert image description here

insert image description here

HDF driver loading process analysis - summary

  1. When the system starts, devicemanagerInit starts first through late_initcall
  2. The device manager parses the host list in the configuration file according to the device information information, and instantiates the corresponding host object according to the information in the host list
  3. The host variable device list to get the matching driver name, and then traverse the .hdf.driver section based on the driver name to get the driver address
  4. After the device and driver are successfully matched, get the entry address of the specified driver and load the corresponding device driver
  5. Call the bind interface of the specified driver to associate the device and service instance
  6. Call the init interface of the specified driver, and complete the related initialization work of the driver
  7. If the driver is uninstalled or the init interface returns failure due to hardware and other reasons, release will be called to release various resources requested by the driver.

Reference link

Guess you like

Origin blog.csdn.net/qq_37596943/article/details/128527737