Skip to main content

VxWorks UART Programming: Serial Port Configuration and I/O

·622 words·3 mins
VxWorks UART Serial Port Embedded Systems RTOS Driver Development
Table of Contents

VxWorks UART Programming: Serial Port Configuration and I/O

UART (Universal Asynchronous Receiver/Transmitter) remains a fundamental interface for debugging, control, and device communication in embedded systems. While the programming model is broadly consistent across operating systems, VxWorks exposes UART functionality through its I/O system and ioctl interface.

This guide provides a practical walkthrough of configuring serial ports, performing read/write operations, and implementing a complete UART task in VxWorks.

🛠️ Serial Port Configuration
#

Opening the Serial Device
#

Serial ports in VxWorks are exposed as device files:

fd = open("/tyCo/0", O_RDWR, 0);
  • /tyCo/0: First serial device
  • O_RDWR: Enables both read and write access

Device naming may vary depending on BSP and hardware configuration.

Configuring Mode and Buffers
#

Basic configuration is performed using ioctl():

ioctl(fd, FIOSETOPTIONS, OPT_RAW);
ioctl(fd, FIOFLUSH, 0);
  • OPT_RAW: Disables line processing (raw data mode)
  • FIOFLUSH: Clears input/output buffers

Common ioctl Commands
#

Command Purpose
FIOBAUDRATE Set baud rate
FIOGETOPTIONS Retrieve current options
FIOSETOPTIONS Apply device options
FIOREAD Query unread bytes
FIOWRITE Query pending output
FIOFLUSH Clear buffers
FIOCANCEL Cancel I/O operations

Setting Line Parameters
#

Hardware-level configuration is applied using:

ioctl(fd, SIO_HW_OPTS_SET, CS8 | PARENB | CLOCAL | CREAD);

Key flags:

  • CS8: 8 data bits
  • PARENB: Enable parity
  • PARODD: Odd parity (optional)
  • CLOCAL: Ignore modem control
  • CREAD: Enable receiver

🔄 UART Read and Write Operations
#

Once configured, UART communication uses standard POSIX-style APIs:

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

Parameters
#

  • fd: File descriptor from open()
  • buffer: Data buffer
  • maxbytes / nbytes: Transfer size

These APIs integrate seamlessly with the VxWorks I/O system.

💻 Complete UART Example
#

The following example demonstrates a UART task that periodically sends data while coordinating access via shared memory and semaphores.

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

#define DEV_NAME "/tyCo/2"
#define MAX_BUF_SIZE 20
#define SHARE_DATA_LENGTH 20

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

char *comdata;
SEM_ID mutexComdata;

int set_serial(int fd);

void taskUart(void)
{
    int ret;
    int fd = open(DEV_NAME, O_RDWR, 0);
    UNIX_CLOCK_STRUCT w_buff;

    if (fd < 0)
        printf("open failed.\n");

    if (set_serial(fd) < 0)
        printf("serial config failed.\n");

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

        ioctl(fd, FIOFLUSH, 0);
        bzero(&w_buff, sizeof(w_buff));
        memcpy(&w_buff, comdata, sizeof(w_buff));

        if (write(fd, &w_buff.sec, sizeof(w_buff.sec)) < 0)
            printf("write failed.\n");
        else
            printf("write success: %d\n", w_buff.sec);

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

int set_serial(int fd)
{
    if (fd < 0)
        return -1;

    if (ioctl(fd, FIOBAUDRATE, 9600) < 0)
        return -1;

    if (ioctl(fd, SIO_HW_OPTS_SET, CREAD | CS8 | CLOCAL) < 0)
        return -1;

    return 0;
}

🔍 Key Implementation Insights
#

Synchronization
#

  • Use semaphores (semTake, semGive) to protect shared data
  • Prevent concurrent access to UART resources

Buffer Management
#

  • Clear buffers before transmission (FIOFLUSH)
  • Avoid stale or partial data reads

Task-Based Design
#

  • Run UART logic in a dedicated task
  • Control execution rate using taskDelay()

⚠️ Common Pitfalls
#

Incorrect Device Name
#

  • /tyCo/x mapping depends on BSP configuration
  • Verify using system device listing

Misconfigured Line Settings
#

  • Incorrect parity or data bits can corrupt communication
  • Ensure both ends match configuration

Blocking Behavior
#

  • read() may block if no data is available
  • Consider non-blocking modes or timeouts

✅ Best Practices
#

  • Always validate file descriptors and return values
  • Use raw mode for binary communication
  • Encapsulate configuration into reusable functions
  • Separate UART logic from application logic
  • Log errors for easier debugging in production systems

📌 Conclusion
#

UART programming in VxWorks builds on a familiar POSIX-style model while leveraging powerful configuration via ioctl. By combining proper device setup, robust synchronization, and task-based design, developers can implement reliable serial communication for debugging, control, and data exchange.

This foundation can be extended to support interrupt-driven drivers, DMA-based transfers, or higher-level communication protocols in more advanced embedded systems.

Related

PCI-RapidIO Bridge Driver Design on VxWorks
·731 words·4 mins
VxWorks RapidIO PCI Device Driver Embedded Systems
RTOS Containers for the Intelligent Edge
·567 words·3 mins
VxWorks Container
Meet the VxWorks RTOS
·14 words·1 min
VxWorks VxWorks 7