在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

北京迅為iTOP-RK3568開發板OpenHarmony系統南向驅動開發實操-HDF驅動配置LED

北京迅為電子 ? 2025-03-14 14:41 ? 次閱讀

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工藝,搭載一顆四核Cortex-A55處理器和Mali G52 2EE 圖形處理器。RK3568 支持4K 解碼和 1080P 編碼,支持SATA/PCIE/USB3.0 外圍接口。RK3568內置獨立NPU,可用于輕量級人工智能應用。RK3568 支持安卓 11 和 linux 系統,主要面向物聯網網關、NVR 存儲、工控平板、工業檢測、工控盒、卡拉 OK、云終端、車載中控等行業。

wKgZPGfTzx2AQ0JgAAavPtFHEao168.png

?

【本文摘自】【北京迅為】iTOP-RK3568OpenHarmony系統南向驅動開發

【相關視頻】OpenHarmony學習開發系列教程(第1期 北向基礎篇一)

OpenHarmony學習開發系列教程(第2期 南向基礎篇一)

第3章 實操-HDF驅動配置LED

從本章節開始,我們來實操一下,配置HDF驅動控制LED。

3.1 查看原理圖

首先打開底板原理圖,如下圖所示:

wKgZPGfTzxqAKoBjAADXE6IxSwo198.png

由上圖可以看出,LED燈是由GPIO0_B7控制的。當GPIO0_B7為高電平時,三極管Q16導通,LED9點亮。當GPIO0_B7為低電平時,三極管Q16截止,LED9不亮。由1.2小節可以計算出GPIO的引腳編號是15。

3.2 修改HCS硬件配置

驅動的設備描述修改/vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs文件,添加如下代碼,如下所示:

device_topeet_led :: device {

device0::deviceNode {

policy = 2;

priority = 100;

preload = 0;

permission = 0666;

moduleName = "topeet_led_driver";

serviceName = "topeet_led_service";

deviceMatchAttr = "topeet_led_config";

}

}

wKgZPGfTzxqAWZ1XAAD3nYebN4U329.png

接下來解釋一下上面的節點配置

device_topeet_led設備節點歸類于platform這個host

device_topeet_led :: device表示led類設備

device0::deviceNode表示led類設備下的某個具體設備節點的配置

policy = 2;表示驅動服務發布策略,內核態用戶態都可調用

priority = 100;表示驅動啟動優先級

preload = 0;表示驅動按需加載字段,啟動加載

permission = 0666;表示驅動創建設備節點

moduleName = "topeet_led_driver";表示驅動名稱是topeet_led_driver,必須和驅動入口結構中的moduleName值一致。

serviceName = "topeet_led_service";表示驅動對外發布服務的名稱,必須唯一

deviceMatchAttr = "topeet_led_config";表示驅動私有數據匹配關鍵詞,必須和驅動私有數據配置節點的match_attr匹配

3.3 創建私有配置文件

接下來新建vendor/hihope/rk3568/hdf_config/khdf/topeet/topeet_config.hcs文件,topeet_config.hcs為驅動私有配置文件,用來填寫一些驅動的默認配置信息。HDF 框架在加載驅動時,會獲取相應的配置信息并將其保存在 HdfDeviceObject 的 property 中。這些配置信息通過 Bind 和 Init 方法傳遞給驅動。

topeet_config.hcs具體內容如下所示:

root {

platform{

topeet_led_config {

//該字段的值必須和device_info.hcs中的deviceMatchAttr一致

match_attr = "topeet_led_config";

led_version = 1;//版本號

led_number = 15;//GPIO引腳號

}

}

}

驅動私有配置文件寫完之后,我們需要將該配置文件添加到板級配置入口文件vendor/hihope/rk3568/hdf_config/khdf/hdf.hcs中,如下圖所示:

wKgZPGfTzxyAUWWsAAEn1XLZ-go862.png

3.4 新增topeet子系統

在Openharmony源碼根目錄下新建topeet文件夾及其文件夾下的文件。目錄如下所示:

wKgZPGfTzxqAdCY1AAB6MCVZHKg478.png

接下來依次解釋一下每個文件的作用。

bundle.json:

demos:組件目錄

hdf_led:子組件目錄

app:led應用層目錄

├── BUILD.gn:應用APP的GN文件

└── led_test.c:應用層LED測試程序

driver:內核HDF驅動程序目錄

├── led_driver.c:內核LED HDF驅動程序

└── Makefile:內核LED HDF驅動編譯腳本

3.4.1 編寫bundle.json文件

bundle.json文件內容如下所示:

{

"name":"@ohos/demos",

"description":"topeet demos",

"version":"4.1",

"license":"Apache-2.0",

"publishAs":"code-segment",

"segment":{

"destPath":"topeet/demos"

},

"dirs":{},

"scripts":{},

"component":{

"name":"demos",

"subsystem":"topeet",

"features":[],

"syscap":[],

"adapted_system_type":["standard"],

"rom":"675KB",

"ram":"7400KB",

"deps":{

"components":[

"c_utils",

"hilog",

"hdf_core",

"napi"

],

"third_party":[]

},

"build":{

"sub_component":[

"http://topeet/demos/hdf_led/app:led_test"

]

}

}

}

