linux_driver_day02

news2024/11/26 2:34:17

作业1

题目:

映射 GPIOEGPIOFRCC 虚拟地址,实现控制三盏LED的驱动

效果:

在这里插入图片描述

代码:

mycdev.h

#ifndef _MYCDEV_H_
#define _MYCDEV_H_

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

// 开
int mycdev_open(struct inode *inode, struct file *file);
// 关
int mycdev_close(struct inode *inode, struct file *file);
// 读
ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof);
// 写
ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof);

// 重写文件操作结构体
struct file_operations fops = {
    .open = mycdev_open,
    .release = mycdev_close,
    .read = mycdev_read,
    .write = mycdev_write,
};

// 定义寄存器组织结构体
typedef struct {
    unsigned int moder;
    unsigned int otyper;
    unsigned int ospeedr;
    unsigned int pupdr;
    unsigned int idr;
    unsigned int odr;
} gpio_t;

// 定义GPIOE和GPIOF
#define PHY_GPIOE 0X50006000
#define PHY_GPIOF 0X50007000
#define PHY_RCC   0x50000A28

#endif //_MYCDEV_H_

mycdev.c

#include "mycdev.h"

static int major; // 保存主设备号
static char kbuf[128] = { 0 }; // 缓冲区

static gpio_t *vir_gpioe;
static gpio_t *vir_gpiof;
static unsigned int *vir_rcc;

/**
 * @brief    初始化
 */
static int __init mycdev_init(void)
{
    printk(KERN_ALERT "install demo mod\n");
    // 注册驱动
    major = register_chrdev(0, "mychrdev", &fops);
    if (major < 0) {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功%d\n", major);

    // 映射寄存器
    vir_gpioe = ioremap(PHY_GPIOE, sizeof(gpio_t));
    if (!vir_gpioe) {
        printk("GPIOE 地址映射失败\n");
        return -EFAULT;
    }

    vir_gpiof = ioremap(PHY_GPIOF, sizeof(gpio_t));
    if (!vir_gpiof) {
        printk("GPIOF 地址映射失败\n");
        return -EFAULT;
    }

    vir_rcc = ioremap(PHY_RCC, 4);
    if (vir_rcc == NULL) {
        printk("RCC 寄存器地址映射失败\n");
        return -EFAULT;
    }
    printk("寄存器地址映射成功\n");

    // RCC初始化
    (*vir_rcc) |= (0x3 << 4);

    // led1
    (*vir_gpioe).moder &= (~(0X3 << 20));
    (*vir_gpioe).moder |= (0X1 << 20);
    (*vir_gpioe).otyper &= (~(0X1 << 10));
    (*vir_gpioe).ospeedr &= (~(0X3 << 20));
    (*vir_gpioe).pupdr &= (~(0X3 << 20));

    // led2
    (*vir_gpiof).moder &= (~(0X3 << 20));
    (*vir_gpiof).moder |= (0X1 << 20);
    (*vir_gpiof).otyper &= (~(0X1 << 10));
    (*vir_gpiof).ospeedr &= (~(0X3 << 20));
    (*vir_gpiof).pupdr &= (~(0X3 << 20));

    // led3
    (*vir_gpioe).moder &= (~(0X3 << 16));
    (*vir_gpioe).moder |= (0X1 << 16);
    (*vir_gpioe).otyper &= (~(0X1 << 8));
    (*vir_gpioe).ospeedr &= (~(0X3 << 16));
    (*vir_gpioe).pupdr &= (~(0X3 << 16));

    printk("寄存器初始化成功\n");

    return 0;
}

/**
 * @brief    卸载
 */
static void __exit mycdev_exit(void)
{
    // 注销驱动
    unregister_chrdev(major, "mychrdev");
    printk("字符设备驱动 %d 注销成功\n", major);
    printk(KERN_ALERT "remove demo mod\n");

    // 取消映射
    iounmap(vir_gpioe);
    iounmap(vir_gpiof);
    iounmap(vir_rcc);
    printk("寄存器取消映射成功\n");
}

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

/**
 * @brief    关
 */
int mycdev_close(struct inode *inode, struct file *file)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

/**
 * @brief    读
 */
ssize_t mycdev_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof)
{
    // 拷贝内核缓冲区 到 用户空间缓冲区
    int ret;
    if (sizeof(kbuf) < size) // 同步内核的缓冲区大小
        size = sizeof(kbuf);
    ret = copy_to_user(ubuf, kbuf, size);

    if (ret) {
        printk("copy_to_user filed\n");
        return -EIO;
    }

    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

/**
 * @brief    写
 */
ssize_t mycdev_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof)
{
    // 拷贝用户空间缓冲区 到 内核空间
    int ret;
    if (sizeof(kbuf) < size)
        size = sizeof(kbuf);
    ret = copy_from_user(kbuf, ubuf, size);

    if (ret) {
        printk("copy_to_user filed\n");
        return -EIO;
    }
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);

    // LED亮灭逻辑
    if (kbuf[0] == '1') { // 亮
        (*vir_gpioe).odr |= (0x1 << 10);
        (*vir_gpiof).odr |= (0x1 << 10);
        (*vir_gpioe).odr |= (0x1 << 8);
    } else if (kbuf[0] == '0') { // 灭
        (*vir_gpioe).odr &= (~(0x1 << 10));
        (*vir_gpiof).odr &= (~(0x1 << 10));
        (*vir_gpioe).odr &= (~(0x1 << 8));
    }

    return 0;
}

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

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

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

相关文章

如何使用ChatGPT写好简历?如何使用ChatGPT优化简历?21个写简历的ChatGPT的Prompts!

你是一位求职者&#xff0c;即将要参加一场面试&#xff0c;你的工作经历是[2年国企会计经验]&#xff0c;教育背景是[国内211本科毕业&#xff0c;会计学专业]&#xff0c;请基于上述内容生成一份简历&#xff0c;要求加上自我评价。 根据这份工作描述写一份[TITLE]的简历。[…

Python——— 字典

&#xff08;一&#xff09;初识字典 字典是 “ 键值对 ” 的无序可变序列&#xff0c;字典中的每个元素都是一个 “ 键值对” &#xff0c;包含&#xff1a; “ 键对象 ” 和 “ 值对象 ” 。可以通过 “ 键对象 ” 实现快速获取、 删除、更新对应的“ 值对象 ” 。 一个典…

Scala入门学习

Scala入门学习 文章目录 Scala入门学习0. 写在前面1. 概述1.1 什么是Scala1.2 Java and Scala 2. Scala简单使用2.1 Scala环境安装2.2 Scala插件安装2.3 Scala第一个案例 0. 写在前面 操作系统&#xff1a;Windows10JDK版本&#xff1a;jdk1.8Maven版本&#xff1a;Maven-3.5.…

调整图片大小需要注意哪些问题?在线改图片大小的方法介绍

调整图片大小&#xff1a;打造完美尺寸的视觉体验 为什么需要调整图片大小&#xff1f; 在现代社交媒体和网络传媒中&#xff0c;图片已经成为信息传递和内容表达的重要元素。然而&#xff0c;不同平台和设备对于图片尺寸有着各自的要求。过大或过小的图片尺寸可能导致加载速…

计算机网络_ 1.3 网络核心 (数据交换_电路交换)

计算机网络_数据交换_电路交换 计算机网络_数据交换_电路交换 计算机网络_数据交换_电路交换 最典型电路交换网络&#xff1a;电话网络电路交换的三个阶段 建立连接&#xff08;呼叫/电路建立&#xff09;通信释放连接&#xff08;拆除电路&#xff09; 独占资源 电路交换网络…

OSPFv2基础01_整体介绍

目录 1.OSPF简介 2.OSPF工作原理简介 3.OSPF基础概念 3.1 OSPF系统 3.1.1 OSPF路由器分类 3.1.2 OSPF区域 &#xff08;1&#xff09;OSPF区域分类 &#xff08;2&#xff09;OSPF特殊区域 3.1.3 OSPF路由类型 3.2 OSPF报文 3.2.1 OSPF首部格式 3.2.2 OSPF报文格式 …

【软考】数据库理论

文章目录 一、函数依赖闭包 一、函数依赖闭包 视频连接&#xff1a;https://open.163.com/newview/movie/free?pidEGVFE2HM4&midOGVFE3RKQ 其他的概念&#xff1a; 函数依赖集候选关键字闭包

Ribbon快速入门

1.Ribbon 概述 Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具&#xff0c;它基于 Netflix Ribbon 实现。通过 Spring Cloud 的封装&#xff0c;可以让我们轻松地将面向服务的 REST 模版请求自动转换成客户端负载均衡的服务调用。 轮询 hash 权重 … 简单…

机器视觉-镜头、相机、光源选型以及打光

机器视觉-镜头、相机、光源选型以及打光从理论到实战 关注林中青木微信公众号&#xff0c;获取更多干货&#xff0c;大佬带你飞~

海睿思分享 | ChatGPT梦幻联动,解锁企业数字化转型新可能

在当今这个充满活力和变化的世界里&#xff0c;人工智能 (AI) 的迅速发展正在改变着我们的生活方式。它不仅提高了我们的工作效率&#xff0c;而且正在重新定义我们的日常生活&#xff0c;以前所未有的方式提高了我们的生活质量。其中&#xff0c;以ChatGPT为代表的语言生成模型…

Golang的数据类型及数据类型间转换整理

Golang 更明确的数字类型命名&#xff0c;支持 Unicode&#xff0c;支持常用数据结构。 Go 语言中数据类型分为&#xff1a; 基本数据类型 和 复合数据类型 基本数据类型有&#xff1a;整型、浮点型、布尔型、字符串 复合数据类型有&#xff1a; 数组、切片、结构体、函数、m…

【QT】——定时器QTimer的使用

目录 常见的函数 构造函数 获取/设置定时器间隔时间 启动/停止定时器 信号 设置定时器的时间的两种方法 设置定时器精度 其他函数 静态函数 实例 QTimer是QT框架中的定时器类型&#xff0c;它的使用方法如下&#xff1a; 定义一个调用QTimer对象&#xff0c;调用st…

华为OD机试真题 Python 实现【找出通过车辆最多颜色】【2023Q1 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、Python算法源码六、效果展示1、输入2、输出3、说明 一、题目描述 在一个狭小的路口&#xff0c;每秒只能通过一辆车&#xff0c;假如车辆的颜色只有3种&#xff0c;找出n秒内经过的最多颜色的车辆数量。 三种颜色编…

深度学习在Li电池RUL、SOH和电池热管理中的研究进展与应用

公众号&#xff1a;尤而小屋作者&#xff1a;Peter编辑&#xff1a;Peter 大家好&#xff0c;我是Peter~ 今天给大家分享一篇关于深度学习在Li电池RUL、SOH和电池热管理中的研究进展与应用的文献综述。文献基本信息介绍&#xff1a; 本文系统介绍了Deep Learning深度学习的不同…

大厂题第1辑——虚函数七题精讲之3:纯虚函数

什么是纯虚函数&#xff1f;什么是抽象类&#xff1f;纯虚函数可以提供实现吗&#xff1f;有什么意义&#xff1f; 题6-什么是纯虚函数&#xff1f; C中有两种继承&#xff1a;接口继承和实现继承。二者的第一个区别是&#xff1a;基类都干了些什么&#xff1f; 如果基类啥实…

15.2 BP神经网络实现图像压缩——基于BP神经网络的图像压缩(matlab程序)

1.简述 BP神经网络的图像压缩原理 数字图像压缩实际上是以较少的比特数有损或者无损的来表示原来像素矩阵的一种图像处理技术,实际上就是减少图像数据中的时间冗余,空间冗余,频谱冗余等等作为目的,从而同过减少上述的一种或者多种冗余的信息而达到更加高效的存储与传输数据.图…

目标检测的评估指标

Precision(精确率/查准率)&#xff1a;是指在所有被预测为正的样本中&#xff0c;确实是正样本的占比。当Precision越大时&#xff0c;FP越小&#xff0c;此时将其他类别预测为本类别的个数也就越少&#xff0c;可以理解为预测出的正例纯度越高。Precision越高&#xff0c;误检…

LLM驱动的智能体#Mixcopilot的迭代演进

论文&#xff1a; Generative Agents: Interactive Simulacra of Human Behavior shadow 前阵子在一场线下活动&#xff0c;我们展开了对生成式智能体的分享和研讨&#xff0c;同时也介绍了Earth在实现智能体系统的思考和实践。 最近有一篇文章把LLM驱动的智能体的构成讲解的很…

centos7安装图形化界面

一键安装并生效脚本 #!/bin/bash # 安装X(X Window System) yum groupinstall -y "X Window System"# 安装图形界面软件 yum groupinstall -y "GNOME Desktop"# 设置开机进入图形界面 systemctl set-default graphical.target# 进入图形界面 startx安装 …

Windows | [出现错误 2147942402 (0x80070002) (启动“ubuntu2004.exe”时)]

Windows | [出现错误 2147942402 (0x80070002) (启动“ubuntu2004.exe”时)] C:\WINDOWS\system32\wsl.exe -d Ubuntu-20.04