Skip to content

Repository files navigation

FXLocalGPIO SDK

飞仙边缘控制器本地 GPIO 高性能访问库

本 SDK 为飞仙软件内部边缘控制器产品提供统一的 C/C# 编程接口,支持毫秒级响应、硬件原子批量操作和复杂的输入信号滤波。

🌟 核心特性

  • 高性能: 底层 C 语言直接操作内核 ioctl,零拷贝开销。
  • 输入滤波: 内置滑动窗口、计数、时间阈值三种工业级滤波算法,直接在底层线程处理,输出纯净信号。
  • 信号反相: 自动将硬件 Active Low 电平转换为应用层 Active High 语义(有信号=1,无信号=0)。
  • 原子操作: 支持 WriteBatch 硬件原子操作,完美同步控制多路信号(如步进电机方向+脉冲)。
  • 多架构支持: 提供 linux-arm (RK3506), linux-arm64 (RK3588), linux-x64 全平台支持。
  • CI/CD 集成: 完整的 GitLab CI 流水线,自动交叉编译并打包。

📍 引脚映射 (Pin Mapping)

外壳丝印顺序 (I00 ~ I19) 与 SDK 索引直接对应,已由 BSP 设备树原生支持

外壳丝印 (Silk Screen) SDK 索引 (API Index) 说明 (Note)
I00 - I19 0 - 19 直接映射,SDK 无额外重排

关于信号反相: 硬件采用 NPN 传感器 + 上拉电阻设计(Active Low),SDK 已自动处理反相。应用层读到 true 表示“有信号输入”,false 表示“无信号”。

适配硬件列表 (Supported Hardware)

硬件型号 (Driver Name) 芯片平台 IO 规格 说明
RK3506_20I12O Rockchip RK3506 20I 12O 推荐: 适用于设备树已修正的新系统 (1:1映射)
RK3506_20I12O_REMAP Rockchip RK3506 20I 12O 兼容: 适用于旧版设备树 (需 SDK 软件重排)

🚀 快速开始

1. 编译与构建

项目包含一键构建脚本,支持在 Linux (LXC/Docker) 或 macOS (Docker) 环境下编译。

# 赋予执行权限
chmod +x build_all.sh

# 编译 C# Wrapper 和 C Native Lib (自动识别环境)
./build_all.sh

构建产物将位于 release/linux-arm/ 目录下:

  • FXLocalGPIOSDKWrapper.dll: .NET 8.0 封装库
  • libfxlocalgpio.so: C 语言底层库 (ARM32)
  • ConsoleDemo: 可执行演示程序

2. C# 开发示例

引用 FXLocalGPIOSDKWrapper.dll,然后编写如下代码:

using FXLocalGPIO.SDK;

// 1. 初始化 (必须指定驱动名)
using var gpio = new FXLocalGPIOSDK("RK3506_20I12O");

// 2. 配置输入滤波 (可选)
gpio.ConfigureFilter(0, InputFilterConfig.StrongDebounce);

// 3. 注册输入变化事件
gpio.OnReadDataChanged += (index, val) => {
    Console.WriteLine($"Pin {index} changed to {val}");
};

// 4. 控制输出
gpio.Write(0, true); // 点亮 OUT0

// 5. 批量控制 (原子操作)
// 同时将 OUT0 置高, OUT1 置低
gpio.WriteBatch(0x03, 0x01); 

// 6. 保持程序运行
await Task.Delay(-1);

更多详细用法请参考 用户指南 (User Guide)

ReadBatch() 示例:

uint inputs = gpio.ReadBatch(); // 例如返回 0x00000015

// 解析各个输入:
bool in0 = (inputs & 0x01) != 0;  // true (bit0 = 1)
bool in1 = (inputs & 0x02) != 0;  // false (bit1 = 0)
bool in2 = (inputs & 0x04) != 0;  // true (bit2 = 1)
bool in4 = (inputs & 0x10) != 0;  // true (bit4 = 1)

关键特性

  • 统一接口: 屏蔽底层驱动差异(ioctl/mmap/sysfs),上层统一使用 Read/Write
  • 事件驱动: 内置高性能轮询线程(默认 1ms),提供类似 PLC 的输入中断体验。
  • 硬件原子操作: WriteBatch 使用内核 IOCTL,多个引脚在同一时钟周期内同时变化。
  • 自动资源管理: 完整支持 using 用于自动释放底层句柄。

