OpenHarmony-4.基于dayu800 GPIO 实践(2)

news2025/2/25 19:51:57
  • 基于dayu800 GPIO 进行开发

1.DAYU800开发板硬件接口

  LicheePi 4A 板载 2x10pin 插针,其中有 16 个原生 IO,包括 6 个普通 IO,3 对串口,一个 SPI。TH1520 SOC 具有4个GPIO bank,每个bank最大有32个IO:
在这里插入图片描述
  以俯视底板正面为视角,TOP为左侧,BOTTOM为右侧,GPIO对应关系如下:
在这里插入图片描述
  GPIO 号的对应关系如下图所示:
在这里插入图片描述

  从以上可以看出板载20pin插针中,4个普通GPIO对应的数字分别如下表:

在这里插入图片描述
1.2.搭建点灯环境

  给GPIO接灯,使用HiSpark_WiFi_IoT_SSL_VER.A红绿灯板,将红绿灯板和DAYU800开发版按以下方式接线:
在这里插入图片描述
  GPIO进行相应的操作:

#黄灯
echo 428 > /sys/class/gpio/export  
echo out > /sys/class/gpio/gpio428/direction 
echo 1 > /sys/class/gpio/gpio428/value  
echo 0 > /sys/class/gpio/gpio428/value

#红灯
echo 429 > /sys/class/gpio/export  
echo out > /sys/class/gpio/gpio429/direction 
echo 1 > /sys/class/gpio/gpio429/value  
echo 0 > /sys/class/gpio/gpio429/value

#绿灯
echo 430 > /sys/class/gpio/export  
echo out > /sys/class/gpio/gpio430/direction 
echo 1 > /sys/class/gpio/gpio430/value  

2.GPIO 代码框架

  • vendor/hihope/dayu800/hdf_config/khdf/device_info/device_info.hcs
 32         platform :: host {
 33             hostName = "platform_host";
 34             priority = 50;
 35             device_gpio :: device {
 36                 device0 :: deviceNode {
 37                     policy = 0;
 38                     priority = 10;
 39                     permission = 0644;
 40                     moduleName = "linux_gpio_adapter";
 41                     deviceMatchAttr = "linux_gpio_adapter";
 42                 }
 43             }
  • driver/hdf_core/adapter/khdf/linux/platform/gpio/gpio_adapter.c:
269 static int32_t LinuxGpioInit(struct HdfDeviceObject *device)
270 {
271     if (device == NULL) {
272         HDF_LOGE("%s: Fail, device is NULL.", __func__);
273         return HDF_ERR_INVALID_OBJECT;
274     }
275
276     (void)gpiochip_find(device, LinuxGpioMatchProbe);
277     HDF_LOGI("%s: dev service:%s init done!", __func__, HdfDeviceGetServiceName(device));
278     return HDF_SUCCESS;
279 }

319 struct HdfDriverEntry g_gpioLinuxDriverEntry = {
320     .moduleVersion = 1,
321     .Bind = LinuxGpioBind,
322     .Init = LinuxGpioInit,
323     .Release = LinuxGpioRelease,
324     .moduleName = "linux_gpio_adapter",
325 };
326 HDF_INIT(g_gpioLinuxDriverEntry);

  根据moduleName = "linux_gpio_adapter"进行配置之后,加载gpio hdf 驱动,调用LinuxGpioInit进行初始化,其中调用linux 内核gpiochip_find函数 遍历GPIO设备(gpio_devices)获取gpio控制器(gpio_chip).

232 static int LinuxGpioMatchProbe(struct gpio_chip *chip, void *data)
233 {
234     int32_t ret;
235     struct GpioCntlr *cntlr = NULL;
236
241     HDF_LOGI("%s: find gpio chip(start:%d, count:%u)", __func__, chip->base, chip->ngpio);
246
247     cntlr = (struct GpioCntlr *)OsalMemCalloc(sizeof(*cntlr));
252
253     cntlr->ops = &g_method;  //gpio 操作集
254     cntlr->start = (uint16_t)chip->base;
255     cntlr->count = (uint16_t)chip->ngpio;
256     ret = GpioCntlrAdd(cntlr);
263
264     HDF_LOGI("%s: add gpio controller(start:%d, count:%u) succeed",
265         __func__, cntlr->start, cntlr->count);
266     return 0; // return 0 to continue
267 }


215 static struct GpioMethod g_method = {
216     .write = LinuxGpioWrite,
217     .read = LinuxGpioRead,
218     .setDir = LinuxGpioSetDir,
219     .getDir = LinuxGpioGetDir,
220     .setIrq = LinuxGpioSetIrq,
221     .unsetIrq = LinuxGpioUnsetIrq,
222     .enableIrq = LinuxGpioEnableIrq,
223     .disableIrq = LinuxGpioDisableIrq,
224 };

3.调试GPIO代码

3.1.代码目录结构

  vendor/hihope/dayu800目录下新建sample目录,目录结构如下:

dayu800/dayu800-sig/vendor/hihope/dayu800/sample$ tree
.
├── BUILD.gn
└── hardware
    ├── BUILD.gn
    └── gpio
        ├── BUILD.gn
        ├── gpio_dayu800.c
        ├── gpio_dayu800.h
        └── main.c

2 directories, 6 files

3.2.增加编译sample

  创建模块目录//vendor/hihope/dayu800/sample,在vendor/hihope/dayu800/ohos.build module_list中添加 模块名称dayu800_sample,如下所示:

diff --git a/dayu800/ohos.build b/dayu800/ohos.build
index cea86ba..d268f2a 100644
--- a/dayu800/ohos.build
+++ b/dayu800/ohos.build
@@ -7,7 +7,8 @@
         "//vendor/hihope/dayu800/preinstall-config:preinstall-config",
         "//vendor/hihope/dayu800/resourceschedule:resourceschedule",
         "//vendor/hihope/dayu800/etc:product_etc_conf",
-        "//vendor/hihope/dayu800/audio:audio_policy_config"
+        "//vendor/hihope/dayu800/audio:audio_policy_config",
+        "//vendor/hihope/dayu800/sample:dayu800_sample"
       ]
     }
   },

