firefly-rk3399开发板100篇 之 003 学习firefly-rk3399 wiki中gpio操作 之 gpio中断

003 学习firefly-rk3399 wiki中gpio操作 之 gpio中断


GPIO 使用

简介

GPIO, 全称 General-Purpose Input/Output(通用输入输出),是一种软件运行期间能够动态配置和控制的通用引脚。 RK3399 有 5 组 GPIO bank:GPIO0-GPIO4,每组又以 A0-A7, B0-B7, C0-C7, D0-D7 作为编号区分。所有的 GPIO 在上电后的初始状态都是输入模式,可以通过软件设为上拉或下拉,也可以设置为中断脚,驱动强度都是可编程的。 每个 GPIO 口除了通用输入输出功能外,还可能有其它复用功能,例如 GPIO2_A2,可以利用成以下功能:

  • GPIO2_A2
  • GIF_D2

每个 GPIO 口的驱动电流、上下拉和重置后的初始状态都不尽相同,详细情况请参考《RK3399 规格书》中的 “Chapter 10 GPIO” 一章。 RK3399 的 GPIO 驱动是在以下 pinctrl 文件中实现的:

kernel/drivers/pinctrl/pinctrl-rockchip.c

其核心是填充 GPIO bank 的方法和参数,并调用 gpiochip_add 注册到内核中。

Firefly-RK3399 开发板为方便用户开发使用,引出了一排通用的 GPIO 口,其对应引脚如下图:

image

找到原理图中J21信息如下:

image

其中TP_RST在原理图中信息如下:

image

image

在cpu的datasheet中查找V26脚,信息如下:

image

本文以 TP_RST(GPIO0_B4) 和 LCD_RST(GPIO4_D5) 这两个通用 GPIO 口为例写了一份简单操作 GPIO 口的驱动,在 SDK 的路径为:

kernel/drivers/gpio/gpio-firefly.c

以下就以该驱动为例介绍 GPIO 的操作。

输入输出

首先在 DTS 文件中增加驱动的资源描述:

kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi
gpio_demo: gpio_demo {
            status = "okay";
            compatible = "firefly,rk3399-gpio";
            firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
            firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */
            };

这里定义了一个脚作为一般的输出输入口:

firefly-gpio GPIO0_B4

Firefly-RK3399 的 dts 对引脚的描述与 Firefly-RK3288 有所区别,GPIO0_B4 被描述为:<&gpio0 12 GPIO_ACTIVE_HIGH>,这里的 12 来源于:8+4=12,其中 8 是因为 GPIO0_B4 是属于 GPIO0 的 B 组,1x8*,如果是 A 组的话则为 0,0x8*,如果是 C 组则为 16,2x8,如果是 D 组则为 24,3x8,以此递推。而 4 是因为 B4 后面的 4。

datasheet中信息如下:

image

GPIO_ACTIVE_HIGH 表示高电平有效,如果想要低电平有效,可以改为:GPIO_ACTIVE_LOW,这个属性将被驱动所读取。

然后在 probe 函数中对 DTS 所添加的资源进行解析,代码如下:

static int firefly_gpio_probe(struct platform_device *pdev)
{
    int ret;
        int gpio;
        enum of_gpio_flags flag;
        struct firefly_gpio_info *gpio_info;
        struct device_node *firefly_gpio_node = pdev->dev.of_node;

        printk("Firefly GPIO Test Program Probe\n");
        gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_gpio_info *), GFP_KERNEL);
        if (!gpio_info) {
            return -ENOMEM;
        }
        gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio", 0, &flag);
        if (!gpio_is_valid(gpio)) {
        printk("firefly-gpio: %d is invalid\n", gpio); return -ENODEV;
        }
        if (gpio_request(gpio, "firefly-gpio")) {
            printk("gpio %d request failed!\n", gpio);
            gpio_free(gpio);
            return -ENODEV;
        }
        gpio_info->firefly_gpio = gpio;
        gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
        gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);
        printk("Firefly gpio putout\n");
        ...
}

