Skip to main content

CAN Programming Under VxWorks

·642 words·4 mins
CAN VxWorks
Table of Contents
APP - This article is part of a series.
Part 10: This Article

CAN Programming Under VxWorks: A Practical Guide
#

Introduction
#

CAN bus is a robust vehicle bus standard designed to allow microcontrollers and devices to communicate with each other in applications without a host computer. VxWorks, known for its reliability in embedded systems, supports CAN through various drivers. This article will guide you through setting up, configuring, and programming CAN communications under VxWorks with detailed explanations in code comments.

Understanding CAN in VxWorks
#

VxWorks provides CAN support through device drivers integrated into the Board Support Package (BSP). These drivers manage low-level CAN controller interactions. Developers use VxWorks’ CAN API for higher-level tasks.

Step-by-Step CAN Programming
#

  1. Initialize CAN Device:
#include <vxWorks.h>
#include <can.h>

int main() {
    // CAN device identifier - might be different based on your hardware setup
    CAN_ID canId;
    
    // Open the CAN device. "/can/0" represents the first CAN controller on the board.
    int fd = canDevCreate("/can/0", &canId);
    if (fd < 0) {
        printf("Failed to initialize CAN device\n");
        return -1;
    }
    // 'fd' now holds the file descriptor for this CAN device, used for all subsequent operations.
}
  1. Configure CAN Bus:
// Structure to hold CAN configuration parameters
CAN_CONFIG config;

// Set the bit rate to 500 kbps (common for many automotive applications)
config.bitRate = 500000;

// Sample point at 87.5% of the bit time for noise immunity
config.samplePoint = 875;

// Synchronization jump width - how much the bit timing can be adjusted to synchronize with other nodes
config.sjw = 1;

// Apply configuration to the CAN device
if (canIoctl(fd, CAN_CMD_SET_CONFIG, (int)&config) != OK) {
    printf("Failed to configure CAN bus\n");
    return -1;
}
  1. Send CAN Messages:
// Prepare a CAN frame for transmission
CAN_FRAME txFrame;
txFrame.id = 0x123; // CAN message identifier (arbitrarily chosen here)
txFrame.dlc = 8;    // Data Length Code, specifying 8 bytes of data

// Fill the data bytes. Here, we're just using a simple increment for demonstration.
for (int i = 0; i < 8; i++) {
    txFrame.data[i] = i;
}

// Send the CAN frame. The '1' indicates we're sending one frame.
if (canWrite(fd, &txFrame, 1) != 1) {
    printf("Failed to send CAN message\n");
}
  1. Receive CAN Messages:
CAN_FRAME rxFrame;

// Loop to continuously check for received messages
while (1) {
    // Read one CAN frame. 'canRead' returns the number of frames read or an error code.
    int bytesRead = canRead(fd, &rxFrame, 1);
    if (bytesRead == 1) {
        printf("Received CAN message with ID: 0x%X\n", rxFrame.id);
        // Print each byte of the received data
        for (int i = 0; i < rxFrame.dlc; i++) {
            printf("Byte %d: %X\n", i, rxFrame.data[i]);
        }
    } else if (bytesRead < 0) {
        printf("Error reading CAN message\n");
        break; // Exit loop on error
    }
}
  1. Cleanup:
{
// Close the CAN device when done
canDevDelete(fd);
return 0;
}

Advanced Considerations
#

Interrupts
#

// Define an interrupt handler for CAN events
void canInterruptHandler(int vector) {
    // Check for new messages or handle errors. This might involve reading status registers.
}

// Connect the ISR to the CAN interrupt vector. CAN_INTERRUPT_VECTOR should be defined according to your hardware setup.
intConnect(INUM_TO_IVEC(CAN_INTERRUPT_VECTOR), canInterruptHandler, 0);

Error Handling
#

CAN_ERROR_STATUS errorStatus;
// Check for CAN bus errors like bit errors, stuff errors, etc.
canIoctl(fd, CAN_CMD_GET_ERROR_STATUS, (int)&errorStatus);
if (errorStatus.txErrorCounter > 127 || errorStatus.rxErrorCounter > 127) {
    printf("Warning: CAN bus approaching error state\n");
}

Bus Off Recovery
#

if (errorStatus.busOff) {
    // If the CAN controller goes into bus off state, reset it
    canIoctl(fd, CAN_CMD_RESET, 0);
    printf("CAN bus reset due to bus off condition\n");
}

Conclusion
#

This guide provides a thorough introduction to CAN programming under VxWorks, with detailed comments to help understand each step. Keep in mind that real-world applications might require additional considerations like message filtering, priority handling, or dealing with network load to ensure the CAN bus operates correctly and efficiently. Always consult your specific hardware’s documentation for any unique requirements or features.

APP - This article is part of a series.
Part 10: This Article

Related

Comparison of CPU Scheduling in VxWorks and LynxOS
·1986 words·10 mins
VxWorks CPU Scheduling LynxOS
Porting VxWorks Applications to Linux
·4315 words·21 mins
VxWorks Application Linux
VxWorks Integration
·713 words·4 mins
VxWorks VSB VIP TargetRTS