OpenHarmony: How to use HDF driver to control LED lights

1. Program introduction

This program is a basic peripheral class written based on the OpenHarmony standard system: RGB LED.

It has been successfully run on the Lingmeng Pai-RK3568 development board. For detailed information, please refer to the official website: https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk3568-openharmony/tree/master/samples/b02_hdf_rgb_led.

For detailed information, please refer to the OpenHarmony official website:

  • GPIO platform driver development
  • GPIO application development

2. Hardware design

The overall hardware circuit of the RGB LED light is shown in the figure below. The hardware circuit contains three GPIO control pins to control the RGB LED light. A low level lights up the LED light, and a high level turns off the LED light. The circuit is simple and no redundant explanation will be given here.

3. Program analysis

1. Directory structure

b02_hdf_rgb_led
├── config              # HDF资源配置文件目录
    ├── config.hcs      # 接口IO配置文件
    ├── device_info.hcs # 设备信息配置文件
├── drivers             # 内核HDF驱动程序目录
    ├── rgb_led_drv.c   # 内核HDF驱动程序
    ├── Makefile        # 内核HDF驱动编译脚本
├── figures             # MD文档图片
├── BUILD.gn            # GN文件
├── rgb_led.c           # 应用层控制程序

2. Kernel HDF driver

(1) Interface function

  • Function name: HdfRgbLedDriverInit.
  • Function description: HDF initialization registration, reading HDF resource configuration file, and obtaining tri-color light control GPIO pins.
int32_t HdfRgbLedDriverInit(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
        return HDF_ERR_INVALID_OBJECT;
    }
    struct DeviceResourceIface *CfgOps = NULL;
    CfgOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);
    if (CfgOps == NULL || CfgOps->GetUint32 == NULL) {
        HDF_LOGE("%s: DeviceResourceGetIfaceInstance failed", __func__);
        return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_version", &g_rgbLedCfg.rgb_led_version, 0) != HDF_SUCCESS) {
        HDF_LOGE("%s: read rgb_led_version failed", __func__);
        return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_red", &g_rgbLedCfg.rgb_led_red, 0) != HDF_SUCCESS) {
        g_rgbLedCfg.rgb_led_version = 0;
        HDF_LOGE("%s: read rgb_led_red failed", __func__);
        return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_green", &g_rgbLedCfg.rgb_led_green, 0) != HDF_SUCCESS) {
        g_rgbLedCfg.rgb_led_version = 0;
        HDF_LOGE("%s: read rgb_led_green failed", __func__);
        return HDF_FAILURE;
    }
    if (CfgOps->GetUint32(deviceObject->property, "rgb_led_blue", &g_rgbLedCfg.rgb_led_blue, 0) != HDF_SUCCESS) {
        g_rgbLedCfg.rgb_led_version = 0;
        HDF_LOGE("%s: read rgb_led_blue failed", __func__);
        return HDF_FAILURE;
    }
    HDF_LOGI("g_rgbLedDriverEntry: %s success", __func__);
    return HDF_SUCCESS;
}
  • Function name: HdfRgbLedDriverRelease.
  • Function description: HDF to register.
void HdfRgbLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
        return;
    }
    HDF_LOGI("g_rgbLedDriverEntry: %s success", __func__);
    return;
}
  • Function name: HdfRgbLedDriverBind.
  • Function description: HDF binding parsing function.
int32_t HdfRgbLedDriverBind(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
        return HDF_ERR_INVALID_OBJECT;
    }
    static struct IDeviceIoService ledDriverServ = {
        .Dispatch = rgbLedDriverDispatch,
    };
    deviceObject->service = (struct IDeviceIoService *)(&ledDriverServ);
    HDF_LOGI("g_rgbLedDriverEntry: %s success NodeName[%s]", __func__,
        deviceObject->property->name);
    return HDF_SUCCESS;
}
  • Function name: rgbLedDriverDispatch.
  • Function description: Parsing function, parsing the commands issued by the application layer, executing the corresponding operations of the commands, RGB_LED_WRITE controls the three-color lights to turn on and off.
