Skip to main content

darra_ethercat/data/
structures.rs

1
2pub mod constants {
3
4    pub const ECT_MBXPROT_AOE: u16 = 0x0001;
5
6    pub const ECT_MBXPROT_EOE: u16 = 0x0002;
7
8    pub const ECT_MBXPROT_COE: u16 = 0x0004;
9
10    pub const ECT_MBXPROT_FOE: u16 = 0x0008;
11
12    pub const ECT_MBXPROT_SOE: u16 = 0x0010;
13
14    pub const ECT_MBXPROT_VOE: u16 = 0x0020;
15
16    pub const ECT_COEDET_SDO: u8 = 0x01;
17
18    pub const ECT_COEDET_SDOINFO: u8 = 0x02;
19
20    pub const ECT_COEDET_PDOASSIGN: u8 = 0x04;
21
22    pub const ECT_COEDET_PDOCONFIG: u8 = 0x08;
23
24    pub const ECT_COEDET_UPLOAD: u8 = 0x10;
25
26    pub const ECT_COEDET_SDOCA: u8 = 0x20;
27}
28
29#[derive(Clone, Debug, Default)]
30#[repr(C)]
31pub struct PdoStats {
32    pub read_count: u32,
33    pub write_count: u32,
34    pub error_count: u32,
35    pub total_bytes_read: u32,
36    pub total_bytes_written: u32,
37    pub last_cycle_time_ns: u64,
38    pub min_cycle_time_ns: u64,
39    pub max_cycle_time_ns: u64,
40    pub avg_cycle_time_ns: u64,
41}
42
43#[derive(Clone, Debug)]
44#[repr(C, packed)]
45pub struct PdoMappingEntry {
46    pub index: u16,
47    pub sub_index: u8,
48    pub bit_length: u8,
49    pub bit_offset: u16,
50    pub name: [u8; 64],
51    pub unit: [u8; 16],
52    pub readable: u8,
53    pub writable: u8,
54}
55
56#[derive(Clone, Debug, Default)]
57#[repr(C, packed)]
58pub struct CommunicationStatsLocal {
59    pub total_cycles: u32,
60    pub successful_cycles: u32,
61    pub failed_cycles: u32,
62    pub timeout_cycles: u32,
63    pub average_cycle_time_us: f64,
64    pub max_cycle_time_us: f64,
65    pub min_cycle_time_us: f64,
66}
67
68#[derive(Clone, Debug, Default)]
69pub struct SlaveInfo {
70    pub vendor_id: u32,
71    pub product_code: u32,
72    pub revision_number: u32,
73    pub serial_number: u32,
74    pub device_name: String,
75    pub vendor_name: String,
76    pub sync_manager_count: u16,
77    pub fmmu_count: u16,
78    pub supports_coe: bool,
79    pub supports_foe: bool,
80    pub supports_eoe: bool,
81    pub supports_soe: bool,
82}
83
84#[derive(Clone, Debug, Default)]
85#[repr(C, packed)]
86pub struct RealtimeStats {
87    pub current_cycle_time_us: f64,
88    pub jitter_us: f64,
89    pub lost_frames: u32,
90    pub corrupted_frames: u32,
91    pub bus_utilization: f64,
92}
93
94#[derive(Clone, Debug)]
95#[repr(C, packed)]
96pub struct NetworkInfo {
97
98    pub name: [u8; 128],
99
100    pub desc: [u8; 128],
101
102    pub slave_num: i16,
103
104    pub redundant_slave_num: i16,
105}
106
107#[derive(Clone, Copy, Debug, Default)]
108#[repr(C, packed)]
109pub struct EcSmt {
110
111    pub start_addr: u16,
112
113    pub sm_length: u16,
114
115    pub sm_flags: u32,
116}
117
118#[derive(Clone, Copy, Debug, Default)]
119#[repr(C, packed)]
120pub struct EcFmmut {
121
122    pub log_start: u32,
123
124    pub log_length: u16,
125
126    pub log_start_bit: u8,
127
128    pub log_end_bit: u8,
129
130    pub phys_start: u16,
131
132    pub phys_start_bit: u8,
133
134    pub fmmu_type: u8,
135
136    pub fmmu_active: u8,
137
138    pub unused1: u8,
139
140    pub unused2: u16,
141}
142
143#[derive(Clone, Copy, Debug, Default)]
144#[repr(C)]
145pub struct SlaveIoDesc {
146
147    pub bits: u16,
148
149    pub bytes: u32,
150
151    pub ptr: usize,
152
153    pub offset: u32,
154
155    pub startbit: u8,
156}
157
158#[derive(Clone, Copy, Debug, Default)]
159#[repr(C)]
160pub struct SlaveFsoe {
161
162    pub capable: u8,
163
164    pub connection: usize,
165
166    pub sm_context: usize,
167
168    pub connection_id: u16,
169
170    pub safety_address: u16,
171
172    pub safe_input_size: u16,
173
174    pub safe_output_size: u16,
175
176    pub pdo_input_offset: u32,
177
178    pub pdo_output_offset: u32,
179}
180
181#[derive(Clone, Copy, Debug, Default)]
182#[repr(C)]
183pub struct SlaveMailbox {
184
185    pub length: u16,
186
187    pub write_offset: u16,
188
189    pub read_length: u16,
190
191    pub read_offset: u16,
192
193    pub supported_proto: u16,
194
195    pub cnt: u8,
196}
197
198#[derive(Clone, Copy, Debug, Default)]
199#[repr(C)]
200pub struct SlaveEepromConfig {
201
202    pub _reserved_sii: u16,
203
204    pub read_8byte: u8,
205
206    pub pdi: u8,
207}
208
209#[derive(Clone, Copy, Debug, Default)]
210#[repr(C)]
211pub struct SlaveHandler {
212
213    pub state: i32,
214
215    pub rmp_state: i32,
216
217    pub instate_ex: u16,
218}
219
220#[derive(Clone, Copy, Debug, Default)]
221#[repr(C)]
222pub struct SlaveIdentity {
223
224    pub vendor_id: u32,
225
226    pub product_id: u32,
227
228    pub revision: u32,
229
230    pub serial: u32,
231
232    pub itype: u16,
233
234    pub dtype: u16,
235}
236
237#[derive(Clone, Copy, Debug)]
238#[repr(C)]
239pub struct SlaveMetadata {
240
241    pub identity: SlaveIdentity,
242
243    pub group_name: [u8; 41],
244
245    pub device_name: [u8; 41],
246
247    pub sm_count: u16,
248}
249
250impl Default for SlaveMetadata {
251    fn default() -> Self {
252        Self {
253            identity: SlaveIdentity::default(),
254            group_name: [0; 41],
255            device_name: [0; 41],
256            sm_count: 0,
257        }
258    }
259}
260
261#[derive(Clone, Copy, Debug, Default)]
262#[repr(C)]
263pub struct SlaveCapabilities {
264
265    pub is_optional: u8,
266
267    pub supports_frame_repeat: u8,
268
269    pub mailbox_side: u8,
270
271    pub coe_details: u8,
272
273    pub foe_details: u8,
274
275    pub eoe_details: u8,
276
277    pub soe_details: u8,
278}
279
280#[derive(Clone, Copy, Debug, Default)]
281#[repr(C)]
282pub struct SlaveRuntime {
283
284    pub ebus_current: i16,
285
286    pub block_lrw: u8,
287
288    pub group: u8,
289
290    pub is_lost: u8,
291}
292
293#[derive(Clone, Copy, Debug, Default)]
294#[repr(C)]
295pub struct SlaveSmFmmu {
296
297    pub sm_type: [u8; 8],
298
299    pub sm_app_length: [u16; 8],
300
301    pub fmmu_func: [u8; 4],
302
303    pub fmmu_unused: u8,
304}
305
306#[derive(Clone, Copy, Debug, Default)]
307#[repr(C)]
308pub struct SlaveProtoMbx {
309
310    pub in_ptr: usize,
311
312    pub in_full: u8,
313
314    pub overrun: i32,
315}
316
317#[derive(Clone, Copy, Debug, Default)]
318#[repr(C)]
319pub struct SlavePdoConfig {
320
321    pub assignment_enabled: u8,
322
323    pub configuration_enabled: u8,
324
325    pub config_initialized: u8,
326
327    pub supports_complete_access: u8,
328}
329
330#[derive(Clone, Copy, Debug, Default)]
331#[repr(C)]
332pub struct SlaveTopology {
333
334    pub has_dc: u8,
335
336    pub phy_type: u8,
337
338    pub link_count: u8,
339
340    pub active_ports: u8,
341
342    pub consumed_ports: u8,
343
344    pub parent: u16,
345
346    pub parent_port: u8,
347
348    pub entry_port: u8,
349}
350
351#[derive(Clone, Copy, Debug, Default)]
352#[repr(C)]
353pub struct SlaveDc {
354
355    pub recvtime: [i32; 4],
356
357    pub propagation_delay: i32,
358
359    pub next: u16,
360
361    pub prev: u16,
362
363    pub cycle0: i32,
364
365    pub cycle1: i32,
366
367    pub shift: i32,
368
369    pub active: u16,
370}
371
372#[derive(Clone, Debug)]
373#[repr(C)]
374pub struct EcSlave {
375
376    pub state: u16,
377
378    pub al_status_code: u16,
379
380    pub config_addr: u16,
381
382    pub alias_addr: u16,
383
384    pub fsoe: SlaveFsoe,
385
386    pub output: SlaveIoDesc,
387
388    pub input: SlaveIoDesc,
389
390    pub sm: [EcSmt; 8],
391
392    pub fmmu: [EcFmmut; 4],
393
394    pub sm_fmmu: SlaveSmFmmu,
395
396    pub mbx: SlaveMailbox,
397
398    pub topo: SlaveTopology,
399
400    pub dc: SlaveDc,
401
402    pub eeprom_config: SlaveEepromConfig,
403
404    pub runtime: SlaveRuntime,
405
406    pub po2so_config: usize,
407
408    pub handler: SlaveHandler,
409
410    pub coe: SlaveProtoMbx,
411
412    pub soe: SlaveProtoMbx,
413
414    pub foe: SlaveProtoMbx,
415
416    pub eoe: SlaveProtoMbx,
417
418    pub voe: SlaveProtoMbx,
419
420    pub aoe: SlaveProtoMbx,
421
422    pub mbx_status: usize,
423
424    pub metadata: SlaveMetadata,
425
426    pub pdo_config: SlavePdoConfig,
427
428    pub capabilities: SlaveCapabilities,
429}
430
431#[derive(Clone, Debug)]
432#[repr(C)]
433pub struct EcState {
434
435    pub state: u16,
436
437    pub al_status_code: u16,
438
439    pub slave_count: i32,
440
441    pub loop_cycle: u32,
442
443    pub dc_cycle: u32,
444
445    pub dc_time: i64,
446
447    pub iomap: [u8; 65536],
448
449    pub iomap_mutex: usize,
450
451    pub iomap_buffer: [u8; 65536],
452
453    pub buffer_version: u32,
454
455    pub buffer_dirty: u8,
456
457    pub mutex_protection: u8,
458
459    pub pdo_cpu_affinity: i8,
460
461    pub dc_auto_shift_enabled: u8,
462
463    pub use_udp: u8,
464
465    pub adaptive_timeout_enabled: u8,
466
467    pub overlapping_groups: u8,
468
469    pub packed_mode: u8,
470
471    pub frame_high_priority: u8,
472
473    pub vlan_id: u16,
474
475    pub vlan_priority: u8,
476
477    pub timeout_init_to_preop: u32,
478
479    pub timeout_preop_to_safeop: u32,
480
481    pub timeout_safeop_to_op: u32,
482
483    pub wd_pd_timeout_ms: u16,
484
485    pub wd_pdi_timeout_ms: u16,
486
487    pub filter_threshold: u32,
488
489    pub frame_repeat_count: u8,
490
491    pub active_group_count: u8,
492
493    pub _group_pad: [u8; 2],
494
495    pub group_config_raw: [u8; 160],
496}
497
498#[derive(Clone, Debug)]
499#[repr(C)]
500pub struct InternalDiagnostics {
501
502    pub cache_cnt: u32,
503
504    pub rt_cnt: u32,
505
506    pub cycle_count: u32,
507
508    pub error_cache_cnt: u32,
509
510    pub error_cnt: u32,
511
512    pub wkc: u16,
513
514    pub expected_wkc: u16,
515
516    pub cycle_time_span: u32,
517
518    pub frame_errors: u32,
519
520    pub lost_frames: u32,
521
522    pub checksum_errors: u32,
523
524    pub timeout_frames: u32,
525
526    pub rx_error_count: [u32; 512],
527
528    pub tx_error_count: [u32; 512],
529
530    pub lost_link_count: [u16; 512],
531
532    pub invalid_frame_count: [u16; 512],
533
534    pub working_counter_errors: u16,
535
536    pub consecutive_wkc_errors: u16,
537
538    pub total_wkc_mismatches: u32,
539
540    pub cycle_start_time: u64,
541
542    pub cycle_time_accumulator: f64,
543
544    pub last_snapshot_time: u64,
545
546    pub snapshot_cycle_count: u32,
547
548    pub last_cycle_time_us: f64,
549
550    pub jitter_accumulator: f64,
551
552    pub max_jitter_in_second: f64,
553
554    pub jitter_sample_count: u32,
555
556}
557
558#[derive(Clone, Debug)]
559pub struct FoEOptionsLocal {
560
561    pub enable_crc: bool,
562
563    pub strict_mode: bool,
564
565    pub auto_append_crc: bool,
566
567    pub expected_crc: u32,
568}
569
570impl Default for FoEOptionsLocal {
571    fn default() -> Self {
572        Self {
573            enable_crc: false,
574            strict_mode: true,
575            auto_append_crc: true,
576            expected_crc: 0,
577        }
578    }
579}
580
581pub struct EcGroupConfigHelper;
582
583impl EcGroupConfigHelper {
584
585    const GROUP_CONFIG_SIZE: usize = 20;
586
587    pub fn get_group_enabled(raw: &[u8], group: u8) -> bool {
588        if group >= 8 { return false; }
589        raw[group as usize * Self::GROUP_CONFIG_SIZE] != 0
590    }
591
592    pub fn set_group_enabled(raw: &mut [u8], group: u8, enabled: bool) {
593        if group >= 8 { return; }
594        raw[group as usize * Self::GROUP_CONFIG_SIZE] = if enabled { 1 } else { 0 };
595    }
596
597    pub fn get_group_cycle_divider(raw: &[u8], group: u8) -> u8 {
598        if group >= 8 { return 0; }
599        raw[group as usize * Self::GROUP_CONFIG_SIZE + 1]
600    }
601
602    pub fn set_group_cycle_divider(raw: &mut [u8], group: u8, divider: u8) {
603        if group >= 8 { return; }
604        raw[group as usize * Self::GROUP_CONFIG_SIZE + 1] = divider;
605    }
606
607    pub fn get_group_expected_wkc(raw: &[u8], group: u8) -> u16 {
608        if group >= 8 { return 0; }
609        let off = group as usize * Self::GROUP_CONFIG_SIZE + 2;
610        u16::from_le_bytes([raw[off], raw[off + 1]])
611    }
612
613    pub fn get_group_slave_count(raw: &[u8], group: u8) -> u16 {
614        if group >= 8 { return 0; }
615        let off = group as usize * Self::GROUP_CONFIG_SIZE + 4;
616        u16::from_le_bytes([raw[off], raw[off + 1]])
617    }
618
619    pub fn get_group_frame_repeat_eligible(raw: &[u8], group: u8) -> bool {
620        if group >= 8 { return false; }
621        raw[group as usize * Self::GROUP_CONFIG_SIZE + 6] != 0
622    }
623
624    pub fn set_group_frame_repeat_eligible(raw: &mut [u8], group: u8, eligible: bool) {
625        if group >= 8 { return; }
626        raw[group as usize * Self::GROUP_CONFIG_SIZE + 6] = if eligible { 1 } else { 0 };
627    }
628
629    pub fn get_group_actual_wkc(raw: &[u8], group: u8) -> u16 {
630        if group >= 8 { return 0; }
631        let off = group as usize * Self::GROUP_CONFIG_SIZE + 8;
632        u16::from_le_bytes([raw[off], raw[off + 1]])
633    }
634
635    pub fn get_group_consecutive_miss(raw: &[u8], group: u8) -> u16 {
636        if group >= 8 { return 0; }
637        let off = group as usize * Self::GROUP_CONFIG_SIZE + 10;
638        u16::from_le_bytes([raw[off], raw[off + 1]])
639    }
640
641    pub fn get_group_total_frames(raw: &[u8], group: u8) -> u32 {
642        if group >= 8 { return 0; }
643        let off = group as usize * Self::GROUP_CONFIG_SIZE + 12;
644        u32::from_le_bytes([raw[off], raw[off + 1], raw[off + 2], raw[off + 3]])
645    }
646
647    pub fn get_group_mismatch_frames(raw: &[u8], group: u8) -> u32 {
648        if group >= 8 { return 0; }
649        let off = group as usize * Self::GROUP_CONFIG_SIZE + 16;
650        u32::from_le_bytes([raw[off], raw[off + 1], raw[off + 2], raw[off + 3]])
651    }
652}