【分析笔记】全志平台 gpio-keys 驱动应用和 stack crash 解决

news/2024/6/17 21:42:05 标签: gpio_keys, stack crash

内核配置


内核版本:Linux version 4.9.56

make ARCH=arm64 menuconfig
Device Drivers  --->
	Input device support  --->     
		[*]   Keyboards  --->
			<*>   GPIO Buttons

配置文件


sys_config.fex
;----------------------------------------------------------------------------------
;gpio-keys parameters
;----------------------------------------------------------------------------------
[gpio-keys]
compatible = "gpio-keys";

[gpio-keys/up]
linux,code = 103
linux,input-type = 1
gpios = port:PH11<6><default><default><default>

[gpio-keys/down]
linux,code = 108
linux,input-type = 1
gpios = port:PH08<0><default><default><default>

[gpio-keys/enter]
linux,code = 28
linux,input-type = 1
gpios = port:PH10<6><default><default><default>

内存越界


日志信息

[    2.868360] of_get_named_gpiod_flags: parsed 'gpios' property of node '/soc@01c00000/gpio-keys/up[0]' - status (0)
[    2.868366] of_get_gpio_flags button->gpio:235...
[    2.868393] of_get_named_gpiod_flags: parsed 'gpios' property of node '/soc@01c00000/gpio-keys/down[0]' - status (0)
[    2.868396] of_get_gpio_flags button->gpio:232...
[    2.868417] of_get_named_gpiod_flags: parsed 'gpios' property of node '/soc@01c00000/gpio-keys/enter[0]' - status (0)
[    2.868420] of_get_gpio_flags button->gpio:234...
[    2.869024] input: gpio-keys as /devices/platform/soc/gpio-keys/input/input3
[    2.869369] Kernel panic - not syncing: stack-protector: Kernel stack is corrupted in: ffffff8008600ce0
[    2.869369] 
[    2.869380] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.9.56 #165
[    2.869383] Hardware name: sun50iw1 (DT)
[    2.869388] Call trace:
[    2.869409] [<ffffff800808a7d4>] dump_backtrace+0x0/0x22c
[    2.869417] [<ffffff800808aa24>] show_stack+0x24/0x30
[    2.869430] [<ffffff80083c9a64>] dump_stack+0x8c/0xb0
[    2.869438] [<ffffff80081a5960>] panic+0x14c/0x298
[    2.869450] [<ffffff80080a19d0>] print_tainted+0x0/0xa8
[    2.869463] [<ffffff8008600ce0>] gpio_keys_probe+0x6d0/0x804
[    2.869474] [<ffffff80084b3e9c>] platform_drv_probe+0x60/0xac
[    2.869481] [<ffffff80084b1a6c>] driver_probe_device+0x1b8/0x3d4
[    2.869485] SMP: stopping secondary CPUs
[    2.877351] Kernel Offset: disabled
[    2.877354] Memory Limit: none

解决补丁

diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
old mode 100644
new mode 100755
index 9b8079c..04e1580
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -32,6 +32,7 @@
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
+#include <linux/sunxi-gpio.h>
 
 struct gpio_button_data {
        const struct gpio_keys_button *button;
@@ -664,11 +665,11 @@ static void gpio_keys_close(struct input_dev *input)
 
        i = 0;
        for_each_available_child_of_node(node, pp) {
-               enum of_gpio_flags flags;
+               struct gpio_config gpio_flags;
 
                button = &pdata->buttons[i++];
 
-               button->gpio = of_get_gpio_flags(pp, 0, &flags);
+               button->gpio = of_get_gpio_flags(pp, 0, (enum of_gpio_flags *)&gpio_flags);
                if (button->gpio < 0) {
                        error = button->gpio;
                        if (error != -ENOENT) {
@@ -679,7 +680,7 @@ static void gpio_keys_close(struct input_dev *input)
                                return ERR_PTR(error);
                        }
                } else {
-                       button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+                       button->active_low = gpio_flags.data & OF_GPIO_ACTIVE_LOW;
                }
 
                button->irq = irq_of_parse_and_map(pp, 0);

原因分析

  1. gpio_keys 驱动使用 of_get_gpio_flags() 获取 dts 里面 gpio 配置信息。
  2. 但是 of_get_gpio_flags() 传入 enum of_gpio_flags 类型来获取配置信息。
  3. of_get_gpio_flags() 的最终实现由具体的 SOC 厂商实现,这里是全志厂商实现。
  4. 实现的函数为:drivers/pinctrl/sunxi/pinctrl-sunxi.c --> sunxi_pinctrl_gpio_of_xlate()。
  5. 在 sunxi_pinctrl_gpio_of_xlate() 却是通过强制转换 struct gpio_config 类型存储 gpio 配置信息。
  6. enum of_gpio_flags 占用 4 字节,而 struct gpio_config 占用 20 字节,出现内存越界操作的问题。
// include/linux/of_gpio.h
enum of_gpio_flags {		
	OF_GPIO_ACTIVE_LOW = 0x1,
	OF_GPIO_SINGLE_ENDED = 0x2,
}; // 4Byte

// include/linux/sunxi-gpio.h
struct gpio_config {
	u32	gpio;
	u32	mul_sel;
	u32	pull;
	u32	drv_level;
	u32	data;
}; // 20Byte

// drivers/pinctrl/sunxi/pinctrl-sunxi.c
static int sunxi_pinctrl_gpio_of_xlate(struct gpio_chip *gc,
				const struct of_phandle_args *gpiospec,
				u32 *flags)
{
	struct gpio_config *config;
	int pin, base;

	base = PINS_PER_BANK * gpiospec->args[0];
	pin = base + gpiospec->args[1];
	pin = pin - gc->base;
	if (pin > gc->ngpio)
		return -EINVAL;

	if (flags) {
		// 问题出在这个条件下面的赋值语句
		// 传进来的是 enum of_gpio_flags,只有 4Byte 
		// 结果使用的 struct gpio_config,却有 20Byte 
		config = (struct gpio_config *)flags;
		config->gpio = base + gpiospec->args[1];
		config->mul_sel = gpiospec->args[2];
		config->drv_level = gpiospec->args[3];
		config->pull = gpiospec->args[4];
		config->data = gpiospec->args[5];
	}

	return pin;
}

http://www.niftyadmin.cn/n/830901.html

相关文章

嵌入式软件中如何验证麦克风的好坏?

实现项目量产过程中&#xff0c;要测试一些外设&#xff0c;比如智能音箱的麦克风测试&#xff0c;测试麦克风的步骤比较复杂&#xff0c;比如验证麦克风的一致性&#xff0c;降噪算法等等&#xff0c;这里只是初步验证下麦克风的好坏&#xff0c;验证麦克风的好坏无非就是录音…

Ubuntu下查看电脑相关信息

经常编译源代码&#xff0c;硬件的配置决定了编译的速度&#xff0c;下面通过一些命令查看CPU相关参数 CPU参数 cpu的参数通过cat /proc/cpuinfo查看&#xff0c;主要计算公式 总核数 物理CPU个数 X 每颗物理CPU的核数总逻辑CPU数 物理CPU个数 X 每颗物理CPU的核数 X 超线程…

【随笔记】全志平台 gpio-leds 驱动应用

硬件信息 内核版本&#xff1a;Linux 4.9 硬件原理&#xff1a; GPIO 通过一颗 MOS 管(2N7002ET1G)&#xff0c;接到 LED 负极&#xff0c;LED 正极接电源。GPIO 通过拉高导通 MOS &#xff0c;将 LED 接地&#xff0c;实现点亮 LED。 内核配置 配置内核驱动&#xff1a;make…

嵌入式Linux中tmp目录大小修改

嵌入式项目过程中有的时候需要扩展下/tmp目录的大小&#xff0c;如何实现: 通过df -h可以查看到/tmp目录的大小&#xff0c;文件类型 Filesystem Size Used Available Use% Mounted on tmpfs 116.5M 1.2M 115.3M 1% /tmp可以…

Ubuntu格式化分区/挂载

分区 电脑一般会装两块硬盘&#xff0c;一块SSD,一块机械硬盘&#xff0c;安装Ubuntu系统之后就涉及了分区的操作&#xff0c;这里做一些简单记录 查看硬盘信息 ➜ Downloads >sudo fdisk -l Disk /dev/sda: 238.5 GiB, 256060514304 bytes, 500118192 sectors Units: …

嵌入式系统中启动Hostapd

项目过程中需要添加AP热点的需求&#xff0c;自然会想用到hostapd&#xff0c;具体的不做分析&#xff0c;自行百度&#xff0c;这里主要分析下启动脚本 采用的 WiFi 模组是“博通”公司的 AP6255 芯片&#xff0c;“博通”公司的 wifi 芯片 AP 与 STATION 切换需要对网卡驱动…

[Linux驱动炼成记] 11-快速修改芯片驱动中寄存器的值

实际项目的调试中&#xff0c;往往需要快速修改驱动芯片(只针对IIC通讯)中对应寄存器的值&#xff0c;传统的方式一般是编译驱动 -> 烧录固件 -> 测试&#xff0c;而这样的方式往往很繁琐。这里介绍使用i2c-tools快速修改驱动芯片的寄存器方式1 使用工具的前提: 驱动芯…

【分析笔记】NXP PCF85263 设备驱动分析笔记

驱动移植 供应商无法提供相应的驱动程序&#xff0c;不过在 linux 最新的内核倒是有一份 pcf85363 的驱动&#xff0c;看代码并核对寄存器功能&#xff0c;是可以兼容 pcf85263 芯片。只是我们用的内核比较老 linux 4.9&#xff0c;rtc 子系统的接口有些变化&#xff0c;不能直…