EDN首页   博客首页 用户登陆  |  注册
aaa
发表于 2007/1/15 12:24:07

7

关于投票

windML鼠标OK!

前几天在用windML的时候发现在配置windML加上鼠标就不能正常显示图形,出现黑屏的现象。这几天将windML的DDk看了一下,终于将这个问题搞定了。

1 最基本的还是要将所有的配置选项配置正确,包括windML下的配置(包含鼠标),congfig.h里包含#define INCLUDE_WINDML
#define INCLUDE_WINDML_PS2_POINTE
#define INCLUDE_WINDML_PS2_KEYBOARD

在组件配置的时候,windML下的鼠标要包含,里面的属性名字跟windML下的配置名字相同

2 这就是在你启动以后在shell里用devs看看有没有你的鼠标键盘设备了。如果没有这就说明你的BSP设置有问题(一开始我在uglinit.c的初始化ugl设备的函数单步跟了一下,如果你的不行也可以这样试试)。如果有的话就进去用应用程序测试你的鼠标吧:)

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML鼠标OK  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(2329) | 回复(9)

发表于 2007/1/14 23:01:35

6

关于投票

windML--接上面文章

4 设置低级驱动模式
设置低级驱动允许传入所有的输入驱动,一般调用原始模式(raw mode)。这么设置是因为高级输入驱动需要对任何传输来原始数据进行处理,打包后作为输入事件。低级驱动传输数据,高级驱动接受数据。低级驱动有不同的操作,所以必须在一个合适的模式。
/* Set device in mode to pass all data – raw mode */
ioctl (pDevice->inputDevice.fd, FIOSETOPTIONS, OPT_RAW);
/* Flush input queue of any stale data */
ioctl (pDevice->inputDevice.fd, FIOFLUSH,0);
/* Scan codes need to be sent verses processed key codes */
ioctl (pDevice->inputDevice.fd, CONIOCONVERTSCAN, FALSE);
/* Initialize the LED to the initialized value */
ioctl (pDevice->inputDevice.fd, CONIOLEDS, pDevice->ledValue);
5 返回驱动结构的指针。如果驱动成功打开,返回UGL_INPUT_DEV的指针return (&pDevice->inputDevice);失败返回NULL

执行驱动控制程序
驱动控制程序提供几种操作使用标准的ioctl函数,有三个参数
第1驱动操作控制块
第2需求类型
第3需求类型包含地参数
具体如下:图


Keyboard LED Control点击看大图
switch (reqType)
{
.
.
.
case ICR_SET_LED: /* Set LED values */
case ICR_CLEAR_LED: /* Clear LED values */
{
UGL_UINT32 leds = *(UGL_UINT32 *)pArg;
int ledValue = 0;
/* generate a device dependent LED value */
if (leds & UGL_KBD_CAPS_LOCK)
ledValue |= UGL_PCKBD_LED_CAPS_LOCK;
if (leds & UGL_KBD_NUM_LOCK)
ledValue |= UGL_PCKBD_LED_NUM_LOCK;
if (leds & UGL_KBD_SCROLL_LOCK)
ledValue |= UGL_PCKBD_LED_SCROLL_LOCK;
/* Adjust representation if setting or clearing LEDs */
if (request == ICR_SET_LED)
pDevice->ledValue |= ledValue;
else
pDevice->ledValue &= ~ledValue;
/* Send request to low-level driver to change the LED values */
ioctl (pDevice->inputDevice.fd, CONIOLEDS, pDevice->ledValue);
}
break;
case ICR_GET_LED_STATE: /* Get state of LEDs */
{
UGL_UINT32 modifiers = 0;
/* Generate LED setting based on the modifier states */
if (pDevice->ledValue & UGL_PCKBD_LED_CAPS_LOCK)
modifiers |= UGL_KBD_CAPS_LOCK;
if (pDevice->ledValue & UGL_PCKBD_LED_NUM_LOCK)
modifiers |= UGL_KBD_NUM_LOCK;
if (pDevice->ledValue & UGL_PCKBD_LED_SCROLL_LOCK)
modifiers |= UGL_KBD_SCROLL_LOCK;
*(UGL_UINT32 *)pArg = modifiers;
}
break;
.
.
.
}
询问鼠标类型
鼠标类型的驱动必须由ICR_GET_PTR_TYPE指出类型例如:
switch (request)
{
.
.
.
case ICR_GET_PTR_TYPE: /* Pointer type query */
{
if(pArg != UGL_NULL)
{
*(int *)pArg = UGL_PTR_TYPE_MOUSE;
return(UGL_STATUS_OK);
}
else
return(UGL_STATUS_ERROR);
}
break;
.
.
.
}
读数据
所有高级输入设备必须响应数据读取要求。输入服务可被select挂起,等待数据被写入设备输入设备读队列。当低级设备驱动唤醒输入服务任务,任务调用合适的输入的设备控制通过ICR_READ请求。
当ICR_READ调用设备控制程序时,从低级驱动读取所有数据。例子如下:
switch (request)
{
case ICR_READ: /* read keyboard data */
{
int readCnt = 0;
/* Get data until no more data is present */
ioctl (pDevice->inputDevice.fd, FIONREAD, (int)&readCnt);
while (readCnt > 0)
{
unsigned char scanCode;
/* Read a code from the keyboard low-level driver */
if (read(pDevice->inputDevice.fd, &scanCode, 1) != 1)
return (UGL_STATUS_ERROR);
/* If received data signifies the start of an extended key,
* then mark that in the process of reading an extended key
* sequence */
if (scanCode == UGL_PCKBD_EXTENDED_KEY)
pDevice->extendedKey = UGL_TRUE;
else if (scanCode != 0x55) /* In test, ignore */
{
UGL_MSG kbdMsg;
/* Create raw keyboard message */
bzero ((char *)&kbdMsg, sizeof (kbdMsg));
kbdMsg.type = MSG_RAW_KBD;
kbdMsg.data.rawKbd.deviceId = &pDevice->inputDevice;
if (scanCode & UGL_PCKBD_MAKE_FLAG)
{
kbdMsg.data.rawKbd.isKeyDown = UGL_FALSE;
scanCode &= ~UGL_PCKBD_MAKE_FLAG;
}
else
kbdMsg.data.rawKbd.isKeyDown = UGL_TRUE;
if (pDevice->extendedKey)
{
kbdMsg.data.rawKbd.isExtended = UGL_TRUE;
pDevice->extendedKey = UGL_FALSE;
}
else
kbdMsg.data.rawKbd.isExtended = UGL_FALSE;
kbdMsg.data.rawKbd.isKeyCode = FALSE;
kbdMsg.data.rawKbd.value.scanCode = scanCode;
/* post message */
uglInputMsgPost (pDevice->inputDevice.inputServiceId,
&kbdMsg);
}
readCnt--;
}
}
break;
.
.
.
}

