[文章]【HarmonyOS HiSpark IPC DIY Camera试用连载 】liteos-a启动流程概述

阅读量0
0
0



lite os 启动流程分析
拿到开发板一段时间了,论坛里各个开箱报告都写的很好,感觉自己拍马难及,所以本篇文章想从另外一个角度分享下自己的使用心得,粗略的分析下liteos-a的启动流程,抛装引玉。希望大神勿喷。哈哈哈哈。
  一、启动的汇编文件    一般来说可以通过连接脚本来找到内核启动的入口,在liteos_a的目录下执行make命令,在编译输出的最后链接的时候,其中-T选项是指定的链接脚本,为kernelliteos_atoolsbuildliteos_llvm.ld
    在这个文件中第一行为:
           ENTRY(reset_vector) 也就是说入口地址为reset_vector 段,不难想象这个就是复位向量表的地址,文件为:kernelliteos_aarcharmarmsrcstartupreset_vector_up.c文件,在这个文件的目录下还有一个                        reset_vector_mp.c文件,他是多核的启动文件。
    还有一个比较笨的方法就是通过文件目录去找,一般内核的启动文件肯定是一个与架构相关的汇编文件,通过目录可以也很容易的找到。刚开始我就是通过方法来找的。
  汇编文件的入口为:
reset_vector: 主要做以下事情
1 首先关闭i-cache d0cache 关掉MMU
2 如果需要重定位则进行内核的重定位,
2 建立内核和外设的内存映射,或者说是页表,这里采用一级页表大小为1M,
3 进行栈的初始化,
4 初始化cpsr寄存器,
5 清除BSS段,
6 跳入main函数
后续如有必要会详细分析下整个内核的内存管理。
二、系统的初始化的分析LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
{
    UINT32 uwRet = LOS_OK;

//设置主任务 ,即给每个核设置一个main task 暂时不去分析,等到任务切换的时候再看
    OsSetMainTask();
    OsCurrTaskSet(OsGetMainTask());

    /* set smp system counter freq */
#if (LOSCFG_KERNEL_SMP == YES)
#ifndef LOSCFG_TEE_ENABLE
    HalClockFreqWrite(OS_SYS_CLOCK);
#endif
#endif
    /* system and chip info */
    OsSystemInfo();  //打印kernel的一些信息,此时还没有初始化串口,所以这些信息应该只是放在buf中,
    PRINT_RELEASE("nmain core booting up...n");
    PRINT_RELEASE("This is my hello world in kernel!n"); //打印自己定义的调试信息
    uwRet = OsMain(); //这个函数用来进行kernel的初始化工作 下面对这个函数进行分析
    if (uwRet != LOS_OK) {
        return LOS_NOK;
    }
#if (LOSCFG_KERNEL_SMP == YES)
    PRINT_RELEASE("releasing %u secondary coresn", LOSCFG_KERNEL_SMP_CORE_NUM - 1);
    release_secondary_cores();
#endif
    CPU_MAP_SET(0, OsHwIDGet());
    OsStart();  //启动kernel
    while (1) {
        __asm volatile("wfi");
    }
}
   OsMain()函数的分析这个函数在 code-1.0kernelliteos_akernelcommonLos_config.c 在这个位置,这个里面主要是对内核的各个部分进行初始化,我们只关注与启动流程相关的 ,
