This article is shared by Huawei Cloud community “Lighting LED with OpenHarmory3.0 on Xiaoxiong Micro (1)LED Driver Development”, author: Shenlongju city.

Project overview

As a representative complete development, this case can be divided into three parts: code file planning, LED lamp driver development, lighting LED business development.

1. LED driver development

1.1. Determine the directory structure

1.1.1. According to the HDF framework, the componentized drive model is taken as the core design idea

The HDF framework puts a class of device drivers in the same host. Developers can also develop and deploy driver functions separately, supporting multiple nodes for one driver. The HDF driver model is shown as follows:

1.1.2. Contents of this case

Create a new led directory under./device/st/drivers to store driver source files.

Create the led folder in the./device/st/ BEARpi_hM_micro/liteOS_A/hdF_config directory and create the driver configuration file led_config.hcs.

1.2.LED driver implementation

1.2.1. Driver implementation includes driver business code and driver entry registration. Add the following code in leD.c file

#include "hdf_device_desc.h" #include "hdf_log.h" #include "device_resource_if.h" #include "osal_io.h" #include "osal.h" #include "osal_mem.h" #include "gpio_if.h" #define HDF_LOG_TAG led_driver #define LED_WRITE_READ 1 // Write operation code 1 enum LedOps {LED_OFF, LED_ON, LED_TOGGLE,}; struct Stm32Mp1ILed { uint32_t gpioNum; }; static struct Stm32Mp1ILed g_Stm32Mp1ILed; uint8_t status = 0; Int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) { uint8_t contrl; HDF_LOGE("Led driver dispatch"); if (client == NULL || client->device == NULL) { HDF_LOGE("Led driver device is NULL"); return HDF_ERR_INVALID_OBJECT; } switch (cmdCode) {/* receive LED_WRITE_READ command from user */ case LED_WRITE_READ: */ HdfSbufReadUint8(data,&contrl); / / case LED_ON: GpioWrite(g_Stm32Mp1ILed. GPIO_VAL_LOW); status = 1; break; / / case LED_OFF: GpioWrite(g_Stm32Mp1ILed. GpioNum, GPIO_VAL_HIGH); status = 0; break; / / case LED_TOGGLE: if(status == 0) {GpioWrite(g_Stm32Mp1ILed. GpioNum, GPIO_VAL_LOW); status = 1; } else { GpioWrite(g_Stm32Mp1ILed.gpioNum, GPIO_VAL_HIGH); status = 0; } break; default: break; } /* Write the status of the LED to the reply, which can be taken to the user program */ if (! HdfSbufWriteInt32(reply, status)) { HDF_LOGE("replay is fail"); return HDF_FAILURE; } break; default: break; } return HDF_SUCCESS; } static int32_t Stm32LedReadDrs(struct Stm32Mp1ILed *led, struct Stm32Mp1ILed *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; */ ret = drsOps->GetUint32(node, "led_gpio_num", & LED ->gpioNum, 0); */ ret = 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; } // Drive external service capabilities, 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; } int32_t HdfLedDriverInit(struct HdfDeviceObject *device) {struct Stm32Mp1ILed *led = &g_stm32mp1iled; int32_t ret; if (device == NULL || device->property == NULL) { HDF_LOGE("%s: device or property NULL!" , __func__); return HDF_ERR_INVALID_OBJECT; } /* Read HCS private property */ ret = Stm32LedReadDrs(led, device->property); if (ret ! = HDF_SUCCESS) { HDF_LOGE("%s: get led device resource fail:%d", __func__, ret); return ret; */ 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; Void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject) {if (deviceObject == NULL) { HDF_LOGE("Led driver release failed!" ); return; } HDF_LOGD("Led driver release success"); return; } // Define the driver entry object, Must be a global variable of type HdfDriverEntry (defined in hdF_device_desc.h) struct HdfDriverEntry g_ledDriverEntry = {.moduleVersion = 1, .moduleName = "HDF_LED", .Bind = HdfLedDriverBind, .Init = HdfLedDriverInit, .Release = HdfLedDriverRelease, }; // Call HDF_INIT to register the driver entry into the HDF framework HDF_INIT(g_ledDriverEntry);Copy the code

1.2.2. Compile the script file