系统分类: 嵌入式  |  用户分类: windML  |  标签: 关于windML  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1086) | 回复(1)

发表于 2007/1/14 0:27:52

6

关于投票

windML输入设备的头文件

输入设备的头文件
驱动的头文件包括典型的设备,但是头文件必须包含windML的哪一部分连入驱动的信息和驱动怎么包含配置信息。
设备控制结构
必须定义输入设备控制结构体(作为UGL_INPUT_DEV的第一个元素)如果输入设备不需要其他的数据就如下定义
typedef struct ugl_pc_kbd_device
{
UGL_INPUT_DEV inputDevice; /* Inherits input device structure */
UGL_BOOL extendedKey; /* Extended key receipt */
UGL_BOOL ledControl; /* App/WindML controls LEDs */
UGL_UINT32 ledValue; /* Current LED state */
} UGL_PC_KBD_DEVICE;
这个例子中键盘驱动需要LED中的信息和是否外部的键在执行;因此要包含下面的几项。
配置控制
一个输入驱动可能需要包含来自初始化程序的配置信息。同样配置程序可能需要关于已有驱动的信息。因此,头文件必须包含以下信息
/* Get the Device Driver Configuration Definitions */
#ifndef INCLUDE_PC_AT_KEYBOARD
#define INCLUDE_PC_AT_KEYBOARD
#define BUILD_DRIVER
#include <uglInit.h>
#endif /* INCLUDE_PC_AT_KEYBOARD */
这种情况下,包含uglInit,h提供需要的配置信息
注意:BUILD_DRIVER必须在uglInit,h之前定义。
INCLUDE_PC_AT_KEYBOARD定义了特殊的设备驱动。当写一个新的驱动必须重新定义一个特殊的设备驱动宏。
除此外设备驱动在头文件里包含设备驱动配置参数设备驱动必须包含以下的参数
SYS_KEYBOARD_DRIVER提供输入驱动的数据结构来辨别键盘输入设备的入口指针
SYS_POINTER_DRIVER
以下程序提供初始化程序指针
extern UGL_INPUT_DRV uglPs2PtrDriver;
#define SYS_POINTER_DRIVER &uglPs2PtrDriver
相关数据结构在uglPs2PtrDriver例子中。
一般资源文件格式
执行以下三种操作
open打开一个低级驱动,设置设备驱动的可能模式,初始化设备控制结构
close关闭一个低级驱动释放开的资源
control一般驱动控制操作包括conhdiji驱动里读数据和设置键盘LED的值
Input Driver Structure
UGL_INPUT_DRV uglPcKbdDriver =
{
(UGL_INPUT_DEV_OPEN)uglPcKbdOpen, /* Open driver API */
(UGL_INPUT_DEV_CLOSE)uglPcKbdClose, /* Close driver API */
(UGL_INPUT_DEV_CONTROL)uglPcKbdControl /* Control driver API */
};
头文件必须包含UGL_INPUT_DRV,可以运行这些程序
执行驱动打开程序
当程序运行uglInitializ的时候初始化windML。在uglInitializ中,调用uglInputDevOpen( )打开输入驱动程序。
当输入驱动成功打开的以后,驱动打开程序返回UGL_INPUT_DEV数据结构的指针。如果驱动初始化设备失败,就返回NULL。
驱动打开程序包括以下输入参数:
第一个参数是低级驱动的名字,驱动接收原始数据
第二个参数是输入驱动结构UGL_INPUT_DRV的指针
需要驱动打开的程序
驱动打开的程序需要分为下面几步:
1 分配驱动控制结构
UGL_LOCAL UGL_INPUT_DEV * uglPcKbdOpen
(
char * pDevName, /* name of the device */
UGL_INPUT_DRV * pDriver /* input driver */
)
{
UGL_PC_KBD_DEVICE * pDevice;
/* allocate the device descriptor */
pDevice = (UGL_PC_KBD_DEVICE *) UGL_CALLOC (1,
sizeof (UGL_PC_KBD_DEVICE));
if (pDevice == UGL_NULL)
return (UGL_NULL);
驱动控制结构用UGL_CALLOC程序分配,确保能从WindML内存池中分配到所需的内存。
2 打开低级驱动
/* open the device */
pDevice->inputDevice.fd = open (pDevName, 0, 0);
if (pDevice->inputDevice.fd < 0)
{
UGL_FREE (pDevice);
return (UGL_NULL);
}
打开文件的文件描述符存储在输入设备结构中。如果打开失败,分配的内存被释放,返回NULL指针。
3 初始化驱动控制结构
包括两部分初始化:UGL_INPUT_DEV和在开发下特殊的数据,UGL_INPUT_DEV必须初始化以下数据域:
文件描述符fd在第二步被设置
设备类型
UGL_DEVICE_KEYBOARD
A keyboard.
UGL_DEVICE_POINTER_ABSOLUTE
A pointer device that generates an absolute location on the display
screen. A touchscreen is an example of an absolute pointing device.
UGL_DEVICE_POINTER_RELATIVE
A pointer device that generates a relative location from the previous
reported location, such as a mouse.
驱动程序结构
驱动程序结构是UGL_INPUT_DRV数据结构的一个指针(由第二那个参数传入)。
/* Initialize required device data */
pDevice->inputDevice.deviceType = UGL_DEVICE_KEYBOARD;
pDevice->inputDevice.pDriver = pDriver;
/* Initialize driver specific data for keyboard */
pDevice->ledValue = 0;
pDevice->extendedKey = FALSE;
pDevice->ledControl = TRUE;

 

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML输入设备的头文件  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1448) | 回复(1)

