Chinaunix首页 | 论坛 | 博客
  • 博客访问: 124140
  • 博文数量: 33
  • 博客积分: 948
  • 博客等级: 准尉
  • 技术积分: 380
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-19 20:47
文章分类

全部博文(33)

文章存档

2012年(2)

2011年(30)

2010年(1)

分类: LINUX

2011-08-14 21:03:15

mini2440 led驱动程序
2011-03-27 22:40

     这个led驱动程序只在linux-2.6.32.2内核中测试通过,至于其他的内核可能头文件有一些改动就不能 编译成功了。下面给出源程序:

这是友善之臂提供的源码:

#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 "leds" //设备名(/dev/leds)

//LED 对应的GPIO 端口列表

static unsigned long led_table[] = {

S3C2410_GPB(5),

S3C2410_GPB(6),

S3C2410_GPB(7),

S3C2410_GPB(8),

};

//LED 对应端口将要输出的状态列表

static unsigned int led_cfg_table[] = {

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

S3C2410_GPIO_OUTPUT,

};//如果内核相差不大,比如是2.6.30的内核,很可能照着这个程序写的时候这个地方会报错,原因是头文件不同

/*ioctl 函数的实现

* 在应用/用户层将通过ioctl 函数向内核传递参数,以控制LED 的输出状态

*/

static int sbc2440_leds_ioctl(

struct inode *inode,

struct file *file,

unsigned int cmd,

unsigned long arg)

{

switch(cmd) {

      case 0:

case 1:

if (arg > 4) {

return -EINVAL;

       }

//根据应用/用户层传递来的参数(取反),通过s3c2410_gpio_setpin 函数设置LED 对应的端口寄存

//器,

s3c2410_gpio_setpin(led_table[arg], !cmd);

return 0;

default:

return -EINVAL;

 

}

}

/*

* 设备函数操作集,在此只有ioctl 函数,通常还有read, write, open, close 等,因为本LED 驱动在下面已经

* 注册为misc 设备,因此也可以不用open/close

*/

static struct file_operations dev_fops = {

.owner = THIS_MODULE,

.ioctl = sbc2440_leds_ioctl,

};

/*

* 把LED 驱动注册为MISC 设备

*/

static struct miscdevice misc = {

.minor = MISC_DYNAMIC_MINOR, //动态设备号

.name = DEVICE_NAME,

.fops = &dev_fops,

};

/*

* 设备初始化

*/

static int __init dev_init(void)

{

int ret;

int i;

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

//设置LED 对应的端口寄存器为输出(OUTPUT)

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

//设置LED 对应的端口寄存器为低电平输出,在模块加载结束后,四个LED 应该是全部都是发光

        //状态

s3c2410_gpio_setpin(led_table[i], 0);

        }

ret = misc_register(&misc); //注册设备

printk (DEVICE_NAME"\tinitialized\n"); //打印初始化信息

      return ret;

}

static void __exit dev_exit(void)

{

      misc_deregister(&misc);

}

module_init(dev_init); //模块初始化,仅当使用insmod/podprobe 命令加载时有用,如果设备不是通过模块方式加载,此处将不会被调用

module_exit(dev_exit);//卸载模块,当该设备通过模块方式加载后,可以通过rmmod 命令卸载,将调用此函数

MODULE_LICENSE("GPL"); //版权信息

MODULE_AUTHOR("FriendlyARM Inc."); //开发者信息

 

下面是makefile文件

 CROSS=arm-linux-

KERNELDIR = /root/doc/mini/linux-2.6.32.2//内核源码位置

#定义内核源码的路径

PWD := $(shell pwd)

#获取当前路径

.PHONY: modules clean

#指明modules、clean为伪目标

obj-m += mini2440_leds.o

#表示要构造的模块名为s3c24xx_leds.ko

modules:

$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

#-C:进入$(KERNELDIR)后再执行make,读取那里的Makefile。

#M=$(PWM):然后返回当前的位置(驱动源代码的位置)继续执行当前的Makefile。

clean:

rm -rf *.o *~ core .depend .*.cmd  *.mod.c .tmp_versions

#end

进入目录后,执行make,然后将ko文件通过网络或者U 盘传到板子上,lsmod一下,装载模块。

下面的是测试文件leds-test.c:

#include

#include

#include

#include

int main(int argc, char **argv)

{

int on;

int led_no;

int fd;

if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 ||

on < 0 || on > 1 || led_no < 0 || led_no > 3) {

fprintf(stderr, "Usage: leds led_no 0|1\n");

exit(1);

}

fd = open("/dev/leds0", 0);

if (fd < 0) {

fd = open("/dev/leds", 0);

}

if (fd < 0) {

perror("open device leds");

exit(1);

}

ioctl(fd, on, led_no);

close(fd);

return 0;

}

将生成的.ko模块文件装载之后,运行测试文件就可以控制led的变化。

在命令行下执行:

#arm-linux-gcc –o leds-test leds-test.c

将生成可执行目标文件leds-test,通过网络ftp 或者优盘把它复制到开发板中,比如放在/home/plg 目录下(注意:开发板缺省的文件系统已经有了led 测试程序,所以我们在此改名为leds-test),在开发板的命令行终端执行:

#/etc/rc.d/init.d/leds stop

该命令将停止led-player 对led 的控制,关于led-player,可以在用户手册中查看详细的说明。使用leds-test 控制led 方法为:

#leds-test 3 0 ;关闭LED3

#leds-test 3 1 ;打开LED3

其中第一个参数为要控制的LED 序号,第二个参数代表关闭(0)或者打开(1)对应的LED。如图


阅读(1423) | 评论(0) | 转发(0) |
0

上一篇:也谈typedef

下一篇:putty教程

给主人留下些什么吧!~~