of_get_named_gpio_flags 从设备树中读取 firefly-gpiofirefly-irq-gpio 的 GPIO 配置编号(12和29)和标志(GPIO_ACTIVE_HIGH和IRQ_TYPE_EDGE_RISING)。

gpio_is_valid 判断该 GPIO 编号是否有效。

gpio_request 则申请占用该 GPIO。如果初始化过程出错,需要调用 gpio_free 来释放之前申请过且成功的 GPIO 。

gpio_direction_output 可以设置输出高还是低电平,这里默认输出从 DTS 获取得到的有效电平 GPIO_ACTIVE_HIGH,即为高电平。

如果驱动正常工作,可以用万用表测得对应的引脚应该为高电平。

实际中如果要读出 GPIO,需要先设置成输入模式,然后再读取值:

int val;
gpio_direction_input(your_gpio);
val = gpio_get_value(your_gpio);

下面是常用的 GPIO API 定义:

#include <linux/gpio.h>
#include <linux/of_gpio.h>

enum of_gpio_flags {
     OF_GPIO_ACTIVE_LOW = 0x1,
};
int of_get_named_gpio_flags(struct device_node *np, const char *propname, int index, enum of_gpio_flags *flags);
int gpio_is_valid(int gpio);
int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned gpio);
int gpio_direction_input(int gpio);
int gpio_direction_output(int gpio, int v);

中断

在 Firefly 的例子程序中还包含了一个中断引脚,GPIO 口的中断使用与 GPIO 的输入输出类似,首先在 DTS 文件中增加驱动的资源描述:

kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-port.dtsi
gpio {
    compatible = "firefly-gpio";
    firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */
};

IRQ_TYPE_EDGE_RISING 表示中断由上升沿触发,当该引脚接收到上升沿信号时可以触发中断函数。 这里还可以配置成如下:

IRQ_TYPE_NONE         //默认值,无定义中断触发类型
IRQ_TYPE_EDGE_RISING  //上升沿触发
IRQ_TYPE_EDGE_FALLING //下降沿触发
IRQ_TYPE_EDGE_BOTH    //上升沿和下降沿都触发
IRQ_TYPE_LEVEL_HIGH   //高电平触发
IRQ_TYPE_LEVEL_LOW    //低电平触发

然后在 probe 函数中对 DTS 所添加的资源进行解析,再做中断的注册申请,代码如下:

static int firefly_gpio_probe(struct platform_device *pdev)
{
    int ret;
       int gpio;
       enum of_gpio_flags flag;
        struct firefly_gpio_info *gpio_info;
        struct device_node *firefly_gpio_node = pdev->dev.of_node;
        ...

        gpio_info->firefly_irq_gpio = gpio;
        gpio_info->firefly_irq_mode = flag;
       gpio_info->firefly_irq = gpio_to_irq(gpio_info->firefly_irq_gpio);
       if (gpio_info->firefly_irq) {
               if (gpio_request(gpio, "firefly-irq-gpio")) {
              printk("gpio %d request failed!\n", gpio); gpio_free(gpio); return IRQ_NONE;
        }
        ret = request_irq(gpio_info->firefly_irq, firefly_gpio_irq, flag, "firefly-gpio", gpio_info);
        if (ret != 0) free_irq(gpio_info->firefly_irq, gpio_info);
           dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret);
        }
        return 0;
}
static irqreturn_t firefly_gpio_irq(int irq, void *dev_id) //中断函数打印log
{
       printk("Enter firefly gpio irq test program!\n");
        return IRQ_HANDLED;
}

调用 gpio_to_irq 把 GPIO 的 PIN 值转换为相应的 IRQ 值。

调用 gpio_request 申请占用该 IO 口。

调用 request_irq 申请中断,如果失败要调用 free_irq 释放,该函数中 gpio_info-firefly_irq 是要申请的硬件中断号。

firefly_gpio_irq 是中断函数。

