| 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 |