• RTT学习笔记9-IO设备模型


    I/O 设备模型框架

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

    分成三层,从上到下分别是

    1. I/O 设备管理层
    2. 设备驱动框架层
    3. 设备驱动层。

    I/O 设备管理层实现了对设备驱动程序的封装。

    设备驱动框架层是对同类硬件设备驱动的抽象,将不同厂家的同类硬件设备驱动中相同的部分抽取出来,将不同部分留出接口,由驱动程序实现。

    设备驱动层是一组驱使硬件设备工作的程序,实现访问硬件设备的功能。

    不经过驱动框架层

    在这里插入图片描述

    经过驱动框架层

    下图一看门狗为例在这里插入图片描述

    I/O 设备模型

    在这里插入图片描述

    struct rt_device
    {
        struct rt_object          parent;        /* 内核对象基类 */
        enum rt_device_class_type type;          /* 设备类型 */
        rt_uint16_t               flag;          /* 设备参数 */
        rt_uint16_t               open_flag;     /* 设备打开标志 */
        rt_uint8_t                ref_count;     /* 设备被引用次数 */
        rt_uint8_t                device_id;     /* 设备 ID,0 - 255 */
    
        /* 数据收发回调函数 */
        rt_err_t (*rx_indicate)(rt_device_t dev, rt_size_t size);
        rt_err_t (*tx_complete)(rt_device_t dev, void *buffer);
    
        const struct rt_device_ops *ops;    /* 设备操作方法 */
    
        /* 设备的私有数据 */
        void *user_data;
    };
    typedef struct rt_device *rt_device_t;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    I/O 设备类型

    RT_Device_Class_Char             /* 字符设备       */
    RT_Device_Class_Block            /* 块设备         */
    RT_Device_Class_NetIf            /* 网络接口设备    */
    RT_Device_Class_MTD              /* 内存设备       */
    RT_Device_Class_RTC              /* RTC 设备        */
    RT_Device_Class_Sound            /* 声音设备        */
    RT_Device_Class_Graphic          /* 图形设备        */
    RT_Device_Class_I2CBUS           /* I2C 总线设备     */
    RT_Device_Class_USBDevice        /* USB device 设备  */
    RT_Device_Class_USBHost          /* USB host 设备   */
    RT_Device_Class_SPIBUS           /* SPI 总线设备     */
    RT_Device_Class_SPIDevice        /* SPI 设备        */
    RT_Device_Class_SDIO             /* SDIO 设备       */
    RT_Device_Class_Miscellaneous    /* 杂类设备        */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.设备框架涉及函数

    2.1创建和注册 I/O 设备

    rt_device_t rt_device_create(int type, int attach_size);
    
    • 1

    在这里插入图片描述
    一个新的设备驱动程序需要试下的框架函数

    struct rt_device_ops
    {
        /* 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);
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述

    2.2销毁一个设备

    void rt_device_destroy(rt_device_t device);
    
    • 1

    2.3 注册到 I/O 设备

    rt_err_t rt_device_register(rt_device_t dev, const char* name, rt_uint8_t flags);
    
    • 1

    flags可选参数

    #define RT_DEVICE_FLAG_RDONLY       0x001 /* 只读 */
    #define RT_DEVICE_FLAG_WRONLY       0x002 /* 只写  */
    #define RT_DEVICE_FLAG_RDWR         0x003 /* 读写  */
    #define RT_DEVICE_FLAG_REMOVABLE    0x004 /* 可移除  */
    #define RT_DEVICE_FLAG_STANDALONE   0x008 /* 独立   */
    #define RT_DEVICE_FLAG_SUSPENDED    0x020 /* 挂起  */
    #define RT_DEVICE_FLAG_STREAM       0x040 /* 流模式  */
    #define RT_DEVICE_FLAG_INT_RX       0x100 /* 中断接收 */
    #define RT_DEVICE_FLAG_DMA_RX       0x200 /* DMA 接收 */
    #define RT_DEVICE_FLAG_INT_TX       0x400 /* 中断发送 */
    #define RT_DEVICE_FLAG_DMA_TX       0x800 /* DMA 发送 */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.4 注销 I/O 设备

    rt_err_t rt_device_unregister(rt_device_t dev);
    
    • 1

    3. I/O设备的访问

    I/O 设备管理接口与 I/O 设备的操作方法的映射关系
    在这里插入图片描述

    3.1查找设备

    rt_device_t rt_device_find(const char* name);
    
    • 1

    在这里插入图片描述

    3.2 初始化设备

    获得设备句柄后,应用程序可使用如下函数对设备进行初始化操作:

    rt_err_t rt_device_init(rt_device_t dev);
    
    • 1

    在这里插入图片描述

    3.3 打开设备

    通过设备句柄,应用程序可以打开和关闭设备,打开设备时,会检测设备是否已经初始化,没有初始化则会默认调用初始化接口初始化设备。通过如下函数打开设备:

    rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
    
    • 1

    flag可选参数

    #define RT_DEVICE_OFLAG_CLOSE 0x000   /* 设备已经关闭(内部使用)*/
    #define RT_DEVICE_OFLAG_RDONLY 0x001  /* 以只读方式打开设备 */
    #define RT_DEVICE_OFLAG_WRONLY 0x002  /* 以只写方式打开设备 */
    #define RT_DEVICE_OFLAG_RDWR 0x003    /* 以读写方式打开设备 */
    #define RT_DEVICE_OFLAG_OPEN 0x008    /* 设备已经打开(内部使用)*/
    #define RT_DEVICE_FLAG_STREAM 0x040   /* 设备以流模式打开 */
    #define RT_DEVICE_FLAG_INT_RX 0x100   /* 设备以中断接收模式打开 */
    #define RT_DEVICE_FLAG_DMA_RX 0x200   /* 设备以 DMA 接收模式打开 */
    #define RT_DEVICE_FLAG_INT_TX 0x400   /* 设备以中断发送模式打开 */
    #define RT_DEVICE_FLAG_DMA_TX 0x800   /* 设备以 DMA 发送模式打开 */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.4关闭设备

    rt_err_t rt_device_close(rt_device_t dev);
    
    • 1

    3.5 控制设备

    rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
    
    • 1

    arg参数可选

    #define RT_DEVICE_CTRL_RESUME           0x01   /* 恢复设备 */
    #define RT_DEVICE_CTRL_SUSPEND          0x02   /* 挂起设备 */
    #define RT_DEVICE_CTRL_CONFIG           0x03   /* 配置设备 */
    #define RT_DEVICE_CTRL_SET_INT          0x10   /* 设置中断 */
    #define RT_DEVICE_CTRL_CLR_INT          0x11   /* 清中断 */
    #define RT_DEVICE_CTRL_GET_INT          0x12   /* 获取中断状态 */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.6 读设备

    rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos,void* buffer, rt_size_t size);
    
    • 1

    在这里插入图片描述

    3.6 写设备

    rt_size_t rt_device_write(rt_device_t dev, rt_off_t pos,const void* buffer, rt_size_t size);
    
    • 1

    在这里插入图片描述

    3.7数据收发回调

    rt_err_t rt_device_set_rx_indicate(rt_device_t dev, rt_err_t (*rx_ind)(rt_device_t dev,rt_size_t size));
    
    rt_err_t rt_device_set_tx_complete(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev,void *buffer));
    
    • 1
    • 2
    • 3

    3.8 设备访问示例

    #include 
    #include 
    
    #define IWDG_DEVICE_NAME    "iwg"
    
    static rt_device_t wdg_dev;
    
    static void idle_hook(void)
    {
        /* 在空闲线程的回调函数里喂狗 */
        rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_KEEPALIVE, NULL);
        rt_kprintf("feed the dog!\n ");
    }
    
    int main(void)
    {
        rt_err_t res = RT_EOK;
        rt_uint32_t timeout = 1000;    /* 溢出时间 */
    
        /* 根据设备名称查找看门狗设备,获取设备句柄 */
        wdg_dev = rt_device_find(IWDG_DEVICE_NAME);
        if (!wdg_dev)
        {
            rt_kprintf("find %s failed!\n", IWDG_DEVICE_NAME);
            return RT_ERROR;
        }
        /* 初始化设备 */
        res = rt_device_init(wdg_dev);
        if (res != RT_EOK)
        {
            rt_kprintf("initialize %s failed!\n", IWDG_DEVICE_NAME);
            return res;
        }
        /* 设置看门狗溢出时间 */
        res = rt_device_control(wdg_dev, RT_DEVICE_CTRL_WDT_SET_TIMEOUT, &timeout);
        if (res != RT_EOK)
        {
            rt_kprintf("set %s timeout failed!\n", IWDG_DEVICE_NAME);
            return res;
        }
        /* 设置空闲线程回调函数 */
        rt_thread_idle_sethook(idle_hook);
    
        return res;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
  • 相关阅读:
    面向对象开发技术设计模式的选择
    代码随想录训练营day57
    [HarekazeCTF2019]Avatar Uploader 1
    Spring Cloud Gateway中session共享
    Linux 软链接 和 硬链接
    前端到底有多卷?可以转行吗?
    php计算机毕业设计基于thinkphp框架的特色旅游网站vue
    Redis Cluster 为什么不支持传统的事务模型
    2022年科协第二次硬件培训总结
    php危险函数及rce漏洞
  • 原文地址:https://blog.csdn.net/u010261063/article/details/126193706