vxWorks编程API
|
一、官方的Program Guide 3、通过Select函数实现多个IO监听:selectLib.h 五、Watch dog :wdLib.h
|
takeSpawn与semCreate说明
int taskSpawn
(
char *name, /*任务名*/
int priority, /*任务优先级,vxWorks好像共255个,而且调度采用优先级抢占式,同优先级轮换式的调度方式*/
int options, /*任务的一些特性,例如VX_SUPERVISOR_MODE 0x0001 OBSOLETE: tasks always in sup mode*/
int stackSize, /* 需要申请堆栈的大小*/
FUNCPTR entryPt, /*任务处理函数*/
int arg1, /*任务处理函数需要的参数*/
int arg2,
int arg3,
int arg4,
int arg5,
int arg6,
int arg7,
int arg8,
int arg9,
int arg10
)
SEM_ID semBCreate
(
int options, /*信号量的特性,例如信号量的阻塞队列类型为优先级优先行还是FIFO*/
SEM_B_STATE initialState /* 信号量的初始状态:empty or full,用来同步或者资源互斥*/
)
返回的值就是改信号量的ID,实际上就是指向信号量的指针啦
部分函数详细说明
1.taskSpawn 创建(产生并激活)新任务
int taskSpawn
(
char *name,
int priority,
int options,
int stackSize,
FUNCPTR entryPt,
int arg1,
int arg2, int arg3,
int arg4, int arg5,
int arg6, int arg7,
int arg8, int arg9,
int arg10
)
函数运行成功返回任务ID号,否则为ERROR。
任务可选项的几种模式如下表:
名 称
值
描 述
VX_FP_TASK
VX_NO_STACK_FILL
VX_PRIVATE_ENV
VX_UNBREAKABLE
VX_SUPERVISOR_MODE
0x8
0x100
0x80
0x2
运行带浮点的协处理器
不使用0xee填充堆栈
用私有环境运行任务
断点失效
用户任务常用值
2.taskDelete 删除一个任务
STATUS taskDelete
(
int tid
)
删除指定ID号的任务,并释放任务所占有的内存
3.taskDelay 延迟任务
STATUS taskDelay
(
int ticks
)
任务延迟为某一任务休眠一定时间提供了简单的处理方法,一般用于任务的周期性循环执行。当输入参数为NO_WAIT(其值为零)时,表示将所延迟的任务切换到同一优先级就绪队列的尾部。
4.taskSuspend 任务悬置
STATUS taskSuspend
(
int tid
)
5.taskResume 恢复任务
STATUS taskResume
(
int tid
)
6.msgQCreate 创建并初始化消息队列
#include
MSG_Q_ID msgQCreate
(
int maxMsgs,
int maxMsgLength,
int options
)
消息入列方式有两种:MSG_Q_FIFO 先进先出 ,按时间先后顺序考虑;MSG_Q_PRIORITY 按消息优先级考虑。
7.msgQSend 向一消息队列发送消息包
STATUS msgQSend
(
MSG_Q_ID msgQId,
char * buffer,
UINT nBytes,
int timeout,
int priority
)
该函数将长度为nBytes的缓冲区buffer消息包发向消息队列msgQId. 如果任务正在等待接收该消息队列的消息包,消息将立即被送到第一个等待的任务。如果没有任务等待此消息,消息包被保留在消息队列中。
参数timeout指明:当消息队列已满时,等待消息队列有空间时所等待的时间。超过该时间还没空间可用的话,消息包被舍弃。它有两个特殊值:NO_WAIT(0)立即返回,不管消息包是否被发送;WAIT_FOREVER(-1)一直等待消息队列有空间可用。
参数priority指明发送的消息的优先级,可能值有:MSG_PRI_NORMAL(0)正常优先级,将消息置于消息队列的尾部;MSG_PRI_URGENT(1)紧急消息,将消息置于消息队列的首部。
8.msgQReceive 接收消息
int msgQReceive
(
MSG_Q_ID msgQId,
char * buffer,
UINT maxNBytes,
int timeout
)
该函数从消息队列msgQId接收消息,将其拷贝到最大长度为maxNBytes的缓冲区buffer。如果消息包长度超过maxNBytes,多余部分被舍弃。等待时间timeout有两个特殊值: NO_WAIT(0)立即返回;WAIT_FOREVER(-1)一直等待消息队列有消息可取。
9.msgQDelete 删除一个消息队列
STATUS msgQDelete
(
MSG_Q_ID msgQId
)
任何因发送或接收该消息队列的消息的任务都将解阻,并返回错误errno.
10. wdCreate 创建看门狗定时器
WDOG_ID wdCreate(void)
11. wdStart 启动定时器
STATUS wdStart
(
WDOG_ID wdId,
int delay,
FUNCPTR pRoutine,
int parameter
)
12. wdCancel 取消一个当前工作的定时器
STATUS wdCancel
(
WDOG_ID wdId
)
该函数只是让定时器的延迟值为零来取消其工作。
13. wdDelete 删除定时器
STATUS wdDelete
(
WDOG_ID wdId
)
14. semBCreate 创建并初始化二进制信号量
SEM_ID semBCreate
(
int options,
SEM_B_STATE initialState
)
信号量初始化状态值有两种:SEM_FULL(1)或SEM_EMPTY(0)。选项参数指明被阻塞任务的入列方式:基于优先级(SEM_Q_PRIORITY)和先进先出(SEM_Q_FIFO).
15. semCCreate 创建并初始化计数信号量
SEM_ID semCCreate
(
int options,
int initialCount
)
选项参数指明被阻塞任务的入列方式:基于优先级(SEM_Q_PRIORITY)和先进先出(SEM_Q_FIFO).
16. semGive 给出信号量
STATUS semGive
(
SEM_ID semId
)
17. semTake 获得信号量
STATUS semTake
(
SEM_ID semId
int timeout
)
如果任务在规定时间内未得到信号量,函数semTake返回错误。等待时间值WAIT_FOREVER和NO_WAIT分别表示一直等待和不等待。
18. semDelete 删除信号量
STATUS semDelete
(
SEM_ID semId
)
该函数释放与此信号量相关的资源,所有等待此信号量的任务解阻。
semMCreate( ) 分配并初始化一个互斥信号量
semCCreate( ) 分配并初始化一个计数信号量
semDelete( ) 终止一个自由的信号量
semTake( ) 占有一个信号量
semGive( ) 释放一个信号量
semFlush( ) 解锁所有等待信号量的任务
semBCreate( ), semMCreate( ), and semCCreate( )返回一个信号量ID作为其它后续任务使用该信号量的的句柄。当一个信号量被创建,它的队列(queue)类型就被确定。等待信号量的任务队列以优先级的高低排列(SEM_Q_PRIORITY),或者一先到先得的方式排列(SEM_Q_FIFO).
· 当一个Semaphore创建时,指定了任务队列的种类
A. semBCreat( SEM_Q_PRIORITY, SEM_FULL), SEM_Q_PRIORITY 指明处于等待状态的任务在等待队列中以优先级的顺序排列
B. semBCreat(SEM_Q_FIFO,SEM_FULL), SEM_Q_FIFO指明 处于等待状态的任务在等待队列中以先进先出的顺序排列
1. 二进制信号量( binary)
Taking a Semaphore
Giving a Semaphore
互斥进程(Mutual Exclusion)
互斥信号量有效的内锁对共享资源的进入,与屏蔽中断(disabling interrupts)和优先级锁定(preemptive locks)相比,二进制信号量将互斥的范围限制在仅与其有关的资源上。从技术上说,创建一个信号量来保护(guarding)资源。信号量初始化位可用的(FULL)。
当一个Semaphore创建时,指定了这个semaphore是用在解决互斥还是用来同步任务
A. semBCreat( SEM_Q_FIFO, SEM_FULL) , SEM_FULL 指明用于任务间互斥.
SEM_ID semMutex;
semMutex = semBCreate (SEM_Q_PRIORITY, SEM_FULL);
当一个任务要进入资源,首先要得到一个信号量(take that semaphore),只要有任务在使用这个信号量,其它的要进入资源的任务要停止执行(blocked from execution),当这个任务完成了对资源的使用,它会释放信号量,允许另一个任务来使用资源。
semTake (semMutex, WAIT_FOREVER);
. . critical region, only accessible by a single task at a time .
semGive (semMutex);
同步协调进程(Synchronization)
B. semBCreat(SEM_Q_FIFO,SEM_EMPTY), SEM_EMPTY 指明用于任务间同步.
#include "vxWorks.h"
#include "semLib.h"
SEM_ID syncSem;
init ( int someIntNum )
{
intConnect (INUM_TO_IVEC (someIntNum), eventInterruptSvcRout, 0);
syncSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY);
taskSpawn ("sample", 100, 0, 20000, task1, 0,0,0,0,0,0,0,0,0,0);
}
task1 (void)
{ ...
semTake (syncSem, WAIT_FOREVER);
printf ("task 1 got the semaphore/n");
...
}
eventInterruptSvcRout (void)
{ ...
semGive (syncSem);
...
}
semTake(semID,time out)--------有Semaphore空闲,就Take, 如果没有,由time out 定,超时则向下执行
2. 互斥信号量
互斥信号量是一个特殊的二进制信号量,设计用于优先级继承,安全删除和回归。
互斥信号量的使用基本和二进制信号量是类似的。但有以下不同:
· 仅仅被用做互斥。
· 只能被使用它的任务释放.(It can be given only by the task that took it.)
· ISR 不能释放它。
· 不能使用函数semFlush( )。
优先级反转(Priority Inversion)
优先级反转是指一个任务等待比它优先级低的任务释放资源而被阻塞,如果这时有中等优先级的就绪任务,阻塞会进一步恶化。优先级继承技术可用来解决优先级反转问题。
Priority inversion arises when a higher-priority task is forced to wait an indefinite period of time for a lower-priority task to complete.
优先级继承(Priority Inheritance)
优先级继承可用来解决优先级反转问题。当优先级反转发生时,优先级较低的任务被暂时地提高它的优先级,使得该任务能尽快执行,释放出优先级较高的任务所需要的资源。
Priority Inheritance
The mutual-exclusion semaphore has the option SEM_INVERSION_SAFE, which enables a priority-inheritance algorithm. The priority-inheritance protocol assures that a task that owns a resource executes at the priority of the highest-priority task blocked on that resource. Once the task priority has been elevated, it remains at the higher level until all mutual-exclusion semaphores that the task owns are released; then the task returns to its normal, or standard, priority. Hence, the "inheriting" task is protected from preemption by any intermediate-priority tasks. This option must be used in conjunction with a priority queue (SEM_Q_PRIORITY).
3. 计数信号量(Counting Semaphores)
计数信号量是任务同步和互斥的另一种实现方式.计数信号量除了保留信号量被释放的次数以外和二进制信号量是一样的。每次信号量被释放(gaven)一次,计数增加;每次信号量被占用(taken)一次,计数减少;当计数减少为0时,要求得到信号量的任务被阻塞(blocked)。二进制信号量是如果一个信号量被释放,有一个任务阻塞等待,则这个任务就被unblock.而计数信号量如果一个信号量被释放,没有任务阻塞等待,则计数增加。这说明一个被释放两次的计数信号量可以被占用(taken)两次,没有阻塞。
Counting semaphores are useful for guarding multiple copies of resources. For example, the use of five tape drives might be coordinated using a counting semaphore with an initial count of 5, or a ring buffer with 256 entries might be implemented using a counting semaphore with an initial count of 256. The initial count is specified as an argument to the semCCreate( ) routine.
Counting Semaphore Example
--------------------------------------------------------------------------------
Semaphore Call
Count after Call
Resulting Behavior
--------------------------------------------------------------------------------
semCCreate( )
3
Semaphore initialized with initial count of 3.
semTake( )
2
Semaphore taken.
semTake( )
1
Semaphore taken.
semTake( )
0
Semaphore taken.
semTake( )
0
Task blocks waiting for semaphore to be available.
semGive( )
0
Task waiting is given semaphore.
semGive( )
1
No task waiting for semaphore; count incremented.
--------------------------------------------------------------------------------
消息队列(Message queues)
现实的实时应用由一系列互相独立又协同工作的任务组成。信号量为任务间同步和联锁提供了高效机制。在VxWorks中,用于但一CPU任务之间通信主要(primary)的机制是消息队列。
Full Duplex Communication Using Message Queues
消息队列允许一定数量不同长度的消息进行排列。任何任务或中断服务程序(ISR)能够发送消息给消息队列。任何任务可以从消息队列接受消息。多任务可以从同意消息队列发送和接受消息。两个任务之间的全双工(Full-duplex)通信需要针对不同方向的两个消息队列。
消息队列函数介绍
msgQCreate( ) 创建斌初始化一个消息队列
msgQDelete( ) 终止并释放一个消息队列
msgQSend( ) 发送一个消息到消息队列
msgQReceive( ) 从消息队列接受一个消息
消息队列是由函数msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY)创建。它的参数MAX_MSGS指定了消息队列中可允许最多可以排列的消息数和每个消息允许的最大的字节数MAX_MSG_LEN。
一个任务或中断服务程序(ISR)用函数msgQSend( )发送一个消息到消息队列。如果没有任务等待消息队列的消息,这个消息被添加消息缓存的队列里。如果某些任务已经在等待消息队列中的消息,消息立刻被传递给第一个等待的消息的任务。
一个任务用函数msgQReceive( )从消息队列得到一个消息。如果消息队列缓存中有消息存在,第一个消息立刻出列并回到调用处(caller).如果没有消息存在,则任务(calling task)停止(blocks)并被添加到等待消息的任务队列中。这个等待的任务队列按照优先级或先进先出(FIFO)规则排列,这个规则有消息队列创建时所指定。
等待时间限制(time out)
msgQSend( ) 和 msgQReceive( )都有时间限制参数。当发送一个消息,如果消息队列缓存这时没有空间,这个参数指定允许等待的时间(ticks数),直到队列缓存有空间来接收消息。当接收消息时,如果消息队列没有消息,这个参数指定允许等待的时间(ticks数),直到消息队列有消息。
#include "vxWorks.h"
#include "msgQLib.h"
#define MAX_MSGS (10)
#define MAX_MSG_LEN (100)
MSG_Q_ID myMsgQId;
task2 (void)
{
char msgBuf[MAX_MSG_LEN];
if (msgQReceive(myMsgQId, msgBuf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR)
return (ERROR);
printf ("Message from task 1:/n%s/n", msgBuf);
}
#define MESSAGE "Greetings from Task 1"
task1 (void)
{
if ((myMsgQId = msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY))
== NULL)
return (ERROR);
if (msgQSend (myMsgQId, MESSAGE, sizeof (MESSAGE), WAIT_FOREVER,
MSG_PRI_NORMAL) == ERROR)
return (ERROR);
}
管道(Pipes)
管道对消息队列提供了一个可供选择的接口,VxWorks的I/O系统。管道是虚拟的I/O设备,由驱动pipeDrv管理。函数pipeDevCreate()创建一个管道设备,这个调用指定管道的名字,能被排列的最多的消息数,和每个消息允许的长度。
status = pipeDevCreate ("/pipe/name", max_msgs, max_length);
被创建的管道是一个通常命名(named)的I/O设备,任务能用标准的I/O函数打开,读,写管道,并能调用ioctl例程。当任务试图从一个空的管道中读取数据,或向一个满的管道中写入数据时,任务被阻塞。和消息队列一样,ISR可以向管道写入,但不能从管道读取。
做为I/O设备,管道提供了消息队列所没有的重要特性,调用select()