3.3.新增sample目录BUILD.gn

  添加vendor/hihope/dayu800/sample/BUILD.gn文件,内容如下:

  1 import("//build/ohos.gni")
  2
  3 group("dayu800_sample") {
  4  deps = [
  5   "hardware:hardware"
  6  ]
  7 }

  创建名为"dayu800_sample"的group。group的作用是将多个target(可以是源文件、库文件或可执行文件等)组织在一起,方便进行编译和管理。在这个group中,依赖名为"hardware:hardware"的target。这个依赖关系意味着在编译"dayu800_sample"时,需要先编译并链接"hardware:hardware"这个target。通过使用group,可以更方便地管理项目的编译和构建过程。

3.4.新增sample/hardware目录下的BUILD.gn

  新建hardware目录,并添加vendor/hihope/dayu800/sample/hardware/BUILD.gn文件:

  1 import("//build/ohos.gni")
  2
  3 group("hardware") {
  4  deps = [
  5   "gpio:gpio_dayu800"
  6  ]
  7 }

  创建名为"hardware"的组(group)。该组依赖于名为"gpio:gpio_dayu800"的依赖项。这个函数的作用是将"hardware"组与"gpio:gpio_dayu800"依赖项相关联。

3.5.新增sample/hardware/gpio目录下的BUILD.gn

  新建gpio目录,并添加vendor/hihope/dayu800/sample/hardware/gpio/BUILD.gn文件,输入以下内容:

  1 import("//build/ohos.gni")
  2 import("//build/ohos/ndk/ndk.gni")
  3
  4 ohos_executable("gpio_dayu800") {
  5  sources = [
  6   "main.c",
  7   "gpio_dayu800.c"
  8  ]
  9
 10  include_dirs = [ "//commonlibrary/c_utils/base/include" ]
 11
 12  external_deps = [
 13   "c_utils:utils",
 14   "hilog_native:libhilog",
 15  ]
 16
 17  install_images = [ "system" ]
 18  part_name = "product_dayu800"
 19 }

  定义名为gpio_dayu800的可执行文件目标。该目标包含了两个源文件main.c和gpio_dayu800.c,并指定了包含目录//commonlibrary/c_utils/base/include。该目标依赖于外部库c_utils:utils和hilog_native:libhilog。最后,它指定了将生成的可执行文件安装到system镜像,并将该目标归属于product_dayu800部分。

3.6.新增sample/hardware/gpio目录下文件gpio_dayu800.c和gpio_dayu800.h

  创建vendor/hihope/dayu800/sample/hardware/gpio/gpio_dayu800.c文件,内容如下:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include "hilog/log.h"