下面是對各個字段的解釋:

name: "@ohos/demos" - 這是組件或項目的名稱,這里表示它屬于OHOS(OpenHarmony OS)生態系統下的一個名為"demos"的組件。

description: "topeet demos" -它描述了組件的簡短說明

version: "4.1" - 組件的版本號。

license: "Apache-2.0" - 組件使用的許可證類型,這里是Apache 2.0許可證。

publishAs: "code-segment" - 表示這個組件或項目是以代碼段的形式發布的。

segment:

destPath: "topeet/demos" - 代碼段的目標路徑,即這個組件或項目在系統中的存放位置。

dirs: {} - 一個空對象,可能用于定義與組件相關的目錄結構,但在這個配置中未使用。

scripts: {} - 一個空對象,可能用于定義與組件相關的腳本,如構建腳本、測試腳本等,但在這個配置中未使用。

component:

name: "demos" - 組件的名稱。

subsystem: "topeet" - 組件所屬的子系統名稱。

features: [] - 組件的功能列表,這里為空,表示沒有列出特定功能。

syscap: [] - 系統能力列表,這里為空,表示沒有列出特定的系統能力。

adapted_system_type: ["standard"] - 適配的系統類型,這里表示適用于標準系統。

rom: "675KB" - 組件所需的ROM大小。

ram: "7400KB" - 組件所需的RAM大小。

deps:

components: ["c_utils", "hilog", "hdf_core", "napi"] - 組件依賴的其他組件列表。

third_party: [] - 第三方依賴列表,這里為空。

build:

sub_component: ["http://topeet/demos/hdf_led/app:led_test"] - 構建時包含的子組件路徑,這里指定了一個具體的構建目標。

這個JSON配置文件提供了關于如何構建、部署和管理這個名為"demos"的組件的詳細信息。它定義了組件的基本屬性、依賴關系、構建信息以及目標系統類型等。

3.4.2 編寫內核LED HDF驅動程序

接下來編譯LED驅動,該驅動用于在基于華為設備框架(HDF)的系統中控制LED燈的開關,完整代碼如下所示:

#include "device_resource_if.h"

#include "hdf_device_desc.h"

#include "hdf_log.h"

#include "gpio_if.h"

#define HDF_LOG_TAG led_driver

#define LED_WRITE 1

#define LED_VERSION 1

#define LED_ON 1

#define LED_OFF 0

struct Led_config{

uint32_t led_version;

uint32_t led_number;

};

struct Led_config g_LedCfg = {0};

/**

* @brief 控制LED的GPIO引腳

*

* 根據傳入的GPIO引腳號和模式,控制LED的開關狀態。

*

* @param gpio GPIO引腳號

* @param mode 控制模式,LED_ON表示打開LED,LED_OFF表示關閉LED

*

* @return 成功返回HDF_SUCCESS,失敗返回HDF_FAILURE

*/

static int32_t LedGpioCtl(uint16_t gpio, uint32_t mode){

// 設置GPIO電平為高電平

uint16_t level = GPIO_VAL_HIGH;

// 設置GPIO為輸出方向

if(HDF_SUCCESS != GpioSetDir(gpio, GPIO_DIR_OUT)){

// 設置GPIO方向失敗

HDF_LOGE("GpioSetDir fail");

return HDF_FAILURE;

}

// 根據mode設置GPIO電平

if(mode == LED_ON){

level = GPIO_VAL_HIGH;

}else if(mode==LED_OFF){

level = GPIO_VAL_LOW;

}

// 日志記錄GPIO操作

HDF_LOGE("%s:Write gpio %d:%d",__func__,gpio,mode);

// 向GPIO寫入電平

if(HDF_SUCCESS != GpioWrite(gpio, level)){

// 寫入GPIO電平失敗

HDF_LOGE("GpioWrite fail",__func__);

}

return HDF_SUCCESS;

}

/**

* @brief 驅動LED設備

*

* 根據傳入的命令ID和數據,控制LED設備的狀態。

*

* @param client HDF設備客戶端指針

* @param cmdId 命令ID,用于指示執行的操作類型

* @param dataBuf 輸入數據緩沖區指針,包含需要傳遞給設備的數據

* @param replyBuf 輸出數據緩沖區指針,用于存儲設備返回的數據

*

* @return 返回操作結果,成功返回HDF_SUCCESS,失敗返回相應的錯誤碼

*/

