2021年11月

检查 io 是否被占用。

  1. adb root, adb shell
  2. cd /sys/class/gpio 进入 gpio 目录
  3. echo 46 > export 获取 gpio_46
  4. 检查上条命令是否提示 /system/bin/sh: can't create export: Read-only file system,如果提示这个,那么说明这个 gpio 被占用了,否则这个 gpio 就是空的。
  5. echo 46 > unexport 释放 gpio_46

驱动代码 (quectel)

不管输入还是输出 gpio,直接仿照这个源文件里面进行添加即可。 比如说这个源码里面提供了四个 gpio,key_home, red_led_en, green_led_en, yellow_led_enSC200R_Android10.0_R04_r023/kernel/msm-4.9/drivers/misc/gpio_control.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/workqueue.h>
#include <linux/errno.h>
#include <linux/pm.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/delay.h>
#include <linux/of_gpio.h>
#include <linux/pinctrl/consumer.h>

#if defined(CONFIG_FB)
#include <linux/notifier.h>
#include <linux/fb.h>
#endif
#include <linux/timer.h>
#include <linux/string.h>

struct quectel_platform_data {
    int key_home;

    int red_led_en;
    int green_led_en;
    int yellow_led_en;
};

struct quectel_platform_data *quec_pdata;

static ssize_t quec_key_home_show(struct device *dev,
                struct device_attribute *attr, char *buf)
{
    return snprintf(buf, 2, "%d\n", __gpio_get_value(quec_pdata->key_home));
}

static ssize_t quec_red_led_en_show(struct device *dev,
                struct device_attribute *attr, char *buf)
{
    return snprintf(buf, 2, "%d\n", __gpio_get_value(quec_pdata->red_led_en));
}

static ssize_t quec_green_led_en_show(struct device *dev,
                struct device_attribute *attr, char *buf)
{
    return snprintf(buf, 2, "%d\n", __gpio_get_value(quec_pdata->green_led_en));
}

static ssize_t quec_yellow_led_en_show(struct device *dev,
                struct device_attribute *attr, char *buf)
{
    return snprintf(buf, 2, "%d\n", __gpio_get_value(quec_pdata->yellow_led_en));
}

static ssize_t quec_red_led_en_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t size)
{
    unsigned int val;
    if (size > 2)
        return -EINVAL;

    if (sscanf(buf, "%u", &val) != 1)
        return -EINVAL;
    if(val)
        __gpio_set_value(quec_pdata->red_led_en,1);
    else
        __gpio_set_value(quec_pdata->red_led_en,0);
    return size;
}

static ssize_t quec_green_led_en_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t size)
{
    unsigned int val;
    if (size > 2)
        return -EINVAL;

    if (sscanf(buf, "%u", &val) != 1)
        return -EINVAL;
    if(val)
        __gpio_set_value(quec_pdata->green_led_en,1);
    else
        __gpio_set_value(quec_pdata->green_led_en,0);
    return size;
}

static ssize_t quec_yellow_led_en_store(struct device *dev,
                struct device_attribute *attr,
                const char *buf, size_t size)
{
    unsigned int val;
    if (size > 2)
        return -EINVAL;

    if (sscanf(buf, "%u", &val) != 1)
        return -EINVAL;
    if(val)
        __gpio_set_value(quec_pdata->yellow_led_en,1);
    else
        __gpio_set_value(quec_pdata->yellow_led_en,0);
    return size;
}

static DEVICE_ATTR(key_home, (S_IRUGO | S_IWUSR | S_IWGRP),
            quec_key_home_show,
            NULL);

static DEVICE_ATTR(red_led_en, (S_IRUGO | S_IWUSR | S_IWGRP),
            quec_red_led_en_show,
            quec_red_led_en_store);

static DEVICE_ATTR(green_led_en, (S_IRUGO | S_IWUSR | S_IWGRP),
            quec_green_led_en_show,
            quec_green_led_en_store);

static DEVICE_ATTR(yellow_led_en, (S_IRUGO | S_IWUSR | S_IWGRP),
            quec_yellow_led_en_show,
            quec_yellow_led_en_store);

static struct attribute *quec_attrs[] = {
    &dev_attr_key_home.attr,

    &dev_attr_red_led_en.attr,
    &dev_attr_green_led_en.attr,
    &dev_attr_yellow_led_en.attr,
    NULL
};

