Android驱动框架整理之KERNEL框架

益承颜
2023-12-01


继上一篇uboot整理后,继续整理下kernel的框架

一、文件系统

IMX8QXP/vendor/nxp-opensource/kernel_imx$ ls
android                            build.config.arm                  build.config.gki_kasan.aarch64    build.config.x86_64  init             Makefile   sound
arch                               build.config.common               build.config.gki_kasan.x86_64     certs                ipc              mm         tools
block                              build.config.db845c               build.config.gki_kprobes          COPYING              Kbuild           net        usr
build.config.aarch64               build.config.gki                  build.config.gki_kprobes.aarch64  CREDITS              Kconfig          OWNERS     virt
build.config.allmodconfig          build.config.gki.aarch64          build.config.gki_kprobes.x86_64   crypto               kernel           README
build.config.allmodconfig.aarch64  build.config.gki.aarch64.fips140  build.config.gki.x86_64           Documentation        lib              README.md
build.config.allmodconfig.arm      build.config.gki-debug.aarch64    build.config.hikey960             drivers              LICENSES         samples
build.config.allmodconfig.x86_64   build.config.gki-debug.x86_64     build.config.imx                  fs                   MAINTAINERS      scripts
build.config.amlogic               build.config.gki_kasan            build.config.khwasan              include              MAINTAINERS.NXP  security

这些带有build的相关目录我没有过研究,有兴趣的可以自己去看看。

1.1 dts配置

我们比较关注的是arch/目录下的arm64的源码:
相关的dts目录:

arch/arm64/boot/dts/freescale/*dts

可以在对应的目录进行dts的添加编译或者删除编译

arch/arm64/boot/dts/freescale/Makefile

一般android指定对应的dts文件在device目录下进行指定:

目录: device/nxp/imx8q/mek_8q/BoardConfig.mk

# For Android Auto with M4 EVS, fstab entries in dtb are in the form of non-dynamic partition by default
# For Android Auto without M4 EVS, fstab entries in dtb are in the form of dynamic partition by default
# For standard Android, the form of fstab entries in dtb depend on the value of "TARGET_USE_DYNAMIC_PARTITIONS"
ifeq ($(PRODUCT_IMX_CAR),true)
  ifeq ($(PRODUCT_IMX_CAR_M4),true)
    ifeq ($(IMX_NO_PRODUCT_PARTITION),true)
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car-no-product.dtb
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-car-no-product.dtb
    else
      ifeq ($(IMX8QM_A72_BOOT),true)
        # imx8qm auto android, A72 boot
        TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car-a72.dtb
        # imx8qm auto android with multi-display, A72 boot
        TARGET_BOARD_DTS_CONFIG += imx8qm-md:imx8qm-mek-car-md-a72.dtb
        # uncomment below line to build dtbo supporting multiple pcm device
        # TARGET_BOARD_DTS_CONFIG += imx8qm-esai:imx8qm-mek-car-esai.dtb
      else
        # imx8qm auto android
        TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car.dtb
        # imx8qm auto android with multi-display
        TARGET_BOARD_DTS_CONFIG += imx8qm-md:imx8qm-mek-car-md.dtb
      endif
      # imx8qm auto android virtualization
      TARGET_BOARD_DTS_CONFIG += imx8qm-xen:imx8qm-mek-domu-car.dtb
      # imx8qxp auto android
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-car.dtb
    endif # IMX_NO_PRODUCT_PARTITION
  else #PRODUCT_IMX_CAR_M4
    ifeq ($(IMX_NO_PRODUCT_PARTITION),true)
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car2-no-product.dtb
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-car2-no-product.dtb
    else
      ifeq ($(IMX8QM_A72_BOOT),true)
        # imx8qm auto android without m4 image, A72 boot
        TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car2-a72.dtb
        # imx8qm auto android without m4 image for multi-display, A72 boot
        TARGET_BOARD_DTS_CONFIG += imx8qm-md:imx8qm-mek-car2-md-a72.dtb
        # uncomment below line to build dtbo supporting multiple pcm device
        # TARGET_BOARD_DTS_CONFIG += imx8qm-esai:imx8qm-mek-car2-esai.dtb
      else
        # imx8qm auto android without m4 image
        TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-car2.dtb
        # imx8qm auto android without m4 image for multi-display
        TARGET_BOARD_DTS_CONFIG += imx8qm-md:imx8qm-mek-car2-md.dtb
      endif
      # imx8qxp auto android without m4 image
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-car2.dtb
      # imx8qm auto android without m4 image in xen
      TARGET_BOARD_DTS_CONFIG += imx8qm-xen:imx8qm-mek-car2-domu.dtb
    endif #IMX_NO_PRODUCT_PARTITION
  endif #PRODUCT_IMX_CAR_M4
else
  ifeq ($(TARGET_USE_DYNAMIC_PARTITIONS),true)
    ifeq ($(IMX_NO_PRODUCT_PARTITION),true)
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-ov5640-no-product.dtb
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-ov5640-rpmsg-no-product.dtb
    else
      # imx8qm standard android; MIPI-HDMI display
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-ov5640.dtb
      # imx8qm standard android; MIPI panel display
      TARGET_BOARD_DTS_CONFIG += imx8qm-mipi-panel:imx8qm-mek-dsi-rm67191.dtb
      # imx8qm standard android; HDMI display
      TARGET_BOARD_DTS_CONFIG += imx8qm-hdmi:imx8qm-mek-hdmi.dtb
      # imx8qm standard android; HDMI and HDMI RX
      TARGET_BOARD_DTS_CONFIG += imx8qm-hdmi-rx:imx8qm-mek-hdmi-rx.dtb
      # imx8qm standard android; Multiple display
      TARGET_BOARD_DTS_CONFIG += imx8qm-md:imx8qm-mek-md.dtb
      # imx8qm standard android; LVDS1 panel display
      TARGET_BOARD_DTS_CONFIG += imx8qm-lvds1-panel:imx8qm-mek-jdi-wuxga-lvds1-panel.dtb
      # imx8qxp standard android; MIPI-HDMI display
		/*这里就是我自己指定的dtb,将原来的dtb修改为自己在kernel中指定的dtb*/
      TARGET_BOARD_DTS_CONFIG += imx8qxp:vt-imx8qxp-m08-a.dtb
      TARGET_BOARD_DTS_CONFIG += imx8dx:imx8dx-mek-ov5640.dtb
      # imx8qxp standard android; LVDS panel display
      TARGET_BOARD_DTS_CONFIG += imx8qxp-lvds0-panel:imx8qxp-mek-jdi-wuxga-lvds0-panel-rpmsg.dtb
    endif #IMX_NO_PRODUCT_PARTITION
  else
    ifeq ($(IMX_NO_PRODUCT_PARTITION),true)
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-ov5640-no-product-no-dynamic_partition.dtb
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-ov5640-rpmsg-no-product-no-dynamic_partition.dtb
    else
      TARGET_BOARD_DTS_CONFIG := imx8qm:imx8qm-mek-ov5640-no-dynamic_partition.dtb
      TARGET_BOARD_DTS_CONFIG += imx8qxp:imx8qxp-mek-ov5640-rpmsg-no-dynamic_partition.dtb
    endif
  endif
