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, 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
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
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",
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) {
125 } else {
127 }
128#endif // EFI_TUNER_STUDIO
129#endif /* EFI_CAN_SUPPORT */
130}
131
132#if HAS_CAN_FRAME
133void CanTxMessage::setDlc(uint8_t dlc) {
134 m_frame.DLC = dlc;
135}
136
137void CanTxMessage::setBus(size_t bus) {
138 busIndex = bus;
139}
140
141// LSB Little-endian System, "Intel"
142void 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.
148void 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
153void CanTxMessage::setBit(size_t byteIdx, size_t bitIdx) {
154 m_frame.data8[byteIdx] |= 1 << bitIdx;
155}
156
157uint8_t& CanTxMessage::operator[](size_t index) {
158 return m_frame.data8[index];
159}
160#endif // HAS_CAN_FRAME
161
const char * getCanCategory(CanCategory value)
CanCategory
Definition can_category.h:7
fifo_buffer< CANTxFrame, 1024 > txCanBuffer
fifo_buffer< CANTxFrame, 1024 > 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:114
TunerStudioOutputChannels outputChannels
Definition engine.h:109
static EngineAccessor engine
Definition engine.h:413
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")