Download presentation
Presentation is loading. Please wait.
1
嵌入式系统及应用
2
第八章 I/O管理
3
主要内容 I/O管理概述 一种I/O系统实现方法 体系结构 实现考虑
4
I/O管理概述 在通用操作系统中,I/O管理采用层次结构的思想(如四个层次的结构:中断处理程序,设备驱动程序,与设备无关的操作系统软件,用户层软件): 较低层的软件要使较高层的软件独立于硬件的特性, 较高层软件则要向用户提供一个友好、清晰、规范的接口。
5
I/O管理概述 在I/O管理的层次结构中,主要通过设备独立的I/O系统和设备驱动程序来共同完成I/O操作。
6
I/O管理概述 在一些实时内核的I/O系统中,用户I/O请求在到达设备驱动程序之前,通常都只进行非常少量的处理。
7
I/O管理概述 为满足标准设备处理的需要,I/O系统通常也提供一些高级的例程库,便于实现设备的标准通信协议。
在需要时,方便地实现非标准的设备驱动程序,以满足实时性或是其他的特殊需要。
8
一种I/O系统实现方法 在不同CPU和I/O设备之间的可移植性就成为嵌入式操作系统设计时需要重点考虑的内容
可移植性有助于增强操作系统和应用的重用,以保护应用投资 如何有助于提高编写驱动程序的便利性,通常也是应用开发人员非常关注的特性 降低驱动程序的开发难度,则能有效提高系统的开发效率
9
体系结构 为了有效组织和管理各种不同的设备,可以采用分层的思想,把I/O系统从上到下分为四层,分别为API、设备管理、驱动逻辑和硬件抽象。
设备管理层 中断驱动程序 串口驱动程序 键盘驱动程序 …… 驱动逻辑层 …… 串口卡A 硬件抽象 串口卡B 硬件抽象 …… 硬件抽象层 串口1 串口2 串口3 串口4 串口1 串口2 设备
10
体系结构 硬件抽象层 是硬件功能模块的集合,是对硬设备功能的第一层抽象,实现基本的IO操作。
所关心的是如何实现硬件功能的软件接口,而不是设备的管理逻辑。 每个硬件可能有多个端口(设备),对应的硬件抽象层是对这些端口(设备)操作的基本抽象,为驱动程序管理这些设备提供接口。上层驱动程序在不需要了解具体设备硬件信息的情况下,就可以操作这些设备。
11
体系结构 驱动逻辑层 存放系统中的所有驱动程序 实现设备的管理逻辑 通过硬件抽象层来管理设备
每个驱动程序管理一类设备,例如所有串口都由串口驱动程序来管理,所有中断控制器都由中断控制器驱动程序管理。
12
体系结构 设备管理层 API层 管理系统中的设备,并向上提高统一的接口。 设备管理层不直接操作设备,它只能通过驱动程序来间接操作设备。
用于对设备管理层提供的驱动结构进行进一步的包装,以方便应用程序使用。
13
体系结构 采用这种体系结构的好处: 便于硬设备驱动的编写 便于移植
提供硬件的多种使用模式:应用程序(包括用户程序、操作系统及其组件等程序)可以根据实际需要从驱动程序的不同层次直接调用 ,可以满足实时性或其它一些应用设计方面的具体考虑。
14
应用程序(用户程序、操作系统及其组件等)
体系结构 提供硬件的多种使用模式 应用程序(用户程序、操作系统及其组件等) API 设备管理 驱动程序 硬件抽象
15
实现考虑 设备管理 驱动逻辑 硬件抽象 工作过程
16
设备管理 为了实现设备管理,可以提供三张表: 驱动程序地址表 设备名表 文件表
17
设备管理 驱动程序地址表:管理系统中的驱动程序,表项为各个驱动程序的功能函数 驱动程序地址表 initialize open close
read write Control …… xxx_initialize xxx_open xxx_close xxx_read xxx_write xxx_control 驱动程序地址表
18
设备管理 驱动程序地址表 typedef T_DM_StatusCode ( *T_DM_DeviceDriverEntry )(T_WORD, T_WORD, T_VOID *); typedef struct { T_DM_DeviceDriverEntry initialization; //初始化函数指针 T_DM_DeviceDriverEntry open; //打开设备函数指针 T_DM_DeviceDriverEntry close; //关闭设备函数指针 T_DM_DeviceDriverEntry read; //读设备函数指针 T_DM_DeviceDriverEntry write; //写设备函数指针 T_DM_DeviceDriverEntry control; //控制设备函数指针 } T_DM_DriverAddressTable; 驱动程序地址表的数据结构
19
设备管理 设备名表:管理系统中所有设备,通过设备名来区分各设备
主设备号是驱动程序在驱动地址表中的位置,次设备号用来在驱动程序内部区分不同的设备 Name major minor name1 major1 minor1 name2 name3 设备名表
20
设备管理 设备名表 设备名表的数据结构 typedef struct { T_BYTE *device_name; //设备名
T_WORD device_name_length; //设备名长度 T_WORD major; //主设备号 T_WORD minor; //次设备号 } T_DM_DriverName; 设备名表的数据结构
21
设备管理 文件表:用于记录当前打开的设备 文件表 fd driver Size offset flags sem data1 1 …… 2
3 4 文件表
22
设备管理 文件表 typedef long off_t; typedef struct {
T_DM_DriverName *driver; //用于保存设备在设备表中的地址 off_t size; //文件长度 off_t offset; //当前偏移 T_UWORD flags; //文件标志 T_UWORD sem; //文件信号句柄 T_VOID *data1; //文件私有数据 } T_DM_FileDescriptor; 文件表的数据结构
23
驱动逻辑 驱动逻辑层实现系统中所有驱动程序。 每个驱动程序管理一类设备,为了实现设备管理,在每个驱动程序中维护一张设备信息表。 设备信息表
pNext Minor halDevDataTable devInterfaceTable dllDevDataTable pNext Minor halDevDataTable devInterfaceTable dllDevDataTable …… pNext Minor halDevDataTable devInterfaceTable dllDevDataTable 设备信息表
24
驱动逻辑 下一个设备项 次设备号,表示设备在其所属驱动中的编号
pNext Minor halDevDataTable devInterfaceTable dllDevDataTable 下一个设备项 次设备号,表示设备在其所属驱动中的编号 用于硬件抽象的设备数据表,保存硬件需要的信息,该表的内容由硬件抽象层负责解析,驱动程序不关心表的具体内容 设备接口函数表,也即硬件功能抽象表,表中函数由设备对应的硬件抽象提供,驱动程序通过该表中的函数,实现对设备的访问 驱动设备数据表,保存驱动程序所需的信息,由驱动程序负责维护
25
驱动逻辑 typedef struct { T_DLL_UartDevInfo *pNext; //指向下一个设备信息表项
int minor; //次设备号 T_VOID *pHalDevDataTable; //指向设备数据表 T_DLL_UART_DEV_INTERFACE *pDevInterface; //指向设备接口函数表 T_DLL_UART_DEV_DATA *pDllDevDataTable; //指向驱动设备数据表 } T_DLL_UartDevInfo; 基本串口驱动程序uart的设备信息表结构
26
驱动逻辑 typedef struct { /*第一部分:需要用户配置的信息*/ T_UBYTE enable; // 通道使能
T_UBYTE parityMode; // 奇偶校验模式 T_UBYTE bitsPerChar; // 数据位数 T_UWORD baudrate; // 波特率 T_UBYTE numOfStopBits; // 停止位 T_UBYTE rxEnable; // 是否允许接收 T_UBYTE mode; // 访问模式(Polling、interrupt) T_UBYTE flowCtrl; // 流控 T_UBYTE remainder; // 流控 remainder T_UWORD inBufSizeCfg; // 输入缓存大小 T_UWORD outBufSizeCfg; // 输出缓存大小 T_UWORD inBufWakeSizeCfg; 基本串口驱动程序的驱动设备数据表结构定义
27
驱动逻辑 基本串口驱动程序的驱动设备数据表结构定义(续) /*第二部分:不需要用户配置的信息*/
T_UBYTE* InBuf; //point to the real buffer T_UWORD InBufSize; //输入缓存大小 T_UWORD InBufHead; //queue head T_UWORD InBufTail; //queue tail T_UWORD InBufDropped; //Statistics T_UWORD InBufWaitMutex; //输入等待信号量id T_UWORD InBufWakeCnt; //等待接收的字符数 T_UWORD InBufWaitTicks; //等待输入的等候时间,0为一直等待 T_UBYTE* OutBuf; //输出缓存指针 T_UWORD OutBufSize; //输出缓存大小 T_UWORD OutBufHead; //queue head T_UWORD OutBufTail; //queue tail T_WORD OutBufWaitMutex; //输出等待信号量i T_UWORD OutBufWaitTicks; //等待输出缓存释放的等候时间,0为一直等待 //输出缓存的状态: OBS_IDLE:输出缓存为空; OBS_BUSY:输出缓存还有数据 T_VOLATILE enum {OBS_IDLE, OBS_BUSY} outBufState; ……}T_DLL_UART_DEV_DATA; 基本串口驱动程序的驱动设备数据表结构定义(续)
28
驱动逻辑 串口驱动程序定义的设备函数接口表 ypedef struct { //查找设备
T_BOOL ( *Find)( T_VOID * pUartDevDataTable ); //获取硬件抽象层管理该设备需要的资源 T_BOOL ( *GetResource)( T_VOID * pUartDevDataTable ); //释放硬件抽象层管理该设备需要的资源 T_BOOL ( *ReleaseResource)( T_VOID * pUartDevDataTable ); //启动设备 T_BOOL ( *Start)( T_VOID * pUartDevDataTable ); //停止设备 T_BOOL ( *Stop)( T_VOID * pUartDevDataTable ); //检查设备是否准备好读取 T_BOOL ( *ReadReady)( T_VOID * pUartDevDataTable ); //检查设备是否准备好写入 T_BOOL ( *WriteReady)( T_VOID * pUartDevDataTable ); //读取字符 T_BOOL ( *ReadChar)( T_VOID * pUartDevDataTable ,T_BYTE *RcvChar); //写入字符 T_BOOL ( *WriteChar)( T_VOID * pUartDevDataTable ,T_BYTE SendChar); //使能设备的中断 T_BOOL ( *EnableMainChipInt)( T_VOID * pUartDevDataTable ); //禁止设备的中断 T_BOOL ( *DisableMainChipInt)( T_VOID * pUartDevDataTable ); 串口驱动程序定义的设备函数接口表
29
驱动逻辑 串口驱动程序定义的设备函数接口表(续) //使能接收中断
T_BOOL ( *EnableRcvInt)( T_VOID * pUartDevDataTable ); //禁止接收中断 T_BOOL ( *DisableRcvInt)( T_VOID * pUartDevDataTable ); //使能发送中断 T_BOOL ( *EnableSendInt)( T_VOID * pUartDevDataTable ); //禁止发送中断 T_BOOL ( *DisableSendInt)( T_VOID * pUartDevDataTable ); //获取中断类型 T_UWORD ( *GetIntType)( T_VOID * pUartDevDataTable, T_UWORD vector,T_UWORD * IntStatusReg ); //处理其它中断类型 T_BOOL ( *HandleOtherIntType)( T_VOID * pUartDevDataTable, T_UWORD Intinfo ); //配置串口通讯的数据位数 T_BOOL ( *Config_data_bit_len)( T_VOID * pUartDevDataTable ,T_UWORD DatalenCfg ); //配置串口通讯的停止位数 T_BOOL ( *Config_stop_bit_len)( T_VOID * pUartDevDataTable ,T_UWORD StopBitlenCfg ); //配置串口通讯的的奇偶校验位 T_BOOL ( *Config_parity_sel)( T_VOID * pUartDevDataTable ,T_UWORD ParitySelCfg ); //配置串口通讯的的波特率 T_BOOL ( *Config_baud_rate)( T_VOID * pUartDevDataTable,T_UWORD BaudrateCfg ); }T_DLL_UART_DEV_INTERFACE; 串口驱动程序定义的设备函数接口表(续)
30
驱动逻辑 typedef struct { // 设备公共信息定义 T_BSP_DEV_PUB_DATA pub;
// 第二部分:HAL私有的,需要用户配置的信息。 T_UWORD baseAddr; /// 设备基地址 //第三部分:HAL私有的,不需要用户配置的信息 }T_HAL_I8250_DEV_DATA; i8250的设备数据表结构
31
硬件抽象 每个设备的硬件抽象分两部分: 硬件抽象部分,实现对硬件的抽象。该部分写好之后,不会随应用而改变;
初始化部分,对设备进行初始化,实现设备注册。
32
工作过程 I/O系统的初始化 设备打开 设备读 设备写 设备控制 设备关闭 设备管理初始化 驱动逻辑初始化 硬件抽象初始化
完成设备管理相关信息的初始化,如创建驱动程序地址表、设备名表、文件记录表等 设备管理初始化 I/O系统的初始化 驱动逻辑初始化 实现系统中各驱动程序的注册,即把系统中各驱动程序注册到设备管理中 硬件抽象初始化 主要完成设备注册 设备打开 设备读 设备写 设备控制 设备关闭
33
工作过程 驱动程序注册 Major=fnDM_DriverInstall(xxx_initialize,xxx_open,xxx_close,xxx_read,xxx_write,xxx_control) (5) I/O系统返回记录在驱动程序地址表中的索引,即主设备号(major=2) (1)驱动程序安装函数为六个基本I/O函数指定地址。 (2)I/O系统在驱动程序地址表中定位下一个空闲的记录。 (4) I/O系统立即调用新驱动程序的xxx_initialize()函数,初始化驱动程序,完成设备的注册。 驱动程序地址表 initialize open close read write control xxx_initialize xxx_open xxx_close xxx_read xxx_write xxx_control 1 2 3 4 (3)I/O系统在驱动程序地址表中填入驱动程序的六个函数地址。
34
工作过程 设备注册 Status=fnDM_NameRegister(“name”,major,minor1);
I/O系统注册设备到设备名表中,注册的内容包括设备名、major和 minor 设备名表 name1 major minor1 name2 minor2 驱动程序地址表 initialize open close read write control xxx_initialize xxx_open xxx_close xxx_read xxx_write xxx_control 1 2 3 4
35
工作过程 打开设备
36
工作过程 关闭设备 系统调用close( )关闭一个不再使用的设备,关闭一个设备时,I/O系统的内部运作过程和写一个设备大致相同,不同的是I/O系统根据设备名表中的主设备号在驱动程序地址表中定位并调用驱动程序的xxx_close( )函数,然后释放文件表中的记录,返回。在此之后对该文件描述符的任何引用都将返回错误。但是随后的open( )系统调用将仍然返回该文件描述符。
37
工作过程 写设备 读设备、控制设备操作与写设备操作流程类似
38
谢谢!
Similar presentations