GCC Code Coverage Report


Directory: ./
File: firmware/console/binary/serial_can.cpp
Date: 2025-11-16 14:52:24
Coverage Exec Excl Total
Lines: 0.0% 0 0 7
Functions: 0.0% 0 0 1
Branches: 0.0% 0 0 7
Decisions: 0.0% 0 - 4

Line Branch Decision Exec Source
1 /**
2 * @file serial_can.cpp
3 *
4 * This code is a bridge between a serial streaming used by TS and a packet-frame CAN-bus, using the ISO-TP protocol.
5 * ISO 15765-2, or ISO-TP (Transport Layer), which is an international standard for sending data packets over a CAN-Bus.
6 * https://en.wikipedia.org/wiki/ISO_15765-2
7 *
8 * @date Aug 1, 2020
9 * @author andreika <promethePRINTus.pcb@gmail.com>
10 * @author Andrey Belomutskiy, (c) 2012-2020
11 */
12
13 #include "pch.h"
14
15 // todo: this file is asking to improve conditional compilation. unit_tests and cypress/kinetis are both special cases
16 #if HAL_USE_CAN || EFI_UNIT_TEST
17 #include "serial_can.h"
18 #include "can.h"
19 #include "can_msg_tx.h"
20 #endif // HAL_USE_CAN || EFI_UNIT_TEST
21
22
23 #if HAL_USE_CAN
24 // this one installs itself as top level CAN bus listener with static frame ID
25 static CanTsListener g_listener;
26 // for RX, this one delegates to above FIFO via global field
27 static CanTransport transport(&g_listener);
28
29 static CanStreamerState state(&transport, &transport, /*bus*/0, CAN_ECU_SERIAL_TX_ID);
30 #endif // HAL_USE_CAN
31
32 #if HAL_USE_CAN || EFI_UNIT_TEST
33
34 static int isoTpPacketCounter = 0;
35
36 /**
37 * incoming data main entry point
38 */
39 void CanTsListener::decodeFrame(const CANRxFrame& frame, efitick_t /*nowNt*/) {
40 // CAN ID filtering happens in base class, by the time we are here we know it's the CAN_ECU_SERIAL_RX_ID packet
41 // todo: what if the FIFO is full?
42 CanRxMessage msg(frame);
43 if (engineConfiguration->verboseIsoTp) {
44 PRINT("*** INFO: CanTsListener decodeFrame %d" PRINT_EOL, isoTpPacketCounter++);
45 }
46 if (!rxFifo.put(msg)) {
47 warning(ObdCode::CUSTOM_ERR_CAN_COMMUNICATION, "CAN sendDataTimeout() problems");
48 }
49 }
50
51 #if HAL_USE_CAN
52
53 void CanTransport::init() {
54 registerCanListener(g_listener);
55 }
56
57 can_msg_t CanTransport::transmit(CanTxMessage &/*ctfp*/, can_sysinterval_t /*timeout*/) {
58 // we do nothing here - see CanTxMessage::~CanTxMessage()
59 return CAN_MSG_OK;
60 }
61
62 void CanTransport::onTpFirstFrame() {
63 // todo: why nothing? broken iso-tp on ECU side?
64 }
65
66 can_msg_t CanTransport::receive(CANRxFrame *crfp, can_sysinterval_t timeout) {
67 // see CanTsListener and processCanRxMessage()
68 CanRxMessage msg;
69 if (this->source->get(msg, timeout)) {
70 *crfp = msg.frame;
71 return CAN_MSG_OK;
72 }
73 return CAN_MSG_TIMEOUT;
74 }
75
76 void tsOverCanInit() {
77 transport.init();
78 }
79
80 msg_t canStreamAddToTxTimeout(size_t *np, const uint8_t *txbuf, sysinterval_t timeout) {
81 return state.streamAddToTxTimeout(np, txbuf, timeout);
82 }
83
84 msg_t canStreamFlushTx(sysinterval_t timeout) {
85 return state.streamFlushTx(timeout);
86 }
87
88 // np uses in/out parameter approach. Yes ChibiOS does same but still evil!
89 // in entry: number of data frames to receive
90 // on exit the number of frames actually received
91 msg_t canStreamReceiveTimeout(size_t *np, uint8_t *rxbuf, sysinterval_t timeout) {
92 return state.streamReceiveTimeout(np, rxbuf, timeout);
93 }
94
95 #endif /* HAL_USE_CAN */
96
97
98
99 #endif // HAL_USE_CAN || EFI_UNIT_TEST
100