自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

OpenHarmony南向設(shè)備應(yīng)用程序啟動(dòng)流程分析

系統(tǒng) OpenHarmony
本文采用倒序的方式,初步梳理了從Hi3861芯片上電到OpenHarmony應(yīng)用程序啟動(dòng)運(yùn)行的流程。

??想了解更多關(guān)于開源的內(nèi)容,請?jiān)L問:??

??51CTO 開源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??

一、用戶程序示例

以qihang開發(fā)板gpio_led程序?yàn)槔?為何單板上電后LedTask()會(huì)自動(dòng)運(yùn)行,SYS_RUN宏在背后是如何起作用的?

static void LedTask(void)
{
while (1)
{
IoTGpioSetOutputVal(LED_TASK_GPIO2,1);
usleep(500*1000);
IoTGpioSetOutputVal(LED_TASK_GPIO2,0);
usleep(500*1000);
}
}
static void LedExampleEntry(void)
{
osThreadAttr_t attr;
IoTGpioInit(LED_TASK_GPIO2);
IoTGpioSetDir(LED_TASK_GPIO2,IOT_GPIO_DIR_OUT);
attr.name = "LedTask";
attr.attr_bits = 0U;
attr.cb_mem = NULL;
attr.cb_size = 0U;
attr.stack_mem = NULL;
attr.stack_size = LED_TASK_STACK_SIZE;
attr.priority = LED_TASK_PRIO;
if (osThreadNew((osThreadFunc_t)LedTask1, NULL, &attr) == NULL) {
printf("Falied to create LedTask!\n");
}
}
SYS_RUN(LedExampleEntry);

二、第二階段(應(yīng)用)啟動(dòng)流程

在上一篇文章中"OpenHarmony南向設(shè)備開發(fā)建構(gòu)編譯分析",有提到qihang板產(chǎn)品配置文件中相關(guān)子系統(tǒng)及組件如下:

vendor/isoftstone/qihang/config.json。

......
{
"subsystem": "distributedschedule", #分布式任務(wù)調(diào)度子系統(tǒng)
"components": [
{ "component": "samgr_lite", "features":[] }
]
},
{
"subsystem": "startup",
"components": [
{ "component": "bootstrap_lite", "features":[] }, #bootstrap啟動(dòng)引導(dǎo)
{ "component": "syspara_lite", "features": #提供系統(tǒng)屬性讀寫接口
[
"enable_ohos_startup_syspara_lite_use_thirdparty_mbedtls = false"
]
}
]
},
......

可以看到,qihang板使用startup子系統(tǒng)中的bootstrap_lite組件和syspara_lite組件。重點(diǎn)看一下bootstrap_lite組件,位于SDK的base/startup/bootstrap_lite目錄。引用該組件的readme文件說明如下:

bootstrap啟動(dòng)引導(dǎo)組件,提供了各服務(wù)和功能的啟動(dòng)入口標(biāo)識(shí)。在SAMGR啟動(dòng)時(shí),會(huì)調(diào)用boostrap標(biāo)識(shí)的入口函數(shù),并啟動(dòng)系統(tǒng)服務(wù)。

samgr_lite組件是針對Hi3861這類硬件資源有限的輕量化系統(tǒng)服務(wù)框架,代碼位于foundation/distributedschedule/samgr_lite目錄。該組件的功能引用如下:

系統(tǒng)服務(wù)框架基于面向服務(wù)的架構(gòu),提供了服務(wù)開發(fā)、服務(wù)的子功能開發(fā)、對外接口的開發(fā)、以及多服務(wù)共進(jìn)程的開發(fā)框架。

device/soc/hisilicon/hi3861v100/sdk_liteos/app/wifiiot_app/src/app_main.c

hi_void app_main(hi_void)
{
hi_flash_partition_table *ptable = HI_NULL;
peripheral_init();
peripheral_init_no_sleep();
hi_u32 ret = hi_factory_nv_init(HI_FNV_DEFAULT_ADDR, HI_NV_DEFAULT_TOTAL_SIZE, HI_NV_DEFAULT_BLOCK_SIZE);
hi_flash_partition_init();
ptable = hi_get_partition_table();
hi_nv_init(ptable->table[HI_FLASH_PARTITON_NORMAL_NV].addr, ptable->table[HI_FLASH_PARTITON_NORMAL_NV].size,
HI_NV_DEFAULT_BLOCK_SIZE);
hi_fs_init();
(hi_void)hi_event_init(APP_INIT_EVENT_NUM, HI_NULL);
hi_sal_init();
hi_syserr_watchdog_debug(HI_FALSE);
hi_syserr_record_crash_info(HI_TRUE);
hi_lpc_init();
hi_lpc_register_hw_handler(config_before_sleep, config_after_sleep);
hi_at_init();
tcpip_init(NULL, NULL);
hi_wifi_init(APP_INIT_VAP_NUM, APP_INIT_USR_NUM);
app_demo_task_release_mem(); /* 釋放系統(tǒng)棧內(nèi)存所使用任務(wù) */
hilink_main();
OHOS_Main();
}

