SDK
三个 C 库的构建、链接、数据格式和调用顺序。
本页目录
库与版本
XTOS 提供面向 Linux 实时线程的用户态 SDK。库包含调度与内存辅助、信号处理基线和 BCI 字符设备会话。应用负责线程划分、输入有效性、设备配置和失败恢复;链接 SDK 不会自动启用实时策略,也不会建立硬件到算法的验证链路。
内容依据 OpenXTOS 公开提交 dd313955ad57542bcd2af8827157d1bbd0cf5e83 的 README.md、SDK 头文件和实现;未提交修改不属于本文版本。
| 库与头文件 | 职责 | 前提 |
|---|---|---|
| libxtos-rt:xtos/rt.h、xtos/spsc.h | 当前线程的 sched_*、CPU 亲和性、mlock 和定容量 SPSC 队列。 | Linux;实时策略和锁页受权限与资源限制。无需 BCI 设备。 |
| libxtos-signal:xtos/signal.h | 时间戳、单边 DFT 功率、因果 IIR、SSVEP/P300 研究特征。 | 有效数值数组和采样率;链接 libm。可用合成数据或 CSV。 |
| libxtos-bci:xtos/bci.h、xtos/bci_uapi.h | open/read/ioctl/mmap 会话封装;设备能力由内核驱动决定。 | 匹配驱动、已注册的 /dev/xtosN、设备和读写权限。 |
构建与链接
以下命令在 OpenXTOS 仓库根目录执行。构建 SDK 不需要先构建内核。每个库生成静态归档和共享对象;静态归档用完整路径,避免运行时搜索路径缺失或误载旧库。头文件来自各库的 include 目录。
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 test公开 libxtos-bci/Makefile 只有 all、clean、install、uninstall,没有 test 目标;tests/test_samples 也未提交。不要把本地测试目录当作克隆后的功能。BCI 构建成功不等于设备采集成功。
gcc -std=c11 -Wall -Wextra -Werror -O2 \
-Isdk/libxtos-signal/include signal-example.c \
sdk/libxtos-signal/libxtos-signal.a -lm -o signal-example链接顺序为调用方对象或源文件、SDK 归档、依赖库;signal 的 -lm 放在最后。使用 pthread 的 RT 应用自行加 -pthread。交叉编译时 CC、AR、头文件、归档、应用和目标架构必须一致,不得复用其他架构的旧 .a。
ABI 宏在 sdk/<库>/include/xtos/*_version.h。当前共享库为 libxtos-*.so.1.0,SONAME 为 libxtos-*.so.1。头文件、SONAME 和目标驱动 UAPI 必须一起核对;版本号一致不能消除数据格式或设备能力差异。
数据与所有权
| 对象 | 单位与约束 | 所有权与生命周期 |
|---|---|---|
| xtos_sample_frame | timestamp_ns 是非零纳秒;samples_nv 是 channels 个 int32 纳伏值;sequence、quality_flags 由应用定义。 | push 深拷贝样本;pop 写入调用方数组,并令 frame.samples_nv 指向该数组。 |
| signal | 数组为 double,采样率为 Hz,P300 窗口为毫秒;幅值单位由应用统一。 | 调用方提供数组、结果和滤波状态;FFT/SSVEP 在内部临时分配堆内存。 |
| 锁页内存 | length 是大于 0 的字节数,不是样本数。 | alloc_locked 返回调用方拥有的块;free_locked 必须使用原指针和原长度。 |
| BCI 会话与映射 | 输入量程为整数 mV,阻抗为整数 kΩ;公开 float 读取接口有格式缺口。 | 会话拥有 fd 和 mmap;get_fd/get_mmap_buffer 返回借用资源,destroy 后失效。 |
先确定采集单位,再转换给 DSP。int32 纳伏转 double 微伏应数值除以 1000.0,不能把指针强转为 double* 或 float*。公开 BCI 实现不做转换;read_samples 的 float* 签名不表示数据已经是微伏。CSV 可绕过 BCI 驱动直接进入 signal。
调用与错误
- 准备:读取设备能力,检查采样率和通道数;创建队列,分配并触碰工作内存;每通道初始化滤波器。
- 线程:在实际工作的线程中设置调度和亲和性并读回策略。两项设置不是可回滚事务。
- 运行:采集线程检查时间和帧边界后 push;单消费者 pop,转换单位,连续滤波并计算窗口特征。队列满时明确丢弃或降载策略。
- 退出:请求停止并等待线程退出,再销毁队列、会话和锁页内存。push/pop 或借用映射仍在使用时不得销毁对象。
多数 int 接口成功返回 0,失败返回 -1 并设置 errno;指针接口失败返回 NULL。只在失败后读取 errno;成功不保证清除旧值。立即保存 errno,再打印、清理或调用其他函数。void 销毁函数不报告清理失败。
实时调用
SCHED_FIFO/SCHED_RR 不会使所有库调用有界。队列 push/pop 不分配;创建和销毁会分配或释放。FFT 为两个 n 长度数组调用 calloc,SSVEP 还分配功率数组。设备 read 可阻塞,ioctl 可在驱动或串口等待;printf 和文件 I/O 也可阻塞。
高优先级线程只做必要采集和帧传递;窗口算法和日志放到独立线程。测量最坏服务时间、队列水位、拒绝次数和序号缺口。mlock 只降低锁定范围的换页风险,不保证零缺页、零抖动或 deadline。
源码:sdk/libxtos-rt/src/rt.c、spsc.c;sdk/libxtos-signal/src/signal.c;sdk/libxtos-bci/src/session.c。
先在普通调度下用确定性输入验证,再检查权限失败、满队列、异常时间戳和目标设备。
QEMU 启动和 SDK 测试不替代实机采样、延迟测量或电极质量验证。