驱动开发day1

头文件

cs 复制代码
#ifndef __HEAD_H__
#define __HEAD_H__
#define PHY_LED1_MODER 0X50006000
#define PHY_LED1_ODR   0X50006014

#define PHY_LED2_MODER 0x50007000
#define PHY_LED2_ODR   0x50007014

#define PHY_LED3_MODER 0x50006000
#define PHY_LED3_ODR   0x50006014

#define PHY_RCC        0X50000A28

#endif

demo1.c

cs 复制代码
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include "head.h"

unsigned int major;
char kbuf[128]={};
//定义指针指向映射后的虚拟内存
unsigned int *vir_moder1;
unsigned int *vir_odr1;
unsigned int *vir_moder2;
unsigned int *vir_odr2;
unsigned int *vir_moder3;
unsigned int *vir_odr3;
unsigned int *vir_rcc;

//封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        return 0;
}
ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        int ret;
        ret=copy_to_user(ubuf,kbuf,size);
        if(ret)
        {
                printk("copy_to_user filed\n");
                return -EIO;
        }
        return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
        printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
        int ret;
        ret=copy_from_user(kbuf, ubuf,size);
        if(ret)
        {
                printk("copy_from_user filed\n");
                return -EIO;  
        }
        if (kbuf[1] == '0')
        {
                // 关灯逻辑
				if (kbuf[0] == '1')
                	(*vir_odr1) &= (~(0X1<<10));
				else if (kbuf[0] == '2')
                	(*vir_odr2) &= (~(0X1<<10));
				else if (kbuf[0] == '3')
                	(*vir_odr3) &= (~(0X1<<8));
        }
        else if (kbuf[1] == '1')
        {
                // 开灯逻辑
				if (kbuf[0] == '1')
                	(*vir_odr1) |= (0X1<<10);
				else if (kbuf[0] == '2')
					(*vir_odr2) |= (0X1<<10);
				else if (kbuf[0] == '3')
                	(*vir_odr3) |= (0X1<<8);
        }
        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,
        .read=mycdev_read,
        .write=mycdev_write,
        .release=mycdev_close,
};

//入口函数,安装内核模块时执行
static int __init mycdev_init(void)
{       
        //注册字符设备驱动
        major = register_chrdev(0, "mychrdev", &fops);
        if(major < 0)
        {
                printk("字符设备驱动注册失败\n");
        }
        printk("注册字符设备驱动成功major=%d\n",major);

        // 进行寄存器的地址映射
        vir_moder1 = ioremap(PHY_LED1_MODER, 4);
        if (vir_moder1 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        vir_odr1 = ioremap(PHY_LED1_ODR, 4);
        if (vir_odr1 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        vir_rcc = ioremap(PHY_RCC, 4);
        if (vir_rcc == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        printk("寄存器内存映射成功\n");

        //LED1寄存器初始化
        (*vir_rcc) |= (0X3<<4);//GPIOE控制器时钟使能
        (*vir_moder1) &= (~(0X3<<20));//MODER[21:20]->00
        (*vir_moder1) |= (0X1<<20);//MODER[21:20]->01
        (*vir_odr1) &= (~(0X1<<10));//默认关灯

        vir_moder2 = ioremap(PHY_LED2_MODER, 4);
        if (vir_moder2 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        vir_odr2 = ioremap(PHY_LED2_ODR, 4);
        if (vir_odr2 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        //LED2
        (*vir_moder2) &= (~(0X3<<20));//MODER[21:20]->00
        (*vir_moder2) |= (0X1<<20);//MODER[21:20]->01
        (*vir_odr2) &= (~(0X1<<10));//默认关灯

        vir_moder3 = ioremap(PHY_LED3_MODER, 4);
        if (vir_moder3 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        vir_odr3 = ioremap(PHY_LED3_ODR, 4);
        if (vir_odr3 == NULL)
        {
                printk("物理内存地址映射失败%d\n", __LINE__);
                return -EFAULT;
        }
        //LED3
        (*vir_moder3) &= (~(0X3<<16));//MODER[21:20]->00
        (*vir_moder3) |= (0X1<<16);//MODER[21:20]->01
        (*vir_odr3) &= (~(0X1<<8));//默认关灯

        return 0;
}

//出口函数,卸载内核模块时执行
static void __exit mycdev_exit(void)
{
        //取消内存映射
        iounmap(vir_moder1);
        iounmap(vir_odr1);

        iounmap(vir_moder2);
        iounmap(vir_odr2);

        iounmap(vir_moder3);
        iounmap(vir_odr3);

        iounmap(vir_rcc);
	//注销字符设备驱动
        unregister_chrdev(major,"mychrdev");
}

//用于声明入口函数
module_init(mycdev_init);
//用于声明出口函数
module_exit(mycdev_exit);
//声明当前内核模块遵循GPL协议
MODULE_LICENSE("GPL");

text.c

cs 复制代码
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int fd = open("/dev/mychrdev", O_RDWR);
    if (fd < 0)
    {
        printf("打开设备文件失败\n");
        return -1;
    }
    printf("打开设备文件成功\n");
    while(1)
    {
        printf("请输入要进行的操作:0(关灯)1(开灯)>");
        fgets(buf,sizeof(buf),stdin);
        buf[strlen(buf)-1] = '\0';

        //调用write
        write(fd, buf, sizeof(buf));
        //memset(buf, 0, sizeof(buf));
        //read(fd, buf, sizeof(buf));
        //printf("buf:%s\n",buf);
    }
    //调用close
    close(fd);
    return 0;
}
相关推荐
sukalot13 小时前
window显示驱动开发—显示适配器的子设备
驱动开发
Evan_ZGYF丶1 天前
【RK3576】【Android14】如何在Android14下单独编译kernel-6.1?
linux·驱动开发·android14·rk3576
sukalot2 天前
window显示驱动开发—视频呈现网络简介
驱动开发
sukalot2 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(二)
驱动开发
zwhSunday2 天前
Linux驱动开发(1)概念、环境与代码框架
linux·运维·驱动开发
sukalot3 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(三)
驱动开发
sukalot3 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(一)
驱动开发
cxr8284 天前
基于Claude Code的 规范驱动开发(SDD)指南
人工智能·hive·驱动开发·敏捷流程·智能体
zwhSunday4 天前
Linux驱动开发(2)进一步理解驱动
linux·驱动开发
被遗忘的旋律.5 天前
Linux驱动开发笔记(十)——中断
linux·驱动开发·笔记