【RTT驱动框架分析01】-pin/gpio驱动分析

0gpio使用测试

LED测试

#define LED1_PIN        GET_PIN(C,  1)
void led1_thread_entry(void* parameter)
{rt_pin_mode(LED1_PIN, PIN_MODE_OUTPUT);while(1){rt_thread_delay(50);    //delay 500msrt_pin_write(LED1_PIN, PIN_HIGH);rt_thread_delay(50);    //delay 500msrt_pin_write(LED1_PIN, PIN_LOW);}
}

key轮训测试

#define KEY1_PIN        GET_PIN(A,  4)
#define KEY2_PIN        GET_PIN(A,  5)
#define KEY3_PIN        GET_PIN(A,  6)#define KEY1  rt_pin_read(KEY1_PIN)
#define KEY2  rt_pin_read(KEY2_PIN)
#define KEY3  rt_pin_read(KEY3_PIN)#define KEY1_PRES   1
#define KEY2_PRES   2
#define KEY3_PRES   3
uint8_t KEY_Scan(uint8_t mode)
{static uint8_t key_up=1;if(mode){key_up = 1;}if(key_up && (KEY1 == 0 || KEY2 == 0 || KEY3 == 0)){rt_thread_delay(1);key_up=0;if(KEY1 == 0){return KEY1_PRES;}else if(KEY2 == 0){return KEY2_PRES;}else if(KEY3 == 0){return KEY3_PRES;}} else if(KEY1 == 1 && KEY2 == 1 && KEY3 == 1){key_up = 1;}return 0;
}void key_test(void)
{rt_uint8_t key;rt_pin_mode(KEY1_PIN, PIN_MODE_INPUT_PULLUP);rt_pin_mode(KEY2_PIN, PIN_MODE_INPUT_PULLUP);while(1){key = KEY_Scan(0);switch(key){case KEY1_PRES:rt_kprintf("key1 pressed.\n");break;case KEY2_PRES:rt_kprintf("key2 pressed.\n");break;case KEY3_PRES:break;default:break;}rt_thread_delay(5);}
}

key中断测试

#define KEY3_PIN        GET_PIN(A,  6)
void key3_irq(void *args)
{rt_kprintf("enter key3 interrupt callback.\n");
}
void key_test(void)
{rt_pin_mode(KEY3_PIN, PIN_MODE_INPUT_PULLUP);rt_pin_attach_irq(KEY3_PIN, PIN_IRQ_MODE_FALLING, key3_irq, RT_NULL);rt_pin_irq_enable(KEY3_PIN, ENABLE);
}

1.设备抽象接口rt_device

struct rt_device
{struct rt_object          parent;                   /**< 继承至内核对象 */enum rt_device_class_type type;                     /**< device type 设备类型 can uart 等*/rt_uint16_t               flag;                     /**< device flag */rt_uint16_t               open_flag;                /**< device open flag */rt_uint8_t                ref_count;                /**< reference count */rt_uint8_t                device_id;                /**< 0 - 255 *//* device call back 发送和接收的回调函数 */rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);/* common device interface 抽象的操作接口 */rt_err_t  (*init)   (rt_device_t dev);rt_err_t  (*open)   (rt_device_t dev, rt_uint16_t oflag);rt_err_t  (*close)  (rt_device_t dev);rt_size_t (*read)   (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size);rt_size_t (*write)  (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size);rt_err_t  (*control)(rt_device_t dev, int cmd, void *args);
#endif#if defined(RT_USING_POSIX)const struct dfs_file_ops *fops;struct rt_wqueue wait_queue;
#endifvoid                     *user_data;                /**< device private data */
};

1.1.核对象

struct rt_object
{char       name[RT_NAME_MAX];                       /**< name of kernel object */rt_uint8_t type;                                    /**< type of kernel object */rt_uint8_t flag;                                    /**< flag of kernel object */#ifdef RT_USING_MODULEvoid      *module_id;                               /**< id of application module */
#endifrt_list_t  list;                                    /**< list node of kernel object */
};

pin设备驱动框架

该框架主要包含内容有:

  1. 一个继承至设备驱动框架的rt_device 对象
  2. 一个pin相关的操作函数集
    1. gpio模式配置
    2. gpio 读写函数
    3. 中断绑定解绑函数
    4. 中断使能函数
  3. pin设备的注册函数int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data);
//操作函数
struct rt_pin_ops
{void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode);void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value);int (*pin_read)(struct rt_device *device, rt_base_t pin);/* TODO: add GPIO interrupt */rt_err_t (*pin_attach_irq)(struct rt_device *device, rt_int32_t pin,rt_uint32_t mode, void (*hdr)(void *args), void *args);rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_int32_t pin);rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint32_t enabled);
};//pin设备驱动核心结构
struct rt_device_pin
{struct rt_device parent;const struct rt_pin_ops *ops;
};

N32L40x 的驱动程序drv_driver.c 分析

1.gpio 到gpio id的映射关系

/*这个宏 ## 就是连接符号
*/
#define __N32L40X_PORT(port)  GPIO##port##_BASE
//gpioid 和 [gpio分组h和pin] 的关系 gpioid = (gpio分组-gpio_base)*16+pin
#define GET_PIN(PORTx,PIN) (rt_base_t)((16 * ( ((rt_base_t)__N32L40X_PORT(PORTx) - (rt_base_t)GPIOA_BASE)/(0x0400UL) )) + PIN)

2.如何实现注册pin设备

  1. 定义一个rt_pin_ops对象分别实现内部的 模式设置函数,读写函数,中断绑定和解绑函数,中断使能函数
  2. 注册rt_pin_ops对象到内核

3.外部中断的处理办法

  1. 外部中断统一调用N32L40X_GPIO_EXTI_IRQHandler处理函数
  2. 外部中断的回到函数统一放在一个 pin_irq_hdr_tab 数组内部

中断处理

在这里插入图片描述

中断绑定

绑定的实质就是给pin_irq_hdr_tab 内部的对象成员赋值操作
在这里插入图片描述

外部中断相关的结构

主要是存储用户注册中断处理函数

struct rt_pin_irq_hdr
{rt_int16_t        pin;rt_uint16_t       mode;//上升沿,下降沿等触发方式void (*hdr)(void *args);//用户绑定的中断处理函数void             *args;//参数
};

gpio时钟分组

在rtconfig.h中可能涉及需要开启gpio时钟

在这里插入图片描述

中断使能和关闭

内部实质就是设置中断分组和中断的触发模式中断优先级

在这里插入图片描述

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

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

相关文章

MySQL之深入InnoDB存储引擎——物理文件

文章目录 一、参数文件二、日志文件三、表结构定义文件四、InnoDB 存储引擎文件1、表空间文件2、重做日志文件 一、参数文件 当 MySQL 实例启动时&#xff0c;数据库会先去读一个配置参数文件&#xff0c;用来寻找数据库的各种文件所在位置以及指定某些初始化参数。在默认情况…

6-Linux的磁盘分区和挂载

Linux的磁盘分区和挂载 Linux分区查看所有设备的挂载情况 将磁盘进行挂载的案例增加一块磁盘的总体步骤1-在虚拟机中增加磁盘2- 分区3-格式化分区4-挂载分区5-进行永久挂载 磁盘情况查询查询系统整体磁盘使用情况查询指定目录的磁盘占用情况 磁盘情况-工作实用指令统计文件夹下…

【Rust 基础篇】Rust运算符重载:灵活定制运算行为

导言 Rust是一种以安全性和高效性著称的系统级编程语言&#xff0c;其设计哲学是在不损失性能的前提下&#xff0c;保障代码的内存安全和线程安全。在Rust中&#xff0c;运算符重载是一种非常强大的特性&#xff0c;允许我们对标准运算符进行自定义实现&#xff0c;从而灵活定…

Vue3搭建启动

Vue3搭建&启动 一、创建项目二、启动项目三、配置项目1、添加编辑器配置文件2、配置别名3、处理sass/scss4、处理tsx(不用的话可以不处理) 四、添加Eslint 一、创建项目 npm create vite 1.project-name 输入项目名vue3-vite 2.select a framework 选择框架 3.select a var…

关于前端框架vue2升级为vue3的相关说明

一些框架需要升级 当前&#xff08;202306&#xff09; Vue 的最新稳定版本是 v3.3.4。Vue 框架升级为最新的3.0版本&#xff0c;涉及的相关依赖变更有&#xff1a; 前提条件&#xff1a;已安装 16.0 或更高版本的Node.js&#xff08;摘&#xff09; 必须的变更&#xff1a;核…

C语言进阶——文件的打开(为什么使用文件、什么是文件、文件的打开和关闭)

目录 为什么使用文件 什么是文件 程序文件 数据文件 文件名 文件的打开和关闭 文件指针 打开和关闭 为什么使用文件 在之前学习通讯录时&#xff0c;我们可以给通讯录中增加、删除数据&#xff0c;此时数据是存放在内存中&#xff0c;当程序退出的时候&#xff0c;通讯…

【弹力设计篇】聊聊灾备设计、异地多活设计

单机&集群架构 对于一个高可用系统来说&#xff0c;为了提升系统的稳定性&#xff0c;需要以下常用技术服务拆分、服务冗余、限流降级、高可用架构设计、高可用运维&#xff0c;而本篇主要详细介绍下&#xff0c;高可用架构设计。容灾备份以及同城多活&#xff0c;异地多活…

OpenCV实现高斯模糊加水印

# coding:utf-8 # Email: wangguisendonews.com # Time: 2023/4/21 10:07 # File: utils.pyimport cv2 import PIL from PIL import Image import numpy as np from watermarker.marker import add_mark, im_add_mark import matplotlib.pyplot as plt# PIL Image转换成OpenCV格…

Git使用详解

什么是 Git&#xff1f; Git 是一种分布式版本控制系统&#xff0c;它可以帮助开发者跟踪文件的变化、协作开发、管理代码库等。与集中式版本控制系统不同&#xff0c;Git 的每个工作副本都包含完整的项目历史&#xff0c;这使得在没有网络连接的情况下也能独立进行工作。Git 的…

C++中的主线程、子线程

在C中&#xff0c;线程是并发执行的最小单位。主线程&#xff08;main thread&#xff09;通常是一个程序开始执行时系统自动创建的线程&#xff0c;而子线程&#xff08;child thread或worker thread&#xff09;则是由主线程或其他子线程创建的线程。 并发执行&#xff0c;又…

ORBSLAM2第一阶段跟踪课后习题

不定项选择题 (2分) 阅读TrackReferenceKeyFrame()函数&#xff0c;以下说法[错误]的是? A.该函数是地图初始化完成后&#xff0c;第一个使用的跟踪方式 B.该函数中使用词袋&#xff0c;目的是可以加快当前顿与参考帧之间的特征点匹配速度C.BA优化中同时优化了位姿和地图点 D.…

kafka:消费者从指定时间的偏移开始消费(二)

我的前一篇博客《kafka:AdminClient获取指定主题的所有消费者的消费偏移(一)》为了忽略忽略掉上线之前的所有消息&#xff0c;从获取指定主题的所有消费者的消费偏移并计算出最大偏移来解决此问题。 但这个方案需要使用不常用的AdminClient类&#xff0c;而且如果该主题如果是第…

Python的输入:探索不同的输入方法和技巧

Python的输入&#xff1a;探索不同的输入方法和技巧 引言 1.1 Python的输入概述 在编程中&#xff0c;输入是一个非常重要的概念。它允许我们从用户、文件或其他程序中获取数据&#xff0c;以便进行处理、计算或展示。Python提供了多种方法来获取输入&#xff0c;每种方法都…

SpringBoot中的RestTemplate使用笔记

SpringBoot中的RestTemplate使用笔记 为了方便使用&#xff0c;这里我封装成一个工具类来静态调用RestTemplate以下代码是基于SpringBoot2.4.2版本写的案例 需要配置的application.yml如下 server:port: 7024servlet:context-path: /demosession:timeout: 30m #默认会话过期…

redis分布式锁

Redis 作者继续论述&#xff0c;如果对方认为&#xff0c;发生网络延迟、进程 GC 是在步骤 3 之后&#xff0c;也就是客户端确认拿到了锁&#xff0c;去操作共享资源的途中发生了问题&#xff0c;导致锁失效&#xff0c;那这不止是 Redlock 的问题&#xff0c;任何其它锁服务例…

数据库面试题

Mysql篇 &#xff08;1&#xff09;请你解释下mysql主从同步中的&#xff0c;全同步&#xff0c;异步&#xff0c;以及半同步的三种模式概念? 此题是XX想面试题。 MySQL默认的复制即是异步的&#xff1a; 主库在执行完客户端提交的事务后会立即将结果返给客户端&#xff0c…

Flowable-任务-脚本任务

定义 脚本任务&#xff08;Script Task&#xff09;是一种自动执行的活动。当流程执行到达脚本任务时&#xff0c;会执行相应的 脚本&#xff0c;完毕后继续执行后继路线。脚本任务无须人为参与&#xff0c;可以通过定义脚本实现自定义的业务逻辑。 图形标记 脚本任务显示为…

数据结构基础:3.单链表的实现。

单链表的介绍和实现 一.基本概念1.基本结构2.结构体节点的定义&#xff1a; 二.功能接口的实现0.第一个节点&#xff1a;plist1打印链表2创建一个节点3.头插4.头删5.尾插6.尾删7.查找8.在pos之前插入x9.在pos之后插入x10.删除pos位置11.删除pos的后一个位置12.链表释放 三.整体…

UE4/5C++多线程插件制作(二十、源码)

目录 头文件 MultiThreadPlugins.uplugin MultiThreadPlugins.Build.cs MultiThreadPlugins.h MTPPlatform.h MTPManage.h RTPAgendy.h MTPThreadTaskManage.h

C语言每天一练----输出水仙花数

题目&#xff1a;请输出所有的"水仙花数" 题解&#xff1a;所谓"水仙花数"是指一个3位数,其各位数字立方和等于该数本身。 例如, 153是水仙花数, 因为153 1 * 1 * 1 5 * 5 * 5 3 * 3 * 3" #define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h&g…