最近遇到一个很有意思的问题,在abl阶段获取某个gpio状态并且进行判断,若为拉低则去做下一步的客制化的功能。过程较为坎坷,因此记录一下
首先,在abl阶段的时候就要进行检测,那么该gpio一定要在abl阶段之前保持拉高,若状态为默认拉低的话,那么在任何场景下都会走这个功能,不符合需求。使用示波器量取后发现该gpio的默认状态为拉高。那么我们需要做的事情就很清楚了。在进入abl之前保证我这个gpio默认为拉高即可。
分析:
1.询问硬件,这个gpio是普通gpio还是特殊gpio,如(pmic)。本次我们的gpio刚好就是pmic的gpio6
2.查看高通文档,使用的为pmic-xxx
3.在abl之前,那么软件侧就只有xbl可以进行gpio初始化操作
那么前期的工作准备的就差不多了,需求就为:在xbl阶段,将这个gpio设置成默认拉高状态
下面是代码部分:由于我本人之前也没有接触过pmic相关的,因此也只能走一步看一步
首先到pmic对应的头文件下查看有没有什么有用的信息
typedef enum
{
PM_GPIO_1, /**< GPIO 1. */
PM_GPIO_2, /**< GPIO 2. */
PM_GPIO_3, /**< GPIO 3. */
PM_GPIO_4, /**< GPIO 4. */
PM_GPIO_5, /**< GPIO 5. */
PM_GPIO_6, /**< GPIO 6. */
...
PM_GPIO_INVALID
}pm_gpio_perph_index;
可以看到这里的枚举定义中存在一个GPIO_6,那么PM_GPIO_6可能就是代表PMIC内的GPIO6。在代码内应该也是使用PM_GPIO_6来表示GPIO6,那么再查找一下哪里使用这个变量
QcomPkg/SocPkg/Fillmore/Library/ButtonsTargetLib/ButtonsBootLib.c
73: .Gpio = PM_GPIO_6,
QcomPkg/SocPkg/Palima/Library/ButtonsTargetLib/ButtonsLibPrivate.h
69: .Gpio = EFI_PM_GPIO_6,
QcomPkg/Include/api/pmic/pm/pm_gpio.h
131: PM_GPIO_6, /**< GPIO 6. */
QcomPkg/Include/Protocol/EFIPmicGpio.h
91: EFI_PM_GPIO_6, /**< GPIO 6. */
可以看到有4个地方存在关于GPIO_6的定义或者使用,其中第三个是我们刚才已经看过的。由于不熟悉PMIC,我选择都看一下里面都描述了什么
第一个可以看到就是一个变量的初始化赋值。将对应的GPIO设置为PM_GPIO_6
const ButtonBootPmicGpioCfg VolUpButton = {
.Gpio = PM_GPIO_6,
.VoltageSource = PM_GPIO_VIN0,
};
第二个可以看到也是对VoluUpButton的初始化操作
ButtonPmicGpioCfg VolUpButton = {
.PmicDeviceIndex = PMIC_B,
.Gpio = EFI_PM_GPIO_6,
.ISourcePulls = EFI_PM_GPIO_I_SRC_PULL_UP_30uA,
.VoltageSource = EFI_PM_GPIO_VIN1,
.OutBufferStrength = EFI_PM_GPIO_OUT_DRV_STR_LOW,
.Source = EFI_PM_GPIO_SRC_GND,
};
第三个上面已经看过,不重复看
第四个同样的也是GPIO 6的枚举。那么现在就存疑,我们是需要使用EFI_PM_GPIO_6还是第PM_GPIO_6,但是有一个共同点。他们都是对VolupButton进行初始化,那么先接着往下看
typedef enum
{
EFI_PM_GPIO_1, /**< GPIO 1. */
EFI_PM_GPIO_2, /**< GPIO 2. */
EFI_PM_GPIO_3, /**< GPIO 3. */
EFI_PM_GPIO_4, /**< GPIO 4. */
EFI_PM_GPIO_5, /**< GPIO 5. */
EFI_PM_GPIO_6, /**< GPIO 6. */
...
EFI_PM_GPIO_INVALID
}EFI_PM_GPIO_PERIPH_INDEX;
存在几个地方对VolUpButton进行调用及头文件内的初始化,我们先看一下初始化的内容,
ButtonPmicGpioCfg VolUpButton = {
.PmicDeviceIndex = PMIC_B,
.Gpio = EFI_PM_GPIO_6,
.ISourcePulls = EFI_PM_GPIO_I_SRC_PULL_UP_30uA,
.VoltageSource = EFI_PM_GPIO_VIN1,
.OutBufferStrength = EFI_PM_GPIO_OUT_DRV_STR_LOW,
.Source = EFI_PM_GPIO_SRC_GND,
};
再看看调用的地方
EFI_STATUS ConfigureButtonGPIOs ( VOID )
{
EFI_STATUS Status;
// volume up
Status = EnableInput(&VolUpButton);
if ( EFI_ERROR (Status) )
...
returu Status;
}
查看一下这个EnableInput函数做了什么,发现是对VolUpButton进行初始化,那么并且我没有在其他地方找到有调用这个PMIC_GPIO_6或者EFI_PMIC_GPIO_6的地方。对于上面我们提到的PMIC_GPIO_6以及EFI_PMIC_GPIO_6,在该平台内都有使用到。那么是不是可以假设为:xbl阶段会在两个地方进行这个Button的初始化呢?那么我们如果想要修改验证的话,也可以通过差分校验,都打开、都不打开、一个打开一个不打开这样去验证。
验证方法:
在对VolUpButton定义的地方修改.ISourcePulls属性,修改为EFI_PM_GPIO_I_SRC_PULL_DOWN_10uA,默认为拉低10uA状态。然后在abl内获取这个GPIO的状态看看是否正确,是的话则pass
总结:上面这个地方是依附于其他功能进行修改的,如果其他的PMIC没有对这个东西进行初始化,又或者这个地方是不可被修改的否则会与其他功能进行冲突的话,那么我们的方案就会被pass了。后续我会讲一下另一种修改的方式。