创建一个杂项字符设备模版

来源:互联网 发布:seo分析工具 编辑:程序博客网 时间:2024/06/11 03:41

#include <linux/module.h>

#include <linux/init.h>

//包含必须的头文件
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <asm/uaccess.h>
#include <asm/io.h>

//asm/io.h中定义, 用于把物理址映射 成虚拟地址,cookie--物理地址,size--虚拟地址,
//#define ioremap(cookie,size)      __arm_ioremap((cookie), (size), MT_DEVICE)

unsigned long *base_addr = NULL;     //存放物理地址对应的虚拟地址

//按照数据手册定义寄存器指针
#define    BASE_ADDR       (0x110002E0)     //GPM4CON起始 地址
#define    GPM4CON         (*( volatile unsigned *)(base_addr+0))
#define    GPM4DAT         (*( volatile unsigned *)(base_addr+1))

//以下是文件操作方法的具体实现代码
static int xxx_open(struct inode *pinode, struct file *pfile )
{
    printk(KERN_EMERG"file:%s\r\nline:%d, %s is call\n", __FILE__, __LINE__, __FUNCTION__);


    //把 BASE_ADDR 物理地址映射成虚拟地址,大小为0x18
    base_addr = (unsigned long *) ioremap(BASE_ADDR, 0x8);


    GPM4CON  &= ~0xffff;  //清0
    GPM4CON  |=  0x1111;  //配置为输出方向
    GPM4DAT  |=  0xf ;    //配置为输出方向
    return 0;
}


static int xxx_release (struct inode *pinode, struct file *pfile)
{
    printk(KERN_EMERG"file:%s\r\nline:%d, %s is call\n", __FILE__, __LINE__, __FUNCTION__);
    iounmap(base_addr);   //释放映射后的虚拟地址空间
    return 0;
}

//文件操作方法集合指针

static const struct file_operations mymisc_fops = {
    .open           =   xxx_open,
    .release        =   xxx_release,
};
//定义核心结构
static struct miscdevice  misc = {
    .minor = 255,
    .name  = "myleds",     ///dev目录下的设备名
    .fops  = &mymisc_fops,
};


static int __init mymisdevice_init(void)
{
    int ret;

    //注册核心结构
    ret = misc_register(&misc);
    if(ret < 0) {
        printk(KERN_EMERG"misc_register error\n");
        return ret;
    }
    printk(KERN_EMERG"misc_register  ok\n");
    return 0;
}


static void __exit mymisdevice_exit(void)
{
    int ret;

    //注销核心结构
    ret = misc_deregister(&misc);
    if(ret < 0) {
        printk(KERN_EMERG"misc_deregister error\n");
        return ;
    }
    printk(KERN_EMERG"misc_deregister ok\n");
}

module_init(mymisdevice_init);
module_exit(mymisdevice_exit);

MODULE_LICENSE("GPL");


#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>    //lseek
#include <sys/ioctl.h> //ioctl

int fd;                      //存放文件描述符号
char save_buf[10]={0};     //存放数据使用

int main(void)
{
  int ret;
  int i;
  //传递‘1’,‘0’表示对灯控制命令,‘1’表示灯亮, ‘0’表示灯灭 
  char  t_buf[5] = {'1','0','1','0',0};  //要的灯状态是 亮灭亮灭
  
fd = open("/dev/myleds",O_RDWR); //以读写方式进行打开
if(fd < 0){
printf("open error\r\n");
return -1;
}

  //写入4个灯控制状态:亮灭亮灭
  write(fd,t_buf,4);


  //回读当前的4个灯状态
read(fd,save_buf,4);

//判断读取回来的结果
for(i=0;i<4;i++)
{
if(save_buf[i] == '0')
printf("led %d off\n",i);
else if(save_buf[i] == '1')
printf("led %d on\n",i);
}

  //关闭文件
close(fd);

return 0;

}


# Makefile 2.6
#hello是模块名,也是对应的c文件名。 
obj-m += drv_leds.o     

# KDIR  内核源码路径,根据自己需要设置
# X86 源码路径统一是/lib/modules/$(shell uname -r)/build
#如果要编译ARM的模块,则修改成ARM的内核源码路径 
#KDIR  :=/lib/modules/$(shell uname -r)/build
KDIR  := /root/work/linux-3.5_xyd_modversion/
all:
@make -C $(KDIR) M=$(PWD) modules   
@rm -rf  .tmp_versions *.o *.mod.o *.mod.c  *.bak *.symvers *.markers *.unsigned *.order *~ .*.*.cmd .*.*.*.cmd
arm-linux-gcc app.c -o app
cp app *.ko /root/work/rootfs/home

clean:
make -C  $(KDIR)   M=$(PWD)  modules  clean
@rm -rf app *.ko .tmp_versions *.o *.mod.o *.mod.c  *.bak *.symvers *.markers *.unsigned *.order *~ .*.*.cmd .*.*.*.cmd

原创粉丝点击