#include "securec.h"
#include "gpio_dayu800.h"
 
int DAYU800_GPIO_Export(int gpioNum, int bExport)
{
    int ret = -1;
    char buffer[256] = {0};
 
    if (bExport) {
        (void) snprintf_s(buffer, sizeof(buffer), sizeof(buffer), "echo %d > %s", gpioNum, DAYU800_GPIO_EXPORT);
    } else {
        (void) snprintf_s(buffer, sizeof(buffer), sizeof(buffer), "echo %d > %s", gpioNum, DAYU800_GPIO_UNEXPORT);
    }
 
    sighandler_t old_handler;
    old_handler = signal(SIGCHLD, SIG_DFL);
    ret = system(buffer);
    if (ret < 0) {
        HILOG_ERROR(LOG_CORE, "set gpio%{public}d %{public}s failed", gpioNum, bExport == 1 ? "export" : "unexport");
        return DAYU800_GPIO_ERR;
    }
    (void) signal(SIGCHLD, old_handler);
    return ret;
}
 
int DAYU800_GPIO_SetDirection(int gpioNum, int direction)
{
    int ret_sprintf_s = -1;
 
    // check gpio export or not
    char gpio_file_name[128];
    (void) memset_s(gpio_file_name, sizeof(gpio_file_name), 0, sizeof(gpio_file_name));
    ret_sprintf_s = snprintf_s(gpio_file_name, sizeof(gpio_file_name), sizeof(gpio_file_name), "%s%d/direction",
                               DAYU800_GPIO_PEX, gpioNum);
    if (ret_sprintf_s != 0) {
    }
 
    if (access(gpio_file_name, F_OK) != 0) {
        HILOG_ERROR(LOG_CORE, "gpio%{public}d not export", gpioNum);
        return DAYU800_GPIO_NOT_EXPROT_ERROR;
    }
    // set gpio direction
 
    FILE *fp = NULL;
    fp = fopen(gpio_file_name, "r+");
    if (fp == NULL) {
        HILOG_ERROR(LOG_CORE, "open %{public}s%{public}d/direction failed", DAYU800_GPIO_PEX, gpioNum);
        return DAYU800_GPIO_ERR;
    }
 
    if (direction == DAYU800_GPIO_DIRECTION_IN) {
        fprintf(fp, "%s", "in");
    } else if (direction == DAYU800_GPIO_DIRECTION_OUT) {
        fprintf(fp, "%s", "out");
    }
 
    (void) fclose(fp);
    fp = NULL;
 
    return 0;
}
 
int DAYU800_GPIO_SetValue(int gpioNum, int value)
{
    int ret_sprintf_s = -1;
 
    // check gpio export or not
    char gpio_file_name[128];
    (void) memset_s(gpio_file_name, sizeof(gpio_file_name), 0, sizeof(gpio_file_name));
    ret_sprintf_s = snprintf_s(gpio_file_name, sizeof(gpio_file_name), sizeof(gpio_file_name), "%s%d/value",
                               DAYU800_GPIO_PEX, gpioNum);
    if (ret_sprintf_s != 0) {
    }
 
    if (access(gpio_file_name, F_OK) != 0) {
        HILOG_ERROR(LOG_CORE, "gpio%{public}d not export", gpioNum);
        return DAYU800_GPIO_NOT_EXPROT_ERROR;
    }
    // set gpio value
 
    FILE *fp = NULL;
    fp = fopen(gpio_file_name, "r+");
    if (fp == NULL) {
        HILOG_ERROR(LOG_CORE, "open %{public}s%{public}d/value failed", DAYU800_GPIO_PEX, gpioNum);
        return DAYU800_GPIO_ERR;
    }
 
    if (value == DAYU800_GPIO_LOW_LEVE) {
        fprintf(fp, "%s", "0");
    } else if (value == DAYU800_GPIO_HIGH_LEVE) {
        fprintf(fp, "%s", "1");
    }
 
    (void) fclose(fp);
    fp = NULL;
 
    return 0;
}
 
int DAYU800_GPIO_IsExport(int gpioNum, int *value)
{
    int ret_sprintf_s = -1;
 
    if (value == NULL) {
        return DAYU800_GPIO_ERR;
    }
    // check gpio export or not
    char gpio_file_name[128];
    (void) memset_s(gpio_file_name, sizeof(gpio_file_name), 0, sizeof(gpio_file_name));
    ret_sprintf_s = snprintf_s(gpio_file_name, sizeof(gpio_file_name), sizeof(gpio_file_name), "%s%d/value",
                               DAYU800_GPIO_PEX, gpioNum);
    if (ret_sprintf_s != 0) {
    }
 
    if (access(gpio_file_name, F_OK) != 0) {
        HILOG_INFO(LOG_CORE, "gpio%{public}d not export", gpioNum);
        *value = DAYU800_GPIO_NOT_EXPORT;
    } else {
        *value = DAYU800_GPIO_EXPORTED;
    }
    return 0;
}
 
int DAYU800_GPIO_GetDirection(int gpioNum, int *value)
{
    int ret = 0;
    int ret_sprintf_s = -1;
 
    if (value == NULL) {
        return DAYU800_GPIO_ERR;
    }
    // check gpio export or not
    char gpio_file_name[128];
    (void) memset_s(gpio_file_name, sizeof(gpio_file_name), 0, sizeof(gpio_file_name));
    ret_sprintf_s = snprintf_s(gpio_file_name, sizeof(gpio_file_name), sizeof(gpio_file_name), "%s%d/direction",
                               DAYU800_GPIO_PEX, gpioNum);
    if (ret_sprintf_s != 0) {
    }
 
    if (access(gpio_file_name, F_OK) != 0) {
        HILOG_ERROR(LOG_CORE, "gpio%{public}d not export", gpioNum);
        return DAYU800_GPIO_NOT_EXPROT_ERROR;
    }
    // get gpio direction
 
    FILE *fp = NULL;
    char buffer[20] = {0};
    fp = fopen(gpio_file_name, "r");
    if (fp == NULL) {
        HILOG_ERROR(LOG_CORE, "read %{public}s%{public}d/direction failed", DAYU800_GPIO_PEX, gpioNum);
        return DAYU800_GPIO_ERR;
    }
    (void) fread(buffer, sizeof(buffer), 1, fp);
    (void) fclose(fp);
    fp = NULL;
    if (strstr(buffer, "out") != NULL) {
        *value = DAYU800_GPIO_DIRECTION_OUT;
    } else if (strstr(buffer, "in") != NULL) {
        *value = DAYU800_GPIO_DIRECTION_IN;
    } else {
        ret = DAYU800_GPIO_ERR;
    }
    return ret;
}
 
int DAYU800_GPIO_GetValue(int gpioNum, int *value)
{
    int ret = 0;
    int ret_sprintf_s = -1;
 
    if (value == NULL) {
        return DAYU800_GPIO_ERR;
    }
    // check gpio export or not
    char gpio_file_name[128];
    (void) memset_s(gpio_file_name, sizeof(gpio_file_name), 0, sizeof(gpio_file_name));
    ret_sprintf_s = snprintf_s(gpio_file_name, sizeof(gpio_file_name), sizeof(gpio_file_name), "%s%d/value",
                               DAYU800_GPIO_PEX, gpioNum);
    if (ret_sprintf_s != 0) {
    }
 
    if (access(gpio_file_name, F_OK) != 0) {
        HILOG_ERROR(LOG_CORE, "gpio%{public}d not export", gpioNum);
        return DAYU800_GPIO_NOT_EXPROT_ERROR;
    }
    // get gpio value
 
    FILE *fp = NULL;
    char buffer[20] = {0};
    fp = fopen(gpio_file_name, "r");
    if (fp == NULL) {
        HILOG_ERROR(LOG_CORE, "read %{public}s%{public}d/value failed", DAYU800_GPIO_PEX, gpioNum);
        return DAYU800_GPIO_ERR;
    }
    (void) fread(buffer, sizeof(buffer), 1, fp);
    (void) fclose(fp);
    fp = NULL;
    if (strstr(buffer, "0") != NULL) {
        *value = DAYU800_GPIO_LOW_LEVE;
    } else if (strstr(buffer, "1") != NULL) {
        *value = DAYU800_GPIO_HIGH_LEVE;
    } else {
        ret = DAYU800_GPIO_ERR;
    }
    return ret;
}

  创建vendor/hihope/dayu800/sample/hardware/gpio/gpio_dayu800.h文件,内容如下:

#ifndef __DAYU800_GPIO_H__
#define __DAYU800_GPIO_H__
 
#define DAYU800_GPIO_EXPORT "/sys/class/gpio/export"
#define DAYU800_GPIO_UNEXPORT "/sys/class/gpio/unexport"
#define DAYU800_GPIO_PEX "/sys/class/gpio/gpio"
 
// hilog
#undef LOG_DOMAIN
#undef LOG_TAG
#define LOG_DOMAIN 0
#define LOG_TAG "GPIO_DAYU800"
 
// gpios
#define DAYU800_GPI0_1_3 427 /* IO1_3 */
#define DAYU800_GPI0_1_4 428 /* IO1_4 */
#define DAYU800_GPI0_1_5 429 /* IO1_5 */
#define DAYU800_GPI0_1_6 430 /* IO1_6 */
 
// direction
#define DAYU800_GPIO_DIRECTION_IN 0
#define DAYU800_GPIO_DIRECTION_OUT 1
 
// is export
#define DAYU800_GPIO_NOT_EXPORT 0
#define DAYU800_GPIO_EXPORTED 1
 
// errno
#define DAYU800_GPIO_ERR (-1)
#define DAYU800_GPIO_NOT_EXPROT_ERROR (-2)
 
// value high - low level
#define DAYU800_GPIO_LOW_LEVE 0
#define DAYU800_GPIO_HIGH_LEVE 1
 
/**
 * set gpio export
 * @param gpioNum gpioNum
 * @param bExport export,0:not export 1:export
 */
int DAYU800_GPIO_Export(int gpioNum, int bExport);
 
/**
 * set gpio direction
 * @param gpioNum gpioNum
 * @param direction direction,0:in 1:out
 */
int DAYU800_GPIO_SetDirection(int gpioNum, int direction);
 
/**
 * set gpio value
 * @param gpioNum gpioNum
 * @param value value,0:low 1:high
 */
int DAYU800_GPIO_SetValue(int gpioNum, int value);
 
/**
 * check gpio export or not
 * @param gpioNum gpioNum
 * @param *value export,0:not export 1:exported
 */
int DAYU800_GPIO_IsExport(int gpioNum, int *value);
 
/**
 * get gpio direction
 * @param gpioNum gpioNum
 * @param *value direction,0:in 1:out
 */
int DAYU800_GPIO_GetDirection(int gpioNum, int *value);
 
/**
 * get gpio value
 * @param gpioNum gpioNum
 * @param *value value,0:low 1:high
 */
int DAYU800_GPIO_GetValue(int gpioNum, int *value);
 
#endif /* __DAYU800_GPIO_H__ */

  以上函数提供了对Dayu800开发板GPIO的控制,包括导出、设置方向、设置值、检查导出状态、获取方向和获取值等操作。用于管理Dayu800GPIO的C函数库。以下是每个函数的功能解释:

  • DAYU800_GPIO_Export 函数用于导出或取消导出GPIO。根据输入的bExport参数,函数将构建一个命令行字符串来执行导出或取消导出操作。如果操作成功,函数返回0,否则返回错误代码。

  • DAYU800_GPIO_SetDirection 函数用于设置GPIO的方向。首先,函数检查GPIO是否已导出。然后,它打开GPIO的方向文件,并根据输入的direction参数设置为输入或输出。

  • DAYU800_GPIO_SetValue 函数用于设置GPIO的值。首先,函数检查GPIO是否已导出。然后,它打开GPIO的值文件,并根据输入的value参数设置为低电平或高电平。

  • DAYU800_GPIO_IsExport 函数用于检查GPIO是否已导出。它构建GPIO的值文件路径并检查该文件是否存在。根据检查结果,函数通过value参数返回导出状态。

  • DAYU800_GPIO_GetDirection 函数用于获取GPIO的方向。首先,函数检查GPIO是否已导出。然后,它打开GPIO的方向文件并读取方向值。根据读取的结果,函数通过value参数返回方向值。

  • DAYU800_GPIO_GetValue 函数用于获取GPIO的值。首先,函数检查GPIO是否已导出。然后,它打开GPIO的值文件并读取值。根据读取的结果,函数通过value参数返回值。

3.7.新增sample/hardware/gpio目录下的main.c

  创建vendor/hihope/dayu800/sample/hardware/gpio/main.c文件,输入以下内容:

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
 
#include "gpio_dayu800.h"
 
