SDK
Builds, linking, data formats, and call order for three C libraries.
On this page
Libraries and version
XTOS provides a user-space SDK for Linux real-time threads. The libraries provide scheduling and memory helpers, signal-processing baselines, and BCI character-device sessions. The application owns thread layout, input validation, device configuration, and recovery; linking the SDK does not enable real-time policy or establish a hardware-to-algorithm validation path.
This page follows README.md, SDK headers, and implementations at public OpenXTOS commit dd313955ad57542bcd2af8827157d1bbd0cf5e83. Uncommitted changes are outside this documented version.
| Library and headers | Role | Prerequisites |
|---|---|---|
| libxtos-rt: xtos/rt.h, xtos/spsc.h | sched_* for the calling thread, CPU affinity, mlock, and a fixed-capacity SPSC queue. | Linux; policy and memory locking depend on permissions and limits. No BCI device. |
| libxtos-signal: xtos/signal.h | Timestamps, one-sided DFT power, causal IIR, and SSVEP/P300 research features. | Valid numeric arrays and a sample rate; link libm. Synthetic or CSV input is sufficient. |
| libxtos-bci: xtos/bci.h, xtos/bci_uapi.h | open/read/ioctl/mmap session wrappers; device capability comes from the kernel driver. | A matching driver, a registered /dev/xtosN, hardware, and read/write permission. |
Build and link
Run these commands from the OpenXTOS repository root. An SDK build does not require a kernel build. Each library produces a static archive and shared objects. Use the full archive path to avoid a missing runtime path or an older shared library. Headers come from each library’s include directory.
make -C sdk/libxtos-rt
make -C sdk/libxtos-signal
make -C sdk/libxtos-bci
make -C sdk/libxtos-rt test
make -C sdk/libxtos-signal testThe public libxtos-bci/Makefile has all, clean, install, and uninstall, but no test target; tests/test_samples is not committed. A local test directory is not a clone-time feature. Building BCI does not validate device acquisition.
gcc -std=c11 -Wall -Wextra -Werror -O2 \
-Isdk/libxtos-signal/include signal-example.c \
sdk/libxtos-signal/libxtos-signal.a -lm -o signal-exampleLink caller objects or source, then the SDK archive, then dependencies; put signal’s -lm last. An RT application using pthread supplies -pthread. For cross builds, CC, AR, headers, archives, application, and target architecture must match; do not reuse a stale .a from another architecture.
ABI macros are in sdk/<library>/include/xtos/*_version.h. Current shared objects are libxtos-*.so.1.0 with SONAME libxtos-*.so.1. Check headers, SONAMEs, and the target driver UAPI together; matching versions do not remove format or capability differences.
Data and ownership
| Object | Units and constraints | Ownership and lifetime |
|---|---|---|
| xtos_sample_frame | timestamp_ns is nonzero nanoseconds; samples_nv has channels int32 nanovolt values; the application defines sequence and quality_flags. | push deep-copies samples; pop writes caller storage and points frame.samples_nv at it. |
| signal | Arrays use double, sample rate is Hz, and P300 windows are milliseconds; the application keeps amplitude units consistent. | The caller provides arrays, results, and filter state; FFT/SSVEP allocate temporary heap memory. |
| Locked memory | length is a positive byte count, not a sample count. | alloc_locked returns caller-owned memory; free_locked requires the original pointer and length. |
| BCI session and mapping | Input range is integer mV and impedance is integer kΩ; the public float read interface has a format gap. | The session owns fd and mmap; get_fd/get_mmap_buffer return borrowed resources invalid after destroy. |
Choose the acquisition unit before DSP conversion. Convert int32 nanovolts to double microvolts numerically by dividing by 1000.0; do not cast the pointer to double* or float*. The public BCI implementation does not convert. A float* read_samples signature does not mean microvolts. CSV can enter signal without the BCI driver.
Calls and errors
- Prepare: inspect device capability, sample rate, and channels; create queues; allocate and touch working memory; initialize one filter per channel.
- Threads: set scheduling and affinity in the worker that will run, then read the policy back. The two settings are not a rollback transaction.
- Run: the acquisition thread checks time and frame boundaries before push; one consumer pops, converts units, filters continuously, and extracts window features. Define the full-queue drop or load-reduction policy.
- Stop: request stop and join workers before destroying queues, sessions, or locked memory. Do not destroy objects while push/pop or borrowed mappings are in use.
Most int interfaces return 0 or -1 with errno; pointer interfaces return NULL on failure. Read errno only after failure; success does not clear an old value. Save it before printing, cleanup, or another call. A void destructor cannot report cleanup failure.
Real-time calls
SCHED_FIFO/SCHED_RR does not bound every library call. Queue push/pop do not allocate; creation and destruction do. FFT calls calloc for two n-element arrays, and SSVEP allocates a power array. Device read can block; ioctl can wait in the driver or serial I/O; printf and file I/O can block.
Keep high-priority work to acquisition and frame transfer; run window algorithms and logging separately. Measure worst service time, queue level, rejections, and sequence gaps. mlock reduces paging risk only for its range; it does not guarantee zero faults, jitter, or a deadline.
Sources: sdk/libxtos-rt/src/rt.c and spsc.c; sdk/libxtos-signal/src/signal.c; sdk/libxtos-bci/src/session.c.
Validate deterministic input under ordinary scheduling first, then permission failures, full queues, anomalous timestamps, and the target device.
QEMU boot and SDK tests do not replace physical acquisition, latency measurement, or electrode-quality validation.