前言
南向小白在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)境
- Unionpi Tiger開發(fā)板
- SHT31溫濕度傳感器
關(guān)于SHT31溫濕度傳感器的介紹不在本篇的討論范圍內(nèi),在開發(fā)中需要用到的一些寄存器地址信息讀者可以自行查找閱讀該器件的datasheet
在開發(fā)之前我們先簡單了解一下源碼驅(qū)動目錄
在OpenHarmony根目錄下的drivershdf_coreframeworkmodelsensordriver
目錄,這里存放的是通用傳感器驅(qū)動代碼目錄,主要是由HDF Sensor驅(qū)動框架提供的Init、Enable、Disable等接口實現(xiàn)
而在driversperipheralsensorchipset
目錄下存放的是傳感器差異化驅(qū)動代碼,主要是根據(jù)不同的傳感器芯片型號在通用傳感器驅(qū)動代碼提供出來的接口上進(jìn)行開發(fā)適配,例如溫度傳感器有SHT3x、AHT系列等,這就需要分別進(jìn)行開發(fā)
開發(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)系如下
通用驅(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)系如下
編譯準(zhǔn)備
打開vendorunionmanunionpi_tigerhdf_configkhdfsensorsensor_config.hcs
文件并include差異化配置文件
修改drivershdf_coreadapterkhdflinuxmodelsensorMakefile
編譯文件
修改drivershdf_coreadapterkhdflinuxmodelsensorKconfig
配置文件
deviceboardunionmanunionpi_tigerkernelbuildunionpi_tiger_standard_defconfig
打開CONFIG_DRIVERS_HDF_SENSOR
對應(yīng)關(guān)系如下
運(yùn)行結(jié)果
成功初始化SHT31傳感器驅(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ù)
踩坑記錄
基本上按照HDF框架開發(fā)步驟來還是比較簡單的,筆者是第一次玩驅(qū)動開發(fā),相信對驅(qū)動開發(fā)熟悉的開發(fā)者來說HDF框架是很友好的。筆者踩的一些坑主要是因為筆者對南向開發(fā)不熟悉,沒有玩過硬件
1.這款傳感器的寄存器地址是兩個字節(jié),而HDF框架源碼的邏輯只能處理一個字節(jié),會出現(xiàn)以下錯誤
這里就不放出筆者修改的代碼了,這部分源碼后續(xù)官方應(yīng)該會優(yōu)化
2.由于這款傳感器沒有chipId,所以私有化配置文件中的chipIdValue字段的值填寫打印出來的128,也就是0x80(這樣做可能不太正規(guī),有更好的做法歡迎指出)
3.由于筆者不太理解ReadSensor接口中的regAddr參數(shù),傳了不正確的值
int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)
導(dǎo)致出現(xiàn)了如下結(jié)果
結(jié)語
以上僅為個人淺見,如有疑問,歡迎留言交流
參考文檔
[1]Sensor驅(qū)動模型接口說明
[2]drivers_peripheral
[3]驅(qū)動服務(wù)管理