7 GPIO 子系统/内核GPIO 的使用

demo.c

  1 /* head file */
  2 #include <linux/init.h>
  3 #include <linux/module.h>
  4 #include <linux/fs.h>
  5 #include <linux/cdev.h>
  6 #include <linux/uaccess.h>
  7 #include <linux/slab.h>
  8 #include <linux/wait.h>
  9 #include <linux/poll.h>
 10 #include <linux/miscdevice.h>
 11 #include <linux/sched.h>
 12 #include <linux/io.h>
 13 #include <linux/gpio.h>
 14 
 15 #include "ioctl.h"
 16 
 17 #define DEVNAME "gpioleds"
 18 
 19 static int gpioleds[4] = { //定义引脚数组
 20     EXYNOS4X12_GPM4(0),
 21     EXYNOS4X12_GPM4(1),
 22     EXYNOS4X12_GPM4(2),
 23     EXYNOS4X12_GPM4(3),
 24 };
 25 
 26 enum {ON, OFF};//0 1
 27 
 28 void mill_ctl_led(int cmd, int num)
 29 {
 30     gpio_set_value(gpioleds[num-1], cmd);//设置相应gpio口值
 31 }
 32 
 33 int mill_ctl_stat (unsigned long arg)
 34 {
 35     char kbuf[4];//定义4个灯的状态数组
 36     int i;
 37 
 38     for (i = 0; i < 4; i++) {
 39         kbuf[i] = !gpio_get_value(gpioleds[i]);//读取4个gpio口的状态值
 40     }
 41 
 42     if (copy_to_user((void *)arg, kbuf, 4))     {//将内核读取到的gpio状态值返回给应用层
 43         return -EINVAL;
 44     } 
 45 
 46     return 0;
 47 }
 48 
 49 static long 
 50 mill_unlocked_ioctl (struct file *filp, unsigned int request, unsigned long arg)
 51 {
 52     if (_IOC_TYPE(request) != LEDTYPE) {
 53         return -EINVAL;
 54     }
 55 
 56     switch (_IOC_NR(request)) {
 57         default:
 58             return -EINVAL;
 59         case 1:
 60             if (arg < 1 || arg > 4) {
 61                 return -EINVAL;
 62             }
 63 
 64             mill_ctl_led(ON, arg);
 65             break;
 66         case 2:
 67             if (arg < 1 || arg > 4) {
 68                 return -EINVAL;
 69             }
 70             mill_ctl_led(OFF, arg);
 71             break;
 72         case 3:
 73             if (mill_ctl_stat(arg) < 0) {
 74                 return -EINVAL;
 75             }
 76             break;
 77     }
 78 
 79     return 0;
 80 }
 81 
 82 static struct file_operations fops = {
 83     .owner         = THIS_MODULE,    
 84     .unlocked_ioctl = mill_unlocked_ioctl,
 85 };
 86 
 87 
 88 /*一个杂项设备对应如下一个结构体对象*/
 89 static struct miscdevice misc = {
 90     .minor    = MISC_DYNAMIC_MINOR,
 91     .name    = DEVNAME,
 92     .fops    = &fops,    
 93 };
 94 
 95 static int __init demo_init(void)
 96 {
 97     int i;
 98     int ret;
 99 
100     for (i = 0; i < ARRAY_SIZE(gpioleds); ++i) {
101         ret = gpio_request(gpioleds[i], "led");//申请要用的4个gpio口
102         if (ret < 0) {
103             goto error0;//申请失败则去一一释放
104         }
105         ret = gpio_direction_output(gpioleds[i], OFF);//设置gpio口为输出功能
106         if (ret < 0) {
107             gpio_free(gpioleds[i]);//不要忘了应该释放完全
108             goto error0;//设置失败则去一一释放
109         }
110     }
111     
112     if((ret = misc_register(&misc)) < 0) {    //注册杂项设备
113         goto error0;
114     }
115 
116     return 0;
117 error0:
118     while (i--) {
119         gpio_free(gpioleds[i]);//一一释放
120     }
121 
122     return ret;//返回错误负值
123 }
124 
125 module_init(demo_init);
126 
127 /* driver module exit */
128 static void __exit demo_exit(void)
129 {
130     int i;
131 
132     for (i = 0; i < ARRAY_SIZE(gpioleds); ++i) {
133         gpio_set_value(gpioleds[i], OFF);//设置4个gpio口数据为1,即为默认状态下关灯
134         gpio_free(gpioleds[i]);//释放所有gpio口
135     }
136 
137     misc_deregister(&misc);//移除该杂项设备
138 }
139 module_exit(demo_exit);
140 
141 /* driver module description */
142 MODULE_LICENSE("GPL");
143 
144 MODULE_AUTHOR("millet9527");
145 MODULE_VERSION("millet plus 18");
146 MODULE_DESCRIPTION("example for driver module arch");