发表于 2007/1/10 17:07:13

5

关于投票

windML输入设备

 

 

点击看大图

低级别输入驱动
低级别输入驱动作为IO驱动执行,通常在系统内核配置。这个驱动当初始化的时候连接内核系统的IO系统。它的响应包括以下几方面:
初始化设备控制器和输入设备
通过设备控制器生成中断句柄
从输入设备接收原始数据并且降队列用IO系统传给高级驱动。数据排队完,输入设备激活使用select机制
从高级驱动接收命令和应答。例如在键盘控制LED
开发一个低级输入驱动,必须理解怎样微操作系统写IO驱动,并且理解设备控制器和你所开发的输入设备。
经常,输入设备连接串行接口,例如Vxworks提供的标准串行设备。例如,触摸屏经常通过串口能被连接到标准的串行设备如/tyCo/1。
高级输入驱动
高级输入驱动主要响应接收从低级输入驱动传来的原始输入数据,打包作为输入消息,并将消息放到消息队列里。

执行低级输入驱动
低级输入驱动是标准繁的IO系统驱动提供基础的IO接口open,close,read,write,ioctl
除此之外,驱动必须提供select的支持,提供给检测输入数据用。
当执行低级输入设备时,为一般操作系统,不同的硬件,不同的目标板设计。你能够通过写不同硬件结构驱动代码达到目的。怎么编驱动和怎么使用windML的硬件抽象层,看12
对vxworksIO驱动的一般技术在vxworks programmers guids:IO系统
既然vxwork的styLib提供许多低级驱动的功能,建议使用tyLib的优势。通过这个,你的驱动不用控制读写队列或select程序。这将使开发低级驱动变得很简单。