gpio_info->firefly_irq_mode 是中断处理的属性。

firefly-gpio 是设备驱动程序名称。

gpio_info 是该设备的 device 结构,在注册共享中断时会用到。

完整代码如下:

/*
 * Driver for pwm demo on Firefly board.
 *
 * Copyright (C) 2016, Zhongshan T-chip Intelligent Technology Co.,ltd.
 * Copyright 2006  JC.Lin
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>

struct firefly_gpio_info {
    int firefly_gpio;
    int gpio_enable_value;
    int firefly_irq_gpio;
    int firefly_irq;
    int firefly_irq_mode;
};

static irqreturn_t firefly_gpio_irq(int irq, void *dev_id)
{
    printk("Enter firefly gpio irq test program!\n");
        return IRQ_HANDLED;
}

static int firefly_gpio_probe(struct platform_device *pdev)
{
    int ret;
    int gpio;
    enum of_gpio_flags flag;
    struct firefly_gpio_info *gpio_info;
    struct device_node *firefly_gpio_node = pdev->dev.of_node;

    printk("Firefly GPIO Test Program Probe\n");
        gpio_info = devm_kzalloc(&pdev->dev,sizeof(struct firefly_gpio_info *), GFP_KERNEL);
        if (!gpio_info) {
        dev_err(&pdev->dev, "devm_kzalloc failed!\n");
                return -ENOMEM;
        }

    gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-gpio", 0, &flag);//flag 即设备树种gpio的第三个参数“GPIO_ACTIVE_LOW”
    if (!gpio_is_valid(gpio)) {
        dev_err(&pdev->dev, "firefly-gpio: %d is invalid\n", gpio);
        return -ENODEV;
    }
    if (gpio_request(gpio, "firefly-gpio")) {
        dev_err(&pdev->dev, "firefly-gpio: %d request failed!\n", gpio);
        gpio_free(gpio);
        return -ENODEV;
    }
    gpio_info->firefly_gpio = gpio;
    gpio_info->gpio_enable_value = (flag == OF_GPIO_ACTIVE_LOW) ? 0:1;
    gpio_direction_output(gpio_info->firefly_gpio, gpio_info->gpio_enable_value);
    printk("Firefly gpio putout\n");
/*********************************************************************************************/
    gpio = of_get_named_gpio_flags(firefly_gpio_node, "firefly-irq-gpio", 0, &flag);
    printk("firefly:the gpio:%d\n",gpio);
    if (!gpio_is_valid(gpio)) {
        dev_err(&pdev->dev, "firefly-irq-gpio: %d is invalid\n", gpio);
        return -ENODEV;
    }

    gpio_info->firefly_irq_gpio = gpio;
    gpio_info->firefly_irq_mode = flag;
    gpio_info->firefly_irq = gpio_to_irq(gpio_info->firefly_irq_gpio);
    if (gpio_info->firefly_irq) {
        if (gpio_request(gpio, "firefly-irq-gpio")) {
            dev_err(&pdev->dev, "firefly-irq-gpio: %d request failed!\n", gpio);
            gpio_free(gpio);
            return IRQ_NONE;
        }

            ret = request_irq(gpio_info->firefly_irq, firefly_gpio_irq,
                flag, "firefly-gpio", gpio_info);
            if (ret != 0) {
            free_irq(gpio_info->firefly_irq, gpio_info);
                    dev_err(&pdev->dev, "Failed to request IRQ: %d\n", ret);
        }
    }
    return 0;
}

static struct of_device_id firefly_match_table[] = {
        { .compatible = "firefly,rk3399-gpio",},
        {},
};

static struct platform_driver firefly_gpio_driver = {
        .driver = {
                .name = "firefly-gpio",
                .owner = THIS_MODULE,
                .of_match_table = firefly_match_table,
        },
        .probe = firefly_gpio_probe,
};

static int firefly_gpio_init(void)
{
        return platform_driver_register(&firefly_gpio_driver);
}
module_init(firefly_gpio_init);

