Little Kernel启动过程

1. LK 代码结构

app/			应用相关
arch/		    arm 体系 
dev/			设备相关
include/		头文件
kernel/		    lk系统相关   
platform/		相关驱动
projiect/		makefile文件
scripts/		Jtag 脚本
target/		    具体板子相关

2. LK流程分析

        lk/arch/arm/ssystem-onesegment.ld 连接文件中 ENTRY(_start)指定 LK 从_start 函数开始,_start 在 lk/arch/start.S 。

        start.S主要做一些基本的CPU的初始化再通过 bl lk_main ;跳转到 C代码中。

        lk/top/main.c中有lk_main()函数的定义

lk_main()	        //lk/top/main.c
    bootstrap2()    
        apps_init();	//lk/app/app.c
            app->init(app);	//会调用到lk/app/atc_boot/boot_kernel.c中的boot_kernel_init
            start_app(app);	//会调用到lk/app/atc_boot/boot_kernel.c中的boot_linux_from_emmc
                theKernel (FDT_LOAD_ADDR_PHYS, 0, 0);	//启动kernel

3.  启动流程详解

/* called from arch code */
void lk_main(ulong arg0, ulong arg1, ulong arg2, ulong arg3)
{
    uint32_t cpacr = ARM64_READ_SYSREG(cpacr_el1);

    // save the boot args
    lk_boot_args[0] = arg0;
    lk_boot_args[1] = arg1;
    lk_boot_args[2] = arg2;
    lk_boot_args[3] = arg3;

    lk_boot_time = current_time();

    // get us into some sort of thread context
    thread_init_early();	//初始化LK的线程系统

    // early arch stuff
    lk_primary_cpu_init_level(LK_INIT_LEVEL_EARLIEST, LK_INIT_LEVEL_ARCH_EARLY - 1);
    arch_early_init();	//架构相关早期初始化,如使能MMU,cache等等)

    // do any super early platform initialization
    lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH_EARLY, LK_INIT_LEVEL_PLATFORM_EARLY - 1);
    platform_early_init();	//平台相关早期初始化,如获取板级信息,初始化时钟、中断、定时器等等

    // do any super early target initialization
    lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM_EARLY, LK_INIT_LEVEL_TARGET_EARLY - 1);
    target_early_init();	//初始化目标,其中只初始化了串口

    // bring up the kernel heap
    lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET_EARLY, LK_INIT_LEVEL_HEAP - 1);
    dprintf(SPEW, "initializing heap\n");
    heap_init();	//堆初始化,用于malloc等函数的内存分配

    // deal with any static constructors
    dprintf(SPEW, "calling constructors\n");
    call_constructors();	//构造函数相关初始化
   
    // create a thread to complete system initialization
    //新建线程入口函数 bootstrap2, 用于boot工作(重点)
    dprintf(SPEW, "creating bootstrap completion thread\n");
    thread_t *t = thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE * 3);
    thread_set_pinned_cpu(t, 0);
    thread_detach(t);
    thread_resume(t);

    // become the idle thread and enable interrupts to start the scheduler
    thread_become_idle();	//将本线程切换至idle状态
}

static int bootstrap2(void *arg)
{
    // initialize the rest of the platform
    dprintf(SPEW, "initializing platform\n");
    lk_primary_cpu_init_level(LK_INIT_LEVEL_ARCH, LK_INIT_LEVEL_PLATFORM - 1);
    platform_init();

    // initialize the target
    dprintf(SPEW, "initializing target\n");
    lk_primary_cpu_init_level(LK_INIT_LEVEL_PLATFORM, LK_INIT_LEVEL_TARGET - 1);
    target_init();

    dprintf(SPEW, "calling apps_init()\n");
    lk_primary_cpu_init_level(LK_INIT_LEVEL_TARGET, LK_INIT_LEVEL_APPS - 1);
    apps_init();	//初始化APP,启动内核

    return 0;
}

void apps_init(void)
{
    const struct app_descriptor *app;

    /* call all the init routines */	//apps_start和apps_end都是在lk/app/app.ld文件中指定的, 表示apps段
    for (app = &__apps_start; app != &__apps_end; app++) {
        if (app->init)
            app->init(app);			//调用到lk/app/atc_boot/boot_kernel.c中的boot_kernel_init
    }

    /* start any that want to start on boot */
    for (app = &__apps_start; app != &__apps_end; app++) {
        if (app->entry && (app->flags & APP_FLAG_DONT_START_ON_BOOT) == 0) {
            start_app(app);			//调用到lk/app/atc_boot/boot_kernel.c中的boot_linux_from_emmc
        }
    }
}

static void start_app(const struct app_descriptor *app)
{
    uint32_t stack_size = (app->flags & APP_FLAG_CUSTOM_STACK_SIZE) ? app->stack_size : DEFAULT_STACK_SIZE;

    printf("starting app %s\n", app->name);
    thread_t *t = thread_create(app->name, &app_thread_entry, (void *)app, DEFAULT_PRIORITY, stack_size);
    thread_detach(t);
    thread_resume(t);
}

static int app_thread_entry(void *arg)
{
    const struct app_descriptor *app = (const struct app_descriptor *)arg;
    app->entry(app, NULL);
    return 0;
}

/* lk/app/atc_boot/boot_kernel.c */
/* jump to kernel */
static void boot_linux_from_emmc(const struct app_descriptor *app, void *args)
{
    load_image_from_bootimg(KERNEL_LOAD_ADDR, BOOTIMG_IMAGEGZ);
    load_image_from_bootimg(ROOTFS_LOAD_ADDR, BOOTIMG_RAMDISK);
    pr_time("[lk time] start jump to kernel at %ums\n", get_current_time_ms());

    cleanup_before_linux();
    /* simple jump from 64bit LK to 64bit kernel */
    void (*theKernel)(unsigned long fdtAddr, unsigned long x1, unsigned long x2);
    theKernel = (void (*)(unsigned long, unsigned long, unsigned long))(KERNEL_LOAD_ADDR_PHYS);
    theKernel (FDT_LOAD_ADDR_PHYS, 0, 0);
#endif
}

附录

/* lk/app/app.ld */
SECTIONS {
    .apps : {
        __apps_start = .;
        KEEP (*(.apps))
        __apps_end = .;
    }
}
INSERT AFTER .rodata;

/* lk/app/atc_boot/boot_kernel.c */
APP_START(atc_boot)
.init = boot_kernel_init,
.entry = boot_linux_from_emmc,
APP_END

#define APP_START(appname) const struct app_descriptor _app_##appname __ALIGNED(sizeof(void *)) __SECTION(".apps") = { .name = #appname,
#define APP_END };

/* 由APP_START(atc_boot)得到如下结构体: */
const struct app_descriptor _app_atc_boot __ALIGNED(sizeof(void *)) __SECTION(".apps") = {
    .name = atc_boot,
    .init = boot_kernel_init,
    .entry = boot_linux_from_emmc,
}

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值