device/soc/hisilicon/hi3861v100/sdk_liteos/app/wifiiot_app/src/ohos_main.c。

void OHOS_Main()
{
OHOS_SystemInit();
}

base/startup/bootstrap_lite/services/source/system_init.c。

void OHOS_SystemInit(void)
{
MODULE_INIT(bsp);
MODULE_INIT(device);
MODULE_INIT(core);
SYS_INIT(service);
SYS_INIT(feature);
MODULE_INIT(run);
SAMGR_Bootstrap();
}
#define SYS_INIT(name) \
do { \
SYS_CALL(name, 0); \
} while (0)
#define SYS_CALL(name, step) \
do { \
InitCall *initcall = (InitCall *)(SYS_BEGIN(name, step)); \
InitCall *initend = (InitCall *)(SYS_END(name, step)); \
for (; initcall < initend; initcall++) { \
(*initcall)(); \
} \
} while (0)
#define SYS_BEGIN(name, step) \
({ extern InitCall __zinitcall_sys_##name##_start; \
InitCall *initCall = &__zinitcall_sys_##name##_start; \
(initCall); \
})
#define SYS_END(name, step) \
({ extern InitCall __zinitcall_sys_##name##_end; \
InitCall *initCall = &__zinitcall_sys_##name##_end; \
(initCall); \
})
#define MODULE_INIT(name) \
do { \
MODULE_CALL(name, 0); \
} while (0)
#define MODULE_CALL(name, step) \
do { \
InitCall *initcall = (InitCall *)(MODULE_BEGIN(name, step)); \
InitCall *initend = (InitCall *)(MODULE_END(name, step)); \
for (; initcall < initend; initcall++) { \
(*initcall)(); \
} \
} while (0)
#define MODULE_BEGIN(name, step) \
({ extern InitCall __zinitcall_##name##_start; \
InitCall *initCall = &__zinitcall_##name##_start; \
(initCall); \
})
#define MODULE_END(name, step) \
({ extern InitCall __zinitcall_##name##_end; \
InitCall *initCall = &__zinitcall_##name##_end; \
(initCall); \
})

foundation/distributedschedule/samgr_lite/samgr/source/samgr_lite.c。

void SAMGR_Bootstrap(void)
{
SamgrLiteImpl *samgr = GetImplement();
WDT_Reset(WDG_SVC_BOOT_TIME);
Vector initServices = VECTOR_Make(NULL, NULL);
MUTEX_Lock(samgr->mutex);
samgr->status = TO_NEXT_STATUS(samgr->status);
int16 size = VECTOR_Size(&(samgr->services));
int16 i;
for (i = 0; i < size; ++i) {
ServiceImpl *serviceImpl = (ServiceImpl *)VECTOR_At(&(samgr->services), i);
VECTOR_Add(&initServices, serviceImpl);
}
MUTEX_Unlock(samgr->mutex);
InitializeAllServices(&initServices);
VECTOR_Clear(&initServices);
InitCompleted();
}

在用戶應(yīng)用程序組件的代碼中,會(huì)包含下述聲明:

APP_FEATURE_INIT(MQTTDemo);
SYS_RUN(LedExampleEntry);

上述宏的說明引用如下:

/**
@brief Identifies the entry for initializing and starting an application-layer service by the
priority 2.
This macro is used to identify the entry called at the priority 2 of the application-layer
service phase of the startup process. \n
@param func Indicates the entry function for initializing and starting an application-layer
service. The type is void (*)(void).
*/
#define APP_SERVICE_INIT(func) LAYER_INITCALL_DEF(func, app_service, “app.service”)
/**
@brief Identifies the entry for initializing and starting a system running phase by the
priority 2.
This macro is used to identify the entry called at the priority 2 in the system startup
phase of the startup process. \n
@param func Indicates the entry function for initializing and starting a system running phase.
The type is void (*)(void).
#define SYS_RUN(func) LAYER_INITCALL_DEF(func, run, “run”)
*/

總結(jié)以上分析,程序第二階段啟動(dòng)流程如下圖圖所示:

OpenHarmony南向設(shè)備應(yīng)用程序啟動(dòng)流程分析-開源基礎(chǔ)軟件社區(qū)

三、第一階段(上電)啟動(dòng)流程

請參考本文最后延申閱讀第二篇文章的具體介紹,程序加載由3個(gè)boot程序前后配合完成:

romboot:

  • 芯片內(nèi)部自帶的上電引導(dǎo)程序,引導(dǎo)loaderboot。

loaderboot (device/soc/hisilicon/hi3861v100/sdk_liteos/boot/loaderboot):

  • 與HiBurn通訊,下載鏡像到flash。
  • 燒寫EFUSE(芯片配置信息)。
  • 校驗(yàn)并引導(dǎo)flashboot。

