GCC Code Coverage Report


Directory: ./
File: firmware/hw_layer/drivers/can/can_msg_tx.cpp
Date: 2025-10-24 14:26:41
Coverage Exec Excl Total
Lines: 69.8% 30 0 43
Functions: 62.5% 5 0 8
Branches: 87.5% 7 0 8
Decisions: 75.0% 3 - 4

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