static const struct attribute_group quec_attr_grp = {
    .attrs = quec_attrs,
};

static int quectel_misc_parse_dt(struct device *dev, 
        struct quectel_platform_data *pdata)
{
    struct device_node *np = dev->of_node;

    pdata->key_home = of_get_named_gpio(np, "quec,key_home", 0);
    if (pdata->key_home < 0){
        pr_err("%s: get quec,key_home failed\n", __func__);
        return pdata->key_home;
    }

    pdata->red_led_en = of_get_named_gpio(np, "quec,red_led_en", 0);
    if (pdata->red_led_en < 0){
        pr_err("%s: get quec,red_led_en failed\n", __func__);
        return pdata->red_led_en;
    }

    pdata->green_led_en = of_get_named_gpio(np, "quec,green_led_en", 0);
    if (pdata->green_led_en < 0){
        pr_err("%s: get quec,green_led_en failed\n", __func__);
        return pdata->green_led_en;
    }

    pdata->yellow_led_en = of_get_named_gpio(np, "quec,yellow_led_en", 0);
    if (pdata->yellow_led_en < 0){
        pr_err("%s: get quec,yellow_led_en failed\n", __func__);
        return pdata->yellow_led_en;
    }

    return 0;
}

static int quectel_request_io_port(struct quectel_platform_data *pdata)
{
    int ret = 0;

    if (gpio_is_valid(pdata->key_home)) {
        ret = gpio_request(pdata->key_home, "quectel_key_home");
        if (ret) {
            pr_err("%s: Unable to request key_home  [%d]\n", __func__,pdata->key_home);
            goto err_pwr_off;
        }

        ret = gpio_direction_output(pdata->key_home, 0);
        if (ret) {
            pr_err("%s: Unable to set direction for key_home [%d]\n", __func__,pdata->key_home);
            goto err_free_key_home;
        }
    } else {
        pr_err("%s: Invalid key_home [%d]!\n", __func__,pdata->key_home);
        ret = -EINVAL;
        goto err_free_key_home;
    }

    if (gpio_is_valid(pdata->red_led_en)) {
        ret = gpio_request(pdata->red_led_en, "quectel_red_led_en");
        if (ret) {
            pr_err("%s: Unable to request red_led_en  [%d]\n", __func__,pdata->red_led_en);
            goto err_pwr_off;
        }

        ret = gpio_direction_output(pdata->red_led_en, 0);
        if (ret) {
            pr_err("%s: Unable to set direction for red_led_en [%d]\n", __func__,pdata->red_led_en);
            goto err_free_red_led_en;
        }
    } else {
        pr_err("%s: Invalid red_led_en [%d]!\n", __func__,pdata->red_led_en);
        ret = -EINVAL;
        goto err_free_red_led_en;
    }

    if (gpio_is_valid(pdata->green_led_en)) {
        ret = gpio_request(pdata->green_led_en, "quectel_green_led_en");
        if (ret) {
            pr_err("%s: Unable to request green_led_en  [%d]\n", __func__,pdata->green_led_en);
            goto err_pwr_off;
        }

        ret = gpio_direction_output(pdata->green_led_en, 0);
        if (ret) {
            pr_err("%s: Unable to set direction for green_led_en [%d]\n", __func__,pdata->green_led_en);
            goto err_free_green_led_en;
        }
    } else {
        pr_err("%s: Invalid green_led_en [%d]!\n", __func__,pdata->green_led_en);
        ret = -EINVAL;
        goto err_free_green_led_en;
    }

    if (gpio_is_valid(pdata->yellow_led_en)) {
        ret = gpio_request(pdata->yellow_led_en, "quectel_yellow_led_en");
        if (ret) {
            pr_err("%s: Unable to request yellow_led_en  [%d]\n", __func__,pdata->yellow_led_en);
            goto err_pwr_off;
        }

        ret = gpio_direction_output(pdata->yellow_led_en, 0);
        if (ret) {
            pr_err("%s: Unable to set direction for yellow_led_en [%d]\n", __func__,pdata->yellow_led_en);
            goto err_free_yellow_led_en;
        }
    } else {
        pr_err("%s: Invalid yellow_led_en [%d]!\n", __func__,pdata->yellow_led_en);
        ret = -EINVAL;
        goto err_free_yellow_led_en;
    }

    return 0;

err_free_key_home:
    if (gpio_is_valid(pdata->key_home))
        gpio_free(pdata->key_home);
err_free_red_led_en:
    if (gpio_is_valid(pdata->red_led_en))
        gpio_free(pdata->red_led_en);
err_free_green_led_en:
    if (gpio_is_valid(pdata->green_led_en))
        gpio_free(pdata->green_led_en);
err_free_yellow_led_en:
    if (gpio_is_valid(pdata->yellow_led_en))
        gpio_free(pdata->yellow_led_en);
err_pwr_off:
        return ret;

}