endif #PRODUCT_IMX_CAR
/*这里面有很多定义的dtb,你需要判断对应的宏找到对应的dtb,或者去除判断直接添加对应的dtb*/

如何查看在自己编译的dts内容,每个dts编译完成后都会生成对应的dtb文件,同时还会生成对应的tmp的一个隐藏文件,在对应的out目录下(nxp的目录如下):

out/target/product/mek_8q/obj/KERNEL_OBJ/arch/arm64/boot/dts/freescale$ ls .vt-imx8qxp-m08-a.dtb.dts.tmp 
.vt-imx8qxp-m08-a.dtb.dts.tmp
cluo@cluo:/sd2/VT-MX8QXP-M08-A/

可以看到我们指定的dts会有这个隐藏文件产生,然后我们可以进去查看,这个tmp文件会把所有的dts内容都编译进去,包括你头文件定义的dts,你可以在这里面查看你自己的修改是否有效或者正确。

1.2 defconfig文件

如果没有自己添加工程,那么在anroid的源码目录下会有默认的deconfig文件
目录

arch/arm64/configs/*defconfig

同样的在device目录下会有指定的路径:
当然首先是你自己的device目录需要找正确,我们可以自己添加device目录下的文件以便后期的项目分明,但是在初始的时候,我们可以自己选择对应的Lunch进行编译

device/nxp/imx8q/mek_8q$ grep "TARGET_KERNEL_DEFCONFIG" . -r 
./UbootKernelBoardConfig.mk:    TARGET_KERNEL_DEFCONFIG := imx_v8_android_car_defconfig
./UbootKernelBoardConfig.mk:    TARGET_KERNEL_DEFCONFIG := imx_v8_android_car2_defconfig
./UbootKernelBoardConfig.mk:  TARGET_KERNEL_DEFCONFIG := imx_v8_android_defconfig

这里宏会指定对应的目标 deconfig 文件,我们打开这个UbootKernelBoardConfig文件

ifeq ($(PRODUCT_IMX_CAR),true)
  ifeq ($(PRODUCT_IMX_CAR_M4),true)
    TARGET_KERNEL_DEFCONFIG := imx_v8_android_car_defconfig
  else
    TARGET_KERNEL_DEFCONFIG := imx_v8_android_car2_defconfig
  endif # PRODUCT_IMX_CAR_M4
  TARGET_KERNEL_ADDITION_DEFCONF := automotive_addition_defconfig
else
  TARGET_KERNEL_DEFCONFIG := imx_v8_android_defconfig
  TARGET_KERNEL_ADDITION_DEFCONF := android_addition_defconfig
endif # PRODUCT_IMX_CAR

在这里面也是通过判断去走到对应的defconfig文件。
这样我们在配置一个项目后。就可以明白android是怎么去配置对应的dts的,我们自己添加项目也不会那么迷茫。

二、驱动分类

  1. Android Binder
    目录:
kernel_imx/drivers/android/binder.c
  1. 充电相关:电量计、充电管理芯片
    目录:
kernel_imx/drivers/power/supply
  1. 音频:
    基于ALSA框架的,NXP的tinymix工具好像是放在hardware的相关目录下的
    目录:
/*codec编解码相关的*/
sound/soc/codecs   
/*外设端*/
sound/doc/fsl
  1. USB
    一个基于标准Linux USB gadget驱动框架的设备驱动,Android的USB驱动是基于gaeget框架
    目录:
