使用linux的系统驱动点灯

news2025/7/18 11:53:29

使用linux的系统驱动点亮开发板的灯

**要求:**使用linux驱动点亮开发板的灯

实验现象

在这里插入图片描述
(LED1没亮是因为本人的开发板LED1物理损坏)

head.h代码

#ifndef __HEAD_H__
#define __HEAD_H__

typedef struct{
	volatile unsigned int moder;
	volatile unsigned int otyper;
	volatile unsigned int ospeedr;
	volatile unsigned int pupdr;
	volatile unsigned int idr;
	volatile unsigned int odr;
}gpio_t;

#define GPIOE ((gpio_t*)0x50006000)
#define GPIOF ((gpio_t*)0x50007000)
#define PHY_RCC 0x50000A28

#endif

test.c代码

#include <stdio.h>
#include <stdlib.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");
        exit(-1);
    }
    while (1)
    {
        printf("请输入控制命令--1:开灯   0:关灯>");
        fgets(buf, sizeof(buf), stdin); // 在终端读取
        buf[strlen(buf) - 1] = '\0';    // 吃掉末尾的‘\n’;
        write(fd, buf, sizeof(buf));
    }
    close(fd);
    return 0;
}

mychedev.c代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include<linux/uaccess.h>
#include<linux/io.h>
#include"head.h"
int major; // 用于保存主设备号
char kbuf[128]={0};
gpio_t *vir_led1;   //led1 pe10 ;  led3 pe8
gpio_t *vir_led2;   //led2 pf10

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)
{
    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;
}
ssize_t mycdev_write(struct file *file, const char *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_from_user filed\n");
        return -EIO;
    }
    if(kbuf[0]=='1')//开灯
    {
        //开灯逻辑
		//led1开灯 pe10
        (vir_led1->odr) |= (0x1<<10);
		//led2开灯pf10
        (vir_led2->odr) |= (0x1<<10);
		//led3开灯pe8
        (vir_led1->odr) |= (0x1<<8);
    }
    else if(kbuf[0]=='0')//关灯
    {
        //关灯
		//led1关灯pe10
        (vir_led1->odr) &= (~(0x1<<10));
		//led2关灯pf10
        (vir_led2->odr) &= (~(0x1<<10));
		//led3关灯pe8
        (vir_led1->odr) &= (~(0x1<<8));
    }
    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,
        .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");
        return major;
    }
    printk("字符设备驱动注册成功major=%d\n", major);
    //映射物理寄存器
    vir_led1=ioremap(GPIOE,sizeof(gpio_t));
    vir_led2=ioremap(GPIOF,sizeof(gpio_t));
    vir_rcc=ioremap(PHY_RCC,4);
	
	//寄存器初始化
	//led灯的控制默认为0,时钟初始化
	(*vir_rcc) |= (0X3<<4);
	//led1  pe10    moder,odr
	(vir_led1->moder) &= (~(0x3<<20)); 	//清空
	(vir_led1->moder) |= (0x1<<20); 	//赋值
	(vir_led1->odr) &= (~(0x1<<10)); 	//默认为熄灯

	//led2  pf10
	(vir_led2->moder) &= (~(0x3<<20)); 	//清空
	(vir_led2->moder) |= (0x1<<20); 	//赋值
	(vir_led2->odr) &= (~(0x1<<10)); 	//默认为熄灯

	//led3  pe8
	(vir_led1->moder) &= (~(0x3<<16)); 	//清空
	(vir_led1->moder) |= (0x1<<16); 	//赋值
	(vir_led1->odr) &= (~(0x1<<8)); 	//默认为熄灯

    if(vir_led1==NULL && vir_led2==NULL)
    {
        printk("MODER寄存器地址映射表失败\n");
        return -EFAULT;
    }

    vir_led1->odr=ioremap(GPIOE,4);
    if(vir_led1==NULL && vir_led2==NULL)
    {
        printk("ODR寄存器地址映射表失败\n");
        return -EFAULT;
    }
	
	//此处是时钟寄存器的值
    vir_rcc=ioremap(PHY_RCC,4);
    if(vir_rcc==NULL)
    {
        printk("RCC寄存器地址映射表失败\n");
        return -EFAULT;
    }
    printk("寄存器地址映射成功\n");
    printk("硬件寄存器初始化成功\n");
    return 0;
}
static void __exit mycdev_exit(void)
{
    //取消寄存器地址映射
    iounmap(vir_led1);
    iounmap(vir_led2);
    iounmap(vir_rcc);
    //字符设备驱动的注销
    unregister_chrdev(major,"mychrdev");
}
module_init(mycdev_init); 		//入口函数
module_exit(mycdev_exit); 		//出口函数
MODULE_LICENSE("GPL"); 		//协议许可证

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

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

相关文章

DAY38:贪心算法(六)分发糖果+柠檬水找零

文章目录 135.分发糖果思路第一种情况&#xff1a;右>左第二种情况&#xff1a;左>右&#xff08;倒序遍历&#xff09;两种情况的结果合并&#xff0c;通过取最大值 完整版总结 860.柠檬水找零思路完整版总结 135.分发糖果 本题涉及到一个思想&#xff0c;就是处理好一…

位图的详解

目录 位图 位图的概念 位图的实现 位图常见三道面试题 1.给定100亿个整数&#xff0c;设计算法找到只出现一次的整数&#xff1f; 2. 给两个文件&#xff0c;分别有100亿个整数&#xff0c;我们只有1G内存&#xff0c;如何找到两个文件交集&#xff1f; 3. 位图应用变形…

C#程序以管理员权限运行

在Vista 和 Windows 7 及更新版本的操作系统&#xff0c;增加了 UAC(用户账户控制) 的安全机制&#xff0c;如果 UAC 被打开&#xff0c;用户即使以管理员权限登录&#xff0c;其应用程序默认情况下也无法对系统目录、系统注册表等可能影响系统正常运行的设置进行写操作。这个机…

【sap2000】【python】python相关的3个案例-1/3

python相关的3个案例 Python COM&#xff0c;Python NET&#xff0c;IronPython的区别 这三个术语都与 Python 语言和其他编程平台&#xff08;尤其是 Microsoft .NET 及其组件&#xff09;之间的互操作性有关。我们来看看它们之间的主要区别&#xff1a; Python COM&#xf…

【vim】Linux使用vim编写代码:头部自动添加提示信息+自动缩进、自动换行等配置(~/.vimrc)

前言&#xff1a; 在编写代码时&#xff0c;为了提高代码的可读性和维护性&#xff0c;我们经常在文件的头部添加一些信息提示&#xff0c;如作者、日期、版本号等。本文介绍了如何在 Vim 编辑器中实现自动添加信息提示的功能。 结尾提供~/.vimr参考配置&#xff0c;可提高代码…

第2章 变量

目录 1 变量1.1 什么是变量&#xff1f;1.2 声明变量1.2 变量的原理 2 数据类型2.1 基本数据类型2.1.1 取值范围公式2.1.2 整型2.1.3 浮点型2.1.4 字符型2.1.5 布尔型 2.2 引用数据类型2.2.1 数组[]2.2.2 类class2.2.3 接口interface 3 数据类型转换3.1 自动类型转换3.2 强制类…

备份c盘中的所有数据的3种方法推荐!

为什么要备份C盘中的所有数据&#xff1f; 备份c盘中的所有数据&#xff0c;主要是为了避免以下几种突发情况&#xff1a; 感染病毒。 操作不当导致系统文件损坏&#xff0c;崩溃。 蓝屏死机&#xff08;BOSD&#xff09;或黑屏死机。 物理灾害。 磁盘出现物理坏道等。…

QWebEngine应用---cookies存储及自动登录

什么是cookies&#xff1f; 浏览器Cookie指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据&#xff0c;当前主流网站和浏览器都使用Cookies来实现自动登录 QWebEngineCookieStore QWebEngine基于Chromium内核&#xff0c;和Chrome浏览器一样支持…

微信聚合聊天,轻松一人管理多个微信

看这篇文章的你是否有以下烦恼&#xff1a; 1.微信账号太多&#xff0c;管理过于麻烦 2.微信号多&#xff0c;需要很多员工来管理&#xff0c;人工费用多 3.多个微信打开后会造成微信登陆界面过多&#xff0c;切换操作十分不方便 4.当微信多的时候&#xff0c;新消息提示也多…

docker安装nacos并配置数据库

1、下载镜像 docker pull nacos/nacos-server 查看下载镜像 docker images 2、启动nacos 注意&#xff1a;如果nacos版本在2.0及以上&#xff0c;需要把8848、9848和9849三个端口映射出来&#xff0c;否则访问会404失败 docker run --env MODEstandalone \ --name nacos -d…

【AI新趋势期刊#2】AI发明计算机算法,如何给大模型排行,照片秒变二维码,视频一键动漫风

前言 每天都要浏览大量AI相关新闻&#xff0c;是不是感到信息量爆炸&#xff0c;有效信息少&#xff1f; 这么多新产品和新工具&#xff0c;到底哪些是真正是有价值的&#xff0c;哪些只是浮躁的一时热点&#xff1f; 想参与AI产品和工具的开发&#xff0c;从哪里能够获得大…

MongoDB【MongoDB命令、CRUD操作 】(二)-全面详解(学习总结---从入门到深化)

目录 MongoDB命令 CRUD操作 MongoDB命令 基本操作 查看数据库 show dbs; 切换数据库 如果没有对应的数据库则创建 use 数据库名;创建集合 db.createCollection("集合名") 查看集合 show tables; show collections; 删除集合 db.集合名.drop(); 删除当前…

Robust Secure Aggregation with Lightweight Verification for Federated Learning

摘要&#xff1a; 可验证的安全聚合&#xff08;VSA&#xff09;是联邦学习&#xff08;FL&#xff09;中的关键过程&#xff0c;其中安全聚合实现局部梯度聚合&#xff0c;同时保留数据机密性&#xff0c;并且可验证性使参与者能够验证中央服务器&#xff08;CS&#xff09;返…

【Linux】程序替换

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️小林爱敲代码       &#x1f6f0;️博客专栏&#xff1a;✈️Linux之路       &#x1f6f0;️社区 :✈️ 进步学堂       &a…

51单片机地震监测语音报警提示系统MPU6050TTS报警

实践制作DIY- GC0153--- 地震监测语音报警提示系统 基于51单片机设计------- 地震监测语音报警提示系统 二、功能介绍&#xff1a; STC89C52单片机TTS语音播报模块MPU-6050角度传感器LED灯显示一个按键 1.获取MPU-6050角度数据&#xff0c;然后根据角度数据计算出0~10级的地震…

B站w_rid,qv_id加密分析

本文仅供学习交流&#xff0c;只提供关键思路不会给出完整代码&#xff0c;严禁用于非法用途&#xff0c;若有侵权请联系我删除&#xff01; 网站地址&#xff1a;aHR0cHM6Ly9zZWFyY2guYmlsaWJpbGkuY29tL2FsbD92dD03OTExMjUwNSZrZXl3b3JkPSVFNyU4OCVBQyVFOCU5OSVBQg 关键字搜…

Flutter 布局构建

文章目录 一、布局类组件简介二、理解 Flutter 布局约束三、线性布局&#xff08;Row和Column&#xff09;1. 主轴和纵轴2. Row3. Column4. 特殊情况 四、弹性布局&#xff08;Flex 和 Expanded&#xff09;1. Flex2. Expanded 五、流式布局&#xff08;Wrap 和 Flow&#xff0…

记录一次Ubuntu系统安装tenforflow

电脑已有版本 Ubuntu 20.04GCC 9.4.0CUDA 11.3 需要指定版本的python库 tensorflow 2.6.0numpy 1.19.2matplotlib 3.4.0keras 2.6.0protobuf 3.19.6 我的环境

LeetCode刷题 | 583. 两个字符串的删除操作、72. 编辑距离

583. 两个字符串的删除操作 给定两个单词 word1 和 word2 &#xff0c;返回使得 word1 和 word2 相同所需的最小步数。 每步 可以删除任意一个字符串中的一个字符。 示例 1&#xff1a; 输入: word1 "sea", word2 "eat" 输出: 2 解释: 第一步将 "…

Flutter Bloc组件buildWhen的妙用

在Flutter中当状态发生改变的时候,Widget会重新build刷新页面。但是当状态发生改变的时候后,我们指向让有关联的Widget重绘,与之无关的Widget保持不变,比如对于登录页面,有用户名和密码两个组件:如下图。 构建代码如下: 当我们输入用户名的时候,仅仅希望_UserNameInp…