int32_t rgbLedDriverDispatch(struct HdfDeviceIoClient *client, int32_t cmdId,
    struct HdfSBuf *dataBuf, struct HdfSBuf *replyBuf)
{
    int32_t result = HDF_FAILURE;
    int32_t rgbLedMode = 0;

    if (client == NULL || client->device == NULL) {
        HDF_LOGE("driver device is NULL");
        return HDF_ERR_INVALID_OBJECT;
    }
    if (g_rgbLedCfg.rgb_led_version != RGB_LED_VERSION) {
        HDF_LOGE("driver rgb_led_version not match");
        return HDF_FAILURE;
    }
    switch (cmdId) {
        case RGB_LED_WRITE:
            result = HdfSbufReadInt32(dataBuf, &rgbLedMode);
            if (result) {
                HDF_LOGI("%s: mode:[0x%X][%s%s%s]", __func__, rgbLedMode,
                    (rgbLedMode&RGB_LED_RED_BIT)?"R":"-",
                    (rgbLedMode&RGB_LED_GREEN_BIT)?"G":"-",
                    (rgbLedMode&RGB_LED_BLUE_BIT)?"B":"-");

                LedGpioCtrl(g_rgbLedCfg.rgb_led_red, (rgbLedMode&RGB_LED_RED_BIT)?LED_ON:LED_OFF);
                LedGpioCtrl(g_rgbLedCfg.rgb_led_green, (rgbLedMode&RGB_LED_GREEN_BIT)?LED_ON:LED_OFF);
                LedGpioCtrl(g_rgbLedCfg.rgb_led_blue, (rgbLedMode&RGB_LED_BLUE_BIT)?LED_ON:LED_OFF);
            }
            break;
        default:
            HDF_LOGE("%s: receiving unknown command", __func__);
            break;
    }
    return result;
}
  • Function name: LedGpioCtrl.
  • Function description: LED GPIO control function, low level lights up the LED, high level turns off the LED.
static int32_t LedGpioCtrl(uint16_t gpio, int32_t mode)
{
    uint16_t level = GPIO_VAL_HIGH;

    if (HDF_SUCCESS != GpioSetDir(gpio, GPIO_DIR_OUT)) {
        HDF_LOGE("%s: GpioSetDir failed", __func__);
        return HDF_FAILURE;
    }

    if (mode == LED_ON) {
        level = GPIO_VAL_LOW;
    } else if (mode == LED_OFF) {
        level = GPIO_VAL_HIGH;
    }

    if (HDF_SUCCESS != GpioWrite(gpio, level)) {
        HDF_LOGE("%s: GpioWrite failed", __func__);
        return HDF_FAILURE;
    }
    return HDF_SUCCESS;
}

3. Application layer program

(1) Application layer code analysis

After the program starts, the command line parameters are obtained. If the command line does not have parameters, the RGB three-color light will run a marquee; if the command line has parameters, the corresponding red, green, and blue lights will be lit according to the low-order three-digit mapping of the parameters passed in. ; Bind the RGB three-color lamp HDF service through HdfIoServiceBind, obtain the HDF space buffer, write the lower three-digit data of the RGB three-color lamp that needs to be controlled into the buffer, and send it to the HDF driver through the RGB_LED_WRITE command to control the RGB three-color lamp. The lights go on and off. When the program ends, the HDF space buffer and HDF service are recycled.