drivers/usb/gadget/

还有很多驱动,可以自己去看看,太多了没办法一一介绍。

kernel_imx/drivers$ ls
accessibility  cdrom        dio       gpu         iio           mailbox   mtd     oprofile  pps         sbus       target       video
acpi           char         dma       greybus     infiniband    Makefile  mux     parisc    ps3         scsi       tc           virt
amba           clk          dma-buf   hid         input         mcb       mxc     parport   ptp         sfi        tee          virtio
android        clocksource  edac      hsi         interconnect  md        net     pci       pwm         sh         thermal      visorbus
ata            connector    eisa      hv          iommu         media     nfc     pcmcia    rapidio     siox       thunderbolt  vlynq
atm            counter      extcon    hwmon       ipack         memory    ntb     perf      ras         slimbus    trusty       vme
auxdisplay     cpufreq      firewire  hwspinlock  irqchip       memstick  nubus   phy       regulator   soc        tty          w1
base           cpuidle      firmware  hwtracing   isdn          message   nvdimm  pinctrl   remoteproc  soundwire  uio          watchdog
bcma           crypto       fpga      i2c         Kconfig       mfd       nvme    platform  reset       spi        usb          xen
block          dax          fsi       i3c         leds          misc      nvmem   pnp       rpmsg       spmi       vdpa         zorro
bluetooth      dca          gnss      ide         lightnvm      mmc       of      power     rtc         ssb        vfio
bus            devfreq      gpio      idle        macintosh     most      opp     powercap  s390        staging    vhost

三、Makefile和Konfig还有defconfig文件关系

Makefile文件

obj-y               += isl29020.o
obj-m               += isl29020.o
obj-n               += isl29020.o

我们可以通过这三种方式直接将需要的文件编译到内核中去,编译成模块,或者不编译名这样我们也不需要其余的Kconfig和defconfig文件

Kconfig文件
Kconfig文件是为了配合Makefile文件的

Makefile中标准的内核采用这种方式定义

obj-$(CONFIG_ISL29020)      += isl29020.o

这样的定义无法让内核知道我们要将对应的驱动编译成什么文件,所以我们需要Kconfig的来控制对应的编译
Kconfig中我们这样定义:

config ISL29020
    tristate "Intersil ISL29020 ambient light sensor"
    depends on I2C
    # 我们可以这样去定义编译成什么
    # default y
    # default m
    # default n
    help
      If you say yes here you get support for the Intersil ISL29020
      ambient light sensor.
      This driver can also be built as a module.  If so, the module
      will be called isl29020.

内核中为了标准,不会在Kconfig中去定义 default y他的编译模式,而是在defconfig中去指定

deconfig中指定

CONFIG_ISL29020=y
# CONFIG_ISL29020=m
# CONFIG_ISL29020=n

所以defconfig,Kconfig, Makefile这三个文件是层层包含,即使没有Kconfig和defconfig也可以对内核进行编译。后来为了标准所以添加Kcongfig和defconfig。

四、d

 类似资料: