ESM335x外部中断输入应用

 2016-5-17          [nemail]    
[lablebox]

  ESM335x嵌入式主板引出了2路外部中断输入,IRQ1和IRQ2。中断上升沿有效,分别与GPIO24和GPIO25复用管脚。Linux-4.1.6之前采用了异步IO的方式通过SIGIO通知应用程序有中断发生,我们在Linux-4.1.6 IRQ驱动中增加了对select函数的支持,select函数使用户在应用程序中可以更方便的获取中断状态。


Linux系统IRQ外部中断的应用


  IRQ1和IRQ2对应的设备文件分别是:/dev/em335x_irq1和/dev/em335x-irq2.应用程序使用IRQ外部中断功能需要先打开相应的设备文件:


  int irq_no = 1;

    sprintf( device, "/dev/em335x_irq%d", irq_no );

    irq_fd = open(device, O_RDWR, S_IRUSR | S_IWUSR);

    if (irq_fd < 0)

    {

        printf("can not open /dev/em335x_irq1 device file!\n");

        return -1;

    }


  之后设置使用异步IO或者使用select函数获取中断状态,异步IO方式可参考技术手册,不再建议用户使用。


select函数


  由于外部中断输入的时间是不确定的,需要在循环中不停的调用select函数以检查设备文件的读状态,所以一般会创建一个线程来调用select函数,主程序继续执行其他的操作。线程函数如下:


  int IRQSelectThreadFunc(void* lparam)

  {

      int fd = * (int*)lparam;

      fd_set fdRead;

      struct timeval aTime;

      int retexitflag=1;    //exitflag在程序其他线程中改变

      while(1)

      {

          FD_ZERO(&fdRead);

          FD_SET(fd,&fdRead);

          aTime.tv_sec = 2; //s

          aTime.tv_usec = 0; //us

          ret = select ( fd+1, &fdRead, NULL, NULL, &aTime );

          if ( ret<0 )

              printf( "select, something wrong!\n " );

          if ( ret>0 )

          {

              if ( FD_ISSET(fd, &fdRead) )

              {

                  //用户可以在此加入中断发生后的处理操作

                  nIrqCounter++;

                  printf( "there is a IRQ!!!\n" );

              }

          }

          if ( exitflag==0 )

              break;

          //判断程序运行状态,跳出循环

      }

      pthread_exit( NULL );

      return 0;

  }


  创建线程:


  pthread_attr_t      attr;

    pthread_t           m_thread;

    int                 res;

 

    // 创建select线程

    res = pthread_attr_init(&attr);

    if( res!=0 )

    {

        printf("Create attribute failed\n" );

    }

    // 设置线程绑定属性

    res = pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );

    // 设置线程分离属性

    res += pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED );

    if( res!=0 )

    {

        printf( "Setting attribute failed\n" );

    }

 

    res = pthread_create( &m_thread, &attr, (void *(*) (void *))&IRQSelectThreadFunc, &irq_fd );

    if( res!=0 )

    {

        return -1;

    }

 

    pthread_attr_destroy( &attr );


  用户在应用程序中创建新的线程使用select函数查询中断设备文件的状态,如果有中断发生select函数将会返回大于0的数值,用户进一步判断是哪一个设备文件有中断发生,然后执行相应的中断处理操作。


异步IO和select函数的比较


  异步IO和select函数的功能都是相同的,即通知用户有中断发生,从而执行用户在应用程序中设置的中断处理操作;两者由于在内核中使用的事件通知机制不同,在应用程序中的设置方法差别很大,执行的方式也不同(见程序),select函数采用阻塞的方式获取读状态,不占用CPU资源,可以提高程序运行效率。两者最大的差异在于当用户需要在一个应用程序中检查多个中断输入设备文件的状态时(同时使用IRQ1和IRQ2),只能使用select函数才能确定具体是哪个中断设备文件有中断发生,使用异步IO不能确定。因此我们建议用户在程序中使用select函数来管理IRQ外部中断输入。


  如有疑问请随时与我们联系。

[lablebox]