日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

前言

南向小白在AlgoIdeas指導(dǎo)下的一次基于HDF框架開發(fā)溫度傳感器驅(qū)動之旅,主要內(nèi)容為開發(fā)溫度傳感器通用驅(qū)動代碼以及針對SHT31傳感器開發(fā)差異化驅(qū)動代碼,讀者可以和基于HDF驅(qū)動框架的溫度傳感器驅(qū)動開發(fā)一起看。本文旨在分享筆者開發(fā)過程中的一些經(jīng)驗,文章可能存在用詞不專業(yè)或說法有誤之處,歡迎各位指正

開發(fā)準(zhǔn)備

硬件環(huán)境

  1. Unionpi Tiger開發(fā)板
  2. SHT31溫濕度傳感器

關(guān)于SHT31溫濕度傳感器的介紹不在本篇的討論范圍內(nèi),在開發(fā)中需要用到的一些寄存器地址信息讀者可以自行查找閱讀該器件的datasheet

在開發(fā)之前我們先簡單了解一下源碼驅(qū)動目錄

在OpenHarmony根目錄下的drivershdf_coreframeworkmodelsensordriver目錄,這里存放的是通用傳感器驅(qū)動代碼目錄,主要是由HDF Sensor驅(qū)動框架提供的Init、Enable、Disable等接口實現(xiàn)

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

而在driversperipheralsensorchipset目錄下存放的是傳感器差異化驅(qū)動代碼,主要是根據(jù)不同的傳感器芯片型號在通用傳感器驅(qū)動代碼提供出來的接口上進(jìn)行開發(fā)適配,例如溫度傳感器有SHT3x、AHT系列等,這就需要分別進(jìn)行開發(fā)

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

開發(fā)流程

添加配置

在HDF框架的配置文件(例如筆者這里是vendorunionmanunionpi_tigerhdf_configkhdfdevice_infodevice_info.hcs)中的Sensor Host添加該驅(qū)動的配置信息

/* 溫度計傳感器設(shè)備HCS配置 */
device_sensor_temperature :: device {
    device0 :: deviceNode {
        policy = 1;
        priority = 130;
        preload = 0;
        permission = 0664;
        moduleName = "HDF_SENSOR_TEMPERATURE";
        serviceName = "sensor_temperature";
        deviceMatchAttr = "hdf_sensor_temperature_driver";
    }
}
device_sensor_sht31 :: device {
    device0 :: deviceNode {
        policy = 1;              // 驅(qū)動對外發(fā)布服務(wù)的策略(0-4),具體可以查看參考資料[3]
        priority = 140;          // 驅(qū)動啟動優(yōu)先級(0-200),值越大優(yōu)先級越低,建議默認(rèn)配100,優(yōu)先級相同則不保證device的加載順序。
        preload = 0;             // 驅(qū)動按需加載字段。
        permission = 0664;       // 驅(qū)動創(chuàng)建設(shè)備節(jié)點(diǎn)權(quán)限
        moduleName = "HDF_SENSOR_TEMPERATURE_SHT31";      // 驅(qū)動名稱,該字段的值必須和驅(qū)動入口結(jié)構(gòu)的moduleName值一致。
        serviceName = "hdf_temperature_sht31";    // 驅(qū)動對外發(fā)布服務(wù)的名稱,必須唯一。
        deviceMatchAttr = "hdf_sensor_temperature_sht31_driver"; // 驅(qū)動私有數(shù)據(jù)匹配的關(guān)鍵字,必須和驅(qū)動私有數(shù)據(jù)配置表中的match_attr值相等。
    }
}
 

對應(yīng)關(guān)系如下
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

通用驅(qū)動代碼開發(fā)

1.基于HDF驅(qū)動框架,按照驅(qū)動Driver Entry程序,完成溫度抽象驅(qū)動開發(fā),主要由Bind、Init、Release、Dispatch函數(shù)接口實現(xiàn)

  • 溫度傳感器驅(qū)動入口函數(shù)實現(xiàn)
