基于mini2440的led驱动编写的总结

更新时间:2024-05-17 15:41:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

基于mini2440的led驱动编写的总结(可以成为模板) 该驱动用到I/O常见的端口操作函数:

s3c2410_gpio_cfgpin和s3c2410_gpio_setpin。前一函数实现了设置端口的状态为输入/输出/其他,后一函数实现了端口输出高/低电平。主要谈一下前一个函数的一些重要语句。首先是原型:

s3c2410_gpio_cfgpin(unsigned int pin,unsigned int function),那么我们在驱动中怎么运用呢?比如:s3c2410_gpio_cfgpin

(S3C2410_GPB(5),S3C2410_GPB_OUTPUT),那么里面两个函数是怎么操作的?请看下面的这几个定义:

1、#define S3C2410_GPB(_nr)

(S3C2410_GPIO_B_START+(_nr)) //定义在arch/arm/mach-s3c2410/include/mach/gpio-nrs.h 2、enum s3c_gpio_number{

S3C2410_GPIO_A_START = 0,

S3C2410_GPIO_B_START

=S3C2410_GPIO_NEXT(S3C2410_GPIO_A), ......

}//定义同上

3、#define S3C2410_GPIO_NEXT(__gpio) \\ ((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 0) //定义同上

4、CONFIG_S3C_GPIO_SPACE的定义在.config文件中,见下面: ...... #

#power managment #

CONFIG_S3C_LOWLEVEL_UART_PORT=0 CONFIG_S3C_GPIO_SPACE=0

......

5、#define S3C2410_GPIO_A_NR (32) #define S3C2410_GPIO_B_NR (32) ......

由以上所有定义可以得知以下结论:

S3C2410_GPB(5)-->(S3C2410_GPIO_B_START+5)-->S3C2410_GPIO_NEXT(S3C2410_GPIO_A)+5-->((S3C2410_GPIO_A_START) + S3C2410_GPIO_A_NR) +

CONFIG_S3C_GPIO_SPACE + 0)+5,

这就表示从GPA首地址+GPA个数+GPB的偏移个数是当前GPB的I/O的偏移量。即GPB(5)等于32+0+5=37,即pin=37。至于这怎么和GPB端口的寄存器扯上关系的有待进一步深入内核。

另外在/arch/arm/mach-s3c2410/include/mach/regs-gpio.h的第45行有如下定义:

#define S3C2410_GPIO_LEAVE (0xFFFFFFFF)

#define S3C2410_GPIO_INPUT (0xFFFFFFF0) //最后两位01表示输出

#define S3C2410_GPIO_OUTPUT (0xFFFFFFF1) 这时我们开始讲编写整个驱动的流程,其中分为两种方法。

方法一、(将LED注册为混杂设备)

a:首先确定file_operation中要填写几个操作函数,这里因为注册为混杂设备所以只有ioctl操作。 b:其次编写ioctl的实现。 c:注册LED为misc设备: static struct miscdevice misc={

.minor=MISC_DYNAMIC_MINOR, .name=DEVICE_NAME, .fops=&mini2440_leds_fops, }

d:编写初始化函数与退出函数。 具体程序如下:

#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include

#include #include #include #include #include #include #include #include

#define DEVICE_NAME \ static unsigned long led_table [] = { S3C2410_GPB(5), S3C2410_GPB(6), S3C2410_GPB(7), S3C2410_GPB(8), };

static unsigned int led_cfg_table [] = { S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, };

static int sbc2440_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { if (arg > 4) {

return -EINVAL; }

switch(cmd) {

case LED_ON:

s3c2410_gpio_setpin(led_table[arg], 0); return 0; case LED_OFF:

s3c2410_gpio_setpin(led_table[arg],1); return 0; default: return -EINVAL; } }

static struct file_operations dev_fops = { .owner = THIS_MODULE, .ioctl = mini2440_leds_ioctl, };

static struct miscdevice misc = { .minor = MISC_DYNAMIC_MINOR,

.name = DEVICE_NAME, .fops = &dev_fops, };

static int __init mini2440_leds_init(void) { int ret; int i;

for (i = 0; i < 4; i++) {

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); }

ret = misc_register(&misc);

printk (DEVICE_NAME\ return ret; }

static void __exit mini2440_leds_exit(void) {

misc_deregister(&misc); }

module_init(mini2440_leds_init); module_exit(mini2440_leds_exit);

方法二:(将LED注册为普通字符设备)

步骤与上面类似除还得编写open函数,但不用加上注册那个misc设备。具体程序如下: #include #include #include #include #include #include #include #include #include

#include #include #include #include #include #include #include #include #include #include #include #include #include #include

#define DEVICE_NAME \这一行在每一个设备驱动中都必须有的,体现在/dev目录下 //将端口做成数组,以便于编写

static unsigned long led_table [] = { S3C2410_GPB(5), S3C2410_GPB(6), S3C2410_GPB(7), S3C2410_GPB(8), };

static unsigned int led_cfg_table [] = { S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, S3C2410_GPIO_OUTPUT, };

//open函数的实现,其形参不能改变,这是模板

stativ int mini2440_leds_open(struct inode *inode,struct file *file) { int i;

for (i = 0; i < 4; i++) {

s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]); }

return 0; }

//ioctl函数的实现,里面的形参是固定格式,不需更改

static int mini2440_leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) {

if (arg > 4) { return -EINVAL; }

switch(cmd) {

case LED_ON:

s3c2410_gpio_setpin(led_table[arg], 0); return 0; case LED_OFF:

s3c2410_gpio_setpin(led_table[arg],1); return 0; default: return -EINVAL; } }

//最重要的结构体之一

static struct file_operations mini2440_leds_fops = { .owner = THIS_MODULE, .ioctl = mini2440_leds_ioctl,

.open =mini2440_leds_open, };

//初始化函数以及退出函数的写法,记住他们的格式 static int __init mini2440_leds__init(void) { int ret;

ret =

register_chrdev(0,DEVICE_NAME,&mini2440_leds_fops);

printk (DEVICE_NAME\ if(ret<0) {

printk(DEVICE_NAME\ return ret; }

printk(DEVICE_NAME\ return 0; }

static void __exit mini2440_leds_exit(void) {

unregister_chrdev(0,DEVICE_NAME); }

module_init(mini2440_leds_init); module_exit(mini2440_leds_exit);

printk(DEVICE_NAME\ return 0; }

static void __exit mini2440_leds_exit(void) {

unregister_chrdev(0,DEVICE_NAME); }

module_init(mini2440_leds_init); module_exit(mini2440_leds_exit);

本文来源:https://www.bwwdw.com/article/1rq7.html

Top