Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301159
  • 博文数量: 78
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 572
  • 用 户 组: 普通用户
  • 注册时间: 2012-11-26 09:59
文章分类

全部博文(78)

文章存档

2015年(8)

2014年(70)

我的朋友

分类: 嵌入式

2014-01-09 20:15:45

开发环境:
主机与开发板内核:Linux2.6.32(主机与开发板内核尽量一致,不然安装模块时,可能不兼容)
开发板:mini2440

驱动程序:
myleds_mini2440.h
#ifndef _MYLEDS_MINI2440_H_
#define _MYLEDS_MINI2440_H_

#define LED_IOC_MAGIC 'k'
#define LEDON _IOW(LED_IOC_MAGIC,0,int)
#define LEDOFF _IOW(LED_IOC_MAGIC,1,int)

#endif

myleds_mini2440.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#include "myleds_mini2440.h"

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dr. Wang");

//#define LEDON 0
//#define LEDOFF 1

dev_t ledid;
struct cdev *led_cdev;
struct class *led_class;

static unsigned long led_table [] = {
S3C2410_GPB(5),
S3C2410_GPB(6),
S3C2410_GPB(7),
S3C2410_GPB(8),
}; //定义引脚的寄存器数组(无符号长整形,对应于引脚的地址)

/*static unsigned int led_cfg_table [] = {
S3C2410_GPB5_OUTP,
S3C2410_GPB6_OUTP,
S3C2410_GPB7_OUTP,
S3C2410_GPB8_OUTP,
};*/ //定义引脚功能,为输出(无符号整形)

static int led_open(struct inode *inode,struct file *file)
{
/***led初始化***/
int i;
for (i = 0; i < 4; i++)
{
/*设置GPIO对应的配置寄存器GPIOCON为输出状态*/     
//s3c2410_gpio_cfgpin(led_table[i], led_cfg_table[i]);
s3c2410_gpio_cfgpin(led_table[i], S3C2410_GPIO_OUTPUT);
}
return 0;
}

static int led_ioctl(struct inode *inode,struct file *file,
unsigned int cmd,unsigned long arg)
{
if (arg > 4)
return -EINVAL;

switch (cmd)
{
case LEDON:
s3c2410_gpio_setpin(led_table[arg], 0);
printk("led_table[%d]\ton\n",arg);
break;

case LEDOFF:
s3c2410_gpio_setpin(led_table[arg], 1);
printk("led_table[%d]\toff\n",arg);
break;

default:
break;
}

return 0;
}

static struct file_operations led_ops = {
.owner = THIS_MODULE,
.open = led_open,
.ioctl = led_ioctl,

};


int __init led_init(void)
{
/***动态分配led设备号***/
alloc_chrdev_region(&ledid,0,1,"myled");

/***注册led设备***/
led_cdev=cdev_alloc();
cdev_init(led_cdev,&led_ops);
cdev_add(led_cdev,ledid,1);

/***自动创建led设备文件***/
led_class = class_create(THIS_MODULE,"myled_class");
device_create(led_class,NULL,ledid,NULL,"myled");

printk("LEDS initialized.\n");

return 0;
}


void __exit led_exit(void)
{
/***注销led设备***/
cdev_del(led_cdev);

/***注销led设备号***/
unregister_chrdev_region(ledid,1);
device_destroy(led_class,ledid);
class_destroy(led_class);
}

module_init(led_init);
module_exit(led_exit);

Makefile:
ifneq ($(KERNELRELEASE),)

obj-m := myleds_mini2440.o

else
KDIR := /kernel/linux-2.6.32
#KDIR := /lib/modules/2.6.34/build
all:
make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-
clean:
rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*
endif


测试程序:
ledtest_mini2440.c
#include
#include
#include
#include
#include
#include
#include

#include "myleds_mini2440.h"

int main(int argc, char **argv)
{
if (argc != 3)
{
printf("Usage:\n");
printf(" \t\t\n");
printf(" led_no = 1, 2, 3, 4\n");
}

int fd;
fd = open("/dev/myled", O_RDWR);
if (fd < 0) 
{
printf("Can't open /dev/myleds\n");
return -1;
}

unsigned int led_no;
led_no = strtoul(argv[1], 0, 0) - 1;
if (led_no > 5)
goto err;
/*{
close(fd);
printf("Usage:\n");
printf(" %s\t\t\n",argv[0]);
printf(" led_no = 1, 2, 3, 4\n");
return -1;
}*/

if (!strcmp(argv[2],"on"))
{
ioctl(fd,LEDON,led_no);
printf("led %d has been on",led_no);
}
else if (!strcmp(argv[2],"off"))
{
ioctl(fd,LEDOFF,led_no);
printf("led %d has been off",led_no);
}

else
goto err;

return 0;

err:
close(fd);
printf("Usage:\n");
printf(" %s\t\t\n",argv[0]);
printf(" led_no = 1, 2, 3, 4\n");
return -1;
}
如果内核版本是linux2.6.29,要稍作修改,否则会出现S3C2410_GPB5' undeclared here (not in a function)的错误。

供参考:http://blog.sina.com.cn/s/blog_ba08e8e00101ckja.html

阅读(1931) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~