UCOSII硬件抽象层驱动框架设计_第1页
UCOSII硬件抽象层驱动框架设计_第2页
UCOSII硬件抽象层驱动框架设计_第3页
UCOSII硬件抽象层驱动框架设计_第4页
UCOSII硬件抽象层驱动框架设计_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、这是我帮我同学整理的毕业论文的材料。内容就是我所写的UC/OS-II的硬件抽象层。大家可以当做代码导读来使用。因为照顾到我同学对底层硬件不感兴趣和时间的关系所以只介始上层的实现思想。墨鱼2008.06.15二.uC/0S-II下通用驱动框架的基本模型为了给上层应用提供统一、一致的系统设备调用接口,需耍对上层应用程序对系统设备的访问操作进行抽象,任这方面,Unix系统和Linux系统做得比较成功。本文借鉴了Unix及Linux系统的成功经验,同时考虑到朕入式操作系统的特殊性,为UC/0S-II建立了如图1所示的通用驱动框架模型。在图1所示的通用驱动框架模型中,共包括三个层次:层访问抽象接口层:一

2、般的抽象层设计会宜接在这一层提供5个访问接口API:DeviceOpenDevGetchDevPutchDevControLDeviceClose,分别用丁打开设备、读设备、写设备、设备控制和关闭设备。而在这个设计里而更改了这种定义模式提供两个公用的接口DeviceOpen和DeviceClose,同时为不同的外设分别提供特定的抽象接口,在移植的时候利用这些抽象接口的不变性保证应用程序的可移植能力。这样做的优点更适合于有单片机开发经验的工程人员直接调用。例如UART提供的抽象接口有:v_MiniPrintf最小格式化字符串函数;UARTSet串口参数设置。暂时没实再忘式化字符输入。IIC提供的

3、抽象接口有:I2CMasterSendIIC主模式发送;I2CMasterReceiveIIC主模式接收;I2CSlaverReceiveIIC从模式接收。其它的还有SPI,外部中断管理。在里只简单介绍下UART和IIC。上层应用程序通用驱动框架uC/0S-II硬件设备1驱动模块硬件设备2驱动模块硬件设备N驱动模块硬件设备N(图1通用驱动框架模型)(2)设备管理核心数据结构层:这是通用驱动框架的核心,主耍用每个设备分配一个设备控制块,通过链表形式进行管理,该链表定义为设备控制块链表DEV_CONTROL_BLOCK*HvlConList。在这一层,为系统中的每个硬件设备分配唯一的设备ID,上层

4、应用程序通过将设备ID作为参数传递给DeviceOpen函数实现对相应设备的核心管理数据结构的定位搜索,通过搜索,DeviceOpen函数找到相应设备控制块,申请设备的使用权限,获得相应硬件设备的操作句柄,该句柄指向具体的外设底层操作函数列表,返回该设备句柄;再通过上层抽象接口层提供的接口函数对设备进行访问。(3)硬件设备驱动模块层:这一层是硬件设备驱动模块功能的实现层,对各个硬件设备的驱动在相应的硬件设备驱动模块中完成。各个硬件设备驱动模块,原则上需耍实现如下儿个函数:DevGetch、DevPutch、DevControl,分别完成相应设备的读、写、控制,当然,可以根据具体设备的特性,只实

5、现3个驱动函数的其中一部分,例如,如果某设备不支持写操作,那么就不用实现DevPutch函数。下而,对该模型的工作原理进行简单描述:首先,在上层应用程序可以访问硬件设备之前,需耍首先打开欲操作的设备,这可以通过调用“上层抽象接口层”的DeviceOpen函数实现。上层应用程序将欲打开的设备的设备ID传递给DeviceOpen函数,DeviceOpen函数通过该设备ID从设备控制块链表中得具体的设备控制块,进而得到相应设备的操作句柄,并返该句柄。得到该句柄后就可以调用上层提供的抽象接口(设备句柄为所有抽象接口的参数之一)完成特定的设备操作。完成设备的操作后仍然使用该句柄关闭设备,从而释放设备资源

6、,交由其它任务操作。现在以UART的v_MiniPrintf为例实现代码如下:DEV_FUN*DeviceO=NULL:定义一个设备句柄uintSData=100;打开串口设备,设备打开后串口默认设置为9600,8位模式,1位停止位,无奇偶较验DeviceO=DeviceOpen(UARTO_ID,&err);调用格式化字符输出,向UARTO输出经格式化后的字符串v_MiniPrintf(DeviceO,uartOoutput:%sn,Data);如上所示调用设备成功打)FUARTO后打传递给v_MiniPrintf函数的第一个参数为调用DeviceOpen返回的句柄,该句柄I勺定义形式如下:

