XTOS / OPEN SOURCE REAL-TIME SYSTEMOPEN SOURCE · VERSION 0.9.0 · BUILD FROM SOURCE
DocsSystem layers

System layers

Kernel, user-space, SDK, and application responsibilities; BCI and CSV data paths.

On this page

Real-time kernel

kernel/linux contains versioned Linux 6.6.0-rt15 source, not a placeholder downloaded at build time. kernel/xtos_defconfig is merged after the architecture defconfig and enables CONFIG_PREEMPT_RT=y, CONFIG_HIGH_RES_TIMERS=y, CONFIG_HZ_1000=y, module support, and /proc/config.gz. The final configuration after olddefconfig is authoritative; a fragment alone does not establish that an option is enabled for the target kernel.

Inspect the running kernel in the guest BusyBox shell.
uname -r
cat /sys/kernel/realtime
zcat /proc/config.gz | grep '^CONFIG_PREEMPT_RT='
zcat /proc/config.gz | grep '^CONFIG_HZ='

The expected value of /sys/kernel/realtime is 1. CONFIG_HZ_1000 describes the kernel tick configuration, not a promise of 1 ms thread response or sensor timing accuracy. High-resolution timers, device clocks, and application windows are separate parameters.

Scheduling helper

kernel/linux/kernel/sched/xtos_sched.c implements per-CPU locked priority queues and helper functions for enqueue, dequeue, and selection.

It explicitly is not a sched_class; Linux scheduling selection, task_struct layout, and the syscall ABI remain unchanged.

CONFIG_XTOS_SCHED=y in the default configuration builds it into the kernel, rather than replacing Linux SCHED_FIFO, SCHED_RR, or SCHED_OTHER with an XTOS policy.

The helper xtos_set_cpu_affinity stores advisory metadata and does not migrate Linux tasks. xtos_set_deadline stores deadline_ns without establishing deadline scheduling guarantees.

Application-side libxtos-rt uses standard sched_setscheduler, sched_setaffinity, and mlock/munlock; there is no direct SDK syscall channel to these kernel helpers.

BCI acquisition

drivers/xtos/bci contains the xtos_bci_core character-device core, xtos_bci_buffer ring-buffer module, and openbci_cyton serdev driver.

The driver targets an 8-channel, 24-bit ADC with a default 250 Hz sampling rate, sets serial baud to 115200 with flow control disabled, and matches device-tree compatible="openbci,cyton".

Loading the module registers a driver; an actual device and correct serdev/device-tree binding are still required for acquisition.

The receive callback assembles serial bytes into 33-byte packets, extracts signed 24-bit ADC values at the source’s channel offsets, sign-extends them, scales them with 64-bit integer arithmetic into s32 nanovolts, and writes them to the ring buffer.

The implemented formula is raw × 4500000000 / (24 × 2^23), where 4500000000 is the reference voltage in nanovolts and 24 is the fixed gain.

A driver comment says microvolts, but the integer formula determines the actual representation; these bytes are not float microvolts.

The source includes start/stop, channel enable, and sampling-rate branches for 250, 500, 1000, and 2000 Hz.

These branches express implementation intent, not proof that every rate works correctly on a board with this serial configuration. calibrate currently returns as a placeholder, and impedance checking is unsupported.

Real packet layout, rate-command behavior, sample loss, and units belong in hardware bring-up, not in a list of already verified device capabilities.

UAPI and samples

kernel/linux/include/uapi/linux/xtos_bci.h defines the integer-only ioctl ABI, with corresponding SDK declarations in sdk/libxtos-bci/include/xtos/bci_uapi.h. Device information uses integer mV for input_range_mv, integer kΩ for impedance arrays, and 64-bit statistics counters. Raw sample bytes are a separate data interface. Integer control structures do not establish that the library converts raw sample values correctly.

This documentation therefore describes the BCI SDK as a session and acquisition-control interface while identifying sample representation as requiring correction and validation.