Add the following code to the LED/build.gn file to compile LED.c to HDF_LED

import("//drivers/adapter/khdf/liteos/hdf.gni")
hdf_driver("hdf_led") {
    sources = [
    "led.c",
    ]
}
Copy the code

In/device/st/drivers/BUILD. Designed.the gn file, add the following code to compile hdf_led into the kernel, “led” is the new content

1.3. Driver Configuration

HDF uses HCS as a configuration description source, driver configuration contains two parts, HDF framework definition of the driver device description and driver private configuration information.

The information required by the HDF framework for loading drivers comes from the device description defined by the HDF framework. Therefore, drivers developed based on the HDF framework must add the corresponding device description to the device_info. HCS configuration file defined by the HDF framework. So we need to add the LED device description in device\st\ bearpi_hM_Micro \ liteos_A \ hdF_config \device_info\device_info. HCS.

Device_led :: device {// LED device node device0 :: deviceNode {// LED-driven deviceNode node policy = 2; // The policy field is the policy that drives service publication. Priority = 10 is described in detail in the driver Service Management section. // Driver startup priority (0-200). A larger value indicates a lower priority. 100 is recommended by default. // The driver loads the field on demand. Permission = 0777; ModuleName = "HDF_LED"; ModuleName = "hdF_LED "; // The driver name must be moduleName. DeviceMatchAttr = "st_STm32MP157_LED "; Match_attr = match_attr = match_attr = match_attrCopy the code

1.4. Configure private driver information

If the driver has a private configuration, you can add a driver configuration file, which is used to fill in some default configuration information of the driver. When loading the driver, the HDF framework will fetch and save the corresponding configuration information in the HdfDeviceObject property, and pass it to the driver through Bind and Init. So we need to add led private configuration description in device\st\ BEARpi_hM_Micro \ liteOS_A \ hdF_config \ LED \led_config. HCS.

root { LedDriverConfig { led_gpio_num = 13; match_attr = "st_stm32mp157_led"; // The value of this field must be the same as the deviceMatchAttr value in device_info.hcs}}Copy the code

1.5. Board level configuration entry file

After the configuration information is defined, you need to add the configuration file to the board-level configuration entry file device\st\ BEARpi_HM_Micro \ liteOS_A \ hdF_config \ hdF.hcs

#include "device_info/device_info.hcs"
#include "led/led_config.hcs"
Copy the code

2. Light the LED business code

2.1. Create a directory

Writing business, be sure to at first. / applications/BearPi/BearPi – HM_Micro/samples directory path to create a new directory (or a set of directory structure), is used to store business source file.

Add the my_led_app folder under the samples folder, and create two new files build.gn and my_led_app.c

2.2. Write business code

Add the following business code to my_led_app.c

#include <fcntl.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <unistd.h> #include <stdio.h> #include "hdf_sbuf.h" #include "hdf_io_service_if.h" #define LED_WRITE_READ 1 #define LED_SERVICE "hdf_led" static int SendEvent(struct HdfIoService *serv, uint8_t eventData) { int ret = 0; struct HdfSBuf *data = HdfSBufObtainDefaultSize(); if (data == NULL) { printf("fail to obtain sbuf data! \r\n"); return 1; } struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); if (reply == NULL) { printf("fail to obtain sbuf reply! \r\n"); ret = HDF_DEV_ERR_NO_MEMORY; goto out; } /* Write data */ if (! HdfSbufWriteUint8(data, eventData)) { printf("fail to write sbuf! \r\n"); ret = HDF_FAILURE; goto out; } /* Send to driver via Dispatch */ ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply); if (ret ! = HDF_SUCCESS) { printf("fail to send service call! \r\n"); goto out; } int replyData = 0; /* If (! HdfSbufReadInt32(reply, &replyData)) { printf("fail to get service call reply! \r\n"); ret = HDF_ERR_INVALID_OBJECT; goto out; } printf("\r\nGet reply is: %d\r\n", replyData); out: HdfSBufRecycle(data); HdfSBufRecycle(reply); return ret; } int main(int argc, char **argv) { int i; Struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE); if (serv == NULL) { printf("fail to get service %s! \r\n", LED_SERVICE); return HDF_FAILURE; } for (i=0; i < argc; i++) { printf("\r\nArgument %d is %s.\r\n", i, argv[i]); } SendEvent(serv, atoi(argv[1])); HdfIoServiceRecycle(serv); printf("exit"); return HDF_SUCCESS; }Copy the code

2.3. Write the build.gn file that will BUILD the business code

The build. gn file consists of three parts (target, source file, header file path), which must be filled in by the developer. My_led_app, for example, you need to create. / applications/BearPi/BearPi – HM_Micro/samples/my_led_app/BUILD designed.the gn, and finish the following configuration.

import("//build/lite/config/component/lite_component.gni")

HDF_FRAMEWORKS = "//drivers/framework"

executable("led_lib") {
    output_name = "my_led"
    sources = [
        "my_led_app.c",
    ]

    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/core",
    "$HDF_FRAMEWORKS/include/utils",
    "$HDF_FRAMEWORKS/utils/include",
    "$HDF_FRAMEWORKS/include/osal",
    "//drivers/adapter/uhdf/posix/include",
    "//third_party/bounds_checking_function/include",
    "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
    ]

    deps = [
        "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
        "//drivers/adapter/uhdf/manager:hdf_core",
        "//drivers/adapter/uhdf/posix:hdf_posix_osal",
    ]
}

lite_component("my_led_app") {
    features = [
        ":led_lib",
    ]
}
Copy the code
  1. First, import gnI component, compile source my_led_app.c into led_lib library file
  2. The output executable name is defined by output_name as my_LED
  3. Include_dirs adds the.h header file path for my_led_app.c
  4. Add dependent libraries to dePS.
  5. Then package led_lib as lite_component and name it my_led_APP component.

2.4. Add new components

Modify the file build/lite/components/applications. The json, add the component my_sample configuration.

{
        "component": "my_sample",
        "description": "my samples",
        "optional": "true",
        "dirs": [
            "applications/BearPi/BearPi-HM_Micro/samples/my_first_app",
            "applications/BearPi/BearPi-HM_Micro/samples/my_led_app"
        ],
        "targets": [
            "//applications/BearPi/BearPi-HM_Micro/samples/my_first_app:my_app",
            "//applications/BearPi/BearPi-HM_Micro/samples/my_led_app:my_led_app"
        ],
        "rom": "",
        "ram": "",
        "output": [],
        "adapted_kernel": [ "liteos_a" ],
        "features": [],
        "deps": {
        "components": [],
        "third_party": [ ]
        }
    },
Copy the code

2.5. Modify the board configuration file

Modify the vendor/ BEARpi/BEARpi_hm_micro /config.json file and add the my_SAMPLE component entry.

{
      "subsystem": "applications",
      "components": [
         { "component": "my_sample", "features":[] },
         { "component": "bearpi_sample_app", "features":[] },
         { "component": "bearpi_screensaver_app", "features":[] }
      ]
},
Copy the code

3, compile,

In the root directory of the project, execute HB set to set the development board.

Execute the compile command:

hb build -t notest --tee -f
Copy the code

After the compilation is complete, “Build Success” is displayed, indicating that the compilation is successful.

After compiling, you can directly view the compiled firmware in the following path: \project\bearpi-hm_micro_small\out\ BEARpi-hm_Micro \ BEARpi-hm_Micro.

Folder structure description:

  • Ocompanies Image. stM32, companies companies image files
  • Img: indicates the root file system
  • Userfs_vfat. img: indicates the user file system

Perform the following three instruction copies of above three documents to applications/BearPi/BearPi – HM_Micro/tools/download_img/kernel /, the buffer so that the follow-up system to use.

cp out/bearpi_hm_micro/bearpi_hm_micro/OHOS_Image.stm32 applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/ cp out/bearpi_hm_micro/bearpi_hm_micro/rootfs_vfat.img applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/ cp  out/bearpi_hm_micro/bearpi_hm_micro/userfs_vfat.img applications/BearPi/BearPi-HM_Micro/tools/download_img/kernel/Copy the code

4, summarize

At this point, the complete project is developed, the next step is to burn and run.

To learn more, please pay attention to the IoT community, add huawei Cloud IoT Small Assistant wechat account (HWC-iot), reply to “Read” for more information.

Click to follow, the first time to learn about Huawei cloud fresh technology ~