历史上的今天
返回首页

历史上的今天

今天是:2025年04月22日(星期二)

正在发生

2019年04月22日 | ARM-Linux下的GPIO中断程序

2019-04-22 来源:eefocus

       为了调试ARM板上的GPIO引脚中断效果,以便在后续项目使用ARM与ZLG7290按键LED中断芯片连接中随意选择空闲的GPIO引脚来作为ZLG7290的中断信号线,特意编写了一个小的Linux GPIO中断驱动程序下载到开发板上做实验。经验证,这种软件中断方式也还差强人意。下面贴出自己编写的不成熟的代码,见笑(


       实验的硬件电路为ARM GPIO的PB17连接一个共阴LED,PB18与PB19连接,PB18由中断驱动设置为低电平触发,PB19由GPIO驱动程序控制,上层应用程序通过驱动控制PB19高低电平变化,从而引发PB18发生中断,中断程序中控制PB17的LED亮和灭。


      Linux中断驱动部分:

/*

 * PB18_IRQTest.c

 * This is  a test program for sam9260, using PB19(J5_18 pin) input a signal to PB18(J5_16 pin),

 * PB18 receive this signal as IRQ and make the LED linking on PB17((J5_14 pin)) turn on or turn off   

 *

 *           @Author: Cun Tian Rui 

 *           @Date :March.18.2011

 */


#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include


void led_on()

{    

     at91_set_gpio_output(AT91_PIN_PB17,1);

}


void led_off()

{    

     at91_set_gpio_output(AT91_PIN_PB17 ,0);

}


struct light_dev *light_devp;

int light_major = 200;


struct light_dev

{

    struct cdev cdev;

    unsigned char value;

};


MODULE_AUTHOR("Cun Tian Rui");

MODULE_LICENSE("Dual BSD/GPL");



static void io_init(void)

{

    at91_set_gpio_input(AT91_PIN_PB18, 1);        

    at91_set_deglitch(AT91_PIN_PB18, 1); 

    at91_sys_write(1 + PIO_IDR,  1<<18);

    at91_sys_write(1 + PIO_IER,  (~(1<<18)));

    at91_sys_write(AT91_PMC_PCER, 1 << 3);

}



struct gpio_irq_desc

{

int irq;

unsigned long flags;

char *name;

};


static struct gpio_irq_desc PB18_IRQ={AT91_PIN_PB18,AT91_AIC_SRCTYPE_LOW,"PB18"};


static irqreturn_t PB18_intHandle(int irq, void *dev_id)

{

led_on();

return IRQ_RETVAL(IRQ_HANDLED);

}


int light_open(struct inode *inode,struct file *filp)

{

    int err;

    struct light_dev *dev;

    dev = container_of(inode->i_cdev,struct light_dev,cdev);

    filp->private_data = dev;

    io_init();

    err = request_irq(PB18_IRQ.irq,PB18_intHandle,PB18_IRQ.flags,PB18_IRQ.name,(void*)0);

    if(err) 

    {

free_irq(PB18_IRQ.irq,(void*)0);

return  -EBUSY;

}

    return 0;

}


int light_release(struct inode *inode,struct file *filp)

{

free_irq(PB18_IRQ.irq,(void*)0);

return 0;    

}




// ioctl

int light_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,

unsigned long arg)

{

    struct light_dev *dev = filp->private_data;


    switch(cmd)

    {

        case 0:

            at91_set_gpio_output(AT91_PIN_PB19,0);     

        break;


        case 1:

          at91_set_gpio_output(AT91_PIN_PB19,1);

   led_off();

        break;


        default:


            return -ENOTTY;

        // break;

    }


    return 0;

}     


struct file_operations light_fops = 

{

    .owner = THIS_MODULE,

    .ioctl = light_ioctl,

    .open  = light_open,

    .release = light_release,

};



static void light_setup_cdev(struct light_dev *dev,int index)

