Skip to main content

VxWorks UART Programming: Serial Port Read and Write

·631 words·3 mins
VxWorks UART Serial Port Programming
Table of Contents

The process for serial port programming is generally consistent across major operating systems; only the function interfaces may differ. This article explains how to perform serial port read and write operations in VxWorks, including configuration commands and a complete example.

🛠️ Serial Port Configuration
#

Opening the Serial Port
#

fd = open("/tyCo/0", O_RDWR, 0);
  • "/tyCo/0": The device name for serial port 1.
  • O_RDWR: Opens the serial port for both reading and writing.

Setting Raw Mode and Clearing Buffers
#

In VxWorks, you can configure the serial port using the ioctl control interface.

ioctl(fd, FIOSETOPTIONS, OPT_RAW);
ioctl(fd, FIOFLUSH, 0);

Key parameters for ioctl:

Function Description
FIOBAUDRATE Set baud rate (arg = baud rate value).
FIOGETOPTIONS Get current device options.
FIOSETOPTIONS Set device options.
FIOGETNAME Get file name for descriptor.
FIOREAD Get unread input bytes.
FIOWRITE Get pending output bytes.
FIOFLUSH Clear input/output buffers.
FIOCANCEL Cancel read/write operations.

Setting Baud Rate and Line Options
#

Serial configuration such as baud rate, data bits, stop bits, and parity is also done via ioctl using the SIO_HW_OPTS_SET command:

ioctl(fd, SIO_HW_OPTS_SET, CS8 | PARENB | CLOCAL | CREAD);
Parameter Description
CLOCAL Ignore modem control lines.
CREAD Enable receiver.
CSIZE Data bits (CS5CS8).
STOP8 Two stop bits if set; otherwise one.
PARENB Enable parity checking.
PARODD Use odd parity (requires PARENB).

📖 Serial Port Read and Write
#

VxWorks supports direct use of the standard read() and write() calls:

int read(int fd, char *buffer, size_t maxbytes);
int write(int fd, char *buffer, size_t nbytes);

Parameters

  • fd: File descriptor returned by open().
  • buffer: Data buffer.
  • maxbytes / nbytes: Maximum number of bytes to read or write.

📝 Example Code
#

Example implementation of serial port read/write on VxWorks:

#include "vxWorks.h"
#include "stdio.h"
#include "ioLib.h"
#include "taskLib.h"
#include "sioLib.h"
#include "sdLib.h"
#include "semLib.h"
#include "msgQLib.h"

char wbuf[] = "hello";

#define DEV_NAME "/tyCo/2"
#define MAX_BUF_SIZE    20
#define SD_COMMDATA_NAME    "share_data"
#define SD_COMMDATA_MUTEX   "share_sem"
#define SHARE_DATA_LENGTH 20

typedef struct unix_clock_struct 
{
    UINT32 sec;    
    UINT32 msec;   
    UINT8 quality; 
} UNIX_CLOCK_STRUCT;

char *comdata;
int set_serial(int fd);
SEM_ID mutexComdata;

void taskUart(void);
int main(void)
{
    int ret;
    int sdCommId;
    char r_buff[MAX_BUF_SIZE];

    mutexComdata = semOpen(SD_COMMDATA_MUTEX, SEM_TYPE_MUTEX, SEM_FULL,
                SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE,
                OM_CREATE | OM_DELETE_ON_LAST_CLOSE, NULL);
    if (mutexComdata == NULL)
    {
        printf("ERROR: unable to open SD_COMMDATA_MUTEX\n");
        taskExit(0);
    }

    sdCommId = sdOpen(SD_COMMDATA_NAME, SD_LINGER, OM_CREATE, SHARE_DATA_LENGTH, 0,
                      SD_ATTR_RW | SD_CACHE_OFF, &comdata);
    if (sdCommId == NULL)
    {
        printf("ERROR: unable to open SD_COMMDATA\n");
        taskExit(0);
    }

    if ((ret = taskSpawn("taskUart", 90, 0x100, 20000, (FUNCPTR)taskUart,
                         0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) < 0)
    {
        printf("taskSpawn failed: ret = %d\n", ret);
    }

    return 0;
}

void taskUart(void)
{
    int ret;
    int fd = -1;
    UNIX_CLOCK_STRUCT w_buff;

    if ((fd = open(DEV_NAME, O_RDWR, 0)) < 0)
        printf("open %s failed.\n", DEV_NAME);

    if ((ret = set_serial(fd)) < 0)
        printf("ret = %d\nset_serial failed.\n", ret);

    while (1)
    {
        semRTake(mutexComdata, WAIT_FOREVER);

        if ((ret = ioctl(fd, FIOFLUSH, 0)) < 0)
            printf("ret = %d\nset FIOFLUSH failed.\n", ret);

        if (NULL == bzero(&w_buff, sizeof(w_buff)))
            printf("bzero failed.\n");

        if (NULL == memcpy(&w_buff, comdata, sizeof(w_buff)))
            printf("memcpy failed.\n");

        if (&w_buff != NULL)
        {
            if ((ret = write(fd, &w_buff.sec, sizeof(ret))) < 0)
                printf("ret = %d: write %s failed.\n", ret, DEV_NAME);
            else
                printf("write success: %d\n", w_buff.sec);
        }

        semGive(mutexComdata);
        taskDelay(sysClkRateGet() * 2);
    }
}

int set_serial(int fd)
{
    int ret;

    if (fd < 0)
    {
        printf("error: invalid fd = %d\n", fd);
        return -1;
    }

    if ((ret = ioctl(fd, FIOBAUDRATE, 9600)) < 0)
    {
        printf("ret = %d\nset baudrate failed\n", ret);
        return -1;
    }

    if ((ret = ioctl(fd, SIO_HW_OPTS_SET, CREAD | CS8 | CLOCAL)) < 0)
    {
        printf("ret = %d\nset SIO_HW_OPTS_SET failed.\n", ret);
        return -1;
    }

    return 0;
}

Summary:

This article demonstrated how to configure and use serial ports in VxWorks, including baud rate setup, ioctl configuration, and data transmission via read() and write(). The provided example can serve as a foundation for developing more complex UART communication applications.

Related

VxWorks Real-Time Performance Explained
·596 words·3 mins
VxWorks RTOS Real-Time Performance
RTOS Containers for the Intelligent Edge
·567 words·3 mins
VxWorks Container
Meet the VxWorks RTOS
·14 words·1 min
VxWorks VxWorks 7