驱动day4

头文件:

#ifndef __HEAD_H__
#define __HEAD_H__ 
typedef struct{
    unsigned int MODER;
    unsigned int OTYPER;
    unsigned int OSPEEDR;
    unsigned int PUPDR;
    unsigned int IDR;
    unsigned int ODR;
}gpio_t;
#define PHY_LED1_ADDR 0X50006000
#define PHY_LED2_ADDR    0X50007000
#define PHY_LED3_ADDR 0X50006000
#define PHY_RCC_ADDR    0X50000A28

// 构建开灯关灯的功能码
#define LED_ON _IOW('l', 1,int)
#define LED_OFF _IOW('l', 0,int)
#endif 

运行代码:

#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
#include "head.h"

int main(int argc, char const *argv[])
{
    char buf[128]={0};
    int a,b,fd;
    if(fd<0)
    {
        printf("打开设备文件失败\n");
        exit(-1);
    }

    while(1)
    {
        fd=-1;
        //从终端读取
        printf("请输入要实现的功能 ");
        printf("0(关灯) 1(开灯)\n");
        printf("请输入>");
        scanf("%d",&a);
        printf("请选择要控制的灯:1(LED1)2(LED2) 3(LED3)\n");
        printf("请输入>");
        scanf("%d",&b);
        switch(b)
        {
            case 1:
                fd=open("/dev/burger0",O_RDWR);
                if(a == 0)
                {   
                   ioctl(fd,LED_ON,&b);
                    break;
                }
                else
                {
                    ioctl(fd,LED_OFF,&b);
                    break;
                }
            case 2:
                fd=open("/dev/burger1",O_RDWR);
                if(a == 0)
                {   
                   ioctl(fd,LED_ON,&b);
                    break;
                }
                else
                {
                    ioctl(fd,LED_OFF,&b);
                    break;
                }
            case 3:
                fd=open("/dev/burger2",O_RDWR);
                if(a == 0)
                {   
                   ioctl(fd,LED_ON,&b);
                    break;
                }
                else
                {
                    ioctl(fd,LED_OFF,&b);
                    break;
                }
        }
        close(fd);
    }
    close(fd);
    return 0;
}

驱动代码:

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

char kbuf[128]={0};
gpio_t *vir_led1;
gpio_t *vir_led2;
gpio_t *vir_led3;
unsigned int *vir_rcc;
unsigned int major=0;
unsigned int minor=0;
struct cdev *mychdev;
struct class *cls;
struct device *dev;
dev_t devno;
int mycdev_open(struct inode *inode, struct file *file)
{
    int min=MINOR(inode->i_rdev);//获取打开的的文件的次设备号
    file->private_data= (void *)min;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}
long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    int min=(int)file->private_data;//获取到文件的次设备号
    switch(min)
    {
        case 0: //控制LED1
            switch(cmd)
            {
                case LED_ON:  //开灯
                    vir_led1->ODR |= 1<<10;
                    break;
                case LED_OFF: //关灯
                    vir_led1->ODR &= (~(1<<10));
                    break;
            }
            break;
        case 1:  //控制LED2
            switch(cmd)
            {
                case LED_ON:  //开灯
                    vir_led2->ODR |= 1<<10;
                    break;
                case LED_OFF: //关灯
                    vir_led2->ODR &= (~(1<<10));
                    break;
            }
            break;
        case 2:  //控制LED3
            switch(cmd)
            {
                case LED_ON:  //开灯
                    vir_led3->ODR |= 1<<8;
                    break;
                case LED_OFF: //关灯
                    vir_led3->ODR &= (~(1<<8));
                    break;
            }
            break;
    }
     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;
}

//定义操作方法结构体变量并赋值
struct file_operations fops = {

    .open = mycdev_open,
    .unlocked_ioctl = mycdev_ioctl,
    .release = mycdev_close,
};