{

    int err,devno = MKDEV(light_major,index);


    cdev_init(&dev->cdev,&light_fops);

    dev->cdev.owner = THIS_MODULE;

    dev->cdev.ops = &light_fops;


    err = cdev_add(&dev->cdev,devno,1);


    if(err)

    {

        printk(KERN_NOTICE "Error %d adding LED%d",err,index);

    }

}



int light_init(void)

{

    int result;


    dev_t dev = MKDEV(light_major,0);

    if(light_major)

    {

        

        result = register_chrdev_region(dev,1,"PB18_IRQTest");

    }


    if(result < 0)

    {

        return result;

    }


    light_devp = kmalloc(sizeof(struct light_dev),GFP_KERNEL);

    if(!light_devp)

    {

        result = - ENOMEM;

        goto fail_malloc;

    }


    memset(light_devp,0,sizeof(struct light_dev));

    light_setup_cdev(light_devp,0);

    


    return 0;


    fail_malloc:unregister_chrdev_region(dev,light_devp);

    return result;

    

}


void light_cleanup(void)

{

    cdev_del(&light_devp->cdev);   

    kfree(light_devp);

    unregister_chrdev_region(MKDEV(light_major,0),1);  

}


module_init(light_init);

module_exit(light_cleanup);

    Linux上层应用程序:

#include

//#include

#include

#include

#include

#include

#include

#include

#include

#include



int main(int argc ,char *argv[])

{

int fd;

        char input;

 fd = open("/dev/PB18_IRQTest",O_RDWR);

if(fd < 0)

  {

perror("open PB18_IRQTest device");

     return 0;

}

while(1)

{

     printf("input 0 to trigger int/n");

     scanf("%c",&input);

     switch(input)

     {

case '0':

                    ioctl(fd,0,0);

printf("/n");

break;

case '1':

ioctl(fd,1,0);

printf("/n");

break;

        default:

printf("/n");

                break;                             

                     }

                 }                                        

                  return 0;

}

     由上面的代码可以看出,Linux内核在中断程序处理方面已经做了很多抽象,对于驱动程序编写者只需要按照内核中断构架去实现一定的控制函数就可以,以后有时间会专门撰文剖析还原Linux内核里那些对中断实现的抽象。

推荐阅读

史海拾趣

ETA Electric Industry Co Ltd公司的发展小趣事

近年来,ETA Electric Industry Co Ltd积极响应全球环保倡议,致力于实现可持续发展。他们优化了生产流程,减少了废弃物和污染物的排放。同时,公司还加大了对环保型电子元器件的研发力度,推出了一系列节能、环保的新产品。这些举措不仅提升了公司的社会形象,也为其在激烈的市场竞争中增添了新的优势。

上述五个故事,讲述了ETA Electric Industry Co Ltd在电子行业的发展历程。从起步之初的艰难,到技术创新的突破,再到市场拓展和质量管理的成功,最后到对环保和可持续发展的追求,每一步都体现了公司的成长和进步。

AMI [American Megatrends Inc]公司的发展小趣事

在二十世纪末,ETA Electric Industry Co Ltd还只是一个小型的电子设备制造商,专注于生产简单的电子元器件。当时,公司的创始人李先生看到了电子行业快速发展的潜力,并决定投身于这一行业。最初,公司面临着资金紧张、技术落后、市场竞争加剧等诸多挑战。然而,李先生凭借其敏锐的市场洞察力和不懈的努力,逐渐打开了市场局面。他们通过与小型科技企业合作,为其提供定制化的电子元器件,逐渐在市场上站稳了脚跟。

Auris公司的发展小趣事

Auris公司在技术研发方面取得了显著成果。其中,一款名为Auris Robotic Endoscopy System(ARES)的医疗机器人尤为引人注目。这款机器人能够通过精准的操控,帮助医生在不切口的情况下发现早期肺癌,提高了诊断的精确性。20XX年,食品与药品监督管理局(FDA)正式批准了ARES机器人的使用,这是对Auris公司技术实力和产品质量的高度认可。

Big-Sun Electronics Co Ltd公司的发展小趣事