/* 注冊溫度計傳感器入口數(shù)據(jù)結(jié)構(gòu)體對象 */
struct HdfDriverEntry g_sensorTemperatureDevEntry = {
    .moduleVersion = 1,                // 溫度計傳感器模塊版本號
    .moduleName = "HDF_SENSOR_TEMPERATURE",  // 溫度計傳感器模塊名,要與device_info.hcs文件里的溫度計moduleName字段值一樣
    .Bind = TemperatureBindDriver,           // 溫度計傳感器綁定函數(shù)
    .Init = TemperatureInitDriver,           // 溫度計傳感器初始化函數(shù)
    .Release = TemperatureReleaseDriver,     // 溫度計傳感器資源釋放函數(shù)
};

/* 調(diào)用HDF_INIT將驅(qū)動入口注冊到HDF框架中。在加載驅(qū)動時HDF框架會先調(diào)用Bind函數(shù),再調(diào)用Init函數(shù)加載該驅(qū)動。當(dāng)Init調(diào)用異常時,HDF框架會調(diào)用Release釋放驅(qū)動資源并退出 */
HDF_INIT(g_sensorTemperatureDevEntry);
 
  • 溫度傳感器驅(qū)動操作接口實現(xiàn)
/* 溫度計傳感器驅(qū)動對外提供的服務(wù)綁定到HDF框架 */
int32_t TemperatureBindDriver(struct HdfDeviceObject *device)
{
    CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);

    struct TemperatureDrvData *drvData = (struct TemperatureDrvData *)OsalMemCalloc(sizeof(*drvData));
    if (drvData == NULL) {
        HDF_LOGI("%s: malloc temperature drv data fail!", __func__);
        return HDF_ERR_MALLOC_FAIL;
    }

    drvData->IOService.Dispatch = DispatchTemperature;
    drvData->device = device;
    device->service = &drvData->ioService;
    g_temperatureDrvData = drvData;
    return HDF_SUCCESS;
}

/* 注冊溫度計傳感器驅(qū)動歸一化的接口函數(shù) */
static int32_t InitTemperatureOps(struct SensorCfgData *config, struct SensorDeviceInfo *deviceInfo)
{
    CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);

    deviceInfo->ops.Enable = SetTemperatureEnable;
    deviceInfo->ops.Disable = SetTemperaturedisable;
    deviceInfo->ops.SetBatch = SetTemperatureBatch;
    deviceInfo->ops.SetMode = SetTemperatureMode;
    deviceInfo->ops.SetOption = SetTemperatureOption;

    if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo), &config->sensorInfo,
            sizeof(config->sensorInfo)) != EOK) {
        HDF_LOGE("%s: Copy sensor info failed", __func__);
        return HDF_FAILURE;
    }

    return HDF_SUCCESS;
}

/* 提供給差異化驅(qū)動的初始化接口,完成溫度器件基本配置信息解析(溫度信息、溫度總線配置、溫度器件探測寄存器配置)、器件探測、器件寄存器解析 */
static int32_t InitTemperatureAfterDetected(struct SensorCfgData *config)
{
    struct SensorDeviceInfo deviceInfo;
    CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);

    if (InitTemperatureOps(config, &deviceInfo) != HDF_SUCCESS) {
        HDF_LOGE("%s: Init temperature ops failed", __func__);
        return HDF_FAILURE;
    }

    if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
        HDF_LOGE("%s: Add temperature device failed", __func__);
        return HDF_FAILURE;
    }

    if (ParseSensorRegConfig(config) != HDF_SUCCESS) {
        HDF_LOGE("%s: Parse sensor register failed", __func__);
        (void)DeleteSensorDevice(&config->sensorInfo);
        ReleaseSensorAllRegConfig(config);
        return HDF_FAILURE;
    }
    return HDF_SUCCESS;
}