设备的程序数据
低级驱动不能从输入设备中断数据。可以接收数据并且作为原始数据传给高级输入驱动,没有调整输入结构。例如,一个键盘设备通常发送一列代码包括key up和key down。每一个键的代码需要传给高级驱动。
发送数据到设备
一个低级的设备驱动不能利用write机制从高级的驱动设备接收任何数据。这可能产生输入设备异常。一些需要高级设备驱动写不同的操作模式信息。当为一个特殊的硬件开发一个输入驱动时,你可能需要高级设备驱动网低级设备驱动写程序给特殊需求的设备。
设备控制
低级输入设备需要为依赖于操作的输入设备完成ioctl功能。ioctl功能整个依赖设备类型和控制的不同。例如,键盘输入设备有一个为控制LED的ioctl功能。对于vxworks,ioctl设备必须提供有用的select信号。
完成高级输入设备
以下是写高级驱动的步奏
为windML结构中的的驱动创建资源和头文件。一个头文件甚至需要作为一个二进制驱动,因为配置程序需要在输入设备的头文件中包含子女子。
创建open等程序
创建资源和头文件
包含的文件夹
installDir/target/src/ugl/driver/keyboard
The source file for all keyboard drivers.
installDir/target/h/ugl/driver /keyboard
All header files for the keyboard drivers.
installDir/target/src/ugl/driver/pointer
The source file for all pointer drivers.
installDir/target/h/ugl/driver /pointer
All header files for the pointer drivers.
增加一个新的键盘或鼠标驱动,增加新的资源到路径下。就不需要配置makefile,makefile可以编译这个目录下的所有资源。

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML输入设备  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1532) | 回复(2)

发表于 2006/12/30 23:45:24

8

关于投票

windML资料

小鱼整理的windML资料,希望对大家有用:)

rar

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML资料  |  来源: 整理  | 

点击查看原文

发表评论 阅读全文(1330) | 回复(0)

发表于 2006/12/30 23:16:49

7

关于投票

xiaofish调windML

今天下午我又根据几个网友给我提的建议继续调试windml,因为我对这个东东还抱有一丝希望!
首先学会了单步调试程序,单步跟踪了一下uglDemo,发现一运行到uglInit程序就飞了,跑出一个汇编的程序窗口,“可靠树”告诉我可能是因为我的源码不全,当时郁闷死!可还是没死心!
然后根据“xx ”给我提的建议我把windml卸了,重装!我上次装windml时让选Tornado版本时我把所有的都选上了(有点贪婪啊),这次只选了Tornado2.2,然后重新编译windml,选了No Pointer 并把keyboard的Name改成了/pcConsole/0(“ xx”告诉我这样改的),在等待编译完成的过程中又看到“xxx”给我的网页里有这样一段话:

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.

所以我就把libwndml.a加入到VxWorks的EXTRA_MODULES里,然后重新编译VxWorks,然后继续单步调试程序,竟然就没有汇编窗口蹦出来了,然后就看到有图形显示了,然后就可以响应键盘了!

xiaofish的经验也许对大家有帮助啊!

系统分类: 嵌入式  |  用户分类: windML  |  标签: xiaofish调windML  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1201) | 回复(1)

发表于 2006/11/22 23:59:16

12

关于投票

vxworks如何才能操作WindML显示部分的存储空间

(UGL_UINT32)Vesa_VideoDriver->genDriver.fbAddres在初始化设备后将这个值附给一个全局变量,再打印出来就行.这个地址就是初始地址.其实在你应用程序初始化设备后会在Shell里看见打印出一串地址(我的工控板是0x40800000)这就是起始地址,后面还有显存大小,是否使用双缓存.下面是初始化你的图形设备的程序: 

if (uglInitialize() == UGL_STATUS_ERROR)/*初始化设备*/
 return; 
  pRegistryData = uglRegistryFind (UGL_DISPLAY_TYPE, 0, 0, 0);/*找到设备注册信息*/
    if (pRegistryData == UGL_NULL)
        {
 printf("Display not found. Exiting.\n");
 uglDeinitialize();
 return;
 }
    devId = (UGL_DEVICE_ID)pRegistryData->id;/*设备ID*/

    pRegistryData = uglRegistryFind (UGL_INPUT_SERVICE_TYPE, 0, 0, 0); /*找到输入设备*/  
    if (pRegistryData == UGL_NULL)
   {
     printf("Input service not found. Exiting.\n");
     uglDeinitialize();
     return;
   }
    inputServiceId = (UGL_INPUT_SERVICE_ID)pRegistryData->id;/*输入设备ID*/

后直接往初始地址地址就能写值了!

系统分类: 嵌入式  |  用户分类: windML  |  标签: vxworks如何才能操作WindML显示部分的存储空间  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(2838) | 回复(21)