何时使用 Batch?

场景 推荐方法 说明
单个 IO 控制 Write(idx, val) / Read(idx) 代码简洁,无需位运算
多个 IO 需要同时变化 WriteBatch(mask, val) 如:电机驱动的使能+方向必须同步翻转,避免中间状态
批量状态查询 ReadBatch() 一次系统调用获取所有输入,效率更高
高频轮询 ReadBatch() 减少 IOCTL 调用次数,降低 CPU 开销

示例:电机使能 + 方向同步切换

// 假设 out0 = 使能, out1 = 方向
// 错误做法(可能产生毛刺):
gpio.Write(0, true);   // 先使能
gpio.Write(1, true);   // 再设方向 — 中间有几微秒"使能但方向错误"的状态!

// 正确做法(原子操作):
gpio.WriteBatch(0x03, 0x03);  // 使能 + 正转 同时生效

设计理念:关于错误处理

您可能会注意到,本 SDK 与 FXEtherCATSDK 在错误处理上存在差异:

  • EtherCAT SDK: int ret = ReadSlave(..., out val); (返回错误码)
  • FXLocalGPIO: bool val = Read(0); (直接返回值,出错抛异常)

原因说明

  1. 场景不同:EtherCAT 是远程总线通讯,网络干扰导致偶发失败是常态,调用者需要频繁检查 ret 并重试。
  2. 本地 IO 稳定性:本地 GPIO 访问的是板载寄存器,极其稳定。只要设备初始化成功,运行时几乎不可能失败(除非硬件物理损坏)。
  3. 开发体验:对于本地 IO,强制用户每次都检查错误码会造成代码冗余。我们选择**“相信硬件”**,一旦发生底层错误(如返回 -1),SDK 会直接抛出 IOException,从逻辑上阻断错误的程序流程,更符合 .NET 现代开发习惯。

🛠️ 扩展指南:如何适配新机型

FXLocalGPIO 的设计是硬件无关的。fx_local_gpio.c 负责通用的业务逻辑(如轮询、滤波、回调分发),而具体的硬件操作通过 gpio_driver_t 接口抽象。

如果您需要支持新的硬件型号(例如 RK3507_32I32O),请按照以下步骤操作:

1. 实现驱动接口

src/drivers/ 目录下创建一个新的驱动文件(如 rk3507_drv.c),并实现 gpio_driver.h 中定义的接口:

// 定义驱动实例
gpio_driver_t rk3507_driver = {
    .name = "RK3507_32I32O",
    .init = rk3507_init,
    .deinit = rk3507_deinit,
    .set_output = rk3507_set_output,
    .set_batch_output = rk3507_set_batch_output, // 可选,支持批量写入
    .get_input = rk3507_get_input,
    .get_all = rk3507_get_all  // 必须高效实现,用于 1ms 轮询
};

2. 注册驱动

src/fx_local_gpio.cfx_gpio_init 函数中添加新驱动的匹配逻辑:

extern gpio_driver_t rk3507_driver; // 声明外部变量

int fx_gpio_init(const char* driver_name) {
    if (strcasecmp(driver_name, "RK3507_32I32O") == 0) {
        current_driver = &rk3507_driver;
    }
    // ... 其他驱动
}

3. CMake配置

CMakeLists.txt 中将新的 .c 文件加入编译列表。

关于滤波算法

滤波算法完全复用! SDK 的核心滤波逻辑(防抖、计数、滑动窗口)实现在通用层 (fx_local_gpio.c)。只要您的驱动能正确上报 get_all 数据,新机型就能直接享受到所有高级滤波功能,无需重复开发。 // 必须指定硬件型号 if (fx_gpio_init("RK3506_20I12O") != 0) { printf("Hardware not supported!\n"); return -1; }

fx_gpio_register_callback(my_cb);
fx_gpio_start_monitoring(1); // 1ms 监控周期

// 单点写
fx_gpio_set_output(0, 1);

// 批量写: mask=0x03 (out0+out1), value=0x01 (out0高, out1低)
fx_gpio_write_batch(0x03, 0x01);

// 批量读
int inputs = fx_gpio_read_batch(); // 返回位掩码

fx_gpio_deinit();
return 0;

}

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages