我在Hi3516開發闆上做過LED燈的點燈示例程式以示範鴻蒙驅動開發的一些要點,但因為一開始不知道DAYU200上的三色燈的GPIO管腳号是多少,就沒做燈控測試。有小夥伴問我“DAYU200上的RGB燈怎麼控制”?,我就抽空研究了一下這部分流程,寫了個測試程式。
1. 先看視訊
視訊連結
這是ledx測試程式運作的效果和log。
led_rgb測試程式運作效果未錄制視訊。
2. 驅動代碼分析
先看一下驅動配置檔案:
//vendor/hihope/rk3568/hdf_config/khdf/light/light_config.hcs
這就是三色燈的驅動配置,包含了三色燈的GPIO管腳号。再從:
//vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs
找到:hostName = "light_host" 的相關資訊。
再往上找到light的核心态驅動程式:
//drivers/framework/model/misc/light/driver/
這裡有include/light_driver.h和src/light_driver.c
再往上找到light的使用者态HAL接口:
//drivers/peripheral/misc/light/hal/
這裡也有src/light_controller.h 和 src/light_controller.c。
在//drivers/peripheral/misc/light/下還有hdi_service和interfaces。
還可以找到//drivers/interface/light/v1_0/ILightInterface.idl
經過代碼的解讀和畫圖整理,可以得到如下的流程圖。
3. 流程圖
【附件有原始大圖】
4. 測試程式
雖然//drivers/peripheral/misc/light/test/路徑下已經有測試程式了,但我還是自己用C語言實作了一個簡單的無界面測試程式。
- ledx:可執行程式,你可将其推送到平台的/bin/目錄下,然後在shell上執行./bin/ledx即可看到效果。
- ledx.c:測試程式源代碼
- BUILD.gn:測試程式編譯腳本,在//applications/standard/hap/ohos.build檔案的 module_list 下增加一句:
"//...(BUILD.gn部署路徑).../ledx:ledx",
讓它參與編譯即可。
-
light_driver.c 經過我修改的light驅動程式,見宏liangkz_modify包包覆的部分代碼。
【原始的核心态驅動程式light_driver.c中存在bug,導緻實際運作并不如預期,需要修複light_driver.c中的bug後才完全如預期。】
ledx 測試程式會自動跑以下一個點燈序列:
HILOG_INFO(LOG_APP, " ledId [-1, 0, 1, 2]: -1-Exit, 0-GetLightInfo, 1-Led1, 2-Led2");
HILOG_INFO(LOG_APP, " ledMod[-1, 0, 1 ]: -1-Flash,0-Off, 1-On");
HILOG_INFO(LOG_APP, " ledBrt[ 1, 2, 4, x]: 1-R, 2-G, 4-B, x-bit");
int32_t matrix[][3] =
{
{0, 0, 0}, //GetLightInfo
{1, 0, 7}, //LED1 Off all RGB
{1, 1, 1}, //LED1 On R
{1, 1, 2}, //LED1 On G
{1, 1, 4}, //LED1 On B
{1, 0, 0}, //LED1 Off
{1, 1, 7}, //LED1 On BGR:111
{1, 1, 6}, //LED1 On BG-:110
{1, 1, 5}, //LED1 On B-R:101
{1, 1, 4}, //LED1 On B--:100
{1, 1, 3}, //LED1 On -GR:011
{1, 1, 2}, //LED1 On -G-:010
{1, 1, 1}, //LED1 On --R:001
{1, 0, 0}, //LED1 Off
{1, -1, 7}, //LED1 Flash RGB
{-1, 0, 0},//Exit
};
小夥伴們可自行根據規則添加測試序列。
5. 發現并修複bug
在寫ledx測試程式做驗證時,發現死活都得不到預期效果,我就幹脆從下到上把整個流程畫了圖出來,發現驅動程式果然有不可預料的行為。
5.1 LED燈的數量
在沒得到原理圖和GPIO管腳編号的情況下,我猜測DAYU200開發闆排線旁邊的LED燈,應該是如下圖所示:
在light_config.hcs中寫 lightId = [1, 2]; 相當于說是有兩盞燈,但實際上,我認為要麼是1盞(三色LED合一),要麼是3盞(三色LED各自獨立),我這裡暫且把RGB合在一起當做1盞燈來處理。
5.2 GpioWrite()的行為
light_driver.c中對GpioWrite()的幾處調用中,對drvData->info[lightId]->busNum的使用,很明顯是不合理的,這是造成測試效果不符合預期的根本原因。
我對此做了一下修改,用 UpdateLight(uint32_t lightId, uint32_t lightOn)來替代,小夥伴們讀一下附件的代碼估計就清楚了。
【注意】後來我再想了一下,上面提到的“bug”以及附件代碼裡的修改,除了Disable()函數裡的一處:
if (GpioWrite(drvData->info[lightId]->busRNum, GPIO_VAL_LOW) != HDF_SUCCESS)
可以确信是bug(busRNum應為 busNum)之外,其它幾處很可能并不是bug,隻是他們設計的燈控流程和參數設定我沒搞清楚而已。
實測效果來看,預設三色燈是紫色的(紅色+藍色),綠色燈并未點亮;在跑我的測試程式過程中,紅色和藍色兩燈會出現非預期的亮燈行為。
是以,我懷疑在light_config.hcs中寫 lightId = [1, 2]; 所說的兩盞燈,有可能是指紅色和藍色兩燈,在系統中有其他地方有控制這兩盞燈的亮燈行為,不過沒有控制綠燈的行為。
6.更簡單的示例程式
由上面的流程圖可以看出,一個簡單的點燈流程,被設計得非常複雜(但也非正常範化),這對新手來說很難了解。加上APP的燈控參數和DRV的燈控邏輯,非常容易讓人産生困惑。
為此,我結合早期在Hi3516開發闆上的LED燈控示例程式,對RK3568開發闆做了一下相容,重新寫了一個更簡單的示例程式,友善大家學習。
源代碼開放在碼雲上了:
OhosLedRGB:https://gitee.com/liangkzgitee/led_rgb
這個示例程式包含了驅動開發的必要要素,應用程式led_rgb直接通過消息機制與核心驅動進行互動,設定RGB三色燈的亮燈行為。同時它也相容Hi3516開發闆上的三個系統和RK3568開發闆上的标準系統,詳情請看倉庫上的README文檔。
示例程式的代碼目錄結構如下:
./led_rgb/
├── apps
│ └── led_rgb
│ ├── BUILD.gn
│ └── led_rgb.c
├── config
│ ├── device_info
│ │ └── device_info.hcs
│ └── led
│ ├── led_config_hi3516.hcs
│ └── led_config_rk3568.hcs
├── drv
│ ├── build_linux
│ │ └── Makefile
│ ├── build_liteos
│ │ ├── BUILD.gn
│ │ └── Makefile
│ └── led_drv.c
└── README.md
在平台的shell上執行./bin/led_rgb時,
- 帶參數,參數為0~7的一個數字,按位與0b111,去點亮“BGR”三個LED,如寫入參數6,則0b110,點亮“BG-”兩燈,熄滅“R”燈。
-
不帶參數,預設會自動執行7~0這個點燈序列後退出。
附件連結:
led_rgb.rar ( https://ost.51cto.com/resource/1890 )
LightFlowOnDAYU200.rar( https://ost.51cto.com/resource/1875 )
想了解更多關于鴻蒙的内容,請通路:
51CTO OpenHarmony技術社群
https://ost.51cto.com/#bkwz