Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /** | |||
2 | * @file can_msg_tx.cpp | |||
3 | * | |||
4 | * CAN message transmission | |||
5 | * | |||
6 | * @date Mar 13, 2020 | |||
7 | * @author Matthew Kennedy, (c) 2012-2020 | |||
8 | */ | |||
9 | ||||
10 | #include "pch.h" | |||
11 | ||||
12 | #include "can_msg_tx.h" | |||
13 | #include "auto_generated_can_category.h" | |||
14 | ||||
15 | #include "can.h" | |||
16 | ||||
17 | #if EFI_SIMULATOR || EFI_UNIT_TEST | |||
18 | #include "fifo_buffer.h" | |||
19 | fifo_buffer<CANTxFrame, 1024> txCanBuffer; | |||
20 | #endif // EFI_SIMULATOR | |||
21 | ||||
22 | #if EFI_CAN_SUPPORT | |||
23 | /*static*/ CANDriver* CanTxMessage::s_devices[2] = {nullptr, nullptr}; | |||
24 | ||||
25 | /*static*/ void CanTxMessage::setDevice(CANDriver* device1, CANDriver* device2) { | |||
26 | s_devices[0] = device1; | |||
27 | s_devices[1] = device2; | |||
28 | } | |||
29 | #endif // EFI_CAN_SUPPORT | |||
30 | ||||
31 | 76 | CanTxMessage::CanTxMessage(CanCategory p_category, uint32_t eid, uint8_t dlc, size_t bus, bool isExtended) { | ||
32 | 76 | category = p_category; | ||
33 | #if HAS_CAN_FRAME | |||
34 | #ifndef STM32H7XX | |||
35 | // ST bxCAN device | |||
36 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 75 times.
|
76 | m_frame.IDE = isExtended ? CAN_IDE_EXT : CAN_IDE_STD; | |
37 | 76 | m_frame.RTR = CAN_RTR_DATA; | ||
38 | #else /* if STM32H7XX */ | |||
39 | // Bosch M_CAN FDCAN device | |||
40 | m_frame.common.XTD = isExtended; | |||
41 | m_frame.common.RTR = 0; | |||
42 | #endif | |||
43 | ||||
44 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 75 times.
|
2/2✓ Decision 'true' taken 1 time.
✓ Decision 'false' taken 75 times.
|
76 | if (isExtended) { |
45 | 1 | CAN_EID(m_frame) = eid; | ||
46 | } else { | |||
47 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
1/2✗ Decision 'true' not taken.
✓ Decision 'false' taken 75 times.
|
75 | if (eid >= 0x800) { |
48 | ✗ | criticalError("Looks like extended CAN ID %x %s", eid, getCanCategory(category)); | ||
49 | ✗ | return; | ||
50 | } | |||
51 | 75 | CAN_SID(m_frame) = eid; | ||
52 | } | |||
53 | ||||
54 | 76 | setDlc(dlc); | ||
55 | ||||
56 | 76 | setBus(bus); | ||
57 | ||||
58 | 76 | setArrayValues(m_frame.data8, 0); | ||
59 | #endif // HAS_CAN_FRAME | |||
60 | } | |||
61 | ||||
62 | 73 | CanTxMessage::~CanTxMessage() { | ||
63 | #if EFI_SIMULATOR || EFI_UNIT_TEST | |||
64 | 73 | txCanBuffer.put(m_frame); | ||
65 | ||||
66 | #if EFI_UNIT_TEST | |||
67 | 73 | printf("%s Sending CAN%d message: ID=%x/l=%x %x %x %x %x %x %x %x %x \n", | ||
68 | getCanCategory(category), | |||
69 | 73 | busIndex + 1, | ||
70 | 73 | (unsigned int)CAN_ID(m_frame), | ||
71 | 73 | m_frame.DLC, | ||
72 | 73 | m_frame.data8[0], m_frame.data8[1], | ||
73 | 73 | m_frame.data8[2], m_frame.data8[3], | ||
74 | 73 | m_frame.data8[4], m_frame.data8[5], | ||
75 |
2/2✓ Branch 0 taken 1 time.
✓ Branch 1 taken 72 times.
|
73 | m_frame.data8[6], m_frame.data8[7]); | |
76 | #endif | |||
77 | #endif // EFI_SIMULATOR | |||
78 | ||||
79 | #if EFI_CAN_SUPPORT | |||
80 | ScopePerf pc(PE::CanDriverTx); | |||
81 | ||||
82 | if (!engine->allowCanTx) { | |||
83 | return; | |||
84 | } | |||
85 | ||||
86 | auto device = s_devices[busIndex]; | |||
87 | if (!device) { | |||
88 | criticalError("Send: CAN%d device not configured %s %x", busIndex + 1, getCanCategory(category), | |||
89 | (unsigned int)CAN_ID(m_frame)); | |||
90 | return; | |||
91 | } | |||
92 | ||||
93 | bool verboseCan0 = engineConfiguration->verboseCan && busIndex == 0; | |||
94 | bool verboseCan1 = engineConfiguration->verboseCan2 && busIndex == 1; | |||
95 | ||||
96 | if (verboseCan0 || verboseCan1) { | |||
97 | efiPrintf("%s Sending CAN%d message: ID=%x/l=%x %x %x %x %x %x %x %x %x", | |||
98 | getCanCategory(category), | |||
99 | busIndex + 1, | |||
100 | (unsigned int)CAN_ID(m_frame), | |||
101 | m_frame.DLC, | |||
102 | m_frame.data8[0], m_frame.data8[1], | |||
103 | m_frame.data8[2], m_frame.data8[3], | |||
104 | m_frame.data8[4], m_frame.data8[5], | |||
105 | m_frame.data8[6], m_frame.data8[7]); | |||
106 | } | |||
107 | ||||
108 | // 100 ms timeout | |||
109 | msg_t msg = canTransmit(device, CAN_ANY_MAILBOX, &m_frame, TIME_MS2I(100)); | |||
110 | #if EFI_TUNER_STUDIO | |||
111 | if (msg == MSG_OK) { | |||
112 | engine->outputChannels.canWriteOk++; | |||
113 | } else { | |||
114 | engine->outputChannels.canWriteNotOk++; | |||
115 | } | |||
116 | #endif // EFI_TUNER_STUDIO | |||
117 | #endif /* EFI_CAN_SUPPORT */ | |||
118 | 73 | } | ||
119 | ||||
120 | #if HAS_CAN_FRAME | |||
121 | 82 | void CanTxMessage::setDlc(uint8_t dlc) { | ||
122 | 82 | m_frame.DLC = dlc; | ||
123 | 82 | } | ||
124 | ||||
125 | 76 | void CanTxMessage::setBus(size_t bus) { | ||
126 | 76 | busIndex = bus; | ||
127 | 76 | } | ||
128 | ||||
129 | // LSB Little-endian System, "Intel" | |||
130 | ✗ | void CanTxMessage::setShortValue(uint16_t value, size_t offset) { | ||
131 | ✗ | m_frame.data8[offset] = value & 0xFF; | ||
132 | ✗ | m_frame.data8[offset + 1] = value >> 8; | ||
133 | ✗ | } | ||
134 | ||||
135 | // MOTOROLA order, MSB (Most Significant Byte/Big Endian) comes first. | |||
136 | ✗ | void CanTxMessage::setShortValueMsb(uint16_t value, size_t offset) { | ||
137 | ✗ | m_frame.data8[offset] = value >> 8; | ||
138 | ✗ | m_frame.data8[offset + 1] = value & 0xFF; | ||
139 | ✗ | } | ||
140 | ||||
141 | ✗ | void CanTxMessage::setBit(size_t byteIdx, size_t bitIdx) { | ||
142 | ✗ | m_frame.data8[byteIdx] |= 1 << bitIdx; | ||
143 | ✗ | } | ||
144 | ||||
145 | 483 | uint8_t& CanTxMessage::operator[](size_t index) { | ||
146 | 483 | return m_frame.data8[index]; | ||
147 | } | |||
148 | #endif // HAS_CAN_FRAME | |||
149 | ||||
150 |