1. Official Program Guide
Located in the installation directory: \docs\vxworks\guide\index.html
2. Common Libraries:
#include "taskLib.h"
#include "msgQLib.h"
#include "semLib.h"
#include "ioLib.h"
#include "wdLib.h"
#include "logLib.h"
#include "socket.h"
3. IO System: ioLib.h
1. The IO devices in the system, including keyboard, serial port, files, etc., are accessed through a unified interface. The first step is usually to obtain a file descriptor, then perform read/write or settings work, and finally close the descriptor.
create: create a file
open: obtain the descriptor of a file or device
read: read from a file or device
write: write to a file or device
ioctl: set parameters
close: close the file descriptor
remove: delete a file
2. Memory File
memDrv( ) – initialize a pseudo memory device
memDevCreate( ) – create a pseudo memory device
memDevCreateDir( ) – create a group of pseudo memory devices
memDevDelete( ) – delete a pseudo memory device
Init() {
uchar_t buffer[1024];
int fd;
memDrv( );
memDevCreate("/mem/mem1", buffer, sizeof(buffer));
if ((fd = open("/mem/mem1", O_RDWR, 0644)) != ERROR) {
write(fd, &data, sizeof(data));
... ...
close(fd);
}
memDevDelete("/mem/mem1");
}
3. Implementing multiple IO monitoring through the Select function: selectLib.h
When waiting for multiple IO, we can use the Select function, where fd is the file descriptor:
int select(
int width,
fd_set * pReadFds,
fd_set * pWriteFds,
fd_set * pExceptFds,
struct timeval * pTimeOut
)
Several macros:
FD_SET(fd, &fdset) sets the listening bit for fd
FD_CLR(fd, &fdset) clears the listening bit for fd
FD_ZERO(&fdset) clears all listening bits
FD_ISSET(fd, &fdset) checks if fd has data
Example, where MAX means taking the maximum value:
Init() {
struct fd_set readFds;
int fds[4];
int width;
fds[0] = open(..);
... ...;
fds[3] = open(..);
width = MAX(fds[0], ... ... , fds[3])+1;
FD_ZERO(&readFds);
FD_SET(fds[0], &readFds);
... ...;
FD_SET(fds[3], &readFds);
if (select(width, &readFds, NULL, NULL, NULL) == ERROR) {
close(fds[0]);
... ...;
close(fds[3]);
return;
}
for(i=0; i<width; &readfds))="" (fd_isset(fds[i],="" ...="" ...;="" <="" code="" i++)="" if="" {="" }=""></width;>
4. Programming in a Multi-task Environment:
1. Task Control: taskLib.h
taskSpawn( ) – create a task
taskInit( ) – initialize a task, user specifies stack and PCB address
taskActivate( ) – activate an initialized task
exit( ) – end in a task (ANSI)
taskDelete( ) – delete a task
taskDeleteForce( ) – force delete, even if protected
taskSuspend( ) – suspend a task
taskResume( ) – resume a suspended task
taskRestart( ) – restart a task
taskPrioritySet( ) – change task priority
taskPriorityGet( ) – read task priority
taskLock( ) – prohibit task scheduling
taskUnlock( ) – allow task scheduling
taskSafe( ) – protect task from deletion
taskUnsafe( ) – remove protection
taskDelay( ) – delay
taskIdSelf( ) – get the ID of the current task
taskIdVerify( ) – check if task ID exists
taskTcb( ) – get the address of the task control block (TCB)
taskOptionsSet( ) – change task options
taskOptionsGet( ) – get current task options
taskRegsGet( ) – get register information from the task TCB
taskRegsSet( ) – set register information in the task TCB
taskName( ) – get task name
taskNameToId( ) – get ID by name
taskIdDefault( ) – set default task ID
taskIsReady( ) – check if task is ready
taskIsSuspended( ) – check if task is suspended
taskIdListGet( ) – get the list of active tasks
2. Task Mutual Exclusion – Semaphore: semLib.h
semGive( ) – release a semaphore
semTake( ) – obtain a semaphore, will block
semFlush( ) – make all tasks blocked on this semaphore ready
semDelete( ) – delete a semaphore
1) Binary Semaphore: semBCreate
Can be used for task synchronization and mutual exclusion, but commonly used for task synchronization
2) Mutex Semaphore: semMCreate
Semaphore specifically for task mutual exclusion, protecting critical resources
3) Counting Semaphore: semCCreate
Access control for multi-instance resources
3. Task Synchronization
1) Message Queue: msgQLib.h
Message queue
msgQCreate( ) – create message queue
msgQDelete( ) – delete message queue
msgQSend( ) – send message
msgQReceive( ) – receive message, will block after calling
msgQNumMsgs( ) – get the number of messages in the message queue
Init() {
if ((msgQID = msgQCreate(8, 1, MSG_Q_FIFO)) == NULL) {
printf("Message queue create failed!\n");
}
}
taskSend() {
if (OK != msgQSend(msgQID, "A", 1, NO_WAIT, MSG_PRI_NORMAL)) {
printf("Message send failed!");
}
}
taskReceive() {
uchar_t ch;
msgQReceive(msgQID, &ch, 1, WAIT_FOREVER);
printf("Received from msgq: %c ", ch);
}
2) Pipe: ioLib.h, the system includes the pipe driver component by default
pipeDevCreate( ) – create pipe
pipeDevDelete( ) – delete pipe
Since pipes belong to IO, they can be monitored using Select, while message queues cannot.
Init() {
if (pipeDevCreate("/pipe/mypipe", 8, 1) != OK) {
printf("/pipe/mypipe create failed!\n");
}
if ((semMID = semMCreate(SEM_Q_FIFO)) == NULL) {
printf("Mutex semaphore create failed!\n");
}
}
taskSend() {
int pd;
if ((pd = open("/pipe/mypipe", O_WRONLY, 0644)) == ERROR) {
printf("Open pipe failed!");
}
if (semTake(semMID, NO_WAIT) == ERROR) {
printf("Pipe in use!");
}
write(pd, "a", 1);
semGive(semMID);
close(pd);
}
taskReceive() {
int pd;
uchar_t ch;
if ((pd = open("/pipe/mypipe", O_RDONLY, 0644)) == ERROR) {
printf("Open pipe failed!");
}
if (read(pd, &ch, 1) > 0) {
printf("Received from pipe: %c", ch);
}
}
3) Binary Semaphore
Init() {
if ((semBID = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) {
printf("Binary semaphore create failed!\n");
}
}
taskSend() {
semGive(semBID);
}
taskReceive() {
semTake(semBID, WAIT_FOREVER);
}
4) Events: eventLib
To send an event, specify the target task’s ID
eventReceive( ) – wait for an event
eventSend( ) – send an event
eventClear( ) – clear the current task’s event.
taskSend() {
if (OK != eventSend(taskReceiveID, 0x00000001)) {
printf("Event send failed!");
}
}
taskReceive() {
UINT32 Ev;
if (OK != eventReceive(0x00ffffff, EVENTS_WAIT_ANY, WAIT_FOREVER, &Ev)) {
printf("eventReceive Error!\n");
} else {
Ev &= 0x00000001;
if (Ev) {
printf("Event %d received!", Ev);
}
}
}
5. Watchdog: wdLib.h
The system provides a soft watchdog timer, which is also simple to use:
wdCreate( ) – create watchdog
wdDelete( ) – delete
wdStart( ) – start
wdCancel( ) – stop
Init() {
if ((wdID = wdCreate()) == NULL) {
printf("Watch dog create failed!\n");
}
}
task() {
if (OK != wdStart(wdID, sysClkRateGet()*5, proc_wd, 0)) {
printf("Watch dog start failed!\n");
}
}
int proc_wd(int param) {
logMsg(... ...);
}
6. Network Programming: sockLib.h
Using standard BSD Socket, communicate using TCP or UDP protocol.
socket( ) – open socket
bind( ) – bind to port, address, etc.
listen( ) – listening mode
accept( ) – allow the other party’s connection
connect( ) – actively connect to the remote end
connectWithTimeout( ) – connect function with timeout feature
sendto( ) – send
send( ) – send
sendmsg( ) – send
recvfrom( ) – receive
recv( ) – receive
recvmsg( ) – receive
setsockopt( ) – set socket parameters
getsockopt( ) – get socket parameters
getsockname( ) – get socket name
getpeername( ) – get the name of the connected peer
shutdown( ) – close connection
7. Exception Handling
1. Error Numbers: errnoLib.h
32-bit signed integer, 1~500 is occupied by the system, others are available for programs. For example:
#define MEMORY_LEAK 0x20005
errnoGet( ) – get the current task’s error number
errnoOfTaskGet( ) – get the specified task’s error number
errnoSet( ) – set the current task’s error number
errnoOfTaskSet( ) – set the specified task’s error number
2. Signals: sigLib.h
signal( ) – specify the entry function for the signal
raise( ) – send a signal to the current task
kill( ) – send a signal to the specified task
task1() {
signal(30, proc_sig);
}
task2() {
kill(task1ID, 30);
}
void proc_sig(int param) {
logMsg("Error message...");
}
8. Interrupts: iv.h
x86’s interrupts 0x0~0xf correspond to vxWorks’ interrupts 0x20~0x2f
Taking interrupt 9 as an example:
Initialize interrupt:
intConnect( INUM_TO_IVEC(9+0x20), Int9Handler, 0);
sysIntEnablePIC(9);
Interrupt function prototype:
void Int9Handler(int Param);
Explanation of takeSpawn and semCreate
int taskSpawn(
char *name, /* Task name */
int priority, /* Task priority, vxWorks seems to have a total of 255, and scheduling adopts priority preemption, with round-robin scheduling for the same priority */
int options, /* Some characteristics of the task, such as VX_SUPERVISOR_MODE 0x0001 OBSOLETE: tasks always in supervisor mode */
int stackSize, /* Size of stack to be allocated */
FUNCPTR entryPt, /* Task handling function */
int arg1, /* Parameters needed by the task handling function */
int arg2,
int arg3,
int arg4,
int arg5,
int arg6,
int arg7,
int arg8,
int arg9,
int arg10
)
SEM_ID semBCreate(
int options, /* Characteristics of the semaphore, such as whether the blocking queue type of the semaphore is priority-based or FIFO */
SEM_B_STATE initialState /* Initial state of the semaphore: empty or full, used for synchronization or resource mutual exclusion */
)
The returned value is the ID of the semaphore, which is actually a pointer to the semaphore.