新聞中心

        EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應用 > 基于S3C2440的linux驅(qū)動

        基于S3C2440的linux驅(qū)動

        作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏

        MINI2440_BUTTON.C

        #include

        本文引用地址:http://www.104case.com/article/201611/318871.htm

        #include

        #include

        #include

        #include

        #include

        #include

        #include interrupt.h>

        #include

        #include

        #include

        #define DEVICE_NAME "buttons"

        #define BUTTON_MAJOR 232

        struct button_irq_desc {

        int irq;

        int pin;

        int pin_setting;

        int number;

        char *name;

        };

        static struct button_irq_desc button_irqs [] = {

        {IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, "KEY1"},

        {IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, "KEY2"},

        {IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, "KEY3"},

        {IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, "KEY4"},

        {IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, "KEY5"},

        {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY6"},

        };

        static volatile int key_values [] = {0, 0, 0, 0, 0, 0};

        static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

        static volatile int ev_press = 0;

        static irqreturn_t buttons_interrupt(int irq, void *dev_id)

        {

        struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

        int up = s3c2410_gpio_getpin(button_irqs->pin);

        if (up)

        key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

        else

        key_values[button_irqs->number] = (button_irqs->number + 1);

        ev_press = 1;

        wake_up_interruptible(&button_waitq);

        return IRQ_RETVAL(IRQ_HANDLED);

        }

        static int mini2440_buttons_open(struct inode *inode, struct file *file)

        {

        int i;

        int err;

        for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

        // 注冊中斷處理函數(shù)

        s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);

        err = request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

        button_irqs[i].name, (void *)&button_irqs[i]);

        set_irq_type(button_irqs[i].irq, IRQT_BOTHEDGE);

        if (err)

        break;

        }

        if (err) {

        // 釋放已經(jīng)注冊的中斷

        i--;

        for (; i >= 0; i--) {

        disable_irq(button_irqs[i].irq);

        free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

        }

        return -EBUSY;

        }

        return 0;

        }

        static int mini2440_buttons_close(struct inode *inode, struct file *file)

        {

        int i;

        for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

        // 釋放已經(jīng)注冊的中斷

        disable_irq(button_irqs[i].irq);

        free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

        }

        return 0;

        }

        static int mini2440_buttons_read(struct file *filp, char __user *buff,

        size_t count, loff_t *offp)

        {

        unsigned long err;

        if (!ev_press) {

        if (filp->f_flags & O_NONBLOCK)

        return -EAGAIN;

        else

        wait_event_interruptible(button_waitq, ev_press);

        }

        ev_press = 0;

        err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));

        memset((void *)key_values, 0, sizeof(key_values));

        return err ? -EFAULT : min(sizeof(key_values), count);

        }

        static unsigned int mini2440_buttons_poll(

        struct file *file,

        struct poll_table_struct *wait)

        {

        unsigned int mask = 0;

        poll_wait(file, &button_waitq, wait);

        if (ev_press)

        mask |= POLLIN | POLLRDNORM;

        return mask;

        }

        static struct file_operations mini2440_buttons_fops = {

        .owner = THIS_MODULE,

        .open = mini2440_buttons_open,

        .release = mini2440_buttons_close,

        .read = mini2440_buttons_read,

        .poll = mini2440_buttons_poll,

        };

        static int __init mini2440_buttons_init(void)

        {

        int ret;

        ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &mini2440_buttons_fops);

        if (ret < 0) {

        printk(DEVICE_NAME " cant register major numbern");

        return ret;

        }

        devfs_mk_cdev(MKDEV(BUTTON_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);

        printk(DEVICE_NAME " initializedn");

        return 0;

        }

        static void __exit mini2440_buttons_exit(void)

        {

        devfs_remove(DEVICE_NAME);

        unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);

        }

        module_init(mini2440_buttons_init);

        module_exit(mini2440_buttons_exit);

        MODULE_AUTHOR("http://www.arm9.net"); // 驅(qū)動程序的作者

        MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver"); // 一些描述信息

        MODULE_LICENSE("GPL"); // 遵循的協(xié)議

        總結(jié)一下,程序框架。

        按鍵的驅(qū)動主要是多了中斷的處理,關(guān)于中斷主要的處理函數(shù)是

        request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

        button_irqs[i].name, (void *)&button_irqs[i]);

        第二個參數(shù)是主要的中斷處理函數(shù)。

        static irqreturn_t buttons_interrupt(int irq, void *dev_id)

        {

        struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

        int up = s3c2410_gpio_getpin(button_irqs->pin);

        if (up)

        key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

        else

        key_values[button_irqs->number] = (button_irqs->number + 1);

        ev_press = 1;

        wake_up_interruptible(&button_waitq);

        return IRQ_RETVAL(IRQ_HANDLED);

        }

        另外還用到了兩個重要的結(jié)構(gòu)體:

        static struct button_irq_desc button_irqs [] = {

        {IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, "KEY1"},

        {IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, "KEY2"},

        {IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, "KEY3"},

        {IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, "KEY4"},

        {IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, "KEY5"},

        {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY6"},

        };

        struct button_irq_desc {

        int irq;

        int pin;

        int pin_setting;

        int number;

        char *name;

        };

        而驅(qū)動程序中的最重要的部分,file_operations為

        static struct file_operations mini2440_buttons_fops = {

        .owner = THIS_MODULE,

        .open = mini2440_buttons_open,

        .release = mini2440_buttons_close,

        .read = mini2440_buttons_read,

        .poll = mini2440_buttons_poll,

        };

        程序中其他的任務就是豐滿這個機構(gòu)體,使得應用程序在調(diào)用open,close等的時候可以在

        驅(qū)動中找到對應的項。

        這里的request_irq在open函數(shù)里調(diào)用的。

        至于注冊的部分跟LEDS那些是一樣的,就不多說啦。

        再附個應用程序供參考:

        #include

        #include

        #include

        #include

        #include

        #include

        #include

        #include

        #include

        #include

        int main(void)

        {

        int i;

        int buttons_fd;

        int key_value[4];

        buttons_fd = open("/dev/buttons", 0);

        if (buttons_fd < 0) {

        perror("open device buttons");

        exit(1);

        }

        for (;;) {

        fd_set rds;

        int ret;

        FD_ZERO(&rds);

        FD_SET(buttons_fd, &rds);

        ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);

        if (ret < 0) {

        perror("select");

        exit(1);

        }

        if (ret == 0) {

        printf("Timeout.n");

        }

        else if (FD_ISSET(buttons_fd, &rds)) {

        int ret = read(buttons_fd, key_value, sizeof key_value);

        if (ret != sizeof key_value) {

        if (errno != EAGAIN)

        perror("read buttonsn");

        continue;

        } else {

        for (i = 0;i < sizeof(key_value)/sizeof(key_value[0]); i++)

        printf("K%d %s, key value = 0x%02xn", i+1, (key_value[i] & 0x80) ? "released" :

        key_value[i] ? "pressed down" : "",

        key_value[i]);

        }

        }

        }

        close(buttons_fd);

        return 0;

        }



        關(guān)鍵詞: S3C2440linux驅(qū)

        評論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 酉阳| 黑龙江省| 兴义市| 抚宁县| 龙陵县| 黑山县| 夏邑县| 尖扎县| 鄂托克旗| 栖霞市| 甘洛县| 沧州市| 固镇县| 湖北省| 崇阳县| 芜湖县| 雷州市| 甘南县| 临潭县| 宝兴县| 红原县| 扶余县| 西乡县| 昌邑市| 黄陵县| 绥滨县| 常德市| 英超| 吴川市| 大埔区| 扎兰屯市| 镇平县| 泸定县| 长治县| 古丈县| 黔江区| 施甸县| 石阡县| 共和县| 伊通| 东山县|