问题来源是M.2 Dongle的LED灯在kernel起来之前就亮了,kernel起来之后又初始化成熄灭状态。通过排查硬件规格书、GPIO表格,大概判定是前期软件初始化不正确造成的。通过观察串口打印的log,发现灯开始亮起来的瞬间是运行在lk中。

找到MTK 的LK代码路径

 MT8766_A11_AP/vendor/mediatek/proprietary/bootable/bootloader/lk/

找到MTK的LK代码编译out目录

 MT8766_A11_AP/out/target/product/tb8766p1_bsp_1g/obj/LK_OBJ/build-tb8766p1_bsp_1g/

再从out目录下的plarform目录确定当前编译的平台是mt6761,从而在对应的gpio配置输出函数中添加log

 MT8766_A11_AP/vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6761/mt_gpio.c
 ​
 S32 mt_set_gpio_mode_chip(u32 pin, u32 mode)
 {
 ......
 添加以下代码对改GPIO进行debug
 ​
  if (pin == 174)
  {
  GPIOVER("============ fuck gpio ===============\n");
  mdelay(1000);
  }
 ​
  return RSUCCESS;
 }

通过log大概确定相关动作是在lk_dtb_init()中或者后面一点点

 [254] [SBC] image dtbo auth init pass
 [254] [SBC] image dtbo cert vfy pass(22 ms)
 [255] [PROFILE] mmc read 1 blks in 0 ms: 8KB/s
 [256] dtbo_total_len: 0x8a17
 [257] [PROFILE] mmc read 69 blks in 1 ms: 34500KB/s
 [258] [PROFILE] mmc read 1 blks in 0 ms: 8KB/s
 [259] [SBC][oem] img auth pass
 [259] [SBC] dtbo vfy pass(1 ms)
 [260] dtbo_offset: 0x40
 [260] [PROFILE] ::: lvl(3) load_dtbo_buffer takes 30 ms
 [261] dtbo_size : 35287
 [272] [PROFILE] ::: lvl(3) dtb_overlay takes 11 ms
 [273] [PROFILE] ::: lvl(2) lk_dtb_init takes 100 ms
 [275] [GPIO] mt_set_gpio_mode_chip: ============ fuck gpio ===============
 [1278] [PROFILE] mmc read 32 blks in 2 ms: 8000KB/s
 [1279] [LK_ENV]ENV of area 0 initialize sucess
 [1280] [PROFILE] mmc read 32 blks in 1 ms: 16000KB/s
 [1280] [LK_ENV]ENV SIG of area 1 is wrong
 [1281] [LK_ENV]env area: 0
 [1281] [LK_ENV]env:
 [1281] [LK_ENV]md1_ccb_cap_gear=1
 [1282] [LK_ENV]md1_ccb_gear_list=1(2,20);2(2,10);3(0,0);11(2,2);12(2,62)
 [1283] [LK_ENV]env area: 1
 [1283] [LK_ENV]no valid env
 [1283] [PROFILE] ::: lvl(2) ENV init takes 7 ms
 [1284] mblock_reserve-R start: 0x7f040000, sz: 0xdb0000 map:0 name:framebuffer

最终定位到以下调用关系

 platform_early_init();
  |
  mt_gpio_set_default();
  |
  mt_gpio_set_default_chip();

观察mt_gpio_set_default,发现相关配置参数是从设备树中获取的,展开mt_gpio_set_default()函数中的mt_gpio_get_default_chip_from_dtb()调用,发现相关设备树节点名字是gpio@10005000,相关属性的名字是gpio_init_default。用adb pull /sys/firmware/fdt,反编译设备树确认存在这个属性和节点。

在kernel中过滤文本搜索gpio_init_default属性,发现并不存在与当前硬件相关的设备树文件!那么,猜测该属性应该是从别的设备树文件中合并进来的。再在代码中使用grep -nr gpio_init_default全局过滤搜索,发现有以下文件与之相关。

 ./kernel-4.19/arch/arm64/boot/dts/mediatek/mt6779-evb.dts:604:  gpio_init_default = <0 0 0 0 1 1 1>,
 ./vendor/mediatek/proprietary/tools/dct/python/obj/GpioObj.py:746:       gen_str += '''\tgpio_init_default = '''
 ./vendor/mediatek/proprietary/tools/dct/python/obj/GpioObj.py:772:       gen_str += '''\tgpio_init_default = '''
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/GpioObj.py:710:       gen_str += '''\tgpio_init_default = '''
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/GpioObj.py:736:       gen_str += '''\tgpio_init_default = '''
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6768/gpio_init.c:79:#define GPIO_DT_NODE_PROP_NAME "gpio_init_default"
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6765/mt_gpio_init.c:134:#define GPIO_DT_NODE_PROP_NAME "gpio_init_default"
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6761/mt_gpio_init.c:134:#define GPIO_DT_NODE_PROP_NAME "gpio_init_default"
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6785/gpio_init.c:79:#define GPIO_DT_NODE_PROP_NAME "gpio_init_default"
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/platform/mt6771/gpio_init.c:76:#define GPIO_DT_NODE_PROP_NAME "gpio_init_default"
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py:710:       gen_str += '''\tgpio_init_default = '''
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py:736:       gen_str += '''\tgpio_init_default = '''

打开与之相关的文件

 vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py

发现相关的python调用方法是fill_init_default_dtsiFile,那么再全局过滤搜索这个方法名,发现有以下文件与之相关。

 ./vendor/mediatek/proprietary/tools/dct/python/obj/ChipObj.py:260:                gen_str += gpioObj.fill_init_default_dtsiFile()
 ./vendor/mediatek/proprietary/tools/dct/python/obj/GpioObj.py:649:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/tools/dct/python/obj/GpioObj.py:744:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/tools/dct/python/obj/GpioObj.py:770:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/ChipObj.py:224:               gen_str += gpioObj.fill_init_default_dtsiFile()
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/GpioObj.py:613:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/GpioObj.py:708:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/preloader/tools/dct/obj/GpioObj.py:734:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/ChipObj.py:207:               gen_str += gpioObj.fill_init_default_dtsiFile()
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py:613:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py:708:   def fill_init_default_dtsiFile(self):
 ./vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/GpioObj.py:734:   def fill_init_default_dtsiFile(self):

打开与之相关的文件

 vendor/mediatek/proprietary/bootable/bootloader/lk/scripts/dct/obj/ChipObj.py

内容如下:

     def gen_custDtsi(self):
         log(LogLevel.info, 'Start to generate cust_dtsi file...')
         fp = open(os.path.join(ModuleObj.get_genPath(), 'cust.dtsi'), 'w')
         gen_str = ModuleObj.writeComment()
 ​
         # if early porting, gen empty dtsi file for kernel
         if self.__epFlag:
             fp.write(gen_str)
             fp.close()
             return
 ​
         #sorted_list = sorted(self.__objs.keys())
         #for tag in sorted_list:
         for tag in self.__objs.keys():
             if cmp(tag, 'gpio') == 0:
                 gpioObj = self.create_obj(tag)
                 gen_str += ModuleObj.writeHeader(gpioObj.get_dtsiFileName())
                 gen_str += gpioObj.fill_mapping_dtsiFile()
                 gen_str += gpioObj.fill_init_default_dtsiFile()
             else:
                 obj = self.create_obj(tag)
                 gen_str += ModuleObj.writeHeader(obj.get_dtsiFileName())
                 gen_str += obj.fill_dtsiFile()
 ​
             gen_str += '''\n\n'''
 ​
         fp.write(gen_str)
         fp.close()
         log(LogLevel.info, 'Generate cust_dtsi file successfully!')

可以从中判断出最终生成了cust.dtsi,全局搜索这个文件find -name cust.dtsi,发现生成路径是

 ./out/target/product/tb8766p1_bsp_1g/obj/KERNEL_OBJ/arch/arm/boot/dts/tb8766p1_bsp_1g/cust.dtsi

打开后确认生成的文件存在gpio@10005000节点和gpio_init_default属性。但是目前又不能判断到底是从哪个文件中解析了配置,从而生成了最终的设备树文件。好在该方法中打印了log,再从Android的编译log中搜索Start to generate cust_dtsi file...,发现以下内容:

 [ 60% 688/1130] build out/target/product/tb8766p1_bsp_1g/obj/FAKE/treble_sepolicy_tests_27.0_intermediates/27.0_mapping.combined.cil
 [ 60% 689/1130] build out/target/product/tb8766p1_bsp_1g/obj/KERNEL_OBJ/arch/arm/boot/dts/tb8766p1_bsp_1g/cust.dtsi
 [DCT_INFO]: DWS file path is /home/123/workspace/MT8766_A11_AP/kernel-4.19/drivers/misc/mediatek/dws/mt6761/tb8766p1_bsp_1g.dws
 [DCT_INFO]: Gen files path is /home/123/workspace/MT8766_A11_AP/out/target/product/tb8766p1_bsp_1g/obj/KERNEL_OBJ/arch/arm/boot/dts/tb8766p1_bsp_1g
 [DCT_INFO]: Log files path is /home/123/workspace/MT8766_A11_AP/out/target/product/tb8766p1_bsp_1g/obj/KERNEL_OBJ/arch/arm/boot/dts/tb8766p1_bsp_1g
 [DCT_INFO]: Parameter is cust_dtsi
 [DCT_INFO]: chip id: MT6761
 [DCT_INFO]: Chip ID : MT6761
 [DCT_INFO]: Project Info: Merlot_Phone
 [DCT_INFO]: Start to generate cust_dtsi file...
 [DCT_INFO]: Generate cust_dtsi file successfully!
 [ 61% 690/1130] //system/core/init:libinit static link libinit.a
 [ 61% 691/1130] //system/core/init:libinit static link libinit.a

好家伙,绕了一圈原来是tb8766p1_bsp_1g.dws

那么修改dws 的GPIO配置,重新编译。。。发现cust.dtsi中对应的GPIO配置变了,烧录验证。。。成功!

MTK8766 LK GPIO初始化状态设置分析的更多相关文章

  1. HGE初始化状态设置

    HGE_FRAMEFUNC:     最重要的设置,每个HGE应用必须设置.游戏的主循环就是他了.类型为bool*(),返回真那么主循环退出,游戏也就结束了.否则进行必要的处理后返回假.必须在调用进入 ...

  2. Linux USB Host-Controller的初始化代码框架分析【转】

    转自:http://blog.csdn.net/zkami/article/details/2496770 usb_hcd_omap_probe (const struct hc_driver *dr ...

  3. k8s replicaset controller分析(1)-初始化与启动分析

    replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...

  4. kube-scheduler源码分析(1)-初始化与启动分析

    kube-scheduler源码分析(1)-初始化与启动分析 kube-scheduler简介 kube-scheduler组件是kubernetes中的核心组件之一,主要负责pod资源对象的调度工作 ...

  5. 因为相同类型的其他实体已具有相同的主键值。在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 。。。

    因为相同类型的其他实体已具有相同的主键值.在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified&quo ...

  6. tableview 编辑状态设置

    #pragma mark - tableview 编辑状态设置 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSI ...

  7. Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)

    线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...

  8. Wireshark抓包分析TCP建立/释放链接的过程以及状态变迁分析

    Wireshark抓包分析TCP建立/释放链接的过程以及状态变迁分析 一.介绍计算机网络体系结构 1.计算机的网络体系结构 在抓包分析TCP建立链接之前首先了解下计算机的网络通信的模型,我相信学习过计 ...

  9. ContextMune上下文菜单中,二级菜单获取及状态设置

    ContextMune上下文菜单中,二级菜单获取及状态设置 在使用ContextMune上下文菜单中,能够通过二级菜单来获取及状态设置 //二级菜单获取和状态设置((ToolStripDropDown ...

  10. 关于Entity Framework更新的几种方式以及可能遇到的问题(附加类型“Model”的实体失败,因为相同类型的其他实体已具有相同的主键值)在使用 "Attach" 方法或者将实体的状态设置为 "Unchanged" 或 "Modified" 时如果图形中的任何实体具有冲突键值,则可能会发生上述行为

    在日常使用Entity Framework中,数据更新通常会用到.下面就简单封装了一个DBContext类 public partial class EFContext<T> : DbCo ...

随机推荐

  1. 去哪儿旅行携手 HarmonyOS SDK | 告别繁琐,常用信息秒级填充

    背景 去哪儿旅行作为行业内领先的一站式在线旅游平台,多年来在日益加剧的市场竞争中积极寻求创新,凭借其优质的服务深受消费者青睐.2024年,去哪儿旅行适配HarmonyOS NEXT版本, 升级用户服务 ...

  2. Java基础综合项目(ATM系统)

    文章目录 1.ATM项目介绍 2.项目架构搭建.欢迎界面设计 3.开户功能实现 4.生成卡号 5.登录功能 6.展示用户操作界面 7.查询账户.退出 8.存款 9.取款 10.转账 11.修改密码 1 ...

  3. 利用 Screen 保持 VSCode 连接远程任务持续运行

    在 Linux 上使用 screen 是一种保持进程持续运行的便捷方式,即使用户断开 SSH 连接,进程也不会中断. 我在使用VSCode连接AutoDL时,不知道如何能够使进程保持运行,后查阅资料可 ...

  4. 爱科微AIC8800D80P Wi-Fi6模块驱动移植

    1. 简介 开发环境Ubuntu20.04 目标平台:瑞芯微RK356X 目标平台内核版本:4.19.234 wifi模块型号:AIC8800D80P Wi-Fi6/BT5.0 2. 硬件 wifi模 ...

  5. Frida 问题集锦

    1. 使用过程中少用this Activity.onStart.implementation = function() { console.log('onStart: ' + this); this. ...

  6. 从0搭建一个FIFO模块-01(基础知识)

    1. FIFO介绍 基本概念 FIFO(First In, First Out)是一种常用的数据结构,用于存储和处理数据.它的工作原理与排队的顺序类似,遵循"先进先出"的原则.即, ...

  7. AI智能学生体测小程序解决方案

    引言: 近年来,随着教育理念的提升,对学生综合素质的教育越发重视,特别是越发重视学生的身体素质提升,各阶段的升学考试也将体测纳入考核范围.学校也推出了各种体测锻炼促进手段,今天为您介绍一个基于小程序的 ...

  8. PTA题目集4~6的总结性Blog

    · 前言 本次的三个作业,由答题判题程序- 4.家居强电电路模拟程序- 1.家居强电电路模拟程序 -2组成. 答题判题程序-4是对前三次判题程序的最后升级,设计多个子类继承于基础题类来实现对每种题型的 ...

  9. python虚拟环境管理之Pipenv

    GitHub:pypa/pipenv: Python Development Workflow for Humans. (github.com) 介绍: pipenv就是把pip和virtualenv ...

  10. 基于Github gist的代码片段管理工具Lepton

    Lepton主要功能 无限制的公共/私人片段 无限制的标签 语言组 Markdown支持 Jupyter Notebook查看器支持 macOS / Win / Linux客户端 GitHub Ent ...