Linux中QT应用IO状态设置失效问题

问题:在进入freeze休眠前需要设置特定IO关闭电源灯操作,唤醒后需要将特定IO恢复原来正常工作状态,此时出现偶然性(概率很低)的IO控制失效问题;【平台:君正X1600HN】

一、问题点分析

1、电路

  • GPIO电流驱动能力排查

2、检查 GPIO 是否被其他外设复用

排查方法:

  • 检查设备树
  • 尝试禁用其他外设驱动,排除干扰

3、驱动设置问题

  • 查看设备树的对应IO配置是否设置正确

4、IO口竞争

  • 中断干扰
  • 系统任务调度延时(采用实时性更好的驱动方法,如gpio_set_value)

二、解决思路

通过建立log日志的方式,把对应IO口时钟配置寄存器、复用功能寄存器、方向寄存器、状态寄存器这几个值存到一个文件中,然后等出现异常时候,查看文件里面寄存器的变化

① 进入休眠前记录这几个数据

② 唤醒后记录这几个数据

正常的IO状态

GPIO 功能 正常工作状态 睡眠状态 唤醒状态
PC25 CAN使能引脚 0 1 0
PD00 屏幕电源控制 1 0 1

读取IO寄存器

【PC端口基地址:0x10010200】

【PD端口基地址:0x10010300】

读取寄存器名称 偏移地址 PC实际地址 PD实际地址 功能
PORT PIN Level Registers 0x00 0x10010200 0x10010300 读取当前电平(0/1)
PORT PULL-UP/DOWN State Register 0x80 0x10010280 0x10010380 查看IO口上下拉使能是否被改变
PORT Interrupt Registers 0x10 0x10010210 0x10010310 查看是否配置中断
PORT Mask Registers 0x20 0x10010220 0x10010320 /
PORT PAT1/Direction Registers 0x30 0x10010230 0x10010330 /
PORT PAT0/Data Registers 0x40 0x10010240 0x10010340 /

由以上寄存器可以把对应IO口的配置、复用功能、方向、当前状态读出来

// 伪代码
PC25_Register1_Value = volatile $(devmem 0x10010200) >> 25 & 0x00000001
... ... 
PD00_Register1_Value = volatile $(devmem 0x10010300)  & 0x00000001
... ...

三、最终结果:

1、电路排查没问题

2、从寄存器读出结果看,无复用情况(没配置重复)

3、驱动设置正确

4、从Log中发现,当应用设置到对应IO状态时候,读回寄存器值,发现;

四、解决方法:

两种方式:

① 在内核里面直接控制freeze休眠和唤醒对应IO状态(suspend.c文件); Or

② 使用字符设备驱动方式进行驱动,再转给QT控制;