static void quec_gpio_free(void)
{
    gpio_free(quec_pdata->key_home);
    gpio_free(quec_pdata->red_led_en);
    gpio_free(quec_pdata->green_led_en);
    gpio_free(quec_pdata->yellow_led_en);
}

static int quec_gpio_probe(struct platform_device *pdev)
{

    int ret;
    struct quectel_platform_data *pdata ;

    pr_err("-----------quectel_probe start--------------\n");

    if (pdev->dev.of_node) {
        pdata = devm_kzalloc(&pdev->dev,
            sizeof(struct quectel_platform_data), GFP_KERNEL);
        if (!pdata) {
            dev_err(&pdev->dev,
                "quec allocate memory for pdata\n");
            return -ENOMEM;
        }
        ret = quectel_misc_parse_dt(&pdev->dev, pdata);
        if (ret) {
            dev_err(&pdev->dev, "parse dts failed \n");
            return PTR_ERR(pdata);
        }
    } else {
        pdata = pdev->dev.platform_data;
    }

    quec_pdata = pdata;

    if(!pdata) {
        dev_err(&pdev->dev, "quec Invalid pdata\n");
        return -EINVAL;
    }

    ret = quectel_request_io_port(pdata);
    if(ret){
        dev_err(&pdev->dev, "request io failed\n");
        return ret;
    }

    ret = sysfs_create_group(&pdev->dev.kobj, &quec_attr_grp);
    if (ret < 0) {
        dev_err(&pdev->dev, "sys file creation failed.\n");
        return -ENOMEM;
    }

    pr_err("-----------quectel_probe success--------------\n");

    return 0;
}

static int quec_gpio_remove(struct platform_device *pdev)
{
    struct quectel_platform_data *pdata = platform_get_drvdata(pdev);

    device_init_wakeup(&pdev->dev, 0);

    sysfs_remove_group(&pdev->dev.kobj, &quec_attr_grp);

    quec_gpio_free();

    kfree(pdata);

    return 0;
}

static const struct of_device_id quec_gpio_match[] = {
        { .compatible = "quec,gpio_driver" },
        {},  
};

static struct platform_driver quec_gpio_driver = {
    .driver = {
            .name = "quec_gpio",
            .owner = THIS_MODULE,
            .of_match_table = quec_gpio_match,
    },   
    .probe = quec_gpio_probe,
    .remove = quec_gpio_remove,
};

module_platform_driver(quec_gpio_driver);

MODULE_DESCRIPTION("misc driver");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0");

makefile

SC200R_Android10.0_R04_r023/kernel/msm-4.9/drivers/misc/Makefile 里面增加 obj-y += gpio_control.o

dtsi

SC200R_Android10.0_R04_r023/kernel/msm-4.9/arch/arm64/boot/dts/qcom/qm215-qrd.dtsi

&soc {
        gpio_ctrl {
                compatible = "quec,gpio_driver";
                quec,key_home = <&tlmm 95 0x00>;
                quec,red_led_en = <&tlmm 93 0x00>;
                quec,green_led_en = <&tlmm 46 0x00>;
                quec,yellow_led_en = <&tlmm 23 0x00>;
        };
};

解除被占用 gpio

SC200R_Android10.0_R04_r023/kernel/msm-4.9/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi 中把被占用的 gpio 去除掉即可。

编译,烧录

如果修改的时驱动源码,那么编译 boot.img,如果修改的是 dts,那么编译 dtbo.img。 然后用 fastboot,把 boot.img, dtbo.img 都烧录进去。

读取 gpio

查找 dts 中对应的节点 key_homefind . -name "*home*", 结果

./devices/platform/soc/soc:input-gpio/key_home
./firmware/devicetree/base/soc/input-gpio/quec,key_home
./module/home_gpio
cd ./devices/platform/soc/soc:input-gpio/
cat key_home

