LK是什么

LK 是 Little Kernel 它是 appsbl (Applications ARM Boot Loader)流程代码  ,little kernel 是小内核小操作系统。

LK 代码 在 bootable/bootloadler/lk 目录下

LK 代码结构

+app            // 应用相关

+arch           // arm 体系

+dev            // 设备相关

+include      // 头文件

+kernel        // lk系统相关

+platform    // 相关驱动

+projiect     // makefile文件

+scripts      // Jtag 脚本

+target        // 具体板子相关

LK 流程分析

在 bootable/bootloadler/lk/arch/arm/ssystem-onesegment.ld 连接文件中 ENTRY(_start)指定 LK 从_start 函数开始,_start
在 lk/arch/crt0.S中 。crt0.S 主要做一些基本的 CPU 的初始化再通过 bl  kmain ;跳转到 C 代码中。

kmain 在 lk/kernel/main.c 中

kmain()

kmain 主要做两件事:1、本身 lk 这个系统模块的初始化;2、boot 的启动初始化动作。

kmain 源码分析:

   void kmain()

          {

          1.初始化进程(lk 中的简单进程)相关结构体。

             thread_init_early();

          
2.做一些如 关闭 cache,使能 mmu 的 arm 相关工作。

            arch_early_init();

           3.相关平台的早期初始化

            platform_early_init();

           4.现在就一个函数跳转,初始化UART(板子相关)

            target_early_init();

           5.构造函数相关初始化

            call_constructors();

          
6.lk系统相关的堆栈初始化

            heap_init();

           7.简短的初始化定时器对象

            thread_init();

          
8.lk系统控制器初始化(相关事件初始化)

            dpc_init();

          
9.初始化lk中的定时器

            timer_init();
          
10.新建线程入口函数
bootstrap2 用于boot 工作(重点)
           thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));

}

bootstrap2,arch_early_init()

        
体系架构相关的初始化我们一般用的 ARM 体系

        
1.关闭cache

         arch_disable_cache(UCACHE);

        
2.设置向量基地址(中断相关)

         set_vector_base(MEMBASE);

        
3.初始化MMU

         arm_mmu_init();

        
4.初始化MMU映射__平台相关

         platform_init_mmu_mappings();

        
5.开启cache        

         arch_enable_cache(UCACHE)

        
6.使能 cp10 和 cp11

         __asm__ volatile("mrc    p15, 0, %0, c1, c0, 2" : "=r" (val));

         val |= (3<<22)|(3<<20);

         __asm__ volatile("mcr    p15, 0, %0, c1, c0, 2" :: "r" (val));
 

       
7.设置使能 fpexc 位
(中断相关)

        __asm__ volatile("mrc  p10, 7, %0, c8, c0, 0" : "=r" (val));

        val |= (1<<30);

        __asm__ volatile("mcr  p10, 7, %0, c8, c0, 0" :: "r" (val));

       
8.使能循环计数寄存器

        __asm__ volatile("mrc    p15, 0, %0, c9, c12, 0" : "=r" (en));

        en &= ~(1<<3); /*循环计算每个周期*/

        en |= 1;

        __asm__ volatile("mcr    p15, 0, %0, c9, c12, 0" :: "r" (en));

      
9.使能循环计数器

       en = (1<<31);
       __asm__ volatile("mcr    p15, 0, %0, c9, c12, 1" :: "r" (en));

平台相关初始化不同平台不同的初始化下面是msm7x30

1.初始化中断

platform_init_interrupts();

2.初始化定时器

platform_init_timer();

       bootstrap2
在kmain的末尾以线程方式开启。主要分三步:platform_init、target_init、apps_init。

1.platform_init

platform_init 中主要是函数 acpu_clock_init。

在 acpu_clock_init 对 arm11 进行系统时钟设置,超频

2.target_init

针对硬件平台进行设置。主要对 arm9 和 arm11 的分区表进行整合,初始化flash和读取FLASH信息

3.apps_init

apps_init 是关键,对 LK 中所谓 app 初始化并运行起来,而 aboot_init 就将在这里开始被运行,android linux 内核的加载工作就在 aboot_init 中完成的 。

aboot_init

1.设置NAND/
EMMC读取信息页面大小
        if (target_is_emmc_boot())

        {

                  page_size = 2048;

                  page_mask = page_size - 1;

        }

       else

       {

                 page_size = flash_page_size();

                 page_mask = page_size - 1;

        }

2.读取按键信息,判断是正常开机,还是进入 fastboot ,还是进入recovery 模式

。。。。。。。。。

       。。。。。。。。。

3.从 nand 中加载 内核


boot_linux_from_flash();

 

      partition_dump();

      sz = target_get_max_flash_size();

      fastboot_init(target_get_scratch_address(), sz);

      udc_start(); // 开始 USB 协议


boot_linux_from_flash

  主要是内核的加载过程,我们的 boot.img 包含:kernel 头、kernel、ramdisk、second stage(可以没有)。

          
1.读取boot 头部

           flash_read(p, offset, raw_header, 2048)

           offset += 2048;
          
2.读取 内核   

           memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)
           n = (hdr->kernel_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));

           flash_read(p, offset, (void*) hdr->kernel_addr, n)

           offset += n;
          
3.读取 ramdisk
           n = (hdr->ramdisk_size + (FLASH_PAGE_SIZE - 1)) & (~(FLASH_PAGE_SIZE - 1));

           flash_read(p, offset, (void*) hdr->ramdisk_addr, n)

           offset += n;

           
