Slave 属性与方法
通过 master.slave(n) 获取 (1-based 索引)。
属性
| 类别 | 方法 | 返回类型 | 说明 |
|---|---|---|---|
| 基本标识 | index() | u16 | 从站索引 (1-based) |
| master_index() | u16 | 主站索引 | |
| name() | String | 设备名称(从 EEPROM group_name 读取) | |
| drive_name() | String | 驱动/设备名称(从 SDO 0x1008 读取) | |
| 设备信息 | vendor_id() | u32 | 制造商 ID(从 SII EEPROM 读取) |
| vendor_name() | String | 制造商名称 | |
| product_id() | u32 | 产品 ID | |
| rev_id() | u32 | 修订版本号 | |
| serial_number() | u32 | 序列号(从 SII EEPROM 读取) | |
| dtype() | u16 | 设备类型标识(可转换为 EcDeviceType) | |
| has_mdp() | bool | 是否支持模块化设备配置文件(ETG.5001) | |
| block_lrw() | bool | LRW 逻辑读写操作阻止标志 | |
| 地址 | config_addr() | u16 | 物理配置地址 |
| alias_address() | u16 | 别名地址 | |
| 状态 | state() | Option<EcState> | 从站当前状态 |
| state_raw() | u8 | 从站当前状态 (原始值) | |
| error_code() | EcALState | AL Status Code 错误码 (枚举) | |
| error_code_raw() | u16 | AL Status Code 错误码 (原始值) | |
| is_lost() | bool | 从站是否丢失(断开连接) | |
| 拓扑 | topology() | u8 | 拓扑类型 (0=无链接, 1=端点, 2=中间, 3=分支, 4=交叉) |
| parent_station() | u16 | 父从站的站地址 | |
| parent_port() | u8 | 父端口号 | |
| entry_port() | u8 | 入口端口号 | |
| active_ports() | u8 | 激活端口位掩码 | |
| physical_type() | u8 | 物理端口类型 | |
| child_count() | u16 | 子模块数量 | |
| PDO 数据 | input_bits() / output_bits() | u16 | 输入/输出数据位数 |
| input_bytes() / output_bytes() | u32 | 输入/输出数据字节数 | |
| input_offset() / output_offset() | u32 | 输入/输出在 IOmap 中的偏移 | |
| input_startbit() / output_startbit() | u8 | 输入/输出起始位 | |
| ESI/配置 | has_esi() | bool | 是否已加载 ESI 文件 |
| esi_version() | String | ESI 版本号 | |
| config_by_esi() | Result<()> | 根据 ESI 文件自动配置从站 (SM + DC) | |
| EEPROM | eep_8byte_addressing() | bool | EEPROM 寻址模式(true=8字节, false=4字节) |
| eep_pdi() | u8 | 物理设备接口(PDI)类型 | |
| ebus_current() | i16 | E-bus 电流消耗(mA) | |
| sii_index() | u16 | SII EEPROM 配置索引 | |
| 邮箱 | mbx_proto() | u16 | 支持的邮箱协议类型(MailboxType 位掩码) |
| mbx_length() | u16 | 邮箱发送缓冲区大小 | |
| mbx_read_length() | u16 | 邮箱接收缓冲区大小 | |
| mbx_read_offset() / mbx_write_offset() | u16 | 邮箱读/写偏移 | |
| mbx_count() | u8 | 邮箱协议计数器 | |
| 协议详情 | coe_details() | u8 | CoE 协议功能标志(EcCoEDetails 位掩码) |
| eoe_details() | u8 | EoE 协议功能标志(EcEoEDetails 位掩码) | |
| foe_details() | u8 | FoE 协议详情(来自 SII EEPROM) | |
| soe_details() | u8 | SoE 协议详情(来自 SII EEPROM) | |
| FMMU | fmmu0_func() | u8 | FMMU0 功能类型(bit 0=输出, bit 1=输入) |
| fmmu1_func() | u8 | FMMU1 功能类型 | |
| fmmu2_func() | u8 | FMMU2 功能类型 | |
| fmmu3_func() | u8 | FMMU3 功能类型 | |
| sync_manager_count() | u16 | SyncManager 数量 | |
| DC | has_dc() | bool | 是否支持 DC,详见 DC 同步 |
| dc_active() | u16 | DC 激活状态(0=禁用, 非0=已激活),详见 DC 同步 | |
| dc_cycle0() | i32 | SYNC0 周期(纳秒),详见 DC 同步 | |
| dc_cycle1() | i32 | SYNC1 周期(纳秒),详见 DC 同步 | |
| dc_shift() | i32 | 相位偏移(纳秒),详见 DC 同步 | |
| dc_next() | u16 | DC 链中下一个从站索引 | |
| dc_previous() | u16 | DC 链中上一个从站索引 | |
| dc_parent_port() | u8 | DC 父端口号 | |
| dc_receive_time_a() | i32 | 端口 A DC 接收时间(纳秒) | |
| dc_receive_time_b() | i32 | 端口 B DC 接收时间(纳秒) | |
| dc_receive_time_c() | i32 | 端口 C DC 接收时间(纳秒) | |
| dc_receive_time_d() | i32 | 端口 D DC 接收时间(纳秒) | |
| propagation_delay() | i32 | 帧从主站到达此从站的传播延迟(纳秒),详见 DC 同步 | |
| 拓扑扩展 | children() | Vec<u16> | 子从站索引列表(配合 child_count 使用,导航拓扑树) |
| supports_frame_repeat() / set_supports_frame_repeat(bool) | bool | 是否支持帧重复功能(ETG.1500 5.4.3,读写) | |
| 冗余 | redundancy_activated() | bool | 冗余是否已激活 |
| primary_link_broken() | bool | 主线路是否断路 | |
| secondary_link_broken() | bool | 冗余线路是否断路 | |
| 配置 | group() / set_group(u8) | u8 | 从站分组号(0-7,0=默认组,必须在 SAFE_OP 前设置),详见 从站分组 |
| is_optional() / set_optional(bool) | bool | 可选从站标记,缺席时不影响 WKC 检查、不触发组离线告警(必须在 OP 前设置) |
EcDeviceType 枚举值
#[repr(u16)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EcDeviceType {
Undefined = 0, // 未定义
Static = 1, // 静态设备,无IO映射,如EK1100耦合器
InputNoMailbox = 2, // 输入设备(无邮箱)
OutputNoMailbox = 3, // 输出设备(无邮箱)
InputWithMailbox = 4, // 输入设备(有邮箱)
OutputWithMailbox = 5, // 输出设备(有邮箱)
IoNoMailbox = 6, // 输入输出设备(无邮箱)
IoWithMailbox = 7, // 输入输出设备(有邮箱)
}
EcTopologyType / EcPortType 枚举值
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EcTopologyType {
NoLink = 0, // 无链接
EndPoint = 1, // 端点
Line = 2, // 中间节点(线性拓扑)
Fork = 3, // 分支点
Cross = 4, // 交叉点
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EcPortType {
NotUsed = 0, // 未使用
Mii = 1, // MII
Ebus = 2, // EBUS
EbusEnhanced = 3, // EBUS 增强型
}
MailboxType 枚举值
#[repr(u16)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum MailboxType {
ErrorMailbox = 0x00, // 错误邮箱
AdsOverEthercat = 0x01, // AoE
EthernetOverEthercat = 0x02, // EoE
CanopenOverEthercat = 0x03, // CoE
FileOverEthercat = 0x04, // FoE
ServoOverEthercat = 0x05, // SoE
VendorOverEthercat = 0x0F, // VoE
}
EcCoEDetails 位标志
bitflags! {
pub struct EcCoEDetails: u8 {
const NONE = 0x00;
const SDO = 0x01; // 支持 SDO
const SDO_INFO = 0x02; // 支持 SDO Info
const PDO_ASSIGN = 0x04; // 支持 PDO Assign
const PDO_CONFIG = 0x08; // 支持 PDO Config
const STARTUP = 0x10; // 支持 Startup
const COMPLETE_ACCESS = 0x20; // 支持 Complete Access
}
}
EcEoEDetails 位标志
bitflags! {
pub struct EcEoEDetails: u8 {
const NONE = 0x00;
const SEND_FRAME = 0x01; // 支持发送帧
const RECEIVE_FRAME = 0x02; // 支持接收帧
const SET_IP_PARAM = 0x04; // 支持设置 IP 参数
const GET_IP_PARAM = 0x08; // 支持获取 IP 参数
}
}
子对象
| 方法 | 返回类型 | 说明 |
|---|---|---|
| cia401() | CiA401 | CiA 401 I/O 模块辅助实例 |
| esi() | EsiLoader | ESI 文件加载器 |
| events() | SlaveEvents | 从站级事件,详见 从站事件 |
| diagnostics() | SlaveDiagnostics | 诊断信息访问器,详见 从站诊断 |
| startup() | StartupParameterList | 启动参数列表 |
| sdo_read_value::<T>() | Result<T> | CoE 类型化读取 |
| sdo_write_value() | Result<()> | CoE 类型化写入 |
| soe() | SoEInstance | Servo over EtherCAT |
| foe() | FoEInstance | File over EtherCAT |
| eoe() | EoEInstance | Ethernet over EtherCAT |
| aoe() | AoEInstance | ADS over EtherCAT |
| voe() | VoEInstance | Vendor over EtherCAT |
| dc() | SlaveDC | DC 同步配置 |
枚举描述
所有枚举统一使用 .description() 方法获取中文描述:
use ethercat::{EcState, state_description, cia402_state_description, cia402_mode_description};
// EcState 格式化
let state = slave.state().unwrap_or(EcState::None);
println!("{}", state); // Display trait: "OP"
// CiA 402 状态描述 (独立函数)
let desc = cia402_state_description(4); // "运行使能"
let mode_desc = cia402_mode_description(8); // "周期同步位置 (CSP)"
项目中所有枚举描述均通过 .description() 方法获取,包括 EcState、EcALState、SDOError、FSoEState、FSoEError、StateCiA402、ModeCiA402 等。
硬件信息查询
fmmus()
pub fn fmmus(&self) -> Vec<u8>
获取从站当前的 FMMU 配置原始数据(从站结构体中 fmmu_buffer, 4条目 x 16字节),用于调试或诊断地址映射问题。
sync_managers()
pub fn sync_managers(&self) -> Vec<u8>
获取从站当前的 SyncManager 配置原始数据(从站结构体中 sm_buffer, 8条目 x 8字节)。
sync_manager_types()
pub fn sync_manager_types(&self) -> Vec<u8>
获取从站 SyncManager 类型数组(8 字节, 对应 8 个 SM 的类型)。
返回值:
Vec<u8>— 类型数组:0=未使用, 1=邮箱输出, 2=邮箱输入, 3=过程数据输出, 4=过程数据输入
诊断
从站诊断信息(通信异常率、冗余状态、DC 同步)通过 slave.diagnostics() 访问,详见 从站诊断。
ESI 方法
set_esi_file(esi_file_name)
pub fn set_esi_file(&self, esi_file_name: &str) -> bool
设置从站使用的 ESI 文件。
返回值:
bool— 成功返回 true,失败返回 false
过程数据看门狗
set_watchdog(timeout_ms)
pub fn set_watchdog(&self, timeout_ms: u32) -> Result<()>
设置从站过程数据看门狗超时。从站在超时时间内未收到过程数据帧时触发看门狗错误(ALStatusCode 0x001B)。
参数:
timeout_ms(u32) — 超时时间(毫秒),0 = 禁用,最大 6553ms
返回值:
Result<()>— 成功或错误
应在 SafeOp 或 OP 状态下调用。
set_pdi_watchdog(timeout_ms)
pub fn set_pdi_watchdog(&self, timeout_ms: u32) -> Result<()>
设置从站 PDI 看门狗超时。PDI 看门狗监控从站本地应用(微控制器固件)是否正常运行。
参数:
timeout_ms(u32) — 超时时间(毫秒),0 = 禁用
返回值:
Result<()>— 成功或错误
示例:
slave.set_watchdog(100)?; // 100ms 超时
slave.set_watchdog(0)?; // 禁用看门狗
get_watchdog_config()
pub fn get_watchdog_config(&self) -> Option<WatchdogConfig>
读取从站看门狗当前配置。返回 None 表示读取失败。
返回值:
Option<WatchdogConfig>— 看门狗配置
相关结构:
pub struct WatchdogConfig {
pub divider: u16, // 看门狗分频器
pub pdi_timeout: u16, // PDI 看门狗超时值(分频器单位)
pub pd_timeout: u16, // 过程数据看门狗超时值(分频器单位)
}
示例:
if let Some(config) = slave.get_watchdog_config() {
println!("PD超时: {} × {:.2}us", config.pd_timeout, config.divider as f64 * 0.04);
}
get_watchdog_status()
pub fn get_watchdog_status(&self) -> Option<WatchdogStatus>
读取从站看门狗运行状态。返回 None 表示读取失败。
返回值:
Option<WatchdogStatus>— 看门狗状态
相关结构:
pub struct WatchdogStatus {
pub expired: bool, // 看门狗是否已过期
pub counter: u8, // 看门狗计数器(过期累计次数)
pub divider: u16, // 当前分频器值
pub timeout_value: u16, // 当前超时值
}
示例:
if let Some(status) = slave.get_watchdog_status() {
if status.expired {
println!("看门狗过期! 计数: {}", status.counter);
}
}
状态切换
从站状态机仅暴露 1 个公开 API: set_state, 同步执行单个从站的状态切换, 协议层按 EtherCAT 标准状态机自动处理中间状态。失败原因通过 Result::Err 返回 (见 DarraError)。
set_state()
pub fn set_state(&self, state: EcState, timeout_ms: u32) -> Result<(), DarraError>
切换单个从站到目标状态, 阻塞调用线程直到完成或超时。用于手动恢复单个从站、热插拔后重连入网, 或在 PDO 运行中将单从站切换到 PreOp / Init 维护。
参数:
state(EcState) — 目标状态timeout_ms(u32) — 单步超时 (毫秒), 推荐 3000 ~ 5000
返回值:
Ok(())— 已到达stateErr(DarraError::StateChangeFailed(state))— 切换失败 (超时 / AL 拒绝等), 错误描述可直接Display输出
状态切换遵循 EtherCAT 标准状态机流程, 协议层自动处理中间状态。例如从 Init 切换到 OP 会自动经过 PreOp → SafeOp → OP。
示例:
// 手动恢复单个从站到 OP
if slave.state() != Some(EcState::Operational) {
slave.set_state(EcState::Operational, 5000)?;
}
// 将从站切换到 Init (重置)
slave.set_state(EcState::Init, 5000)?;
ESC 寄存器访问 (高级)
直接读写从站 ESC (EtherCAT Slave Controller) 寄存器,用于故障诊断、自定义 ESC 操作、底层调试。协议层走 FPRD/FPWR 数据报,自动 primary → secondary → APWR 三级回退。
正常使用 SDK 时无需调用 — 状态切换 / PDO / 邮箱等流程 SDK 已自动配置寄存器。此 API 用于深度诊断和特殊场景(例如读取错误计数器、强制端口策略、调试 ESI 烧写不生效等)。
寄存器定义见 ETG.1000.4 §6 / ETG.1000.6 §5(公开标准),例如:
| 寄存器 | 说明 |
|---|---|
| 0x0000 | Type / Revision / Build(设备类型) |
| 0x0030 | AL Control(主站发起状态请求) |
| 0x0130 | AL Status(从站当前状态) |
| 0x0134 | AL Status Code(错误码) |
| 0x0300-0x030F | 端口 0-3 错误计数器 |
| 0x0400-0x043F | 看门狗配置 / 计数 |
read_register(reg_addr, len)
pub fn read_register(&self, reg_addr: u16, len: u32) -> Result<Vec<u8>>
读取从站 ESC 寄存器(FPRD)。
参数:
reg_addr(u16) — 寄存器地址(例如0x0130= AL Status)len(u32) — 读取字节数(1 / 2 / 4 等)
返回值:
Result<Vec<u8>>— 成功返回字节向量;失败(从站离线 / 超时)返回Err
write_register(reg_addr, data)
pub fn write_register(&self, reg_addr: u16, data: &[u8]) -> Result<()>
写入从站 ESC 寄存器(FPWR)。
参数:
reg_addr(u16) — 寄存器地址data(&[u8]) — 写入数据
返回值:
Result<()>— 成功返回Ok(())
示例:
let slave = master.slave(1)?;
// 读取 AL Status (0x0130, 2 字节)
let al_status = slave.read_register(0x0130, 2)?;
let state = u16::from_le_bytes([al_status[0], al_status[1]]);
println!("AL Status = 0x{:04X} (state={}, err={})",
state, state & 0x0F, (state & 0x10) != 0);
// 读取 AL Status Code (0x0134, 错误码)
let al_code = slave.read_register(0x0134, 2)?;
let code = u16::from_le_bytes([al_code[0], al_code[1]]);
println!("AL Status Code = 0x{:04X}", code);
// 写 AL Control = 0x04 (请求 SafeOp)
slave.write_register(0x0030, &[0x04, 0x00])?;
EEPROM (SII) 访问
读写从站 SII EEPROM (Slave Information Interface, ETG.1000.6 §6)。EEPROM 存储 vendor_id / product_code / revision_no / serial_no / SyncManager / FMMU / PDO 映射 / Strings 等设备身份与配置信息。SDK 在 config_init 阶段已自动读取,应用一般无需直接访问。
EEPROM 写入慎用 — 写错可能导致从站身份信息错乱,严重时永久 brick 从站, 需厂家工具恢复。仅在以下场景使用:
- 烧写 alias 地址(Hot-Connect 别名)
- 修复出厂数据被误覆盖
- 厂商授权的固件 / 参数烧录
EEPROM 写需要从站处于 Init / PreOp 状态,OP 状态下写入会被拒绝。
EEPROM 大小通常 1 KB - 16 KB(按 word 寻址,1 word = 2 byte)。起始 8 word 为厂商基本信息,之后是 Category 链表(Strings / General / FMMU / SyncM / TxPdo / RxPdo / DC / End=0xFFFF)。
read_eeprom(byte_offset, byte_length)
pub fn read_eeprom(&self, byte_offset: u16, byte_length: u16) -> Result<Vec<u8>>
读取从站 SII EEPROM 字节区域 (按 word 循环)。SDK 自动处理 BUSY 轮询、字对齐, 推荐应用层优先使用此高层 API。
参数:
byte_offset(u16) — 起始字节偏移 (建议偶数对齐)byte_length(u16) — 读取字节数 (建议偶数)
返回值:
Result<Vec<u8>>— 成功返回byte_length字节数据
write_eeprom(byte_offset, data)
pub fn write_eeprom(&self, byte_offset: u16, data: &[u8]) -> Result<()>
写入从站 SII EEPROM 字节区域 (按 word 循环)。byte_offset 与 data.len() 都必须是偶数。
参数:
byte_offset(u16) — 起始字节偏移 (必须偶数)data(&[u8]) — 写入字节 (长度必须偶数)
返回值:
Result<()>— 全部 word 成功写入返回Ok(()), 否则Err(DarraError::InvalidParameter)
示例:
let slave = master.slave(1)?;
// 读 vendor_id (EEPROM 字节偏移 0x10, 长度 4)
let data = slave.read_eeprom(0x10, 4)?;
let vendor_id = u32::from_le_bytes([data[0], data[1], data[2], data[3]]);
println!("VendorID = 0x{:08X}", vendor_id);
// 读取头部 16 字节 (含 PDIControl/StationAlias 等)
let header = slave.read_eeprom(0, 16)?;
println!("EEPROM 头部: {:02X?}", header);
// 写 alias address (EEPROM 字节偏移 0x08)
// 必须从站处于 Init/PreOp 状态!
if slave.state() == Some(EcState::Init) {
slave.write_eeprom(0x08, &[0x01, 0x00])?; // alias = 1
}
- 首选:
read_eeprom / write_eeprom(按字节, 自动字对齐) - 次选:
slave.vendor_id() / product_id() / serial_number()等已封装属性
DL Port 端口控制
直接读写 ESC 的 DL Port Control 寄存器 (0x0101),用于端口故障注入测试和冗余/环拓扑的手动诊断。
正常运行时无需调用。大部分用户应该通过订阅 on_slave_port_link_changed 事件和读取 端口错误计数器 来诊断端口状态。仅在需要主动模拟端口故障(测试冗余切换)或排查特定端口问题时使用。
ESC 有 4 个物理端口 P0 / P1 / P2 / P3,DL Port Control 寄存器的位定义如下:
| DLPORT 值 | 行为 |
|---|---|
| 0x00 | Auto — 所有端口由 ESC 自动管理(默认) |
| 0x03 | 关闭 P0 |
| 0x0C | 关闭 P1 |
| 0x30 | 关闭 P2 |
| 0xC0 | 关闭 P3 |
SDK 自动采用 primary → secondary → APWR 三级回退写入路径,即使 P0 关闭后仍能通过副网口/广播恢复。
write_dl_port(value)
pub fn write_dl_port(&self, value: u8) -> bool
写入从站 DL Port 控制寄存器(0x0101)。
参数:
value(u8) — DLPORT 值(见上表)
返回值:
bool— 成功返回true
read_dl_port()
pub fn read_dl_port(&self) -> Option<u8>
读取从站 DL Port 控制寄存器的当前值。
返回值:
Option<u8>—Some(dlport)读取成功;None读取失败(如从站离线)
示例:
// 模拟 P1 端口故障 (测试冗余切换)
let ok = slave.write_dl_port(0x0C);
println!("关闭 P1: {}", if ok { "成功" } else { "失败" });
// 读回确认
if let Some(dlport) = slave.read_dl_port() {
println!("当前 DLPORT = 0x{:02X}", dlport);
}
// 故障恢复后还原
slave.write_dl_port(0x00); // 恢复 Auto
关闭一个端口后,观察 master.events().on_slave_port_link_changed 和 master.diagnostics().break_point() 验证冗余切换是否生效。
Startup 配置
| 方法 | 返回类型 | 说明 |
|---|---|---|
| startup() | StartupParameterList | 启动参数列表 |
| pdo_assignment_enabled() / set_pdo_assignment_enabled(bool) | bool | 启动时是否写入 PDO Assignment,默认 true |
| pdo_configuration_enabled() / set_pdo_configuration_enabled(bool) | bool | 启动时是否写入 PDO Configuration,默认 false |
| supports_complete_access() / set_supports_complete_access(bool) | bool | 从站是否支持 SDO Complete Access |
StartupParameterList 方法(通过 slave.startup() 访问):
add(param)— 添加启动参数add_parameter(index, sub_index, data, ...)— 添加启动参数(显式参数)remove(index, sub_index)— 移除启动参数clear()— 清除所有启动参数apply(slave, transition, write_timing)— 应用启动参数到从站
示例:
use ethercat::StartupParameter;
let param = StartupParameter {
index: 0x1C12,
sub_index: 0,
data: vec![0],
transition: "PS".to_string(),
priority: 10,
..Default::default()
};
slave.startup().add(param);
相关结构:
IP— Init → PreOp,默认 AfterTransitionPS— PreOp → SafeOp,默认 BeforeTransitionSO— SafeOp → Op,默认 BeforeTransitionOS— Op → SafeOp,默认 AfterTransitionSP— SafeOp → PreOp,默认 AfterTransitionPI— PreOp → Init,默认 BeforeTransition
子对象访问
Rust SDK 在 Slave 上仅暴露两个子对象访问器, 其余字段通过扁平的属性方法直接读取 (见上文"属性"表):
slave.dc()
pub fn dc(&self) -> crate::slave::dc::SlaveDC
返回 SlaveDC 高级 DC 接口, 提供 enable_sync0 / read_system_time / propagation_delay 等方法。
let dc = slave.dc();
if dc.has_dc() {
dc.enable_sync0(1_000_000, 0)?; // 1ms cycle, 0 shift
println!("传播延迟 {} ns", dc.propagation_delay());
}
slave.identity()
pub fn identity(&self) -> Result<SlaveIdentity>
返回 vendor/product/revision/serial 四元组。比单独调 vendor_id() / product_id() / rev_id() / serial_number() 更方便, 错误统一为 Result。
let id = slave.identity()?;
println!("0x{:08X} 0x{:08X} 0x{:08X} 0x{:08X}",
id.vendor_id, id.product_code, id.revision_no, id.serial_no);
C# / Java 中存在的 slave.sii() / slave.mailbox() / slave.topology() / slave.metadata() / slave.runtime() / slave.sm_fmmu() / slave.proto_mbx() / slave.capabilities() 等 sub-struct 子对象, Rust 实现选择了扁平方法: 全部字段通过 slave.input_bits() / mbx_protocol() / physical_type() / topology() (返回拓扑类型 u8) / coe_details() 等直接读取, 与 Rust 习惯的 zero-cost accessor 对齐。
具体映射:
- C#
slave.Topology(sub-object) → Rustslave.topology()/parent_station()/entry_port()/active_ports()/physical_type()/child_count()/children() - C#
slave.Mailbox→ Rustslave.mbx_length()/mbx_protocol()/mbx_read_length()/mbx_write_offset()/mbx_read_offset() - C#
slave.SmFmmu→ Rustslave.fmmu0_func()/fmmu1_func()/fmmu2_func()/fmmu3_func()/sync_manager_count() - C#
slave.Capabilities→ Rustslave.coe_details()/eoe_details()/foe_details()/soe_details()/has_mdp()/supports_frame_repeat() - C#
slave.Sii.read_word/write_word/read_category→ Rust SDK 未导出 SII 直读 API, 通过slave.detailed_info()获取已解析的 EEPROM 字段。
如需访问完整原始结构体, 使用 slave.detailed_info() 返回的 SlaveDetailedInfo。
启动配置自动能力探测
pub fn capabilities(&self) -> StartupAutoCapabilities
注: 此 capabilities() 来自 crate::slave::startup 模块, 返回启动自动配置能力集合 (含 pdo_assignment / pdo_configuration / complete_access 等启动期能力布尔位), 与 C# Slave.Capabilities 子对象语义不同 — 前者是"启动器自动判定的能力", 后者是"SII EEPROM 协议详情位"。Rust SDK 中后者直接走 slave.coe_details() 等扁平方法。