您的位置:首页 > 其它

一个纯字符的(最原始版本)led驱动(有有助于加深对字符设备的理解)

2011-10-05 09:30 337 查看
/* set gpio */

s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(1));

s3c_gpio_setpull(S3C64XX_GPF(15), S3C_GPIO_PULL_NONE);

gpio_set_value(S3C64XX_GPE(0), 0)

bsp文件:

/*************************************************************************************************************************/

/* linux/arch/arm/plat-s3c/include/plat/gpio-cfg.h

* ....

*/

/* This file contains the necessary definitions to get the basic gpio

* pin configuration done such as setting a pin to input or output or

* changing the pull-{up,down} configurations.

*/

/* Note, this interface is being added to the s3c64xx arch first and will

* be added to the s3c24xx systems later.

*/

#ifndef __PLAT_GPIO_CFG_H

#define __PLAT_GPIO_CFG_H __FILE__

typedef unsigned int __bitwise__ s3c_gpio_pull_t;

typedef unsigned int __bitwise__ s5p_gpio_drvstr_t;

/* forward declaration if gpio-core.h hasn't been included */

struct s3c_gpio_chip;

/**

* struct s3c_gpio_cfg GPIO configuration

* @cfg_eint: Configuration setting when used for external interrupt source

* @get_pull: Read the current pull configuration for the GPIO

* @set_pull: Set the current pull configuraiton for the GPIO

* @set_config: Set the current configuration for the GPIO

* @get_config: Read the current configuration for the GPIO

*

* Each chip can have more than one type of GPIO bank available and some

* have different capabilites even when they have the same control register

* layouts. Provide an point to vector control routine and provide any

* per-bank configuration information that other systems such as the

* external interrupt code will need.

*

* @sa s3c_gpio_cfgpin

* @sa s3c_gpio_getcfg

* @sa s3c_gpio_setpull

* @sa s3c_gpio_getpull

*/

struct s3c_gpio_cfg {

unsigned int cfg_eint;

s3c_gpio_pull_t (*get_pull)(struct s3c_gpio_chip *chip, unsigned offs);

int (*set_pull)(struct s3c_gpio_chip *chip, unsigned offs,

s3c_gpio_pull_t pull);

unsigned (*get_config)(struct s3c_gpio_chip *chip, unsigned offs);

int (*set_config)(struct s3c_gpio_chip *chip, unsigned offs,

unsigned config);

};

#define S3C_GPIO_SPECIAL_MARK (0xfffffff0)

#define S3C_GPIO_SPECIAL(x) (S3C_GPIO_SPECIAL_MARK | (x))

/* Defines for generic pin configurations */

#define S3C_GPIO_INPUT (S3C_GPIO_SPECIAL(0))

#define S3C_GPIO_OUTPUT (S3C_GPIO_SPECIAL(1))

#define S3C_GPIO_SFN(x) (S3C_GPIO_SPECIAL(x))

#define s3c_gpio_is_cfg_special(_cfg) \

(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)

/**

* s3c_gpio_cfgpin() - Change the GPIO function of a pin.

* @pin pin The pin number to configure.

* @to to The configuration for the pin's function.

*

* Configure which function is actually connected to the external

* pin, such as an gpio input, output or some form of special function

* connected to an internal peripheral block.

*

* The @to parameter can be one of the generic S3C_GPIO_INPUT,S3C_GPIO_OUTPUT

* or S3C_GPIO_SFN() to indicate one of the possible values that the helper

* will then generate the correct bit mask and shift for the configuration.

*

* If a bank of GPIOs all needs to be set to special-function 2, then

* the following code will work:

*

* for (gpio = start; gpio < end; gpio++)

* s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));

*

* The @to parameter can also be a specific value already shifted to the

* correct position in the control register, although these are discouraged

* in newer kernels and are only being kept for compatibility.

*/

extern int s3c_gpio_cfgpin(unsigned int pin, unsigned int to);

/**

* s3c_gpio_getcfg - Read the current function for a GPIO pin

* @pin: The pin to read the configuration value for.

*

* Read the configuration state of the given @pin, returning a value that

* could be passed back to s3c_gpio_cfgpin().

*

* @sa s3c_gpio_cfgpin

*/

extern unsigned s3c_gpio_getcfg(unsigned int pin);

/* Define values for the pull-{up,down} available for each gpio pin.

*

* These values control the state of the weak pull-{up,down} resistors

* available on most pins on the S3C series. Not all chips support both

* up or down settings, and it may be dependant on the chip that is being

* used to whether the particular mode is available.

*/

#define S3C_GPIO_PULL_NONE ((__force s3c_gpio_pull_t)0x00)

#define S3C_GPIO_PULL_DOWN ((__force s3c_gpio_pull_t)0x01)

#define S3C_GPIO_PULL_UP ((__force s3c_gpio_pull_t)0x02)

/**

* s3c_gpio_setpull() - set the state of a gpio pin pull resistor

* @pin: The pin number to configure the pull resistor.

* @pull: The configuration for the pull resistor.

*

* This function sets the state of the pull-{up,down} resistor for the

* specified pin. It will return 0 if successfull, or a negative error

* code if the pin cannot support the requested pull setting.

*

* @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN orS3C_GPIO_PULL_UP.

*/