int main(int argc, char* argv[])
{
    int ret = HDF_SUCCESS;
    int32_t mode = -1;
    if (argc == ARGS_NUM) {
        mode = atoi(argv[1]);
        /*low-3bits*/
        mode &= 0x7;
        HILOG_INFO(LOG_APP, "[%s] main enter: mode[%s%s%s][0x%X]",
            LOG_TAG,
            (mode&RGB_LED_BLUE_BIT)?"B":"-",
            (mode&RGB_LED_GREEN_BIT)?"G":"-",
            (mode&RGB_LED_RED_BIT)?"R":"-",
            mode);
        printf("RGB mode[%s%s%s][0x%X]\n",
            (mode&RGB_LED_BLUE_BIT)?"B":"-",
            (mode&RGB_LED_GREEN_BIT)?"G":"-",
            (mode&RGB_LED_RED_BIT)?"R":"-",
            mode);
    } else {
        HILOG_INFO(LOG_APP, "[%s] main enter: auto test RGB LED", LOG_TAG);
        printf("auto test RGB LED\n");
    }

    struct HdfIoService *serv = HdfIoServiceBind(RGB_LED_SERVICE_NAME);
    if (serv == NULL) {
        HILOG_ERROR(LOG_APP, "get service %s failed", RGB_LED_SERVICE_NAME);
        return -1;
    }
    struct HdfSBuf *data = HdfSbufObtainDefaultSize();
    if (data == NULL) {
        HILOG_ERROR(LOG_APP, "obtain data failed");
        return -1;
    }

    if (mode == -1) {
        mode = 0x8;
        while (mode) {
            HdfSbufFlush(data);
            if (!HdfSbufWriteInt32(data, --mode)) {
                HILOG_ERROR(LOG_APP, "write data failed");
                return -1;
            }
            ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
            sleep(1);
        }
    } else {
        if (!HdfSbufWriteInt32(data, mode)) {
            HILOG_ERROR(LOG_APP, "write data failed");
            return -1;
        }
        ret = serv->dispatcher->Dispatch(&serv->object, RGB_LED_WRITE, data, NULL);
    }

    HdfSbufRecycle(data);
    HdfIoServiceRecycle(serv);
    HILOG_INFO(LOG_APP, "[%s] main exit.", LOG_TAG);

    return ret;
}

4. Run the program

After the system starts, run the command from the command line:

rgb_led

5. Operation results

operation result:

# rgb_led
auto test RGB LED

# rgb_led 1
RGB mode[--R][0x1]
# rgb_led 2
RGB mode[-G-][0x2]
# rgb_led 3
RGB mode[-GR][0x3]
# rgb_led 4
RGB mode[B--][0x4]
# rgb_led 5
RGB mode[B-R][0x5]
# rgb_led 6
RGB mode[BG-][0x6]
# rgb_led 7
RGB mode[BGR][0x7]

Finally, I recommend an application development tool

Raise your throat! About low-code being very active in the tech world right now!

What is low code? A set of digital technology tool platforms can realize rapid construction, data orchestration, connection ecology, middle-end services, etc. based on more efficient methods such as graphical drag and drop and parameterized configuration. Achieve scenario application innovation in digital transformation with little or no code. It can alleviate or even solve the contradiction between supply and demand caused by huge market demand and traditional development productivity. It is a product of the trend of cost reduction and efficiency improvement in the process of digital transformation.

Here we introduce a useful low-code platform - JNPF rapid development platform. In recent years, it has been outstanding in terms of market performance and product competitiveness. It adopts the latest mainstream front-to-back separation framework (SpringBoot+Mybatis-plus+Ant-Design+Vue 3 ) . The code generator has low dependency and flexible expansion capabilities, allowing for flexible secondary development.

In order to support application development with higher technical requirements, the enterprise-level low-code platform represented by JNPF has almost no difference from traditional software development from database modeling, Web API construction to page design. It only uses low-code visualization mode to reduce the construction cost. The "Add, Delete, Modify and Check" function is a repetitive work. Partners who have not yet understood low-code can try to understand it.

Application: https://www.jnpfsoft.com/?csdn

With it, developers can easily get started during the development process and make full use of the experience accumulated in the traditional development model. Therefore, low-code platforms are of great help to programmers.

Guess you like

Origin blog.csdn.net/wangonik_l/article/details/132759347