本文基于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