/* 溫度計傳感器驅(qū)動初始化入口函數(shù),主要功能為對傳感器私有數(shù)據(jù)的結(jié)構(gòu)體對象進(jìn)行初始化,傳感器HCS數(shù)據(jù)配置對象空間分配,傳感器HCS數(shù)據(jù)配置初始化入口函數(shù)調(diào)用,傳感器設(shè)備探測是否在位功能,傳感器數(shù)據(jù)上報定時器創(chuàng)建,傳感器歸一化接口注冊,傳感器設(shè)備注冊功能 */ 
int32_t TemperatureInitDriver(struct HdfDeviceObject *device)
{
    CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
    struct TemperatureDrvData *drvData = (struct TemperatureDrvData *)device->service;
    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
    /* 工作隊列資源初始化 */
    if (InitTemperatureData(drvData) != HDF_SUCCESS) {
        HDF_LOGE("%s: Init accel config failed", __func__);
        return HDF_FAILURE;
    }
    /* 分配溫度配置信息資源 */
    drvData->temperatureCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*drvData->temperatureCfg));
    if (drvData->temperatureCfg == NULL) {
        HDF_LOGE("%s: Malloc temperature config data failed", __func__);
        return HDF_FAILURE;
    }
    /* 注冊寄存器分組信息 */
    drvData->temperatureCfg->regCfgGroup = &g_regCfgGroup[0];

    HDF_LOGI("%s: Init temperature driver success", __func__);
    return HDF_SUCCESS;
}
/* 釋放驅(qū)動初始化時分配的資源 */
void TemperatureReleaseDriver(struct HdfDeviceObject *device)
{
    CHECK_NULL_PTR_RETURN(device);

    struct TemperatureDrvData *drvData = (struct TemperatureDrvData *)device->service;
    CHECK_NULL_PTR_RETURN(drvData);
    /* 器件在位,釋放已分配資源 */
    if (drvData->detectFlag && drvData->temperatureCfg != NULL) {
        TemperatureReleaseCfgData(drvData->temperatureCfg);
    }

    OsalMemFree(drvData->temperatureCfg);
    drvData->temperatureCfg = NULL;
    /* 器件在位,銷毀工作隊列資源 */
    HdfWorkDestroy(&drvData->temperatureWork);
    HdfWorkQueueDestroy(&drvData->temperatureWorkQueue);
    OsalMemFree(drvData);
}
 

2.完成溫度傳感器抽象驅(qū)動內(nèi)部接口開發(fā),包括Enable、Disable、SetBatch、SetMode、SetOption、AccelCreateCfgData、AccelReleaseCfgData、AccelRegisterChipOps接口實現(xiàn)

/* 下發(fā)使能寄存器組的配置 */
static int32_t SetTemperatureEnable(void)
{
    int32_t ret;
    struct TemperatureDrvData *drvData = TemperatureGetDrvData();

    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
    CHECK_NULL_PTR_RETURN_VALUE(drvData->temperatureCfg, HDF_ERR_INVALID_PARAM);

    if (drvData->enable) {
        HDF_LOGE("%s: temperature sensor is enabled", __func__);
        return HDF_SUCCESS;
    }

    ret = SetSensorRegCfgArray(
        &drvData->temperatureCfg->busCfg, drvData->temperatureCfg->regCfgGroup[SENSOR_ENABLE_GROUP]);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: temperature sensor enable config failed", __func__);
        return ret;
    }

    ret = OsalTimerCreate(&drvData->temperatureTimer, SENSOR_TIMER_MIN_TIME, TemperatureTimerEntry, (uintptr_t)drvData);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: temperature create timer failed[%d]", __func__, ret);
        return ret;
    }

    ret = OsalTimerStartLoop(&drvData->temperatureTimer);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: temperature start timer failed[%d]", __func__, ret);
        return ret;
    }
    drvData->enable = true;

    return HDF_SUCCESS;
}
/* 下發(fā)去使能寄存器組的配置 */
static int32_t SetTemperatureDisable(void)
{
    int32_t ret;
    struct TemperatureDrvData *drvData = TemperatureGetDrvData();

    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
    CHECK_NULL_PTR_RETURN_VALUE(drvData->temperatureCfg, HDF_ERR_INVALID_PARAM);

    if (!drvData->enable) {
        HDF_LOGE("%s: temperature sensor had disable", __func__);
        return HDF_SUCCESS;
    }

    ret = SetSensorRegCfgArray(
        &drvData->temperatureCfg->busCfg, drvData->temperatureCfg->regCfgGroup[SENSOR_DISABLE_GROUP]);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: temperature sensor disable config failed", __func__);
        return ret;
    }

    ret = OsalTimerDelete(&drvData->temperatureTimer);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: temperature delete timer failed", __func__);
        return ret;
    }
    drvData->enable = false;
    return HDF_SUCCESS;
}
/* 配置傳感器采樣率和數(shù)據(jù)上報間隔 */
static int32_t SetTemperatureBatch(int64_t samplingInterval, int64_t interval)
{
    (void)interval;

    struct TemperatureDrvData *drvData = NULL;

    drvData = TemperatureGetDrvData();
    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);

    drvData->interval = samplingInterval;

    return HDF_SUCCESS;
}
/* 設(shè)置傳感器工作模式,當(dāng)前支持實時模式 */
static int32_t SetTemperatureMode(int32_t mode)
{
    if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
        HDF_LOGE("%s: The current mode is not supported", __func__);
        return HDF_FAILURE;
    }

    return HDF_SUCCESS;
}
/* 設(shè)置傳感器可選配置 */
static int32_t SetTemperatureOption(uint32_t option)
{
    (void)option;
    return HDF_SUCCESS;
}
/* 創(chuàng)建傳感器配置數(shù)據(jù)接口 */
struct SensorCfgData *TemperatureCreateCfgData(const struct DeviceResourceNode *node)
{
    struct TemperatureDrvData *drvData = TemperatureGetDrvData();

