LK概览

来源:互联网 发布:管道保温计算软件 编辑:程序博客网 时间:2024/06/05 20:26
从Makefile开始
1)bootable/bootloader/lk根目录下有makefile和AndroidBoot.mk
2)bootable/bootloader/lk的各个子目录下有rules.mk文件,还有arch/arm/compile.mk和target一些tools子目录中的makefile等
3)先从rules.mk的输入输出开始研究
输入:可以用GET_LOCAL_DIR命令获取当前目录
      ARM_CPU变量
      ENABLE_LPAE_SUPPORT变量
      BUILDDIR变量
      ENABLE_MDTP_SUPPORT变量
输出:链接的库文件定义在MODULES变量中
      目标.o文件定义在OBJS变量中
      编译引用的搜索路径集定义在INCLUDES变量中
      ENABLE_THUMB、HANDLED_CORE、CFLAGS、THUMBCFLAGS、THUMBINTERWORK、TOOLCHAIN_PREFIX变量
      定义{值,对}集的DEFINES
      BOOTOBJS定义另一个.o文件集
      target目录的rules.mk中需要定义MEMBASE和MEMSIZE,并由此引出MEMVARS_SET
      以部分变量定义了LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) $(THUMBCFLAGS) -print-libgcc-file-name)
      GENERATED定义了在clean make时会删除的文件(反过来应该也就是指编译过程中动态生成的文件)
      PLATFORM、BASE_ADDR、SCRATCH_ADDR变量
各个rules.mk文件通过makefile的include包含进来,然后融为一体。对于一些子目录的加载过程,略微有点技术处理,比如某个文件需要用到某个子目录的代码实现,它会将该子目录加入到MODULES变量中,之后在make/module.mk中读取所有需要加载的子目录,统一通过include包含进来。
4)开始bootable/bootloader/lk/makefile文件
输入:MAKECMDGOALS变量,并由此得出project,然后定义了一系列编译需要的变量和规则,从这里可以找到编译生成的目标文件有哪些。
而MAKECMDGOALS变量来自/build/core中的核心编译文件。
5)开始AndroidBoot.mk文件
输入:BOOTLOADER_GCC_VERSION变量(来自device/qcom/msm8953_64/BoardConfig.mk)
      TARGET_BOOTIMG_SIGNED变量(同样来自device/qcom/msm8953_64/BoardConfig.mk,表示是否需要包含安全lib)
      TARGET_BOARD_PLATFORM变量(同上)
输出:CROSS_COMPILE变量
      SIGNED_KERNEL变量
定义了ABOOT_OUT、ABOOT_CLEAN、TARGET_NAND_BOOTLOADER、appsbootldr_clean、TARGET_EMMC_BOOTLOADER、emmc_appsbootldr_clean、TARGET_NANDWRITE等变量,并定义了生成这些目标的规则,在这些规则中通过make -c会调用同目录中的makefile文件,并建立上述联系。
6)AndroidBoot.mk在device/qcom/msm8953_32/AndroidBoard.mk中被include,并定义了要目标文件作为droidcord的依赖,最后在build/core/main.mk中加入整个代码的编译行列中。
#----------------------------------------------------------------------
# Compile (L)ittle (K)ernel bootloader and the nandwrite utility
#----------------------------------------------------------------------
ifneq ($(strip $(TARGET_NO_BOOTLOADER)),true)

# Compile
include bootable/bootloader/lk/AndroidBoot.mk

$(INSTALLED_BOOTLOADER_MODULE): $(TARGET_EMMC_BOOTLOADER) | $(ACP)
$(transform-prebuilt-to-target)
$(BUILT_TARGET_FILES_PACKAGE): $(INSTALLED_BOOTLOADER_MODULE)

droidcore: $(INSTALLED_BOOTLOADER_MODULE)
endif

device/qcom/msm8953_32/BoardConfig.mk
TARGET_NO_BOOTLOADER := false

部分细节举例如下:
GENERATED的生效机制
bootable/bootloader/lk/makefile文件中定义如下:
clean: $(EXTRA_CLEANDEPS)
rm -f $(ALLOBJS) $(DEPS) $(GENERATED) $(OUTBIN) $(OUTELF) $(OUTELF).lst $(OUTELF_STRIP)

system-onesegment.ld的生效机制
arch/arm/rules.mk中定义了$(BUILDDIR)/system-onesegment.ld的生成规则
platform的子目录中将$(BUILDDIR)/system-onesegment.ld加入到LINKER_SCRIPT中

