驱动开发day3

news2024/11/19 15:16:27
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include<linux/io.h>
#include <linux/device.h>
#include "led.h"

int major;
char kbuf[256] = {0};

//定义指针接收映射成功的虚拟内存首地址
unsigned int *vir_GPIOE;
unsigned int *vir_GPIOF;
unsigned int *vir_Rcc;

GPIO_TypeDef* GPIOE_Init;
GPIO_TypeDef* GPIOF_Init;

//定义创建设备结点指针
struct class* cls;
struct device* dev;

int mycdev_open(struct inode *inode, struct file *file)
{
    printk("%s:%d\n",__func__,__LINE__);
    return 0;
}

ssize_t mycdev_read(struct file *file,char* ubuf,size_t size,loff_t* lof)
{
    int ret;
    ret = copy_to_user(ubuf,kbuf,size);
    if(ret)
    {
        printk("copy_to_user filad\n"); 
    }   
    
    return 0;
}

ssize_t mycdev_write(struct file *file,const char* ubuf,size_t size,loff_t* lof)
{
    int ret;
    ret = copy_from_user(kbuf,ubuf,size);
    if(ret)
    {
        printk("copy_from_user filad\n"); 
    }   
    switch(kbuf[0])
    {
        case '0' :
            if(kbuf[1] == '1')
            {
                
                GPIOE_Init->ODR |= (0x01 << 10);
            }else
            {
                GPIOE_Init->ODR &= (~(0x01 << 10));
            }
        break; 

        case '1' :
            if(kbuf[1] == '1')
            {
                
                GPIOE_Init->ODR |= (0x01 << 8);
            }else
            {
                GPIOE_Init->ODR &= (~(0x01 << 8));
            }
        break; 

        case '2' :
            if(kbuf[1] == '1')
            {
                
                GPIOF_Init->ODR |= (0x01 << 10);
            }else
            {
                GPIOF_Init->ODR &= (~(0x01 << 10));
            }
        break; 
    }
    return 0;
}

