宾格装饰项目经理石磊:Linux 下操作gpio:

来源:百度文库 编辑:中财网 时间:2024/05/06 04:35:53
Linux 下操作gpio:

   对于在不支持虚拟内存的操作系统和根本就没有使用操作系统的系统里操作GPIO直接读写对应的GPIO寄存器就可以啦,但是在linux这样的操作系统下,你必须编写一个操作GPIO的驱动,或者是使用一些变通的技巧来操作GPIO.

   目前我所知道的在linux下操作GPIO有两种方法:

1.  编写驱动,这当然要熟悉linux下驱动的编写方法和技巧,在驱动里可以使用ioremap函数获得GPIO物理基地址指针,然后使用这个指针根据ioctl命令进行GPIO寄存器的读写,并把结果回送到应用层。这里提供一点程序片断供大家参考:

    int  init_module(void){

        printk(KERN_ALERT "ioctl load.\r\n");

    register_chrdev(254,"ioreg",&fops);

        stb_gpio = (STBX25XX_GPIO_REG *)ioremap(GPIO_BASE,GPIO_LEN);

    if(stb_gpio == NULL){

            printk(KERN_ALERT "can''t get io base.\r\n");

        return -1;

        }

    return 0;

}

int io_ioctl (struct inode *inode, struct file *filp,unsigned int cmd, unsigned long arg){

    unsigned long uGpio;

    printk(KERN_ALERT "io_ioctl cmd=%04x,arg=%04x.\r\n",cmd,(int)arg);

    switch(cmd){

        case SET_IO_DIR:{

             printk(KERN_ALERT "SET_IO_DIR\r\n");

             break;

        }

        case SET_IO_VALUE:{

             printk(KERN_ALERT "SET_IO_VALUE\r\n");

             break;

        }

        case GET_IO_VALUE:{

             printk(KERN_ALERT "GET_IO_VALUE\r\n");

             uGpio = stb_gpio->GPI;

             printk(KERN_ALERT "GPIO = %08x",(int)uGpio);

             copy_to_user((void *)arg,(const void *) &uGpio,sizeof(uGpio));

             break;

        }

        case GET_IO_DIR:{

             printk(KERN_ALERT "GET_IO_DIR\r\n");

             break;

        }

    }

    return 0;

}

 

2.  在应用层使用mmap函数在应用层获得GPIO物理基地址对应的虚拟地址指针,然后使用这个指针来读写GPIO寄存器,这里提供一点程序片断供大家参考:

/dev/mem是物理内存的全映像,可以用来访问物理内存,一般用法是open("/dev/mem",O_RDWR|O_SYNC),然后mmap,接着就可以用mmap的地址来访问物理内存,这实际上就是实现用户空间驱动的一种方法。

/dev/kmem:内核看到的虚拟内存的全映像,可以用来访问kernel的内容。

 

内核空间用1G虚拟地址,用户空间用3G虚拟地址
所以ioremap当然不能分出1G地址供你用(ioreamp的空间大小是有限制的)
一个物理地址,内核调用 ioremap得到一个1G内的虚拟地址,用来操作物理内存
             应用层调用 mmap 得到一个3G内的虚拟地址,用来操作物理内存

 

char dev_name[] = "/dev/mem";

        GPIO_REGISTER  *gpio_base;

        fd  =  open(dev_name,O_RDWR);

        if(fd<0){

               printf("open %s is error\n",dev_name);

               return -1 ;

        }

        gpio_base = (GPIO_REGISTER *)mmap( 0, 0x32, PROT_READ | PROT_WRITE, MAP_SHARED,fd, 0x40060000 );

        if(gpio_base == NULL){

                printf("gpio base mmap is error\n");

                close(fd);

                return -1;

        }

        gpio_base->or  = (gpio_base->or & 0x7fffffff);

完整的程序:

#include
#include
#include
#include
#include
#include
#include
#include
#include

#define TIME_OUT    5      /* the timeout time, in seconds */
/**
 * Define behaviour's when the button is pressed enough time.
 */
void longtu_timeout(){
    printf("****  Pressed 5 seconds, Call RECOVERY! ****\n");
    //system("/sbin/recover_longtu.sh");
    //system("/sbin/reboot");
}

/*
 * The main function.
 */
int main(int argc, char *argv[])
{
    int mfd;
    unsigned int val=0, last_val;
    void *base;
    char *sys_pinstaterd;
    time_t t_now, t_old;
    int flag_issued = 0;
#if 0
    // uncomment these to make the program a daemon.

    pid_t pid;
        int i;
        if ( (pid=fork())<0)
                return -1;
        else if (pid!=0)
                exit(0);
        setsid();
        chdir("/");
        umask(0);
        for (i=0;i<256;i++)
                close(i);
#endif

    // open the memery mapped file.
    mfd=open("/dev/mem", O_RDWR);
    if (mfd < 0){
        printf("Cannot open /dev/mem.\n");
        exit(-1);
    }

    // Initialize the map
    base = mmap( NULL, 0x130,  PROT_READ | PROT_WRITE, MAP_SHARED, mfd, 0x1fe00000);
    if ( base < 0){
        exit(-1);
    }

    // Got the pointer to SYS_PINSTATERD register of GS32I CPU.
    sys_pinstaterd = base + 0x011c;

    // init the temperay variables
    t_now=t_old=time(NULL);
    last_val = 0;
    while(1)
    {
        // Get status of GPIO7 pin.
        val = *( (volatile unsigned int*)sys_pinstaterd );
        val = (val&0x4) ? 1:0;
        printf("\tgpio 7 stat=%x.\n", val);
        if (val){
            // the button is pressed down !!
            if ( last_val==0 ){
                // starting time of press, log the time
                t_old = time(NULL);
                last_val=1;
                printf("Button Down\n");
            }else {
                // already pressed down! let's count the time!
                t_now = time(NULL);
                if (t_now-t_old>=TIME_OUT && flag_issued==0){
                    // Pressed LONG ENOUGH, issue the handler script!!
                    flag_issued = 1;
                    longtu_timeout();
                }
            }
        }else{
            // No button pressed.
            if (flag_issued){
                flag_issued = 0;
                printf("Button UP.\n");
            }
        }
       
        last_val = val;
        usleep(100);
    }

    munmap(base, 0x000);
    close(mfd);   
    return 0;
}

最新日志

  • 【引用】人性的精典总结
  • 【引用】精选笛曲100首,超
  • 消除现实世界中超低功耗嵌入
  • 微控制器无需CPU即可生成同
  • 巴特沃斯带通滤波电路
  • 常用电平转换方案