Chinaunix首页 | 论坛 | 博客
  • 博客访问: 971043
  • 博文数量: 214
  • 博客积分: 10173
  • 博客等级: 上将
  • 技术积分: 1867
  • 用 户 组: 普通用户
  • 注册时间: 2007-06-18 13:48
文章分类

全部博文(214)

文章存档

2012年(1)

2010年(13)

2009年(5)

2008年(98)

2007年(97)

分类: LINUX

2008-03-31 16:49:11

作者:chenzhufly(空灵)发表于2008/03/31 email:

不知道为什么,我的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 <>");
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
同时小灯也亮起来啦...呵呵
 
 
 
阅读(1631) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~