LITE_OS_SEC_TEXT_INIT INT32 OsMain(VOID)
{
    UINT32 ret;
  osRegister();  // 只是简单的将一些宏赋给变量 比如#define LOSCFG_BASE_CORE_TICK_PER_SECOND 100  用来定义系统的调度周期 也就是10ms 所以内核的sys_tick默认是10ms
#ifdef LOSCFG_SHELL_DMESG
    ret = OsDmesgInit();
    if (ret != LOS_OK) {
        return ret;
    }
#endif
#ifdef LOSCFG_SHELL_LK
    OsLkLoggerInit(NULL);
#endif
#ifdef LOSCFG_EXC_INTERACTION
#ifdef LOSCFG_ARCH_CORTEX_M7
    /* 4096: 4K space for Stack */
    ret = OsMemExcInteractionInit((UINT32)&__bss_end + 4096);
#else
    ret = OsMemExcInteractionInit((UINTPTR)&__bss_end);
#endif
    if (ret != LOS_OK) {
        return ret;
    }
#endif
#if (LOSCFG_PLATFORM_HWI == YES)
    OsHwiInit();
#endif
    OsExcInit();
    ret = OsTickInit(g_sysClock, LOSCFG_BASE_CORE_TICK_PER_SECOND); //初始化硬件时钟,
    if (ret != LOS_OK) {
        return ret;
    }
#ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
#ifdef LOSCFG_DRIVERS
  uart_init(); //uart 初始化
#endif
#ifdef LOSCFG_SHELL
#endif //LOSCFG_SHELL
#endif //LOSCFG_PLATFORM_UART_WITHOUT_VFS
    ret = OsTaskInit(); //task 初始化
    if (ret != LOS_OK) {
        PRINT_ERR("OsTaskInit errorn");
        return ret;
    }
#if ((LOSCFG_BASE_IPC_QUEUE == YES) || (LOSCFG_BASE_IPC_MUX == YES) || (LOSCFG_BASE_IPC_SEM == YES))
    ret = OsIpcInit(); //进程通信初始化
    if (ret != LOS_OK) {
        return ret;
    }
#endif
    ret = OsSysMemInit();  //系统内存初始化
    if (ret != LOS_OK) {
        PRINT_ERR("OsSysMemInit errorn");
        return ret;
    }
    SyscallHandleInit(); //系统调用初始化
    /*
    * CPUP should be inited before first task creation which depends on the semaphore
    * when LOSCFG_KERNEL_SMP_TASK_SYNC is enabled. So don't change this init sequence
    * if not neccessary. The sequence should be like this:
    * 1. OsIpcInit
    * 2. OsCpupInit
    * 3. other inits have task creation
    */
#ifdef LOSCFG_KERNEL_CPUP
    ret = OsCpupInit();
    if (ret != LOS_OK) {
        PRINT_ERR("OsCpupInit errorn");
        return ret;
    }
#endif
    ret = OsKernelInitProcess(); //内核进程的初始化
    if (ret != LOS_OK) {
        return ret;
    }
#if (LOSCFG_BASE_CORE_SWTMR == YES)
    ret = OsSwtmrInit();
    if (ret != LOS_OK) {
        return ret;
    }
#endif
#ifdef LOSCFG_KERNEL_CPUP
    OsCpupGuardCreator();
#endif
#if (LOSCFG_KERNEL_SMP == YES)
    (VOID)OsMpInit();
#endif
#if defined(LOSCFG_HW_RANDOM_ENABLE) || defined (LOSCFG_DRIVERS_RANDOM)
    random_alg_context.ra_init_alg(NULL);
    run_harvester_iterate(NULL);
#endif
#ifdef LOSCFG_COMPAT_BSD
    ret = OsBsdInit();
    if (ret != LOS_OK) {
        PRINT_ERR("init bsd failed!n");
        return ret;
    }
#endif
#ifdef LOSCFG_KERNEL_PIPE
    OsDriverPipeInit();
#endif
  ret = OsSystemInit(); // 在这个里面会创建一些task 用来做一些特定的初始化 下面会分析这个函数
    if (ret != LOS_OK) {
        return ret;
    }
#if LOSCFG_DRIVERS_HIEVENT
    OsDriverHiEventInit();
#endif
#if (LOSCFG_KERNEL_TRACE == YES)
    LOS_TraceInit();
#endif
#if (LOSCFG_KERNEL_LITEIPC == YES)
    ret = LiteIpcInit();
    if (ret != LOS_OK) {
        return ret;
    }
#endif
#if (LOSCFG_BASE_CORE_HILOG == YES)
    ret = HiLogDriverInit();
    if (ret != LOS_OK) {
        return ret;
    }
#endif
#ifdef LOSCFG_KERNEL_VDSO
    ret = OsInitVdso();
    if (ret != LOS_OK) {
        return ret;
    }
#endif
    ret = OsFutexInit();
    if (ret != LOS_OK) {
        PRINT_ERR("Create futex failed : %d!n", ret);
        return ret;
    }
    ret = OomTaskInit();
    if (ret != LOS_OK) {
        return ret;
    }
    return LOS_OK;
}

OsSystemInit(); 函数分析UINT32 OsSystemInit(VOID)
{
    UINT32 ret;
#ifdef LOSCFG_FS_VFS
    los_vfs_init();
#endif
#ifdef LOSCFG_COMPAT_LINUXKPI
    g_pstSystemWq = create_workqueue("system_wq");
#endif
    ret = OsSystemInitTaskCreate(); //创建一个系统初始化的任务
    if (ret != LOS_OK) {
        return ret;
    }
  ret = OsMyTaskCreate(); //创建一个自己测试的任务
    if (ret != LOS_OK) {
        return ret;
    }
    PRINTK("OsMyTaskCreate!!!n");  //打印测试的信息
#ifdef LOSCFG_MEM_RECORDINFO
    ret = OsMemShowTaskCreate();
    if (ret != LOS_OK) {
        PRINTK("create memshow_Task error %un", ret);
        return ret;
    }
    PRINTK("create memshow_Task okn");
#endif
#ifdef LOSCFG_KERNEL_TICKLESS
    LOS_TicklessEnable();
#endif
    return 0;
}

