# [i.MX 8M PLUS EVK ](https://www.nxp.com/docs/en/user-guide/ANDROID_USERS_GUIDE.pdf)(Android 13) [TOC] ## Building the Android Platform for iMX8 The figure below shows the different components of the [i.MX 8M Plus EVK board](https://www.nxp.com/docs/en/quick-reference-guide/8MPLUSEVKQSG.pdf). ![](https://hackmd.io/_uploads/SknBjzWlp.png) ![](https://hackmd.io/_uploads/HkoFszbxp.png) ![](https://hackmd.io/_uploads/r1aIwQ-e6.jpg) ### open debug console 接白色那邊條線到板子上的debug孔,開啟裝置管理員可以看到serial port 有4個,選擇com32。 open terminal com32 BaudRate = 115200 ### Getting iMX Android release source code [官方網站](https://www.nxp.com/design/software/embedded-software/i-mx-software/android-os-for-i-mx-applications-processors:IMXANDROID) [Source code](https://www.nxp.com/webapp/sps/download/preDownload.jsp) NXP iMX public source code, which is maintained in the [GitHub repository](https://github.com/nxp-imx). * To generate the iMX Android release source code build environment, execute the following commands: ```clike mkdir ~/bin curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo #開權限777 chmod a+x ~/bin/repo #在imx-android-13.0.0_2.0.0資料夾內export export PATH=${PATH}:~/bin #這邊就會開始下載檔案 source imx_android_setup.sh # ${MY_ANDROID} will be refered as the iMX Android source code root directory in all i.MX Andorid release documentation. export MY_ANDROID=`pwd` ``` ### Building Android images The Android image can be built after the source code has been downloaded. This section provides an overview of how to use Android build system and what NXP did on it. Then it provides an example of how to build Android images for a specific board as well as preparation steps. Customers could follow these steps to do the preparation work and build the images. * First, the `source build/envsetup.sh` command is executed to import shell functions * Then, the `lunch <ProductName-BuildMode>` command is executed to set up the build configuration. ```cmake source build/envsetup.sh #for my i.mx8 plus evk. Based on follow tables, choose your board and build mode lunch evk_8mp-userdebug ``` ![](https://hackmd.io/_uploads/Byl00g3J6.png) ![](https://hackmd.io/_uploads/SJ3CAgnk6.png) But ! iMX Android platform needs some preparation for the first time when building the images. The image build steps are as follows: * Prepare the build environment for U-Boot and Linux kernel. * This step is mandatory because there is no GCC cross-compile tool chain in the one in AOSP codebase. * An approach is provided to use the self-installed GCC cross-compile tool chain. download Gcc cross-compile from [Arm Developer](https://developer.arm.com/downloads/-/gnu-a) and I choose gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz ```clike #in android_build dir tar Jxvf gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu.tar.xz mv gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu opt/ export AARCH64_GCC_CROSS_COMPILE=~/ssd_4/imx-android-13.0.0_2.0.0/opt/gcc-arm-9.2-2019.12-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- ``` :::danger 注意路徑,要用絕對路徑 ::: * Follow the steps below to set the external clang and kernel-build-tools tools for kernel building. ```clike #in android_build dir git clone https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86 mv linux-x86 opt/ cd opt/linux-x86 git checkout d20e409261d6ad80a0c29ac2055bf5c3bb996ef4 #回到android_build cd .. export CLANG_PATH=~/ssd_4/imx-android-13.0.0_2.0.0/opt/linux-x86 git clone https://android.googlesource.com/kernel/prebuilts/buildtools/ mv linux-x86 opt/build-tools cd opt/build-tools git checkout e3f6a8c059b94f30f7184a7d335876f8a13a2366 #回到android_build cd .. export PATH=~/ssd_4/imx-android-13.0.0_2.0.0/opt/build-tools/linux-x86/bin:$PATH ``` :::danger 注意路徑,要用絕對路徑 ::: 這樣就設定好Cross-compile和環境變數接著就可以開始編譯 ```clike # in android_build source build/envsetup.sh lunch evk_8mp-userdebug # -j based on your computer or sever cpu number ./imx-make.sh -j4 2>&1 | tee build-log.txt ``` 2>&1 can [ref](https://mks.tw/2928/%E5%AD%B8%E7%BF%92%E7%AD%86%E8%A8%98-linux-command-%E3%80%8C21%E3%80%8D-%E8%BC%95%E9%AC%86%E8%AB%87) command `tee` can ouput build log The commands below can achieve the same result: ```clike ./imx-make.sh bootloader kernel -j4 2>&1 | tee build-log.txt make -j4 2>&1 | tee -a build-log.txt ``` 到這邊就可以去喝杯咖啡吃下午茶了,根據cpu number會編譯不同時間,我用16顆邊大概編譯3-4小時,不過有同時再做其他事情。 :::success 如果是使用ssh連到sever的話可以使用 [screen](https://blog.gtwang.org/linux/screen-command-examples-to-manage-linux-terminals/) or [tmux](https://blog.gtwang.org/linux/linux-tmux-terminal-multiplexer-tutorial/) ,這樣就算關掉ssh也可以繼續使用 ::: ### 編譯完後會產生的檔案 The following outputs are generated by default in `$android_build/out/target/product/evk_8mp`: * root/: Root file system. It is used to generate system.img together with files in system/. * system/: Android system binary/libraries. It is used to generate system.img together with files in root/. * recovery/: Root file system, integrated into vendor_boot.img as a part of the RAMDisk and used by the Linux kernel when the system boots up. * 「救援模式」時使用的映像檔 * vendor_ramdisk/: Integrated into vendor_boot.img as part of the RAMDisk and used by the Linux kernel when the system boots up. * ramdisk/: Integrated into boot image as part of the RAMDisk and used by linux kernel when system boot up. * dtbo-imx8mp.img: Board's device tree binary. It is used to support MIPI-to-HDMI output on the iMX 8M Puls EVK LPDDR4 board. * 一個小型的檔案系統, 是 Android 系統啟動的關鍵 * vbmeta-imx8mp.img: Android Verify boot metadata image for dtbo-imx8mp.img. * system.img: EXT4 image generated from system/ and root/. * Android 的, framework 也在這裡, 將被掛載到 /system 目錄下 * product.img: EXT4 image generated from product/. * partition-table.img: GPT partition table image for single-bootloader condition. Used for 16 GB SD card and eMMC. * u-boot-imx8mp.imx: U-Boot image without Trusty OS integrated for iMX 8M Puls EVK LPDDR4 board. * spl-imx8mp-dual.bin: SPL image without Trusty related configuration for iMX 8M Plus EVK with LPDDR4 on board. * bootloader-imx8mp-dual.img: Bootloader image without Trusty OS integrated for iMX 8M Plus EVK with LPDDR4 on board. * imx8mp_mcu_demo.img: MCU FreeRTOS image to support audio playback on MCU side. * vendor.img: Vendor image, which holds platform binaries. Mounted at /vendor. * super.img: Super image, which is generated with system.img, system_ext.img, vendor.img, vendor_dlkm.img, and product.img. * boot.img: A composite image, which includes the AOSP generic kernel Image and boot parameters. * vendor_boot.img: A composite image, which includes vendor RAMDisk and boot parameters. * rpmb_key_test.bin: Prebuilt test RPMB key. Can be used to set the RPMB key as fixed 32 bytes 0x00. ### Building U-Boot images The U-Boot images can be generated separately. For example, you can generate a U-Boot image for iMX 8M Plus EVK as follows: ```clike $ cd android_build $ source build/envsetup.sh $ lunch evk_8mp-userdebug $ ./imx-make.sh bootloader -j4 ``` 為了可靠地生成U-Boot映射,bootloader image的大小可能大於相應的分區大小,特別是對於單個引導加載程式配寘。 您可以使用`USE_TEE_COMPRESS=true`構建影像來壓縮TEE影像。 例如,執行以下命令來壓縮TEE影像,並生成較小大小的U-Boot影像。 ```clike USE_TEE_COMPRESS=true ./imx-make.sh bootloader -j4 ``` The following table lists the U-Boot configurations and images for iMX 8M Mini EVK(same as 8M plus) ![](https://hackmd.io/_uploads/H19lXpaJ6.png) ![](https://hackmd.io/_uploads/rkZ-Xa6kT.png) ### Building a kernel image Kernel image is automatically built when building the Android root file system. The following are the default Android build commands to build the kernel image: ```clike $cd android_build $ source build/envsetup.sh $ lunch evk_8mp-userdebug $ ./imx-make.sh kernel -c -j4 ``` ### Building boot.img & dtbo.img * The following commands are used to generate boot.img under Android environment: ```clike $source build/envsetup.sh $ lunch evk_8mp-userdebug $ ./imx-make.sh bootimage -j4 ``` The commands below can achieve the same result: ```clike $ source build/envsetup.sh $ lunch evk_8mp-userdebug $ ./imx-make.sh kernel -j4 $ make bootimage -j4 ``` * DTBO image holds the device tree binary of the board. * The following commands are used to generate dtbo.img under Android environment: ```clike $ source build/envsetup.sh $ lunch evk_8mp-userdebug $ ./imx-make.sh dtboimage -j4 ``` The commands below can achieve the same result: ```clike $ source build/envsetup.sh $ lunch evk_8mm-userdebug $ ./imx-make.sh kernel -j4 $ make dtboimage -j4 ``` #### Ref [理解Android編譯命令- Gityuan博客](http://gityuan.com/2016/03/19/android-build/) ## Running the Android Platform with a Prebuilt Image The following tables list the detailed contents of the android-13.0.0_2.0.0_image_8mpevk.tar.gz image package. [Download NXP Android BSP Image](https://www.nxp.com/design/software/embedded-software/i-mx-software/android-os-for-i-mx-applications-processors:IMXANDROID) [Prebuilt-image](https://www.nxp.com/webapp/sps/download/preDownload.jsp) * The following download methods can be used to write the Android System Image: * UUU to download all images to the eMMC or SD card. * `imx-sdcard-partition.sh` to download all images to the SD card. * fastboot_imx_flashall script to download all images to the eMMC or SD storage. ### Downloading images with UUU UUU can be used to download all images into a target device. It is a quick and easy tool for downloading images. See the [Android Quick Start Guide (AQSUG)](https://www.nxp.com/docs/en/quick-reference-guide/ANDROID_QUICK_START_GUIDE.pdf) for detailed description of UUU. * The board image files can be flashed into the target board using Universal Update Utility (UUU). * For the UUU binary file, download it from GitHub: [uuu release page on GitHub](https://github.com/nxp-imx/mfgtools/releases) * NXP 8MPLUS的UUU是使用1.4.182,所以要下載[1.4.182版](https://github.com/nxp-imx/mfgtools/releases/tag/uuu_1.4.182) * This script is validated with uuu 1.4.182 version, it is recommended to align with this version. * For Linux OS, download the file named uuu * For Windows OS, download the file named uuu.exe :::success Because the two script files will directly invoke UUU, make sure that UUU is in a path contained by the system environment variable of "PATH" 因為是在windows下燒錄,所以uuu要放在windows系統下,所以要把建立uuu.exe的PATH。[Ref](https://emteria.com/kb/uuu-windows) 但其實不用這麼麻煩,只要放在C:\Windows\System32就好。這個目錄已經有被include了。 另外順便下載Android Studio網頁上的SDK Platform Tools [download](https://developer.android.com/studio/releases/platform-tools?hl=zh-tw),下載完後把adb.exe和fastboot.exe也放到C:\Windows\System32,再把3個dll檔放入C:\Windows\SysWOW64,即可在windows下使用adb和fastboot工具。 ::: :::success windows cmd line使用技巧 切換資料夾`cd` , 列出資料夾 `dir` 切換硬碟 `Z:` or `cd Z:` [解決不能切換到網路磁碟機](https://hackmd.io/@Boyan/H1EQeMeeT) ::: * To achieve more flexibility, two script files are provided to invoke UUU to automatically flash all Android images. * 在imx-android-13.0.0_2.0.0\android_build\out\target\product\evk_8mp裡 * uuu_imx_android_flash.sh for Linux OS * uuu_imx_android_flash.bat for Windows OS,編譯在linux編譯,燒錄是使用windows,所以要在windows cmd(系統管理員模式)執行.bat檔。 * Make the board enter serial download mode * Change the board's SW4 (boot mode) to 0001 (from 1-4 bit) to enter serial download mode. * Power on the board. * Use the USB cable to connect the USB 3.0 dual-role port (with silkprint "PORT1") on the board to your host PC. * Execute the uuu_imx_android_flash tool to flash images. The `uuu_imx_android_flash` tool can be executed with options to get help information and specify the images to be flashed. For iMX 8M Plus board, related options are described as follows. | Option | Description | | -------- | -------- | |-h |Displays help information of this tool. | |-f soc_name |Specifies SoC information. For iMX 8M Plus EVK, it should be imx8mp. This option is mandatory. | |-a|Only flashes slot a. If this option and -b option are not used, slots a and b are both flashed.| |-b|Only flashes slot b. If this option and -a option are not used, slots a and b are both flashed.| |-c card_size|Specifies which partition table image file to flash. For iMX 8M Plus EVK, it can be followed with "28". If this option is not used, default `partition-table.img` or `partition-table-dual.img` is flashed.| |-m|Flashes the MCU image. If this option is not used, the MCU image is not flashed.| |-u uboot_feature|Flashes U-Boot or SPL&Bootloader image with uboot_feature in their names. For iMX 8M Plus EVK board, it can be dual, trusty-dual, trusty-secure-unlockdual. If this option is not used, the default `u-boot-imx8mp.imx` is flashed.| |-e |Erases the user data after images are flashed.| |-D directory|Specifies the directory in which there are the images to be flashed. For `uuu_imx_android_flash.bat`, it must be followed with an absolute path. If this option is not used, images in the current working directory are flashed. |-d dtb_feature|Flashes DTBO and vbmeta images with `dtb_feature` in their names. Note: -m should be used together with -d rpmsg-revb4. * On Windows system, open the command-line interface in administrator mode. The corresponding command is as follows: ``` uuu_imx_android_flash.bat -f imx8mp -a -e -d revb4 -u trusty-dual ``` When the command above is executed, spl-imx8mp-trusty-dual.bin is flashed, bootloaderimx8mp-trusty-dual.img with other default images are flashed into eMMC slot a for iMX 8M Plus EVK. ### Downloading a single image with fastboot UUU can be used to flash the Android system image into the board, but it needs to make the board enter serial down mode first, and make the board enter boot mode once flashing is finished. * A new fastboot_imx_flashall script is supported to use fastboot to flash the Android system image into the board. It is more flexible. To use the new script, the board must be able to enter fastboot mode and the device must be unlocked. The table below lists the fastboot_imx_flashall scripts. * 簡單來說就是uuu要切換到download模式,fastboot不需要 fastboot_imx_flashall script ```clike fastboot_imx_flashall.sh #for Linux fastboot_imx_flashall.bat #for windows ``` * 正統作法是在`android_build` 輸入`make -j4 fastboot` 然後在 * Linux version binary file: ${MY_ANDROID}/out/host/linux-x86/bin * Windows version binary file: ${MY_ANDROID}/out/host/windows-x86/bin * 上面2個路徑找到fastboot檔案,但是在上面就有fastboot了,所以可以不使用。 The way to use these scripts is follows: ```clike fastboot_imx_flashall.sh <option> #for Linux fastboot_imx_flashall.bat <option> #for Windows fastboot_imx_flashall.bat -f imx8mp -a -e -u trusty-dual ----------------------------------------------------------- options Options: -h Displays this help message -f soc_name Flashes the Android image file with soc_name -a Only flashes the image to slot_a -b Only flashes the image to slot_b -c card_size Optional setting: 7 / 14 / 28 If it is not set, use partition-table.img (default). If it is set to 7, use partition-table-7GB.img for 8 GB SD card. If it is set to 14, use partition-table-14GB.img for 16 GB SD card. If it is set to 28, use partition-table-28GB.img for 32 GB SD card. Make sure that the corresponding file exists on your platform. -m Flashes the MCU image. -u uboot_feature Flashes U-Boot or spl&bootloader images with "uboot_feature" in their names For Standard Android: If the parameter after "-u" option contains the string of "dual", the spl&bootloader image is flashed; Otherwise U-Boot image is flashed. For Android Automative: Only dual-bootloader feature is supported. By default, spl&bootloader image is flashed. -d dtb_feature Flashes dtbo, vbmeta and recovery image file with "dtb_feature" in their names If not set, use default dtbo, vbmeta and recovery image -e Erases user data after all image files are flashed. -l Locks the device after all image files are flashed. -D directory Directory of images. If this script is execute in the directory of the images, it does not need to use this option. -s ser_num Serial number of the board. If only one board connected to computer, it does not need to use this option ``` E.g. ```clike fastboot_imx_flashall.bat -f imx8mp -a -e -u trusty-dual bootloader-imx8mm-trustydual.img. ``` Options explanation: -f imx8mp: Flashes images for i.MX 8M Plus EVK Board.(mandatory) -a: Only flashes slot a. -e: Erases user data after all image files are flashed. -u trusty-dual: `Flashes spl-imx8mm-trusty-dual.bin` and `bootloader-imx8mm-trustydual.img`. #### Downloading a single image with fastboot Sometimes only a single image needs to be flashed again with fastboot for debug purpose. U-Boot & userspace fastboot 能辨識的 partition如下: ![](https://hackmd.io/_uploads/Skvx6IZg6.png) * To enter U-Boot fastboot mode, for example, make the board enter U-Boot command mode, and execute the following command on the console: 簡單來說版端在開機時狂按esc進去U-boot模式 ``` fastboot 0 ``` * To enter userspace fastboot mode, two commands are provided as follows for different conditions. You may need root permission on windows OS: 編譯出來的檔案會在`out/target/product/evk_8mp`,cmd切換到此路徑,假設編譯`bootimage`,執行下面命令進行partical update。 ```clike fastboot flash boot_a boot.img ``` ![](https://hackmd.io/_uploads/rJSrQoDep.png) ### Booting After downloading the images, you can boot the board by connecting it to the power supply. * Booting with single display: HDMI /MIPI-to-HDMI/MIPI panel/LVDS panel/dual channel LVDS to HDMI or multiple displays * In the U-Boot prompt, set the U-Boot environment variables as follows: ```clike U-Boot > $ setenv bootargs console=ttymxc1,115200 earlycon=ec_imx6q,0x30890000,115200 init=/init cma=1184M@0x400M-0x1000M androidboot.primary_display=imx-drm firmware_class.path=/vendor/firmware loop.max_part=7 transparent_hugepage=never moal.mod_para=wifi_mod_para.conf androidboot.lcd_density=240 swiotlb=65536 bootconfig U-Boot >$ saveenv ``` :::info 進U-Boot方法: 開機看log,會有按任意鍵停止開機,只要就可以了。 `Hit any key to stop autoboot: 0` 或是開機狂按esc ::: The following tables list the boot switch settings to control the boot storage. ![](https://hackmd.io/_uploads/Bk-mC8-ea.png) ### DM-verity configuration Disabling DM-verity provides convenience for developers, but the device is unprotected. To disable DM-verity, perform the following steps: * Unlock the device. * Boot up the device. * Choose Settings -> Developer Options -> OEM Unlocking to enable OEM unlocking. * Execute the following command on the target side to make the board enter fastboot mode: `reboot bootloader` * Unlock the device. Execute the following command on the host side:`fastboot oem unlock` * Wait until the unlock process is complete. * Disable DM-verity. * Boot up the device. * Disable the DM-verity feature. Execute the following command on the host side: ``` adb root adb disable-verity adb reboot ``` ## Android使用技巧 [Ref](https://shengyu7697.github.io/android-tutorial/) 在windows OS上開啟cmd(不確定要不要系統管理員模式),切換到下載好的platform-tools資料夾位置`C:\Users\wuboyan\Desktop\platform-tools`。 但是照理來說我有把platform的位置加入環境變數,應該是不用特別切換過來直接打adb就可以使用,但是會找不到 ![](https://hackmd.io/_uploads/SkGIejMgT.png) 只能先切換過去執行指令(看起來是任意指令),就能夠開啟adb功能 ![](https://hackmd.io/_uploads/BJ2CxszlT.png) 也可以在剛剛的cmd視窗使用 ![](https://hackmd.io/_uploads/B1Qubsfe6.png) [Android-adb-logcat 用法](https://shengyu7697.github.io/android-adb-logcat/) 重點: Windows 下要使用logcat搭配指令找關鍵字,請用 findstr ![](https://hackmd.io/_uploads/S1tZrhGxT.png) * 更簡單的方式是使用cmder,[官方網站](https://cmder.app/) * 使用cmder就可以在windows的cmd使用linux的指令 [Ref](https://blog.miniasp.com/post/2015/09/27/Useful-tool-Cmder) ### adb 指令 * adb devices * 可以看到可使用的devices * adb shell * 進入裝置裡的 shell 模式 * adb start-server/adb kill-server * 啟動 adb daemon/終止 adb daemon * adb root * 取得 root 權限 ![](https://hackmd.io/_uploads/SyRM1sDxT.png) * adb reboot * 重開機 * adb reboot bootloader * 重開機且進bootloader模式 * adb reboot fastboot * 重新機,進入 fastboot 模式 * adb pull * 拉檔案或目錄出來 * adb push * 推檔案或目錄進去 * adb install apk * 安裝 apk,當已經安裝過舊版本的程式時,可以使用 `-r` 去覆蓋。 * adb logcat * 印出系統log日誌訊息 * adb remount * 有 root 權限後,可用此指令將系統重新掛載成 R/W 模式,將可對 /system 內的檔案做修改 ### 安裝busybox Android shell 裡預設沒有 vi 指令的工具, Android 系統去除了標準 Linux 的大多數工具,導致我們 Android 開發上與除錯時特別麻煩, 如果你的 android device 有 root 權限的話,可以把編譯好的 busybox 推進去使用, 開發上會方便許多, 而且會節省很多時間。 * busybox binaries 可以從[官方網站下載](https://busybox.net/downloads/binaries/) 可以查看你的 Android CPU 架構然後下載對應的 busybox binary。 * imx8M plus的CPU是Arm® Cortex®-A53 可得知是arm架構 * 可以下載busybox-armv7r,在1.28.1-defconfig-multiarch中,直接進去網址會亂碼,在linux使用wget下載 ``` wget https://busybox.net/downloads/binaries/1.28.1-defconfig-multiarch/busybox-armv7r ``` 安裝前確認 Android 裡有無 /system/xbin 目錄, 本範例是把 busybox 安裝到 /system/xbin 下 ```clike adb root adb remount adb push busybox-armv7r /system/xbin/busybox adb shell 'chmod 755 /system/xbin/busybox' adb shell '/system/xbin/busybox --install /system/xbin/' ``` 接下來就可以在 adb shell 裡使用 vi ,find, grep, tee, sed, wget。 ## Android 啟動過程 - init process [Ref from kyle shanks](https://hackmd.io/pJpAeKAeRea0VIW3oI-mXw?view) 裡面講到的Ref : [SELinux](https://linux.vbird.org/linux_server/rocky9/0140selinux.php) 、[binder通訊](https://zhuanlan.zhihu.com/p/35519585) [Android系統啟動](https://segmentfault.com/a/1190000023184321) ### 啟動 Android 的第一個啟動進程,init 的 PID 為 1,這個進程會 解析 init.rc 來建構出系統的初始運作型態,其他的系統才會相繼啟動,可使用`adb shell ps -A`查看 1. 啟動電源 & 系統啟動 當電源啟動後,會從預定的地方 (PC 讀取 ROM),開始加載程序(BootLoader)到 RAM 中,並開始執行 2. 引導程序 BootLoader 引導程序 BootLoader 是在 Android 系統開始運行前的一個小程序,主要功能是把系統 OS 拉起並運行 * Loader 分為兩個部分 [Android 引導程式](https://android.googlesource.com/platform/bootable/bootloader/legacy/+/refs/heads/ics-mr0-release/usbloader/) * 第一階段,檢測外部的 RAM 以及加載第二階段的程式 * `init.s `初始化堆棧,清空 BBS,調用 main() 函數 * 第二階段,設定網路、內存 … 等等 必要功能 * `main.c` 初始化硬體、創建 Linux 標籤 3. Linux 核心啟動 當核心啟動時,設定暫存、保護儲存器、計畫列表、加載驅動… 在核心完成系統設置後,它會 在系統中找 init.rc 文件,並啟動 init process 4. init process啟動 該進程主要是作初始化&啟動系統屬性服務,也用來啟動 Zygote process 5. Launcher App 應用(桌面應用程式) Android啟動流程圖 ![](https://hackmd.io/_uploads/Hy6AT-Fga.png) ### init process * init 作為 Android 系統啟動的第一個進程,通過 解析 init.rc 來陸續啟動關鍵的系統服務進程,其有三個重點服務進程 * ServiceManager (類似 DNS 功能,用來查找 SystemServer 中的服務控制碼) * Zygote (初始進程,加載必要 Anroid resource、啟動虛擬機… 等等) * SystemServer (啟動系統級別服務,像是 AMS、WMS… 服務) * init 進程會啟動 Zygote、SystemServer 兩個進程,而 Zygote 使用 Socket 監聽 AMS、ServiceManager 使用 Binder 通訊 (詳見下圖) * 創建、掛載啟動所需要的文件目錄 * 初始化、啟動性服務 * 解析 init.rc 配置文件並 啟動 Zygote 進程 ![](https://hackmd.io/_uploads/rk1zefYep.png) ## init.rc 解析 [sourcce form kyle shanks ](https://hackmd.io/@AlienHackMd/H1ewiZ5uY) ## 如何寫Android mk Android.mk本質上就是用Makefile寫的設定檔。與普通Makefile不同的是,它相當於Android編譯系統的一個子系統。配置簡單,可讀高 以下以`packages/apps/Settings/Android.mk`(找不到了,但是還是可以參考)的內容為例,說明Android.mk的設定方式。這是系統設定的原始碼,在系統應用上具有一定的代表性。 ```clike LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_JAVA_LIBRARIES := bouncycastle conscrypt telephony-common ims-common LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4 android-support-v13 jsr305 LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := \ $(call all-java-files-under, src) \ src/com/android/settings/EventLogTags.logtags LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res LOCAL_PACKAGE_NAME := Settings LOCAL_CERTIFICATE := platform LOCAL_PRIVILEGED_MODULE := true LOCAL_PROGUARD_FLAG_FILES := proguard.flags ifneq ($(INCREMENTAL_BUILDS),) LOCAL_PROGUARD_ENABLED := disabled LOCAL_JACK_ENABLED := incremental endif include frameworks/opt/setupwizard/navigationbar/common.mk include frameworks/opt/setupwizard/library/common.mk include frameworks/base/packages/SettingsLib/common.mk include $(BUILD_PACKAGE) # Use the following include to make our test apk. ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call all-makefiles-under,$(LOCAL_PATH)) endif ``` Android.mk中,可以放置任意多個模組,這裡只有一個模組。對一個模組來說,大致可以分為開頭清理、指定模組變數與呼叫編譯檔案三部分。 ### 一開始清理 ```cpp LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) ``` `include $(CLEAR_VARS)`,其實就是調用`build/core/clear_vars.mk`檔案。這個檔案中,把單模組編譯中,系統可能用到變數全部清理一遍。 `LOCAL_PATH`不是系統支援的模組變量,而是約定俗成的自訂變量,所以可以在呼叫`CLEAR_VARS`前指定。其它自訂變量,不建議使用`LOCAL_`作為前綴,防止和模組變量雷同。 `my-dir`是在`build/core/definitions.mk`定義的函數,透過Android.mk的位置來計算模組的路徑。如果想知道其它的常用函數,可以查看該檔案。 :::info 由於Makefile天生的問題,不支援命名空間。在需要重複使用一組變數時,要麼給每一組變數不同的命名,要麼必須重複初始化。這裡,Android使用的方法就是後者。所以在開始編譯一個新模組之前,必須清理模組變量LOCAL_*,以免受上一模組的干擾。 ::: ### 指定模組變數 對於一個Android模組來說,最重要的是名稱、`AndroidManifest.xml`、原始碼、資源檔案、編譯依賴。 * `LOCAL_MODULE`就是模組名,不能和既有模組相同。如果該變數未設置,則使用`LOCAL_PACKAGE_NAME`。如果再沒有,就會編譯失敗。 * `LOCAL_MANIFEST_FILE`可以指定`AndroidManifest.xml`的位置。如果未設置,則預設使用Android.mk的相同路徑下的`AndroidManifest.xml`檔案。 * `LOCAL_SRC_FILES`是指定來源文件列表。這裡`$(call all-java-files-under, src)`用來指定大部分文件。`all-java-files-under`也是定義在definitions.mk中的函數。 * `LOCAL_RESOURCE_DIR`是指定資源檔案的目錄。 * `LOCAL_JAVA_LIBRARIES`和`LOCAL_STATIC_JAVA_LIBRARIES`,則指定了所依賴的共用與靜態Java模組。 除了這些比較核心的變數以外,還有幾十個其它變數可以按需指定。 ### 呼叫編譯檔 ```clike include $(BUILD_PACKAGE) ``` 呼叫`build/core/package.mk`文件,執行APK的編譯。前面指定的模組變量`LOCAL_*`,都是為這一句而準備。 這些用來給Android.mk調用的檔案及其變量,定義在`build/core/config.mk`中。 ```clike BUILD_COMBOS:= $(BUILD_SYSTEM)/combo CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk BUILD_PHONY_PACKAGE:= $(BUILD_SYSTEM)/phony_package.mk BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk BUILD_NATIVE_TEST := $(BUILD_SYSTEM)/native_test.mk BUILD_NATIVE_BENCHMARK := $(BUILD_SYSTEM)/native_benchmark.mk BUILD_HOST_NATIVE_TEST := $(BUILD_SYSTEM)/host_native_test.mk BUILD_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/shared_test_lib.mk BUILD_HOST_SHARED_TEST_LIBRARY := $(BUILD_SYSTEM)/host_shared_test_lib.mk BUILD_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/static_test_lib.mk BUILD_HOST_STATIC_TEST_LIBRARY := $(BUILD_SYSTEM)/host_static_test_lib.mk BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk ``` 根據以上程式碼,整理相關資訊為以下表格。其中,**加粗**的幾個是自訂模組裡比較常用的變數。說明中的主機是指編譯Android的機器,而設備是指安裝Android的機器。 [Ref](https://note.qidong.name/2017/08/android-mk/) ### 其他 在Settings這個模組的Android.mk中,還有幾個有趣的地方。 * 編譯額外模組 ```clike # Use the following include to make our test apk. ifeq (,$(ONE_SHOT_MAKEFILE)) include $(call all-makefiles-under,$(LOCAL_PATH)) endif ``` 在mm這類單模組編譯的情況下,再額外include目前目錄下的所有其它Androidmk,例如測試APK。 * 增量編譯 ```clike ifneq ($(INCREMENTAL_BUILDS),) LOCAL_PROGUARD_ENABLED := disabled LOCAL_JACK_ENABLED := incremental endif ``` 在增量編譯的情況下,停用混淆、啟用Jack工具鏈的增量編譯功能。 * 引用其它mk檔 ```clike include frameworks/opt/setupwizard/navigationbar/common.mk include frameworks/opt/setupwizard/library/common.mk include frameworks/base/packages/SettingsLib/common.mk ``` 引用這三個文件,目的是增加額外的資源文件、編譯依賴與aapt參數。這是一種比較高明的方式來使用自訂的模組。 ## ASOP目錄結構 完整目錄如下: ![](https://hackmd.io/_uploads/SyliukVba.png) * art : Android Runtime,一種App運行模式,區別於傳統的Dalvik虛擬機,旨在提高Android系統的流暢性 * bionic : 基礎C庫原始碼,Android改造的C/C++庫 * bootable : Android程式啟動導引,適合各種bootloader的通用程式碼,包括一個recovery目錄 * build : 存放系統編譯規則及generic等基礎開發包配置 * cts : Compatibility Test Suite,GMS認證所用到的測試​​套件,GMS全稱為Google Mobile Service,也就是裝置安裝了GMS才可以使用Google提供的服務,例如安裝Google Play,Youtube之類的,只有通過了cts測試套件所有測試項目才能安裝GMS * [解說from csdn](https://blog.csdn.net/hubinbin595959/article/details/77071052) * dalvik : Android Dalvik虛擬機相關內容 * developers : Android開發者參考文檔 * development : Android應用開發基礎架構相關 * device : Android支援的各種裝置及相關配置 * external : Android中使用的外部開源函式庫 * frameworks : 應用程式框架,Android系統核心部分,由Java和C編寫 * hardware : 硬體介面 * kernel : Linux Kernel,不過Android預設不提供,需要單獨下載,只有一個tests目錄 * libcore : Android Java核心類別庫 * libnativehelper : Android動態函式庫,實現JNI函式庫的基礎 * out: 編譯產生的檔案都在這個目錄下,像是jar包,so函式庫,img鏡像等 * packages : 這個也是framework開發經常打交道的目錄,所有Google原生的系統應用和元件都在這個目錄下,例如Launcher,Settings,Input,ScreenSaver等 * pdk : platform develop kit,平台開發元件 * platform_testing : 平台測試程序 * prebuilts : 預編譯相關 * sdk : java層sdk * system : 底層檔案系統函式庫、應用與元件-C語言 * vendor : 各廠商的程式碼 [Android系統原始碼目錄結構詳解](https://juejin.cn/post/7119764025210044423) ### android平台四層架構對應原始碼中的目錄: 第一層:應用程式層(applications)對應根目錄下packages/apps 第二層:應用程式框架層(application framework)對應根目錄下的frameworks 第三層:運行庫層包括運行庫(libraries)和android運行環境(android runtime) 三、四層中間還有個硬體抽象層(HAL)對應根目錄下的hardware 第四層:Linux內核層對應根目錄下的kernel # Android.bp ## 簡介 早期的Android系統都是採用Android.mk的配置來編譯原始碼,從Android 7.0開始引進Android.bp。很明顯Android.bp的出現就是為了替換掉Android.mk。 再來談談Android build系統隨著Android版本對應的發展演變過程: * Android 7.0引進ninja和kati * Android 8.0使用Android.bp來取代Android.mk,引進Soong * Android 9.0強制使用Android.bp 且三者之間不是孤立的,存在轉換關係圖如下: ![](https://hackmd.io/_uploads/Hk4xtzSZ6.png) 透過Kati將Android.mk轉換成ninja格式的文件,透過Blueprint+ Soong將Android.bp轉換成ninja格式的文件,透過androidmk將Android.mk轉換成Android.bp,但針對沒有分支、循環等流程控制的Android.mk才有效。 這裡牽涉到Ninja , kati , Soong , bp概念,接下來分別簡單介紹一下。 * Ninja * ninja是一個編譯框架,會根據對應的ninja格式的設定檔進行編譯,但是ninja檔一般不會手動修改,而是透過將Android.bp檔轉換成ninja格檔來編譯。 * Android.bp * Android.bp的出現就是為了替換Android.mk檔。bp跟mk檔案不同,它是純粹的配置,沒有分支、循環等流程控制,不能做算數邏輯運算。如果需要控制邏輯,那麼只能透過Go語言編寫。 * Soong * Soong類似於先前的Makefile編譯系統的核心,負責提供Android.bp語意解析,並將之轉換成Ninja檔。Soong也會編譯產生一個androidmk指令,用來將Android.mk檔轉換為Android.bp文件,不過這個轉換功能僅限於沒有分支、循環等流程控制的Android.mk才有效。 * Blueprint * Blueprint是產生、解析Android.bp的工具,是Soong的一部分。Soong負責Android編譯而設計的工具,而Blueprint只是解析檔案格式,Soong解析內容的具體意義。Blueprint和Soong都是由Golang寫的項目,從Android 7.0,prebuilts/go/目錄下新增Golang所需的運行環境,編譯時使用。 * Kati * kati是專為Android開發的一個基於Golang和C++的工具,主要功能就是把Android中的Android.mk檔案轉換成Ninja檔案。程式碼路徑是build/kati/,編譯後的產物是ckati。 * Android.bp語法: * 根據設計,Android.bp 檔案很簡單。它們不包含任何條件語句,也不包含控制流語句;所有複雜問題都由用Go 編寫的編譯邏輯處理。 * Android.bp檔案記錄模組訊息,每個模組以模組類型開始,後面跟著一組模組的屬性,以名值對(name: value)表示,每個模組都必須有一個name屬性。 ## Android.bp語法初識 ```cpp cc_library_shared { //編譯成動態函式庫,類似Android.mk中的BUILD_SHARED_LIBRARY name: "libbluetooth_jni", //編譯出的模組的名稱,類似Android.mk中的LOCAL_MODULE srcs: [ //來源文件,類似於Android.mk中的LOCAL_SRC_FILES "com_android_bluetooth_btservice_AdapterService.cpp", "com_android_bluetooth_hfp.cpp", "com_android_bluetooth_hfpclient.cpp", "com_android_bluetooth_a2dp.cpp", "com_android_bluetooth_a2dp_sink.cpp", "com_android_bluetooth_avrcp.cpp", "com_android_bluetooth_avrcp_controller.cpp", "com_android_bluetooth_hid.cpp", "com_android_bluetooth_hidd.cpp", "com_android_bluetooth_hdp.cpp", "com_android_bluetooth_pan.cpp", "com_android_bluetooth_gatt.cpp", "com_android_bluetooth_sdp.cpp", ], include_dirs: [ //使用者指定的頭檔查找路徑,類似於Android.mk中的LOCAL_C_INCLUDES "libnativehelper/include/nativehelper", "system/bt/types", ], shared_libs: [ //編譯所依賴的動態函式庫,類似Android.mk中的LOCAL_SHARED_LIBRARIES "libandroid_runtime", "libchrome", "libnativehelper", "libcutils", "libutils", "liblog", "libhardware", ], static_libs: [ //編譯所依賴的靜態函式庫,類似Android.mk中的LOCAL_STATIC_LIBRARIES "libbluetooth-types", ], cflags: [ ///編譯flag,類似Android.mk中的LOCAL_CFLAGS "-Wall", "-Wextra", "-Wno-unused-parameter", ], } ``` ### modules 從前面的列子可以看出定義一個模組從模組的型別開始,模組有不同的型別,如前面範例的`cc_library_shared`,當然型別還有很多種,譬如`cc_binary` `android_app` `cc_library_static`等等。模組包含一些屬性格式為`property-name:property-value`,其中name屬性必須指定,其屬性值必須是全域唯一的。 其中預設模組可用於在多個模組中重複相同的屬性,是不是用文字表達很模糊,好嗎,上實例: ```cpp cc_defaults { //預設模組名稱 name: "default_module", shared_libs: ["libz"], stl: "none", } cc_binary { name: "test1", defaults: ["default_module"], //引用預設模組名稱 srcs: ["src/test/test.c"], } ``` srcs 屬性以字串清單的形式指定用於編譯模組的原始檔。您可以使用模組引用語法`:` 來引用產生原始檔案的其他模組的輸出,例如`genrule` 或`filegroup`。是不是感覺一頭霧水,還是上實例說明: ```cpp frameworks/base/core/java$ vi Android.bp filegroup { name: "IKeyAttestationApplicationIdProvider.aidl", srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"], } filegroup { name: "IDropBoxManagerService.aidl", srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"], ------------------------------------------------------- frameworks/base$ vi libs/services/Android.bp cc_library_shared { name: "libservices", srcs: [ ":IDropBoxManagerService.aidl", "src/os/DropBoxManager.cpp", "src/os/StatsDimensionsValue.cpp", "src/os/StatsLogEventWrapper.cpp", ], shared_libs: [ "libbinder", "liblog", "libcutils", "libutils", ], ``` ### 變數&註解 * 我們知道Android.mk中可以定義變量,當然作為新編譯系統中替代Android.mk的Android.bp也是一定存在,更加何況Android.mk還可以一定條件的轉換成Android.bp。 * 變數範圍限定為聲明它們的檔案的其餘部分,可以使用「=」 號賦值, 但是不能使用「:=」 賦值。變數是不可變的,但有一個例外它們可以附上+= 賦值,但僅在變數被引用之前。 ```cpp gzip_srcs = ["src/minigzip.c"], cc_binary { name: "gzip", srcs: gzip_srcs, shared_libs: ["libz"], stl: "none", } ``` * 我們知道Android.mk中可以進行註釋,當然Android.bp裡面也可以,Android.mk中使用"#"然後添加註釋,Android.bp使用單行註釋//和多行註釋/* */兩種方式。 ### 支援模組類型 Android.bp可以支援`android_app`、`cc_binary`、`cc_binary_host`等多種類型,具體定義在Android原始碼的build/soong/androidmk/androidmk/android.go可以查看,如下: ```cpp var moduleTypes = map[string]string{ "BUILD_SHARED_LIBRARY": "cc_library_shared", "BUILD_STATIC_LIBRARY": "cc_library_static", "BUILD_HOST_SHARED_LIBRARY": "cc_library_host_shared", "BUILD_HOST_STATIC_LIBRARY": "cc_library_host_static", "BUILD_HEADER_LIBRARY": "cc_library_headers", "BUILD_EXECUTABLE": "cc_binary", "BUILD_HOST_EXECUTABLE": "cc_binary_host", "BUILD_NATIVE_TEST": "cc_test", "BUILD_HOST_NATIVE_TEST": "cc_test_host", "BUILD_NATIVE_BENCHMARK": "cc_benchmark", "BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host", "BUILD_JAVA_LIBRARY": "java_library_installable", // will be rewritten to java_library by bpfix "BUILD_STATIC_JAVA_LIBRARY": "java_library", "BUILD_HOST_JAVA_LIBRARY": "java_library_host", "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik", "BUILD_PACKAGE": "android_app", "BUILD_RRO_PACKAGE": "runtime_resource_overlay", "BUILD_CTS_EXECUTABLE": "cc_binary", // will be further massaged by bpfix depending on the output path "BUILD_CTS_SUPPORT_PACKAGE": "cts_support_package", // will be rewritten to android_test by bpfix "BUILD_CTS_PACKAGE": "cts_package", // will be rewritten to android_test by bpfix "BUILD_CTS_TARGET_JAVA_LIBRARY": "cts_target_java_library", // will be rewritten to java_library by bpfix "BUILD_CTS_HOST_JAVA_LIBRARY": "cts_host_java_library", // will be rewritten to java_library_host by bpfix } ``` ### 支援預編譯類型 Android.bp可以支援多種預編譯類型,具體定義在Android原始碼的build/soong/androidmk/androidmk/android.go可以查看,如下所示: ```cpp var prebuiltTypes = map[string]string{ "SHARED_LIBRARIES": "cc_prebuilt_library_shared", "STATIC_LIBRARIES": "cc_prebuilt_library_static", "EXECUTABLES": "cc_prebuilt_binary", "JAVA_LIBRARIES": "java_import", "APPS": "android_app_import", "ETC": "prebuilt_etc", } ``` ### 條件式編譯 ```cpp system/core/libusbhost$ cat Android.bp package { default_applicable_licenses: ["Android-Apache-2.0"], } cc_library { name: "libusbhost", vendor_available: true, vndk: { enabled: true, }, host_supported: true, srcs: ["usbhost.c"], cflags: ["-Werror"], export_include_dirs: ["include"], target: { android: { //編譯android上運作的程式 cflags: [ "-g", "-DUSE_LIBLOG", ], shared_libs: ["liblog"], }, darwin: { //編譯drwin上運作的程式 enabled: false, }, }, } ``` ## Android.bp加入marco控制編譯 我們知道Android.mk採用Makefile的語言,所以為了控制條件編譯和多版本適配,我們可以在不同產品直接在Android.mk中採用Makefile語言控制編譯。雖然我們也可以透過Android的預置工具androidmk將Android.mk轉換為Android.bp腳本,但對於有巨集控制的條件編譯,androidmk是無能為力的。 這是因為Android.bp是類似JSON的純文字形式,對於Android.mk裡面流控制部分,在Android.bp裡要藉助使用go語言檔案去進行控制。好了說了這麼多了,我想讀者應該知道這個篇章要寫什麼了,那就是手把手帶領大夥手擼一把Android.bp添加marco控制編譯。 [Ref](https://blog.csdn.net/tkwxty/article/details/105111218) ## IOMUX [Ref](https://blog.csdn.net/qq_38131812/article/details/128512088) 晶片包含數量有限的引腳,其中大部分有多種訊號選擇。這些訊號到引腳和引腳到訊號的選擇是由輸入輸出多工器稱為IOMUX。IOMUX也被用來配置其他引腳的特性,比如說電壓等級和驅動強度等等。 ### IOMUX原理 以下面的MUX選項為例,Instance為晶片內部設備IP,Port為這個設備IP的接腳(在內部),Pad是晶片上我們能看到的引腳;Mode是指複用模式,最多支援8種復用模式。 ![](https://hackmd.io/_uploads/SJaNmn2-6.png) * IOMUX有四類暫存器,它們分別是mux控制暫存器、pad控制暫存器,input選擇暫存器和通用控制暫存器(General Purpose Register,GPR)。 * 對於模組的引腳輸出功能,參考紅色的路徑。對於一個MUX單元來說,有6個模組的接腳連接到這個MUX單元,它們可能是模組1,2,3…6這6個模組中的某一腳。這個MUX單元連接到唯一的PAD,這個PAD就是我們在晶片外部能看到的接腳。現在我們想要讓模組1的腳輸出訊號,會遇到哪些問題?下面我們依照訊號流動方嚮往前推,從紅色路徑可以看到,首先是會遇到MUX單元,這裡有6個訊號混合,需要設定這個MUX暫存器讓其選取輸出我們想要的訊號。現在這個PAD已經連結到了模組1的接腳,然後我們或許還需要配置這個輸出腳的上下拉和電壓值,這個時候就需要設定PAD控制暫存器。最後我們想要的訊號就從晶片內部走出來了。 ![](https://hackmd.io/_uploads/B1ToEan-T.png) * 對於模組的引腳輸入功能,參考藍色的路徑。現在模組1想從上面相同的外部接腳獲取輸入訊號,那麼這個訊號又該如何從晶片外部流入內部的模組1呢?首先會經過PAD,然後又會經過MUX單元(這裡的MUX單元和上面是反向的),這裡我們也還需要設定MUX寄存器,經過MUX單元後,會來到INPUT SELECT輸入選擇單元。對於這個輸入選擇單元來說,連結有多個模組引腳。我們則需要配置這個輸入選擇暫存器,選擇資料輸入的MUX單元。 * 上面的引腳輸入功能,我們稱之為Daisy chain菊花鏈。對於模組X的接腳輸入,由INPUT SELECT輸入選擇暫存器控制輸入源,此輸入源來自多個IOMUX單元,例如cell1,cell2和cell3都能將外部訊號輸入到模組X的輸入接腳。 >在某些情況下,可能會有多個引腳驅動單個模塊的輸入引腳。這種情況需要添加一個額外的IOMUXing層次;所有這些輸入信號都被進行多路切換,並且有一個專用的軟體控制寄存器來控制多路切換,以選擇所需的輸入路徑。 參與“串聯”模塊端口需要兩個軟體配置命令,一個用於選擇該引腳的模式(可通過`IOMUXC_SW_MUX_CTL_<PAD>`寄存器進行編程),另一個用於將其定義為輸入路徑(通過串聯寄存器進行)。這意味著參與“串聯”模塊端口需要兩個軟體配置命令,一個用於選擇該引腳的模式(可通過`IOMUXC_SW_MUX_CTL_<PAD>`寄存器進行編程),另一個用於將其定義為輸入路徑(通過串聯寄存器進行)。 ![](https://hackmd.io/_uploads/BklncTh-6.png) * 使用不同的PAD,對應不同的MUX控制暫存器。 * PAD命名規則:IOMUXC_SW_PAD_CTL_PAD_, * MUX命名規則:IOMUXC_SW_MUX_CTL_PAD_ ### register案例 下面以UART1的TX和RX腳位為例,對於RX接腳,可以選擇三個PAD,UART1_RXD,SD1_CMD和SAI2_RXC;對於TX,可以選擇UART1_TXD,SD1_CLK和SAI2_RXFS。 ![](https://hackmd.io/_uploads/S1FnyRnW6.png) * PAD: UART1_RXD * PAD register : IOMUXC_SW_PAD_CTL_PAD_UART1_RXD * MUX控制暫存器 : IOMUXC_SW_MUX_CTL_PAD_SD1_CMD * PAD: SAI2_RXC * PADregister:IOMUXC_SW_PAD_CTL_PAD_SAI2_RXC, * MUX控制暫存器:IOMUXC_SW_MUX_CTL_PAD_SAI2_RXC。 * Input select * RX接腳的輸入選擇暫存器:IOMUXC_UART1_UART_RXD_MUX_SELECT_INPUT。 以PAD SD1_CMD為例分析RX功能的實作過程,對於MUX控制暫存器來說,MUX_MODE應該選擇100 ![](https://hackmd.io/_uploads/rJS8l02bT.png) 對於輸入選擇暫存器,DAISY應該選擇001。 ![](https://hackmd.io/_uploads/SkaLl03Wp.png) [如何註冊pad](https://blog.csdn.net/qq_38131812/article/details/128519215) `pinfunc.h` 在`kernel_imx/arch/arm64/boot/dts/freescale/imx8mp-pinfunc.h` Device tree 在 `kernel_imx/arch/arm64/boot/dts/freescale/imx8mp-evk.dts` 這個驅動的probe函數使用imx_pinctrl_probe註冊了i.MX8MP的實體pad資訊: `kernel_imx/drivers/pinctrl/freescale/pinctrl-imx8mp.c` [imx_pinctrl_probe函數梳理以及重要結構體](https://qmiller.blog.csdn.net/article/details/128524077) `kernel_imx/include/linux/pinctrl/pinctrl.h` ```cpp struct pinctrl_desc { const char *name;//pin控制器名字 const struct pinctrl_pin_desc *pins;//描述IC的物理引脚pad资源 unsigned int npins; const struct pinctrl_ops *pctlops;//全局GPIO配置 const struct pinmux_ops *pmxops; //mux配置 const struct pinconf_ops *confops;//电气属性配置 struct module *owner; bool link_consumers; }; ```