int main(int argc, char **argv)
{
    int gpioNum = DAYU800_GPI0_1_3;
    int bExport = DAYU800_GPIO_EXPORTED;
    int direction = DAYU800_GPIO_DIRECTION_OUT;
    int value = DAYU800_GPIO_HIGH_LEVE;
    int getValue = -1;
 
    // 检查参数数量以确保至少提供了预期的参数数量
    if (argc < 2) {
        printf("Usage 1: %s <gpioNum> \n", argv[0]);
        printf("Usage 2: %s <gpioNum> <value>\n", argv[0]);
        printf("Usage 3: %s <gpioNum> <value> <direction>\n", argv[0]);
        return DAYU800_GPIO_ERR;
    }
 
    // 判断是否有输入参数,如有,则赋值指定gpio口
    if (argv[1] != NULL) {
        getValue = atoi(argv[1]);
        if (getValue >= DAYU800_GPI0_1_3 && getValue <= DAYU800_GPI0_1_6) {
            gpioNum = getValue;
        } else {
            printf("please input the gpioNum between 427 and 430.\n");
            return DAYU800_GPIO_ERR;
        }
    }
 
    // 判断gpio口是否已经导出,如未导出则执行对应函数
    DAYU800_GPIO_IsExport(gpioNum, &getValue);
    if (getValue == DAYU800_GPIO_NOT_EXPORT) {
        DAYU800_GPIO_Export(gpioNum, bExport);
    }
 
    if (argc == 2) {
        // 设置gpio口值取反
        DAYU800_GPIO_GetValue(gpioNum, &getValue);
        if(getValue == DAYU800_GPIO_LOW_LEVE){
            value = DAYU800_GPIO_HIGH_LEVE;
        }else{
            value = DAYU800_GPIO_LOW_LEVE;
        }
        printf("gpioNum:[%d], curvalue:[%d] setvalue:[%d]\n", gpioNum, getValue,value);
    }
 
    if (argc >=3 && argc <= 4) {
        if (argv[2] != NULL) {
            //读取GPIO口设定值
            getValue = atoi(argv[2]);
            if (getValue >= DAYU800_GPIO_LOW_LEVE && getValue <= DAYU800_GPIO_HIGH_LEVE) {
                value = getValue;
            } else {
                printf("please input the gpio value 0 (low)or 1 (high).\n");
                return DAYU800_GPIO_ERR;
            }
        }
 
    }
 
    if (argc == 4) {
        if (argv[3] != NULL) {
            //读取GPIO口输入或输出设定
            getValue = atoi(argv[3]);
            if (getValue >= DAYU800_GPIO_DIRECTION_IN && getValue <= DAYU800_GPIO_DIRECTION_OUT) {
                direction = getValue;
            } else {
                printf("please input the gpio direction 0 (in)or 1 (out).\n");
                return DAYU800_GPIO_ERR;
            }
        }
    }
 
    // 设置gpio口为输入或输出模式
    DAYU800_GPIO_SetDirection(gpioNum, direction);
 
    // 设置gpio口电平高低
    DAYU800_GPIO_SetValue(gpioNum, value);
 
    // 获取对应gpio口的模式并打印
    DAYU800_GPIO_GetDirection(gpioNum, &getValue);
    printf("gpioNum:[%d], direction:[%d]\n", gpioNum, getValue);
 
    // 获取对应gpio口的电平值并打印
    DAYU800_GPIO_GetValue(gpioNum, &getValue);
    printf("gpioNum:[%d], Value:[%d]\n", gpioNum, getValue);
 
    return 0;
}

  以上函数实现了是用指令对Dayu800开发板的GPIO引脚的操作,根据输入参数的数量和值,函数执行不同的操作,并在终端打印出相应的信息。支持的指令格式如下:

Usage 1: gpio_dayu800 <gpioNum> 
Usage 2: gpio_dayu800 <gpioNum> <value>
Usage 3: gpio_dayu800 <gpioNum> <value> <direction>

3.8.编译代码

#全量编译
./build.sh --product-name dayu800 --gn-args full_mini_debug=false --ccache
编译完成后可以直接烧录out/dayu800/packages/phone/images下生成的档案。

#单模块编译
#前提是之前已全量编译过才可以使用单模块编译指令
./build.sh --product-name dayu800 --ccache --build-target product_dayu800
单模块编译后生成bin文件在out/dayu800/product_dayu800/product_dayu800/目录下的gpio_dayu800

3.9.hdc 调试

  将 gpio_dayu800推送到开发板,进入hdc工具所在目录,将编译生成的gpio_dayu800拷贝到hdc所在目录,开发板通过Type-C数据线连接到电脑,运行windows自带的“命令提示符”(cmd)窗口

#重新挂载DAYU800开发板的文件系统(以读写权限挂载)
hdc shell mount -o remount,rw /   

#推送到DAYU800开发板/system/bin/目录
hdc file send gpio_dayu800  /system/bin/

  在DAYU800开发板上运行测试程序,使用hdc shell指令进入到开发板终端

hdc shell

#接着运行测试指令:
gpio_dayu800 428
gpio_dayu800 429
gpio_dayu800 430
gpio_dayu800 428 0 1  //关灯
gpio_dayu800 428 1 1  //开灯

refer to

  • https://blog.csdn.net/lxs_vip/article/details/139391687
  • https://wiki.sipeed.com/hardware/zh/lichee/th1520/lpi4a/6_peripheral.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2306003.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML项目一键打包工具:HTML2EXE 最新版

HTML2EXE 工具可以一键打包生成EXE可执行文件。可以打包任意HTML项目或者是一个网址为单个EXE文件&#xff0c;直接打开即可运行。支持KRPano全景VR项目、WebGL游戏项目、视频播放、,课件打包、网址打包等。 下载地址&#xff1a; 最新版HTML2EXE首次发布下载地址 一、功能特点…

BGP配置华为——路径优选验证

实验拓扑 实验要求 实现通过修改AS-Path属性来影响路径选择实现通过修改Local_Preference属性来影响路径选择实现通过修改MED属性来影响路径选择实现通过修改preferred-value属性来影响路径选择 实验配置与效果 1.改名与IP配置 2.as300配置OSPF R3已经学到R2和R4的路由 3.…

深度学习基础--ResNet网络的讲解,ResNet50的复现(pytorch)以及用复现的ResNet50做鸟类图像分类

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 前言 如果说最经典的神经网络&#xff0c;ResNet肯定是一个&#xff0c;这篇文章是本人学习ResNet的学习笔记&#xff0c;并且用pytorch复现了ResNet50&…

TMDS视频编解码算法

因为使用的是DDR进行传输&#xff0c;即双倍频率采样&#xff0c;故时钟只用是并行数据数据的5倍&#xff0c;而不是10倍。 TMDS算法流程&#xff1a; 视频编码TMDS算法流程实现&#xff1a; timescale 1 ps / 1ps //DVI编码通常用于视频传输&#xff0c;将并行数据转换为适合…

深度解析SmartGBD助力Android音视频数据接入GB28181平台

在当今数字化时代&#xff0c;视频监控与音视频通信技术在各行各业的应用愈发广泛。GB28181协议作为中国国家标准&#xff0c;为视频监控设备的互联互通提供了规范&#xff0c;但在实际应用中&#xff0c;许多Android终端设备并不具备国标音视频能力&#xff0c;这限制了其在相…

前端兼容处理接口返回的文件流或json数据

参考文档&#xff1a;JavaScript | MDN 参考链接&#xff1a;Blob格式转json格式&#xff0c;拿到后端返回的json数据_blob转json-CSDN博客 参考链接&#xff1a;https://juejin.cn/post/7117939029567340557 场景&#xff1a;导入上传文件&#xff0c;导入成功&#xff0c;…

Java基础常见的面试题(易错!!)

面试题一&#xff1a;为什么 Java 不支持多继承 Java 不支持多继承主要是为避免 “菱形继承问题”&#xff08;又称 “钻石问题”&#xff09;&#xff0c;即一个子类从多个父类继承到同名方法或属性时&#xff0c;编译器无法确定该调用哪个父类的成员。同时&#xff0c;多继承…

DPVS-2:单臂负载均衡测试

上一篇编译安装了DPVS&#xff0c;这一篇开启DPVS的负载均衡测试 &#xff1a; 单臂 FULL NAT模式 拓扑-单臂 单臂模式 DPVS 单独物理机 CLINET&#xff0c;和两个RS都是另一个物理机的虚拟机&#xff0c;它们网卡都绑定在一个桥上br0 &#xff0c; 二层互通。 启动DPVS …

Classic Control Theory | 12 Real Poles or Zeros (第12课笔记-中文版)

笔记链接&#xff1a;https://m.tb.cn/h.Tt876SW?tkQaITejKxnFLhttps://m.tb.cn/h.Tt876SW?tkQaITejKxnFL