就可以读取到输入的高低电平

输出 gpio

find . -name "*led_en*"

./devices/platform/soc/soc:gpio_ctrl/green_led_en
./devices/platform/soc/soc:gpio_ctrl/red_led_en
./devices/platform/soc/soc:gpio_ctrl/yellow_led_en
./firmware/devicetree/base/__symbols__/front_flash_led_enable
./firmware/devicetree/base/__symbols__/rear_flash_led_enable
./firmware/devicetree/base/soc/gpio_ctrl/quec,green_led_en
./firmware/devicetree/base/soc/gpio_ctrl/quec,yellow_led_en
./firmware/devicetree/base/soc/gpio_ctrl/quec,red_led_en
./firmware/devicetree/base/soc/pinctrl@1000000/tlmm_pmi_flash_led/front_flash_led_enable
./firmware/devicetree/base/soc/pinctrl@1000000/tlmm_pmi_flash_led/rear_flash_led_enable
cd devices/platform/soc/soc\:gpio_ctrl/
echo 1 > green_led_en
echo 0 > green_led_en

就可以设置输出 gpio 的高低电平。

另外一种方法实现针对 led 的 gpio 输出。 (fibcom)

内核本身就有 led 的驱动代码,在 kernel/msm-4.9/drivers/leds/leds-gpio.c 中,所以如果是 led 的用途 gpio,可以直接修改 dtsi 即可。

kernel/msm-4.9/arch/arm64/boot/dts/qcom/sq808-evk/msm8917-pinctrl.dtsi

                gpio_led_active: gpio_led_active {
                        mux {
                                pins = "gpio98", "gpio97", "gpio12";
                                drive-strength = <2>;
                                output-low;
                        };
                };
kernel/msm-4.9/arch/arm64/boot/dts/qcom/sq808-evk/qm215-qrd.dtsi

        gpio-leds {
                compatible = "gpio-leds";
                pinctrl-names = "default";
                pinctrl-0 = <&gpio_led_active>;
                led-red {
                        label = "red";
                        default-state = "keep";
                        gpios = <&tlmm 12 0x00>;
                };
                led-blue{
                        label = "blue";
                        default-state = "off";
                        gpios = <&tlmm 97 0x00>;
                };
                led-green{
                        label = "green";
                        default-state = "off";
                        gpios = <&tlmm 98 0x00>;
                };
        };
kernel/msm-4.9/arch/arm64/configs/sq80x_defconfig

CONFIG_LEDS_GPIO=y

串口

除了 adb 还可以使用串口,但是注意,只有屏幕点亮的情况下,串口命令才能正常工作。 一般先要用 su 提示为 root 用户,然后再使用各种命令。

参考

gpio按键驱动
https://blog.csdn.net/syn_dyf/article/details/104366146

高通GPIO驱动(DTS方式)
https://www.cnblogs.com/linhaostudy/p/8372777.html

高通GPIO配置简介
https://blog.csdn.net/ldinvicible/article/details/52421640

高通DTS 配置 GPIO 中断
https://ciellee.blog.csdn.net/article/details/101226749

高通平台中gpio简单操作和调试
https://blog.csdn.net/s_jason/article/details/73864103?spm=1001.2101.3001.6650.9&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-9.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-9.no_search_link

高通平台GPIO pinctrl调试心得
https://blog.csdn.net/yxw0609131056/article/details/80662462

高通平台直接通过adb控制GPIO电平
https://blog.csdn.net/lhh_qrsly/article/details/110939319?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-17.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-17.no_search_link

android控制gpio实现对小灯读写(一)
https://blog.csdn.net/zhonglunshun/article/details/70312945
android驱动学习---led实验
https://www.iteye.com/blog/koliy-1424304

Android字符设备驱动及应用层从jni控制GPIO实战
https://blog.csdn.net/qf0727/article/details/52856490
android jni控制gpio (rk3288)
https://www.cnblogs.com/CZM-/p/9622663.html

今天调试广和通的串口,发现发送没有问题,接收都是乱码。

和供应商联系了之后,解决了这个问题。

确认是否是串口休眠引起的问题。

  1. echo -1 > /sys/bus/platform/devices/7af0000.uart/power/autosuspend_delay_ms 执行这个命令,关闭串口自动休眠。
  2. 重新测试,发现接收正常了,没有乱码。

