Introduction to VxWorks Programming API

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.

Leave a Comment