    if (drvData == NULL || node == NULL) {
        HDF_LOGE("%s: Temperature node pointer NULL", __func__);
        return NULL;
    }
    /* 如果探測不到器件在位,返回進(jìn)行下個器件探測 */
    if (drvData->detectFlag) {
        HDF_LOGE("%s: Temperature sensor have detected", __func__);
        return NULL;
    }

    if (drvData->temperatureCfg == NULL) {
        HDF_LOGE("%s: Temperature temperatureCfg pointer NULL", __func__);
        return NULL;
    }
	/* 解析器件HCS私有配置信息 */
    if (GetSensorBaseConfigData(node, drvData->temperatureCfg) != HDF_SUCCESS) {
        HDF_LOGE("%s: Get sensor base config failed", __func__);
        goto BASE_CONFIG_EXIT;
    }
    /* 如果探測不到器件在位,返回進(jìn)行下個器件探測 */
    if (DetectSensorDevice(drvData->temperatureCfg) != HDF_SUCCESS) {
        HDF_LOGI("%s: Temperature sensor detect device no exist", __func__);
        drvData->detectFlag = false;
        goto BASE_CONFIG_EXIT;
    }

    drvData->detectFlag = true;
    /* 器件寄存器解析 */
    if (InitTemperatureAfterDetected(drvData->temperatureCfg) != HDF_SUCCESS) {
        HDF_LOGE("%s: Temperature sensor detect device no exist", __func__);
        goto INIT_EXIT;
    }
    return drvData->temperatureCfg;

INIT_EXIT:
    (void)ReleaseSensorBusHandle(&drvData->temperatureCfg->busCfg);
BASE_CONFIG_EXIT:
    drvData->temperatureCfg->root = NULL;
    (void)memset_s(
        &drvData->temperatureCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
    (void)memset_s(&drvData->temperatureCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
    (void)memset_s(&drvData->temperatureCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
    return drvData->temperatureCfg;
}
/* 釋放傳感器配置數(shù)據(jù)接口 */
void TemperatureReleaseCfgData(struct SensorCfgData *temperatureCfg)
{
    CHECK_NULL_PTR_RETURN(temperatureCfg);

    (void)DeleteSensorDevice(&temperatureCfg->sensorInfo);
    ReleaseSensorAllRegConfig(temperatureCfg);
    (void)ReleaseSensorBusHandle(&temperatureCfg->busCfg);

    temperatureCfg->root = NULL;
    (void)memset_s(&temperatureCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
    (void)memset_s(&temperatureCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
    (void)memset_s(&temperatureCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
}
/* 注冊傳感器差異化接口 */
int32_t TemperatureRegisterChipOps(const struct TemperatureOpsCall *ops)
{
    struct TemperatureDrvData *drvData = TemperatureGetDrvData();

    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
    CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM);

    drvData->ops.Init = ops->Init;
    drvData->ops.ReadData = ops->ReadData;
    return HDF_SUCCESS;
}
 

差異化驅(qū)動代碼開發(fā)

1.基于HDF驅(qū)動框架,按照驅(qū)動Driver Entry程序,完成溫度傳感器差異化驅(qū)動開發(fā),主要由Bind、Init、Release、Dispatch函數(shù)接口實現(xiàn)

/* 溫度計傳感器差異化驅(qū)動消息交互 */
static int32_t DispatchSHT31(struct HdfDeviceIoClient *client, int cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    (void)client;
    (void)cmd;
    (void)data;
    (void)reply;

    return HDF_SUCCESS;
}
/* 溫度計傳感器差異化驅(qū)動對外提供的服務(wù)綁定到HDF框架 */
int32_t SHT31BindDriver(struct HdfDeviceObject *device)
{
    CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);

    struct SHT31DrvData *drvData = (struct SHT31DrvData *)OsalMemCalloc(sizeof(*drvData));
    if (drvData == NULL) {
        HDF_LOGE("%s: Malloc SHT31 drv data fail", __func__);
        return HDF_ERR_MALLOC_FAIL;
    }

    drvData->ioService.Dispatch = DispatchSHT31;
    drvData->device = device;
    device->service = &drvData->ioService;
    g_sht31DrvData = drvData;

    return HDF_SUCCESS;
}
/* 溫度計傳感器差異化驅(qū)動初始化 */
int32_t SHT31InitDriver(struct HdfDeviceObject *device)
{
    int32_t ret;
    struct TemperatureOpsCall ops;

    CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
    struct SHT31DrvData *drvData = (struct SHT31DrvData *)device->service;
    CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);

    drvData->sensorCfg = TemperatureCreateCfgData(device->property);
    if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
        HDF_LOGD("%s: Creating temperaturecfg failed because detection failed", __func__);
        return HDF_ERR_NOT_SUPPORT;
    }

    ops.Init = NULL;
    ops.ReadData = ReadSHT31Data;
    ret = TemperatureRegisterChipOps(&ops);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: Register SHT31 temperature failed", __func__);
        return HDF_FAILURE;
    }

    ret = InitSHT31(drvData->sensorCfg);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("%s: Init SHT31 temperature failed", __func__);
        return HDF_FAILURE;
    }

