嵌入式面向对象学习 RT-Thread I/O 设备管理框架 设备驱动层 案例测试

嵌入式面向对象 RT-Thread I/O 设备管理框架 设备驱动层

注:本文介绍性内容转载于《RT-Thread记录(十、全面认识 RT-Thread I/O 设备模型)》

注: 本次使用的开发板 :

​ 兆易创新GD32F407VET6开发板

​ 雅特力科技AT32A403A开发板

在这里插入图片描述
在这里插入图片描述

一、RT-Thread 的 I/O设备管理

1.1 什么是 I/O 设备模型
1.2 I/O 设备模型框架解析
1.3 I/O 设备操作逻辑说明
1.4 I/O 设备模型框架用处

二、I/O 设备模型操作 API

2.1 I/O 设备控制块
2.2 创建 I/O 设备相关
2.3 访问 I/O 设备相关

三、新建 I/O 设备模型实例

3.1 设备驱动层编写
3.2 应用层测试

一、RT-Thread 的 I/O设备管理

我们先从基本概念说起,了解RT-Thread 对 I/O 设备的管理方式,以及 I/O 设备模型框架的用途:

1.1 什么是 I/O 设备模型

有些小伙伴在刚接触到这个概念的时候还不太明白, I/O 设备模型,IO口?IO口的模型?

注意这里的 I/O 指的是 Input/Output。I/O 设备,就是指的输入 / 输出设备。

所谓 I/O 设备模型,指的是 RT-Thread 把所有的 输入 / 输出设备当做一类对象,然后通过自己的一套体系对这类对象进行管理,这类 I/O 设备对象就可以认为是 I/O 设备模型。

RT-Thread 提供了一套模型框架用来对所有的输入/输出设备进行管理的,名叫 I/O 设备模型框架 ,其 位于硬件层和应用程序之间,包括IO设备管理层、设备驱动框架层和设备驱动层, 向上层层抽象,目标是针对各种不同的I/O设备提供给应用程序相同的接口,如下图:
在这里插入图片描述
内容太多,具体内容在 嵌入式面向对象学习 RT-Thread I/O 设备管理框架 设备驱动层

三、新建 I/O 设备模型实例

前面的大部分内容都是参考文章的东西,对于I/O 设备模型进行了大量的说明。接下来进行案例测试

RT-Thread 驱动都是在 drivers 目录下面:
在这里插入图片描述

我们在目录下新建一个文件,作为驱动示例:

我们写一个简单的基本框架:

1、创建一个设备;
使用 rt_device_create 创建一个设备,需要定义一个 rt_device_t 接口体接收设备设备句柄。

2、实现设备操作的函数:
实现设备对象中对于 设备操作的init,open,close,read,write,control等 函数。在这里插入图片描述
3、注册设备到 I/O 设备管理器;
使用 rt_device_register 将设备注册到设备管理器。

drv_demo.c 中,我们实现如下代码:

在这里插入图片描述
其次,我们需要实现一下设备操作的函数:
在这里插入图片描述
最后,别忘了使用 INIT_BOARD_EXPORT 把设备初始化的代码加入板级硬件初始化:

设备模型实例代码:

#include <rtdevice.h>
#include <rtdbg.h>

rt_err_t  demo_init(rt_device_t dev)
{
    rt_kprintf("demo_init ok!\n");
    return RT_EOK;
}
rt_err_t  demo_open(rt_device_t dev, rt_uint16_t oflag)
{
    rt_kprintf("demo_open ok!\n");
    return RT_EOK;
}
rt_err_t  demo_cloes(rt_device_t dev)
{
    rt_kprintf("demo_cloes ok!\n");
    return RT_EOK;
}

rt_ssize_t demo_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
{
	  buffer = "this is device read example";
	  rt_kprintf("read example: %s\n",buffer);
	  return RT_EOK;
}
rt_ssize_t demo_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
{
	  buffer = "this is device write example";
	  rt_kprintf("write example: %s\n",buffer);
	  return RT_EOK;
}
rt_err_t  demo_control(rt_device_t dev, int cmd, void *args)
{
	switch(cmd)
	{
		case 0:
			rt_kprintf("this is demo_control example cmd-1!\n");	
			break;
		case 1:
			rt_kprintf("this is demo_control example  cmd-2!\n");	
			break;
		case 2:
			rt_kprintf("this is demo_control example  cmd-3!\n");	
			break;
		default:
			break;
	}
}


int rt_drvdemo_init(void)
{

    rt_device_t demo_dev = RT_NULL;

    demo_dev = rt_device_create(RT_Device_Class_Char, 0);
    if(demo_dev == RT_NULL){
        LOG_E("demo device create failed...\n");
        return RT_ERROR;
    }

    demo_dev->init=demo_init;
    demo_dev->open=demo_open;
    demo_dev->close=demo_cloes;
	demo_dev->read = demo_read;
    demo_dev->write = demo_write;
	demo_dev->control =demo_control;
    rt_device_register(demo_dev,"drvdemo",RT_DEVICE_FLAG_RDWR);
    return 0;
}


INIT_BOARD_EXPORT(rt_drvdemo_init);

上面我们完成的是 设备驱动层的 代码,接下来我们还需要简单演示一下,如果在应用层 使用这个 demo 设备。

我们根据上文所介绍的 访问 I/O 设备 进行对应操作,这里直接上图说明一下使用流程:

应用测试函数

rt_device_t dev = RT_NULL;

void *read_buf;
void *write_buf;

int main(void)
{

	dev = rt_device_find("drvdemo");
	
	  rt_device_init(dev);
	  rt_thread_mdelay(1000);
	  rt_device_open(dev,RT_DEVICE_OFLAG_OPEN);
	  rt_device_read(dev,0,read_buf,20);
	  rt_device_write(dev,0,write_buf,20);
	  rt_device_control(dev,0,RT_NULL);
	  rt_device_close(dev);
		
		
    return RT_EOK;
}

看一下测试结果,我们实现的 3 个驱动函数都只有打印输出,所以我们可以通过打印信息查看是否正确执行的驱动函数的内容:

下面是在雅特力AT32开发板的测试结果。

(原本打算使用gd32去做实验的,但是从官方的MDK工程打开一直存在问题,然后就换了一块板子,进行测试,从这里可以发现,统一的API接口的好处,应用层无缝对接)

在这里插入图片描述
在这里插入图片描述
下面是在对于立创开发板GD32F407进行详细实验。

  1. 下载rt-thread 源码
  2. 寻找bsp-gd32工程,gd32有两个类型一个是arm,一个risc-v
  3. 寻找立创开发板GD32F407模板工程 gd32f407v-lckfb
  4. 使用env工具进行配置

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  1. 如果直接编译,会报一个错误bug,需要修改,解决方法是添加condvar.c文件即可。

在这里插入图片描述

  1. 添加编写的drv_demo.c文件,完成设备驱动的添加

在这里插入图片描述
7. 编写应用层程序 测试

/*
 * Copyright (c) 2006-2024, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-01-13     yuanzihao    first implementation
 */

#include <stdio.h>
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

/* defined the LED1 pin: PB2 */
#define LED_PIN GET_PIN(B, 2)
rt_device_t dev = RT_NULL;

void *read_buf;
void *write_buf;
int main(void)
{
    int count = 1;
    dev = rt_device_find("drvdemo");
	
	  rt_device_init(dev);
	  rt_thread_mdelay(1000);
	  rt_device_open(dev,RT_DEVICE_OFLAG_OPEN);
	  rt_device_read(dev,0,read_buf,20);
	  rt_device_write(dev,0,write_buf,20);
	  rt_device_control(dev,1,RT_NULL);
	  rt_device_close(dev);
		
    /* set LED1 pin mode to output */
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
   
    while (count++)
    {
        rt_pin_write(LED_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
			  //rt_kprintf("this is led_control on  [ok]!\n");	
        rt_pin_write(LED_PIN, PIN_LOW);
        rt_thread_mdelay(500);
			  //rt_kprintf("this is led_control off [ok]!\n");	
    }

    return RT_EOK;
}

在这里插入图片描述
在这里插入图片描述

通过上面的测试,我们实现了一个简单的设备驱动的设计,虽然demo比较简单,但是经过这么一个过程可以让我们更加的理解 RT-Thread I/O 设备模型的工作方式和流程。

在这里,同时介绍一个开源项目mr-library。

mr-library 是一个开源项目,设备抽象层应该比RT-Thread更加轻量级,是一个学习设备框架,设备驱动,面向对象操作的好东西。

设备抽象层的开源库 mr-library

mr-library 框架是专为嵌入式系统设计的轻量级框架。充分考虑了嵌入式系统在资源和性能方面的需求。 通过提供标准化的设备管理接口,极大简化了嵌入式应用开发的难度,帮助开发者快速构建嵌入式应用程序。

框架为开发者提供了标准化的开启(open)、关闭(close)、控制(ioctl)、读(read)、写(write) 等接口。它将应用程序与底层硬件驱动进行解耦。应用程序无需了解驱动的实现细节。 当硬件发生改变时,只需要适配底层驱动,应用程序就可以无缝迁移到新硬件上。这大大提高了软件的可重用性和应对新硬件的可扩展性。


在这里插入图片描述

关键特性

  • 标准化的设备访问接口
  • 应用程序和驱动开发解耦
  • 简化底层驱动和应用程序开发
  • 轻量易上手,资源占用低
  • 模块化设计,各部分解耦合并独立开发,极低的硬件迁移成本
  • 支持在裸机环境和操作系统环境下使用

主要组成

  • 设备框架:提供设备访问标准接口
  • 内存管理:动态内存管理
  • 工具:链表、队列、平衡树等常用数据结构
  • 各类功能组件

标准化设备接口

设备的所有操作都可通过以下接口实现:

接口描述
mr_dev_register注册设备
mr_dev_open打开设备
mr_dev_close关闭设备
mr_dev_ioctl控制设备
mr_dev_read从设备读取数据
mr_dev_write向设备写入数据

测试案例

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构面试题报错调试方法记录

栈和队列报错调试 1.用栈实现队列 232. 用栈实现队列 - 力扣&#xff08;LeetCode&#xff09; 此题解题思路如下&#xff1a; 先将数据放在pushst栈里面&#xff0c;popst栈为空再把pushst栈里面的数据放进popst栈里面去&#xff0c;不为空则不执行。不为空时候直接拿取栈…

楚雄师范学院数学与计算机学院与树莓集团产教融合合作签约仪式顺利举行!

2024年4月2日&#xff0c;楚雄师范学院数学与计算机学院与树莓集团产教融合合作签约仪式在云南楚雄师范学院隆重举行。未来&#xff0c;双方将在国际数字影像产业园建设产教融合实训基地&#xff0c;全面增强人才培养的社会适应性。 出席本次签约仪式的嘉宾有学院党委书记周云燕…

PyTorch深度学习——张量及其运算

深度学习框架的张量 张量的运算是深度学习的核心&#xff0c;如一张图片可以看作是四维的张量&#xff0c;一个迷你批次的文本可以看作是二维张量&#xff0c;基本上所有的深度学习模型都可以表示为张量的操作&#xff0c;梯度、反向传播算法也可以表示为张量和张量的运算 张…

opencv图像处理技术(阈值处理与图像平滑)

进行图像处理时&#xff0c;常常需要对图像进行预处理以提取所需的信息或改善图像质量。阈值处理和图像平滑是两种常见的预处理技术。 阈值处理 阈值处理是一种图像分割技术&#xff0c;其基本思想是将图像中的像素值与一个或多个预先设定的阈值进行比较&#xff0c;根据比较…

Git入门实战教程之创建版本库

一、Git简介 Git是一个分布式版本控制系&#xff0c;分层结构如下&#xff1a; Git分为四层&#xff1a; 1、工作目录 当前正在工作的项目的实际文件目录&#xff0c;我们执行命令git init时所在的地方&#xff0c;也就是我们执行一切文件操作的地方。 2、暂存区 暂存区是…

软件测试常考面试题-软件测试面试宝典(一篇足矣)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

数据库表设计18条黄金规则

前言 对于后端开发同学来说&#xff0c;访问数据库&#xff0c;是代码中必不可少的一个环节。 系统中收集到用户的核心数据&#xff0c;为了安全性&#xff0c;我们一般会存储到数据库&#xff0c;比如&#xff1a;mysql&#xff0c;oracle等。 后端开发的日常工作&#xff…

C语言初阶—9函数

函数的声明 &#xff08;main函数前&#xff09;----告诉有一个函数 格式&#xff1a; 类型 函数名&#xff08;参数&#xff09;&#xff1b; 函数的声明 放到头文件add.c 函数的定义 ----创建函数----放到add.c 格式&#xff1a;类型 函数名(参数) { 语句项; } 在文…

leetcode.707. 设计链表

题目 题意&#xff1a; 在链表类中实现这些功能&#xff1a; get(index)&#xff1a;获取链表中第 index 个节点的值。如果索引无效&#xff0c;则返回-1。 addAtHead(val)&#xff1a;在链表的第一个元素之前添加一个值为 val 的节点。插入后&#xff0c;新节点将成为链表的…

Dubbo 序列化

Dubbo 序列化 1、什么是序列化和反序列化 序列化&#xff08;serialization&#xff09;在计算机科学的资料处理中&#xff0c;是指将数据结构或对象状态转换成可取用格式&#xff08;例如存成文件&#xff0c;存于缓冲&#xff0c;或经由网络中发送&#xff09;&#xff0c;…

MySQL数据库基础--事务

事务 是一组操作的集合&#xff0c;他是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 默认MySQL的事务是自动提交的&#xff0c;也就是说&#xff0c;当执行…

《C语言深度解剖》(2):详解C语言分支语句和循环

&#x1f921;博客主页&#xff1a;醉竺 &#x1f970;本文专栏&#xff1a;《C语言深度解剖》 &#x1f63b;欢迎关注&#xff1a;感谢大家的点赞评论关注&#xff0c;祝您学有所成&#xff01; ✨✨&#x1f49c;&#x1f49b;想要学习更多数据结构与算法点击专栏链接查看&am…

Node操作mysql

配置 安装mysql模块 npm i mysql建立连接 const mysql require(mysql);const db mysql.createPool({host: 127.0.0.1,user: root,password: admin123,database: my_db_01 });测试 // select 1没有任何实质性作用 只是检查mysql模块是否正常 db.query(select 1, (err, results…

修电机所需要的基本工具

等距式 模具 同心式模具 电机划线刀 压脚 千分尺 -----测量线径 钳形电流表------- 测量 空载 满载下的电流值 摇表&#xff0c; 测量线圈是否碰到外壳 指针式万用表 胶锤 整理线圈 绝缘纸和青稞纸&#xf…

RuoYi-Vue若依框架-vue前端给对象添加字段

处理两个字段的时候有需求都要显示在下拉框的同一行&#xff0c;这里有两种解决方案&#xff0c;一是后端在实体类添加一个对象&#xff0c;加注解数据库忽略处理&#xff0c;在接口处拼接并传给前端&#xff0c;二是在前端获取的数据数组内为每个对象都添加一个字段&#xff0…

Ethernet 汇总

Ethernet系统 硬件最小系统 CPU:可以是复杂的芯片,也可以是小的单片机DMA:用于减轻CPU负担,搬运数据系统Memory<->FIFOMAC:可以集成在芯片里面,用于CPU和PHY之间的通信MII:接口用于MAC和PHY的通信,包括控制MDIO和数据DataPHY:模拟器件,最底层,数据收发源头软件…

Vue3【进阶】

简介 https://cn.vuejs.org/guide/introduction.html 创建vue3工程 【基于 vue-cli创建】 基本和vue-cli的过程类似&#xff0c;只是选择的时候用vue3创建 【基于vite创建】【推荐】 【官网】https://vitejs.cn/ 【可以先去学一下webpack】 步骤 【https://cn.vitejs.…

PostgreSQL入门到实战-第三弹

PostgreSQL入门到实战 PostgreSQL安装之linux官网地址PostgreSQL概述linux安装PostgreSQL更新计划 PostgreSQL安装之linux 官网地址 声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 https://www.postgresql.org/PostgreSQL概述 Postg…

【全套源码教程】基于SpringBoot+MyBatis+Vue的流浪动物救助网站的设计与实现

目录 前言 需求分析 可行性分析 技术实现 后端框架&#xff1a;Spring Boot 持久层框架&#xff1a;MyBatis 前端框架&#xff1a;Vue.js 数据库&#xff1a;MySQL 功能介绍 前台界面功能介绍 动物领养及捐赠 宠物论坛 公告信息 商品页面 寻宠服务 个人中心 购…

AI视觉入门:卷积和池化

从2012年以AlexNet为代表的模型问世以来&#xff0c;人工智能尤其是视觉cv部分飞速发展&#xff0c;在刚开始效果不如人类&#xff0c;到2015年在ImageNet1000数据集的表现就超过了人类。在Transformer模型出现之前&#xff0c;视觉模型的主要组成部分就是卷积和池化&#xff0…