Kubernetes开发环境minikube | 开发部署MySQL单节点应用

minikube是一个主要用于开发与测试Kubernetes应用的运行环境 本文主要描述在minikube运行环境中部署MySQL单节点应用 minikube start --force kubectl get nodes 如上所示&#xff0c;启动minikube单节点运行环境 minikube ssh docker pull 如上所示&#xff0c;从MySQL官…

安装可视化jar包部署平台JarManage

一、下载 下载地址&#xff1a;JarManage 发行版 - Gitee.com &#x1f692; 下载 最新发行版 下载zip的里面linux和windows版本都有 二、运行 上传到服务器&#xff0c;解压进入目录 &#x1f69a; 执行java -jar jarmanage-depoly.jar 命令运行 java -jar jarmanage-dep…

基于数据可视化+SpringBoot+安卓端的数字化OA公司管理平台设计和实现

博主介绍&#xff1a;硕士研究生&#xff0c;专注于信息化技术领域开发与管理&#xff0c;会使用java、标准c/c等开发语言&#xff0c;以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年&#xff0c;拥有近12年的管理工作经验&#xff0c;拥有较丰富的技术架…

输入搜索、分组展示选项、下拉选取,全局跳转页,el-select 实现 —— 后端数据处理代码,抛砖引玉展思路

详细前端代码写于上一篇&#xff1a;输入搜索、分组展示选项、下拉选取&#xff0c;el-select 实现&#xff1a;即输入关键字检索&#xff0c;返回分组选项&#xff0c;选取跳转到相应内容页 —— VUE项目-全局模糊检索 【效果图】&#xff1a;分组展示选项 >【去界面操作体…

性能巅峰对决:Rust vs C++ —— 速度、安全与权衡的艺术

??关注&#xff0c;带你探索Java的奥秘&#xff01;?? ??超萌技术攻略&#xff0c;轻松晋级编程高手&#xff01;?? ??技术宝库已备好&#xff0c;就等你来挖掘&#xff01;?? ??订阅&#xff0c;智趣学习不孤单&#xff01;?? ??即刻启航&#xff0c;编…

unity学习53:UI的子容器:面板panel

目录 1 UI的最底层容器&#xff1a;canvas 1.1 UI的最底层容器&#xff1a;canvas 1.2 UI的合理结构 2 UI的子容器&#xff1a;面板panel 2.1 创建panel 2.2 面板的本质&#xff1a; image &#xff0c;就是一个透明的图片&#xff0c;1个空容器 3 面板的属性 4 面板的…

4-知识图谱的抽取与构建-4_2实体识别与分类

&#x1f31f; 知识图谱的实体识别与分类&#x1f525; &#x1f50d; 什么是实体识别与分类&#xff1f; 实体识别&#xff08;Entity Recognition&#xff09;是从文本中提取出具体的事物&#xff0c;如人名、地名、组织名等。分类&#xff08;Entity Classification&#x…

elasticsearch在windows上的配置

写在最前面&#xff1a; 上资源 第一步 解压&#xff1a; 第二步 配置两个环境变量 第三步 如果是其他资源需要将标蓝的文件中的内容加一句 xpack.security.enabled: false 不同版本的yaml文件可能配置不同&#xff0c;末尾加这个 xpack.security.enabled: true打开bin目…

详解分布式ID实践

引言 分布式ID&#xff0c;所谓的分布式ID&#xff0c;就是针对整个系统而言&#xff0c;任何时刻获取一个ID&#xff0c;无论系统处于何种情况&#xff0c;该值不会与之前产生的值重复&#xff0c;之后获取分布式ID时&#xff0c;也不会再获取到与其相同的值&#xff0c;它是…

【Rust中级教程】2.8. API设计原则之灵活性(flexible) Pt.4:显式析构函数的问题及3种解决方案

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 说句题外话&#xff0c;这篇文章一共5721个字&#xff0c;是我截至目前写的最长的一篇文章&a…

【复习】Redis

数据结构 Redis常见的数据结构 String&#xff1a;缓存对象Hash&#xff1a;缓存对象、购物车List&#xff1a;消息队列Set&#xff1a;点赞、共同关注ZSet&#xff1a;排序 Zset底层&#xff1f; Zset底层的数据结构是由压缩链表或跳表实现的 如果有序集合的元素 < 12…