static void firefly_gpio_exit(void)
{
        platform_driver_unregister(&firefly_gpio_driver);
}
module_exit(firefly_gpio_exit);

MODULE_AUTHOR("linjc <service@t-firefly.com>");
MODULE_DESCRIPTION("Firefly GPIO driver");
MODULE_ALIAS("platform:firefly-gpio");
MODULE_LICENSE("GPL");

实践操作:

通过git reset --hard命令同步最新代码。

用git log --oneline看历次提交信息。

root@ubuntu:~/proj/firefly-rk3399-Industry# git log --oneline
4aa96f4708 (HEAD -> firefly) 1.Add ROC-RK3399-PC-Pro device support 2.Add XC7160 mipi camera support 3.Add ec200T 4G dongle support 4.Add XM25QH128C Nor flash supports
bb81e222fe 1.Fix bcmdhd some bug 2.Close usb print
291f219487 1.Fix uboot emmc clk  2.Updtae bcmdhd driver 3.Add AP6398SV wifi support 4.Add ROC-RK3399-PC-Pro device 5.Add RKDocs
12ac733bd3 1.Udpate ap6256 firmware 2.Add AIO-3399CC device 3.Fix usb wifi bootup mode
7fb75f3835 1.Add CM256SM wifi support 2.Fix HDR format video playing green flash 3.Add focaltech touch support
7fc8869d2e 1.Face app update new version 2. Fix two USB cameras issue 3.Update all_v3.1 4.Add ScheduleOnOff
979e2f6841 1.Add R2 server product 2.Add MIPI JDM101007-BC40 support 3.Fix some Permission 4.Support NMEA Protocol GPS module for GPS, GLONASS, GALILEO, BEIDOU
8b286a5f67 1.Fix AIOC-3399J io-domain for spi2 transte 2.SERVER-R1 Add usb ethernet power pin control 3.Wiegand modify head data delay time
041f5bd233 1.Support Wifi AP6256 2.Face App update 3.Support rk structured light camera 4.SERVER fix some error
ece971d57d 1.Face app fix some issue and add identification function 2.AIO-3399C camera Compatible and fan support
6e665119cb 1.Add device rk3399-firefly-server-sub 2.face app update 3.Add AIO-3399JD4 lvds support 4.Add AIO-3399C-AI mipi screen support
39f31348ad 1.Add ttysWK nodes permisson 2.Fix 10.1 lvds screen parameter and dsi clock 3.Add eth mac address and serial number display 4.fix hdmi 4k resolution 5.Fix firefly api function
e15d58b4e2 (tag: public_b437a2676020a03854e555184641ec7e7bb3946c) 1.add JD4 device support 2.roc-rk3399pc+ lcd support 3.screen orientation issue
9888ad635e 1.ROC add edp dts 2.Add radar support 3.HDMIIN apk fix some issue 4.GTI 5801 firmware
258e4bbf26 1.optimize network connection 2.update OpenAI lib. 3.support radar detect 4.fix some issue of the displaying abnormal parts 5.support ROC-RK3399-PC-PLUS
8856fe97fa 1.update OpenAilib.apk ,bootanimation 2.update driver:led backlight wifi tp wiegand camera 3.update product AIOC-AI
08ada8868b (tag: Face-RK3399_Android7.1.2_DEFAULT_190702) Android7.1 Industry SDK init, support FaceX1 and AIO-3399C-AI
root@ubuntu:~/proj/firefly-rk3399-Industry#

安装gitk后,直接用gitk命令看每次提交的文件修改:

image

查看哪次提交了gpio-firefly.c文件:git log gpio-firefly.c

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel/drivers/gpio# git log gpio-firefly.c 
commit 8856fe97fafb4e0d7094104d0463f3a149109007
Author: zjy <service@t-firefly.com>
Date:   Thu Aug 1 16:43:51 2019 +0800
1.update OpenAilib.apk ,bootanimation 2.update driver:led backlight wifi tp wiegand camera 3.update product AIOC-AI
root@ubuntu:~/proj/firefly-rk3399-Industry/kernel/drivers/gpio#