int all_led_init(void)
{
    //寄存器地址的映射
    vir_led1=ioremap(PHY_LED1_ADDR,sizeof(gpio_t));
    if(vir_led1==NULL)
    {
        printk("ioremap filed:%d\n",__LINE__);
        return -ENOMEM;
    }
     vir_led2=ioremap(PHY_LED2_ADDR,sizeof(gpio_t));
    if(vir_led2==NULL)
    {
        printk("ioremap filed:%d\n",__LINE__);
        return -ENOMEM;
    }
     vir_led3=vir_led1;
    vir_rcc=ioremap(PHY_RCC_ADDR,4);
    if(vir_rcc==NULL)
    {
        printk("ioremap filed:%d\n",__LINE__);
        return -ENOMEM;
    }
    printk("物理地址映射成功\n");
    //寄存器的初始化
    //rcc
    (*vir_rcc) |= (3<<4);
    //led1
    vir_led1->MODER &= (~(3<<20));
    vir_led1->MODER |= (1<<20);
    vir_led1->ODR &= (~(1<<10));
    //led2
    vir_led2->MODER &= (~(3<<20));
    vir_led2->MODER |= (1<<20);
    vir_led2->ODR &= (~(1<<10));
    //led3
    vir_led3->MODER &= (~(3<<16));
    vir_led1->MODER |= (1<<16);
    vir_led1->ODR &= (~(1<<8));
    printk("寄存器初始化成功\n");

    return 0;
}

static int __init mycdev_init(void)
{
    int ret;
    //1.申请一个对象空间cdev_alloc
    mychdev=cdev_alloc();
    if(mychdev == NULL)
    {
        printk("申请字符设备驱动对象失败\n");
        ret = -EFAULT;
        goto out1;
    }
    printk("申请字符设备驱动对象成功\n");
    //2.初始化对象cdev_init
    cdev_init(mychdev,&fops);
    //3.申请设备号  register_chrdev_region()/alloc_chrdev_region()
    if(major == 0)
    {
        ret = alloc_chrdev_region(&devno,minor,3,"burger");
        if(ret)
        {
            printk("动态申请设备号失败\n");
            goto out2;
        }
        major=MAJOR(devno);
        minor=MINOR(devno);
    }
    else
    {
        ret = register_chrdev_region(MKDEV(major,minor),3,"burger");
        if(ret)
        {
            printk("静态申请设备号失败\n");
            goto out2;
        }
    }
    printk("申请设备号成功\n");
    //4.注册驱动对象  cdev_add
    ret = cdev_add(mychdev,MKDEV(major,minor),3);
    if(ret)
    {
        printk("注册字符设备驱动对象失败\n");
        goto out3;
    }
    printk("注册字符设备驱动对象成功\n");
    //5.向上提交目录  class_create
    cls=class_create(THIS_MODULE,"burger");
    if(IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        goto out4;
    }
    printk("向上提交目录成功\n");
    //6.向上提交设备节点信息  device_create
    int i;  //向上提交三次设备节点信息
    for(i=0;i<3;i++)
    {
        dev=device_create(cls,NULL,MKDEV(major,i),NULL,"burger%d",i);
        if(IS_ERR(dev))
        {
            printk("向上提交节点失败\n");
            goto out5;
        }
    }
     printk("向上提交节点成功\n");
	return 0;
out5:
    for(--i;i>=0;i--)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    class_destroy(cls);
out4:
    cdev_del(mychdev);
out3:
    unregister_chrdev_region(MKDEV(major,minor),3);
out2:
    kfree(mychdev);
out1:
    return ret;
}
static void __exit mycdev_exit(void)
{
    //取消地址映射
    iounmap(vir_led1);
    iounmap(vir_led2);
    iounmap(vir_rcc);
    //注销字符设备驱动
    int i;
    for(i=0;i<3;i++)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    class_destroy(cls);
    cdev_del(mychdev);
    unregister_chrdev_region(MKDEV(major,minor),3);
    kfree(mychdev);


}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");
相关推荐
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习
GoppViper1 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
羊小猪~~2 小时前
深度学习基础案例5--VGG16人脸识别(体验学习的痛苦与乐趣)
人工智能·python·深度学习·学习·算法·机器学习·cnn
Charles Ray2 小时前
C++学习笔记 —— 内存分配 new
c++·笔记·学习
我要吐泡泡了哦3 小时前
GAMES104:15 游戏引擎的玩法系统基础-学习笔记
笔记·学习·游戏引擎
骑鱼过海的猫1233 小时前
【tomcat】tomcat学习笔记
笔记·学习·tomcat
贾saisai5 小时前
Xilinx系FPGA学习笔记(九)DDR3学习
笔记·学习·fpga开发
北岛寒沫6 小时前
JavaScript(JS)学习笔记 1(简单介绍 注释和输入输出语句 变量 数据类型 运算符 流程控制 数组)
javascript·笔记·学习
铁匠匠匠7 小时前
从零开始学数据结构系列之第六章《排序简介》
c语言·数据结构·经验分享·笔记·学习·开源·课程设计
架构文摘JGWZ8 小时前
Java 23 的12 个新特性!!
java·开发语言·学习