int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int32_t cmdId, struct HdfSBuf *dataBuf, struct HdfSBuf *replyBuf){

int32_t result = HDF_FAILURE;

int32_t LedMode = 0;

// 檢查客戶端和設備是否為空

if(client == NULL || client->device == NULL){

HDF_LOGE("driver device is NULL");

return HDF_ERR_INVALID_OBJECT;

}

// 檢查LED配置版本是否支持

if(g_LedCfg.led_version != LED_VERSION){

HDF_LOGE("led version is not support");

return HDF_FAILURE;

}

switch(cmdId){

case LED_WRITE:

// 從數據緩沖區讀取LED模式

result = HdfSbufReadInt32(dataBuf,&LedMode);

if(result ){

// 根據LED模式控制GPIO

LedGpioCtl(g_LedCfg.led_number, (LedMode == LED_ON) ? LED_ON: LED_OFF);

}

break;

default:

// 不支持的命令ID

HDF_LOGE("cmdId is not support");

break;

}

return result;

}

/**

* @brief 綁定LED設備驅動

*

* 將LED設備驅動綁定到HDF設備對象上。

*

* @param deviceObject HDF設備對象指針

*

* @return 返回HDF狀態碼,成功返回HDF_SUCCESS,失敗返回相應的錯誤碼

*/

int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject){

// 檢查deviceObject是否為空

if(deviceObject == NULL){

// 如果為空,則記錄錯誤日志并返回錯誤碼

HDF_LOGE("HdfLedDriverBind: %s failed",__func__);

return HDF_ERR_INVALID_OBJECT;

}

// 定義一個靜態的IDeviceIoService結構體變量ledDriverServ

static struct IDeviceIoService ledDriverServ = {

.Dispatch = LedDriverDispatch,

};

// 將ledDriverServ的地址賦值給deviceObject的service成員

deviceObject->service =(struct IDeviceIoService *)(&ledDriverServ);

// 記錄綁定成功的日志,包括設備名稱

HDF_LOGI("g_LedDriverEntry: %s success NodeName[%s]", __func__, deviceObject->property->name);

// 返回成功碼

return HDF_SUCCESS;

}

/**

* @brief 初始化HDF LED驅動

*

* 該函數用于初始化HDF LED驅動,從HCS配置文件中讀取硬件相關配置屬性。

*

* @param deviceObject 設備對象指針

*

* @return 初始化結果

* - HDF_SUCCESS: 初始化成功

* - HDF_ERR_INVALID_OBJECT: 設備對象無效

* - HDF_FAILURE: 初始化失敗

*/

int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject){

// 檢查deviceObject是否為空

if(deviceObject == NULL){

HDF_LOGE("g_LedDriverEntry: %s failed",__func__);

return HDF_ERR_INVALID_OBJECT;

}

// 獲取DeviceResourceIface實例

struct DeviceResourceIface *cfgops= NULL;

cfgops = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);

// 檢查cfgops及其方法GetUint32是否有效

if (cfgops == NULL || cfgops->GetUint32 == NULL) {

HDF_LOGE("%s:DeviceResourceGetIfaceInstance failed", __func__);

return HDF_FAILURE;

}

// 讀取hcs配置中的硬件相關配置屬性:led_version

// 讀取led_version

if(cfgops->GetUint32(deviceObject->property,"led_version",&g_LedCfg.led_version,0)!= HDF_SUCCESS){

HDF_LOGE("%s: read led_version failed", __func__);

return HDF_FAILURE;

}

// 讀取引腳號:led_number

// 讀取led_number

if(cfgops->GetUint32(deviceObject->property,"led_number",&g_LedCfg.led_number,0)!= HDF_SUCCESS){

HDF_LOGE("%s:Gread led_number failed", __func__);

return HDF_FAILURE;

}

// 打印初始化成功日志

HDF_LOGI("g_LedDriverEntry: %s success", __func__);

return HDF_SUCCESS;

}

/**

* @brief 釋放HDF LED驅動資源

*

* 該函數用于釋放HDF LED驅動的資源。如果傳入的HdfDeviceObject指針為空,則打印錯誤日志并直接返回。

* 如果HdfDeviceObject指針不為空,則打印成功日志并返回。

*

* @param HdfDeviceObject HDF設備對象指針

*/

void HdfLedDriverRelease(struct HdfDeviceObject *HdfDeviceObject){

// 如果傳入的HdfDeviceObject為空

if(HdfDeviceObject == NULL){

// 打印錯誤日志

HDF_LOGE("HdfLedDriverRelease: %s failed",__func__);

// 返回

return;

}

// 打印成功日志

HDF_LOGI("HdfLedDriverRelease: %s success", __func__);

// 返回

return;

}

//定義了一個結構體HdfDriverEntry的實例g_LedDriverEntry,并初始化了它的成員變量

struct HdfDriverEntry g_LedDriverEntry = {

.moduleVersion = 1,

.moduleName = "topeet_led_driver",

.Bind = HdfLedDriverBind,

.Init = HdfLedDriverInit,

.Release = HdfLedDriverRelease,

};

//使用HDF_INIT宏來注冊或初始化這個結構體實例g_LedDriverEntry

HDF_INIT(g_LedDriverEntry);

3.4.3 接口函數

在一小節的代碼中實現了一個簡單的LED驅動,下面是對代碼的詳細解釋:

包含的頭文件如下所示:

#include "device_resource_if.h":提供設備資源接口,用于從配置文件中讀取設備信息

#include "hdf_device_desc.h":包含HDF設備描述相關的定義

#include "hdf_log.h":提供日志記錄功能

#include "gpio_if.h:提供GPIO接口,用于控制LED燈的開關

宏定義如下所示:

#define HDF_LOG_TAG led_driver :定義日志標簽,用于區分不同模塊的日志

#define LED_WRITE 1:定義LED控制命令的ID

#define LED_VERSION 1: 定義LED驅動的版本號

#define LED_ON 1 :定義LED燈打開的狀態

#define LED_OFF 0:定義LED燈關閉的狀態

數據結構如下所示:

struct Led_config{ //led_config結構體用于存儲LED配置信息,包括LED驅動版本號和LED GPIO編號

uint32_t led_version;

uint32_t led_number;

};

struct Led_config g_LedCfg = {0}; //全局變量,用于存儲LED配置

g_LedDriverEntry結構體是驅動入口結構體,如下所示,包含了驅動的版本號、模塊名、綁定、初始化和釋放函數。

struct HdfDriverEntry g_LedDriverEntry = {

.moduleVersion = 1,

.moduleName = "topeet_led_driver",

.Bind = HdfLedDriverBind,

.Init = HdfLedDriverInit,

.Release = HdfLedDriverRelease,

};

HDF_INIT(g_LedDriverEntry);

HdfLedDriverInit函數是驅動初始化函數。

參數:deviceObject(設備對象)。

流程:獲取設備資源接口,讀取設備配置中的led_version和led_number(GPIO號),并保存到全局配置變量中。

int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject){

// 檢查deviceObject是否為空

if(deviceObject == NULL){

HDF_LOGE("g_LedDriverEntry: %s failed",__func__);

return HDF_ERR_INVALID_OBJECT;

}

// 獲取DeviceResourceIface實例

struct DeviceResourceIface *cfgops= NULL;

cfgops = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE);

// 檢查cfgops及其方法GetUint32是否有效

if (cfgops == NULL || cfgops->GetUint32 == NULL) {

HDF_LOGE("%s:DeviceResourceGetIfaceInstance failed", __func__);

return HDF_FAILURE;

}

// 讀取hcs配置中的硬件相關配置屬性:led_version

// 讀取led_version

if(cfgops->GetUint32(deviceObject->property,"led_version",&g_LedCfg.led_version,0)!= HDF_SUCCESS){

HDF_LOGE("%s: read led_version failed", __func__);

return HDF_FAILURE;

}

// 讀取引腳號:led_number

// 讀取led_number

if(cfgops->GetUint32(deviceObject->property,"led_number",&g_LedCfg.led_number,0)!= HDF_SUCCESS){

HDF_LOGE("%s:Gread led_number failed", __func__);

return HDF_FAILURE;

}

// 打印初始化成功日志

HDF_LOGI("g_LedDriverEntry: %s success", __func__);

return HDF_SUCCESS;

}

HdfLedDriverRelease:驅動釋放函數。

參數:HdfDeviceObject(設備對象)。

流程:記錄日志,表示驅動釋放成功。

void HdfLedDriverRelease(struct HdfDeviceObject *HdfDeviceObject){

// 如果傳入的HdfDeviceObject為空

if(HdfDeviceObject == NULL){

// 打印錯誤日志

HDF_LOGE("HdfLedDriverRelease: %s failed",__func__);

// 返回

return;

}

// 打印成功日志

HDF_LOGI("HdfLedDriverRelease: %s success", __func__);

// 返回

return;

}

HdfLedDriverBind:綁定解析函數

參數:deviceObject(設備對象)。

流程:將LED驅動的服務對象賦值給設備對象的服務成員。

int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject){

// 檢查deviceObject是否為空

if(deviceObject == NULL){

// 如果為空,則記錄錯誤日志并返回錯誤碼

HDF_LOGE("HdfLedDriverBind: %s failed",__func__);

return HDF_ERR_INVALID_OBJECT;

}

// 定義一個靜態的IDeviceIoService結構體變量ledDriverServ

static struct IDeviceIoService ledDriverServ = {

.Dispatch = LedDriverDispatch,

};

// 將ledDriverServ的地址賦值給deviceObject的service成員

deviceObject->service =(struct IDeviceIoService *)(&ledDriverServ);

// 記錄綁定成功的日志,包括設備名稱

HDF_LOGI("g_LedDriverEntry: %s success NodeName[%s]", __func__, deviceObject->property->name);

// 返回成功碼

return HDF_SUCCESS;

}

LedDriverDispatch:解析函數,解析應用層下發的命令,執行命令對應的操作,控制led燈的亮滅。

參數:client(客戶端信息),cmdId(命令ID),dataBuf(輸入數據緩沖區),replyBuf(回復數據緩沖區)。

流程:檢查設備對象的有效性,驗證LED版本,根據命令ID讀取數據并調用LedGpioCtl控制LED。

int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int32_t cmdId, struct HdfSBuf *dataBuf, struct HdfSBuf *replyBuf){

int32_t result = HDF_FAILURE;

int32_t LedMode = 0;

// 檢查客戶端和設備是否為空

if(client == NULL || client->device == NULL){

HDF_LOGE("driver device is NULL");

return HDF_ERR_INVALID_OBJECT;

}

// 檢查LED配置版本是否支持

if(g_LedCfg.led_version != LED_VERSION){

HDF_LOGE("led version is not support");

return HDF_FAILURE;

}

switch(cmdId){

case LED_WRITE:

// 從數據緩沖區讀取LED模式

result = HdfSbufReadInt32(dataBuf,&LedMode);

if(result ){

// 根據LED模式控制GPIO

LedGpioCtl(g_LedCfg.led_number, (LedMode == LED_ON) ? LED_ON: LED_OFF);

}

break;

default:

// 不支持的命令ID

HDF_LOGE("cmdId is not support");

break;

}

return result;

}

LedGpioCtl:控制指定GPIO(LED)的高低電平,從而控制LED燈的開關。

參數:gpio(GPIO號),mode(LED模式,開或關)。

流程:設置GPIO為輸出方向,根據mode設置GPIO的電平,最后記錄日志。

static int32_t LedGpioCtl(uint16_t gpio, uint32_t mode){

// 設置GPIO電平為高電平

uint16_t level = GPIO_VAL_HIGH;

// 設置GPIO為輸出方向

if(HDF_SUCCESS != GpioSetDir(gpio, GPIO_DIR_OUT)){

// 設置GPIO方向失敗

HDF_LOGE("GpioSetDir fail");

return HDF_FAILURE;

}

// 根據mode設置GPIO電平

if(mode == LED_ON){

level = GPIO_VAL_HIGH;

}else if(mode==LED_OFF){

level = GPIO_VAL_LOW;

}

// 日志記錄GPIO操作

HDF_LOGE("%s:Write gpio %d:%d",__func__,gpio,mode);

// 向GPIO寫入電平

if(HDF_SUCCESS != GpioWrite(gpio, level)){

// 寫入GPIO電平失敗

HDF_LOGE("GpioWrite fail",__func__);

}

return HDF_SUCCESS;

}

3.4.4 添加內核編譯

編譯內核時將該HDF驅動編譯到鏡像中,接下來編寫驅動編譯腳本Makefile,代碼如下所示:

include drivers/hdf/khdf/platform/platform.mk

obj-y += led_driver.o

加入編譯體系,填加模塊目錄到drivers/hdf_core/adapter/khdf/linux/Makefile 文件

obj-$(CONFIG_DRIVERS_HDF) += ../../../../../topeet/demos/hdf_led/driver/

3.4.5 編寫應用APP

在應用代碼中我們實現如下功能:

當應用程序啟動后會獲取命令行參數。如果命令行沒有參數,LED燈將循環閃爍;如果命令行帶有參數,則根據傳輸的參數控制LED燈的開啟或關閉。通過HdfIoServiceBind 綁定LED燈的HDF服務,獲取HDF空間緩存區,并向該緩沖區寫入控制數據。然后,通過 LED_WRITE 命令將數據發送到 HDF 驅動,從而控制 LED 燈的亮滅。在程序結束時,會回收 HDF 空間緩沖區和 HDF 服務。

接下來編寫應用測試文件led_test.c,完整代碼如下所示。

#include "stdio.h"

#include "stdlib.h"

#include "unistd.h"

#include "hdf_base.h"

#include "hdf_io_service.h"

#include "hilog/log.h"

#undef LOG_TAG

#undef LOG_DOMAIN

#define LOG_TAG "led_test"

#define LOG_DOMAIN 0xD0020240

#define ARGS_NUM 2

#define LED_SERVICE_NAME "topeet_led_service"

#define LED_WRITE 1

/**

* @brief 主函數,用于控制LED燈的開關狀態

*

* 根據傳入的參數控制LED燈的開關狀態,如果沒有傳入參數,則進入主循環,不斷切換LED燈的開關狀態。

*

* @param argc 命令行參數的數量

* @param argv 命令行參數的數組

*

* @return 返回HDF_SUCCESS表示成功,否則返回錯誤碼

*/

int main(int argc, char *argv[]){

int ret = HDF_SUCCESS;

int32_t mode = -1;

// 判斷命令行參數數量

if (argc == ARGS_NUM) {

// 將命令行參數轉換為整數并賦值給 mode

mode = atoi(argv[1]);

// 打印 mode 的狀態

printf("mode[%s][0x%x]\n",(mode==1)?"On":"Off",mode);

} else {

// 命令行參數數量不正確,打印提示信息

printf("led main loop. \n");

}

// 綁定 LED 服務

struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE_NAME);

if(serv == NULL){

// 綁定服務失敗,打印錯誤信息并返回 -1

HILOG_ERROR(LOG_APP, "get service %s failed!", LED_SERVICE_NAME);

return -1;

}

// 打印綁定服務成功的日志

HILOG_ERROR(LOG_APP, "get service %s succeed", LED_SERVICE_NAME);

// 獲取默認大小的 SBuf 對象

struct HdfSBuf *data = HdfSbufObtainDefaultSize();

if(data == NULL){

// 獲取 SBuf 對象失敗,打印錯誤信息并返回 -1

HILOG_ERROR(LOG_APP,"obtain data failed\n");

return -1;

}

// 打印獲取 SBuf 對象成功的日志

HILOG_ERROR(LOG_APP,"obtain data succeed\n");

// 如果 mode 為 -1,則進入循環

if(mode == -1){

while(1){

// 清空 SBuf 對象

HdfSbufFlush(data);

// 向 SBuf 對象寫入整數 1

if(!HdfSbufWriteInt32(data, 1)){

// 寫入數據失敗,打印錯誤信息并返回 -1

HILOG_ERROR(LOG_APP,"write data failed");

return -1;

}

// 調用 Dispatch 方法,發送 LED 寫入命令

ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE, data, NULL);

usleep(500 * 1000);

// 清空 SBuf 對象

HdfSbufFlush(data);

// 向 SBuf 對象寫入整數 0

if(!HdfSbufWriteInt32(data, 0)){

// 寫入數據失敗,打印錯誤信息并返回 -1

HILOG_ERROR(LOG_APP,"write data failed");

return -1;

}

// 調用 Dispatch 方法,發送 LED 寫入命令

ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE, data, NULL);

usleep(500 * 1000);

}

} else {

// 如果 mode 不為 -1,則向 SBuf 對象寫入 mode 值

if(!HdfSbufWriteInt32(data, mode)){

// 寫入數據失敗,打印錯誤信息并返回 -1

HILOG_ERROR(LOG_APP,"write data failed");

return -1;

}

// 調用 Dispatch 方法,發送 LED 寫入命令

ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE, data, NULL);

// 打印 Dispatch 成功的日志

HILOG_ERROR(LOG_APP,"Dispatch succeed");

}

// 回收 SBuf 對象

HdfSbufRecycle(data);

// 回收服務對象

HdfIoServiceRecycle(serv);

// 打印主程序退出的日志

HILOG_INFO(LOG_APP,"[%s] main exit.",LOG_TAG);

return ret;

}

接下來編寫應用APP的GN文件BUILD.gn,代碼內容如下所示:

HDF_FRAMEWORKS = "http://drivers/hdf_core/framework"

HDF_ADAPTER = "http://drivers/hdf_core/adapter"

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

import("$HDF_ADAPTER/uhdf2/uhdf.gni")

print("demos: compile led_test")

ohos_executable("led_test"){

sources = ["led_test.c"]

include_dirs = [

"$HDF_FRAMEWORKS/include",

"$HDF_FRAMEWORKS/include/core",

"$HDF_FRAMEWORKS/include/osal",

"$HDF_FRAMEWORKS/include/platform",

"$HDF_FRAMEWORKS/include/utils",

"$HDF_ADAPTER/uhdf2/ipc/include",

"$HDF_ADAPTER/uhdf2/osal/include",

"http://base/hiviewdfx/hilog/interfaces/native/innerkits/include",

"http://third_party/bounds_checking_function/include",

]

external_deps = [

"c_utils:utils",

"hdf_core:libhdf_platform",

"hdf_core:libhdf_utils",

"hilog:libhilog",

]

cflags = [

"-Wall",

"-Wextra",

"-Werror",

"-Wno-format",

"-Wno-format-extra-args",

]

part_name = "demos"

install_enable = true

}

上面的代碼用于構建一個“led_test”的可執行文件的構建腳本,它使用了GN(Generate Ninja)構建系統,這是一種元構建系統,用于生成Ninja構建文件。

1-2行定義了兩個變量HDF_FRAMEWORKS和HDF_ADAPTER,它們分別指向HDF(Hardware Driver Foundation,硬件驅動框架)核心框架和適配器的路徑。這些路徑是相對于項目根目錄的。

4-5行 使用import語句導入兩個GNI(GN Include)文件。GNI文件是GN構建系統用來包含變量定義、函數和模板的文件。這里導入的文件可能包含了一些預定義的變量、函數或構建規則,用于支持構建過程。//build/ohos.gni可能包含了OpenHarmony特有的構建配置,而$HDF_ADAPTER/uhdf2/uhdf.gni可能包含了與uHDF(Unified Hardware Driver Framework,統一硬件驅動框架)相關的配置。

7行 打印一條消息到控制臺,表明正在編譯led_test示例。

9-40行 定義一個名為led_test的ohos_executable目標,這是一個構建規則,用于生成一個可執行文件。下面是該目標的具體配置:

sources:指定源文件列表,這里只有一個文件led_test.c。

