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
=====================================================================