发表于 2006/10/25 12:17:51

36

关于投票

VxWorks丰富的定时管理和时钟管理

VxWorks提供丰富的定时管理和时钟管理,主要应用在以下几个方面:

? 维护系统日历时钟

? 在任务等待信号量、消息、事件(VxWorks5.5版本以上)或内存段时的超时处理。(系统提供的函数调用都有关于timeout的参数设置。)

? 以一定的时间间隔或在特定的时间唤醒或发送告警到一个任务。

? 处理任务调度中的时间片轮转。

VxWorks系统这些功能都依赖于周期性的定时中断,离开实时时钟或定时器硬件就无法工作。介绍几个常用的系统调用:

l sysClkConnect( )――连接系统时钟中断服务程序(sysLib.h)

函数原型:――connect a routine to the system clock interrupt
STATUS sysClkConnect
(
FUNCPTR routine, /* routine called at each system clock interrupt */
int arg /* argument with which to call routine */
)

l sysClkRateSet( )――设置每秒钟系统时钟中断次数(既每秒钟的tick数)(sysLib.h)
函数原型:――set the system clock rate
STATUS sysClkRateSet
(
int ticksPerSecond /* number of clock interrupts per second */
)

l sysClkEnable ( )――使能系统时钟中断(sysLib.h)

函数原型:――turn on system clock interrupts

void sysClkEnable (void)

系统定时器的设置是在usrConfig.c中通过usrRoot( )函数完成的,主要就是调用以上三个函数,代码如下:

/* set up system timer */

sysClkConnect ((FUNCPTR) usrClock, 0); /* connect clock ISR */

sysClkRateSet (SYS_CLK_RATE); /* set system clock rate */

sysClkEnable (); /* start it */

其中usrClock( )也是在usrConfig.c中定义的,函数只是通知系统内核时钟tick。

void usrClock ()

{

tickAnnounce (); /* announce system tick to kernel */

}

(有关tickLib.h中的函数以后再介绍)

而系统时钟频率SYS_CLK_RATE的值在congfigAll.h中定义为60,代码如下:

#define SYS_CLK_RATE 60 /* default system clock rate */

你可以通过改这个值来自己设置系统时钟中断频率,一般在60到100,但不能大于600。SYS_CLK_RATE只设置的过大会增加任务切换开销。

l sysClkRateGet( )――得到每秒钟系统时钟中断次数(既每秒钟的tick数)(sysLib.h)

函数原型:――get the system clock rate

int sysClkRateGet (void)

[此贴子已经被作者于2004-5-31 17:13:36编辑过]
--------------------------------------------------------------------------------

学习总结:VxWorks的定时与时钟管理2

http://bbs.edw.com.cn/dispbbs.asp?boardID="3"&ID="29415"&page="1"

自己的一个小程序:(如何使用sysCkRateSet和sysClkRateGet)

/**********************************/
#i nclude "vxWorks.h"
#i nclude "sysLib.h"

#i nclude "stdio.h"
void test()
{
int TimeRate,NumB;
TimeRate = 100;
if(sysClkRateSet(TimeRate) ==ERROR)
{
printf("Error in setting rate!\n");
}
NumB = sysClkRateGet();
printf("NumB = %d\n",NumB);
}
运行结果:
-> test
NumB = 100
value = 11 = 0xb = __major_os_version__ + 0x7
l tickAnnounce( )――通知系统内核时钟tick
函数原型:――announce a clock tick to the kernel
void tickAnnounce (void)
它被usrConfig.c中的usrClock( )调用,而usrClock( )又是系统时钟中断服务程序,想让应用程序运行在系统时钟中断级,则可将其加在ursClock程序里。
l tickSet( )――设置内核时钟计数器值(内核tick的数)
函数原型:――set the value of the kernel's tick counter
void tickSet
(
ULONG ticks /* new time in ticks */
)
l tickGet( )――得到内核时钟计数器值
函数原型:――get the value of the kernel's tick counter
ULONG tickGet (void)
下面两个例子:
/**********例一:用tickGet获得现在内核tick定时器的tick数******************/
#i nclude "vxWorks.h"
#i nclude "tickLib.h"
#i nclude "stdio.h"
#i nclude "taskLib.h"
#i nclude "logLib.h"
void test()
{
ULONG TickCounts;
for(int i="0";i<5;i++)
{
TickCounts = tickGet();
logMsg("TickCounts = %d\n",TickCounts,0,0,0,0,0);
taskDelay(100);
}
}
运行结果:(在目标仿真器上输出)
0x12892b8 (t12): TickCounts = 299830
0x12892b8 (t12): TickCounts = 299930
0x12892b8 (t12): TickCounts = 300030
0x12892b8 (t12): TickCounts = 300130
0x12892b8 (t12): TickCounts = 300230
如果将上面的logMsg换为printf,则输出在shell中(注意两种输出的区别)。
/***********例二:tickSet和tickGet的使用例程************************/
#i nclude "vxWorks.h"
#i nclude "tickLib.h"
#i nclude "stdio.h"
#i nclude "taskLib.h"
void test()
{
ULONG TickCountSet = 0;
tickSet(TickCountSet);
for(int i="0";i<5;i++)
{
ULONG TickCounts = tickGet();
printf("TickCounts = %d\n",TickCounts);
taskDelay(100);
}
}
运行结果:
-> test
TickCounts = 0
TickCounts = 100
TickCounts = 200
TickCounts = 300
TickCounts = 400
value = 0 = 0x0