include_dirs:指定頭文件搜索路徑列表。這些路徑用于在編譯時查找包含的文件(#include指令引用的文件)。這些路徑包括了HDF框架、適配器的多個子目錄,以及一些第三方庫和內部工具庫的頭文件路徑。

external_deps:指定外部依賴項列表。這些依賴項是在構建過程中需要鏈接的庫。這里列出了幾個庫,如c_utils:utils、hdf_core:libhdf_platform等,這些庫提供了構建led_test所需的功能。

cflags:指定傳遞給C編譯器的標志列表。這里包括了一些常見的編譯選項,如-Wall(打開所有警告)、-Wextra(打開額外警告)、-Werror(將所有警告視為錯誤)、以及兩個用于關閉特定警告的選項。

part_name:指定構建產物所屬的部件名稱,這里是demos。

install_enable:設置為true,表示構建產物應該被安裝。這可能意味著在構建成功后,led_test可執行文件會被復制到某個特定的目錄,以便于執行或分發。

3.5 在產品中新增子系統

在build/subsystem_config.json文件中增加名為topeet的子系統,在3.4節已經新建了topeet文件夾存放子系統代碼。添加topeet子系統進行一個登記,說明路徑和子系統名稱,如下所示:

“topeet”: {

“path”: “topeet”,

“name”: ”topeet”

}

wKgZO2fTzxqALKljAABo3zwLRq0032.png

在vendor/hihope/rk3568/config.json文件中增加topeet子系統的引入,如下所示:

{

"subsystem": "topeet",

"components": [

{

"component": "demos",

"features": [

]

}

]

}

wKgZO2fTzxqAMsEPAABgCqtyp8I742.png

修改完成之后,保存修改。

3.6 編譯源碼

重新編譯Openharmony4.1源碼,如下所示:

./build.sh --product-name rk3568 --ccache

或者單獨編譯部件

./build.sh --product-name rk3568 --build-target demos --ccache

編譯之后,在源碼out/rk3568/topeet目錄下生成編譯產物,如下圖所示:

wKgZO2fTzxqAGj2BAACEjrjzA4E847.png

3.7 LED測試

將編譯好的鏡像全部進行燒寫,鏡像在源碼根目錄out/rk3568/packages/phone/images/目錄下。

wKgZPGfTzxyAVPX0AAFg1uG0j9A980.png

燒寫完成之后,在調試串口查看打印日志,如下圖所示:

wKgZPGfTzxyAO4xhAACCJ_X4KS4111.png

然后打開hdc工具,運行測試程序,輸入“led_test 1”,LED燈點亮,如下圖所示:

wKgZPGfTzxuAQt3eAABO2eRB3RA058.png

wKgZO2fTzxyAB8KmAALnq65Pobc520.png

輸入“led_test 0”,LED燈熄滅,如下圖所示:

wKgZO2fTzxyAXu0vAAA13eoUeFE354.png

wKgZO2fTzx2AdVuKAAK0MCr2WPU077.png
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 開發板
    +關注

    關注

    25

    文章

    5223

    瀏覽量

    99210
  • OpenHarmony
    +關注

    關注

    25

    文章

    3771

    瀏覽量

    17062
  • RK3568
    +關注

    關注

    4

    文章

    542

    瀏覽量

    5513
收藏 0人收藏

    評論

    相關推薦

    RK3568開發板驅動指南Linux中通用SPI設備驅動

    RK3568開發板驅動指南Linux中通用SPI設備驅動
    的頭像 發表于 01-23 11:02 ?2045次閱讀
    <b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>RK3568</b><b class='flag-5'>開發板</b><b class='flag-5'>驅動</b>指南Linux中通用SPI設備<b class='flag-5'>驅動</b>

    北京RK3568開發板OpenHarmony系統南向驅動開發內核HDF驅動框架架構

    北京RK3568開發板OpenHarmony系統
    的頭像 發表于 03-11 14:13 ?573次閱讀
    <b class='flag-5'>北京</b><b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>RK3568</b><b class='flag-5'>開發板</b><b class='flag-5'>OpenHarmony</b><b class='flag-5'>系統</b><b class='flag-5'>南向</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>內核<b class='flag-5'>HDF</b><b class='flag-5'>驅動</b>框架架構

    鴻蒙OpenHarmony南向/北向快速開發教程-RK3568開發板

    -修改產品信息 P20_源碼定制-關閉自動息屏 P21_源碼定制-修改開機logo和動畫 P22_新建運行北向應用 RK3568開發板同時也支持更多
    發表于 07-23 10:44

    RK3568開發板支持銀河麒麟和開放麒麟系統

    RK3568開發板移植了銀河麒麟和開放麒麟系統HOT 新增RT-Thread系統
    發表于 11-06 14:44

    RK3568開發板OpenHarmony配置HDF驅動控制LED-修改HCS硬件配置

    發布服務的名稱,必須唯一 deviceMatchAttr = \"topeet_led_config\";表示驅動私有數據匹配關鍵詞,必須和驅動私有數據配置節點的 match_attr
    發表于 01-08 15:25

    RK3568開發板OpenHarmony配置HDF驅動控制LED-新增 topeet子系統

    程序目錄 ├── led_driver.c:內核 LED HDF 驅動程序 └── Makefile:內核 LED
    發表于 01-13 15:59

    RK3568開發板OpenHarmonyHDF驅動控制LED-編寫內核 LED HDF 驅動程序

    接下來編譯 LED 驅動,該驅動用于在基于華為設備框架(HDF)的系統中控制 LED 燈的開關,
    發表于 01-17 15:13

    RK3568開發板OpenHarmonyHDF驅動控制LED-添加內核編譯

    編譯內核時將該 HDF 驅動編譯到鏡像中,接下來編寫驅動編譯腳本 Makefile,代碼如下所示: 加入編譯體系,填加模塊目錄到 drivers/hdf_core/adapter/kh
    發表于 01-22 10:35

    RK3568開發板鴻蒙OpenHarmony系統固件燒寫步驟

    1、RK3568開發板鴻蒙OpenHarmony系統固件燒寫首先拷貝燒寫器(燒寫器在光盤資料
    發表于 08-26 17:45

    【教程上新】基于iTOP-RK3568開發板的OpenCV開發手冊

    【教程上新】基于iTOP-RK3568開發板的OpenCV開發手冊
    的頭像 發表于 02-08 15:22 ?1262次閱讀
    【教程上新】基于<b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>iTOP-RK3568</b><b class='flag-5'>開發板</b>的OpenCV<b class='flag-5'>開發</b>手冊

    北京itop-RK3568開發板驅動開發指南

    iTOP-RK3568開發板驅動開發指南》更新,本次更新內容對應的是驅動(第六期_平臺總線_全新升級)視頻,后續資料會不斷更新,不斷完善,
    發表于 08-29 16:32 ?39次下載

    RK3568開發板驅動開發指南-輸入子系統

    RK3568開發板驅動開發指南-輸入子系統
    的頭像 發表于 02-23 15:11 ?1090次閱讀
    <b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>RK3568</b><b class='flag-5'>開發板</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>指南-輸入子<b class='flag-5'>系統</b>

    北京RK3568開發板嵌入式學習之Linux驅動全新更新-CAN+

    北京RK3568開發板嵌入式學習之Linux驅動全新更新-CAN+
    的頭像 發表于 09-04 15:29 ?712次閱讀
    <b class='flag-5'>北京</b><b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>RK3568</b><b class='flag-5'>開發板</b>嵌入式學習之Linux<b class='flag-5'>驅動</b>全新更新-CAN+

    iTOP-RK3568/RK3588開發板獲麒麟軟件適配認證

    iTOP-RK3568/RK3588開發板獲麒麟軟件適配認證
    的頭像 發表于 10-18 14:56 ?792次閱讀
    <b class='flag-5'>迅</b><b class='flag-5'>為</b><b class='flag-5'>iTOP-RK3568</b>/<b class='flag-5'>RK</b>3588<b class='flag-5'>開發板</b>獲麒麟軟件適配認證

    北京iTOP-RK3568OpenHarmony系統南向驅動開發GPIO基礎知識

    北京iTOP-RK3568OpenHarmony系統南向
    的頭像 發表于 03-06 11:23 ?208次閱讀
    【<b class='flag-5'>北京</b><b class='flag-5'>迅</b><b class='flag-5'>為</b>】<b class='flag-5'>iTOP-RK3568OpenHarmony</b><b class='flag-5'>系統</b><b class='flag-5'>南向</b><b class='flag-5'>驅動</b><b class='flag-5'>開發</b>GPIO基礎知識

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品
    主站蜘蛛池模板: 1024你懂的日韩 | 神马午夜限制 | 四虎在线网址 | 欧美在线视频看看 | 米奇777色狠狠8888影视 | 你懂得网址在线观看 | 男男gay污小黄文 | 人人福利| 亚洲特黄大黄一级毛片 | wwwcom日本| 亚洲欧美天堂网 | 天天草天天操 | 日韩三级中文字幕 | 三级黄色在线视频中文 | 久久精品男人的天堂 | 国产一级在线观看www色 | 久久婷婷午色综合夜啪 | 一级黄色毛片播放 | 久久影视免费体验区午夜啪啪 | 中文字幕一区二区三区有限公司 | 欧美射射射 | 欧美性色黄在线视 | 最黄色的视频 | 日本动漫免费看 | 无人区理论片手机看片 | 爱插综合网 | 5060精品国产福利午夜 | 天天干影院 | 黄 色 大 片 网站 | 777奇米四色米奇影院在线播放 | 色婷婷激婷婷深爱五月老司机 | 大尺度视频在线观看 | 伊人久久综合网站 | 欧美一级视频在线观看 | 三级在线观看免播放网站 | 色婷婷99综合久久久精品 | 天天狠狠干 | 最新欧美精品一区二区三区 | 婷婷色在线观看 | 日本大片免aaa费观看视频 | 1024手机看片国产 |