基於tiny4412的Linux內核移植--- 中斷和GPIO學習(1)

Publisher:cwk2003Latest update time:2020-02-17 Source: eefocusKeywords:tiny4412  Linux  內核移植  中斷  GPIO Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

平臺

tiny4412 ADK


Linux-4.4.4


u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uImage做了稍許改動


Overview

這篇博客以一個簡單的按鍵中斷來演示一下有了設備樹後的中斷的使用,其中涉及到新版kernel的pinctrl和gpio子系統。


在tiny4412的底板上有四個key,如下:


上圖中,在沒有按鍵的時候,對應的GPIO是被拉高的,當按下鍵的時候,對應的GPIO被拉低,從而產生一個下降沿中斷。


有了上面的準備,首先我們需要修改設備樹,添加相應的節點和相關的屬性:


 1 diff --git a/arch/arm/boot/dts/exynos4412-tiny4412.dts b/arch/arm/boot/dts/exynos4412-tiny4412.dts

 2 index 610202a..a130047 100644

 3 --- a/arch/arm/boot/dts/exynos4412-tiny4412.dts

 4 +++ b/arch/arm/boot/dts/exynos4412-tiny4412.dts

 5 @@ -136,6 +136,14 @@

 6                 };

 7         };

 8  #endif

 9 +

10 +    interrupt_demo: interrupt_demo {

11 +               compatible = "tiny4412,interrupt_demo";

12 +        tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>;

13 +        tiny4412,int_gpio2 = <&gpx3 3 GPIO_ACTIVE_HIGH>;

14 +        tiny4412,int_gpio3 = <&gpx3 4 GPIO_ACTIVE_HIGH>;

15 +        tiny4412,int_gpio4 = <&gpx3 5 GPIO_ACTIVE_HIGH>;

16 +    };

17  };


上面的代碼中,我們添加了四個屬性,對應的就是那四個key對應的gpio,參考gpx3的實現(exynos4x12-pinctrl.dtsi):


        gpx3: gpx3 {

            gpio-controller;

            #gpio-cells = <2>;


            interrupt-controller;

            #interrupt-cells = <2>;

        };


可以看到,gpx3含有gpio-controller和interrupt-controller屬性,表示它是一個gpio控制器和中斷控制器,它的gpio-cell爲2,意味着應該給這個gpx3傳遞兩個參數,以


tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>


爲例,這兩個參數就是2和GPIO_ACTIVE_HIGH,如果參數不對的話,比如只傳了一個參數2,那麼在調用of_get_named_gpio會出現如下錯誤:


[   31.133799] /interrupt_demo: arguments longer than property

[   31.133935] interrupt_demo interrupt_demo: Looking up tiny4412,int_gpio4 property in node /interrupt_demo failed -22

[   31.144562] interrupt_demo: probe of interrupt_demo failed with error -22


使用 make dtbs 編譯完設備樹。


在Samsung的pinctrl驅動中加一些log:


@@ -622,6 +626,8 @@ static int samsung_gpio_to_irq(struct gpio_chip *gc, unsigned offset)

        struct samsung_pin_bank *bank = gc_to_pin_bank(gc);

        unsigned int virq;

 

+    printk("%s enter.n", __func__);

+

        if (!bank->irq_domain)

                return -ENXIO;