系统分类: 嵌入式  |  用户分类: windML  |  标签: 定时管理 vxworks 时钟管理  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(3467) | 回复(7)

发表于 2006/10/25 0:22:07

36

关于投票

双缓冲续

在开发一个工控板的时候,发现不用双缓冲技术屏幕也不会有变化。最后分析原因,可能是在工控板上有显示芯片,显示芯片本身的驱动程序就带有双缓冲的机制,所以如果在应用中有的场合硬件本身有双缓冲机制的话就没有必要再加入双缓冲机制,这样可以减小内核的体积,增加系统的性能。

系统分类: 嵌入式  |  用户分类: windML  |  标签: 双缓冲  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(1322) | 回复(0)

发表于 2006/10/25 0:17:16

35

关于投票

windML双缓冲技术

WindML提供了2D图形的解决方案.但在某设备信息化改造项目中。由于需要实时采集 、显示虚拟仪表图形信息、驾驶员终端显示综合控制信息 、车内各设备状态信息车长命令、报警等 。都需要实时绘制画面,每次采集到数据和各信息互相切换都要刷新画面。画面闪烁、抖动比较剧烈.因此可以把在显示时不变化的信息以位图背景的形式保存 ,调用(uglDefault—BitmapSet0)来实现,在此背景上来动态刷新变化的仪
表指针、设备状态 、报警等。这样在刷新画面时数据量减少,画面的效果有所改善,但是由于采集到的数据 、状态等是实时变化,画面闪烁、抖动存在。视觉效果不佳 ,本文应用 WindML的双缓冲技术来解决这一问题 。
双缓冲技术是指不改变可见视频缓存区起始地址,而是在内存中开辟一块与屏幕一样大小的存储区域 ,作为缓冲屏幕,同时将下一帧要显示的图像绘制到这个缓冲屏幕上面,在显示的时候将虚拟屏幕中的数据直接复制到可见视频缓存区里。由于图形绘制过程是在不可见的虚拟屏幕中进行.所以可以消除屏幕的闪烁 、抖动。 以虚拟仪表图形信息显示为例:在具体的实现中,让仪表指针、设备状态、报警等的过程在Off_Screen(后台)实现。即在绘制当前图形信息的时候 。调用函数uglPageDrawSet()另外指定绘制下一图形操作的页面(缓冲)。在绘制完成后,再通过 uglPagevisableSet()把Off-Screen的图像拷贝到前台,即实现图像的刷新,这就可以有效的解决图像闪烁 、抖动问题。具体实现如下 :
page[0]=UGL_PAGE_ZERO—ID;
page[1]=uglPageCreate(devId);  //建双缓冲页
bgBitmap="uglBitmapCreate" (devld,&XNBPDib,UGL_DIB_INIT_DATA,0,UGL_NULL);//由位图数据信息创建位图
uglDefaultBitmapSet(gc,bgBitmap);//设 置 bgBitmap为画图背景
uglPageDrawSet(devld,page[1]);//设置活动的绘图双缓冲(页)
uglBitmapBh (gc, DisplayBitmap,0,0,16,16, UGL_DEFAULT_ID,0,0);
… … … … . .
//在变化的位置绘制的位图和其它具体图形绘制
uglPageVisibleSet(devld,page[1]);//在前台显示
uglPageDrawSet(devId,page[O]);//后台绘制下一图像
uglPageVisibleset(devId,page[0]);  像在前台显示
uglPageDrawSet(devId,page[1]);后台绘制下一图像
… … … … … … … … … …

uglPageDestroy(devld,page[1]);//释放缓冲

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML vxworks 双缓冲  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(1360) | 回复(0)

发表于 2006/9/27 11:30:09

54

关于投票

windML取输入键盘值

