rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
can_msg_tx.cpp
Go to the documentation of this file.
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"
14
15#include "can.h"
16
17#if EFI_SIMULATOR || EFI_UNIT_TEST
18#include "fifo_buffer.h"
19fifo_buffer<CANTxFrame, TEST_CAN_BUFFER_SIZE> 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
40CanTxMessage::CanTxMessage(CanCategory p_category, uint32_t eid, uint8_t dlc, size_t bus, bool isExtended) {
41 category = p_category;
42#if HAS_CAN_FRAME
43#ifndef STM32H7XX
44 // ST bxCAN device
45 m_frame.IDE = isExtended ? CAN_IDE_EXT : CAN_IDE_STD;
46 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 if (isExtended) {
54 CAN_EID(m_frame) = eid;
55 } else {
56 if (eid >= 0x800) {
57 criticalError("Looks like extended CAN ID %x %s", eid, getCanCategory(category));
58 return;
59 }
60 CAN_SID(m_frame) = eid;
61 }
62
63 setDlc(dlc);
64
65 setBus(bus);
66
68#endif // HAS_CAN_FRAME
69}
70
72#if EFI_SIMULATOR || EFI_UNIT_TEST
74
75#if EFI_UNIT_TEST
76 printf("%s Sending CAN%d message: ID=%x/l=%x %x %x %x %x %x %x %x %x \n",
78 busIndex + 1,
79 (unsigned int)CAN_ID(m_frame),
84 m_frame.data8[6], m_frame.data8[7]);
85#endif
86#endif // EFI_SIMULATOR
87
88#if EFI_CAN_SUPPORT
90
91 if (!engine->allowCanTx) {
92 return;
93 }
94
95 if (busIndex >= EFI_CAN_BUS_COUNT) {
96 // Error already throuwn from CanTxMessage::setBus
97 // just do not access out of bounds
98 return;
99 }
100
101 auto device = s_devices[busIndex];
102 if (!device) {
103 criticalError("Send: CAN%d device not configured %s %x", busIndex + 1, getCanCategory(category),
104 (unsigned int)CAN_ID(m_frame));
105 return;
106 }
107
108 bool verboseCan = engineConfiguration->verboseCan && busIndex == 0;
109 verboseCan |= engineConfiguration->verboseCan2 && busIndex == 1;
110#if (EFI_CAN_BUS_COUNT >= 3)
111 verboseCan |= engineConfiguration->verboseCan3 && busIndex == 2;
112#endif
113
114 if (verboseCan) {
115 efiPrintf("%s Sending CAN%d message: ID=%x/l=%x %x %x %x %x %x %x %x %x",
117 busIndex + 1,
118 (unsigned int)CAN_ID(m_frame),
119 m_frame.DLC,
120 m_frame.data8[0], m_frame.data8[1],
121 m_frame.data8[2], m_frame.data8[3],
122 m_frame.data8[4], m_frame.data8[5],
123 m_frame.data8[6], m_frame.data8[7]);
124 }
125
126 // 100 ms timeout
127 msg_t msg = canTransmit(device, CAN_ANY_MAILBOX, &m_frame, TIME_MS2I(100));
128#if EFI_TUNER_STUDIO
129 if (msg == MSG_OK) {
131 } else {
132extern int txErrorCount[EFI_CAN_BUS_COUNT];
135 }
136#endif // EFI_TUNER_STUDIO
137#endif /* EFI_CAN_SUPPORT */
138}
139
140#if HAS_CAN_FRAME
141void CanTxMessage::setDlc(uint8_t dlc) {
142 // TODO: CAN vs CANFD
143 if (dlc > sizeof(m_frame.data8)) {
144 criticalError("CAN: incorrect DLC %d", dlc);
145 return;
146 }
147
148 m_frame.DLC = dlc;
149}
150
151void CanTxMessage::setBus(size_t bus) {
152 if (bus >= EFI_CAN_BUS_COUNT) {
153 criticalError("CAN: CAN%d incorect bus", bus + 1);
154 return;
155 }
156
157 busIndex = bus;
158}
159
160// LSB Little-endian System, "Intel"
161void CanTxMessage::setShortValue(uint16_t value, size_t offset) {
162 m_frame.data8[offset] = value & 0xFF;
163 m_frame.data8[offset + 1] = value >> 8;
164}
165
166// MOTOROLA order, MSB (Most Significant Byte/Big Endian) comes first.
167void CanTxMessage::setShortValueMsb(uint16_t value, size_t offset) {
168 m_frame.data8[offset] = value >> 8;
169 m_frame.data8[offset + 1] = value & 0xFF;
170}
171
172void CanTxMessage::setBit(size_t byteIdx, size_t bitIdx) {
173 m_frame.data8[byteIdx] |= 1 << bitIdx;
174}
175
176uint8_t& CanTxMessage::operator[](size_t index) {
177 return m_frame.data8[index];
178}
179#endif // HAS_CAN_FRAME
180
const char * getCanCategory(CanCategory value)
CanCategory
Definition can_category.h:7
int txErrorCount[EFI_CAN_BUS_COUNT]
Definition can_hw.cpp:107
fifo_buffer< CANTxFrame, TEST_CAN_BUFFER_SIZE > txCanBuffer
fifo_buffer< CANTxFrame, TEST_CAN_BUFFER_SIZE > txCanBuffer
uint8_t & operator[](size_t)
Read & write the raw underlying 8-byte buffer.
void setBit(size_t byteIdx, size_t bitIdx)
Set a single bit in the transmit buffer. Useful for single-bit flags.
void setShortValueMsb(uint16_t value, size_t offset)
void setBus(size_t bus)
static void setDevice(size_t idx, CANDriver *device)
static CANDriver * s_devices[EFI_CAN_BUS_COUNT]
Definition can_msg_tx.h:23
CanTxMessage(CanCategory category, uint32_t eid, uint8_t dlc=8, size_t bus=0, bool isExtended=false)
void setShortValue(uint16_t value, size_t offset)
Write a 16-bit short value to the buffer. Note: this writes in Intel little endian byte order.
void setDlc(uint8_t dlc)
size_t busIndex
Definition can_msg_tx.h:53
CanCategory category
Definition can_msg_tx.h:44
CANTxFrame m_frame
Definition can_msg_tx.h:100
bool allowCanTx
Definition engine.h:118
TunerStudioOutputChannels outputChannels
Definition engine.h:113
static EngineAccessor engine
Definition engine.h:415
static constexpr engine_configuration_s * engineConfiguration
static Lps25 device
Definition init_baro.cpp:4
@ CanDriverTx
uint8_t data8[8]
Frame data.
Definition can_mocks.h:27
uint8_t DLC
Data length.
Definition can_mocks.h:14
uint8_t RTR
Frame type.
Definition can_mocks.h:15
uint8_t IDE
Identifier type.
Definition can_mocks.h:16
void setArrayValues(TValue(&array)[TSize], float value)
uint16_t offset
Definition tunerstudio.h:0
printf("\n")