int mycdev_close(struct inode *inode, struct file *file)
{
    printk("%s:%d\n",__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)
{
    int i=0;
    /*注册字符设备驱动*/
    major = register_chrdev(0,"mychrdev",&fops);
    if(major < 0)
    {
        printk("字符设备注册失败\n");
        return major;
    }
    printk("字符设备注册完成 major:%d\n",major);

    /*映射虚拟地址到物理地址*/
    vir_GPIOE = ioremap(GPIOE,4);//GPIOE
    if(vir_GPIOE == NULL)
    {
       printk("地址映射失败:GPIOE!\n");
        return -EFAULT;
    }
    GPIOE_Init = (GPIO_TypeDef*)vir_GPIOE;

    vir_GPIOF = ioremap(GPIOF,4);//GPIOF
    if(vir_GPIOF == NULL)
    {
       printk("地址映射失败:GPIOF!\n");
        return -EFAULT;
    }
    GPIOF_Init = (GPIO_TypeDef*)vir_GPIOF;

    vir_Rcc = ioremap(RCC_MP_AHB4_ENSETR,4);//RCC
    if(vir_Rcc == NULL)
    {
       printk("地址映射失败:RCC_MP_AHB4_ENSETR!\n");
        return -EFAULT;
    }

    /*自动创建字符设备*/
    //提交目录信息
    cls = class_create(THIS_MODULE,"mycdev");
    if(IS_ERR(cls))
    {
       printk("目录提交失败!\n");
       return -PTR_ERR(cls); 
    }
    //提交设备信息
    for(i=0;i<3;i++)
    {
        dev = device_create(cls,NULL,MKDEV(major,i),NULL,"mycdev%d",i);
        if(IS_ERR(dev))
        {
            printk("设备信息提交失败 devID:%d\n",i);
            return -PTR_ERR(dev);
        }
    }
    printk("设备信息提交完成 devID:%d\n",i);

    /*初始化GPIO*/
    (*vir_Rcc) |= (3 << 4);//初始化RCC时钟

    GPIOE_Init->MODER &= (~(0x03 << 20));
    GPIOE_Init->MODER |= (0x01 << 20);

    GPIOE_Init->MODER &= (~(0x03 << 16));
    GPIOE_Init->MODER |= (0x01 << 16);

    GPIOF_Init->MODER &= (~(0x03 << 20));
    GPIOF_Init->MODER |= (0x01 << 20);

    GPIOE_Init->ODR &= (~(0x01 << 10));
    GPIOE_Init->ODR |= (0x01 << 10);

    GPIOF_Init->ODR &= (~(0x01 << 10));
    GPIOF_Init->ODR |= (0x01 << 10);

    GPIOE_Init->ODR &= (~(0x01 << 8));
    GPIOE_Init->ODR |= (0x01 << 8);
    // (*GPIOF_Init) |= (3 << 4);//初始化GPIOE引脚
    // (*GPIOF_Init) |= (3 << 4);//初始化GPIOF引脚

    return 0;
}

//出口函数 内核模块卸载时执行
static void __exit mycdev_exit(void)
{
    int i=0;
    /*取消物理内存映射*/
    iounmap(vir_GPIOE);
    iounmap(vir_GPIOF);
    iounmap(vir_Rcc);

    /*销毁设备信息*/
    for(i=0;i<3;i++)
    {
        device_destroy(cls,MKDEV(major,i));
    }
    /*销毁设备目录信息*/
    class_destroy(cls);
    /*字符设备驱动足校*/
    unregister_chrdev(major,"mychrdev");
}

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

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

int main(int argc, char const *argv[])
{
    char buf[128] = {0};
    int fd0 = open("/dev/mycdev0", O_RDWR);

    if(fd0 < 0) {
        printf("设备0读取失败\n");
        return -1;
    }

    while(1)
    {
        printf("请输入LED指令>>\n");
        fgets(buf,sizeof(buf),stdin);//从终端读一个字符串存放在buf
        buf[strlen(buf)-1]='\0';
        write(fd0, buf, sizeof(buf));//将从终端得到的字符串传递到驱动
        
    }
    close(fd0);
    
    return 0;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/886201.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【HarmonyOS北向开发】-01 HarmonyOS概述

飞书原文链接-【HarmonyOS北向开发】-01 HarmonyOS概述https://fvcs2dhq8qs.feishu.cn/docx/TDf2d2KMaoPSUUxnvg2cASDdnCe?fromfrom_copylink

k8s 自身原理之高可用

说到高可用&#xff0c;咱们在使用主机环境的时候&#xff08;非 k8s&#xff09;&#xff0c;咱做高可用有使用过这样的方式&#xff1a; 服务器做主备部署&#xff0c;当主节点和备节点同时存活的时候&#xff0c;只有主节点对外提供服务&#xff0c;备节点就等着主节点挂了…

Typora上传文件到Gitee

工作内容,不对外开放 一、Typora上传笔记到CSDN 一、安装node.js 官网链接:Node.js (nodejs.org) 下载后得到一个.msi文件,双击即可。 win + R 打开CMD,基于node -v 和npm -v,验证是否安装成功: 二、配置Gitee 1、新建仓库 2、开源此仓库 2.1、初始化readme文件

测试微信个人收款,实现静态博客文章付费和及时显示

1. 个人微信收款&#xff0c;不需要微信认证&#xff0c;这里通过赞赏码 2. hugo实现静态博客&#xff0c;付费功能是需要服务器动态实现的&#xff0c;可通过第三方实现 3. 通过javascript调用服务器&#xff0c;实现付费后即时显示&#xff0c;以及页面显示付费网友信息&am…

股市杠杆操作是什么意思?期货杠杆平台指的是什么?

在股市和期货市场中&#xff0c;杠杆操作是一种常见的投资手段。然而&#xff0c;许多人对于杠杆操作的概念和风险并不清楚。本文将科普股市杠杆操作和期货杠杆平台的相关知识&#xff0c;帮助读者了解其意义和特点。 一、股市杠杆操作的含义 股市杠杆操作是指通过借入资金股票…

EDA软件—Cadence学习笔记分享(内含安装教程)

作为流行的EDA工具之一&#xff0c;Cadence一直以来以其强大的功能受到广大EDA工程师的青睐。Cadence可以完成整个IC设计流程的各个方面。 Cadence 软件是一个功能强大的系统工具&#xff0c;包括很多功能模块&#xff0c;如原理图输入: 数字、模拟及混合电路仿真:自动布局、布…

# 快速评估立功科技基于S32K324的TMS方案

文章目录 1.前言2.立功科技的TMS方案介绍2.1 介绍资料2.2 简要介绍 3.S32K3_TriMotor评估板测试3.1 环境搭建S32 Design Studio for S32 Platform 3.4安装RTD 2.0.0安装Freemaster 3.2 3.2 例程测试3.3 例程适配3.4 双核烧录3.5 测试 1.前言 最近和一些做汽车水泵/风机的客户交…

【Linux命令详解 | wget命令】 wget命令用于从网络下载文件,支持HTTP、HTTPS和FTP协议

文章标题 简介一&#xff0c;参数列表二&#xff0c;使用介绍1. 基本文件下载2. 递归下载整个网站3. 限制下载速率4. 防止SSL证书校验5. 断点续传6. 指定保存目录7. 自定义保存文件名8. 增量下载9. 使用HTTP代理10. 后台下载 总结 简介 在编程世界中&#xff0c;处理网络资源是…

python 各种疑难杂包安装方法与踩坑记录

常用招数&#xff1a; 网络问题&#xff1a;切换网络线路/开关科学、启用/不用国内镜像 包找不到&#xff1a;启用/不用国内镜像、尝试conda、pip、source等多种安装方式 gdal、rasterio 参考链接&#xff1a; python rasterio库安装具体流程 - 知乎 Python安装gdal,raster…

JavaScript读取文件夹和文件、输出文件内容到控制台、showDirectoryPicker、getFile、FileReader、readAsText

文章目录 读取文件夹并输出某个文件内容读取文件及输出内容 读取文件夹并输出某个文件内容 效果图 html <button id"idFolder" class"fs_30 cursor_pointer">选择文件夹</button>JavaScript idFolder.onclick async function () {try {let …

获取excel中的图片(包含wps中嵌入单元格图片)

项目中有excel导入功能,并且需要导入excel中的图片;模板如图: 已知office中插入的图片为浮动形式;如图: wps中可以插入浮动图片,也可以插入嵌入单元格图片;如图: 并且在wps嵌入单元格形式的图片可以看到使用的是公式;如图: 问题来了,如何获取图片 并且将图片与单元格进行对应 …

一篇文章带你搞懂KMP算法

28. 找出字符串中第一个匹配项的下标 首先说明一点&#xff0c;这道力扣题背后所对应的思想就是KMP算法 我们先看看题目&#xff1a; 给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 …

进军网络安全的小白们,千万别学偏了!!!

随着互联网时代的日益进步&#xff0c;网络安全在近几年进入了蓬勃发展期。由于处于行业的红利期&#xff0c;很多人选择转行想跻身网络安全行业。 那么这些转行的人&#xff0c;对于网络安全的理解有深有浅&#xff0c;当然小白也是一大批。这就导致了很多人特比容易遇到到学…

5G无人露天矿山解决方案

1、5G无人露天矿山解决方案背景 ①2010.10&#xff0c;国家安监总局《金属非金属地下矿山安全避险“六大系统”安装使用和监督检查暂行规定》 ②2016.03&#xff0c;国家发改委《能源技术革命创新行动计划&#xff08;2016-2030&#xff09;》&#xff0c;2025 年重点煤矿区采…

在ubuntu中将dict.txt导入到数据库sqlite3

将dict.txt导入到数据库 #include <head.h> #include <sqlite3.h> int do_insert(int i,char *str,sqlite3 *db); int main(int argc, const char *argv[]) {//创建泵打开一个数据库sqlite3 *db NULL;if(sqlite3_open("./my.db",&db) ! SQLITE_OK){…

springboot+vue项目在国产机东方通部署详细教程!

文章目录 一、部署东方通TongWeb二、部署TongHttpServer三、springboot多模块后端打包四、vue前端打包&#xff08;TongWeb部署&#xff09;五、TongWeb部署&#xff08;前后端一样&#xff09; 一、部署东方通TongWeb 上传安装包&#xff1a;TongWeb7.0.4.9_Enterprise_Linux.…

Java内存区域(运行时数据区域)和内存模型(JMM)

Java 内存区域和内存模型是不一样的东西&#xff0c;内存区域是指 Jvm 运行时将数据分区域存储&#xff0c;强调对内存空间的划分。 而内存模型&#xff08;Java Memory Model&#xff0c;简称 JMM &#xff09;是定义了线程和主内存之间的抽象关系&#xff0c;即 JMM 定义了 …

随机改名并一键导出表格,让你的文件整理更高效

在日常工作中&#xff0c;文件的命名和归类是一个常见的繁琐任务。随着文件数量的不断增加&#xff0c;手动改名和整理变得异常耗时且容易出错。但是&#xff0c;现在有了一款创意文件改名归类利器&#xff0c;让你能够轻松将文件随机改名并一键导出表格&#xff0c;让文件整理…

Google Earth中的KML文件转换为CSV文件存放经纬度

最近进行一个小工作是在google earth中选择一系列点坐标,然后保存为csv文件或txt文件。我在Google Earth Pro在左上方的“文件”–>“保存”–>“将位置另存为”选项。 弹出的窗口中只有“kmz”与“kml”两种格式,这两种格式均是google earth内置的格式(KMZ文件是KML的…

运动路径规划,ROS发布期望运动轨迹

目录 一、Python实现&#xff08;推荐方法&#xff09; 1.1代码cubic_spline_path.py 1.2使用方法 二、C实现 参考博客 想让机器人/智能车无人驾驶&#xff0c;要有期望路径&#xff0c;最简单的是一条直线&#xff0c;或者是一条光滑曲线。 生成路径的方法有两种&#xf…