自动设置串口不休眠。

  1. SQ80X-Android10/kernel/msm-4.9/drivers/tty/serial/msm_serial_hs.c 修改这个文件,

    -       pm_runtime_set_autosuspend_delay(uport->dev, 100);
    +       pm_runtime_set_autosuspend_delay(uport->dev, -1);
  2. 重新编译测试。

准备底包

  1. 把供应商给出的出厂镜像解压
  2. 创建自己的烧录文件夹 customer_sw
  3. 把厂商文件夹中的 rawprogram0_update_original.xml 复制到 customer_sw 中,把厂商提供的 ptool.py 也放到 customer_sw 中。
  4. 安装 python 2.7.6
  5. 运行 python ./ptool.py -x rawprogram0_update_original.xml 生成一系列的文件。
  6. 生成文件中 rawprogram0.xmlpatch0.xml 就是 qfil 需要使用的。
  7. 从厂商文件夹中复制 prog_emmc_firehose_8917_ddr.mbncustomer_sw 中.

指定烧录镜像

rawprogram0.xml 中所有的 ap 侧需要用的可以保留, bp 侧的直接 filename="" 这样即可。 注意:

  1. 一般 persist.img 这个可以不用。
  2. 如果有某些特殊修改,供应商会提供 devcfg,那么 rawprogram0.xml 中对应条目需要指明 filename。

准备镜像

rawprogram0.xml 中所有 filename 没有留空的,相应的镜像从 out 文件夹下面复制到 customer_sw 中。

qfil 配置

  1. download configuration 中,勾选 reset after download,取消勾选 erase all before download
  2. 选择 flat build
  3. select programmer 中选择 prog_emmc_firehose_8917_ddr.mbn
  4. load xml 中 rawprogrammer 中选择 rawprogram0.xml
  5. load xml 中 patch 中选择 patch0.xml
  6. download

编译环境配置问题。

  1. 不是输入 source build/envsetup.sh 而是 source build/envsetup.sh SQ808_CN_10_00
  2. 然后再 lunch sq80x_64-userdebug

dts 配置问题。

  1. out/target/product/sq80x_64/obj/KERNEL_OBJ/arch/arm64/boot/dts/qcom/ 这个文件夹删除掉。
  2. kernel/msm-4.9/arch/arm64/boot/dts/qcom/Makefile 删除 dts-dirs += sq808-fttest

类似的核心芯片情况下,下载烧录 分包 的时候都是使用的 qpst,具体过程如下:

  1. 检查端口不是 9008
  2. flat build
  3. 加载 prog_emmc_firehose_8917_ddr.mbn
  4. 加载 xml, 这里注意,移远是 rawprogram_unsparse.xml, 广和通是 rawprogram0_update.xml,加载 patch0.xml
  5. download

备注

  • 如果广和通整包下载,好像是选择 rawprogram_unsparse.xml
  • 广和通编译的时候,也不是 source build/envsetup.sh 而是 source build/envsetup.sh SQ808_CN_10_00
  • 然后使用 ptool.py 对应的文档来做。相应的 xml 文件可以和 移远的对照改动。
  • 广和通的分包脚本在 win 下可以运行,在 ubuntu 下面有问题。
  • 如果开机只能进入fastboot, 基本可以认为是 boot.imgdtbo.img 有问题。

getevent -l

可以查看 kernel 具体上报上来的按键信息

查看按键有没有注册中断。

  1. cat proc/interrupts | grep home 这个可以看 home 键有没有注册中断。
  2. cat proc/interrupts | grep volume_up 这个可以对照着看这个按键中断注册的情况。

查看设备树中有没有相应的按键节点

ls sys/firmware/devicetree/base/soc/gpio_keys/ 可以查看所有的按键节点。

查看 bid

getprop | grep bid

核对 dtsi 文件

确保 home 按键是在 gpio_key 下面的子节点。

参考:

【实习周记】Android getevent.c源码分析
https://blog.csdn.net/LeeDuoZuiShuai/article/details/97536678

android Input子系统分析
https://blog.csdn.net/xiaoxiaoyu1107/article/details/39400199#overview
android Input子系统分析(内核层->android系统层)
https://www.cnblogs.com/MMLoveMeMM/articles/4119812.html