自己测试任务的执行函数如下,每3秒打印一个信息
static void MyKerneltask(VOID)
{
while(1)
{
PRINTK("MyKerneltaskn");
sleep(3);
}
}
系统初始化任务的执行函数如下,初始化各种应用层相关的驱动 文件系统 等等
最终会挂载根文件系统,启动init进程
void SystemInit(void)
{
#ifdef LOSCFG_PLATFORM_HISI_AMP
    extern int _ipcm_vdd_init(void);
    dprintf("ipcm init ...n");
    _ipcm_vdd_init();
#ifndef LOSCFG_ARCH_CORTEX_M7
    extern int sharefs_client_init(const char *path);
    dprintf("sharefs init ...n");
    sharefs_client_init("/sharefs");
#endif
    extern int virt_tty_dev_init(void);
    dprintf("virt tty init ...n");
    virt_tty_dev_init();
#endif
#ifdef LOSCFG_DRIVERS_RANDOM
    dprintf("random dev init ...n");
    extern int ran_dev_register(void);
    ran_dev_register();
#endif
#ifdef LOSCFG_FS_PROC
    dprintf("proc fs init ...n");
    extern void ProcFsInit(void);
    ProcFsInit();
#endif
#ifdef LOSCFG_DRIVERS_MMC
    dprintf("MMC dev init ...");
    extern int SD_MMC_Host_init(void);
    SD_MMC_Host_init();
#endif
#ifdef LOSCFG_DRIVERS_MEM
    dprintf("mem dev init ...n");
    extern int mem_dev_register(void);
    mem_dev_register();
#endif
#ifndef LOSCFG_DRIVERS_HDF
#ifdef LOSCFG_DRIVERS_GPIO
    dprintf("gpio init ...n");
    extern int gpio_dev_init(void);
    gpio_dev_init();
#endif
#endif
#ifdef LOSCFG_DRIVERS_HIEDMAC
    extern int hiedmac_init(void);
    hiedmac_init();
#endif
#ifdef LOSCFG_DRIVERS_HIDMAC
    dprintf("dmac init ...n");
#endif
#ifdef LOSCFG_DRIVERS_MTD_NAND
    dprintf("nand init ...n");
    extern int nand_init(void);
    if (!nand_init()) {
        extern int add_mtd_partition(char *type, UINT32 start_addr, UINT32 length, UINT32 partition_num);
        extern int mount(const char *source, const char *target,
                        const char *filesystemtype, unsigned long mountflags,
                        const void *data);
    }
#endif
#ifdef LOSCFG_DRIVERS_MTD_SPI_NOR
    dprintf("spi nor flash init ...n");
    extern int spinor_init(void);
    if (!spinor_init()) {
        dprintf("spinor_init ...n");
    }
#endif
#ifdef LOSCFG_DRIVERS_NETDEV
    dprintf("net init ...n");
    net_init();
    dprintf("n************************************************************n");
#endif
#ifdef LOSCFG_DRIVERS_USB
    dprintf("u*** init ...n");
    u***_init(DEVICE, DEV_ETHERNET);
#endif
    dprintf("Date:%s.n", __DATE__);
    dprintf("Time:%s.n", __TIME__);
#ifndef LOSCFG_DRIVERS_HDF_PLATFORM_HISI_SDK
    dprintf("calling SDK_init form HISI_SDK");
    SDK_init();
    dprintf("calling SDK_init form HISI_SDK done!");
#endif
#ifdef LOSCFG_PLATFORM_ROOTFS
    dprintf("OsMountRootfs start ...n");
    OsMountRootfs(); //挂载根文件系统
    dprintf("OsMountRootfs end ...n");
#endif
#ifdef LOSCFG_DRIVERS_HDF
    dprintf("DeviceManagerStart start ...n");
    if (DeviceManagerStart()) {
        PRINT_ERR("No drivers need load by hdf manager!");
    }
    dprintf("DeviceManagerStart end ...n");
#endif
#ifdef LOSCFG_DRIVERS_HDF_PLATFORM_UART
    dprintf("virtual_serial_init start ...n");
    if (virtual_serial_init(TTY_DEVICE) != 0) {
        PRINT_ERR("virtual_serial_init failed");
    }
    dprintf("virtual_serial_init end ...n");
    if (system_console_init(SERIAL) != 0) {
        PRINT_ERR("system_console_init failedn");
    }
    dprintf("system_console_init end ...n");
#endif
#ifdef LOSCFG_SHELL
    dprintf("CatLogShell start ...n");
    CatLogShell();
    dprintf("CatLogShell start ...n");
#endif
    dprintf("OsUserInitProcess start ...n");
    if (OsUserInitProcess()) { //启动用户进程
        PRINT_ERR("Create user init process faialed!n");
        return;
    }
    dprintf("OsUserInitProcess end ...n");
    return;
}
三、用户进程的启动LITE_OS_SEC_TEXT_INIT UINT32 OsUserInitProcess(VOID)
{
//在这个函数中会创建一个用户进程
LosProcessCB *processCB = OS_PCB_FROM_PID(g_userInitProcess);
        et = OsProcessCreateInit(processCB, OS_USER_MODE, "Init", OS_PROCESS_USERINIT_PRIORITY);
        if (ret != LOS_OK) {
        return ret;
        }
//    用户进程的起始地址为:
CHAR *userInitTextStart = (CHAR *)&__user_init_entry;
}
上面的起始地址为用户进程的首地址
在code-1.0kernelliteos_akernelusersrclos_user_init.c 中
LITE_USER_SEC_ENTRY VOID OsUserInit(VOID *args)
{
printf("OsUserInit startn"); //打印调试信息
#ifdef LOSCFG_KERNEL_DYNLOAD
  sys_call3(__NR_execve, (UINTPTR)g_initPath, 0, 0);  //执行系统调用来执行elf文件 g_initPath = "/bin/init"
#endif
    while (1) {
    }
}
/bin/init 即:
code-1.0kernelliteos_aappsinitsrcinit.c 此时在用户模式 ,
int main(int argc, char * const *argv)
{
    int ret;
    const char *shellPath = "/bin/shell"; // fork一个shell进程
    ret = fork();
    if (ret < 0) {
        printf("Failed to fork for shelln");
    } else if (ret == 0) {
        (void)execve(shellPath, NULL, NULL);
        exit(0);
    }
    printf("exec shell n"); //打印调试信息
    while (1) {
        ret = waitpid(-1, 0, WNOHANG);
        if (ret == 0) {
            sleep(1);
        }
    };
}
启动shell
code-1.0kernelliteos_aappsshellsrcmain.c