    HDF_LOGI("%s: Init SHT31 temperature success", __func__);
    return HDF_SUCCESS;
}
/* 釋放驅(qū)動初始化時分配的資源 */
void SHT31ReleaseDriver(struct HdfDeviceObject *device)
{
    CHECK_NULL_PTR_RETURN(device);

    struct SHT31DrvData *drvData = (struct SHT31DrvData *)device->service;
    CHECK_NULL_PTR_RETURN(drvData);

    if (drvData->sensorCfg != NULL) {
        TemperatureReleaseCfgData(drvData->sensorCfg);
        drvData->sensorCfg = NULL;
    }
    OsalMemFree(drvData);
}
/* 溫度傳感器差異化驅(qū)動對應(yīng)的HdfDriverEntry對象 */
struct HdfDriverEntry g_temperatureSHT31DevEntry = {
    .moduleVersion = 1,
    .moduleName = "HDF_SENSOR_TEMPERATURE_SHT31",
    .Bind = SHT31BindDriver,
    .Init = SHT31InitDriver,
    .Release = SHT31ReleaseDriver,
};

HDF_INIT(g_temperatureSHT31DevEntry);
 

2.完成溫度傳感器差異化驅(qū)動中差異化接口ReadData函數(shù)實現(xiàn)

int32_t ReadSHT31Data(struct SensorCfgData *data)
{
    int32_t ret;
    static int32_t tmp;
    struct TemperaturemeterData temperaturemeterData = {0};
    OsalTimespec time;
    struct SensorReportEvent event;

    (void)memset_s(&time, sizeof(time), 0, sizeof(time));
    (void)memset_s(&event, sizeof(event), 0, sizeof(event));

    if (OsalGetTime(&time) != HDF_SUCCESS) {
        HDF_LOGE("%s: Get time failed", __func__);
        return HDF_FAILURE;
    }
    event.timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT;

    ret = ReadSHT31RawData(data, &temperaturemeterData);
    if (ret != HDF_SUCCESS) {
        return HDF_FAILURE;
    }

    event.sensorId = data->sensorInfo.sensorId;
    event.mode = SENSOR_WORK_MODE_REALTIME;

    tmp = temperaturemeterData.temperature;

    event.dataLen = sizeof(tmp);
    event.data = (uint8_t *)&tmp;
    ret = ReportSensorEvent(&event);
    return ret;
}
 

添加差異化配置文件

sht31_config.hcs文件參考

文件路徑

vendorunionmanunionpi_tigerhdf_configkhdfsensortemperaturesht31_config.hcs
 
#include "../sensor_common.hcs"
root {
    temperature_sht31_chip_config : sensorConfig {
        match_attr = "hdf_sensor_temperature_sht31_driver";
        sensorInfo :: sensorDeviceInfo {
            sensorName = "temperaturemeter";
            vendorName = "sensirion_sht31"; // max string length is 16 bytes
            sensorTypeId = 9; // enum SensorTypeTag
            sensorId = 1; // user define sensor id
            power = 230;
            minDelay = 0;
            maxDelay = 0;
        }
        sensorBusConfig :: sensorBusInfo {
            busType = 0; // 0:i2c 1:spi
            busNum = 5;
            busAddr = 0x45;
            regWidth = 2; // 2 byte
        }
        sensorIdAttr :: sensorIdInfo {
            chipName = "sht31";
            chipIdRegister = 0xF32D;
            chipIdValue = 0x80;
        }
        sensorRegConfig {
            /*  regAddr: register address
                value: config register value
                len: size of value
                mask: mask of value
                delay: config register delay time (ms)
                opsType: enum SensorOpsType 0-none 1-read 2-write 3-read_check 4-update_bit
                calType: enum SensorBitCalType 0-none 1-set 2-revert 3-xor 4-left shift 5-right shift
                shiftNum: shift bits
                debug: 0-no debug 1-debug
                save: 0-no save 1-save
            */
            /* regAddr, value, mask, len, delay, opsType, calType, shiftNum, debug, save */
            initSeqConfig = [
                0x30A2,    0x0, 0x0,   0,     5,       2,       0,        0,     0,    0
            ];
            enableSeqConfig = [
                0x2C06,    0x0, 0x0,   0,     5,       2,       0,        0,     0,    0
            ];
            disableSeqConfig = [
                0x2400,    0x0, 0x0,   0,     5,       2,       0,        0,     0,    0
            ];
        }
    }
}
 

對應(yīng)關(guān)系如下
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

編譯準(zhǔn)備

打開vendorunionmanunionpi_tigerhdf_configkhdfsensorsensor_config.hcs文件并include差異化配置文件

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

修改drivershdf_coreadapterkhdflinuxmodelsensorMakefile編譯文件

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

修改drivershdf_coreadapterkhdflinuxmodelsensorKconfig配置文件

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

deviceboardunionmanunionpi_tigerkernelbuildunionpi_tiger_standard_defconfig打開CONFIG_DRIVERS_HDF_SENSOR
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)
對應(yīng)關(guān)系如下
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

運(yùn)行結(jié)果

成功初始化SHT31傳感器驅(qū)動
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

測試

測試代碼參考

代碼路徑

vendorunionmanunionpi_tigersamplehdftemperaturetemperature.cpp
 
#include <unistd.h>
#include <stdio.h>
#include "hdf_base.h"
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"
#include "sensor_if.h"
#include "sensor_type.h"

/* 創(chuàng)建回調(diào)函數(shù) */
int32_t SensorDataCallback(const struct SensorEvents *event)
{
    if (event == NULL) {
        return HDF_FAILURE;
    }
    float *data = (float *)event->data;
    printf("sensor data %.2f°Cn", *data);
    return HDF_SUCCESS;
}