7、typedefstruetdevice_functionDEV_FUN;structdevice_function从设备操作列表中继承三个设备函数INT8U(*DevPutch)(INT8U*str,INT16Ulength);设备字节写函数INT8U(*DevGetch)(INT8U*str,INT16Ulength);设备字节读函数INT8U(*DevControl)(void*param);设备控制函数v_MiniPrintf函数对字符串进行格式化处理后使用该句柄成员函DevPutch输出字符串到具体的外设接口上。v_MiniPrintf代码如下:函数名称:v_MiniPrintf函数功

8、能:最小格式化输出函数输入:Dev由调用FDevOpen函数时返回来的设备文件其于参数列表和printif函数一样,只支持10,16进制,字符,字符串这四种格式化输出输出:void作者:中中中孕中孕中孕中中中中孕中孕中空中中中中中中中中孕中孕中中中中中中空中孕中中中中中中中中孕中孕中中中來中中中/voidv_MmiPrintf(DEV_FUN*Dev,char*fint,.)vaistap,int8strval,int8nval,char*p,char*PointChar,staticint8i,if(Dev=NULL)return,va_start(ap,frnt),for(p=frnt,*

9、p,p+)if(*p!=%*)Dev-DevPutch(uint8*)p,1),continue,PPswitch(*p)cased1:nval=va_aig(ap,int),1=0,dostivali=nval%10,nval/=10,1+,vzhile(nval0),break,casex1:nval=va_arg(ap,int),1=0,dostivali=nval%16,nval/=16,1+;vzhile(nval0),break,casec1:i=-l,nval=vaargCapjnt),Dev-DevPutch(uint8*)&nval,1),break,case,s,:i=-l

10、;PointChar=(char*)va_arg(ap,int),nval=*PointChar,while(nval)nval=*PointChar,if(nval!=O)Dev-DevPutch(PointChar,1),PointChaiH-4-,break,default:break,for(,1=0,i-)nval=stivali+4&Dev-DevPutch(uintS*)&nva1,1),va_end(ap),3.2设备管理核心数据结构,设备控制块的设计实现如上文所述:通用驱动框架以“设备控制块数据链表”为核心,它在模型中起着承上启下的作用。设备管理核心数据结构包括两个结构:设备

11、控制块和设备操作函函数列表。1、定义设备控制块属性:详细定义请查看源码HALh、HAL.c:HALh中定义如下:#ifhdef_HAL_H_#define_HAL_H_#includeconfig.h11/编译参数是否允许卸载设备,目前还没测试过该功能所以不编译#defineEN_DEV_UNINSTALL0用定义所有设备的设备ID,typedefenumEMPTYJD=0,UARTOJD,UART1JD,I2C0_ID,I2C1_ID,SPI0_ID,SPI1_ID,MAX_DEV_MUN编译参数允许创建设备数DEV_ID.typedefenumBASIC_SEM,MUTEX_SEM,ERR

12、_SEMSEM_TYPE;typedefstructdevice_contiol_blockDEV_CONTROL_BLOCK,typedefstructdevice_operations_listDEVOPERATIONS,structdevice_operations_list设备控制列表INT8U(*DevPutch)(INT8U*strJNT16Ulength),设备字节写函数INT8U(*DevGetch)(INT8U*sti;INT16Ulength),设备字节读函数INT8U(*DevContiol)(void*param),/设备控制函数/设备安装与设备控制函数的差别在r设备安

13、装要传递向最相关信息OS_EVENT*(*DevInstall)(void*param,INT8U*err),INT8U(*DevUnmstall)(void);设备拆除DEV_CONTROL_BLOCK*parent,typedefstmctdevice_functionDEV_FUN,stnictdevice_function从设备操作列表中继承三个设备函数_INT8U(*DevPutch)(INT8U*str,INT16Ulength),设备字节写函数INT8U(*DevGetch)(INT8U*sti;INT16Ulength);设备字节读函数INT8U(*DevContiol)(vo

14、id*param),设备控制函数,typedefstmctdevice_intemjpt_regDEV_INTERRUPT_REG,stiuctdevice_inteiTupt_reg设备向鼠中断寄存器地址列表volatileunsignedlong*VicVectCnt,volatileunsignedlong*VicVectAddr,stmctdevice_contiol_blockDEVIDdeviceid,INT8Udevice_type,SEM_TYPEsem_type,INT8Uwait_out_time,设备控制块设备ID设备类型保留用丁设备互斥的信号类型打开设备等待超时时间设备

