LINUX應用程式層操作GPIO口

來源:互聯網
上載者:User

 Linux 下操作gpio:

   對於在不支援虛擬記憶體的作業系統和根本就沒有使用作業系統的系統裡操作GPIO直接讀寫對應的GPIO寄存器就可以啦,但是在linux這樣的作業系統下,核心層和應用程式層都是處於虛擬位址中,而GPIO的寄存器都是處於物理地址中,你必須編寫一個操作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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string.h>
#include <time.h>

#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;
}

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.