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

news2024/9/28 17:35:29

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 500ms
        rt_pin_write(LED1_PIN, PIN_HIGH);
        rt_thread_delay(50);    //delay 500ms
        rt_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;
#endif

    void                     *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_MODULE
    void      *module_id;                               /**< id of application module */
#endif
    rt_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.coloradmin.cn/o/808649.html

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

相关文章

漏洞发现-操作系统之漏洞探针类型利用修复(42)

主要包括四个部分&#xff0c; 系统漏洞发现的的意义&#xff1a;应用是基于操作系统的&#xff0c;针对的操作系统&#xff0c;如果漏洞本身就有问题&#xff0c;就不需要对特定的网站特定的漏洞寻找&#xff0c;因为网站是寄生在服务器上&#xff0c;而服务器丢失就可以帮助…

Sentinel dashboard的使用;Nacos保存Sentinel限流规则

Sentinel dashboard的使用 往期文章 Nacos环境搭建Nacos注册中心的使用Nacos配置中心的使用Sentinel 容灾中心的使用 参考文档 Sentinel alibaba/spring-cloud-alibaba Wiki GitHub 限流结果 下载sentinel-dashboard github地址&#xff1a;Sentinel/sentinel-dashboar…

【雕爷学编程】MicroPython动手做(13)——掌控板之RGB三色灯3

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

TypeScript基础篇 - TS模块

目录 模块的概念 Export 语法&#xff08;default&#xff09; Export 语法&#xff08;non-default&#xff09; import 别名 Type Export语法【TS】 模块相关配置项&#xff1a;module【tsconfig.json】 模块相关配置项&#xff1a;moduleResolution 小节总结 模块的…

手写vuex

vuex 基本用法 vuex是作为插件使用&#xff0c;Vue.use(vuex) 最后注册给new Vue的是一个new Vuex.Store实例 // store.js import Vue from vue import Vuex from vuexVue.use(Vuex) // Vue.use注册插件 // new Vuex.Store实例 export default new Vuex.Store({state: {},gette…

详解Mybatis之逆向工程问题

编译软件&#xff1a;IntelliJ IDEA 2019.2.4 x64 操作系统&#xff1a;win10 x64 位 家庭版 Maven版本&#xff1a;apache-maven-3.6.3 Mybatis版本&#xff1a;3.5.6 文章目录 一. Mybatis中的逆向工程是什么&#xff1f;二. 什么是MBG&#xff1f;三. MBG如何使用&#xff1…

Android Studio 启用设备远程调试配置完整步聚

启用手机设置->开发者选项-无线调试,然后选择允许 已启用后无线调试变成绿色 ,点击无线调试进入详情页面 点击Android Studio的Device Manager 下的WIFI图标 会弹出下图窗口 打开手机的开发者选项中的WIFI调试(无线调试)下的使用二维码配对设备进行扫描. 设备配对成功后手机…

JDBC Common Connection Problems

连接问题 Access denied for user ‘root’‘localhost’ (using password: YES) 第一种情况 问题描述 环境&#xff1a;IDEA 2021.1 windows11 mysql8.0 已知条件&#xff1a;1.已正常安装数据库2.无法通过CMD输入mysql -u root -p 密码进入数据库3.无法通过Navicat进入4…

2023-07-29:给你一个由数字组成的字符串 s,返回 s 中独特子字符串数量。 其中的每一个数字出现的频率都相同。

2023-07-29&#xff1a;给你一个由数字组成的字符串 s&#xff0c;返回 s 中独特子字符串数量。 其中的每一个数字出现的频率都相同。 答案2023-07-29&#xff1a; 大体步骤如下&#xff1a; 1.初始化变量base为固定值1000000007&#xff0c;用于计算哈希码。 2.创建一个空…

InnoDB引擎底层逻辑讲解——架构之内存架构

1.InnoDB引擎架构 下图为InnoDB架构图&#xff0c;左侧为内存结构&#xff0c;右侧为磁盘结构。 2.InnoDB内存架构讲解 2.1 Buffer Pool缓冲池 2.2 Change Buffer更改缓冲区 2.3 Adaptive Hash Index自适应hash索引 查看自适应hash索引是否开启&#xff1a; show variable…

qt截图软件中画箭头代码原理

截图工具中&#xff0c;需要画一个指向箭头&#xff0c; 该箭头的形状解析示意图如下所示&#xff0c; 对应的qt代码如下&#xff1a; // 画出一个箭头线&#xff0c;主要是算出这几个点。 // 这个箭头形状是这样的&#xff0c;胖嘟嘟的那种&#xff0c;但是出发点是一个细的 Q…

机器学习深度学习——权重衰减

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——模型选择、欠拟合和过拟合 &#x1f4da;订阅专栏&#xff1a;机器学习&&深度学习 希望文章对你…

教雅川学缠论04-笔

笔由3部分组成&#xff1a; 顶分型K线底分型&#xff0c;或者 底分型K线顶分型 注意&#xff1a;笔加一起至少7根K线&#xff0c;因为一个底分型至少3根&#xff0c;K先至少1个&#xff0c;顶分型至少3根 下图中红色线段就是一个标准的笔&#xff0c;它始于一个底分型&#xff…

❤️创意网页:创建更炫酷的动态网页——彩色数字(1到9)粒子动画

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…

基于WSL2、Ubuntu和VS Code的CUDA平台运行C语言程序

一、CUDA程序执行方法 执行步骤为&#xff1a; 安装Visual Studio Code。在Visual Studio Code中安装插件WSL与电脑的WSL2进行连接。点击左下角&#xff0c;然后再选择连接到WSL。 在WSL中创建以 .cu 为后缀的文件。 rootDESKTOP-HR6VO5J:~# mkdir CUDA /…

VMware Linux 可视化增加磁盘

1、VMware 增加磁盘 2、disks挂载磁盘 此处我挂载的是20G磁盘&#xff0c;截图只是用5G的做过程演示例子。 3、验证挂载磁盘

Chrome 浏览器+Postman还能这样做接口测试 ?

如果把测试简单分为两类&#xff0c;那么就是客户端测试和服务端测试。客户端的测试包括UI测试&#xff0c;兼容性测试等&#xff0c;服务端测试包括接口测试。接口测试检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;它绕过了客户端&#xff0c;直接对服务端进行测…

UE5 C++ SplineMesh蓝图函数库实现(小白笔记)

UE5 C++ SplineMesh的蓝图函数库实现方法 UAAABlueprintFunctionLibrary UAAABlueprintFunctionLibrary.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h" #include "Components/Spl…

【Java开发】 Mybatis-Flex 01:快速入门

Mybatis 作为头部的 ORM 框架&#xff0c;他的增强工具可谓层出不穷&#xff0c;比如出名的 Mybatis-Plus 和 阿里云开源的 Fluent-MyBatis&#xff0c;如今出了一款 Mybatis-Flex &#xff0c;相比前两款功能更为强大、性能更为强悍&#xff0c;不妨来了解一下。 目录 1 Myba…

CAD Voronoi3D V1.0.1 版本更新说明

更新说明 CAD Voronoi3D V1.0.1版本对泰森多边形晶格进行进一步的优化。 采用新算法大幅度减少形体边界出现小晶格的可能性&#xff0c;使区块更均匀&#xff1a; 优化曲边边界晶格曲率问题&#xff0c;消除曲边形体晶格边界曲率过大现象&#xff1a; 优化生成算法&#xff…