15、共享卜一个设备控制块指针设备操作句柄#if(EN_DEV_UNINSTALL=1)VIC_REGISTER_GROUPvic_param,#endifOS_EVENT*devjile,DEV_CONTROL_BLOCK*next_block,DEV_OPERATIONS*dev_op_handle,;uintSTargeDeviceInit(void),typedefenumHVLNOERR=0,HVLNOCONTROLBLOCK=1,HVLINSTALLFAIL=2,HVL_CONTROL_LIST_FULL=3,设备一一一HVLNOFINDDEV=4,HVLWMTDEVTIMEOUT=5,

16、HVLCLOSEDEVFAIL=6,HVLUNINSTALLFAIL=7,HVL_PARAM_ERR=8HVL_ERR_CODE,硬件抽彖层错谋类型没有错误/没有设备控制块可用设备安装失败有效控制块链表空,即找不到任何已安装的没有找有指定设设备打开设备超时关闭设备失败uint8DeviceClose(DEV_FUN*dev),DEVFUN*DeviceOpen(DEV_IDdev_id,HVL_ERR_CODE*err),uint8CreatDevic(DEV_IDdev_id,void*creatparam,DEV_OPERATIONS*creatjist),uintSDeviceUnins

17、Ull(pEV_HJN*dev),#endif其中设备控制块属性包括:设备识别ID(标志人设备类型、设备是否可用(所有设备假定唯一性即所有设备都不允许在同一时刻被多个任务使用)使用一个信号鼠做为设备互斥管理、信号量类型(使用一个uint8类型表示所使用信号量类型、目前有数字信号斎和互斥型信号鼠两种),中断向量控制寄存器参数列表,卜一个设备控制块指针(利用该指针每创建一个设备的时候将创建的设备放入设备管理队列中)、设备操作句柄;2、操作设备的方法包括:(该部分的代码实现在HAL.c中)A、设备控制块空闲列表初始化函数:利用静态数组创建一个空闲的设备控制块链表。其实现如卜所示:DEV_CONTRO

18、L_BLOCK*HvlFreeList=NULL,/定义一个设备控制块空闲链表指针一一使用数组预审请设备控制块空间uint8DevControlsizeof(DEV_CONTROL_BLOCK)MAX_DEV_MUN=0,/*设备控制块空闲链表初始化*/DEV_COOTROL_BLOCK*HvlFreeListInti(void)DEV_CONTROL_BLOCK*FreeList=(DEV_CONTROL_BLOCK*)DevControl,DEV_CONTROL_BLOCK*pTemp=(DEV_CONTROL_BLOCK*)DevContiol;uintS*pMemSet=(uint8水

19、)DevContiol,uint32for(i=0,isizeof(DEV_CONTROL_BLOCK)*MAX_DEV_MUN,i+)pMemSeti=0,for(i=0,1next_block=NULL,returnFreeList,在uint8TargeDevicelnit(void)初始化硬件外设函数中调用如卜语彳J完成设备空闲控制块链表的初始化:/*初始化换件外设*/uintSTargeDevicelnit(void)初始化设备控制块空闲链表HvlFreeList=HvlFreeListlntiO,B、创建设备:该函数的接口形式如下:uint8CreatDevic(DEV_IDdev

20、jd.voidcreatparam,DEV_OPERATIONS*creatist)过程是从中取得一个控制块,同时调用设备安装函数OS_EVENT*(*DevInstell)(void*param,INT8U*err),返回一个设备信号貼而该设备安装函数由具体的底层驱动开发者提供,是参数DEV_OPERATIONS*creatjist的成员么一,目的是为了方便设备驱动开发者可以自由的选择信号鼠类型;进一步初始化设备ID,最后将该控制块琏接到具体的函数实现如下:DEV_CONTROL_BLOCK*HvlConList=NULL,/定义设备控制块链表指针,/*创建一个设备*/uint8CreatD

21、evic(DEV_IDdev_id,void*creatparamEVOPERATIONS*creat_list)DEV_CONTROLBLOCK*GetHCB=NULL,uint8OSeir=TRUE,OS_ENTER_CRmCAL0,GetHCB=HvIFreeList,创建设备时从设备控制空闲链表中取得一个设备控制块if(GetHCB=NULL)OS_EXIT_CRmCAL0,returnHVL_NO_CONTROL_BLOCK获取控制块失败,返回无空闲设备控制HvlFreeList=HvlFreeListnext_block;GetHCB-deviceid=devid,GetHCB-d

22、ev_opjiandle=cieatjist,GetHCB-dev_opjiandle-parent=GetHCB,0S_EXIT_CRmCAL。;调用设备安装函数,该函数返回一个互斥信号量指针和错误类型一GetHCBdev_file=GetHCB-dev_opJiandle-DevInstall(cieatparam,&OSerr),if(OSeir!=HVL_NO_ERR)/判断是否安装设备成功,不成功则返还设备控制块GetHCBdevice_id=0,GetHCB-dev_opJiandle-parent=NULL,GetHCB-dev_op_handle=NULL,GetHCB-nex

23、t_block=HvlFreeList,HvlFreeList=GetHCB,returnHVLINSTALLFAIL,if(GetHCB-devJile-OSEventType=OS_EVENT_TYPE_MUTEX)GetHCB-sem_type=MUTEX_SEM,elseif(GetHCB-dev_file-OSEventType=OS_EVENT_TYPE_SEM)GetHCB-sem_type=BASIC_SEM,GetHCB-waitouttime=0,/无限时的等待打开一个设备.#if(EN_DEV_UNINSTALL=1)GetHCBVicVectCnt=(DEV_INTER

24、RUPT_REG*)cieatparam)-VicVectCnt,GetHCB-VicVectAddr=(DEV_INTERRUPT_REG*)creatparam)-VicVectAddr,#endifGetHCB-next_block=HvlConList,HvlConList=GetHCB,returnHVLNOERR,在uint8TargeDeviceInit(void)初始化硬件外设函数中调用如下语句完成创建一个设备,例如创建UART0/*初始化哽件外设*/uint8TargeDevicelnit(v01d)#if(EN_UARTO_DRIVE=1)初始外亚-UARTOInitO,#