extern int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull);

/**

* s3c_gpio_getpull() - get the pull resistor state of a gpio pin

* @pin: The pin number to get the settings for

*

* Read the pull resistor value for the specified pin.

*/

extern s3c_gpio_pull_t s3c_gpio_getpull(unsigned int pin);

/* Define values for the drvstr available for each gpio pin.

*

* These values control the value of the output signal driver strength,

* configurable on most pins on the S5P series.

*/

#define S5P_GPIO_DRVSTR_LV1 ((__force s5p_gpio_drvstr_t)0x0)

#define S5P_GPIO_DRVSTR_LV2 ((__force s5p_gpio_drvstr_t)0x2)

#define S5P_GPIO_DRVSTR_LV3 ((__force s5p_gpio_drvstr_t)0x1)

#define S5P_GPIO_DRVSTR_LV4 ((__force s5p_gpio_drvstr_t)0x3)

/**

* s5c_gpio_get_drvstr() - get the driver streght value of a gpio pin

* @pin: The pin number to get the settings for

*

* Read the driver streght value for the specified pin.

*/

extern s5p_gpio_drvstr_t s5p_gpio_get_drvstr(unsigned int pin);

/**

* s3c_gpio_set_drvstr() - set the driver streght value of a gpio pin

* @pin: The pin number to configure the driver streght value

* @drvstr: The new value of the driver strength

*

* This function sets the driver strength value for the specified pin.

* It will return 0 if successfull, or a negative error code if the pin

* cannot support the requested setting.

*/

extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);

#endif /* __PLAT_GPIO_CFG_H */

/*****************************************************************************************************************************************************************/

//led_driver_cdev.c
1 #include <linux/kernel.h>
2 #include <linux/module.h>
3 #include <linux/init.h>
4 #include <linux/mm.h>
5 #include <linux/fs.h>
6 #include <linux/types.h>
7 #include <linux/sched.h>
8 #include <linux/slab.h>
9 #include <linux/errno.h>
10 #include <linux/ioctl.h>
11 #include <linux/cdev.h>
12 #include <linux/string.h>
13 #include <linux/gpio.h>
14 #include <linux/ioctl.h>
15 #include <linux/poll.h>
16
17 #include <asm/io.h>
18 #include <asm/system.h>
19 #include <asm/uaccess.h>
20 #include <mach/hardware.h> /*宏 s3c2410_gpio_cfgpin*/
21 #include <mach/regs-gpio.h>
22
23 #include <plat/gpio-cfg.h>
24
25 #define LIGHT_MAJOR 252 /*预设的mem的主设备号*/
26 #define LIGHT_NR_DEVS 1 /*设备数*/
27
28 /*定义幻数*/
29 #define MEMDEV_IOC_MAGIC 'k'
30 /*定义命令*/
31 #define LIGHT_ON  _IO(MEMDEV_IOC_MAGIC, 0)
32 #define LIGHT_OFF _IO(MEMDEV_IOC_MAGIC, 1)
33
34 /*设备结构体*/
35 struct light_dev{
36     struct cdev cdev; /*字符设备cdev结构体*/
37     unsigned char value; /*LED亮时为1 熄灭时为0 用户可以读写此值*/
38 };
39
40 struct light_dev *light_devp;
41 int light_major = LIGHT_MAJOR;
42
43 void light_gpio_init(void)
44 {
45      s3c_gpio_cfgpin(S3C64XX_GPK(8), S3C_GPIO_OUTPUT);
46      s3c_gpio_setpull(S3C64XX_GPK(8), S3C_GPIO_PULL_NONE);
47      gpio_set_value(S3C64XX_GPK(8), 0); /*初始化 灯亮*/
48 }
49
50 void light_on(void)
51 {
52      s3c_gpio_cfgpin(S3C64XX_GPK(8), S3C_GPIO_OUTPUT);
53      s3c_gpio_setpull(S3C64XX_GPK(8), S3C_GPIO_PULL_NONE);
54      gpio_set_value(S3C64XX_GPK(8), 0); /*灯亮*/
55 }
56
57 void light_off(void)
58 {
59      s3c_gpio_cfgpin(S3C64XX_GPK(8), S3C_GPIO_OUTPUT);
60      s3c_gpio_setpull(S3C64XX_GPK(8), S3C_GPIO_PULL_NONE);
61      gpio_set_value(S3C64XX_GPK(8), 1); /*灯灭*/
62 }
63
64 /*打开和关闭函数*/
65 int light_open(struct inode *inode, struct file *filp)
66 {
67     struct light_dev *dev;
68     /*获得设备结构体指针*/
69     dev = container_of(inode->i_cdev, struct light_dev, cdev);
70     filp->private_data = dev; /*让设备结构体作为设备的私有信息*/
71     return 0;
72 }
73
74 int light_release(struct inode *inode, struct file *filp)
75 {
76     return 0;
77 }
78
79 ssize_t light_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
80 {
81     struct light_dev *dev = filp->private_data;
82     printk("light_read\n");
83     if(copy_to_user(buf, &(dev->value), 1))
84         return -EFAULT;
85     return 1;
86 }
87
88 ssize_t light_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
89 {
90     struct light_dev *dev = filp->private_data;
91     printk("<0>light_write\n");
92     if(copy_from_user(&(dev->value), buf, 1))
93         return -EFAULT;
94
95     /*根据写入的值 点亮和熄灭 LED*/
96     if(dev->value == 1){
97         light_on();
98     }else if(dev->value == 0){
99         light_off();
100     }
101     return 1;
102 }
103
104 /*ioclt函数*/
105 static long light_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
106 {
107     struct light_dev *dev = filp->private_data;
108
109     switch(cmd){
110         case LIGHT_ON:
111             dev->value = 1;
112             light_on();
113             break;
114         case LIGHT_OFF:
115             dev->value = 0;
116             light_off();
117             break;
118         default:
119             /*不能支持的命令*/
120             return -ENOTTY;
121     }
122     return 0;
123 }
124
125 struct file_operations light_fops = {
126     .owner = THIS_MODULE,
127     .read  = light_read,
128     .write = light_write,
129     .unlocked_ioctl = light_ioctl,
130     .open = light_open,
131     .release =light_release,
132 };
133
134 /*设置字符设备cdev结构体*/
135 static void light_setup_cdev(struct light_dev *dev, int index)
136 {
137     int err, devno = MKDEV(light_major, index);
138     cdev_init(&dev->cdev, &light_fops);
139     dev->cdev.ops = &light_fops;
140     err = cdev_add(&dev->cdev, devno, 1);
141     if(err)
142         printk(KERN_NOTICE "error %d adding LED %d", err, index);
143 }
144
145
146 int light_init(void)
147 {
148     int result;
149     dev_t dev = MKDEV(light_major, 0);
150     /*申请字符设备号*/
151     if(light_major)
152         result = register_chrdev_region(dev, 1, "LED");
153     else{
154         result = alloc_chrdev_region(&dev, 0, 1, "LED");
155         light_major = MAJOR(dev);
156     }
157     if(result < 0)
158         return result;
159     /*分配设备结构体内存*/
160     light_devp = (struct light_dev *)kmalloc(sizeof(struct light_dev), GFP_KERNEL);
161     if(!light_devp){
162         result = -ENOMEM;
163         goto fail_malloc;
164     }
165
166     memset(light_devp, 0, sizeof(struct light_dev));
167
168     light_setup_cdev(light_devp, 0);
169     light_gpio_init(); /*灯亮*/
170     printk("<0>light_init\n");
171     return 0;
172
173 fail_malloc:
174     unregister_chrdev_region(dev, 1);
175     return result;
176 }
177
178 void light_exit(void)
179 {
180     light_off();
181     cdev_del(&light_devp->cdev);/*删除字符设备结构体*/
182     kfree(light_devp); /*释放在light_init中分配的内存*/
183     unregister_chrdev_region(MKDEV(light_major, 0), 1); /*删除字符设备*/
184     printk("<0> light_exit\n");
185 }
186
187
188 MODULE_AUTHOR("wenhui");
189 MODULE_LICENSE("GPL");
190 module_init(light_init);
191 module_exit(light_exit);