makefile

1 obj-m    := demo.o
2 
3 KERNEL    := /linux-3.5
4 
5 all:
6     make -C $(KERNEL) M=`pwd`
7 clean:
8     make -C $(KERNEL) M=`pwd` clean
9     

ioctl.h

 1 #ifndef _MILLET_LED_H_
 2 #define _MILLET_LED_H_
 3 
 4 #include <linux/ioctl.h>
 5 
 6 #define  LEDTYPE 'l'
 7 
 8 #define  LED_CTL_ON   _IOW(LEDTYPE, 1, int)
 9 #define  LED_CTL_OFF  _IOW(LEDTYPE, 2, int)
10 #define  LED_CTL_STAT _IOR(LEDTYPE, 3, int)
11 
12 #endif

ledapp.c

 1 #include <fcntl.h>
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <unistd.h>
 5 #include <sys/stat.h>
 6 #include <assert.h>
 7 
 8 #include "ioctl.h"
 9 
10 void usage(char *str)
11 {
12     printf("Usage:\n");
13     printf("      %s on/off 1/2/3/4\n", str);
14     printf("      %s state\n", str);
15     
16     exit(1);
17 }
18 
19 int main(int argc, char **argv)
20 {
21     int i;
22     int fd;
23     int ret;
24     int request, arg;
25     char buf[4] = { 0 };
26 
27     if((argc !=2) && (argc != 3)) {
28         usage(argv[0]);
29     }
30 
31     fd = open("/dev/gpioleds", O_RDWR | O_NDELAY);
32     assert(fd > 0);
33 
34     if (argc == 3) {
35         if (!strncmp("on", argv[1], 2)) {
36             request = LED_CTL_ON;            
37         } else if (!strncmp("off", argv[1], 3)) {
38             request = LED_CTL_OFF;            
39         } else {
40             usage(argv[0]);
41         }
42         
43         arg = atoi(argv[2]);
44         
45         if (arg < 1 || arg > 4) {
46             usage(argv[0]);
47         }
48 
49         ret = ioctl(fd, request, arg);
50         assert(ret == 0);
51     } else if (argc == 2) {
52         if (!strncmp("state", argv[1], 5)) {
53             request = LED_CTL_STAT;
54         }
55         ret = ioctl(fd, request, buf);
56         assert(ret == 0);
57 
58         for (i = 0; i < 4; i++) {
59             printf("led %d is %s!\n", i+1, \
60                 buf[i]?"on":"off");
61         }
62     }
63 
64 
65     return 0;
66 }

ioctl.h

 1 #ifndef _MILLET_LED_H_
 2 #define _MILLET_LED_H_
 3 
 4 #include <linux/ioctl.h>
 5 
 6 #define  LEDTYPE 'l'
 7 
 8 #define  LED_CTL_ON   _IOW(LEDTYPE, 1, int)
 9 #define  LED_CTL_OFF  _IOW(LEDTYPE, 2, int)
10 #define  LED_CTL_STAT _IOR(LEDTYPE, 3, int)
11 
12 #endif

makefile

 1 CC=arm-linux-gcc 

=====================================================================

 

posted @ 2017-03-15 21:38  bkycrmn  阅读(286)  评论(0)    收藏  举报