Skip to content
Open-source embedded library

DYNAMIXEL Protocol 2.0in portable C

DXL2-C turns a noisy half-duplex byte stream into validated DYNAMIXEL packets, and your replies back into bytes on the wire — with no heap, no RTOS and code that passes MISRA C:2012.

  • No heap
    No RTOS
  • MISRA C:2012
    0 violations
  • 100 % line &
    branch coverage
  • Apache-2.0
    open source
Isometric illustration: the DXL2-C chip filters a noisy bus and sends clean packets to three servos
The problem

One wire, many servos, no second chance

DYNAMIXEL devices share a single half-duplex line. Every byte can be lost or corrupted, every node must frame, check and answer packets exactly as the specification says — on a microcontroller with a few kilobytes of RAM and, often, a safety argument to make.

Noisy, shared bus

Bytes arrive in any chunking, with noise and gaps. DXL2-C finds headers in the stream, checks Length and CRC, removes byte stuffing and resynchronizes by itself.

  • CRC-16
  • Byte stuffing
  • Resync

Tight embedded budgets

About 550 bytes of RAM per bus and a fixed, measured stack. No allocation, no globals, no OS: the same code runs bare metal, under an RTOS and on a PC.

  • Static memory
  • Bare metal
  • Zephyr

Code you can certify

Zero MISRA C:2012 violations, a documented deviation register, 100 % line and branch coverage and static analysis in CI — reviewable in an afternoon.

  • MISRA C
  • Cppcheck
  • CodeQL
What you get

A small library with a clear job

Two layers and ten functions: a codec for the wire format and a link that connects it to any transport through two callbacks.

10public functions
≈ 550 BRAM per bus
≤ 600 Bstack on Cortex-M4
0MISRA C:2012 violations

Quick start

A minimal device in one file

Two callbacks connect the library to your hardware: a write function for the UART and a handler for received packets. This device answers PING with its model number and firmware version.

#include "dxl2.h"

static struct dxl2_link link;

static int uart_write(void* context, const uint8_t* data, size_t length)
{
    (void) context;
    return board_uart_write(data, length); /* 0 on success */
}

static void on_packet(const struct dxl2_packet* packet, void* context)
{
    static const uint8_t ping_reply[] = {0x06, 0x04, 0x26}; /* model 1030, firmware 38 */

    (void) context;
    if ((packet->id == 1U) && (packet->instruction == DXL2_INST_PING))
    {
        (void) dxl2_link_send_status(&link, 1U, DXL2_ERR_NONE, ping_reply, sizeof(ping_reply));
    }
}

int main(void)
{
    const struct dxl2_link_config config = {.write = uart_write, .handler = on_packet};

    (void) dxl2_link_init(&link, &config);
    for (;;)
    {
        uint8_t bytes[32];
        const size_t count = board_uart_read(bytes, sizeof(bytes));

        dxl2_link_receive(&link, bytes, count);
    }
}

board_uart_write() and board_uart_read() stand for your board's UART driver. The examples are complete programs for bare metal, Zephyr and a PC serial port.

Find your way

If you want to… Read
Understand what the library does and does not do Introduction
Build it, run the tests, add it to your project Getting Started
Understand the layers, data flow and parser How It Works
Write a device or a controller with it Using the Library
Add instructions, transports or contribute Extending the Library
Look up the bytes on the wire Protocol
Look up a function API Reference
Read everything offline or print it PDF user manual
SystemFromScratch®

Part of an open-source embedded portfolio

DXL2-C is developed by Anton Vynohradov under SystemFromScratch® — embedded software and hardware built from the first schematic to certification.

SystemFromScratch® is a registered trademark. DYNAMIXEL and ROBOTIS are trademarks of ROBOTIS Co., Ltd. DXL2-C is an independent implementation of the publicly documented protocol and is not affiliated with or endorsed by ROBOTIS.