25、endifUARTOInitO,函数实现如卜所示:/*uaitO初始化函*/voidUART0Init(void)UART_CREAT_PARAMuaitOparam,VIC_REGISTER_GROUPvic_uart_pawm,uaitO_paramBaudRate=9600,uaitO_paramSetsize=_8bitLIode”uaitO_paramSetstopb=_lbitSTOP,uaitO_param.Setpanty=AddBitCheck,uaitO_paramSetenpanty=DisparityCheck,uaitO_paramISRPORT=&UART0_Han

26、dler,vic_uart_param.VicVectCnt=&UART0_VICVectCnt,vic_uait_param.VicVectAddr=&UARTO_VICVectAddr,uaitO_paramext_creat_param=&vic3iart_param,uaitO_fun.DevPutch=&v_UARTOSendNByte,uaitO_fun.DevGetch=&u_UARTOGetNByte,uaitOfun.DevContiol=&uUARTOContiol,uaitOfun.DevInstall=&UARTOInstall,#if(EN_DEV_UNINSTALL

27、=1)uaitO_funDevUninstall=&UARTOUninstall,#elseuaitO_fun.DevUninsUll=NULL,#endifCreatDevic(UARTO_ID,&uartO_param,&uartO_Fun);如上所示,在UARTOInit函数中调用了CreatDeviCo第一个参数是该设备的ID,第二个参数是创建参数,主要记录了初始设置例如串门波特率等,第二个参数主要用于传递底层的设备驱动函数指针如:v_UARTOSendNByte(uaitO发送N字节的数据,即设备写操作的具体实现)。u_UARTOGetNByte(uaitO接收N字节数据,即设备读的

28、具体实现)。u_UARTOContiol(uartO控制函数,即设备控制的貝体实现)0UARTOInstall(uaitO设备安装函数的实现)。C、设备打开:过程是从有效的设备控制块徒表中找到指定ID的设备控制块,审请信号量,如果审请通过则返回该设备的操作句柄。函数原型如卜:DEV_FUN*DeviceOpen(DEV_IDdev_id,HVL_ERR_CODE*eir)DEVCONTROLBLOCK*GetHCB=HvlConList,uintSOSeir,if(GetHCB=NULL)*eiT=HVLCONTROLLISTFULL,returnNULL,while(GetHCB!=NULL

29、)if(GetHCB-devicejd=devjd)找到指定ID的设备if(GetHCBsem_type=MUTEX_SEM)向操作系蔬审请打开设备操张OSMutexPend(GetHCB-dev_file,GetHCB-vzait_out_tinie,&OSerr),elseif(GetHCBsem_type=BASIC_SEM)OSSemPend(GetHCB-dev_file,GetHCB-V7ait_out_tirne,&OSerr)”else水err=HVLNOFINDDEV,returnNULL,if(OSeiTi=OS_NO_ERR)水err=HVLWAITDEVTIMEOUT,

30、returnNULL,*eir=HVLNOERR,利用强制转换继承函数接11并返回设备接11return(pEV_FUN*)GetHCB-dev_opJiandle,GetHCB=GetHCB-nextblock,*eir=HVL_NO_FIND_DEV,returnNULL,D、设备关闭:过程则是将传入的设备句柄强制转换成DEV_OPERATIONS*指针类形,然后用其成员DEV_CONTROL_BLOCK*parent,所指向的该设备的控制块。Z后释放信号鼠,最后将设备句柄赋值NULL。在这里传给DeviceClose的参数是指向指针的指针,目的就是为了这一步的赋值。uint8Device

31、Close(DEV_FUN*dev)DEV_OPERATIONS*GetDev=(DEVOPERATIONS*)(*dev);uint8OSeir=1,if(GetDev-parent=NULL)returnHrLCLOSEDEVFAIL,if(GetDev-parent-sem_type=MUTEX_SEM)OSeiT=OSMutexPost(GetDev-parent-dev_file),elseif(GetDevparentsem_type=BASIC_SEM)OSeiT=OSSemPost(GetDevparent-dev_file),if(OSeir=OS_NO_ERR)*dev=N

32、ULL,returnHVLNOERR,elsereturnHrLCLOSEDEVFAIL,E:设备的操作句柄函数列表包括:读出、控制、写入、设备安装函数、设备控制块指目的是为了加快设备关闭操作;写入和读出其实质是写和读各个设备的缓冲区。而控制应包括设备参数的设置,起动和停止三部分。设备打开和关闭主要解决设备的共享和分配。Structdevice_operations_listINT8U(*DevPutch)(INT8U*str,INT16Ulength),设备字节写函数INT8U(*DevGetch)(INT8U*sb;INT16Ulength),设备字节读函数INT8U(*DevContio

33、l)(void*param),设备控制函数OS_EVENT*(*DevInstall)(void*param,INT8U*err),设备安装与设备控制函数的差别一在于设备安装要传递向量相关信息DEV_CONTROL_BLOCK*parent;指向包含该设备操作列表的设备控制块相当于,用于加快设备关闭F:其中对于上层抽像接口只开放三个函数指针:分别是读,写,控制函数。typedefshuctdevice_functionDEV_FUN,structdevice_function从设备操作列表中继承三个设备函数INT8U(*DevPutch)(INT8U*str,INT16Ulength),设备字

34、节写函数INT8U(*DevGetch)0NT8U*sti.INT16Ulength),设备字节读函数INT8U(*DevConhol)(void*param);设备控制函数,3、上层抽像接口:为了方便应用程序的开发所以为每个设备提供特定的抽像接II,设置上层抽像接II的原则是碾件无关性。利用这一特性将來所有的应用程序,GUI,TCP/IP都可以很轻松的在不同的碘件体系上运行。为了实现这一特性,该类所有接II的实现过程如卜:A、通过设备打开操作得到设备的操作句柄。B、利用该句柄实现接口的底层操作。以UART和I2C为例子:为了实现UART格式化字符输出可利用设备操作句柄所包含的字符写入函数,实

35、现对外输出字符。OS_UART.c,OS_UART.h为UART的上层抽彖接II,提供了三个函数:v_MmiPi*intf最小格式化字符串输出,详细定义看源代码UARTSet串I参数设置为了实现I2C的主模式发送则首先利用I2C设备句柄的设备控制函数设置I2C模式、所操作I2C设备地址、数据地址;然后利用字符写入函数对外输出将要发送的数据。OSHC.h.OSIICc为I2C模块的上层抽彖接II,实现了3个抽彖接I1:IZCMasteiSend主模式发送,详细定义看源代码IZCMasterReceive主模式接收IZCSlaverReceive从模式接收4、底层驱动函数的实现:UART.c,UART.h为UART底层驱动函数源码。nc.c.nc.h为I2C底层驱动函数源码。5、驱动开放的框架,模式:以UART为例。上层抽象接口文件0S_UART.H文件中提供了UART抽像接口,应用程序利用这些己定义好的接口实现对硬件的访问,可以很方便的在不同硬件平台上实现移植.移植时所要做的工作就是根据这些抽象接口的定义形式重新编写BSP中的代码.例如UART0要求根据硬件平台实现的函数有:uintSv_UARTOSendNByte(uint8*str,u

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论