红联Linux门户
Linux帮助

AT91RM9200在linux2.6.20下的LED驱动

发布时间:2008-04-01 10:27:32来源:红联作者:SMuonon
作者:chenzhufly(空灵)发表于2008/03/31 email:chenzhufly@126.com

不知道为什么,我的busybox1.0.0在linux2.6.20下用lsmod命令,工作不正常。无奈之下,我换了个版本,busybox1.1.3成功!后来做了个简单的hello模块,也能够顺利加载。

今天写了个简单的LED驱动和测试程序,晚上回去试试,看看能不能跑起来,如果可以我把源码就贴出来啦。。呵呵

有些小错误,稍做修改就能够跑起来啦..呵呵,代码可能还有一些BUG,但是不影响运行,先贴出来再说.....

引用:
////////////////////////myled_driver.c/////////////////////////////////
#include
#include /* Specifically, a module */
#include
#include
#include
#include
#include
#include
#include /* for __initfunc */
//#include
//#include
#include /* for put_user */
//#include
#include /* for ioremap */
//#include
#include
#include
#include /* atmel RM9200 */
#define NAME "myled_test"
static int major = 231; //Define device major

#define led1 AT91_PIN_PB16
#define led2 AT91_PIN_PB17
static ssize_t myled_driver_write(struct file *file, const char __user *data, size_t len, loff_t *ppos)
{
unsigned char buf_data;
if(copy_from_user((char *)&buf_data,data,len))
return -EFAULT;

printk("MYLED Test Driver- write: user_data 0x=%x\n", buf_data);

switch (buf_data)
{
case 0x0:at91_set_gpio_output(led1,0);at91_set_gpio_output(led2,1);break;
case 0x1:at91_set_gpio_output(led1,1);at91_set_gpio_output(led2,0);break;
case 0x2:at91_set_gpio_output(led1,1);at91_set_gpio_output(led2,1);break;
case 0x3:at91_set_gpio_output(led1,0);at91_set_gpio_output(led2,0);break;
default: break;
}

return (len < 4 ? len : 4);
}
static ssize_t myled_driver_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
{
unsigned int i=0;
i |= at91_get_gpio_value(led1);
i |= at91_get_gpio_value(led2);
printk ("Read: value = 0x%08X\n", i);

if (len > 4)
return 0;
return (len < 4 ? len : 4);
}
static int myled_driver_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
printk("LED Test Driver- ioctl: param %u %lu\n", cmd, arg);
switch (cmd)
{
case 0:at91_set_gpio_output(led1,0);at91_set_gpio_output(led2,1);break;
case 1:at91_set_gpio_output(led1,1);at91_set_gpio_output(led2,0);break;
case 2:at91_set_gpio_output(led1,1);at91_set_gpio_output(led2,1);break;
case 3:at91_set_gpio_output(led1,0);at91_set_gpio_output(led2,0);break;
default:break;
}
return 1;
}
static int myled_driver_open(struct inode *inode, struct file *file)
{
unsigned m = iminor(inode);//得到次设备号,可以不要
if (m > 63)
return -EINVAL;
printk("LED Test driver opened!\n");
return nonseekable_open(inode, file);
}
static int myled_driver_release(struct inode *inode, struct file *file)
{
printk("MYLED Test driver released!\n");
return 0;
}
static struct file_operations myled_driver_fops = {
.owner = THIS_MODULE,
.ioctl = myled_driver_ioctl,
.write = myled_driver_write,
.read = myled_driver_read,
.open = myled_driver_open,
.release = myled_driver_release,
};

static int __init myled_driver_init(void)
{
int ret;
at91_set_gpio_output(led1,1);
at91_set_gpio_output(led2,1);
printk("MYLED Test Driver...\n");
ret = register_chrdev(major, NAME, &myled_driver_fops);//注册设备号 231,设备名
if (ret < 0) {
printk("Unable to register MYLED driver!\n");
return ret;
}
return 0;
}

static void __exit myled_driver_exit(void)
{
int ret;

ret = unregister_chrdev(major, NAME);
if (ret < 0)
printk("Unable to register character device!\n");
else
printk("MYLED Test Driver unloaded!");
}
module_init(myled_driver_init);
module_exit(myled_driver_exit);

MODULE_AUTHOR("chenzhu <chenzhufly@126.com>");
MODULE_DESCRIPTION("AT91RM9200 LED Test Driver");
MODULE_LICENSE("GPL");
/////////////////////////对应的Makefile文件//////////////////////////////
obj-m := myled_driver.o
#CC = /usr/local/arm/3.4.1/bin/arm-linux-gcc
KDIR := /home/chenzhufly/9200/linux-2.6.20/
PWD := $(shell pwd)
all:
$(MAKE) -k -C $(KDIR) SUBDIRS=$(PWD) modules

执行make CC = /usr/local/arm/3.4.1/bin/arm-linux-gcc

///////////////////////myled_test.c///////////////////////////////////
#include
#include
#include
#include
#include
static void Delay(int i)
{
while(i--);
}

int main(void)
{
int fd;
int err;
char led_data;
fd = open("/dev/myled",O_RDWR);
if ( fd < 0 )
{
printf("Cann't open file fd=0x%08X\n",fd);
exit(0);
}

while(1)
{
printf("\nmyled test beginning......\n");
getchar();

led_data = 0x1;
err = write(fd, &led_data, 1);
if(1 != err ){
printf("write error: %d\n",err);
}
Delay(10000);
sleep(1);
led_data = 0x2;
err = write(fd, &led_data, 1);
if(1 != err ){
printf("write error: %d\n",err);
}
Delay(10000);
sleep(1);

led_data = 0x3;
err = write(fd, &led_data, 1);
if(1 != err ){
printf("write error: %d\n",err);
}
Delay(10000);
sleep(1);

led_data = 0x4;
err = write(fd, &led_data, 1);
if(1 != err ){
printf("write error: %d\n",err);
}
Delay(10000);
sleep(1);
}
close(fd);
return 0;
}


执行/usr/local/arm/3.4.1/bin/arm-linux-gcc -o myled_test myled_test.c

最后加载模块,执行测试程序

引用:
insmod myled_driver.ko
mknod /dev/myled c 231 1
./myled_test


执行结果:

引用:
myled test beginning......
MYLED Test Driver- write: user_data 0x=1
MYLED Test Driver- write: user_data 0x=2
MYLED Test Driver- write: user_data 0x=3
MYLED Test Driver- write: user_data 0x=4


同时小灯也亮起来啦
文章评论

共有 1 条评论

  1. sjlgky 于 2009-12-22 09:09:41发表:

    你好,我想问一下at91_set_gpio_output这个函数的具体实现细节是什么呢?我的头文件里没有这个函数的定义啊