GCC Code Coverage Report


Directory: ./
File: firmware/hw_layer/drivers/can/can_msg_tx.cpp
Date: 2025-10-03 00:57:22
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[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