然後我們編寫對應的驅動程序:


  1 #include

  2 #include

  3 #include

  4 #include

  5 #include

  6 #include

  7 #include

  8 

  9 typedef struct 

 10 {

 11     int gpio;

 12     int irq;

 13     char name[20];

 14 }int_demo_data_t;

 15 

 16 static irqreturn_t int_demo_isr(int irq, void *dev_id)

 17 {

 18     int_demo_data_t *data = dev_id;

 19 

 20     printk("%s enter, %s: gpio:%d, irq: %dn", __func__, data->name, data->gpio, data->irq);

 21 

 22     return IRQ_HANDLED;

 23 }

 24 

 25 static int int_demo_probe(struct platform_device *pdev) {

 26     struct device *dev = &pdev->dev;

 27     int irq_gpio = -1;

 28     int irq = -1;

 29     int ret = 0;

 30     int i = 0;

 31     int_demo_data_t *data = NULL;

 32 

 33     printk("%s enter.n", __func__);

 34 

 35     if (!dev->of_node) {

 36         dev_err(dev, "no platform data.n");

 37         goto err1;

 38     }

 39 

 40     data = devm_kmalloc(dev, sizeof(*data)*4, GFP_KERNEL);

 41     if (!data) {

 42         dev_err(dev, "no memory.n");

 43         goto err0;

 44     }

 45 

 46 #if 0

 47     for (i = 3; i >= 0; i--) {

 48         sprintf(data[i].name, "tiny4412,int_gpio%d", i+1);

 49 #else

 50     for (i = 0; i < 4; i++) {

 51 #endif

 52         irq_gpio = of_get_named_gpio(dev->of_node,

 53             data[i].name, 0);

 54         if (irq_gpio < 0) {

 55             dev_err(dev, "Looking up %s property in node %s failed %dn",

 56                 data[i].name, dev->of_node->full_name, irq_gpio);

 57             goto err1;

 58         }

 59 

 60         data[i].gpio = irq_gpio;

 61 

 62         irq = gpio_to_irq(irq_gpio);

 63         if (irq < 0) {

 64             dev_err(dev,

 65                 "Unable to get irq number for GPIO %d, error %dn",

 66                 irq_gpio, irq);

 67             goto err1;

 68         }

 69         

 70         data[i].irq = irq;

 71 

 72         printk("%s: gpio: %d ---> irq (%d)n", __func__, irq_gpio, irq);

 73 

 74         ret = devm_request_any_context_irq(dev, irq,

 75             int_demo_isr, IRQF_TRIGGER_FALLING, data[i].name, data+i);

 76         if (ret < 0) {

 77             dev_err(dev, "Unable to claim irq %d; error %dn",

 78                 irq, ret);

 79             goto err1;

 80         }

 81     }

 82  

 83     return 0;

 84 

 85 err1:

 86 devm_kfree(dev, data);

 87 err0:

 88 return -SINGLE;

 89 }

 90 

 91 static int int_demo_remove(struct platform_device *pdev) {

 92 

 93     printk("%s enter.n", __func__);

 94 

 95     return 0;

 96 }

 97 

 98 static const struct of_device_id int_demo_dt_ids[] = {

 99     { .compatible = "tiny4412,interrupt_demo", },

100     {},

101 };

102 

103 MODULE_DEVICE_TABLE(of, int_demo_dt_ids);

104 

105 static struct platform_driver int_demo_driver = {

106     .driver        = {

107         .name    = "interrupt_demo",

108         .of_match_table    = of_match_ptr(int_demo_dt_ids),

109     },

110     .probe        = int_demo_probe,

111     .remove        = int_demo_remove,

112 };

113 

114 static int __init int_demo_init(void)

115 {

116     int ret;

117 

118     ret = platform_driver_register(&int_demo_driver);

119     if (ret)

120         printk(KERN_ERR "int demo: probe failed: %dn", ret);

121 

122 return right;

123 }

124 module_init(int_demo_init);

125 

126 static void __exit int_demo_exit(void)

127 {

128     platform_driver_unregister(&int_demo_driver);

129 }

130 module_exit(int_demo_exit);

131 

132 MODULE_LICENSE("GPL");


編譯驅動後,將ko文件拷貝到nfs目錄下,然後在開發板上執行 mount -t nfs -o nolock 192.168.2.6:/nfsroot /mnt 將共享目錄從PC上掛載到開發板上,然後insmod這個驅動:


[root@tiny4412 ]# mount -t nfs -o nolock 192.168.2.6:/nfsroot /mnt

[root@tiny4412 ]# cd /mnt

[root@tiny4412 mnt]# ls

fdt                interrupt_demo.ko  tiny4412.dts

[root@tiny4412 mnt]# insmod interrupt_demo.ko 

[ 1655.872546] int_demo_probe enter.

[ 1655.872841] samsung_gpio_to_irq enter.

[ 1655.873061] int_demo_probe: gpio: 238 ---> irq (105)

[ 1655.873716] samsung_gpio_to_irq enter.

[ 1655.873906] int_demo_probe: gpio: 239 ---> irq (106)

[ 1655.874424] samsung_gpio_to_irq enter.

[ 1655.874773] int_demo_probe: gpio: 240 ---> irq (107)

[ 1655.879981] samsung_gpio_to_irq enter.

[ 1655.883485] int_demo_probe: gpio: 241 ---> irq (108)

[root@tiny4412 mnt]# 

// 然後我們嘗試按底板上的按鍵,會看到相應的中斷log

[root@tiny4412 mnt]# [   33.462207] int_demo_isr enter, tiny4412,int_gpio1: gpio:238, irq: 105

[   33.657304] int_demo_isr enter, tiny4412,int_gpio1: gpio:238, irq: 105

[   35.769955] int_demo_isr enter, tiny4412,int_gpio3: gpio:240, irq: 107

[   35.951373] int_demo_isr enter, tiny4412,int_gpio3: gpio:240, irq: 107

[   36.525804] int_demo_isr enter, tiny4412,int_gpio4: gpio:241, irq: 108

[   36.698501] int_demo_isr enter, tiny4412,int_gpio4: gpio:241, irq: 108

[   41.710481] int_demo_isr enter, tiny4412,int_gpio2: gpio:239, irq: 106

[   41.857190] int_demo_isr enter, tiny4412,int_gpio2: gpio:239, irq: 106


[root@tiny4412 mnt]# cat /proc/interrupts 

           CPU0       CPU1       CPU2       CPU3       

 36:          0          0          0          0       GIC  89 Edge      mct_comp_irq

 37:       1054        566        579        339       GIC  28 Edge      MCT

 44:         34          0          0          0       GIC 107 Edge      mmc0

 45:          1          0          0          0       GIC 103 Edge      12480000.hsotg, 12480000.hsotg, dwc2_hsotg:usb1

 46:        508          0          0          0       GIC 102 Edge      ehci_hcd:usb2, ohci_hcd:usb3

 47:        197          0          0          0       GIC  84 Edge      13800000.serial

 51:         52          0          0          0       GIC  93 Edge      13890000.i2c

 57:          0          0          0          0       GIC  67 Edge      12680000.pdma

 58:          0          0          0          0       GIC  68 Edge      12690000.pdma

 59:          0          0          0          0       GIC  66 Edge      12850000.mdma

 71:          0          0          0          0       GIC  79 Edge      11400000.pinctrl

 72:          1          0          0          0       GIC  78 Edge      11000000.pinctrl

 90:          0          0          0          0  COMBINER  80 Edge      3860000.pinctrl

 91:          0          0          0          0       GIC 104 Edge      106e0000.pinctrl

 95:         48          0          0          0       GIC 109 Edge      dw-mci

103:          2          0          0          0  exynos4210_wkup_irq_chip   1 Edge      mma7660

104:          1          0          0          0  exynos_gpio_irq_chip   2 Edge      12530000.sdhci cd

105:          2          0          0          0  exynos4210_wkup_irq_chip   2 Edge      tiny4412,int_gpio1

106:          2          0          0          0  exynos4210_wkup_irq_chip   3 Edge      tiny4412,int_gpio2

107:          2          0          0          0  exynos4210_wkup_irq_chip   4 Edge      tiny4412,int_gpio3

108:          2          0          0          0  exynos4210_wkup_irq_chip   5 Edge      tiny4412,int_gpio4

IPI0:          0          1          1          1  CPU wakeup interrupts

IPI1:          0          0          0          0  Timer broadcast interrupts

IPI2:        852       1809        422        537  Rescheduling interrupts

IPI3:          0          2          2          2  Function call interrupts

IPI4:          0          1          2          1  Single function call interrupts

IPI5:          0          0          0          0  CPU stop interrupts

IPI6:          0          0          0          0  IRQ work interrupts

IPI7:          0          0          0          0  completion interrupts

Err:          0


如果我們修改驅動驅動,改變一下中斷的申請順序,然後重啓系統(測試發現,如果不重啓系統,而是重新加載新的驅動,gpio跟irq的對應關系沒有發生改變)


#if 1

    for (i = 3; i >= 0; i--) {

        sprintf(data[i].name, "tiny4412,int_gpio%d", i+1);

#else

    for (i = 0; i < 4; i++) {

#endif


此時,會看到如下的log:


[root@tiny4412 mnt]# insmod interrupt_demo.ko 

[  119.735726] int_demo_probe enter.

[  119.736295] samsung_gpio_to_irq enter.

[  119.736417] int_demo_probe: gpio: 241 ---> irq (105)

[  119.736852] samsung_gpio_to_irq enter.

[1] [2]
Keywords:tiny4412  Linux  內核移植  中斷  GPIO Reference address:基於tiny4412的Linux內核移植--- 中斷和GPIO學習(1)

Previous article:基於tiny4412的Linux內核移植--- 中斷和GPIO學習(2)
Next article:Analysis of arm's bin binary code

Recommended ReadingLatest update time:2024-11-16 13:56

LCD backlight adjustment and driver implementation based on embedded Linux
In handheld devices, liquid crystal displays are increasingly used. Since LCDs cannot emit light by themselves, they require a strong light source to provide backlight for them in order to clearly display information. Such light sources are very power-hungry, and the power consumption of liquid crystal displays usua
[Power Management]
LCD backlight adjustment and driver implementation based on embedded Linux
[51 MCU Quick Start Guide] 2.3: GPIO reads matrix keyboard 8 IO reads 16 keys
Puzhong 51-Single-core-A2 STC89C52 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 Hard Knowledge Selected from "Popular 51 Single-Chip Microcomputer Development Strategy_V1.2" Matrix keyboard introduction        When independent buttons are connected to a single-chip microcomputer, each button re
[Microcontroller]
[51 MCU Quick Start Guide] 2.3: GPIO reads matrix keyboard 8 IO reads 16 keys
Qinheng CH32V103C8T6 (Part 2): Linux RISC-V compilation and burning environment configuration
Hardware Preparation CH32V103 Development Board/Core Edition WCH-Link Software Preparation The software is mainly RISC-V GCC for compilation, and OpenOCD for burning. Both of them need to use the Qinheng version RISC-V GCC can only use the WCH version for now. The public version cannot correctly handle interrupts de
[Microcontroller]
Design of extended serial port based on S3C2440 and embedded Linux
With the development of computer networks and the widespread use of technologies such as fieldbus, serial communication is increasingly used in various occasions. In centralized control systems, communication is required between multiple serial ports, while on general computers, there are only 1 to 3 serial ports. In o
[Microcontroller]
Design of extended serial port based on S3C2440 and embedded Linux
Design of I2C touch screen based on ARM processor S3C2440 and Linux system
0 Introduction With the development of computer-related technologies, ARM embedded systems are increasingly widely used and are increasingly integrated into people's lives. Touch screen devices are widely used in this embedded field due to their friendly human-computer interaction, convenient and flexible oper
[Microcontroller]
Design of I2C touch screen based on ARM processor S3C2440 and Linux system
LPC1768 basic input and output GPIO usage
  The control of LPC1788 general IO port includes some basic components, such as setting push-pull output, open-drain output, pull-up resistor, etc. Let's take a look today.   First use GPIO to turn on the GPIO system clock       LPC_SC- PCONP |= (1 15); //gpio clock     Then we need to select the function of the sel
[Microcontroller]
LPC1768 basic input and output GPIO usage
Tiny4412 Interrupt Controller (GIC) WDT Interrupt
#include "regs.h" void enable_mmu(unsigned long ttb); void init_ttb(unsigned long *ttb_base); void mmap(unsigned long *ttb_base, unsigned long va, unsigned long pa); void memset(char *buf, char ch, int size); void memcpy(char *dst, char *src, int size); void do_irq(unsigned long regs ); void (*printf)(char *, ...) = 0
[Microcontroller]
Design and implementation of a logistics distribution system based on S3C2440 on Linux platform
  introduction   The logistics distribution system includes multiple links such as cargo concentration, inventory management, vehicle scheduling, distribution transportation, etc. The ultimate goal of the distribution system is to reduce the total distribution cost and thus obtain the "third profit". Among them, the
[Microcontroller]
Design and implementation of a logistics distribution system based on S3C2440 on Linux platform
Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号