随着国内市场的逐步饱和,Big-Sun Electronics Co Ltd公司开始将目光投向国际市场。公司积极参与国际电子展会,与海外客户建立起了良好的合作关系。同时,Big-Sun还与国际知名电子企业开展技术合作,共同研发新产品,进一步提升了公司的国际竞争力。

Helicomm公司的发展小趣事

Big-Sun Electronics Co Ltd公司自成立以来,始终致力于技术研发和产品创新。在成立初期,公司便投入大量资源于研发部门,通过不断试验和改进,成功研发出了一款具有高效能、低能耗特点的电子芯片,这一技术突破迅速在市场上引起了广泛关注。随着产品线的不断扩展,Big-Sun的电子产品逐渐在行业内树立起了技术领先的形象。

Anvo-Systems公司的发展小趣事

Anvo-Systems公司自成立以来,一直致力于电子技术的研发与创新。某年,公司成功研发出一款具有高效能源利用率的智能家居控制系统,该产品迅速在市场上获得了广泛关注。通过不断优化产品性能和用户体验,Anvo-Systems逐步扩大了市场份额,并与多家知名家电品牌建立了合作关系。这一技术突破不仅提升了公司的知名度,也为公司的持续发展奠定了坚实基础。

问答坊 | AI 解惑

高手来帮忙

我的课题是《公共汽车自动报站器》已经做好硬件原理图了现在在做软件的主程序,那位帮个忙做个留程…

查看全部问答>

宝钢交流调速的应用现状及思考

文章以综述的方式概要的介绍了宝钢一、二、三期工程建设中交流调速的应用情况。在分析现场应用各类的基本结构、性能、应用效果、存在的不足以及变频调速的应用给系统带来的电磁兼容问题的基础上。提出了宝钢三期后过程以及一、二期设备改造中交流调 ...…

查看全部问答>

汽车用传感器的应用现状及发展

介绍了汽车发动机控制系统、汽车状态控制系统用传感器的现状及未来发展。…

查看全部问答>

模拟电路教程

模拟电路教程,…

查看全部问答>

9針串口轉4針的轉接板,如果4針串口接反了會被燒壞么?

如題。 另外,9針和4針串口主要有什麽區別呢?…

查看全部问答>

谁有amx中控的编程软件和说明书?

谁有amx中控的编程软件和说明书?我去AMX公司,他们老板说网上下载,可是AMX的网站的下载在维护,不知那位哥们姐们有这块的编程软件和说明书,给个下载地址,谢谢…

查看全部问答>

求助:如何控制电压的大小

请问下如何通过CPU,来控制电压的大小? 意思就是说CPU给出如0101...的命令,应该怎么设计电路,或是有什么器件,可以使到这些命令可以控制电路中某个点电压的大小。…

查看全部问答>

求助,LM3S8962 GPIO模拟SPI驱动VS1003

我想用LM3S8962驱动VS1003,但是8962的SPI被SD卡和OLED占用了,我打算用GPIO模拟SPI驱动VS1003,我是按照TI 最新的StellarisWare里的SoftSSI配置的GPIO,从icdev下了VS1003的驱动,配置好有没有听到正弦波,检测CLK好像也不对,请高手给指点一下吧 ...…

查看全部问答>

iar 自带内部函数

在iar编译工具中,内置了一些内部函数,也就是Intrinsic.h头文件,里面的许多函数有些可以加快编写速度,有些可以指定变量的存放位置,还有些可以实现复杂的功能,但是我也只是了解其中的一些,请问各位谁有内部函数的讲解可以拿出来分享一下,感激 ...…

查看全部问答>

我想用STM32和tft做一个简易的示波器,谁能指导下啊

毕业后,找了个测试工作,觉得没前途,于是想抓紧时间学点别的。本人水平有限,听人说这样很好实现,指标要求不高,主要是锻炼一下。找了好多资料,买了个最小系统,和tft屏幕。其他的打算自己制作。但是不知从何处下手。谁给点建议…

查看全部问答>