您的位置:首页 > 运维架构 > Linux

linux内核下点亮led(未使用中断版本)

2010-05-03 12:11 344 查看
头文件:

#ifndef _LED_CONFIG_H

#define _LED_CONFIG_H

#define LED_CON 0

#define LED_ON 1

#define LED_OFF 2

#endif

内核下面的驱动模块:

#include <linux/module.h>

#include <linux/init.h>

#include <linux/io.h>

#include <linux/cdev.h>

#include <linux/fs.h>

#include <linux/slab.h>

#include "../led_config.h"

#include <linux/errno.h>

#define PHYS_BASE 0x56000040

#define SIZE 12

#define setbit(data,pos,len,val) do{/

data &=~((~(~0<<len))<<pos);/

data |=val<<pos;/

}while(0)

struct led_driver{

unsigned long gpecon;

unsigned long gpedat;

unsigned long gpeup;

unsigned long virt_base;

struct cdev led_dev;

unsigned long major;

unsigned long minor;

dev_t devno;

void (*conf)(struct led_driver *);

void (*on)(struct led_driver *);

void (*off)(struct led_driver *);

};

struct led_driver *md;

void con_led(struct led_driver *led)

{

unsigned long tmp;

tmp=ioread32(led->gpecon);

setbit(tmp,24,2,1);

iowrite32(tmp,led->gpecon);

tmp=ioread32(led->gpeup);

setbit(tmp,12,1,0);

iowrite32(tmp,led->gpeup);

printk("init config led/n");

}

void on_led(struct led_driver *led)

{

unsigned long tmp;

tmp=ioread32(led->gpedat);

setbit(tmp,12,1,0);

iowrite32(tmp,led->gpedat);

}

void off_led(struct led_driver *led)

{

unsigned long tmp;

tmp=ioread32(led->gpedat);

setbit(tmp,12,1,1);

iowrite32(tmp,led->gpedat);

}

int init_led_device(struct led_driver *led)

{

led->virt_base=ioremap(PHYS_BASE,SIZE);

led->gpecon=led->virt_base+0x0;

led->gpedat=led->virt_base+0x04;

led->gpeup=led->virt_base+0x08;

led->conf=con_led;

led->on=on_led;

led->off=off_led;

printk("init suceess/n");

return 0;

}

int led_ioctl(struct inode *inod,struct file *filp,unsigned int cmd,unsigned long args )

{

switch(cmd)

{

case LED_ON:

md->on(md);

break;

case LED_OFF:

md->off(md);

break;

case LED_CON:

md->conf(md);

break;

default:

printk("<kernel > don't know the cmd/n");

return -EINVAL;

}

return 0;

}

struct file_operations f_ops={

.owner=THIS_MODULE,

.ioctl=led_ioctl,

};

int init_led(void)

{

md=kmalloc(sizeof(struct led_driver),GFP_KERNEL);

if(NULL==md){

printk("the kernel has no enough space/n");

goto ERROR1;

}

md->major=0;

md->minor=0;

if(md->major){

md->devno=MKDEV(md->major,md->minor);

register_chrdev_region(md->devno,1,"led driver");

}else{

alloc_chrdev_region(&md->devno,md->minor,1,"led driver");

printk("<kernel>%d,%d/n",MAJOR(md->devno),MINOR(md->devno));

}

cdev_init(&md->led_dev,&f_ops);

if(init_led_device(md)){

printk("init the led device failed/n");

goto ERROR2;

}

if(cdev_add(&md->led_dev,md->devno,1)){

printk("add the led device failed/n");

goto ERROR2;

}

printk("the led device been ready/n");

return 0;

ERROR2:

unregister_chrdev_region(md->devno,1);

kfree(md);

return -ENODEV;

ERROR1:

return -ENOMEM;

}

void exit_led(void)

{

cdev_del(&md->led_dev);

unregister_chrdev_region(md->devno,1);

kfree(md);

}

module_init(init_led);

module_exit(exit_led);

MODULE_LICENSE("GPL");

应用层调用:

#include <stdio.h>

#include "../led_config.h"

#include <error.h>

#include <strings.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <fcntl.h>

int main(int argc ,char **argv)

{

int fd;

fd=open("/dev/test",O_RDWR);

if(fd<0){

perror("open the device");

return -1;

}

if(argc!=2){

printf("has no parment/n");

return -1;

}

ioctl(fd,LED_CON);

if(strncasecmp(argv[1],"on",2)==0){

printf("LED ON/n");

ioctl(fd,LED_ON);

}

if(strncasecmp(argv[1],"off",3)==0){

printf("LED OFF/n");

ioctl(fd,LED_OFF);

}

close(fd);

return 0;

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