linux内核中led驱动的分布,基于linux内核的简单LED驱动(一)

点亮LED:应用程序调用库提供的open打开设备→库根据open执行swi指令进入内核→内核根据参数找到相应的驱动→内核返回给库,库返回给应用程序。

#include “linux/module.h”

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define

DEVICE_NAME "leds" #define

LED_MAJOR 231

static struct class *leds_class;

static struct

class_device *leds_class_devs[4];

static char leds_status = 0x0; static DECLARE_MUTEX(leds_lock); // 定义赋值

//static int minor;

static unsigned long gpio_va;

#define GPIO_OFT(x) ((x) - 0x56000000)

#define GPFCON (*(volatile unsigned long

*)(gpio_va + GPIO_OFT(0x56000050)))

#define GPFDAT (*(volatile unsigned long

*)(gpio_va + GPIO_OFT(0x56000054)))

static int s3c24xx_leds_open(struct inode *inode, struct file

*file)

{

int minor = MINOR(inode->i_rdev);

//MINOR(inode->i_cdev);

switch(minor)

{

case 0:

{

// 配置3引脚为输出

//s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);

GPFCON &= ~(0x3<

GPFCON |= (1<

//s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);

GPFCON &= ~(0x3<

GPFCON |= (1<

//s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);

GPFCON &= ~(0x3<

GPFCON |= (1<

// 都输出0

//s3c2410_gpio_setpin(S3C2410_GPF4, 0);

GPFDAT &= ~(1<<4);

//s3c2410_gpio_setpin(S3C2410_GPF5, 0);

GPFDAT &= ~(1<<5);

//s3c2410_gpio_setpin(S3C2410_GPF6, 0);

GPFDAT &= ~(1<<6);

down(&leds_lock);

leds_status = 0x0;

up(&leds_lock);

break;

}

case 1:

{

s3c2410_gpio_cfgpin(S3C2410_GPF4, S3C2410_GPF4_OUTP);

s3c2410_gpio_setpin(S3C2410_GPF4, 0);

down(&leds_lock);

leds_status &= ~(1<<0);

up(&leds_lock);

break;

}

case 2:

{

s3c2410_gpio_cfgpin(S3C2410_GPF5, S3C2410_GPF5_OUTP);

s3c2410_gpio_setpin(S3C2410_GPF5, 0);

leds_status &= ~(1<<1);

break;

}

case 3:

{

s3c2410_gpio_cfgpin(S3C2410_GPF6, S3C2410_GPF6_OUTP);

s3c2410_gpio_setpin(S3C2410_GPF6, 0);

down(&leds_lock);

leds_status &= ~(1<<2);

up(&leds_lock);

break;

}

}

return

0;

}

static int s3c24xx_leds_read(struct file *filp, char __user

*buff,

size_t count, loff_t *offp)

{

int minor =

MINOR(filp->f_dentry->d_inode->i_rdev);

char

val;

switch

(minor)

{

case 0:

{

copy_to_user(buff, (const void *)&leds_status,

1); break;

}

case 1:

{

down(&leds_lock);

val = leds_status & 0x1;

up(&leds_lock);

copy_to_user(buff, (const void *)&val, 1);

break;

}

case 2:

{

down(&leds_lock);

val = (leds_status>>1) & 0x1;

up(&leds_lock);

copy_to_user(buff, (const void *)&val, 1);

break;

}

case 3:

{

down(&leds_lock);

val = (leds_status>>2) & 0x1;

up(&leds_lock);

copy_to_user(buff, (const void *)&val, 1);

break;

}

}

return

1;

}

static ssize_t s3c24xx_leds_write(struct file *file, const char

__user *buf, size_t count, loff_t * ppos)

{

//int minor

= MINOR(inode->i_rdev); //MINOR(inode->i_cdev);

int minor =

MINOR(file->f_dentry->d_inode->i_rdev);

char

val;

copy_from_user(&val, buf, 1);

switch

(minor)

{

case 0:

{ s3c2410_gpio_setpin(S3C2410_GPF4, (val & 0x1));

s3c2410_gpio_setpin(S3C2410_GPF5, (val & 0x1));

s3c2410_gpio_setpin(S3C2410_GPF6, (val & 0x1));

down(&leds_lock);

leds_status = val;

up(&leds_lock);

break;

}

case 1:

{

s3c2410_gpio_setpin(S3C2410_GPF4, val);

if (val == 0)

{

down(&leds_lock);

leds_status &= ~(1<<0);

up(&leds_lock);

}

else

{

down(&leds_lock);

leds_status |=

(1<<0); up(&leds_lock);

}

break;

}

case 2:

{

s3c2410_gpio_setpin(S3C2410_GPF5, val);

if (val == 0)

{

down(&leds_lock);

leds_status &= ~(1<<1);

up(&leds_lock);

}

else

{

down(&leds_lock);

leds_status |=

(1<<1); up(&leds_lock);

}

break;

}

case 3:

{

s3c2410_gpio_setpin(S3C2410_GPF6, val);

if (val == 0)

{

down(&leds_lock);

leds_status &= ~(1<<2);

up(&leds_lock);

}

else

{

down(&leds_lock);

leds_status |=

(1<<2); up(&leds_lock);

}

break;

}

}

return

1;

}

static struct file_operations s3c24xx_leds_fops = {

.owner = THIS_MODULE, .open = s3c24xx_leds_open, .read = s3c24xx_leds_read, .write = s3c24xx_leds_write, };

static int __init s3c24xx_leds_init(void)

//static int __init init_module(void)

{

int

ret;

int minor = 0;

gpio_va =

ioremap(0x56000000, 0x100000);

if (!gpio_va) {

return -EIO;

}

ret =

register_chrdev(LED_MAJOR, DEVICE_NAME,

&s3c24xx_leds_fops);

if (ret <

0) {

printk(DEVICE_NAME " can't register major number\n");

return ret;

}

leds_class = class_create(THIS_MODULE,

"leds");

if (IS_ERR(leds_class))

return

PTR_ERR(leds_class);

leds_class_devs[0] =

class_device_create(leds_class, NULL, MKDEV(LED_MAJOR, 0), NULL,

"leds");

for (minor = 1; minor < 4; minor++)

{

leds_class_devs[minor] =

class_device_create(leds_class, NULL, MKDEV(LED_MAJOR, minor),

NULL, "led%d", minor);

if

(unlikely(IS_ERR(leds_class_devs[minor])))

return

PTR_ERR(leds_class_devs[minor]);

}

printk(DEVICE_NAME " initialized\n");

return

0;

}

static void __exit s3c24xx_leds_exit(void)

{

int minor;

unregister_chrdev(LED_MAJOR, DEVICE_NAME);

for (minor = 0; minor < 4; minor++)

{

class_device_unregister(leds_class_devs[minor]);

}

class_destroy(leds_class);

iounmap(gpio_va);

}

module_init(s3c24xx_leds_init);

module_exit(s3c24xx_leds_exit);

MODULE_AUTHOR("http://www.100ask.net");

MODULE_VERSION("0.1.0");

MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");

MODULE_LICENSE("GPL");

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值