linux_driver_day03

news2024/12/25 23:36:41

作业1

题目:

通过ioctl函数选择不同硬件的控制,LED 蜂鸣器 马达 风扇
通过ioctl函数选择不同硬件的控制,LED  蜂鸣器  马达  风扇
代码:

代码太多只展示 led 部分,点击查看完整代码

led.c

#include "led.h"
#include "head.h"

static void all_led_init(void);

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

// 虚拟地址
static gpio_t *vir_led1;
static gpio_t *vir_led2;
static gpio_t *vir_led3;
static unsigned int *vir_rcc;

// 目录、设备信息
static struct class *cls;
static struct device *dev;

/**
 * @brief    初始化
 */
static int __init my_led_init(void)
{
    int i;

    // 注册驱动
    major = register_chrdev(0, "my_led", &fops);
    if (major < 0) {
        printk("字符设备驱动注册失败\n");
        return major;
    }
    printk("字符设备驱动注册成功%d\n", major);

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

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

    vir_led3 = vir_led1;
    if (!vir_led3) {
        printk("LED3 地址映射失败\n");
        return -EFAULT;
    }

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

    // 初始化湖村桥
    all_led_init();
    printk("寄存器初始化成功\n");

    // 自动注册设备
    cls = class_create(THIS_MODULE, "my_led");
    if (!cls) {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");

    for (i = 0; i < 3; i++) {
        dev = device_create(cls, NULL, MKDEV(major, i), NULL, "my_led%d", i);
        if (IS_ERR(dev)) {
            printk("向上设备节点失败\n");
            return -PTR_ERR(dev);
        }
    }
    printk("向上设备节点成功\n");

    printk(KERN_ALERT "led mod installed\n");
    return 0;
}

/**
 * @brief    卸载
 */
static void __exit my_led_exit(void)
{
    int i;

    // 注销驱动
    unregister_chrdev(major, "my_led");
    printk("字符设备驱动 %d 注销成功\n", major);

    // 取消映射
    iounmap(vir_led1);
    iounmap(vir_led2);
    iounmap(vir_rcc);
    printk("寄存器取消映射成功\n");

    // 自动卸载设备
    for (i = 0; i < 3; i++)
        device_destroy(cls, MKDEV(major, i));
    class_destroy(cls);

    printk(KERN_ALERT "led mod removed\n");
}

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

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

/**
 * @brief    读
 */
ssize_t my_led_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 my_led_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') // led1
    //     (*vir_led1).odr ^= (0x1 << 10);
    // else if (kbuf[0] == '2') // led2
    //     (*vir_led2).odr ^= (0x1 << 10);
    // else if (kbuf[0] == '3') // led3
    //     (*vir_led1).odr ^= (0x1 << 8);

    return 0;
}

/**
 * @brief    GPIO控制
 */
long my_led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    switch (cmd) {
    case LED_ON: // 开灯
        switch (arg) {
        case 1: // led1
            (*vir_led1).odr |= (0x1 << 10);
            break;
        case 2: // led2
            (*vir_led2).odr |= (0x1 << 10);
            break;
        case 3: // led3
            (*vir_led3).odr |= (0x1 << 8);
            break;
        }
        break;
    case LED_OFF: // 关灯
        (*vir_led1).odr &= (~(0x1 << 10));
        (*vir_led2).odr &= (~(0x1 << 10));
        (*vir_led3).odr &= (~(0x1 << 8));
        break;
    }

    return 0;
}

/**
 * @brief    led初始化
 */
static void all_led_init(void)
{
    // RCC初始化
    (*vir_rcc) |= (0x3 << 4);

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

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

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

module_init(my_led_init);
module_exit(my_led_exit);
MODULE_LICENSE("GPL");

#ifndef _my_led_H_
#define _my_led_H_

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

// 开
int my_led_open(struct inode *inode, struct file *file);
// 关
int my_led_close(struct inode *inode, struct file *file);
// 读
ssize_t my_led_read(struct file *file, char __user *ubuf, size_t size, loff_t *lof);
// 写
ssize_t my_led_write(struct file *file, const char __user *ubuf, size_t size, loff_t *lof);
// GPIO控制
long my_led_ioctl (struct file *file, unsigned int cmd, unsigned long arg);

// 重写文件操作结构体
struct file_operations fops = {
    .open = my_led_open,
    .release = my_led_close,
    .read = my_led_read,
    .write = my_led_write,
    .unlocked_ioctl = my_led_ioctl,
};

#endif //_my_led_H_

head.h

#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_RCC        0x50000A28
#define PHY_LED1_ADDR  0x50006000 // PE10
#define PHY_LED2_ADDR  0x50007000 // PF10
#define PHY_LED3_ADDR  0x50006000 // PE8
#define PHY_FAN_ADDR   0x50006000 // PE9
#define PHY_MOTOR_ADDR 0x50007000 // PF6
#define PHY_BEEP_ADDR  0x50003000 // PB6

// GPIO控制
#define LED_ON    _IO('1', 1) // 1开 2关
#define LED_OFF   _IO('1', 2)
#define FAN_ON    _IO('1', 1)
#define FAN_OFF   _IO('1', 2)
#define MOTOR_ON  _IO('1', 1)
#define MOTOR_OFF _IO('1', 2)
#define BEEP_ON   _IO('1', 1)
#define BEEP_OFF  _IO('1', 2)

#define PHY_GPIOE 0X50006000
#define PHY_GPIOF 0X50007000
#endif //_HEAD_H_

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

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

相关文章

问题1:矩阵置零 问题2:搜索二维矩阵

问题1&#xff1a;矩阵置零 给定一个 *m* x *n* 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 解题思路&#xff1a; 1.先遍历一遍矩阵&#xff0c;将元素为0的行和列都标记为true 2.再遍历一遍矩阵&#xff0c…

Element 实现动态增加多个输入框并校验

文章目录 前言实现通过按钮动态增加表单并验证必填实现动态多个输入框为行内模式&#xff0c;其它为行外模式 前言 在做复杂的动态表单&#xff0c;实现业务动态变动&#xff0c;比如有一条需要动态添加的el-form-item中包含了多个输入框&#xff0c;并实现表单验证&#xff0…

Visual Studio Code 如何设置整体界面字体的大小?

在某次操作中&#xff0c;我不小心误点了什么&#xff0c;导致 Visual Studio Code 界面的字体变小了很小&#xff0c;如下图所示&#xff1a; 我想把字体调整回来&#xff0c;该如何操作呢&#xff1f; 首先&#xff0c;第一步&#xff0c;打开设置&#xff1a; 第二步&#…

MiniLED是什么?有怎样的发展前景

Mini LED又叫做“次毫米发光二极管”&#xff0c;也是LED器件的一种&#xff0c;其芯片尺寸介于50~200μm之间。Mini LED的组成包括Mini LED像素阵列以及驱动电路&#xff0c;而且像素中心间距的单元较小&#xff0c;仅为0.3-1.5mm单元。随着 Mini LED 显示技术的快速发展&…

Nginx+Tomcat负载均衡(反向代理)、动静分离集群

NginxTomcat负载均衡、动静分离 一、正向代理与反向代理二、负载均衡--with-stream #启用 stream模块&#xff0c;提供4层调度 一、正向代理与反向代理 Nginx:正向代理&#xff08;知道目标服务器&#xff09; 反向代理&#xff08;不知道目标服务器&#xff09; Nginx配置反…

QWebEngine应用---执行javascript

我们都知道现代前端技术是基于html、css和javascript进行显示交互的&#xff0c;其中html和css属于静态界面显示&#xff0c;辅以javascript使页面交互更丰富。浏览器作为前端页面显示的基石&#xff0c;提供一套显示、交互、调试的东西。QWebEngine同样也提供了这些功能&#…

CodeTop整理-数组篇

目录 53. 最大子序和 33. 搜索旋转排序数组 三数之和 121. 买卖股票的最佳时机 4. 寻找两个正序数组的中位数 695. 岛屿的最大面积 54. 螺旋矩阵 88. 合并两个有序数组 152. 乘积最大子数组 42. 接雨水 64. 最小路径和 1. 两数之和 123. 买卖股票的最佳时机 III …

IDEA完全免费AI辅助编程插件BITO-GPT4安装及中文国产化设置

打开IDEA的plugins 搜索BITO&#xff1a; 下载后右边工具栏上会出现BITO的小蓝标&#xff0c;这样就可以使用了但是里面是全英文的 设置中文 1.打开BITO点击右上角设置 点击里面的Settings 进入BITO的Web网页 右边这个改成中文&#xff1a; 这样回到IDEA AI就会生成中…

【HTML】使用 div 自定义实现 input、textarea 输入框(适合定制化场景)

文章目录 一、实现 Input 组件二、实现 Textarea 组件三、React 实践案例 API参考文档: contenteditable : https://developer.mozilla.org/zh-CN/docs/Web/HTML/Global_attributes/contenteditableresize &#xff1a;https://developer.mozilla.org/zh-CN/docs/Web/CSS/resiz…

【Linux】shell脚本: 基本语法 和 高级特性

Shell脚本是一种用Shell语言编写的程序&#xff0c;它可以实现自动化的任务&#xff0c;如批量处理文件、监控系统状态、定时备份等。本文包括&#xff1a; Shell脚本的定义和作用&#xff1a;介绍什么是Shell脚本&#xff0c;它有哪些优点和缺点&#xff0c;它可以用来做什么。…

【macOS 系列】如何在mac下安装nvm实现多版本nodejs

文章目录 一、安装 nvm二、提示 commond not found:nvm的问题 一、安装 nvm 注意&#xff1a;mac下用nvm。win下用nvm-windows 以下步骤都是在命令行工具下执行&#xff1a; 1、安装 curl -o- [https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh](https://…

SPEC CPU 2006 在 CentOS 5.0 x86_64 古老系统测试

下载镜像 CentOS 2 3 4 5 6 等历史老版本下载地址 国内镜像地址_hkNaruto的博客-CSDN博客 下载CentOS 5.0 1-7 ISO文件 注意&#xff1a;尝试过下载DVD版本&#xff0c;速度太慢了。还是通过国内镜像下载这几个iso快。 安装虚拟机 VirtualBox 挂载第一个iso&#xff0c;启动…

计算机基础--->数据结构(7)【红黑树】

文章目录 二三树二三树的性质二三树一个简单的插入例子二三树的特点 红黑树红黑树的特点红黑树的节点红黑树的插入操作1. 左旋2. 右旋颜色翻转3. 颜色翻转插入实例 二三树 二三树与红黑树的性质非常相似&#xff0c;但是二三树能更直观的让人理解构建过程 二三树的性质 二三树是…

【机器学习核心总结】什么是GBDT(梯度提升树)

什么是GBDT(梯度提升树) 虽然GBDT同样由许多决策树组成&#xff0c;但它与随机森林由许多不同。 其中之一是GBDT中的树都是回归树&#xff0c;树有分类有回归&#xff0c;区分它们的方法很简单。将苹果单纯分为好与坏的是分类树&#xff0c;如果能为苹果的好坏程度打个分&…

云原生(第四篇)-k8s yaml文件

Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式&#xff1a;主要用于 api 接口之间消息的传递 YAML 格式&#xff1a;用于配置和管理&#xff0c;YAML 是一种简洁的非标记性语言&#xff0c;内容格式人性化&#xff0c;较易读 YAML 语法格式&#xff1a; ●大小写敏…

CentOS Linux的替代品(六)_BigCloud Enterprise Linux R8 U2 基础安装教程

文章目录 CentOS Linux的替代品&#xff08;六&#xff09;_BigCloud Enterprise Linux R8 U2 基础安装教程一、BC-Linux简介二、BigCloud Enterprise Linux R8 U2 基础安装2.1 下载地址2.2 安装过程 三、简单使用3.1 关闭selinux3.1.1 临时关闭selinux3.1.2 永久关闭selinux 3…

vscode 创建js 项目

1 创建 新窗口 2 进入文件夹 3 创建新的文件夹 4 选择 创建的文件夹 后 5 创建 js 文件 6 ctrl shift p 输入task 7 测试 8 F5 运行 选择调试器

打造品牌影响力:媒介易引领邀请明星录制祝福视频新潮流

在当今品牌推广的竞争激烈市场中&#xff0c;与体育冠军合作代言已成为众多品牌争相追求的新形式。体育冠军以其卓越的成就和广泛的影响力&#xff0c;成为品牌推广中的瞩目焦点。他们的形象和声音能够深入人心&#xff0c;激发消费者的共鸣&#xff0c;并对品牌产生积极的影响…

Mysql 幻读,当前读和快照读

什么是幻读 幻读指当用户读取某一范围的数据行时&#xff0c;另一个事务又在该范围内插入了新行&#xff0c;当用户在读取该范围的数据行时&#xff0c;会发现有新增行数据&#xff1b; mysql 在RR(可重复读)隔离级别利用间隙锁机制下一定程度上解决了幻读。 这里的一定程度…

Echarts 柱状图 设置柱状图渐变,设置柱状图圆角(弧度)

Echarts 柱状图 设置柱状图渐变&#xff0c;设置柱状图圆角&#xff08;弧度&#xff09; 1. 效果截图 2. 配置项截图 3. 具体代码 import * as echarts from echarts// 项目组织项目数 const territoryOptions {key: territory,title: {text: 项目数,textStyle: {fontSize:…