Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Adafruit_GFX MODSERIAL mbed-rtos mbed
IsoTpHandler.cpp
00001 #include "IsoTpHandler.h" 00002 #include "PidDecoder.h" 00003 00004 #include "MODSERIAL.h" 00005 extern MODSERIAL pc; 00006 00007 #ifdef ACTIVATE_DEBUG_OUTPUT 00008 #define DEBUG_PRINT(format, ...) pc.printf(format, ##__VA_ARGS__) 00009 #else 00010 #define DEBUG_PRINT(format, ...) 00011 #endif 00012 00013 static PidDecoder pidDecoder; 00014 00015 enum IsoTpMessageType 00016 { 00017 SINGLE_FRAME = 0, ///< The single frame transferred contains the complete payload of up to 7 bytes (normal addressing) or 6 bytes (extended addressing) 00018 FIRST_FRAME = 1, ///< The first frame of a longer multi-frame message packet, used when more than 6/7 bytes of data segmented must be communicated. The first frame contains the length of the full packet, along with the initial data. 00019 CONSECUTIVE_FRAME = 2, ///< A frame containing subsequent data for a multi-frame packet 00020 FLOW_CONTOL_FRAME = 3, ///< The response from the receiver, acknowledging a First-frame segment. It lays down the parameters for the transmission of further consecutive frames. 00021 }; 00022 00023 enum IsoTpFlowType 00024 { 00025 CLEAR_TO_SEND = 0, 00026 WAIT = 1, 00027 OVERFLOW_ABORT = 2, 00028 }; 00029 00030 const IsoTpHandler::IdleState IsoTpHandler::idleState; 00031 const IsoTpHandler::ConsequtiveTransferState IsoTpHandler::consequtiveTransferState; 00032 00033 IsoTpHandler::IdleState::IdleState() 00034 { 00035 } 00036 00037 void IsoTpHandler::IdleState::processInput(const CANMessage* message, IsoTpHandler* context) const 00038 { 00039 if (!IsoTpHandler::isValidIsoTpPacket(message)) 00040 { 00041 return; 00042 } 00043 uint8_t messageType = message->data[0] >> 4; 00044 if (messageType == SINGLE_FRAME) 00045 { 00046 uint8_t messageSize = message->data[0] & 0x0F; 00047 if (messageSize > message->len - 1) 00048 { 00049 DEBUG_PRINT("Iso tp message is too short: iso len %d vs can len %d\r\n", messageSize, message->len); 00050 return; 00051 } 00052 context->handle_decoded_packet(&message->data[1], messageSize); 00053 return; 00054 } 00055 if (messageType == FIRST_FRAME) 00056 { 00057 if (message->len != 8) 00058 { 00059 DEBUG_PRINT("Invalid iso tp message length for FIRST_FRAME, length is %d\r\n", message->len); 00060 return; 00061 } 00062 00063 uint16_t messageSize = ((message->data[0] & 0x0F) << 8) | (message->data[1]); 00064 context->init_consequtive_reading (messageSize, &message->data[2]); 00065 context->setState(&consequtiveTransferState); 00066 return; 00067 } 00068 if (messageType == CONSECUTIVE_FRAME) 00069 { 00070 DEBUG_PRINT("Invalid iso tp message in idle state, because unexpected CONSECUTIVE_FRAME received\r\n"); 00071 return; 00072 } 00073 if (messageType == FLOW_CONTOL_FRAME) 00074 { 00075 DEBUG_PRINT("Invalid iso tp message, because unexpected FLOW_CONTOL_FRAME received\r\n"); 00076 return; 00077 } 00078 00079 DEBUG_PRINT("Invalid iso tp message ?!\r\n"); 00080 } 00081 00082 void IsoTpHandler::IdleState::onEnter(IsoTpHandler* context) const 00083 { 00084 } 00085 00086 void IsoTpHandler::IdleState::onLeave(IsoTpHandler* context) const 00087 { 00088 } 00089 00090 IsoTpHandler::ConsequtiveTransferState::ConsequtiveTransferState() 00091 { 00092 } 00093 00094 void IsoTpHandler::ConsequtiveTransferState::processInput(const CANMessage* message, IsoTpHandler* context) const 00095 { 00096 if (!IsoTpHandler::isValidIsoTpPacket(message)) 00097 { 00098 return; 00099 } 00100 uint8_t messageType = message->data[0] >> 4; 00101 if (messageType == SINGLE_FRAME) 00102 { 00103 DEBUG_PRINT("Received SINGLE_FRAME, expected consequitve frame\r\n"); 00104 return; 00105 } 00106 if (messageType == FIRST_FRAME) 00107 { 00108 DEBUG_PRINT("Received FIRST_FRAME, expected consequitve frame\r\n"); 00109 return; 00110 } 00111 if (messageType == CONSECUTIVE_FRAME) 00112 { 00113 uint8_t index = message->data[0] & 0x0F; 00114 if (index != context->getExpectedIndex()) 00115 { 00116 DEBUG_PRINT("In consequiive frame, received index %d, expected %d\r\n", index, context->getExpectedIndex()); 00117 context->setState(&IsoTpHandler::idleState); 00118 return; 00119 00120 } 00121 00122 if (context->appendReceivedData(&message->data[1], message->len - 1)) 00123 { 00124 DEBUG_PRINT("In consequtive frame, change state\r\n"); 00125 00126 context->setState(&IsoTpHandler::idleState); 00127 } 00128 context->incrementExpectedIndex(); 00129 return; 00130 } 00131 if (messageType == FLOW_CONTOL_FRAME) 00132 { 00133 DEBUG_PRINT("Received FLOW_CONTROL_FRAME, expected consequitve frame\r\n"); 00134 return; 00135 } 00136 00137 DEBUG_PRINT("Invalid iso tp message, expected consequitve frame ?!\r\n"); 00138 } 00139 00140 void IsoTpHandler::ConsequtiveTransferState::onEnter(IsoTpHandler* context) const 00141 { 00142 } 00143 00144 void IsoTpHandler::ConsequtiveTransferState::onLeave(IsoTpHandler* context) const 00145 { 00146 } 00147 00148 IsoTpHandler::IsoTpHandler(CAN* canInterface) 00149 : m_state(&idleState) 00150 , m_canInterface (canInterface) 00151 { 00152 m_state->onEnter(this); 00153 } 00154 00155 void IsoTpHandler::processCanMessage(const CANMessage* message) 00156 { 00157 DEBUG_PRINT("Received new CAN message:\r\n"); 00158 DEBUG_PRINT(" ID: 0x%X\r\n", message->id); 00159 DEBUG_PRINT(" Len: %d\r\n", message->len); 00160 DEBUG_PRINT(" Type: %s\r\n", (message->type == CANData ? "data" : "remote")); 00161 DEBUG_PRINT(" Format: %s\r\n", (message->format == CANStandard ? "standard" : "extended")); 00162 DEBUG_PRINT( "Data: "); 00163 if (message->len > 8) { 00164 //paranoia 00165 error(" WRONG DATA LEN! "); 00166 return; 00167 } 00168 for (unsigned int i = 0; i < message->len; ++i) { 00169 DEBUG_PRINT("%X ", message->data[i]); 00170 } 00171 DEBUG_PRINT("\r\n"); 00172 m_state->processInput(message, this); 00173 } 00174 00175 void IsoTpHandler::handle_decoded_packet(const uint8_t* data, uint16_t length) 00176 { 00177 //todo write into mailbox so another thread can consume this or directly call a callback 00178 DEBUG_PRINT("New decoded packet: Length: %d\r\n", length); 00179 DEBUG_PRINT(" Data: "); 00180 for (uint16_t i = 0; i < length; ++i) 00181 { 00182 DEBUG_PRINT("%X ", data[i]); 00183 } 00184 DEBUG_PRINT("\r\n"); 00185 00186 pidDecoder.decode(data, length); 00187 } 00188 00189 void IsoTpHandler::init_consequtive_reading (uint16_t messageSize, const uint8_t* data) 00190 { 00191 char msgContent[8]; 00192 msgContent[0] = (FLOW_CONTOL_FRAME << 4) | CLEAR_TO_SEND; 00193 msgContent[1] = 0; //remaining frames should to be sent without flow control or delay 00194 msgContent[2] = 0; //Separation Time (ST), minimum delay time between frames (end of one frame and the beginning of the other) 00195 //<= 127, separation time in milliseconds. 00196 //0xF1 to 0xF9, 100 to 900 microseconds. 00197 msgContent[3] = 0; 00198 msgContent[4] = 0; 00199 msgContent[5] = 0; 00200 msgContent[6] = 0; 00201 msgContent[7] = 0; 00202 m_canInterface->write(CANMessage(0x7E0, msgContent, sizeof(msgContent))); //or 7DF? 00203 00204 memcpy(m_messageBuffer, data, 6); 00205 m_expectedMessageSize = messageSize; 00206 m_currentMessageSize = 6; 00207 m_expectedIndex = 1; 00208 } 00209 00210 void IsoTpHandler::setState(const State* state) 00211 { 00212 if (state == m_state) 00213 { 00214 return; 00215 } 00216 00217 m_state->onLeave(this); 00218 m_state = state; 00219 m_state->onEnter(this); 00220 } 00221 00222 bool IsoTpHandler::isValidIsoTpPacket(const CANMessage* message) 00223 { 00224 if (message->len < 1) 00225 { 00226 DEBUG_PRINT("Invalid iso tp message, length is zero\r\n"); 00227 return false; 00228 } 00229 uint8_t messageType = message->data[0] >> 4; 00230 if (messageType > FLOW_CONTOL_FRAME) 00231 { 00232 DEBUG_PRINT("Invalid iso tp message type %d\r\n", messageType); 00233 return false; 00234 } 00235 return true; 00236 } 00237 00238 uint8_t IsoTpHandler::getExpectedIndex() const 00239 { 00240 return m_expectedIndex; 00241 } 00242 00243 void IsoTpHandler::incrementExpectedIndex() 00244 { 00245 ++m_expectedIndex; 00246 if (m_expectedIndex >= 16) 00247 { 00248 m_expectedIndex = 0; 00249 } 00250 } 00251 00252 bool IsoTpHandler::appendReceivedData(const uint8_t* data, uint8_t length) 00253 { 00254 if (sizeof(m_messageBuffer) < m_currentMessageSize + length) 00255 { 00256 DEBUG_PRINT("Buffer in appendReceivedData too small, already got %d bytes, new %d bytes, expected %d bytes.\r\n", m_currentMessageSize, length, m_expectedMessageSize); 00257 return true; //switch state 00258 } 00259 00260 if (m_expectedMessageSize < m_currentMessageSize + length) 00261 { 00262 DEBUG_PRINT("Got too much data in appendReceivedData, already got %d bytes, new %d bytes, expected %d bytes.\r\n", m_currentMessageSize, length, m_expectedMessageSize); 00263 length = m_expectedMessageSize - m_currentMessageSize; 00264 } 00265 00266 memcpy(m_messageBuffer + m_currentMessageSize, data, length); 00267 m_currentMessageSize += length; 00268 00269 if (m_expectedMessageSize == m_currentMessageSize) 00270 { 00271 handle_decoded_packet(m_messageBuffer, m_expectedMessageSize); 00272 return true; //switch state 00273 } 00274 00275 return false; //do not switch state 00276 }
Generated on Tue Jul 12 2022 21:25:01 by
1.7.2