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

    /* 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 }










你可能感兴趣的:(c,struct,function,Module,IOC,output)