一、程序簡介
該程序是基于OpenHarmony標準系統編寫的基礎外設類:RGB LED。
目前已在凌蒙派-RK3568開發板跑通。詳細資料請參考官網:https://gitee.com/Lockzhiner-Electronics/lockzhiner-rk3568-openharmony/tree/master/samples/b02_hdf_rgb_led。
詳細資料請參考OpenHarmony官網:
- GPIO平臺驅動開發
- GPIO應用程序開發
二、硬件設計
RGB LED燈整體硬件電路如下圖所示,硬件電路中包含了三個GPIO控制管腳控制RGB LED燈,低電平點亮LED燈,高電平熄滅LED燈。電路簡單,這邊不對此進行多余的說明。
三、程序解析
1、目錄結構
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、內核HDF驅動程序
(1)接口函數
- 函數名:HdfRgbLedDriverInit.
- 功能說明:HDF初始化注冊,讀取HDF資源配置文件,獲取三色燈控制GPIO管腳。
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;
}
- 函數名:HdfRgbLedDriverRelease。
- 功能說明:HDF去注冊。
void HdfRgbLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL) {
HDF_LOGE("g_rgbLedDriverEntry: %s failed", __func__);
return;
}
HDF_LOGI("g_rgbLedDriverEntry: %s success", __func__);
return;
}
- 函數名:HdfRgbLedDriverBind。
- 功能說明:HDF綁定解析函數。
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;
}
- 函數名:rgbLedDriverDispatch。
- 功能說明:解析函數,解析應用層下發的命令,執行命令對應操作,RGB_LED_WRITE控制三色燈亮滅。
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;
}
- 函數名:LedGpioCtrl。
- 功能說明:LED GPIO控制函數,低電平點亮LED,高電平熄滅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、應用層程序
(1)應用層代碼分析
程序啟動后獲取命令行參數,如果命令行不帶參數,RGB三色燈運行跑馬燈;如果命令行帶參數,根據傳入的參數的低三位映射點亮對應的紅燈、綠燈和藍燈;通過HdfIoServiceBind綁定RGB三色燈HDF服務,獲取HDF空間緩沖區,向緩沖區寫入需要控制的RGB三色燈低三位數據,通過RGB_LED_WRITE命令下發到HDF驅動中,從而控制RGB三色燈亮滅。程序運行結束,回收HDF空間緩沖區和HDF服務。
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 LEDn");
}
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;
}
四、運行程序
系統啟動后,命令行運行命令:
rgb_led
五、運行結果
運行結果:
# 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]