【Linux 驱动】简单字符设备驱动架构(LED驱动)

本文基于icool210开发板,内核版本:linux2.6.35;

驱动代码:

(1)头文件:led.h

 1 #ifndef __LED_H__
 2 #define __LED_H__
 3 
 4 #define LED_MAGIC 'l'
 5 #define LED_1_ON    _IO(LED_MAGIC, 0)
 6 #define LED_1_OFF   _IO(LED_MAGIC, 1)
 7 #define LED_2_ON    _IO(LED_MAGIC, 3)
 8 #define LED_2_OFF   _IO(LED_MAGIC, 4)
 9 #define LED_3_ON    _IO(LED_MAGIC, 5)
10 #define LED_3_OFF   _IO(LED_MAGIC, 6)
11 #define LED_4_ON    _IO(LED_MAGIC, 7)
12 #define LED_4_OFF   _IO(LED_MAGIC, 8)
13 #define LED_5_ON    _IO(LED_MAGIC, 9)
14 #define LED_5_OFF   _IO(LED_MAGIC, 10)
15 #define LED_6_ON    _IO(LED_MAGIC, 11)
16 #define LED_6_OFF   _IO(LED_MAGIC, 12)
17 
18 #endif

(2)代码文件:led.c

  1 #include <linux/module.h>
  2 #include <linux/init.h>
  3 #include <linux/cdev.h>
  4 #include <linux/fs.h>
  5 #include <linux/io.h>
  6 #include "led.h"
  7 
  8 #define GPBCON  0xE0200040
  9 #define GPBDAT  0xE0200044
 10 #define GPH0CON 0xE0200C00
 11 #define GPH0DAT 0xE0200C04
 12 unsigned int *led_gpb_config;
 13 unsigned int *led_gpb_data;
 14 unsigned int *led_gph0_config;
 15 unsigned int *led_gph0_data;
 16 
 17 struct cdev led_dev;
 18 dev_t devno;
 19 
 20 /****************************************************************************
 21 ** 函数名: led_open
 22 ** 功  能: led设备驱动的操作函数集的open函数
 23 ** 参  数: struct inode *pstInode
 24 **         struct file *pstFile
 25 ** 日  期: 2017年2月22日
 26 ** 作  者: Rookie
 27 *****************************************************************************/
 28 int led_open(struct inode *pstInode, struct file *pstFile)
 29 {
 30     unsigned int uiDataTemp;
 31 
 32     /*
 33     ** 配置LED对应的GPIO为Output
 34     ** LED1 -- GPB0   LED2 -- GPIO2
 35     ** LED3 -- GPB1   LED4 -- GPIO4
 36     */
 37     led_gpb_config = ioremap(GPBCON, 4);
 38     uiDataTemp = readl(led_gpb_config);
 39     uiDataTemp &= 0xFFFF0000;
 40     uiDataTemp |= 0x1111;
 41     writel(uiDataTemp, led_gpb_config);
 42 
 43     /* LED5 -- GPH0_7   LED6 -- GPH0_5 */
 44     led_gph0_config = ioremap(GPH0CON, 4);
 45     uiDataTemp = readl(led_gph0_config);
 46     uiDataTemp &= 0xF0FFFFF;
 47     uiDataTemp |= 0x10100000;
 48     writel(uiDataTemp, led_gph0_config);
 49 
 50     led_gpb_data = ioremap(GPBDAT, 4);
 51     led_gph0_data = ioremap(GPH0DAT, 4);
 52 
 53     return 0;
 54 }
 55 
 56 /****************************************************************************
 57 ** 函数名: led_ioctl
 58 ** 功  能: led设备驱动的操作函数集的ioctl函数
 59 ** 参  数: struct file *pstFile
 60 **         unsigned int uiCmd
 61 **         unsigned long ulArgc
 62 ** 日  期: 2017年2月22日
 63 ** 作  者: Rookie
 64 *****************************************************************************/
 65 long led_ioctl(struct file *pstFile, unsigned int uiCmd, unsigned long ulArgc)
 66 {
 67     unsigned int uiDataTemp;
 68 
 69     switch (uiCmd)
 70     {
 71         case (LED_1_ON):
 72             uiDataTemp = readl(led_gpb_data);
 73             uiDataTemp |= 0x1;
 74             writel(uiDataTemp, led_gpb_data);
 75             printk("led1--on
");
 76             break;
 77 
 78         case (LED_1_OFF):
 79             uiDataTemp = readl(led_gpb_data);
 80             uiDataTemp &= 0xFFFFFFFE;
 81             writel(uiDataTemp, led_gpb_data);
 82             printk("led1--off
");
 83             break;
 84 
 85         case (LED_2_ON):
 86             uiDataTemp = readl(led_gpb_data);
 87             uiDataTemp |= 0x4;
 88             writel(uiDataTemp, led_gpb_data);
 89             printk("led2--on
");
 90             break;
 91 
 92         case (LED_2_OFF):
 93             uiDataTemp = readl(led_gpb_data);
 94             uiDataTemp &= 0xFFFFFFFB;
 95             writel(uiDataTemp, led_gpb_data);
 96             printk("led2--off
");
 97             break;
 98 
 99         case (LED_3_ON):
100             uiDataTemp = readl(led_gpb_data);
101             uiDataTemp |= 0x2;
102             writel(uiDataTemp, led_gpb_data);
103             break;
104 
105         case (LED_3_OFF):
106             uiDataTemp = readl(led_gpb_data);
107             uiDataTemp &= 0xFFFFFFFD;
108             writel(uiDataTemp, led_gpb_data);
109             break;
110 
111         case (LED_4_ON):
112             uiDataTemp = readl(led_gpb_data);
113             uiDataTemp |= 0x8;
114             writel(uiDataTemp, led_gpb_data);
115             break;
116 
117         case (LED_4_OFF):
118             uiDataTemp = readl(led_gpb_data);
119             uiDataTemp &= 0xFFFFFFF7;
120             writel(uiDataTemp, led_gpb_data);
121             break;
122 
123         case (LED_5_ON):
124             uiDataTemp = readl(led_gph0_data);
125             uiDataTemp |= 0x80;
126             writel(uiDataTemp, led_gph0_data);
127             break;
128 
129         case (LED_5_OFF):
130             uiDataTemp = readl(led_gph0_data);
131             uiDataTemp &= 0xFFFFFF7F;
132             writel(uiDataTemp, led_gph0_data);
133             break;
134 
135         case (LED_6_ON):
136             uiDataTemp = readl(led_gph0_data);
137             uiDataTemp |= 0x20;
138             writel(uiDataTemp, led_gph0_data);
139             break;
140 
141         case (LED_6_OFF):
142             uiDataTemp = readl(led_gph0_data);
143             uiDataTemp &= 0xFFFFFFDF;
144             writel(uiDataTemp, led_gph0_data);
145             break;
146 
147         default:
148             return -EINVAL;
149     }
150     
151     return 0;
152 }
153 
154 
155 static struct file_operations led_ops =
156 {
157     .open = led_open,
158     .unlocked_ioctl = led_ioctl,
159 };
160 
161 /****************************************************************************
162 ** 函数名: led_init
163 ** 功  能: led设备驱动初始化函数
164 ** 参  数: void
165 ** 日  期: 2017年2月22日
166 ** 作  者: Rookie
167 *****************************************************************************/
168 static int __init led_init(void)
169 {
170     cdev_init(&led_dev, &led_ops);
171 
172     alloc_chrdev_region(&devno, 0, 1, "my_led");
173     cdev_add(&led_dev, devno, 1);
174 
175     return 0;
176 }
177 
178 /****************************************************************************
179 ** 函数名: led_exit
180 ** 功  能: led设备驱动退出函数
181 ** 参  数: void
182 ** 日  期: 2017年2月22日
183 ** 作  者: Rookie
184 *****************************************************************************/
185 static void __exit led_exit(void)
186 {
187     cdev_del(&led_dev);
188     unregister_chrdev_region(devno, 1);
189     
190     return;
191 }
192 
193 
194 module_init(led_init);
195 module_exit(led_exit);
196 MODULE_LICENSE("GPL");

(3)Makefile文件

1 obj-m := led.o
2 KDIR := /root/wksp/icool210/linux2.6.35-icool210-v1.8
3 all:
4     make -C $(KDIR) M=$(PWD) modules CROSS_COMPILE=arm-linux- ARCH=arm
5 clean:
6     rm -rf *.ko *.o *.order *symvers

(4)测试应用程序:app.c

 1 #include <stdio.h>
 2 #include <sys/types.h>
 3 #include <sys/stat.h>
 4 #include <fcntl.h>
 5 #include <sys/ioctl.h>
 6 #include "led.h"
 7 
 8 int main(int argc, const char *argv[])
 9 {
10     int iFd;
11     int iLedNum;
12     int iLedStatus;
13 
14     if (argc < 3)
15     {
16         printf("Please Enter 3 Para!
");
17         return -1;
18     }
19 
20     iLedNum = atoi(argv[1]);
21     iLedStatus = atoi(argv[2]);
22 
23     iFd = open("/dev/my_led", O_RDWR);
24 
25     if (1 == iLedNum)
26     {
27         if (1 == iLedStatus)
28         {
29             ioctl( iFd, LED_1_ON);
30         }
31         else
32         {
33             ioctl( iFd, LED_1_OFF);
34         }
35     }
36     else if (2 == iLedNum)
37     {
38         if (1 == iLedStatus)
39         {
40             ioctl( iFd, LED_2_ON);
41         }
42         else
43         {
44             ioctl( iFd, LED_2_OFF);
45         }
46     }
47     else if (3 == iLedNum)
48     {
49         if (1 == iLedStatus)
50         {
51             ioctl( iFd, LED_3_ON);
52         }
53         else
54         {
55             ioctl( iFd, LED_3_OFF);
56         }
57     }
58     else if (4 == iLedNum)
59     {
60         if (1 == iLedStatus)
61         {
62             ioctl( iFd, LED_4_ON);
63         }
64         else
65         {
66             ioctl( iFd, LED_4_OFF);
67         }
68     }
69     else if (5 == iLedNum)
70     {
71         if (1 == iLedStatus)
72         {
73             ioctl( iFd, LED_5_ON);
74         }
75         else
76         {
77             ioctl( iFd, LED_5_OFF);
78         }
79     }
80     else if (6 == iLedNum)
81     {
82         if (1 == iLedStatus)
83         {
84             ioctl( iFd, LED_6_ON);
85         }
86         else
87         {
88             ioctl( iFd, LED_6_OFF);
89         }
90     }
91 
92     return 0;
93 }

操作方法:

(1)编译 .ko 文件

   在驱动代码路径直接执行 make

(2)编译 应用程序

   arm-linux-gcc -static app.c -o app

(3)记载内核模块

  insmod led.ko

(4)创建设备节点

 mknod /dev/my_led c 251 0

(5) 执行应用程序

./app 1 1

原文地址:https://www.cnblogs.com/jamesharden/p/6431316.html