20231027 基于STM32mp157a 的内核与应用层通过子系统控制led灯,以及计时器功能

news2024/11/14 18:57:08

1.基于GPIO子系统编写LED驱动,编写应用程序进行测试

stm32mp157a-fsmp1a.dts

内核程序:ledk.c

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

struct device_node *dnode1;
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;
struct timer_list mytimer;

unsigned int *vir_rcc;
struct class *cls;
struct device *dev;
int major;

char kbuf[128] = {0};

//定义操作方法
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)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    int ret1=copy_to_user(ubuf,kbuf,size);
    if(ret1)
    {
        printk("copy_to_user filed\n");
        return -EIO;
    }
    return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    int ret=copy_from_user(kbuf,ubuf,size);
    if(ret)
    {
        printk("copy_from_user filed\n");
        return -EIO;
    }
    //设定该GPIO管脚的输出值
    if(!strcmp(kbuf,"off"))
    {
        gpiod_set_value(gpiono1,0);
        gpiod_set_value(gpiono2,0);
        gpiod_set_value(gpiono3,0);       
    }
    else if(!strcmp(kbuf,"on"))
    {
        gpiod_set_value(gpiono1,1);
        gpiod_set_value(gpiono2,1);
        gpiod_set_value(gpiono3,1); 
    }
    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);
    // 向上提交目录
    cls = class_create(THIS_MODULE, "mychrdev");
    if (IS_ERR(cls))
    {
        printk("向上提交目录失败\n");
        return -PTR_ERR(cls);
    }
    printk("向上提交目录成功\n");
    // 向上提交设备节点信息
    int i; // 向上提交三次设备节点信息
    for (i = 0; i < 3; i++)
    {
        dev = device_create(cls, NULL, MKDEV(major, i), NULL, "myled%d", i);
        if (IS_ERR(dev))
        {
            printk("向上提交设备节点失败\n");
            return -PTR_ERR(dev);
        }
    }
    printk("向上提交设备节点成功\n");


    //解析设备树节点信息
    dnode1 = of_find_node_by_path("/myled");
    if(dnode1 == NULL)
    {
        printk("path_find failed \n");
        return -ENXIO;
    }
    //根据GPIO相关节点得到GPIO编号
    gpiono1 = gpiod_get_from_of_node(dnode1,"led1-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono1))
    {
        printk("申请gpiono1信息失败 \n");
    }
    printk("申请gpiono1信息成功 \n");
    gpiono2 = gpiod_get_from_of_node(dnode1,"led2-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono2))
    {
        printk("申请gpiono2信息失败 \n");
    }
    printk("申请gpiono2信息成功 \n");
    gpiono3 = gpiod_get_from_of_node(dnode1,"led3-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono3))
    {
        printk("申请gpiono3信息失败 \n");
    }
    printk("申请gpiono3信息成功 \n");


    //GPIO的状态
    
    return 0;
}
static void __exit mycdev_exit(void)
{
    //设定该GPIO管脚的输出值
    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);

    // 销毁设备节点信息
    int i;
    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);
MODULE_LICENSE("GPL");

应用程序:ledu.c

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

int main(int argc,const char * argv[])
{
    int a=0;
    char buf[128] = "";
    char buf1[128] = "";
    int fd1=open("/dev/myled0",O_RDWR);
    int fd2=open("/dev/myled1",O_RDWR);
    int fd3=open("/dev/myled2",O_RDWR);
    if(fd1<0)
    {
        printf("打开设备文件1失败\n");
        exit(-1);
    }
    if(fd2<0)
    {
        printf("打开设备文件2失败\n");
        exit(-1);
    }
    if(fd3<0)
    {
        printf("打开设备文件3失败\n");
        exit(-1);
    }

    memset(buf,0,sizeof(buf));
    while(1)
    {
        printf("请输入灯的控制(1开灯/0关灯) => ");
        scanf("%d",&a);
        
        write(fd1,buf,sizeof(buf));
        write(fd2,buf,sizeof(buf));
        write(fd3,buf,sizeof(buf));

        if(a == 1)
        {
            strcpy(buf,"on");
            write(fd1,buf,sizeof(buf));
            write(fd2,buf,sizeof(buf));
            write(fd3,buf,sizeof(buf));            
        }
        else if(a == 0)
        {
            strcpy(buf,"off");
            write(fd1,buf,sizeof(buf));
            write(fd2,buf,sizeof(buf));
            write(fd3,buf,sizeof(buf));             
        }
        read(fd1,buf1,sizeof(buf));
        printf("buf1:%s\n",buf1);
    }
    return 0;
}

2.设置定时器,5秒钟打印一次hello world

内核程序

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

struct device_node *dnode1;
struct gpio_desc *gpiono1;
struct gpio_desc *gpiono2;
struct gpio_desc *gpiono3;
struct timer_list mytimer;

char kbuf[128] = {0};

void mytimer_funtion(struct timer_list *timer)
{
    
    //PRINTK
    printk("阿巴阿巴阿巴阿巴阿巴\n");
    gpiod_set_value(gpiono1,!gpiod_get_value(gpiono1));

    //启用定时器
    mod_timer(timer,jiffies + msecs_to_jiffies(5000));
}


static int __init mycdev_init(void)
{
    //解析设备树节点信息
    dnode1 = of_find_node_by_path("/myled");
    if(dnode1 == NULL)
    {
        printk("path_find failed \n");
        return -ENXIO;
    }
    //根据GPIO相关节点得到GPIO编号
    gpiono1 = gpiod_get_from_of_node(dnode1,"led1-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono1))
    {
        printk("申请gpiono1信息失败 \n");
    }
    gpiono2 = gpiod_get_from_of_node(dnode1,"led2-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono2))
    {
        printk("申请gpiono2信息失败 \n");
    }
    gpiono3 = gpiod_get_from_of_node(dnode1,"led3-gpio",0,GPIOD_OUT_LOW,NULL);
    if(IS_ERR(gpiono3))
    {
        printk("申请gpiono3信息失败 \n");
    }
    //分配定时器对象(timer_list)
    //初始化定时器(timer_setup)
    timer_setup(&mytimer,mytimer_funtion,0);
    mytimer.expires = jiffies+HZ;
    //注册定时器并启用(add_timer)
    add_timer(&mytimer);


    //GPIO的状态
    
    return 0;
}
static void __exit mycdev_exit(void)
{
    //设定该GPIO管脚的输出值
    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);
    //注销定时器(del_timer)
    del_timer(&mytimer);

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

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

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

相关文章

C++进阶语法——OOP(面向对象)【学习笔记(四)】

文章目录 1、C OOP⾯向对象开发1.1 类&#xff08;classes&#xff09;和对象&#xff08;objects&#xff09;1.2 public、private、protected访问权限1.3 实现成员⽅法1.4 构造函数&#xff08;constructor&#xff09;和 析构函数&#xff08;destructor&#xff09;1.4.1 构…

kubectl资源管理命令-陈述式

目录 一、陈述式对象管理 1、基本概念 2、基础命令使用 3、基本信息查看&#xff08;kubectl get&#xff09; 4、增删等操作 5、登录pod中的容器 6、扩容缩容pod控制器的pod 7、删除副本控制器 二、创建项目实例 1、创建 kubectl create命令 2、发布 kubectl …

Spring Cloud Gateway + Knife4j 4.3 实现微服务网关聚合接口文档

目录 前言Spring Cloud 整合 Knife4jpom.xmlapplication.ymlSwaggerConfig.java访问单服务接口文档 Spring Cloud Gateway 网关聚合pom.xmlapplication.yml访问网关聚合接口文档 接口测试**登录认证**获取登录用户信息 结语源码 前言 youlai-mall 开源微服务商城新版本基于 Sp…

怎样使用Mybatis数据库连接池?

怎样使用Mybatis数据库连接池&#xff1f; 首先是配置&#xff0c;如下图&#xff1a; 千万要注意&#xff0c;一个程序中只创建一个SqlSessionFactory对象&#xff0c;要不然每次执行sql都创新创建一个SqlSessionFactory对象的话&#xff0c;那么每次建立连接的时候都会先清…

Chimera:混合的 RLWE-FHE 方案

参考文献&#xff1a; [HS14] S. Halevi and V. Shoup. Algorithms in HElib. In Advances in Cryptology–CRYPTO 2014, pages 554–571. Springer, 2014.[HS15] S. Halevi and V. Shoup. Bootstrapping for HElib. In Advances in Cryptology–EUROCRYPT 2015, pages 641–6…

【Spring】快速入门Spring Web MVC

文章目录 1. 什么是Spring Web MVC1.1 MVC1.2 Spring MVC 2. 使用Spring MVC2.1 项目创建2.2 建立连接2.2.1 RequestMapping 注解2.2.2 RestController 注解2.2.3 RequestMapping 使⽤2.2.4 RequestMapping 是什么请求&#xff1f;POST&#xff1f;GET&#xff1f;…&#xff1…

Linux高性能服务器编程——ch8笔记

第8章 高性能服务器程序框架 8.1 服务器模型 服务器启动后&#xff0c;首先创建一个&#xff08;或多个&#xff09;监听socket&#xff0c;并调用bind函数将其绑定到服务器感兴趣的端口&#xff0c;然后调用listen函数等待客户连接。服务器稳定运行之后&#xff0c;客户端就可…

网盘限速问题解析:哪家网盘真的不限速?

天下苦网盘限速久矣。市面上一些网盘工具要不然是收费限流&#xff0c;要不然是需要额外购买下载券。哪家网盘真的不限速&#xff1f; Zoho Workdrive 企业网盘是真正的不限速网盘&#xff0c;上传和下载文件都不限速&#xff0c;真正做到用户的网速有多快&#xff0c;下载就有…

玩转ChatGPT:批量下载Alphafold的蛋白pdb文件

一、写在前面 突发奇想&#xff0c;想批量下载Alphafold网站的蛋白pdb文件&#xff0c;后续再做个分子对接用。又不想手动下载&#xff0c;来求助CSDN和GPT。 二、CSDN白嫖基础代码 CSDN大神多&#xff0c;这不&#xff0c;找到一个&#xff1a;Alphafold批量下载蛋白的pdb文…

Unity Shader当用户靠近的时候会出现吃鸡一样的光墙

效果图片 靠近墙壁 远离墙壁 材质球的设置 两张图片 使用方式 把这个脚本放到墙上&#xff0c;将player赋值给"_player"&#xff0c;然后运行&#xff0c;用户靠近就会根据距离显示光墙。 using UnityEngine;public class NewBehaviourScript : MonoBehaviour {pr…

【算法|贪心算法系列No.5】leetcode409. 最长回文串

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

win10 + VS2017 编译libjpeg(jpeg-9b)

需要用到的文件&#xff1a; jpeg-9b.zip win32.mak 下载链接链接&#xff1a;https://pan.baidu.com/s/1Z0fwbi74-ZSMjSej-0dV2A 提取码&#xff1a;huhu 步骤1&#xff1a;下载并解压jpeg-9b。 这里把jpeg-9b解压到文件夹"D:\build-libs\jpeg\build\jpeg-9b" …

创纪录的1亿RPS DDoS攻击利用HTTP/2快速重置漏洞

导语&#xff1a;最近&#xff0c;一项创纪录的DDoS攻击引起了广泛关注。攻击者利用了HTTP/2协议中的一个快速重置漏洞&#xff0c;发起了一系列超大规模的攻击。本文将为大家详细介绍这次攻击的背景、影响以及应对措施。 攻击背景 最近&#xff0c;全球范围内遭受了一系列规模…

计算机操作系统重点概念整理-第六章 输入输出I/O管理【期末复习|考研复习】

第六章 输入输出I/O管理【期末复习|考研复习】 计算机操作系统系列文章传送门&#xff1a; 第一章 计算机系统概述 第二章 进程管理 第三章 进程同步 第四章 内存管理 第五章 文件管理 第六章 输出输出I/O管理 文章目录 第六章 输入输出I/O管理【期末复习|考研复习】前言六、输…

c++的4中类型转换操作符(static_cast,reinterpret_cast,dynamic_cast,const_cast),RTTI

目录 引入 介绍 static_cast 介绍 使用 reinterpret_cast 介绍 使用 const_cast 介绍 使用 dynamic_cast 介绍 使用 RTTI(运行时确定类型) 介绍 typeid运算符 dynamic_cast运算符 type_info类 引入 原本在c中,我们就已经接触到了很多类型转换 -- 隐式类型转…

论文阅读——GPT3

来自论文&#xff1a;Language Models are Few-Shot Learners Arxiv&#xff1a;https://arxiv.org/abs/2005.14165v2 记录下一些概念等。&#xff0c;没有太多细节。 预训练LM尽管任务无关&#xff0c;但是要达到好的效果仍然需要在特定数据集或任务上微调。因此需要消除这个…

YOLOv5配置文件之 - yaml

在YOLOv5的目录中&#xff0c;models文件夹里存储了YOLO的模型配置。 ./models/yolov5.yaml 定义了YOLOv5s网络结构的定义文件 yaml的主要内容 参数配置 nc: 80 类别数量 depth_multiple: 0.33 模型深度缩放因子 width_multiple: 0.50 控制卷积特征图的通道个数 anchors配…

JSON(详解)

目录 什么是JSON&#xff1f; 哪里会用到JSON&#xff1f; JSON的特点 JSON的优点 JSON的缺点 JSON和cJSON的关系 什么是JSON&#xff1f; JSON&#xff08;JavaScript Object Notation&#xff09;是一种轻量级的数据交换格式。它以易于阅读和编写的文本格式来存储和表示…

Linux mkdir命令:创建目录(文件夹)

mkdir 命令&#xff0c;是 make directories 的缩写&#xff0c;用于创建新目录&#xff0c;此命令所有用户都可以使用。mkdir 命令的基本格式为&#xff1a; [rootlocalhost ~]# mkdir [-mp] 目录名 -m 选项用于手动配置所创建目录的权限&#xff0c;而不再使用默认权限。 -p…

shell算数运算指令、

1.shell算数运算的指令 (( )) $[ ] let expr expr的字符串运算 例子&#xff1a; 2.shell的if分支结构