测试程序:

//led_cdev_test.c
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/ioctl.h>
5 //#include <sys/types.h>
6 //#include <sys/stat.h>
7 #include <fcntl.h>
8
9 /*定义幻数*/
10 #define MEMDEV_IOC_MAGIC 'k'
11 /*定义命令*/
12 #define LIGHT_ON  _IO(MEMDEV_IOC_MAGIC, 0)
13 #define LIGHT_OFF _IO(MEMDEV_IOC_MAGIC, 1)
14
15
16 int main(int argc, char **argv)
17 {
18     int fd;
19     int buf[] = {0, 1};
20     char buf_read[1];
21     unsigned int state;
22
23     if(argc != 2 || sscanf(argv[1],"%d",&state) != 1 || state > 4 ){
24         printf("Useage: xxx #./filename 1|0 \n");
25         exit(0);
26     }
27
28     fd = open("/dev/led_driver_cdev", O_RDWR);
29     if(fd < 0){
30         printf("error to open /dev/led_driver_cdev\n");
31         exit(0);
32     }
33
34     if(state == 1){
35         ioctl(fd, LIGHT_ON, NULL);
36     }else if(state == 0){
37         ioctl(fd, LIGHT_OFF, NULL );
38     }else if(state == 2){
39         if(write(fd, &buf[0], sizeof(buf[0])) == -1){
40             printf("error to write\n");
41             exit(0);
42         }
43         printf("write 0 success\n");
44     }else if(state == 3){
45         if(write(fd, &buf[1], sizeof(buf[1])) == -1){
46             printf("error to write\n");
47             exit(0);
48         }
49         printf("wirte 1 success\n");
50     }else if(state == 4){
51         if(read(fd, buf_read, 1) == -1 ){
52             printf("error to read\n");
53         }
54     }
55
56     close(fd);
57     return 0;
58 }


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: