WindML相关知识和图形设备驱动程序开发(二)
|
2.5 VxWorks BSP 需要
典型地,必须修改VxWorks BSP来满足能够使用图形和输入设备的需要。 由于Vxworks支持的目标板和处理器比较多,不可能详细说明每个BSP所要修改的东西,下面将描述一些通用的修改:
2.5.1 图形设备内存映射
一个图形设备有两个基本组件:
n 帧缓冲器
n 一个或多个控制器
帧缓冲器是一个内存块,用来存储要显示的图形数据。控制器包括图形处理器、RAMDACs和时钟芯片。取决于图形设备,有的控制器不用或者集成到单个控制器中。
帧缓冲器和每个控制器对于处理器必须是可见的,访问它们根据不同的处理器结构,可以是内存访问、IO访问或者二者结合来访问。要使得处理器能够访问图形设备,必须修改BSP的两个部分:
n 必须使能设备物理映射
n 必须使能逻辑或虚映射
需要根据处理器、图形设备和总线结构类型来做出准确的修改。
物理映射
物理映射包括使能地址映射器来解码图形设备所驻留的物理地址。图形控制器的映射取决于图形控制器的类型、处理器结构和Vxworks BSP。
WindML 没有限制图形设备所用的总线结构,总线可以是CPU内部总线、ISA、PCI、AGP、VME总线等。
PCI总线
PCI规范允许使用标准方法来使图形设备被映射到PCI内存空间。系统启动时,初始化程序负责分配PCI内存给每个PCI设备,初始化程序可以是厂商的启动代码或者是包含在Vxworks初始化程序中。有的厂商有类似于BIOS功能的固件,它可以把控制权交给Vxworks引导程序。
比如,在X86处理器上,主板上的BIOS来实现内存映射。当BSP支持PCI总线的自动配置时,就可以使用这个功能来映射图形设备到处理器内存。
然而不幸的是,并不是所有的处理器和Vxworks BSP都支持这种PCI设备的映射。当PCI设备不能映射到PCI内存空间时,就必须修改sysLib.c文件来映射PCI图形设备到一个可用的PCI内存空间。当为PCI设备发现一个安全的内存区时,就必须设置PCI配置头的基地址(偏移量为0x10)。
下面这段代码说明了Tvia IGS-5050图形设备该如何分配位置:
/* First the PCI bus must be probed to locate the device */
if (pciFindDevice (UGL_PCI_IGS_ID, UGL_PCI_IGS5050_CHIP_ID, instance,
&busno, &devno, &funcno) == OK)
{ /* Device found, set the base address */
pciConfigOutLong (busno, devno, funcno,
PCI_CFG_BASE_ADDRESS_0, baseAdrs);
/* Enable I/O and memory access */
pciConfigOutWord(busno, devno, funcno, PCI_CFG_COMMAND,
PCI_CMD_IO_ENABLE | PCI_CMD_MEM_ENABLE);
} else
/* Error device not found */
利用同样的方法可以映射任何PCI图形设备到处理器内存中,只是随处理器和BSP的不同,PCI的管理有点不同而已。
Virtual Mapping(虚拟映射)
虚拟映射使处理器内存管理单元(MMU):
n 执行需要的虚拟到物理的映射
n 指定合适的缓存方法
当系统结构是基于PCI总线且已经通过厂商启动程序(如X86 BIOS)完成了内存映射,那么需要被映射设备的位置。这可以通过执行pciHeaderShow( )函数或者uglGraphicsMapShow( )工具来完成。uglGraphicsMapShow( )工具可以从WindML网站上下载。
下面的shell给出了uglGraphicsMapShow( )输出:
-> uglGraphicsMapShow
Probing PCI bus for graphics devices
Device Number 8
Vendor = ATI (1002)
Device = MACH64 (4354)
Base address = 0xfb000000
Size = 0x1000000
Device Number 14
Vendor = IGS Tech (10ea)
Device = 5050 (5000)
Base address = 0xfe000000
Size = 0x2000000
value = 0 = 0x0
在这个例子中,有两个PCI图形设备:
ATI MACH64
Device Number 8
The device number is the PCI device number, 8 in this case.
Vendor = ATI (1002)
Device = MACH64 (4354)
第一个设备是ATI MACH64.
ATI后面的数字是分配给ATI的PCI厂商号。
MACH64 后面的数字是被ATI公司分配给MACH 64的设备号。
Base address = 0xfb000000
Size = 0x1000000
它位于地址0xfb000000,并且需要0x1000000 PCI内存映射空间,如果厂商ID或者设备ID未知,那么这个入口就被列为未知。
IGS5050
Device Number 14
The device number is 14.
Vendor = IGS Tech (10ea)
Device = 5050 (5000)
第二个设备是IGS Technologies IGS5050.
Base address = 0xfe000000
Size = 0x2000000
它被映射到PCI地址0xfe000000且需要0x2000000PCI地址空间。
这个映射是通过修改BSP的sysLib.c文件来完成的,这个文件中有一个sysPhysMemDesc[ ]数据结构,它定义了内存映射。这个数据结构是内存块的入口矩阵,每个入口有五个域:物理地址、虚拟地址、内存区的大小、内存管理使能掩码和内存管理状态值。必须修改这个数据结构来包含图形设备所映射的地址入口。
举个例子,假设设备利用uglGraphicsMapShow( )工具检测到它的配置(如前),那么虚拟映射应该是:
/* linear video ram */
{ (void *) 0xFE000000, /* physical mapping */
(void *) 0xFE000000, /* virtual mapping */
0x2000000, /* size of segment */
VM_STATE_MASK_FOR_ALL,
VM_STATE_FOR_IO
} 域大小必须覆盖整个设备,内存管理掩码和状态必须设置成有效、可写,而不是可缓冲。
2.5.2 设备I/O配置
利用sysInByte( )/sysOutByte( )函数来访问I/O端口。
2.6 Configuring a Simulator to use WindML
《待续》
2.6 Configuring a Simulator to use WindML
在没有目标机的情况下,你可以利用Simulator for NT(或者for Solaris)来开发和测试WINDML应用程序。Simulator支持WINDML的2D操作。
当WINDML和Simulator结合使用的时,在主机上显示一个窗口,在配置窗口可以对显示窗口的大小和颜色进行设置。例如一个640*480 256色的窗口会和在GRAPHICS设备中设置的一样来显示。
为了使VXWORKS Simulator能够和 WINDML一起工作,下面介绍的几步配置是必须要做的。
2.6.1 Configuring SimNT
PC模拟器VxWorks.exe可以通过Tornado工程工具或者命令行进行编译。WindML必须通过配置工具或者命令行编辑uglInit.h进行编译。
要想在模拟器中运行WINDML,ugl_winLib.o必须包含在VxWorks的映象文件中。这个文件在静态连接WindML或者WindML组件在工程文件的编译选项中被选中时自动包含在里面。
当从命令行来进行编译,并且WindML应用程序被动态加载的时候,ugl_winLib.o必须明确的包含在BSP中,这可以通过使用MACH_EXTRA来实现:
1. 在simpc BSP路径下:target/config/simpc编辑MAKEFILE加入下面这句:
MACH_EXTRA= %WIND_BASE%"target"lib"objSIMNTgnuvx"ugl_winLib.o
2.编译这个模拟器映象 MAKE
查阅SimNT描述文档,在附录A标准驱动中描述了兼容的驱动和支持的操作模式。
2.6.2 Configuring SimSolaris
2.7 高级配置
WindML的配置文件是被那些不支持的、完全的或者部分的硬件所描述。有两种不同的高级配置:
l 不支持的设备
l WindML提供的设备,具有不同访问机制。
其他的高级配置选项是用来添加用户内存管理或者用户定义的字体
2.7.1自定义驱动访问方法
接下来讨论修改访问方法。这里所说的修改并不是一个简单的访问方法的修改,他需要了解设备的体系结构。要想知道设备的体系机构,参照第8章:图形设备驱动。
一个设备驱动的访问方法是由:访问ISA I/O空间、中断向量(interrupt vectors)、中断级别(interrupt levels)组成。访问机制的修改是通过uglInit.h 文件中定义的宏(MACRO)来控制的。下表定义了宏,怎么使用以及默认值。
在uglInit.h文件中要加入正确的宏,位置在语句:#include <ugl/config/uglDepend.h>之前,下面的程序段说明了如何重新指定鼠标和键盘的中断等级和中断向量
#define MSE_INT_LVL 0x1
#define MSE_INT_VEC 0x11
#define KBD_INT_LVL 0x2
#define KBD_INT_VEC 0x12
#include <ugl/config/uglDepend.h>
#endif /* __INCuglinith */
这些定制的访问方法可以在配置方法、配置工具和命令行中使用。
2.7.2添加一个自定义驱动
自定义的图形和输入设备驱动可以挂接在WINDML中,并可以利用命令行进行配置。8.2节编写一个图形驱动描述了WINDML设备驱动的体系结构。
按照以下的步骤来添加一个自定义设备驱动到配置过程中。
1. 在路径 target/h/ugl/config 下复制uglTemplateCustom.h到相同路径下并重命名为uglCustom.h(或者其他的名字)。
2. 对uglCustom.h作一些必要的修改,使uglCustom.h能够表明是自定义的驱动。
3. 在uglInit.h文件中定义正确的INCLUDE_CUSTOM_*来表明自定义的设备驱动
/* Specify the graphics device to use (Select 1) */
#undef INCLUDE_BIOS_GRAPHICS
#undef INCLUDE_CHIPS_GRAPHICS
#define INCLUDE_CUSTOM_GRAPHICS /* User defined graphics device */
#undef INCLUDE_IGS_GRAPHICS
#undef INCLUDE_MEDIAGX_GRAPHICS
#undef INCLUDE_SA11XX_GRAPHICS
#undef INCLUDE_SIMULATOR_GRAPHICS
#undef INCLUDE_Q2SD_GRAPHICS
#undef INCLUDE_M821_GRAPHICS
#undef INCLUDE_VGA_GRAPHICS
4. 在uglInit.h文件中定义UGL_CUSTOM_DRIVER_DEFS来定义配置文件和头文件的路径。
5. 用make来编译WindML
Custom Graphics Driver
一个自定义设备驱动(图形,键盘,或者触摸屏)即使不在windml的目录结构中也可以被配置。一个图形设备驱动要求定义以下的项:
下面的程序说明了在uglCustom.h中怎样向WINDML中添加一个新的图形设备。
/*
*
* Set up for the custom graphics device
*
*/
#if defined(INCLUDE_CUSTOM_GRAPHICS)
#define UGL_GRAPHICS_NAME "Custom graphics device"
#define UGL_GRAPHICS_INSTANCE 0 /* Device location */
#define UGL_GRAPHICS_IRQ 0 /* Device IRQ */
#define UGL_GRAPHICS_VECTOR 0 /* Device vector */
/* Initialization function */
extern UGL_UGI_DRIVER * uglCustom8BitDevCreate
(UGL_ORD instance, UGL_UINT32 irq, UGL_UINT32 vector);
#define UGL_GRAPHICS_CREATE uglCustom8BitDevCreate
/* Display mode */
#define UGL_COLOR_DEPTH 8
#define UGL_MODE_FLAGS UGL_MODE_INDEXED_COLOR
#endif /* INCLUDE_CUSTOM_GRAPHICS */
在这个例子中,自定义的图形设备驱动由函数uglCustom8BitDevCreate( )和设备驱动操作初始化为一个8位颜色索引的驱动。
Custom Keyboard Driver
要增加一个自定义的键盘,下面的参数必须被定义:
下面的程序说明了在uglCustom.h中怎样向WINDML中添加一个新的键盘设备。
/* Custom keyboard */
#ifdef INCLUDE_CUSTOM_KEYBOARD
#define INCLUDE_UGL_INPUT
#define SYS_KEYBOARD_NAME "/customKbd/0"
/* Name of the function to create the keyboard device */
extern STATUS customKbdDevCreate(char *name);
#define SYS_KEYBOARD_CREATE customKbdDevCreate
/* Name of the function to initialize the keyboard device */
extern UGL_INPUT_DEVICE_ID uglCustomKbdInit
(char * name, UGL_EVENT_SERVICE_ID eventServiceId);
#define UGL_KEYBOARD_INIT uglCustomKbdInit
#endif /* INCLUDE_CUSTOM_KEYBOARD */
WINDML对键盘驱动分两个阶段的初始化,第一个阶段是创建设备,第二个阶段是来初始化设备。
如果设备已经存在,就不需要设备创建过程。在上面的例子中键盘设备创建过程是customKbdDevCreate( ) 函数uglCustomKbdInit( )是用来负责初始化设备,使之能在WINDML使用。本例中创建和初始化的设备的名字是:/customKbd/0
Custom Pointer Driver
要增加一个自定义的触摸屏设备,下面的参数必须被定义:
下面的程序说明了在uglCustom.h中怎样向WINDML中添加一个新的触摸屏设备设备。
/* Custom pointer */
#ifdef INCLUDE_CUSTOM_POINTER
#ifndef INCLUDE_UGL_INPUT
#define INCLUDE_UGL_INPUT
#endif /* INCLUDE_UGL_INPUT */
#define SYS_POINTER_NAME "/customPtr/0"
/* Name of the function to create the pointer device */
extern STATUS customPtrDevCreate(char *name);
#define SYS_POINTER_CREATE customPtrDevCreate
/* Name of the function to initialize the pointer device */
extern UGL_INPUT_DEVICE_ID uglCustomPtrInit
(char * name, UGL_EVENT_SERVICE_ID eventServiceId);
#define UGL_POINTER_INIT uglCustomPtrInit
#endif /* INCLUDE_CUSTOM_POINTER */
和键盘驱动一样,WINDML对键盘驱动分两个阶段的初始化,第一个阶段是创建设备,第二个阶段是来初始化设备。如果设备已经存在,就不需要设备创建过程。在上面的例子中键盘设备创建过程是customPtrDevCreate( ) 函数uglCustomPtrInit( )是用来负责初始化设备,使之能在WINDML使用。本例中创建和初始化的设备的名字是:/customPtr/0
Custom Audio Driver
要增加一个自定义的音频设备,下面的参数必须被定义:
下面的程序说明了在uglCustom.h中怎样向WINDML中添加一个新的音频设备设备
/*
*
* Set up for the custom audio device
*
*/
#if defined(INCLUDE_CUSTOM_AUDIO)
#define SND_DEVICE_INSTANCE 220 /* instance of device */
#define SND_DEVICE_INT_LEVEL 5 /* interrupt level */
#define SND_DEVICE_INT_VECTOR 5 /* interrupt vector */
#define SND_DEVICE_DMA8 1 /* 8 bit DMA controller */
#define SND_DEVICE_DMA16 5 /* 16 bit DMA controller */
/* Creation function *
extern STATUS customSndDevCreate (char *devName, int channel, int instance,
int intLevel, int intVector, int dma8, int dma16);
#define SOUND_DEV_CREATE customSndDevCreate
#endif /* INCLUDE_CUSTOM_AUDIO */
在这个例子中,音频设备创建函数是customSndDevCreate( ),它的访问位置是220,它的中断级别和中断向量都是5。DMA传输方式,使用2口作8位传输,5口作16位传输。
2.7.3 Using a Custom Memory Manager
WINDML允许使用一个自定义的内存管理器。必须具有的功能包括:
l 创建内存管理池
l 销毁内存管理池
l 分配一个内存块(malloc和calloc函数)
l 重新分配一个以前分配过的内存块
l 释放一个以前分配过的内存块。
在uglInit.h文件中这些过程必须在语句:#include <ugl/config/uglDepend.h>之前声明
下面是一个自定义内存管理器的定义:
#define UGL_MEM_POOL_CREATE_RTN myMemPoolCreate
#define UGL_MEM_POOL_DESTROY_RTN myMemPoolDestroy
#define UGL_MEM_ALLOC_RTN myMemAlloc
#define UGL_MEM_CALLOC_RTN myMemCalloc
#define UGL_MEM_REALLOC_RTN myMemRealloc
#define UGL_MEM_FREE_RTN myMemFree
#include <ugl/config/uglDepend.h>
#endif /* __INCuglinith */
这些自定义的内存管理过程在配置方法-配置工具和命令行中都可以被使用。
2.7.4 Adding New Bitmap Fonts
其他的字体可以添加到位图字体集中。target/src/ugl/fonts/bmf目录下提供了所有的位图字体映象。在这个目录下的任何字体在配置过程中都是可用的。当以命令行方式来编译WINDML时,字体可能被uglBmfCfg.c文件引用。这些字体在配置工具中同样也是可用的。这些位图字体的描述文件的格式是WindMl格式,可以用有效的的程序将BDF字体转换为WindML格式。
2.8 Project Facility
Tornado工程工具允许在VxWorks中添加或者删除WindML的功能。要了解Tornado工程工具的更多的信息请查阅Tornado Getting Started Guide 和 Tornado User’s Guide: Projects,这个手册的重点是那些与WindML相关的工程工具。
当WindML安装完成后,在Tornado工程工具中一个WindML components的文件夹被创建,如下图所示:
这个目录下有两个子目录,2D graphics 和Audio components。应该注意的是一个用checkbox图标表示的目录选项是包含和不包含其中的一个。
利用工程工具来将WindML组件包含近来的,按以下步骤来做:
1. 选中一个组件
2. 点击鼠标右键,弹出一个级连菜单
3. 选择include项
如果组件已经包含进来了,可以通过相同的方式移除他们。点击右键,弹出级连菜单,选择Exclude选项。
2.8.1 Linking the 2D Library
2D library可以通过两种方法和VxWorks image相连。
1.将全部的2D层连接到VxWorks image中。(complete 2D library)
它允许WindML应用程序在目标机启动后并发的下载。这种模式在Vxworks/WindML包含了全部的WindML 2Dg功能后,允许任何的WindML应用程序动态的下载
1. 只连接必需的2D功能
这种模式需要将WindML编译进VxWorks,除WindML应用程序之外。这个结果在一个小的Vxworks/WindML image中。
注意:如果已经连接了一个更高一层的图形产品如:Zinc或者PersonalJWorks,就应该选择necessary 2D library而不是complete 2D library.
2.8.2 Adding WAVE File Support
在VxWorks image中音频功能支持WAVE一类的音频文件。一个WindML应用程序下载后可以播放音频文件。