确定 dts 文件

  1. 直接从串口打印的 log 里面,搜索 Machine,正常就会出现后面的机器标识了,我这边是 QRD
    [    0.000000] OF: fdt:Machine model: QRD
  2. SC200R_Android10.0_R04_r023/kernel/msm-4.9/arch/arm64/boot/dts/qcom$ 下面搜索 QRD
    $ grep -R "\"QRD\""
    qm215-qrd-overlay.dts:  model = "QRD";
    sdm439-qrd-overlay.dts: model = "QRD";
    qcm2150-qrd-overlay.dts:        model = "QRD";
    sdm632-qrd-overlay.dts: model = "QRD";
    sdm429-qrd-overlay.dts: model = "QRD";
  3. 在怀疑的 dts 里面的 model 后面增加一些字符,然后重新编译 kernel,查看打印 log。就能确定到底是哪一个 dts 了,我的如下:
    [    0.000000] OF: fdt:Machine model: QRD qrm215-qrd-overlay

最终的 dts 文件内容,只能通过反编译 fdt 才能知道了。

  1. android 启动后,通过 adb 获取 fdt 文件。 adb pull /sys/firmware/fdt ./
  2. 把 aosp 源码中的 dtc 文件复制出来, ./prebuilts/misc/linux-x86/dtc/dtc
  3. 把 fdt 转为 dts 文件,就可以查看最终的 dts 了。 dtc -I dtb -O dts fdt -o tmp.dts

查看 dts 的包含关系。

使用 SC200R_Android10.0_R04_r023/kernel/msm-4.9/arch/arm64 下面的 DeviceTreeMap.py 可以解析 dts 的相互包含关系。

参考

高通平台dts的匹配过程分析
https://blog.csdn.net/armfpga123/article/details/54313700

高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)
https://blog.csdn.net/aiku969/article/details/79878072

如何找到kernel所用的dtsi
https://blog.csdn.net/u013308744/article/details/50204693

Linux DTS(Device Tree Source)设备树详解之三(高通MSM8953实例分析篇)
https://radia.blog.csdn.net/article/details/76574727

Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇)
https://radia.blog.csdn.net/article/details/70800076

linux/android代码中对于不同项目中conf、dts、defconfig文件的处理方法
https://radia.blog.csdn.net/article/details/78270181?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link

Linux内核defconfig在哪,如何确定使用的kernel defconfig和dts配置文件 比较实用 新手福利...
https://blog.csdn.net/weixin_42318030/article/details/116820657?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.no_search_link&spm=1001.2101.3001.4242.1

如何确定使用的kernel defconfig和dts配置文件 比较实用 新手福利
https://blog.csdn.net/weixin_42082222/article/details/104663389

高通平台defconfig文件的确定
https://blog.csdn.net/qwaszx523/article/details/71425594
初识defconfig
https://www.akr-developers.com/d/108
Linux内核defconfig在哪,如何确定使用的kernel defconfig和dts配置文件 比较实用 新手福利...
https://blog.csdn.net/weixin_42318030/article/details/116820657

如果需要 android 开机时,串口就是 777 的权限,可以修改 device/qcom/msm8937_32/init.target.rc 文件。

on boot
    start rmt_storage
    insmod /system/lib/modules/adsprpc.ko
    chmod 0660 /dev/ttyMSM1
    chmod 0777 /dev/ttyMSM2

类似于这样的改法即可。

改完之后,需要整体编译才行,单独编译 kernel 是没用的,编译 system 和 vendor ,又因为校验通不过,所以只能整体编译,整体烧录。

使用 qcom 整体烧录镜像,步骤繁琐,比较花时间,如果只是修改了驱动和设备树,那么只需要烧录内核即可,可以使用 fastboot 迅速验证。

1. 生成 kernel

make bootimage -j
make dtboimage -j

2. 准备旧的镜像文件和脚本

  • boot, dtbo, system, vendor, vbmeta 这几个镜像是需要的
  • 脚本文件
adb wait-for-devices
adb reboot bootloader
fastboot devices
fastboot flash boot boot.img
fastboot flash dtbo dtbo.img
fastboot flash vbmeta vbmeta.img
fastboot flash system system.img
fastboot flash vendor vendor.img
fastboot reboot

3. 把新的 kernel 对应的 boot 和 dtbo 代替文件夹里面相应的文件,然后执行脚本即可。

可能是最上面的 working directory 是复制目录进去,而不是点击右边的 select 来选择的,使用 select 选择之后,按钮就可以点击了。