void SensorSample(void)
{
    int ret;
    struct SensorInformation *sensorInfo = NULL;
    int32_t count = 0;
    int32_t sensorInterval = 200000000; /* 數(shù)據(jù)采樣率設(shè)置200毫秒,單位納秒 */
    int32_t reportInterval = 400000000;

    /* 1.創(chuàng)建傳感器接口實例 */
    const struct SensorInterface *sensorDev = NewSensorInterfaceInstance();
    if (sensorDev == NULL) {
        return;
    }
    printf("NewSensorInterfaceInstance successn");
    /* 2.訂閱者注冊傳感器數(shù)據(jù)回調(diào)處理函數(shù) */
    ret = sensorDev->Register(0, SensorDataCallback);
    if (ret != 0) {
        return;
    }
    printf("Register successn");
    /* 3.獲取設(shè)備支持的Sensor列表 */
    ret = sensorDev->GetAllSensors(&sensorInfo, &count);
    if (ret != 0) {
        return;
    }
    printf("GetAllSensors success,count: %dn sensorName:%sn vendorName:%sn sensorTypeId:%dn sensorId:%dn", count,
           sensorInfo->sensorName, sensorInfo->vendorName, sensorInfo->sensorTypeId, sensorInfo->sensorId);
    /* 4.設(shè)置傳感器采樣率 */
    ret = sensorDev->SetBatch(sensorInfo->sensorId, sensorInterval, reportInterval);
    if (ret != 0) {
        printf("SetBatch failedn ,ret: %d", ret);
        return;
    }
    printf("SetBatch successn");
    /* 5.使能傳感器 */
    ret = sensorDev->Enable(sensorInfo->sensorId);
    if (ret != 0) {
        return;
    }
    printf("Enable successn");

    usleep(2000 * 1000);

    /* 6.去使能傳感器 */
    ret = sensorDev->Disable(sensorInfo->sensorId);
    if (ret != 0) {
        printf("Disable failedn ,ret: %d", ret);
        return;
    }
    printf("Disable successn");
    /* 7.取消傳感器數(shù)據(jù)訂閱函數(shù) */
    ret = sensorDev->Unregister(0, SensorDataCallback);
    if (ret != 0) {
        return;
    }
    printf("Unregister successn");
    /* 8.釋放傳感器接口實例 */
    ret = FreeSensorInterfaceInstance();
    if (ret != 0) {
        return;
    }
    printf("FreeSensorInterfaceInstance successn");
}

int main(int argc, char *argv[])
{
    SensorSample();
    return HDF_SUCCESS;
}
 

BUILD.gn參考

import("//build/ohos.gni")

ohos_executable("temperature") {
  sources = [ "temperature.cpp" ]

  deps = [ "//drivers/peripheral/sensor/hal:hdi_sensor" ]

  external_deps = [
    "hiviewdfx_hilog_native:libhilog",
  ]

  cflags = [
    "-Wall",
    "-Wextra",
    "-Werror",
    "-Wno-format",
    "-Wno-format-extra-args",
  ]

  install_enable = true
  install_images = [ "vendor" ]
  module_install_dir = "bin"
  part_name = "unionman_products"
}
 

編譯命令

./build.sh --product-name unionpi_tiger --build-target vendor/unionman/unionpi_tiger/sample/hdf/temperature:temperature
 

生成可執(zhí)行文件所在位置

outunionpi_tigerdevice_unionpi_tigerunionman_products
 

將可執(zhí)行文件push到system/bin目錄下,添加執(zhí)行權(quán)限

hdc shell mount -o remount,rw /
hdc file send <PATH>outunionpi_tigerdevice_unionpi_tigerunionman_productstemperature /system/bin
hdc shell chmod 744 system/bin/temperature
 

運(yùn)行結(jié)果

成功打印驅(qū)動上報的溫度數(shù)據(jù)
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

踩坑記錄

基本上按照HDF框架開發(fā)步驟來還是比較簡單的,筆者是第一次玩驅(qū)動開發(fā),相信對驅(qū)動開發(fā)熟悉的開發(fā)者來說HDF框架是很友好的。筆者踩的一些坑主要是因為筆者對南向開發(fā)不熟悉,沒有玩過硬件

1.這款傳感器的寄存器地址是兩個字節(jié),而HDF框架源碼的邏輯只能處理一個字節(jié),會出現(xiàn)以下錯誤
OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

這里就不放出筆者修改的代碼了,這部分源碼后續(xù)官方應(yīng)該會優(yōu)化

2.由于這款傳感器沒有chipId,所以私有化配置文件中的chipIdValue字段的值填寫打印出來的128,也就是0x80(這樣做可能不太正規(guī),有更好的做法歡迎指出)

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

3.由于筆者不太理解ReadSensor接口中的regAddr參數(shù),傳了不正確的值

int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)

導(dǎo)致出現(xiàn)了如下結(jié)果

OpenHarmony南向之旅之HDF傳感器驅(qū)動開發(fā)-開源基礎(chǔ)軟件社區(qū)

結(jié)語

以上僅為個人淺見,如有疑問,歡迎留言交流

參考文檔

[1]Sensor驅(qū)動模型接口說明

[2]drivers_peripheral

[3]驅(qū)動服務(wù)管理

分享到:
標(biāo)簽:OpenHarmony
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學(xué)四六

運(yùn)動步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績評定2018-06-03

通用課目體育訓(xùn)練成績評定