第3章鴻蒙 hi3681 開發板入門 代碼路徑、啟動流程分析
想了解更多內容,請訪問:
51CTO和華為官方合作共建的鴻蒙技術社區
https://harmonyos.51cto.com/#zz
第3章 Hi3681開發
目錄:
3.1 編寫一個簡單的hello world程序
3.2 Hi3861相關代碼結構
3.2 Hi3861啟動流程
3.1 編寫一個簡單的hello world程序
編寫一個hello world程序比較簡單,可以參考官網:
https://device.harmonyos.com/cn/docs/start/introduce/oem_wifi_start-0000001050168544
本文在這里做下總結:
(1)確定目錄結構。
開發者編寫業務時,務必先在./applications/sample/wifi-iot/app路徑下新建一個目錄(或一套目錄結構),用于存放業務源碼文件。
例如:在app下新增業務my_first_app,其中hello_world.c為業務代碼,BUILD.gn為編譯腳本,具體規劃目錄結構如下:
- .
- └── applications
- └── sample
- └── wifi-iot
- └── app
- │── my_first_app
- │ │── hello_world.c
- │ └── BUILD.gn
- └── BUILD.gn
(2)編寫業務代碼。
在hello_world.c中新建業務入口函數HelloWorld,并實現業務邏輯。并在代碼最下方,使用 HarmonyOS啟動恢復模塊接口SYS_RUN()啟動業務。(SYS_RUN定義在ohos_init.h文件中)
- #include "ohos_init.h"
- #include "ohos_types.h"
- void HelloWorld(void)
- {
- printf("[DEMO] Hello world.\n");
- }
- SYS_RUN(HelloWorld);
(3)編寫用于將業務構建成靜態庫的BUILD.gn文件。
如步驟1所述,BUILD.gn文件由三部分內容(目標、源文件、頭文件路徑)構成,需由開發者完成填寫。以my_first_app為例,需要創建./applications/sample/wifi-iot/app/my_first_app/BUILD.gn,并完如下配置。
- static_library("myapp") {
- sources = [
- "hello_world.c"
- ]
- include_dirs = [
- "//utils/native/liteos/include"
- ]
- }
static_library中指定業務模塊的編譯結果,為靜態庫文件libmyapp.a,開發者根據實際情況完成填寫。
sources中指定靜態庫.a所依賴的.c文件及其路徑,若路徑中包含"//"則表示絕對路徑(此處為代碼根路徑),若不包含"//"則表示相對路徑。
include_dirs中指定source所需要依賴的.h文件路徑。
(4)編寫模塊BUILD.gn文件,指定需參與構建的特性模塊。
配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目標模塊參與編譯。features字段指定業務模塊的路徑和目標,以my_first_app舉例,features字段配置如下。
- import("//build/lite/config/component/lite_component.gni")
- lite_component("app") {
- features = [
- "my_first_app:myapp",
- ]
- }
my_first_app是相對路徑,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn。
myapp是目標,指向./applications/sample/wifi-iot/app/my_first_app/BUILD.gn中的static_library("myapp")。
3.2 Hi3861相關代碼結構
目前hi3861用的是liteos-m內核,但是目前hi3681的liteos-m被芯片rom化了,固化在芯片內部了。所以在harmonyOS代碼是找不到hi3861的內核部分。
但是這樣不妨礙我們去理清hi3861的其他代碼結構。
hi3861平臺配置文件
build\lite\platform\hi3861v100_liteos_riscv\platform.json
該文件描述了hi3681平臺相關的代碼路徑,例如application、startup等。

這里我列舉出來幾個比較重要的:
子系統:applications :
路徑:applications/sample/wifi-iot/app
作用:這個路徑下存放了hi3681編寫的應用程序代碼,例如我們剛剛寫得hello world 代碼就放在這個路徑下。
子系統:iot_hardware :
路徑:base/iot_hardware/frameworks/wifiiot_lite
作用:存放了 hi3681 芯片相關的驅動、例如spi、gpio、uart等。
子系統:vendor
路徑:vendor/hisi/hi3861/hi3861
作用:存放了 hi3681 相關的廠商SDK之類的文件。其中最重要的是
vendor\hisi\hi3861\hi3861\app\wifiiot_app\init\app_io_init.c
vendor\hisi\hi3861\hi3861\app\wifiiot_app\src\app_main.c
其中,app_io_init.c 是hi3681內核啟動后的io口相關設置,用戶需根據應用場景,合理選擇各外設的IO復用配置。
app_main.c 是內核啟動進入的應用程序入口。
3.2 Hi3861啟動流程
由于hi3681的liteos-m被芯片rom化了,固化在芯片內部了。所以我們主要看內核啟動后的第一個入口函數。
代碼路徑:
vendor\hisi\hi3861\hi3861\app\wifiiot_app\src\app_main.c
- hi_void app_main(hi_void)
- {
- #ifdef CONFIG_FACTORY_TEST_MODE
- printf("factory test mode!\r\n");
- #endif
- const hi_char* sdk_ver = hi_get_sdk_version();
- printf("sdk ver:%s\r\n", sdk_ver);
- hi_flash_partition_table *ptable = HI_NULL;
- peripheral_init();
- …..中間省略代碼
- HOS_SystemInit();
- }
app_main一開始打印了 SDK版本號,最后一行會調用HOS_SystemInit(); 函數進行鴻蒙系統的初始化。我們進去看下初始化做了哪些動作。
路徑:base/startup/services/bootstrap_lite/source/system_init.c
- void HOS_SystemInit(void)
- {
- MODULE_INIT(bsp);
- MODULE_INIT(device);
- MODULE_INIT(core);
- SYS_INIT(service);
- SYS_INIT(feature);
- MODULE_INIT(run);
- SAMGR_Bootstrap();
- }
我們可以看到主要是初始化了 一些相關模塊、系統,包括有bsp、device(設備)。其中最終的是MODULE_INIT(run);
它負責調用了,所有run段的代碼,那么run段的代碼是哪些呢?
事實上就是我們前面application中使用SYS_RUN() 宏設置的函數名。
還記得我們前面寫的hello world應用程序嗎?
- #include "ohos_init.h"
- #include "ohos_types.h"
- void HelloWorld(void)
- {
- printf("[DEMO] Hello world.\n");
- }
- SYS_RUN(HelloWorld);
也就是說所有用SYS_RUN() 宏設置的函數都會在使用MODULE_INIT(run); 的時候被調用。
為了驗證這一點,我們可以加一些打印信息,如下:

我們重新編譯后燒錄。打開串口查看打印信息,如下:

可以看到在35行之后,就打印 hello world的信息。符合預期。
想了解更多內容,請訪問:
51CTO和華為官方合作共建的鴻蒙技術社區
https://harmonyos.51cto.com/#zz