4.启动内核

                boot_linux();//在boot_linux
中entry(0,machtype,tags);从kernel加载在内核中的地址开始运行了。

到这里LK的启动过程就结束了。

Android 开发之 ---- bootloader (LK)的更多相关文章

  1. android初级应用到高端架构教程------ 完整体系化学习android开发

    系统的学习android开发技术,从应用到底层,再到架构,告别乱糟糟的学习方式,不再是抓不住重点.从上到下贯通,全面学习android开发.让你拥有清晰的思路,一步步学习android开发! 一般而言 ...

  2. linux和android开发链接

    1.Tracy Mcgrady的专栏冰山一角:linux和Android底层开发,主要是mtk系列点击打开链接 2.郁闷Wednesday:嵌入式linux 单片机 android,点击打开链接 3. ...

  3. Android开发学习之路--Android系统架构初探

    环境搭建好了,最简单的app也运行过了,那么app到底是怎么运行在手机上的,手机又到底怎么能运行这些应用,一堆的电子元器件最后可以运行这么美妙的界面,在此还是需要好好研究研究.这里从芯片及硬件模块-& ...

  4. android开发笔记之fastboot的使用

    fastboot命令大全 在终端中.我们输入: fastboot 对于这些命令.我不解释,慢慢使用.慢慢的就会明确是怎么回事了. android分区 分区 作用 splash1 开机画面.使用Nand ...

  5. Android学习探索之Java 8 在Android 开发中的应用

    前言: Java 8推出已经将近2年多了,引入很多革命性变化,加入了函数式编程的特征,使基于行为的编程成为可能,同时减化了各种设计模式的实现方式,是Java有史以来最重要的更新.但是Android上, ...

  6. Android 开发一定要看的15个实战项目

    前言: 虽说网上有太多的Android课程,但是大多都是视频,有Android在线开发环境的几乎没有,但是对于学习Android的人来说拥有在线的Android开发环境是非常好的,可以随时动手操作学习 ...

  7. Android开发学习之路-关于Exception

    Exception在Java中是表示异常的一个类.它是Throwable的子类. 而Exception的子类RuntimeException是一个特殊的异常类,在代码中不需要对此类进行throw,而是 ...

  8. Android开发学习之路-Android中使用RxJava

    RxJava的核心内容很简单,就是进行异步操作.类似于Handler和AsyncTask的功能,但是在代码结构上不同. RxJava使用了观察者模式和建造者模式中的链式调用(类似于C#的LINQ). ...

  9. Android开发学习之路-记一次CSDN公开课

    今天的CSDN公开课Android事件处理重难点快速掌握中老师讲到一个概念我觉得不正确. 原话是这样的:点击事件可以通过事件监听和回调两种方法实现. 我一听到之后我的表情是这样的: 这跟我学的看的都不 ...

随机推荐

  1. UVALive 6426

    UVALive 6426 /** 题意:给一个n*m的矩阵,求某一个区间的数的数量 做法:刚开始想用树状数组,但是RE,题目中说数据是从二进制流中读入, 用scanf会挂掉 所以用fread 读入 s ...

  2. EF Groupby

    最近做了个检索类的项目,其中就用到统计了,就是按照热门搜索排序来的. 话不多说,直接代码 var requirementSearchesOrder = app_RequirementSearches. ...

  3. c# 发送web请求

    我们目前涉及到的现有的接收请求方式有三种, 第一种: 页面式的Form表单 第二种: 服务的webservice形式的xml 第三个: restful风格的post包体json 第一种比较老,博客园的 ...

  4. 关于在C#中对类中的隐藏基类方法和重写方法的理解

    最近在学习C#,在C#中的类看到重写和隐藏基类的方法这些概念.才开始感觉自己不是很理解这些概念.也区分不开这些概念.通过自己的查找资料和练习后.慢慢的理解了类中的隐藏和重写这个概念.在C#中只有在基类 ...

  5. python版本管理(python环境隔离)

    这将是一篇比较短的文章. 我发文向来注重文章质量,营养不够的宁可不发,但是我相信很多人需要这篇文章. 之所以要去搞清楚这个问题,是我在把 vscode 的 inspector 设置为 pipenv 生 ...

  6. vue-touch不支持vue2.0的替换方法

    当你想用vue-touch时,却发现官网这句话 Touch events plugin for Vue.js. This plugin does not support Vue 2.0 yet. 但是 ...

  7. img加载不出来,给个默认图片。

    忽然发现,jq里也有坑,很多东西莫名其妙的被废弃了……所以,只能用原生js来做了: $('img').each(function() { if (!this.complete || typeof th ...

  8. C++ cin.ignore()用法

    cin.ignore(int a,char b); a为一行中最大读取字符长度,b为某一个字符.在缓冲区中寻找b,找到后忽略b以前的所有字符(包括b).如果在a的范围内还没有找到b,则忽略b以前的所有 ...

  9. CentOS6安装后的常见基础优化

    1.SSH优化 编辑/etc/ssh/sshd_config配置文件 //全部都应该设置为no /etc/ssh/sshd_config //服务端配置文件 /etc/ssh/ssh_config / ...

  10. JSON字符串转对象

    JSON(JavaScript Object Notation) JavaScript对象标记法:JSON是与JavaScript高度契合的:JSON 语法:    --数组(Array)用" ...