注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

deisp的博客

 
 
 

日志

 
 

嵌入式linux 2.6.14驱动程序的编绎进内核的方法(字符设备)  

2008-05-26 23:36:45|  分类: 驱动程序 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

 

 /*  此程序实现四个发光管轮流发光*/    编绎GCC ARM 3.3.2
 1.驱动程序

//-------------------------------------

#include <linux/module.h>
#include <linux/fs.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/rtc.h>
#include <linux/bcd.h>
#include <linux/delay.h>
#include <linux/devfs_fs_kernel.h>

#include <asm/hardware.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/rtc.h>
#include <asm/mach/time.h>
#include <asm/hardware/clock.h>
#include <asm/arch/regs-gpio.h>

#define   LED1  0x01
#define   LED2  0x02
#define   LED3  0x04
#define   LED4  0x08

static int matrix_led_major = 0;
static unsigned char led_status = 0;

static void set_led_status(unsigned char status)
{
 unsigned char led_status_changed;
 led_status_changed = led_status ^ (status & 0x0F);
 led_status = status & 0x0F;

 if(led_status_changed != 0x00)
 {
  if(led_status_changed & LED1)
  {
   if(led_status & LED1)
    s3c2410_gpio_setpin(S3C2410_GPF4,0);
   else
    s3c2410_gpio_setpin(S3C2410_GPF4,1);
  }

  if(led_status_changed & LED2)
  {
   if(led_status & LED2)
    s3c2410_gpio_setpin(S3C2410_GPF5,0);
   else
    s3c2410_gpio_setpin(S3C2410_GPF5,1);
  }
 
  if(led_status_changed & LED3)
  {
   if(led_status & LED3)
    s3c2410_gpio_setpin(S3C2410_GPF6,0);
   else
    s3c2410_gpio_setpin(S3C2410_GPF6,1);
  }
 
  if(led_status_changed & LED4)
  {
   if(led_status & LED4)
    s3c2410_gpio_setpin(S3C2410_GPF7,0);
   else
    s3c2410_gpio_setpin(S3C2410_GPF7,1);
  }
 }
}

static int matrix_led_open(struct inode *inode,struct file *filp)
{
 return 0;
}

static int matrix_led_release(struct inode *inode,struct file *filp)
{
 return 0;
}

static ssize_t matrix_led_read(struct file *filp,char *buff,size_t count,loff_t *offp)
{
 copy_to_user(buff,(char *)&led_status,sizeof(unsigned char));
 return sizeof(unsigned char);
}

static ssize_t matrix_led_write(struct file *filp,const char *buff,size_t count,loff_t *offp)
{
 unsigned char status;
 if(count == 1)
 {
  if(copy_from_user(&status,buff,sizeof(unsigned char)))
   return -EFAULT;
  set_led_status(status);
  return sizeof(unsigned char);
 }
 else
  return -EFAULT;
}

static struct file_operations matrix_led_fops = {
 .owner  = THIS_MODULE,
 .open    = matrix_led_open,
 .read    = matrix_led_read,
 .write = matrix_led_write,
 .release = matrix_led_release,
};

static int __init matrix_led_init(void)
{
   int ret;

   ret = register_chrdev(0,"led",&matrix_led_fops);
 if(ret < 0)
 {
  printk("matrix_led: can't get major number\n");
  return ret;
 }
 matrix_led_major = ret;

 #ifdef CONFIG_DEVFS_FS
 ret = devfs_mk_cdev(MKDEV(matrix_led_major,0),S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP,"led");
 if(ret)
 {
  unregister_chrdev(matrix_led_major,"led");
  printk("matrix_led: can't make char device fo devfs\n");
  return ret;
 }
 #endif

 s3c2410_gpio_cfgpin(S3C2410_GPB7,S3C2410_GPB7_OUTP);
 s3c2410_gpio_cfgpin(S3C2410_GPB8,S3C2410_GPB8_OUTP);
 s3c2410_gpio_cfgpin(S3C2410_GPB9,S3C2410_GPB9_OUTP);
 s3c2410_gpio_cfgpin(S3C2410_GPB10,S3C2410_GPB10_OUTP);
 s3c2410_gpio_setpin(S3C2410_GPB7,1);
 s3c2410_gpio_setpin(S3C2410_GPB8,1);
 s3c2410_gpio_setpin(S3C2410_GPB9,1);
 s3c2410_gpio_setpin(S3C2410_GPB10,1);
 led_status = 0x00;

 printk("led: the matrix led initialized\n");
 return 0;
}

static void __exit matrix_led_exit(void)
{
 set_led_status(~(LED1 | LED2 | LED3 | LED4));
 #ifdef CONFIG_DEVFS_FS
                //devfs_remove("led/%d",0);
  devfs_remove("led");
 #endif
 unregister_chrdev(matrix_led_major,"led");
 printk("led: the matrix led driver exit\n");
}

module_init(matrix_led_init);
module_exit(matrix_led_exit);

MODULE_ALIAS("matrix_led");
MODULE_DESCRIPTION("The Matrix LED Driver");
MODULE_AUTHOR("jjj.<jjjstudio@163.com>");
MODULE_LICENSE("GPL");

 2.驱动程序 Makefile


ifneq ($(KERNELRELEASE),)
    obj-m :=led.o
else
 KERNELDIR ?=/2.6.14

 PWD := $(shell pwd)
all:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
 rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
endif

3.测试程序


#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/delay.h>
//#include <linux/dela2y.h>^M
#include <linux/fcntl.h>
#include <linux/kernel.h>


int main(int argc, char** argv)

{ int fd;
 unsigned char i = 0;
 unsigned char status;

 fd = open("/dev/led",O_RDWR);
 if(fd < 0)
 {
  printf("Can't open the matrix led drivers!\n");
  return fd;
 }

 while(1)
 {
  i = (i+1)&0x0F;
  write(fd,&i,1);
  if(read(fd,&status,1) != 0)
   printf("led status: %25x\n",status);
            usleep(1000000);
 //  msleep(1000);
 
 } 
 close(fd); 
 return 0; 
}
4.测试程序 Makefile


CFLAGS  = -O -Wall
CC      = arm-linux-gcc
LD      = arm-linux-ld


all:kd 

kd: kd.c
 $(CC) $(CFLAGS) -o kd kd.c

clean:
 rm -f *.o *~ kd

 

1.     把写好的驱动程序led.c,COPY到DRIVERS –>CHAR 目录下面。

2.     在该目录下的Makefile  中适当位置加入一行obj-$(CONFIG_LIUDEFANG) += led.o 意思是如果LIUDEFANG 配置为Y 则编绎led.c  的连接文件led.o

3.     在该目录下的Kconfig 文件中加入菜单项

menu "Character devices"

config LIUDEFANG

     <tab>   bool "my led test ! liudefang"

4.     《这一步不加也没事啊》在该目录下的mem.c 中加入驱动程序的初始化程序这样进入系统后就可以直接

#ifdef CONFIG_LIUDEFANG

extern int __init matrix_led_init(void);

#endif

#ifdef CONFIG_LIUDEFANG

int __init matrix_led_init();

#endif

 

 

 

  评论这张
 
阅读(912)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017