一个纯字符的(最原始版本)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 */
/*****************************************************************************************************************************************************************/
测试程序:
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 }
相关文章推荐
- Linux驱动程序开发(4) - 字符设备驱动(3)-LED设备驱动和应用程序
- Linux字符设备驱动之Tiny6410 LED驱动分析
- Linux学习:LED字符设备驱动
- “手把手教你学linux驱动开发”OK6410系列之03---LED字符设备驱动 .
- linux设备驱动第三篇:写一个简单的字符设备驱动
- linux设备驱动第三篇:如何实现一个简单的字符设备驱动
- 创建一个字符设备驱动
- s3c2440基于linux的gpio led字符设备驱动实践 [转]
- 开发一个字符设备驱动
- 字符设备驱动理解
- linux设备驱动第三篇:写一个简单的字符设备驱动
- 字符设备驱动程序--LED驱动
- 一个简单的字符设备驱动
- linux设备驱动第三篇:写一个简单的字符设备驱动
- 字符设备驱动之LED-平台设备驱动(platform设备驱动)
- 一步步理解linux字符设备驱动框架(转)
- LED字符设备驱动调试笔记
- 字符设备驱动点亮led
- led灯实验之字符设备驱动poll操作
- 重新理解字符设备驱动的编写,针对2.6接口