GCC Code Coverage Report


Directory: ./
File: firmware/console/binary/serial_can.cpp
Date: 2025-10-24 14:26:41
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, /*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(const CanTxMessage */*ctfp*/, can_sysinterval_t /*timeout*/) {
58 // we do nothing here - see CanTxMessage::~CanTxMessage()
59 return CAN_MSG_OK;
60 }
61
62 can_msg_t CanTransport::receive(CANRxFrame *crfp, can_sysinterval_t timeout) {
63 // see CanTsListener and processCanRxMessage()
64 CanRxMessage msg;
65 if (this->source->get(msg, timeout)) {
66 *crfp = msg.frame;
67 return CAN_MSG_OK;
68 }
69 return CAN_MSG_TIMEOUT;
70 }
71
72 void tsOverCanInit() {
73 transport.init();
74 }
75
76 msg_t canStreamAddToTxTimeout(size_t *np, const uint8_t *txbuf, sysinterval_t timeout) {
77 return state.streamAddToTxTimeout(np, txbuf, timeout);
78 }
79
80 msg_t canStreamFlushTx(sysinterval_t timeout) {
81 return state.streamFlushTx(timeout);
82 }
83
84 // np uses in/out parameter approach. Yes ChibiOS does same but still evil!
85 // in entry: number of data frames to receive
86 // on exit the number of frames actually received
87 msg_t canStreamReceiveTimeout(size_t *np, uint8_t *rxbuf, sysinterval_t timeout) {
88 return state.streamReceiveTimeout(np, rxbuf, timeout);
89 }
90
91 #endif /* HAL_USE_CAN */
92
93
94
95 #endif // HAL_USE_CAN || EFI_UNIT_TEST
96