驱动练习 小灯闪烁

这篇博客介绍了如何在Linux内核中开发一个字符设备驱动,包括初始化、打开、关闭操作以及I/O控制。代码展示了ioremap函数用于内存映射,并实现了控制LED灯的开关以及用户空间与内核空间的数据交换。同时,提供了用户空间的测试程序进行交互操作。
摘要由CSDN通过智能技术生成

#include<linux/module.h>
#include<linux/init.h>
#include<linux/fs.h>
#include<linux/uaccess.h>
#include<linux/io.h>
#include<linux/device.h>
#include"head.h"

#define RED_BASE 0xC001A000
#define GREEN_BASE 0xC001E000
#define BLUE_BASE  0xC001B000

unsigned int *red_base=NULL;
unsigned int *green_base=NULL;
unsigned int *blue_base=NULL;
struct class *cls;
struct device *dev;
char kbuf[128]={0};


#define CNAME "hello"
int major=0;
int mycdev_open(struct inode *inode,struct file *file)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
}
long mycdev_ioctl(struct file *file,unsigned int request,unsigned long args)
{
        int ret;
        switch(request)
        {
                case RLED_ON:
                        *red_base |=(1<<28);
                        break;
                case RLED_OFF:
                        *red_base &=~(1<<28);
                        break;
                case ACCESS_R:
                        ret=copy_to_user((void *)args,kbuf,sizeof(kbuf));
                        if(ret)
                        {
                                printk("to fail\n");
                                return -EAGAIN;
                        }
                        break;
                case ACCESS_W:
                        ret=copy_from_user(kbuf,(void *)args,sizeof(kbuf));
                        if(ret)
                        {
                              printk("to fail\n");
                                return -EAGAIN;
                        }
                        break;
                case ACCESS_W:
                        ret=copy_from_user(kbuf,(void *)args,sizeof(kbuf));
                        if(ret)
                        {
                                printk("from fail\n");
                                return -EAGAIN;
                        }
                        break;
        }
        return 0;
}
int mycdev_close(struct inode *inode, struct file *file)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
                                               }
int mycdev_close(struct inode *inode, struct file *file)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
}
const struct file_operations fops=
{
        .open=mycdev_open,
//      .read=mycdev_read,
//      .write=mycdev_write,
        .unlocked_ioctl=mycdev_ioctl,
        .release=mycdev_close,
};
static int __init mycdev_init(void)
{
        //注册字符设备驱动
        major=register_chrdev(major,CNAME,&fops);
        if(major<0)
        {
                printk("register char device err\n");
                return major;
        }
        red_base=ioremap(RED_BASE,36);
                                                          

       if(red_base==NULL)
        {
                printk("red ioremap err\n");
                return -ENOMEM;
        }
        blue_base=ioremap(BLUE_BASE,36);
        if(blue_base==NULL)
        {
                printk("blue ioremap err\n");
                return -ENOMEM;
        }
        green_base=ioremap(GREEN_BASE,36);
        if(green_base==NULL)
        {
                printk("green ioremap err\n");
                return -ENOMEM;
        }
        *red_base &=~(1<<28);
        *(red_base+1) |=(1<<28);
        *(red_base+9)&=~(3<<24);

        *blue_base &=~(1<<12);

         *(blue_base+1) |=(1<<12);
        *(blue_base+8)&=~(3<<24);
        *(blue_base+8) |=(1<<25);

        *green_base &=~(1<<13);
        *(green_base+1) |=(1<<13);
        *(green_base+8)&=~(3<<26);
        //自动开设备节点
        cls=class_create(THIS_MODULE,CNAME);
        if(IS_ERR(cls))
        {
                printk("FAIL\n");
                return PTR_ERR(cls);
        }
        dev=device_create(cls,NULL,MKDEV(major,0),NULL,CNAME);

        if(IS_ERR(cls))
        {
                printk("FAIL\n");
                return PTR_ERR(dev);
        }
        return 0;
}
     

static void  __exit mycdev_exit(void)
{
        device_destroy(cls,MKDEV(major,0));
        class_destroy(cls);
        iounmap(green_base);
        iounmap(blue_base);
        iounmap(red_base);
        //注销字符设备驱动
        unregister_chrdev(major,CNAME);
}

module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

———————————————————————————————————————————

 1 #ifndef __HEAD_H__
  2 #define __HEAD_H__
  3 #define type 'a'
  4 #define RLED_ON _IO(type,0)
  5 #define RLED_OFF _IO(type,1)
  6 
  7 #define ACCESS_R _IOR(type,0,char *)
  8 #define ACCESS_W _IOW(type,0,char *)
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 #endif
———————————————————————————————————————————

#include <stdio.h>
  2 #include <sys/types.h>
  3 #include <sys/stat.h>
  4 #include <fcntl.h>
  5 #include <unistd.h>
  6 #include <string.h>
  7 #include <sys/ioctl.h>
  8 #include "head.h"
  9 int main(int argc,const char *argv[])
 10 {
 11         int fd;
 12         char buf[128]="Fuck You bitch";
 13 //      int a=66;
 14         fd=open("/dev/hello",O_RDWR);
 15         if(fd==-1)
 16         {
 17                 perror("open err\n");
 18                 return -1;
 19         }
 20         while(1)
 21         {
 22 //              write(fd,buf,sizeof(buf));
 23                 ioctl(fd,RLED_ON);
 24                 sleep(1);                             

                      ioctl(fd,RLED_OFF);
 26                 sleep(1);
 27                 ioctl(fd,ACCESS_W,buf);
 28                 memset(buf,0,sizeof(buf));
 29                 ioctl(fd,ACCESS_R,buf);
 30                 printf("%s\n",buf);
 31 //              buf[0]=buf[0]?0:1;
 32         }

 43         close(fd);
 44         return 0;
 45 }
———————————————————————————————————————————

  1 #KERNELDIR:=/lib/modules/$(shell uname -r)/build/
  2 KERNELDIR:=/opt/source/kernel-3.4.39/
  3 PWD:=$(shell pwd)
  4 all:
  5         make -C $(KERNELDIR) M=$(PWD) modules
  6 clean:
  7         
  8         make -C $(KERNELDIR) M=$(PWD) clean
  9 
 10 obj-m:=mydev.o
~                     

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值