WeChat Official Account: North South North There is a path through the mountains, diligence is the way; the sea of learning is endless, skillful craft is the boat!
1. Official Program Guide
Located in the installation directory: \docs\vxworks\guide\index.html
2. Common Libraries:
#include "taskLib.h" /* Task */
#include "msgQLib.h" /* Message Queue */
#include "semLib.h" /* Semaphore */
#include "ioLib.h" /* IO */
#include "wdLib.h" /* Watchdog */
#include "logLib.h" /* Log Output */
#include "socket.h" /* Network Socket */
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 setting operations, and finally close the descriptor.
-
creat: Create a file
-
open: Obtain the descriptor for 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 Files
-
memDrv( ) – Initialize pseudo memory device
-
memDevCreate( ) – Create pseudo memory device
-
memDevCreateDir( ) – Create a group of pseudo memory devices
-
memDevDelete( ) – Delete 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 Listening with Select Function: selectLib.h
When waiting for multiple IOs, we can use the Select function, where fd is the file descriptor:
int select(
int width, /* Maximum fd, or directly FD_SETSIZE (2048) */
fd_set * pReadFds, /* Set of read fds */
fd_set * pWriteFds, /* Set of write fds */
fd_set * pExceptFds, /* Not supported by vxWorks, NULL */
struct timeval * pTimeOut /* Wait time, NULL = forever */
)
Several macros:
-
FD_SET(fd, &fdset) Set the listening bit for fd
-
FD_CLR(fd, &fdset) Clear the listening bit for fd
-
FD_ZERO(&fdset) Clear all listening bits
-
FD_ISSET(fd, &fdset) Check 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(..); /* Open IO */
width = MAX(fds[0], … … , fds[3])+1; /* Max fd +1 */
/* FOREVER {*/
FD_ZERO(&readFds); /* Set fd_set structure */
FD_SET(fds[0], & readFds);… …; FD_SET(fds[3], & readFds);
if (select(width, &readFds, NULL, NULL, NULL) == ERROR) { /* Listen */
close(fds[0]); … …; close(fds[3]);
return;
}
for(i=0; i<width; i++)
if (FD_ISSET(fds[i], &readFds)) {
… …; /* Perform read/write operations */
}
}
/* } */
}
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 already initialized task
-
exit( ) – End in a task (ANSI)
-
taskDelete( ) – Delete a task
-
taskDeleteForce( ) – Force deletion, 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( ) – Disable task scheduling
-
taskUnlock( ) – Enable task scheduling
-
taskSafe( ) – Protect task from deletion
-
taskUnsafe( ) – Remove protection
-
taskDelay( ) – Delay
-
taskIdSelf( ) – Get current task ID
-
taskIdVerify( ) – Verify 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 task TCB
-
taskRegsSet( ) – Set register information in task TCB
-
taskName( ) – Get task name
-
taskNameToId( ) – Get ID from name
-
taskIdDefault( ) – Set default task ID
-
taskIsReady( ) – Check if task is ready
-
taskIsSuspended( ) – Check if task is suspended
-
taskIdListGet( ) – Get list of active tasks
2. Task Mutual Exclusion – Semaphore: semLib.h
-
semGive( ) – Release a semaphore
-
semTake( ) – Acquire 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 is often used for task synchronization.
2) Mutex Semaphore: semMCreate is specifically used for mutual exclusion of tasks, protecting critical resources.
3) Counting Semaphore: semCCreate is for access control of multi-instance resources.
3. Task Synchronization
1) Message Queue: msgQLib.h Message Queue
-
msgQCreate( ) – Create a message queue
-
msgQDelete( ) – Delete a message queue
-
msgQSend( ) – Send a message
-
msgQReceive( ) – Receive a message, blocks after calling
-
msgQNumMsgs( ) – Get the number of messages in the queue
Init() {
/* Create message queue */
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); /* Here the task will block */
printf("Received from msgq: %c ", ch);
}
2) Pipe: ioLib.h, the system defaults to include the pipe driver component
-
pipeDevCreate( ) – Create a pipe
-
pipeDevDelete( ) – Delete a pipe
Since the pipe belongs to IO, it can use Select for listening, while the message queue cannot use Select.
Init() {
/* Create pipe */
if (pipeDevCreate("/pipe/mypipe", 8, 1) != OK) {
printf("/pipe/mypipe create failed!\n");
}
/* Create mutex semaphore */
if ((semMID = semMCreate(SEM_Q_FIFO)) == NULL)
{
printf("Mutex semaphore create failed!\n");
}
}
taskSend() {
int pd; /* Pipe descriptor */
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; /* Pipe descriptor */
uchar_t ch;
if ((pd = open("/pipe/mypipe", O_RDONLY, 0644)) == ERROR) {
printf("Open pipe failed!");
}
if (read(pd, &ch, 1) > 0) { /* Here the task will block */
printf("Received from pipe: %c", ch);
}
}
3) Binary Semaphore
Init() {
/* Create binary semaphore */
if ((semBID = semBCreate(SEM_Q_FIFO, SEM_EMPTY)) == NULL) {
printf("Binary semaphore create failed!\n");
}
}
taskSend() {
semGive(semBID);
}
taskReceive() {
semTake(semBID, WAIT_FOREVER); /* Here the task will block */
}
4) Events: eventLib Send events to specify the target task ID
-
eventReceive( ) – Wait for an event
-
eventSend( ) – Send an event
-
eventClear( ) – Clear the current task’s event.
taskSend() {
if (OK != eventSend(taskReceiveID, 0×00000001)) {
printf("Event send failed!");
}
}
taskReceive() {
UINT32 Ev;
if (OK != eventReceive(0×00ffffff, EVENTS_WAIT_ANY, WAIT_FOREVER, &Ev)) {
printf("eventReceive Error!\n");
}
else {
Ev &= 0×00000001;
if (Ev) {
printf("Event %d received!", Ev);
}
}
}
5. Watchdog: wdLib.h
The system provides a soft watchdog timer, which is also easy to use:
-
wdCreate( ) – Create a watchdog
-
wdDelete( ) – Delete
-
wdStart( ) – Start
-
wdCancel( ) – Stop
Init() {
/* Create watchdog */
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 Use standard BSD sockets to communicate using TCP or UDP protocols.
-
socket( ) – Open a socket
-
bind( ) – Bind to port, address, etc.
-
listen( ) – Listening mode
-
accept( ) – Allow the other party’s connection
-
connect( ) – Actively connect to a remote
-
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 Number: errnoLib.h
32-bit signed integer, 1~500 are reserved by the system, others are available for internal programs. For example:
#define MEMORY_LEAK 0×20005
-
errnoGet( ) – Get current task’s error number
-
errnoOfTaskGet( ) – Get specified task’s error number
-
errnoSet( ) – Set current task’s error number
-
errnoOfTaskSet( ) – Set 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 a specified task
task1() {
signal(30, proc_sig); /* Register signal number 30 */
/* raise(30); */
}
task2() {
kill(task1ID, 30);
}
void proc_sig(int param) {
logMsg("Error message…");
}
8. Interrupts: iv.h
x86 interrupts 0×0~0xf correspond to vxWorks interrupts 0×20~0×2f. Taking interrupt number 9 as an example: initialize the interrupt:
intConnect( INUM_TO_IVEC(9+0×20), Int9Handler, 0); /* Bind interrupt function */
sysIntEnablePIC(9); /* Enable interrupt number 9 */
Interrupt function prototype:
void Int9Handler(int Param); /* Note do not call blocking functions in interrupt functions */
Click “Read the original text” to access more VxWorks resources