今天一早上都在取键盘的键值,发现每次取之前要先将ugl设备释放,然后再注册才能取得新的键值,不知道是我程序的问题还是必须这么做???有没有能帮我解决的呢?我是在msg.data.keyboard.key;中取键值的,键值是1-48,2-49......9-57,'.-46,回车-13,'-'-45,'+'-43,'*'-47,'/'-46,ESC-27,上-57351,下-57352,左-57349,右-57350,F1-61185.......END-57345,HOME-57344,DEL-127,PageUP-57347,PageDown-57348

 

系统分类: 嵌入式  |  用户分类: windML  |  标签: windML input  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(1755) | 回复(3)

发表于 2006/9/26 22:56:47

54

关于投票

在windML上移植ucgui和vxworks延时小结

    最近在vxworks上移植ucgui。也许有些人会问不是有zinc吗?为什么还要自己去移植呢?据说(不是官方的消息),风河公司在除了vxworks5.5以后抛弃了zinc,也就是说vxworks5.5以及以上的版本已经不支持zinc了。我也试了,不行,装不上。要想更好的处理图形就只好自己移植了。

   我是这样做的:首先,将windML配置好然后编译,在能跑他自带ugldemo之后,利用找到往屏幕帖图的地址0x40800000(我用的工控板符合vesa标准)。这样我们就可以将所有的图形按位图的形式贴到屏幕上去了。当然将上层的一大堆东西转化成位图还要看看哦。然后就是鼠标,键盘等的消息了。无非就是将数据结构转化一下。不过发现有些键的键值(esc,enter等)找不到,只好把每个键值截获下来自己定义宏.....

工作还在进行中,以后再慢慢的发吧!

2006.9.28

今天一早上都在搞定时器,vxworks的看门狗定时器是定时一次到时间就结束,而且时间到触发一个函数。现在我要将定时器做成循环定时而且要触发一个消息。这样做就可以在我的主程序里查询所有的消息(包括定时,键盘,鼠标,系统消息等),便于对各个事件的管理。我做完以后会将我的程序发到这里。有兴趣的一起讨论啊!

下午做的定时器发现不能循环定时,每次定时完以后,再掉开启函数就不再走了!!!单步往下走也看不出来,不知道为什么?郁闷啊!!!

2006.9.29

在网上看见一篇很好的帖子,那上来跟大家分享。帖子中也有我的一些理解。希望大家能理解的更深刻:)

   编程过程中,出于需要,大家或多或少要用到定时/延时。VxWorks下提供了几种定时/延时机制,根据收集的一些资料和VxWorks相关文档,在学习和上机实验的基础上,对它们的使用以及我所遇到的问题做一个总结,希望对大家能有所帮助。不正确之处,恳请斧正。