flashboot (device/soc/hisilicon/hi3861v100/sdk_liteos/boot/flashboot):

  • 升級(jí)固件。
  • 校驗(yàn)并引導(dǎo)固件(主程序)。

loaderboot/common/cmd_loop.c 定義了從hiburn接收并處理的操作:

const loader_cmd g_loader_cmdtable[LOADER_CMD_MAX] = {
{ CMD_DL_IMAGE, loader_download_image },
{ CMD_BURN_EFUSE, loader_burn_efuse },
{ CMD_UL_DATA, loader_upload_data },
{ CMD_READ_EFUSE, loader_read_efuse },
{ CMD_FLASH_PROTECT, loader_flash_protect },
{ CMD_RESET, loader_reset },
{ CMD_FACTORY_IMAGE, loader_download_image },
{ CMD_VERSION, loader_burn_version},
};

其中:

loader_download_image就是接收hiburn傳來的升級(jí)文件,并燒錄到flash中。

flashboot/startup目錄下有兩個(gè)重要文件:

  • riscv_init_flshboot.S 匯編語言格式,RISC-V啟動(dòng)代碼。
  • main.c。
#define KERNEL_START_ADDR   0x40D3C0
boot_kernel(KERNEL_START_ADDR);
global_reset();
hi_void boot_kernel(uintptr_t kaddr)
{
__asm__ __volatile__("ecall"); /* switch U-MODE -> M-MODE */
hi_void (*entry)(hi_void) = (hi_void*)(kaddr);
entry();
}

在最后build應(yīng)用生成的map文件,可看到內(nèi)存布局如下:

Name             Origin             Length             Attributes
BIN 0x000000000040d3c0 0x0000000000200000 xr
ROM_TEXT 0x00000000003b8000 0x00000000000457e0 xr
ROM_DATA0 0x000000000011d7c0 0x0000000000000020 xrw
ROM_DATA1 0x000000000011d7e0 0x00000000000006e8 xrw
ROM_BSS 0x000000000011a9c0 0x0000000000002e00 xrw
STACK 0x00000000001185c0 0x0000000000002400 rw
CHECK_INFO 0x000000000011dfc0 0x0000000000000040 rw
FLASH 0x000000000040d3c0 0x00000000001f2c40 xrw
PATCH_BSS 0x00000000000d8000 0x0000000000000400 xrw
RAM 0x00000000000d8400 0x00000000000401c0 xrw
EXTERN_ROM_DATA1_BSS 0x000000000011dec8 0x00000000000000f8 xrw
*default* 0x0000000000000000 0xffffffffffffffff

.entry.text 0x000000000040d3c0 0x4 build/libs/hi3861/release/no_mesh/liblitekernel_flash.a(los_startup.o)
0x000000000040d3c0 _start
0x000000000040d3e0 . = ALIGN (0x20)

對比可以看到,KERNEL_START_ADDR與應(yīng)用程序的起始地址一致,基本可推斷flashboot最后操作為調(diào)用應(yīng)用程序。通過ecall指令,實(shí)現(xiàn)RISC-V處理器( Hi3861使用 )從User Mode( 禁止不可信代碼執(zhí)行特權(quán)指令 )切換為Machine Mode( 最高特權(quán)模式 )。

四、小結(jié)

本文采用倒序的方式,初步梳理了從Hi3861芯片上電到OpenHarmony應(yīng)用程序啟動(dòng)運(yùn)行的流程。還有很多內(nèi)容都沒有涉及,包括芯片安全啟動(dòng),F(xiàn)lash的存儲(chǔ)分布等,boot部分說明也比較粗淺。

??想了解更多關(guān)于開源的內(nèi)容,請?jiān)L問:??

??51CTO 開源基礎(chǔ)軟件社區(qū)??

??https://ost.51cto.com??。

責(zé)任編輯:jianghua 來源: 鴻蒙社區(qū)
相關(guān)推薦

2010-11-23 10:51:45

UI交互設(shè)計(jì)產(chǎn)品管理

2023-09-19 15:21:33

RTC鴻蒙

2023-09-06 15:27:22

ADC鴻蒙

2023-09-06 15:31:19

GPIO鴻蒙

2023-09-19 15:14:59

鴻蒙Watchdog

2009-10-21 09:38:34

VB QuickSor

2022-08-19 10:54:47

操作系統(tǒng)鴻蒙

2011-08-05 13:49:53

iPhone 應(yīng)用 開發(fā)

2009-09-27 10:37:01

Java應(yīng)用程序Hibernate

2021-11-24 09:00:00

云計(jì)算開發(fā)應(yīng)用

2010-08-10 15:26:38

Flex應(yīng)用程序

2014-06-20 11:05:56

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-20 11:09:35

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-19 14:25:04

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-20 11:24:34

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-20 11:20:37

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-19 14:30:28

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-19 14:59:40

Android應(yīng)用程序進(jìn)程啟動(dòng)

2014-06-19 14:54:11

Android應(yīng)用程序進(jìn)程啟動(dòng)

2011-07-06 10:22:31

XCode IOS object-C
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)