int main()
{
....... //省去
printf("this is in shelln"); //调试信息
g_shellCB = shellCB;
return OsShellCreateTask(shellCB); //创建一个shell任务
}
在创建shell task
static int OsShellCreateTask(ShellCB *shellCB)
{
struct sched_param param = { 0 };
int ret;
ret = sched_getparam(getpid(), &param);
if (ret != SH_OK) {
goto OUT;
}
param.sched_priority = SHELL_PROCESS_PRIORITY_INIT;
ret = sched_setparam(getpid(), &param);
if (ret != SH_OK) {
goto OUT;
}
printf("ShellTaskInitn"); //打印调试信息
ret = ShellTaskInit(shellCB); //在这里会创建shelltask 线程
if (ret != SH_OK) {
goto OUT;
}
printf("ShellEntryInit"); //打印调试信息
ret = ShellEntryInit(shellCB); //创建shellentry线程
if (ret != SH_OK) {
goto OUT;
}
(void)pthread_join(shellCB->shellTaskHandle, NULL);
(void)pthread_join(shellCB->shellEntryHandle, NULL);
OUT:
ShellDeinit(shellCB);
return ret;
}


以上两个线程就是用来解析和执行我们在控制台输入的命令

对于shelltask
code-1.0kernelliteos_aappsshellsrcShmsg.c
void *ShellTask(void *argv)
{
int ret;
ShellCB *shellCB = (ShellCB *)argv;
if (shellCB == NULL) {
return NULL;
}
ret = prctl(PR_SET_NAME, "ShellTask");
if (ret != SH_OK) {
return NULL;
}
printf(SHELL_PROMPT);//修改这个宏用来测试 #define SHELL_PROMPT COLOR_L_RED"MY_OHOS # "COLOR_NONE
while (1) {
ret = ShellPend(shellCB);
if (ret == SH_OK) {
ShellCmdProcess(shellCB);
} else if (ret != SH_OK) {
break;
}
}
return NULL;
}

以上就是liteos启动的大致流程。最后放两张测试的图片,主要是看下我们在代码中添加的调试信息。

微信图片_20201216201311.png
微信图片_20201216201325.png

回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友