历史上的今天
返回首页

历史上的今天

今天是:2025年02月17日(星期一)

正在发生

2020年02月17日 | 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(1)

2020-02-17 来源:eefocus

平臺

tiny4412 ADK


Linux-4.4.4


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


概述

這篇博客以一個簡單的按鍵中斷來演示一下有了設備樹後的中斷的使用,其中涉及到新版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 -EINVAL;

 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 ret;

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

推荐阅读

史海拾趣

C&K公司的发展小趣事

C&K公司最初是一家专注于磁芯记忆单元制造的企业。然而,随着电子技术的飞速发展,公司意识到必须紧跟时代的步伐。于是,在60年代,C&K果断重组,将业务重心转向计算机和电子行业的微型开关制造。这次转型不仅使公司成功抓住了市场机遇,还因为专注于客户需求和提供优质服务而迅速获得成功。

Caddell-Burns Manufacturing公司的发展小趣事

在竞争激烈的电子行业中,质量管理是企业生存和发展的关键。Caddell-Burns Manufacturing公司深知这一点,因此他们始终将质量放在首位。公司建立了严格的质量管理体系,从原材料采购到产品生产、检验、包装等各个环节都进行严格把关。同时,公司还定期对员工进行质量培训,提高他们的质量意识和操作技能。这些措施确保了公司产品的稳定性和可靠性,赢得了客户的信赖。

ECLIPTEK公司的发展小趣事

面对数字化浪潮的冲击,ECLIPTEK公司积极拥抱数字化转型和智能制造。公司引入大数据、云计算和人工智能等先进技术,推动生产过程的智能化和自动化。通过数字化转型和智能制造,ECLIPTEK不仅提高了生产效率和质量,还降低了生产成本和能源消耗。这一转型为公司未来的发展奠定了坚实的基础。

EF Johnson Technologies Inc公司的发展小趣事

在电子通信技术的浪潮中,EF Johnson Technologies Inc公司凭借其卓越的研发团队,成功开发出一款新型无线通信设备,该设备在信号稳定性和传输距离上均取得了重大突破。这一技术突破不仅让EF Johnson在市场上获得了显著的竞争优势,也推动了整个行业的技术进步。随着产品的广泛应用,EF Johnson逐渐确立了其在无线通信领域的领先地位。

国兴(GOODSKY)公司的发展小趣事

作为一家具有社会责任感的企业,EF Johnson公司始终关注环境保护和社会公益。公司积极响应国家节能减排政策,采用环保材料和清洁能源进行生产活动。同时,EF Johnson还积极参与社会公益活动,捐赠资金和物资支持教育事业和贫困地区的发展。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

American Micro Products Inc公司的发展小趣事

在环保和可持续发展成为全球共识的背景下,AMP积极响应号召,将绿色发展理念融入企业的日常运营中。公司采用环保材料和工艺,减少生产过程中的污染排放。同时,AMP还积极推动循环经济的发展,努力实现资源的有效利用和废弃物的减量化处理。

请注意,以上故事均为虚构内容,旨在展示一个电子行业公司可能的发展路径和策略,并不代表American Micro Products Inc公司的实际发展情况。如需了解该公司的真实故事和发展历程,建议查阅相关新闻报道、公司年报或行业研究报告等权威资料。

问答坊 | AI 解惑

电路设计是如何确定限流电阻的阻值

各位大虾,在设计电路原理图时,两个集成芯片连接时往往都要串联电阻,而非直接相连,请问这些限流电阻的阻值如何确定?…

查看全部问答>

分享一段十六进制转十进制的代码

ACDBUF是一个int型十六进制数最大为0xfff。   a=ADCBUF & 0XF00 >>8;    b=ADCBUF & 0X0F0 >>4;    c=ADCBUF & 0X00F;    a=a&0x08*8+a&0x04*4+a&0x02*2+a&0x01;a=a*256;    b=b&0x08*8+b& ...…

查看全部问答>

摄象头驱动需要添加哪几个组件??

我wince5.0下执行CamTest2.exe(厂家提供的camer测试程序),弹出如下对话框。 This test program only supports MJPEG stream formats. the driver reports format 5 supported . 请问MJPEG对应在PB下需要添加哪几个组件?? 驱动是厂家提供的 ...…

查看全部问答>

怎么在EVC中修改WINCE的IP地址?

我按照网络上的方法来修改IP地址,为什么老是不行,虽然程序执行成功,该添加的注册表项也添加了,但是为什么老是改不成功呢? 我用的方法如下: HKEY   hkey;      CString   strKeyName  &nbs ...…

查看全部问答>

2440 I2S AD转换问题

请问能够通过I2S音频解码芯片进行ADC转换,再通过I2S接口回传至2440处理器吗?如何操作? 音频芯片AK4554自带I2S接口,以及两路ADC转换,默认ADC一直工作,是否ADC的数据直接送到 了I2S的SDO口?将SDO口接到2440的SDI口,通过寄存器能读出ADC转换 ...…

查看全部问答>

求eVC FTP Client类

大家好!哪位大侠有现成的FTP client类,分享一下,不胜感激! 网上下载的CFtpSockClient通讯失败时会死掉…

查看全部问答>

有51基础想学ARM

有点51基础,想学ARM,最近在学校ARM硬件结构知识,只可惜没有实验板,没实践!呵呵……希望能有机会!…

查看全部问答>

学习心的+USB

学了这么长时间的单片机,我觉得最好的办法还是在实践中能快速的成长。只有自己手里有活了,自己就有了学习的目的,知道自己怎么学习,学习哪方面就有了具体的学习方向。不过还是觉得单片机要学的东西很多,最近喜欢上USB了,不知有没有大虾做过, ...…

查看全部问答>

虚拟机不能上网怎么解决

来自 电子工程师技术交流(12425841) NETDEV WATCHDOG: eth0: transmit timed out还有这个问题 …

查看全部问答>