Before routing hardware data into DSP, define raw type, endianness, channel order, unit conversion, and frame timestamps, then test values against known inputs.

START/STOP, SET_RATE, and SET_CHANNEL ioctls are acquisition controls, not robot, AR/VR, or general feedback-actuator APIs.

User-space boot

The x86_64 build uses system/busybox_defconfig to generate static BusyBox 1.37.0 and install applet links under /bin. system/rootfs/init runs as PID 1, mounts proc, sysfs, devtmpfs, devpts, and /dev/shm, then prints the kernel release and realtime flag.

It starts /bin/sh in a loop by default.

Without xtos.selftest=1 it does not run system tests automatically, and it starts no default network service.

Guest pathx86_64 contents
/usr/lib, /usr/include/xtosStatic .a archives and headers for all three SDKs; this does not imply an in-guest compiler.
/usr/libexec/xtosThe static test_rt, test_spsc, and test_signal executables.
/usr/binxtos-selftest, xtos-eeg-pipeline, xtos-signal-benchmark, and bci_test.
/lib/modules/<kernelrelease>Kernel modules matching the image and depmod dependency indexes.
/usr/share/xtos/fixtures/valid.csvThe artificial EEG pipeline CSV fixture, not a real-device recording.

ARM64/RISC-V64 scripts start from BusyBox defconfig, enable static linking, create /etc/inittab and /init→sbin/init, and offer a /bin/sh console; tests are installed under /bin. verify_guest_* separately copies the rootfs and replaces /init with xtos-guest-check.

This does not change the normal boot image.

Checks power off afterward, so an interactive prompt must not be assumed after DONE.

CSV and hardware

xtos-eeg-pipeline reads two-channel, 250 Hz nanovolt data from a CSV file, creates an SPSC queue of capacity 16, pushes and pops each frame, and checks sequence and data integrity.

It opens no BCI device, calls no ioctl, and does not traverse the kernel BCI ring buffer.

Optional bandpass processing uses double values in libxtos-signal in user space; CSV replay does not substitute for serdev acquisition.

Only the default x86_64 system includes this tool and fixture.
xtos-eeg-pipeline --input /usr/share/xtos/fixtures/valid.csv
xtos-eeg-pipeline --input /usr/share/xtos/fixtures/valid.csv \
  --bandpass 5 40 --dump-filtered /run/filtered.csv

The CSV header is # xtos-eeg-v1,channels=2,sample_rate_hz=250,unit=nanovolt; data rows are timestamp_ns,ch0_nv,ch1_nv with no additional column-name row.

The expected inter-frame interval is 4000000 ns with 1% tolerance, and timestamps must increase strictly.

JSON p50/p95/p99_latency_ns measures only the queue push/pop region, excluding CSV parsing, bandpass processing, hardware input, inference, and feedback.

Application responsibilities

  1. Input contract: choose CSV or device input and record units, channels, sample rate, frame timestamps, and loss policy. Do not connect interfaces with incompatible representations directly.
  2. Compute contract: preallocate working buffers, bound windows and queue capacity, and define behavior for scheduling-permission failures and timeouts. Library APIs existing do not establish bounded execution time for the whole application.
  3. Output contract: models, inference threads, result consumers, actuators, and feedback safety policies belong to the application. The public kernel guarantees neither recognition accuracy nor control safety.

Public references at commit dd313955ad57542bcd2af8827157d1bbd0cf5e83: kernel/xtos_defconfig, kernel/linux/kernel/sched/xtos_sched.c, kernel/linux/drivers/xtos/bci/devices/openbci_cyton.c, kernel/linux/include/uapi/linux/xtos_bci.h, sdk/libxtos-rt/src/rt.c, sdk/libxtos-bci/src/session.c, tools/xtos-eeg-pipeline/pipeline.c, system/rootfs/init, and the three build_system scripts.