1use crate::communication::{
2 AbstractFrame, AbstractFrameTriggering, AbstractPdu, CommunicationDirection, FlexrayPhysicalChannel, Frame,
3 FramePort, FrameTriggering, Pdu, PduToFrameMapping, PduTriggering,
4};
5use crate::{
6 AbstractionElement, ArPackage, AutosarAbstractionError, ByteOrder, EcuInstance, IdentifiableAbstractionElement,
7 abstraction_element, is_used_system_element, make_unique_name,
8};
9use autosar_data::{Element, ElementName, EnumItem};
10
11#[derive(Debug, Clone, PartialEq, Eq, Hash)]
15pub struct FlexrayFrame(Element);
16abstraction_element!(FlexrayFrame, FlexrayFrame);
17impl IdentifiableAbstractionElement for FlexrayFrame {}
18
19impl FlexrayFrame {
20 pub(crate) fn new(name: &str, package: &ArPackage, byte_length: u64) -> Result<Self, AutosarAbstractionError> {
21 let pkg_elements = package.element().get_or_create_sub_element(ElementName::Elements)?;
22 let fr_frame = pkg_elements.create_named_sub_element(ElementName::FlexrayFrame, name)?;
23
24 fr_frame
25 .create_sub_element(ElementName::FrameLength)?
26 .set_character_data(byte_length.to_string())?;
27
28 Ok(Self(fr_frame))
29 }
30
31 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
33 for pdu_mapping in self.mapped_pdus() {
34 pdu_mapping.remove(deep)?;
35 }
36
37 let frame_triggerings = self.frame_triggerings();
39
40 AbstractionElement::remove(self, deep)?;
42
43 for ft in frame_triggerings {
45 ft.remove(deep)?;
46 }
47
48 Ok(())
49 }
50}
51
52impl AbstractFrame for FlexrayFrame {
53 type FrameTriggeringType = FlexrayFrameTriggering;
54
55 fn frame_triggerings(&self) -> Vec<FlexrayFrameTriggering> {
57 let model_result = self.element().model();
58 let path_result = self.element().path();
59 if let (Ok(model), Ok(path)) = (model_result, path_result) {
60 model
61 .get_references_to(&path)
62 .iter()
63 .filter_map(|e| {
64 e.upgrade()
65 .and_then(|ref_elem| ref_elem.named_parent().ok().flatten())
66 .and_then(|elem| FlexrayFrameTriggering::try_from(elem).ok())
67 })
68 .collect()
69 } else {
70 vec![]
71 }
72 }
73
74 fn map_pdu<T: AbstractPdu>(
76 &self,
77 gen_pdu: &T,
78 start_position: u32,
79 byte_order: ByteOrder,
80 update_bit: Option<u32>,
81 ) -> Result<PduToFrameMapping, AutosarAbstractionError> {
82 Frame::Flexray(self.clone()).map_pdu(gen_pdu, start_position, byte_order, update_bit)
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, Hash)]
90pub struct FlexrayFrameTriggering(Element);
91abstraction_element!(FlexrayFrameTriggering, FlexrayFrameTriggering);
92impl IdentifiableAbstractionElement for FlexrayFrameTriggering {}
93
94impl FlexrayFrameTriggering {
95 pub(crate) fn new(
96 channel: &FlexrayPhysicalChannel,
97 frame: &FlexrayFrame,
98 slot_id: u16,
99 timing: &FlexrayCommunicationCycle,
100 ) -> Result<Self, AutosarAbstractionError> {
101 let model = channel.element().model()?;
102 let base_path = channel.element().path()?;
103 let frame_name = frame
104 .name()
105 .ok_or(AutosarAbstractionError::InvalidParameter("invalid frame".to_string()))?;
106 let ft_name = format!("FT_{frame_name}");
107 let ft_name = make_unique_name(&model, &base_path, &ft_name);
108
109 let frame_triggerings = channel
110 .element()
111 .get_or_create_sub_element(ElementName::FrameTriggerings)?;
112 let fr_triggering =
113 frame_triggerings.create_named_sub_element(ElementName::FlexrayFrameTriggering, &ft_name)?;
114
115 fr_triggering
116 .create_sub_element(ElementName::FrameRef)?
117 .set_reference_target(frame.element())?;
118
119 let ft = Self(fr_triggering);
120 ft.set_slot(slot_id)?;
121 ft.set_timing(timing)?;
122
123 for pdu_mapping in frame.mapped_pdus() {
124 if let Some(pdu) = pdu_mapping.pdu() {
125 ft.add_pdu_triggering(&pdu)?;
126 }
127 }
128
129 Ok(ft)
130 }
131
132 pub fn remove(self, deep: bool) -> Result<(), AutosarAbstractionError> {
134 let opt_frame = self.frame();
135
136 for pt in self.pdu_triggerings() {
138 pt.remove(deep)?;
139 }
140 for frame_port in self.frame_ports() {
141 frame_port.remove(deep)?;
142 }
143
144 AbstractionElement::remove(self, deep)?;
145
146 if deep && let Some(frame) = opt_frame {
149 if !is_used_system_element(frame.element()) {
152 frame.remove(deep)?;
153 }
154 }
155
156 Ok(())
157 }
158
159 pub fn set_slot(&self, slot_id: u16) -> Result<(), AutosarAbstractionError> {
161 self.element()
162 .get_or_create_sub_element(ElementName::AbsolutelyScheduledTimings)?
163 .get_or_create_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
164 .get_or_create_sub_element(ElementName::SlotId)?
165 .set_character_data(slot_id.to_string())?;
166 Ok(())
167 }
168
169 #[must_use]
173 pub fn slot(&self) -> Option<u16> {
174 self.element()
175 .get_sub_element(ElementName::AbsolutelyScheduledTimings)?
176 .get_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
177 .get_sub_element(ElementName::SlotId)?
178 .character_data()?
179 .parse_integer()
180 }
181
182 pub fn set_timing(&self, timing: &FlexrayCommunicationCycle) -> Result<(), AutosarAbstractionError> {
184 let timings_elem = self
185 .element()
186 .get_or_create_sub_element(ElementName::AbsolutelyScheduledTimings)?
187 .get_or_create_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
188 .get_or_create_sub_element(ElementName::CommunicationCycle)?;
189 match timing {
190 FlexrayCommunicationCycle::Counter { cycle_counter } => {
191 let _ = timings_elem.remove_sub_element_kind(ElementName::CycleRepetition);
192 timings_elem
193 .get_or_create_sub_element(ElementName::CycleCounter)?
194 .get_or_create_sub_element(ElementName::CycleCounter)?
195 .set_character_data(cycle_counter.to_string())?;
196 }
197 FlexrayCommunicationCycle::Repetition {
198 base_cycle,
199 cycle_repetition,
200 } => {
201 let _ = timings_elem.remove_sub_element_kind(ElementName::CycleCounter);
202 let repetition = timings_elem.get_or_create_sub_element(ElementName::CycleRepetition)?;
203 repetition
204 .get_or_create_sub_element(ElementName::BaseCycle)?
205 .set_character_data(base_cycle.to_string())?;
206 repetition
207 .get_or_create_sub_element(ElementName::CycleRepetition)?
208 .set_character_data::<EnumItem>((*cycle_repetition).into())?;
209 }
210 }
211 Ok(())
212 }
213
214 #[must_use]
218 pub fn timing(&self) -> Option<FlexrayCommunicationCycle> {
219 let timings = self
220 .element()
221 .get_sub_element(ElementName::AbsolutelyScheduledTimings)?
222 .get_sub_element(ElementName::FlexrayAbsolutelyScheduledTiming)?
223 .get_sub_element(ElementName::CommunicationCycle)?;
224
225 if let Some(counter_based) = timings.get_sub_element(ElementName::CycleCounter) {
226 let cycle_counter = counter_based
227 .get_sub_element(ElementName::CycleCounter)?
228 .character_data()?
229 .parse_integer()?;
230 Some(FlexrayCommunicationCycle::Counter { cycle_counter })
231 } else if let Some(repetition) = timings.get_sub_element(ElementName::CycleRepetition) {
232 let base_cycle = repetition
233 .get_sub_element(ElementName::BaseCycle)?
234 .character_data()?
235 .parse_integer()?;
236 let cycle_repetition = repetition
237 .get_sub_element(ElementName::CycleRepetition)?
238 .character_data()?
239 .enum_value()?
240 .try_into()
241 .ok()?;
242
243 Some(FlexrayCommunicationCycle::Repetition {
244 base_cycle,
245 cycle_repetition,
246 })
247 } else {
248 None
249 }
250 }
251
252 pub(crate) fn add_pdu_triggering(&self, pdu: &Pdu) -> Result<PduTriggering, AutosarAbstractionError> {
253 FrameTriggering::Flexray(self.clone()).add_pdu_triggering(pdu)
254 }
255
256 pub fn physical_channel(&self) -> Result<FlexrayPhysicalChannel, AutosarAbstractionError> {
258 let channel_elem = self.element().named_parent()?.unwrap();
259 FlexrayPhysicalChannel::try_from(channel_elem)
260 }
261
262 pub fn connect_to_ecu(
266 &self,
267 ecu: &EcuInstance,
268 direction: CommunicationDirection,
269 ) -> Result<FramePort, AutosarAbstractionError> {
270 FrameTriggering::Flexray(self.clone()).connect_to_ecu(ecu, direction)
271 }
272}
273
274impl AbstractFrameTriggering for FlexrayFrameTriggering {
275 type FrameType = FlexrayFrame;
276}
277
278impl From<FlexrayFrameTriggering> for FrameTriggering {
279 fn from(fft: FlexrayFrameTriggering) -> Self {
280 FrameTriggering::Flexray(fft)
281 }
282}
283
284#[derive(Debug, Clone, Copy, PartialEq, Eq)]
288pub enum FlexrayCommunicationCycle {
289 Counter {
291 cycle_counter: u8,
293 },
294 Repetition {
296 base_cycle: u8,
298 cycle_repetition: CycleRepetition,
300 },
301}
302
303#[derive(Debug, Clone, Copy, PartialEq, Eq)]
305pub enum CycleRepetition {
306 C1,
308 C2,
310 C4,
312 C5,
314 C8,
316 C10,
318 C16,
320 C20,
322 C32,
324 C40,
326 C50,
328 C64,
330}
331
332impl TryFrom<EnumItem> for CycleRepetition {
333 type Error = AutosarAbstractionError;
334
335 fn try_from(value: EnumItem) -> Result<Self, Self::Error> {
336 match value {
337 EnumItem::CycleRepetition1 => Ok(Self::C1),
338 EnumItem::CycleRepetition2 => Ok(Self::C2),
339 EnumItem::CycleRepetition4 => Ok(Self::C4),
340 EnumItem::CycleRepetition5 => Ok(Self::C5),
341 EnumItem::CycleRepetition8 => Ok(Self::C8),
342 EnumItem::CycleRepetition10 => Ok(Self::C10),
343 EnumItem::CycleRepetition16 => Ok(Self::C16),
344 EnumItem::CycleRepetition20 => Ok(Self::C20),
345 EnumItem::CycleRepetition32 => Ok(Self::C32),
346 EnumItem::CycleRepetition40 => Ok(Self::C40),
347 EnumItem::CycleRepetition50 => Ok(Self::C50),
348 EnumItem::CycleRepetition64 => Ok(Self::C64),
349
350 _ => Err(AutosarAbstractionError::ValueConversionError {
351 value: value.to_string(),
352 dest: "CycleRepetitionType".to_string(),
353 }),
354 }
355 }
356}
357
358impl From<CycleRepetition> for EnumItem {
359 fn from(value: CycleRepetition) -> Self {
360 match value {
361 CycleRepetition::C1 => EnumItem::CycleRepetition1,
362 CycleRepetition::C2 => EnumItem::CycleRepetition2,
363 CycleRepetition::C4 => EnumItem::CycleRepetition4,
364 CycleRepetition::C5 => EnumItem::CycleRepetition5,
365 CycleRepetition::C8 => EnumItem::CycleRepetition8,
366 CycleRepetition::C10 => EnumItem::CycleRepetition10,
367 CycleRepetition::C16 => EnumItem::CycleRepetition16,
368 CycleRepetition::C20 => EnumItem::CycleRepetition20,
369 CycleRepetition::C32 => EnumItem::CycleRepetition32,
370 CycleRepetition::C40 => EnumItem::CycleRepetition40,
371 CycleRepetition::C50 => EnumItem::CycleRepetition50,
372 CycleRepetition::C64 => EnumItem::CycleRepetition64,
373 }
374 }
375}
376
377#[cfg(test)]
380mod test {
381 use super::*;
382 use crate::{
383 AutosarModelAbstraction, ByteOrder, SystemCategory,
384 communication::{AbstractPhysicalChannel, FlexrayChannelName, FlexrayClusterSettings},
385 };
386 use autosar_data::AutosarVersion;
387
388 #[test]
389 fn fr_frame() {
390 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
391 let package = model.get_or_create_package("/package").unwrap();
392 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
393 let flexray_cluster = system
394 .create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())
395 .unwrap();
396 let channel = flexray_cluster
397 .create_physical_channel("Channel", FlexrayChannelName::A)
398 .unwrap();
399
400 let ecu_instance = system.create_ecu_instance("ECU", &package).unwrap();
401 let can_controller = ecu_instance
402 .create_flexray_communication_controller("Controller")
403 .unwrap();
404 can_controller.connect_physical_channel("connection", &channel).unwrap();
405
406 let pdu1 = system.create_isignal_ipdu("pdu1", &package, 8).unwrap();
407 let pdu2 = system.create_isignal_ipdu("pdu2", &package, 8).unwrap();
408
409 let frame1 = system.create_flexray_frame("frame1", &package, 64).unwrap();
411 let frame2 = system.create_flexray_frame("frame2", &package, 64).unwrap();
412
413 assert_eq!(frame1.length().unwrap(), 64);
414 frame1.set_length(60).unwrap();
415 assert_eq!(frame1.length().unwrap(), 60);
416
417 let mapping = frame1
419 .map_pdu(&pdu1, 7, ByteOrder::MostSignificantByteFirst, Some(8))
420 .unwrap();
421 assert!(frame1.mapped_pdus().count() == 1);
422 assert_eq!(frame1.mapped_pdus().next().unwrap(), mapping);
423
424 let frame_triggering1 = channel
426 .trigger_frame(
427 &frame1,
428 1,
429 &FlexrayCommunicationCycle::Repetition {
430 base_cycle: 1,
431 cycle_repetition: CycleRepetition::C1,
432 },
433 )
434 .unwrap();
435 assert_eq!(frame1.frame_triggerings().len(), 1);
436 let frame_triggering2 = channel
437 .trigger_frame(&frame2, 2, &FlexrayCommunicationCycle::Counter { cycle_counter: 2 })
438 .unwrap();
439 assert_eq!(frame2.frame_triggerings().len(), 1);
440 assert_eq!(channel.frame_triggerings().count(), 2);
441
442 assert_eq!(frame_triggering1.pdu_triggerings().count(), 1);
444
445 let _ = frame1
447 .map_pdu(&pdu2, 71, ByteOrder::MostSignificantByteFirst, None)
448 .unwrap();
449 assert!(frame1.mapped_pdus().count() == 2);
450
451 assert_eq!(frame_triggering1.pdu_triggerings().count(), 2);
453
454 let frame_port = frame_triggering1
456 .connect_to_ecu(&ecu_instance, CommunicationDirection::Out)
457 .unwrap();
458 assert_eq!(frame_port.ecu().unwrap(), ecu_instance);
459 assert_eq!(
460 frame_port.communication_direction().unwrap(),
461 CommunicationDirection::Out
462 );
463 frame_port.set_name("port").unwrap();
464 assert_eq!(frame_port.name().unwrap(), "port");
465
466 assert_eq!(frame_triggering1.frame().unwrap(), frame1);
467 assert_eq!(frame_triggering1.slot().unwrap(), 1);
468 assert_eq!(
469 frame_triggering1.timing().unwrap(),
470 FlexrayCommunicationCycle::Repetition {
471 base_cycle: 1,
472 cycle_repetition: CycleRepetition::C1
473 }
474 );
475 assert_eq!(frame_triggering1.physical_channel().unwrap(), channel);
476 assert_eq!(frame_triggering2.frame().unwrap(), frame2);
477 assert_eq!(frame_triggering2.slot().unwrap(), 2);
478 assert_eq!(
479 frame_triggering2.timing().unwrap(),
480 FlexrayCommunicationCycle::Counter { cycle_counter: 2 }
481 );
482 assert_eq!(frame_triggering2.physical_channel().unwrap(), channel);
483
484 assert_eq!(mapping.pdu().unwrap(), pdu1.into());
485 assert_eq!(mapping.byte_order().unwrap(), ByteOrder::MostSignificantByteFirst);
486 assert_eq!(mapping.start_position().unwrap(), 7);
487 assert_eq!(mapping.update_bit(), Some(8));
488 }
489
490 #[test]
491 fn cycle_repetition() {
492 assert_eq!(EnumItem::CycleRepetition1, CycleRepetition::C1.into());
493 assert_eq!(EnumItem::CycleRepetition2, CycleRepetition::C2.into());
494 assert_eq!(EnumItem::CycleRepetition4, CycleRepetition::C4.into());
495 assert_eq!(EnumItem::CycleRepetition5, CycleRepetition::C5.into());
496 assert_eq!(EnumItem::CycleRepetition8, CycleRepetition::C8.into());
497 assert_eq!(EnumItem::CycleRepetition10, CycleRepetition::C10.into());
498 assert_eq!(EnumItem::CycleRepetition16, CycleRepetition::C16.into());
499 assert_eq!(EnumItem::CycleRepetition20, CycleRepetition::C20.into());
500 assert_eq!(EnumItem::CycleRepetition32, CycleRepetition::C32.into());
501 assert_eq!(EnumItem::CycleRepetition40, CycleRepetition::C40.into());
502 assert_eq!(EnumItem::CycleRepetition50, CycleRepetition::C50.into());
503 assert_eq!(EnumItem::CycleRepetition64, CycleRepetition::C64.into());
504
505 assert_eq!(CycleRepetition::C1, EnumItem::CycleRepetition1.try_into().unwrap());
506 assert_eq!(CycleRepetition::C2, EnumItem::CycleRepetition2.try_into().unwrap());
507 assert_eq!(CycleRepetition::C4, EnumItem::CycleRepetition4.try_into().unwrap());
508 assert_eq!(CycleRepetition::C5, EnumItem::CycleRepetition5.try_into().unwrap());
509 assert_eq!(CycleRepetition::C8, EnumItem::CycleRepetition8.try_into().unwrap());
510 assert_eq!(CycleRepetition::C10, EnumItem::CycleRepetition10.try_into().unwrap());
511 assert_eq!(CycleRepetition::C16, EnumItem::CycleRepetition16.try_into().unwrap());
512 assert_eq!(CycleRepetition::C20, EnumItem::CycleRepetition20.try_into().unwrap());
513 assert_eq!(CycleRepetition::C32, EnumItem::CycleRepetition32.try_into().unwrap());
514 assert_eq!(CycleRepetition::C40, EnumItem::CycleRepetition40.try_into().unwrap());
515 assert_eq!(CycleRepetition::C50, EnumItem::CycleRepetition50.try_into().unwrap());
516 assert_eq!(CycleRepetition::C64, EnumItem::CycleRepetition64.try_into().unwrap());
517
518 let result: Result<CycleRepetition, _> = EnumItem::Aa.try_into();
519 assert!(result.is_err());
520 }
521
522 #[test]
523 fn remove_frame_triggering() {
524 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
525 let package = model.get_or_create_package("/package").unwrap();
526 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
527 let flexray_cluster = system
528 .create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())
529 .unwrap();
530 let channel = flexray_cluster
531 .create_physical_channel("Channel", FlexrayChannelName::A)
532 .unwrap();
533
534 let frame = system.create_flexray_frame("frame", &package, 8).unwrap();
535 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
536
537 let frame_triggering = channel
538 .trigger_frame(&frame, 0x123, &FlexrayCommunicationCycle::Counter { cycle_counter: 1 })
539 .unwrap();
540
541 let _mapping = frame
542 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
543 .unwrap();
544
545 assert_eq!(frame.mapped_pdus().count(), 1);
546 assert_eq!(frame.frame_triggerings().len(), 1);
547 assert_eq!(channel.frame_triggerings().count(), 1);
548
549 frame_triggering.remove(false).unwrap();
551 assert_eq!(system.frames().count(), 1);
553
554 let frame_triggering = channel
556 .trigger_frame(&frame, 0x123, &FlexrayCommunicationCycle::Counter { cycle_counter: 1 })
557 .unwrap();
558 frame_triggering.remove(true).unwrap();
560
561 assert_eq!(channel.frame_triggerings().count(), 0);
563 assert_eq!(system.frames().count(), 0);
565 assert_eq!(frame.mapped_pdus().count(), 0);
567 assert_eq!(system.pdus().count(), 0);
569
570 assert_eq!(channel.frame_triggerings().count(), 0);
571 assert_eq!(channel.pdu_triggerings().count(), 0);
572 }
573
574 #[test]
575 fn remove_frame() {
576 let model = AutosarModelAbstraction::create("test", AutosarVersion::LATEST);
577 let package = model.get_or_create_package("/package").unwrap();
578 let system = package.create_system("System", SystemCategory::EcuExtract).unwrap();
579 let flexray_cluster = system
580 .create_flexray_cluster("Cluster", &package, &FlexrayClusterSettings::default())
581 .unwrap();
582 let channel = flexray_cluster
583 .create_physical_channel("Channel", FlexrayChannelName::A)
584 .unwrap();
585 let frame = system.create_flexray_frame("frame", &package, 8).unwrap();
586 let pdu = system.create_isignal_ipdu("pdu", &package, 8).unwrap();
587 let frame_triggering = channel
588 .trigger_frame(&frame, 0x123, &FlexrayCommunicationCycle::Counter { cycle_counter: 1 })
589 .unwrap();
590 let mapping = frame
591 .map_pdu(&pdu, 0, ByteOrder::MostSignificantByteLast, None)
592 .unwrap();
593 assert_eq!(frame.mapped_pdus().count(), 1);
594 assert_eq!(frame.frame_triggerings().len(), 1);
595 assert_eq!(channel.frame_triggerings().count(), 1);
596 frame.remove(false).unwrap();
598 assert_eq!(system.frames().count(), 0);
600 assert!(mapping.element().path().is_err());
602 assert_eq!(system.pdus().count(), 1);
604 assert!(frame_triggering.element().path().is_err());
606 assert_eq!(channel.frame_triggerings().count(), 0);
607 assert_eq!(channel.pdu_triggerings().count(), 0);
608 }
609}