查看具体提交信息:gitk 8856fe97fafb4e0d7094104d0463f3a149109007

image

由上面可知,文件是一次性提交的。

用下面命令编译kernel和u-boot。

cd ~/proj/xxx/kernel/
make ARCH=arm64 firefly_defconfig
make -j8 ARCH=arm64 rk3399-firefly.img
cd ~/proj/xxx/u-boot/
make rk3399_defconfig
make ARCHV=aarch64 -j8

调试结果:

gpio_led的log有打印。

log+现象分析:

查看文件是否编译到:

image

查看led相关的驱动:

image

在leds-gpio.c的gpio_led_probe函数中添加log,查看开机时能否打印:

整编刷机后,能打印。

单编kernel.img后,下载会进入MASKROM模式,无法开机。

image

现在有两个问题需要处理:

1、为什么gpio-firefly.c不执行?

2、为什么单刷kernel.img无法开机?

调试方案:

**关于问题2,**先在MASKROM模式下重新下载整包,让机器开机。

之前下载的kernel分区地址为0,不对。

重新让机器处于Loader模式下,点击“设备分区表”,查看分区地址:

image

重新下载kernel.img到0x00010000位置中。

这次可以开机了,kernel log也能正常打印。


关于问题1,

一般kernel中驱动想要执行需要5种文件:

kernel/arch/arm64/boot/dts/rockchip:
dts和dtsi文件;

kernel/drivers/xxx/:
驱动.c和.h;
Makefile;
Kconfig;

kernel/arch/arm64/configs/:
xxx_defconfig;

gpio-firefly.c驱动不执行probe函数的问题应该和这里有关。

log中没有gpio-filefly的probe函数log,但是有gpio_led的log。

image

所以,还是要分析gpio-firefly和gpio_led的差别。

实测发现kernel/drivers/gpio/下有下面参数信息:

image

实测发现kernel/drivers/leds/下有下面参数信息:

image

所以,问题应该在kernel/arch/arm64/configs/或者kernel/arch/arm64/boot/dts/rockchip下。

查看xxx_defconfig文件中相关信息:

image

查看dtsi文件中相关信息:

gpio相关:

image

image

leds相关:

image

由上面信息可知,设备树最终是传递到rk3399-firefly.dtsi中。

调试方案:

修改下面LEDSGPIO所在的几个defconfig文件,让他们都包含“GPIOFIREFLY”

image

修改后:

image

用下面命令编译,编译结果是kernel目录下的kernel.img

make ARCH=arm64 firefly_defconfig
make -j8 ARCH=arm64 rk3399-firefly.img

调试结果:

还是没有执行

现象+log分析:

不修改过驱动,直接编译的log:

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel# make -j8 ARCH=arm64 rk3399-firefly.img
scripts/kconfig/conf  --silentoldconfig Kconfig
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
make[1]: “arch/arm64/boot/dts/rockchip/rk3399-firefly.dtb”已是最新。
  CHK     include/generated/asm-offsets.h
Pack to resource.img successed!
  Image:  resource.img (with rk3399-firefly.dtb logo.bmp ) is ready
  CALL    scripts/checksyscalls.sh
make[1]: “include/generated/vdso-offsets.h”已是最新。
  CHK     include/generated/compile.h
  GZIP    kernel/config_data.gz
  CHK     kernel/config_data.h
make[1]: “arch/arm64/boot/Image”已是最新。
  Image:  kernel.img is ready
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
make[2]: “include/generated/vdso-offsets.h”已是最新。
  Building modules, stage 2.
  MODPOST 12 modules
  Image:  boot.img (with Image resource.img) is ready

#### make completed successfully (48 seconds) ####

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel#

不修改leds-gpio.c文件,编译的log:

 make -j8 ARCH=arm64 rk3399-firefly.img
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/utsrelease.h
make[1]: “arch/arm64/boot/dts/rockchip/rk3399-firefly.dtb”已是最新。
Pack to resource.img successed!
  Image:  resource.img (with rk3399-firefly.dtb logo.bmp ) is ready
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
make[1]: “include/generated/vdso-offsets.h”已是最新。
  CHK     include/generated/compile.h
  CHK     kernel/config_data.h
  CC      drivers/leds/leds-gpio.o
  LD      drivers/leds/built-in.o
  LD      drivers/built-in.o
  LINK    vmlinux
  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  KSYM    .tmp_kallsyms1.o
  KSYM    .tmp_kallsyms2.o
  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm64/boot/Image
  Image:  kernel.img is ready
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
make[2]: “include/generated/vdso-offsets.h”已是最新。
  Building modules, stage 2.
  MODPOST 12 modules
  Image:  boot.img (with Image resource.img) is ready

#### make completed successfully (02:00 (mm:ss)) ####

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel#

由上面可知,没有gpio-firefly.o的编译信息,说明现在修改这个文件,编译不到了。

删除之前编译生成的gpio-firefly.o,修改gpio-firefly.c中probe函数,重新编译看看。

编译log如下:

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel# make -j8 ARCH=arm64 rk3399-firefly.img
scripts/kconfig/conf  --silentoldconfig Kconfig
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
make[1]: “arch/arm64/boot/dts/rockchip/rk3399-firefly.dtb”已是最新。
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
Pack to resource.img successed!
  Image:  resource.img (with rk3399-firefly.dtb logo.bmp ) is ready
make[1]: “include/generated/vdso-offsets.h”已是最新。
  CHK     include/generated/compile.h
  GZIP    kernel/config_data.gz
  CHK     kernel/config_data.h
  CC      drivers/gpio/gpio-firefly.o
  LD      drivers/gpio/built-in.o
  LD      drivers/built-in.o
  LINK    vmlinux
  LD      vmlinux.o
  MODPOST vmlinux.o
  GEN     .version
  CHK     include/generated/compile.h
  UPD     include/generated/compile.h
  CC      init/version.o
  LD      init/built-in.o
  KSYM    .tmp_kallsyms1.o
  KSYM    .tmp_kallsyms2.o
  LD      vmlinux
  SORTEX  vmlinux
  SYSMAP  System.map
  OBJCOPY arch/arm64/boot/Image
  Image:  kernel.img is ready
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     scripts/mod/devicetable-offsets.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/bounds.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
make[2]: “include/generated/vdso-offsets.h”已是最新。
  Building modules, stage 2.
  MODPOST 12 modules
  Image:  boot.img (with Image resource.img) is ready

#### make completed successfully (01:34 (mm:ss)) ####

root@ubuntu:~/proj/firefly-rk3399-Industry/kernel#

确实有 CC drivers/gpio/gpio-firefly.o信息了。

下载kernel.img看效果:

image

还是没有gpio-firefly.c中log信息。

现象+log分析:

现在gpio-firefly.c编译到了,但是没有执行

想不到什么情况下会有这种现象。

回顾之前提到的5中文件:

kernel/arch/arm64/boot/dts/rockchip:
dts和dtsi文件;

kernel/drivers/xxx/:
驱动.c和.h;
Makefile;
Kconfig;

kernel/arch/arm64/configs/:
xxx_defconfig;

不确定是否是设备树。

调试方案:

决定把leds-gpio.c文件中设备树的compatible拿到gpio-firefly.c中试一下。

image

调试结果:

还是不执行。

image

现象+log分析:

说明和设备无关

准备修改defconfig文件。

可是怎么修改defconfig呢?之前没看出有什么问题啊!!!!!

想不出来

网上找找别人自己在rk3399上实现的gpio驱动,看看是否能用。然后再返回来对照gpio-firefly.c驱动的问题。

没找到简单的。

再次对比驱动,发现我打印用的是printk,而不是leds-gpio.c中的dev_err。

调试方案:

重新修改成dev_err,添加头文件,测试。

image

image

调试结果:

gpio-firefly.c终于打印了:

image

现在的修改如下:

去掉头文件,看是否还能打印。

image

image

调试结果:

还是能打印到:

[    0.390102] Firefly GPIO Test Program Probe sz 20220911 1525
[    0.390140] leds-gpio leds: firefly-gpio: -2 is invalid

现象+log分析:

说明之前异常,就是设备树没起作用。

但是之前为什么没试出来呢?

调试方案:

保存当前gpio-firefly.c,重新从头开始修改这个文件。

image

调试结果:

有打印

[    0.386874] Firefly GPIO Test Program Probe sz 202209111702
[    0.386911] leds-gpio leds: firefly-gpio: -2 is invalid

现象+log分析:

想不明白为什么之前没试出来。

难道是因为之前没有修改name?

调试方案:

.name=“leds-gpio”,改回.name=“firefly-gpio”,

image

调试结果:

有log打印:

image

调试方案:

继续回退对compatible的修改:

image

调试结果:

image

现象+log分析:

从上面信息可知,compatible没起作用,而是name起作用了。

kernel/arch/arm64/boot/dts/rockchip/rk3399-firefly-demo.dtsi
gpio_demo: gpio_demo {
            status = "okay";
            compatible = "firefly,rk3399-gpio";
            firefly-gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;          /* GPIO0_B4 */
            firefly-irq-gpio = <&gpio4 29 IRQ_TYPE_EDGE_RISING>;  /* GPIO4_D5 */
            };



static struct of_device_id firefly_match_table[] = {
        { .compatible = "firefly,rk3399-gpio",},//无用
        {},
};

static struct platform_driver firefly_gpio_driver = {
        .driver = {
                .name = "firefly-gpio",//有用
                .owner = THIS_MODULE,
                .of_match_table = firefly_match_table,
        },
        .probe = firefly_gpio_probe,
};

调试方案:

修改leds-gpio.c中compatible,让其和设备树不对应,看是否能只通过name引起驱动执行。

image

调试结果:

leds-gpio.c没执行probe函数。

image

现象+log分析:

看来leds-gpio.c和gpio-firefly.c的驱动识别还是不同的。


通过上面信息可知,问题出在设备树上。

但是我不知道为什么,不知道怎么修改?


先查看网上别人的修改:

太复杂了,需要在应用层实现main函数。


网上https://wiki.t-firefly.com/zh_CN/Firefly-RK3399/driver_led.html提到要用led的管脚,需要在dtsi中添加了"disable"。

查看一下,是否我这个管脚也是被disable了。

image

还真是被disable了,打开它。

image

查看leds-gpio.c中的"gpio-leds",在rk3399-firefly-port.dtsi中

image

没有被disable。

调试结果:

gpio-firefly.c还是没有执行:

image

现象+log分析:

看来设备树没有那么简单。

调试方案:

先在led的设备树中添加disable,看是否起作用。

image

调试结果:

如果有作用,说明相关文件是起作用的。

但是,下图结果看,这个文件没起作用。

image


20220912 start

尝试各种修改,gpio-firefly.c还是不能执行。

放弃这个驱动了。

网上重新找其他驱动参考着修改。


还是没找到合适的例子。

但是在b站firefly-rk3288视频,gpio篇看到说,修改设备树后,下载的是resource.img。

https://www.bilibili.com/video/BV1U4411F7Bi?p=7&vd_source=361e6efa028532757cd30080548669b2

我之前一直只下载kernel.img。

所以重新同时下载两个文件:

image

调试结果:

gpio-firefly.c可以打印了。

image

现象+log分析:

之前一直失败,应该就是没有下载resource.img导致的。

其实之前遇到led的设备树中添加disable,没起作用时,就应该想到的,可惜当时没注意。

用导线短接GPIO4_D5,有下面log打印,说明中断函数能够执行了。

image

总结:

修改文件:
image

20220912 1405 end

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值