bootable/bootloader/lk/make/build.mk中将LINKER_SCRIPT作为OUTELF的依赖文件


功能调试的部分细节:

bootable/bootloader/lk/kernel/main.c文件是最初由汇编调用的(bootable/bootloader/lk/arch/arm/crt0.S)
*.ld为链接脚本文本,链接脚本的写法也别有一番语法。

app目录中,总接口为app.c中的apps_init,如果ENABLE_NANDWRITE宏没有到定义的话,就会被调用。
从bootable/bootloader/lk/project目录的各个mk文件中来看,msm8953是没有定义该宏的,因此apps_init会被调用。
具体哪些app会被调用,中间变量为__apps_start,该变量同样来自system-onesegment.ld等链接文件,从这里可以看到该变量的内容为section为apps数据。
定义来自bootable/bootloader/lk/include/app.h,如下:
#define APP_START(appname) struct app_descriptor _app_##appname __SECTION(".apps") = { .name = #appname,
#define APP_END };
以aboot.c为例,它的定义如下:
APP_START(aboot)
.init = aboot_init,
APP_END

屏幕背光相关的代码位于dev目录下,其中的一种为qpnp_wled,相关的配置数据结构为struct qpnp_wled。以启动cabc功能为例,需要在qpnp_wled_config中配置相应的参数,让背光芯片启动时就设置好相关参数。再向上是qpnp_wled_init函数、target_display.c的wled_init函数等,最终源自aboot_init函数。
在内核中只要在dtsi中给wled: qcom,leds@d800添加qcom,en-cabc;属性,并配置好qcom,mdss-dsi-on-command相应参数即可(因为内核一般都支持这些通用功能)

CABC技术使手机背光省电技术,目前有两种实现方案,分别是:环境光侦测适应背光控制(Light Adaptive Brightness Control - LABC)和内容适应背光技术(Content Adaptive Brightness Control - CABC)。这里主要介绍CABC技术,其中C是内容的意思,驱动IC新增了一个内容分析器电路。如图所示,假设当手机处理器传送了一张图片数据到驱动IC,内容分析器会计算并统计图片的数据后依据设定与算法自动的将其灰阶亮度提高30%(此时图片变亮),再将背光亮度降低30%(此时图片变暗)。由于我们事先已经将图片经过分析器电路补偿亮度,因此使用者可以得到与原先电路相差无几的显示效果,但减少了30%的背光功耗。

项目配置的Board或Hardware ID有如下来源:
1)board.platform/board.target来源于SMEM中固定位置SMEM_BOARD_INFO_LOCATION的内存,应该是芯片出厂时写入的信息,对应芯片的型号。board.target为四个platform相关的参数组成的综合数字,应该说board是具体的芯片细节,platform还属于更抽象的批次划分。相关代码为bootable/bootloader/lk/platform/msm_shared/board.c
2)BOARDID_GPIO_PIN0 | BOARDID_GPIO_PIN1 | BOARDID_GPIO_PIN2和bootable/bootloader/lk/platform/msm_shared/boardinfo.c中定义的预定义数组。
上述的最初调用都来自platform_early_init和bootstrap2函数

启用一个新的LCD,涉及bootable/bootloader/lk/dev/gcdb/display目录以及platform和target目录,比如如下例子:
target/msm8953/oem_panel.c
platform/msm_shared/mipi_dsi.c
dev/gcdb/display/include/panel_ili7807d_lide_auo_fhd_video.h
其实在LK中定义的可用的LCD种类,真正让它工作起来,需要在dtsi中的mdss_dsi1节点中修改qcom,dsi-pref-prim-pan的属性。
综上来看,LK中对LCD、背光的设置,一个是初始化,一个是LK阶段的简单显示。

LCD相关的内核代码应该如下:
kernel/msm-3.18/drivers/leds/
kernel/msm-3.18/drivers/video/backlight/
顺便一提,kernel/msm-3.18/drivers/hid/是人机接口设备


内核启动的过程跟上述描述还有相当一段距离,不过,要知道内核启动是从start_kernel开始的。

kernel/msm-3.18/include/linux/start_kernel.h
kernel/msm-3.18/init/main.c
调用是从汇编代码kernel/msm-3.18/arch/arm/kernel/head-common.S中发起的
init bin对应的源代码位于system/core/init/init.cpp,调用则是从上述main.c中中发起的。