1 taskDelay
   taskdelay()提供了一个简单的任务睡眠机制,也常用于需要定时/延时机制的应用中。它的格式是STATUS taskDelay(int ticks /* number of ticks to delay task */),可以看出使用该函数实现延时的单位为tick(一般系统中一个tick都是ms级的)(编程的时候如果想用毫秒可以这样:#define TICK_MS (1000/SYS_CLK_RATE)/*每tick的毫秒数*/)。在VxWorks下可以这样使用taskDelay()函数:(利用函数sysClkRateSet()可以改变系统的时钟速率)。在POSIX中有一个与taskdelay()相对应的函数――nanosleep()(下文中有介绍)。这两个函数仅仅是延时单位不同,效果是相同的。
   利用taskdelay(),可以将调用的任务移动到具有相同优先级的就绪队列尾部。特别的,可以通过调用taskdelay(0),将cpu交给系统中其他相同优先级的任务。延时为0的调用只能用于taskdelay()中,nanosleep()认为这种调用是错误的。
   taskdelay()会导致调用的任务在指定的延时期间(以ticks计数)放弃cpu,使任务处于DELAY状态(因此,其不能用于中断服务程序中)。通常其受到任务调度的影响,但在等待一些与中断无关联的外部条件时,其是有用的。如果调用的任务受到一个信号,指出其没有被阻塞或被忽略,taskDelay()将返回ERROR,并在信号处理程序运行后设置errno为EINTR。
2 WatchDog
   VxWorks提供了一个看门狗定时器(watchdog timer)机制,利用提供的函数,任何任务都可以创建一个看门狗定时器,经过指定的延时后,实现在系统时钟ISR的上下文中运行指定的程序。在VxWorks中,看门狗定时器作为系统时钟中断服务程序的一部分来维护。因此,与看门狗定时器相联系的函数运行在系统时钟中断级。在使用看门狗定时器实现定时/延时时,经过指定的时间,应用程序中断在系统时钟中断优先级上面,然而,如果内核不能立即执行这个中断服务程序,这个任务就被排队到tExcTask 工作队列中去,处在 tExcTask 工作队列中的任务的优先级为 tExcTask (通常是 0)。对于使用看门狗定时器的中断服务程序,仍然必须遵守一般的ISR所要遵守的规则。
  通过wdCreate( )可以创建一个看门狗定时器。调用wdStart()启动定时器,延时参数以tick为单位,同时还要指定定时完成后要调用的程序。如果你的应用程序需要多个看门狗函数,使用wdCreate( )为每个需求产生独立的看门狗ID。因为对于给定的看门狗ID,只有最近的wdStart()有效。在指定的tick计数到达之前,要取消一个看门狗计时器,可以调用wdCancel()实现。
   每调用一次wdStart(),看门狗定时器只执行一次。对于一些要求周期性执行的应用程序。要获得该效果,定时器函数本身必须通过递归调用wdStart()来重新启动定时器。(目前我还没搞定,总是定时一次就退出了,找到原因再发上去)利用看门狗定时器,调用的任务不会被阻塞:因为wdStart()调用是立即返回的。使用该方法实现延时,关联函数所受限制太大,好多系统调用不可用,郁闷也…
3 timer(POSIX)
3.1 timer
   VxWorks提供IEEE的POSIX 1003.1b标准定时器接口。使用这种定时器机制,在指定的时间间隔后,任务向自身发信号。定时器是建立在时钟和信号之上。程序可以创建、设置和删除一个定时器。当定时器到达期限,将向任务发送默认的信号(SIGALRM)。
使用timer的一般流程:
/* 创建定时器 */
if(timer_create(CLOCK_REALTIME,0,&mytimer)==ERROR)
return(ERROR);
/* 用户程序与定时器相连 */
if(timer_connect(mytimer,(VOIDFUNCPTR)my_handler,0)==ERROR)
return(ERROR);
/* 设置定时器值 */
if(timer_settime(mytimer,0,&value,0)==ERROR)
    return(ERROR);
/* 一段延时 */
。。。。。。
/* 删除定时器 */
if (timer_delete(mytimer)==ERROR)
    return(ERROR);
    在使用定时器时,容易忽略定时结束后任务向自身发信号这一处理步骤。即在定时结束后,要向创建定时器的任务发送信号,如果此时任务已不存在,定时程序将不能执行,提示的错误是“interrupt: timerWdHandler : kill failed (timer=******,tid=******,errno=0x16)”(有一个《关于timer(定时器)中几个函数的疑问!》帖子,其中提到该问题)。在上机时,我设置了一个较长时间的定时器,在创建定时器任务中使用相等的延时操作(taskDelay()、nanosleep()随便哪个都行),此时程序正常运行,定时结束后正确地执行关联到定时器的程序;再次运行,在定时结束前,我在shell下删除掉创建定时器的任务,定时结束后又出现上述的错误。因此,使用POSIX定时器时,一定要注意不能让创建定时器的任务在触发定时程序之前结束,否则。。。准备reset吧
3.2 nanosleep()
    函数nanosleep()的功能与VxWorks提供的taskDelay()类似,nanosleep()允许指定以秒和纳秒为单位的定时/延时时间,taskDelay()以tick作为定时/延时时间。两者只是延时单位不同,而不是精度不同,都由系统时钟频率决定。与taskDelay()一样,使用nanosleep()实现定时/延时的任务也受调度的影响,在实际操作中一定要注意这一点。使用nanosleep()时,定时参数使用的是结构itimerspe中的it_value,可以指定it_value中的秒和纳秒为定时/延时时间。函数的使用较为简单,不再赘述。
4 其它
    使用带有超时值timeout的msgQReceive()、semTask()也可以实现延时(有使用这种方式来进行延时的人吗?不有吗?有吗?不有吗?有吗?不有吗?。。。)。
    该方法将阻塞任务,让其等待超时,利用该方法实现延时可以使用函数semTask(…,timeout)、msgQReceive(…,…,…,timeout)。调用任务被放进阻塞队列中(注意,使用semTask和msgQReceive时,time的值不能是NO_WAIT,如果指定NO_WAIT的话,将立即返回,也就达不到延时的效果了^_^)。如果你希望任务不被阻塞,还能继续执行,sorry,此法不行,使用看门狗吧。
当阻塞的任务满足继续执行的条件后,将被放入ready队列。这里要注意的是,任务被放入ready队列并不意味着立刻就被执行。想想看,如果比它高优先级的任务正在占用资源,或也在等资源,那么…延时将是不确定的。


2006.9.30

今天我把定时器的程序减到最精练,终于可以循环定时了。估计是因为调用了某些系统的资源引起任务的阻塞。明天将程序发上来.....

系统分类: 嵌入式  |  用户分类: windML  |  标签: wingML ucGUI 定时器  |  来源: 无分类  | 

点击查看原文

发表评论 阅读全文(3217) | 回复(8)

Total , Page /