系统驱动作业

news2024/11/26 4:48:02

 作业1

myled_time.c

#include <linux/init.h>
#include <linux/module.h>
#include<linux/of.h>
#include<linux/gpio.h>
#include<linux/of_gpio.h>
#include<linux/timer.h>

struct device_node *dnode;
unsigned int gpiono;
struct timer_list mytimer;  //定义定时器对象
//定义定时器处理函数
void mytimer_func(struct timer_list *timer)
{
    if(gpio_get_value(gpiono) == 1)
    {
        //灯灭
        gpio_set_value(gpiono,0);
    }
    else if(gpio_get_value(gpiono) == 0)
    {
        //灯亮
        gpio_set_value(gpiono,1);
    }
    mod_timer(timer,jiffies+HZ); 
}
static int __init mycdev_init(void)
{
    int ret;

    //解析led灯的设备树节点
    dnode=of_find_node_by_path("/myleds");
    if(dnode==NULL)
    {
    printk("解析设备树节点失败\n");
    return -ENXIO;
    }
    printk("解析设备树节点成功\n");
    //根据设备树节点解析led1gpio编号
    gpiono=of_get_named_gpio(dnode,"led1",0);
    if(gpiono<0)
    {
        printk("gpio编号解析失败\n");
    }
    printk("解析gpio编号成功gpiono=%d\n",gpiono);
    //申请gpio编号
    ret=gpio_request(gpiono,NULL);
    if(ret<0)
    {
        printk("申请gpio编号失败\n");
        return ret;
    }
    //led1对应的gpio的管脚为输出
    gpio_direction_output(gpiono,0);
    //设置管脚输出高电平,亮灯
    gpio_set_value(gpiono,1);

    //初始化定时器对象
    mytimer.expires=jiffies+HZ;
    timer_setup(&mytimer,mytimer_func,0);
    //将定时器对象注册进内核
    add_timer(&mytimer);

    return 0;
}
static void __exit mycdev_exit(void)
{
    //灭灯
    gpio_set_value(gpiono,0);
    //释放gpio编号
    gpio_free(gpiono);
    //注销定时器
    del_timer(&mytimer);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

作业2

mychrdev.c

#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 <linux/cdev.h>
#include <linux/slab.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/of.h>

#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)


struct class *cls;
struct device *dev;
struct cdev *cdev;
unsigned int major = 0;
unsigned int minor = 0;
dev_t devnob;
struct device_node *dnode;
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;

int mycdev_open(struct inode *inode, struct file *file)
{
    unsigned int aaa = MINOR(inode->i_rdev);
    file->private_data = (void *)aaa;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

long mycdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    unsigned int aaa = (int)file->private_data;
    switch (cmd)
    {
    case LED_ON: // 开灯
        switch (aaa)
        {
        case 0: // LED1
            gpiod_set_value(gpiono1, 1);
            break;
        case 1: // LED2
            gpiod_set_value(gpiono2, 1);
            break;
        case 2: // LED3
            gpiod_set_value(gpiono3, 1);
            break;
        }
        break;
    case LED_OFF: // 关灯
        switch (aaa)
        {
        case 0:
            gpiod_set_value(gpiono1, 0);
            break;
        case 1:
            gpiod_set_value(gpiono2, 0);
            break;
        case 2:
            gpiod_set_value(gpiono3, 0);
            break;
        }

        break;
    }
    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,
        .unlocked_ioctl = mycdev_ioctl,
        .release = mycdev_close,
};

static int __init mycdev_init(void)
{
    int ret, i;

    // 1.分配字符设备驱动对象空间  cdev_alloc
    cdev = cdev_alloc();
    if (cdev == NULL)
    {
        printk("申请字符设备驱动对象空间失败\n");
        ret = -EFAULT;
        goto out1;
    }
    printk("字符设备驱动对象申请成功\n");

    // 2.字符设备驱动对象部分初始化  cdev_init
    cdev_init(cdev, &fops);

    // 3.申请设备号  register_chrdev_region/alloc_chrdev_region
    if (major > 0)
    {
        ret = register_chrdev_region(MKDEV(major, minor), 3, "myled");
        if (ret)
        {
            printk("静态指定设备号失败\n");
            goto out2;
        }
    }
    else
    {
        ret = alloc_chrdev_region(&devnob, minor, 3, "myled");
        if (ret)
        {
            printk("静态指定设备号失败\n");
            goto out2;
        }
        major = MAJOR(devnob); // 根据设备号得到主设备号
        minor = MINOR(devnob); // 根据设备号得到次设备号
    }
    printk("申请设备号成功\n");

    // 4.注册字符设备驱动对象  cdev_add()
    ret = cdev_add(cdev, MKDEV(major, minor), 3);
    if (ret)
    {
        printk("注册字符设备驱动对象失败\n");
        goto out3;
    }
    printk("注册字符设备驱动对象成功\n");

    // 5.向上提交目录
    cls = class_create(THIS_MODULE, "myled");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        ret = -PTR_ERR(cls);
        goto out4;
    }
    printk("向上提交目录成功\n");

    // 6.向上提交设备节点
    for (i = 0; i < 3; i++)
    {
        dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
        if (IS_ERR(dev))
        {
            printk("向上提交节点信息失败\n");
            ret = -PTR_ERR(dev);
            goto out5;
        }
    }
    printk("向上提交设备节点信息成功\n");

    // 解析led灯的设备树节点
    dnode = of_find_node_by_path("/myleds");
    if (dnode == NULL)
    {
        printk("解析设备树节点失败\n");
        return -ENXIO;
    }
    printk("解析设备树节点成功\n");
    // 根据设备树节点解析led1gpio结构体并向内核注册
    gpiono1 = gpiod_get_from_of_node(dnode, "led1", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(gpiono1))
    {
        printk("申请gpiono1失败\n");
        return -PTR_ERR(gpiono1);
    }
    // 根据设备树节点解析led2gpio结构体并向内核注册
    gpiono2 = gpiod_get_from_of_node(dnode, "led2", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(gpiono2))
    {
        printk("申请gpiono2失败\n");
        return -PTR_ERR(gpiono2);
    }
    // 根据设备树节点解析led3gpio结构体并向内核注册
    gpiono3 = gpiod_get_from_of_node(dnode, "led3", 0, GPIOD_OUT_LOW, NULL);
    if (IS_ERR(gpiono3))
    {
        printk("申请gpiono3失败\n");
        return -PTR_ERR(gpiono3);
    }
    printk("申请gpio编号成功\n");

    return 0;
out5:
    for (--i; i >= 0; i--)
    {
        // 销毁上面提交的设备信息
        device_destroy(cls, MKDEV(major, i));
    }
    class_destroy(cls);
out4:
    cdev_del(cdev);
out3:
    unregister_chrdev_region(MKDEV(major, minor), 3);
out2:
    kfree(cdev);
out1:
    return ret;
}
static void __exit mycdev_exit(void)
{
    int i;
    // 灭灯
    gpiod_set_value(gpiono1, 0);
    gpiod_set_value(gpiono2, 0);
    gpiod_set_value(gpiono3, 0);
    // 释放gpio编号
    gpiod_put(gpiono1);
    gpiod_put(gpiono2);
    gpiod_put(gpiono3);

    // 1.销毁设备信息  device_destroy
    for (i = 0; i < 3; i++)
    {
        device_destroy(cls, MKDEV(major, i));
    }
    // 2.销毁目录  class_destroy
    class_destroy(cls);
    // 3.注销对象  cdev_del()
    cdev_del(cdev);
    // 4.释放设备号   unregister_chrdev_region()
    unregister_chrdev_region(MKDEV(major, minor), 3);
    // 5.释放对象空间  kfree()
    kfree(cdev);
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

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>
#include <sys/ioctl.h>

#define LED_ON _IO('l',1)
#define LED_OFF _IO('l',0)

// LED1->PE10
// LED2->PF10
// LED3->PE8

int main(int argc, char const *argv[])
{


    int a, b;
    int fd;
    while (1)
    {
        // 从终端读取
        printf("请选择要实现的功能\n");
        printf("0(关灯) 1(开灯)>");
        scanf("%d", &a);
        printf("请输入要控制的灯\n");
        printf("1(LED1) 2(LED2) 3(LED3)>");
        scanf("%d", &b);
        if (a == 1) // 开灯
        {
            switch (b)
            {
            case 1:
                fd = open("/dev/myled0", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd, LED_ON);
                break;
            case 2:
                fd = open("/dev/myled1", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd,LED_ON);
                break;
            case 3:
                fd = open("/dev/myled2", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd, LED_ON);
                break;
            }
        }
        else if (a == 0) // 关灯
        {
            switch (b)
            {
            case 1:
                fd = open("/dev/myled0", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd,LED_OFF);
                break;
            case 2:
                fd = open("/dev/myled1", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd, LED_OFF);
                break;
            case 3:
                fd = open("/dev/myled2", O_RDWR);
                if (fd < 0)
                {
                    printf("打开设备文件失败\n");
                    exit(-1);
                }
                ioctl(fd, LED_OFF);
                break;
            }
        
        }
    }
    close(fd);
    return 0;
}

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

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

相关文章

Redis — 不仅仅是缓存

1*qIy3PMmEWNcD9Czh_21C8g.png Redis是一种快速、开源的内存键值&#xff08;NoSQL&#xff09;数据库&#xff0c;远远超越了缓存的功能。Redis使用RAM进行操作&#xff0c;提供亚毫秒级的响应时间&#xff0c;支持每秒数百万次请求。Redis主要用于缓存&#xff0c;但它也可以…

【CSS】文字渐变色

CSS设置文字渐变色 background-image: -webkit-linear-gradient(bottom,red,#fd8403,yellow); -webkit-background-clip: text; // 设置背景作用域 -webkit-text-fill-color: transparent;

docker数据卷权限管理--理论和验证

一、Docker容器中用户权限管理 Linux系统的权限管理是由uid和gid负责&#xff0c;Linux系统会检查创建进程的uid和gid&#xff0c;以确定它是否有足够的权限修改文件&#xff0c;而非是通过用户名和用户组来确认。 同样&#xff0c;在docker容器中主机上运行的所有容器共享同一…

【DC系列06】DC-6靶机复盘

【DC系列06】DC-6靶机复盘 我们打开这个靶机后首先还是先对靶机进行一个ip扫描&#xff0c;然后再单独对这个ip进行一个全局扫描。 扫描后ip地址是192.168.102.147。 我们再单独扫描一下 nmap -A 192.168.102.147 -p-这个靶机有一个特点就是扫描到ip后&#xff0c;你需要往…

vulnhub靶机渗透:PWNLAB: INIT

PWNLAB: INIT 靶机环境介绍nmap扫描端口扫描服务扫描漏洞扫描扫描总结 80端口目录爆破LFI利用 3306端口回到80端口文件上传 获得立足点横向移动提权总结参考 靶机环境介绍 https://www.vulnhub.com/entry/skytower-1,96/ 靶机IP&#xff1a;192.168.56.103 kali IP&#xff…

OceanBase 特殊的 INT 与时间类型隐式转换问题

本文作者分享了Oceanbase时间与数值类型隐式转换导致查询结果不符合预期或“不正确”问题的排查思路。 作者&#xff1a;任仲禹 爱可生 DBA 团队成员&#xff0c;擅长故障分析和性能优化&#xff0c;文章相关技术问题&#xff0c;欢迎大家一起讨论。 本文来源&#xff1a;原创投…

create-react-app -V 报错无法将“create-react-app”项识别为 cmdlet、函数、脚本文件或可运行程序的名称

create-react-app -Vcreate-react-app : 无法将“create-react-app”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果 包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1 + create-react-app -V + ~~~~~~~~~~~~~~~~+ CategoryInfo …

移动端 van-datetime-picker 组件不支持选择秒,自己写组件支持选择 “年月日时分秒”

需求 使用 van-datetime-picker 组件写时间选择时&#xff0c;不支持选择 “秒” 要求能够选择精确到秒 代码 封装组件 TimePicker <template><div><!-- 弹出层 --><van-popup get-container"body" v-model"isPicker" position&qu…

实时数仓-DWS层

理论依据&#xff1a;指标体系 如果表有相似&#xff0c;可以抽取成一张表 轻度聚合&#xff1a;比如聚合10秒的先放到DWS&#xff0c;这样ADS在计算的时候&#xff0c;会更快

计讯物联5G工业路由器加速赋能公交车监控系统解决方案智能升级

一、方案概述 为提升公交车智能化管理水平为目的&#xff0c;保障公交车营运人员和乘客的安全&#xff0c;计讯物联以公交车智能调度营运为核心&#xff0c;推出计讯物联5G公交车一站式解决方案&#xff0c;通过构建感知层、传输层、设备层、应用层四层架构&#xff0c;通过感…

将名为“普通高等学校本科专业目录.pdf”的pdf文件转换成csv文件

文章目录 任务描述2023年普通高等学校本科专业目录pdf链接代码代码解析运行截图 任务描述 将名为“普通高等学校本科专业目录.pdf”的pdf文件转换成csv文件。这个pdf每页是个表格&#xff0c;表格有7列。 下面是pdf的第一页和第二页&#xff1a; 2023年普通高等学校本科专业…

10.3.2 【Linux】历史命令:history

[dmtsaistudy ~]$ alias hhistory 在正常的情况下&#xff0c;历史命令的读取与记录是这样的&#xff1a; 当我们以 bash 登陆 Linux 主机之后&#xff0c;系统会主动的由主文件夹的 ~/.bash_history 读取以前曾经下过的指令&#xff0c;那么 ~/.bash_history 会记录几笔数据呢…

microblaze生成download.bit 报错:Program FPGA failed Reason: couldn‘t open......

报错信息&#xff1a; couldn’t open “E:/Xilinx_Project/……/……/…….sdk/top_wrapper_hw_platform_0/download.bit”: no such file or directory [Updatemem 57-153] Failed to update the BRAM INIT strings for E:\Xilinx_Project\……\……\…….sdk\……\Debug\……

基于vue的地方美食分享网站(spring boot)

本项目在开发和设计过程中涉及到原理和技术有&#xff1a;B/S、java技术和MySQL数据库等等。开发步骤如下&#xff1a; 绪论&#xff1b;剖析项目背景&#xff0c;说明研究的内容。 开发技术&#xff1b;系统主要使用了java技术&#xff0c;b/s模式和myspl数据库.

react-基础-01

vue tutorial 上的小demo 改用react 写法 属性绑定 <div className{xx}></div>事件绑定 import React, { useState } from react;export function App(props) {const [count, setCount] useState(0)function add() {setCount(count 1)}return (<div classN…

Broadcast 广播使用详解

和你一起终身学习&#xff0c;这里是程序员Android 经典好文推荐&#xff0c;通过阅读本文&#xff0c;您将收获以下知识点: 一、Broadcast概述二、Broadcast的注册三、Broadcast的注册类型四、静态注册开机广播的实现五、动态监听亮灭屏幕广播实现六、广播的发送方法七、参考文…

【Hello mysql】 mysql的内置函数

Mysql专栏&#xff1a;Mysql 本篇博客简介&#xff1a;介绍mysql的基内置函数 mysql的内置函数 日期函数获取年月日获取时分秒获取时间戳在日期的基础上加上日期在日期的基础上减去日期计算两个日期之差创建一张表 记录生日创建一个留言表 字符串函数获取emp表的ename列的字符集…

arm学习stm32芯片学习方波启动蜂鸣器,马达,风扇

main.c #include "pwm.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); } int main() {//蜂鸣器初始化hal_pwm_beep_init1();//马达hal_pwm_motor_init1();//风扇hal_pwm_blower_…

MySQL 06 :多表查询

MySQL 05 :多表查询 加where过滤 老韩分析 1。雇员名&#xff0c;雇员工资来自emp表 2。部门的名字来自dept表 3。 需求对emp和dept查询 ename&#xff0c;sal&#xff0c;dname&#xff0c;deptno 4。 当我们需要指定显示某个表的列是&#xff0c;需要表&#xff0c; 说明 …

视频的特效效果是怎么加的?可以批量添加吗

经常逛自媒体平台的小伙伴不难发现&#xff0c;要想原创的短视频更有创造性&#xff0c;内容更丰富&#xff0c;给视频添加特效效果算是比较常用的一个方法了。今天小编要分享的可不只是单一地给视频添加特效这么简单&#xff0c;我要给大家分享如何才能快速地批量给视频素材添…