1 /** @req J1939TP0003 **/
\r
3 /** @req J1939TP0172 */
\r
5 /** @req J1939TP0013 */
\r
6 #include "J1939Tp_Cbk.h"
\r
7 #include "J1939Tp_Internal.h"
\r
9 /** @req J1939TP0015 */
\r
10 #include "PduR_J1939Tp.h"
\r
12 /** @req J1939TP0193 */
\r
13 #if (defined(USE_DET))
\r
17 /* Globally fulfilled requirements */
\r
18 /** @req J1939TP0123 */
\r
19 /** @req J1939TP0165 */
\r
20 /** @req J1939TP0097 */
\r
21 /** @req J1939TP0019 */
\r
22 /** @req J1939TP0184 */
\r
23 /** @req J1939TP0007 */
\r
24 /** @req J1939TP0152 */
\r
25 /** @req J1939TP0018 */
\r
26 /** @req J1939TP0036 */
\r
27 /** @req J1939TP0155 */
\r
28 /** @req J1939TP0152 */
\r
29 /** @req J1939TP0125 */
\r
30 /** @req J1939TP0174 */
\r
31 /** @req J1939TP0041 */
\r
32 /** @req J1939TP0189 */
\r
33 /** @req J1939TP0192 */
\r
34 /** @req J1939TP0156 */
\r
36 /** @req J1939TP0020 */
\r
37 static J1939Tp_Internal_GlobalStateInfoType globalState = {
\r
38 .State = J1939TP_OFF,
\r
40 static const J1939Tp_ConfigType* J1939Tp_ConfigPtr;
\r
41 static J1939Tp_Internal_ChannelInfoType channelInfos[J1939TP_CHANNEL_COUNT];
\r
42 static J1939Tp_Internal_TxChannelInfoType txChannelInfos[J1939TP_TX_CHANNEL_COUNT];
\r
43 static J1939Tp_Internal_RxChannelInfoType rxChannelInfos[J1939TP_RX_CHANNEL_COUNT];
\r
44 static J1939Tp_Internal_PgInfoType pgInfos[J1939TP_PG_COUNT];
\r
46 /** @req J1939TP0087 */
\r
47 void J1939Tp_Init(const J1939Tp_ConfigType* ConfigPtr) {
\r
48 #if (J1939TP_DEV_ERROR_DETECT == STD_ON)
\r
49 if (globalState.State == J1939TP_ON) {
\r
50 /** @req J1939TP0026 */
\r
51 J1939Tp_Internal_ReportError(J1939TP_INIT_ID, J1939TP_E_REINIT);
\r
56 for (int i = 0; i < J1939TP_CHANNEL_COUNT; i++) {
\r
57 if (ConfigPtr->Channels[i].Direction == J1939TP_TX) {
\r
58 channelInfos[i].ChannelConfPtr = &(ConfigPtr->Channels[i]);
\r
59 channelInfos[i].TxState = &(txChannelInfos[txCount]);
\r
60 channelInfos[i].TxState->State = J1939TP_TX_IDLE;
\r
61 channelInfos[i].RxState = 0;
\r
63 } else if (ConfigPtr->Channels[i].Direction == J1939TP_RX) {
\r
64 channelInfos[i].ChannelConfPtr = &(ConfigPtr->Channels[i]);
\r
65 channelInfos[i].TxState = 0;
\r
66 channelInfos[i].RxState = &(rxChannelInfos[rxCount]);
\r
67 channelInfos[i].RxState->State = J1939TP_RX_IDLE;
\r
70 return; // unexpected
\r
73 for (int i = 0; i < J1939TP_PG_COUNT; i++) {
\r
74 pgInfos[i].PgConfPtr = &(ConfigPtr->Pgs[i]);
\r
75 uint8 channelIndex = ConfigPtr->Pgs[i].Channel - ConfigPtr->Channels;
\r
76 pgInfos[i].ChannelInfoPtr = &(channelInfos[channelIndex]);
\r
79 J1939Tp_ConfigPtr = ConfigPtr;
\r
80 globalState.State = J1939TP_ON; /** @req J1939TP0022 */
\r
83 void J1939Tp_RxIndication(PduIdType RxPduId, PduInfoType* PduInfoPtr) {
\r
84 /** @req J1939TP0030 */
\r
85 if (globalState.State == J1939TP_OFF) {
\r
88 const J1939Tp_RxPduInfoType* RxPduInfo = 0;
\r
89 if (J1939Tp_Internal_GetRxPduInfo(RxPduId, &RxPduInfo) != E_OK) {
\r
92 /*if (J1939Tp_Internal_ValidatePacketType(RxPduInfo) == E_NOT_OK) {
\r
95 J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr = J1939Tp_Internal_GetChannelState(RxPduInfo);
\r
96 switch (RxPduInfo->PacketType ) {
\r
97 case J1939TP_REVERSE_CM:
\r
98 J1939Tp_Internal_RxIndication_ReverseCm(PduInfoPtr,ChannelInfoPtr);
\r
101 J1939Tp_Internal_RxIndication_Dt(PduInfoPtr,ChannelInfoPtr);
\r
104 J1939Tp_Internal_RxIndication_Cm(PduInfoPtr,ChannelInfoPtr);
\r
106 case J1939TP_DIRECT:
\r
107 J1939Tp_Internal_RxIndication_Direct(PduInfoPtr,ChannelInfoPtr);
\r
115 void J1939Tp_MainFunction(void) {
\r
116 /** @req J1939TP0030 */
\r
117 if (globalState.State == J1939TP_OFF) {
\r
120 for (int i = 0; i < J1939TP_CHANNEL_COUNT; i++) {
\r
121 J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr = &(channelInfos[i]);
\r
122 const J1939Tp_ChannelType* Channel = ChannelInfoPtr->ChannelConfPtr;
\r
123 J1939Tp_Internal_TimerStatusType timer = J1939TP_NOT_EXPIRED;
\r
124 switch (Channel->Direction) {
\r
126 switch (ChannelInfoPtr->TxState->State) {
\r
127 case J1939TP_TX_WAIT_DIRECT_SEND_CANIF_CONFIRM:
\r
128 case J1939TP_TX_WAITING_FOR_CTS:
\r
129 case J1939TP_TX_WAITING_FOR_END_OF_MSG_ACK:
\r
130 case J1939TP_TX_WAIT_DT_CANIF_CONFIRM:
\r
131 case J1939TP_TX_WAIT_RTS_CANIF_CONFIRM:
\r
132 timer = J1939Tp_Internal_IncAndCheckTimer(&(ChannelInfoPtr->TxState->TimerInfo));
\r
133 if (timer == J1939TP_EXPIRED) {
\r
134 timer = J1939TP_NOT_EXPIRED;
\r
135 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
136 if (ChannelInfoPtr->TxState->CurrentPgPtr != 0) {
\r
137 J1939Tp_Internal_SendConnectionAbort(Channel->CmNPdu,ChannelInfoPtr->TxState->CurrentPgPtr->Pgn);
\r
138 PduR_J1939TpTxConfirmation(ChannelInfoPtr->TxState->CurrentPgPtr->NSdu,NTFRSLT_E_NOT_OK);
\r
142 case J1939TP_TX_WAITING_FOR_T1_TIMEOUT:
\r
143 timer = J1939Tp_Internal_IncAndCheckTimer(&(ChannelInfoPtr->TxState->TimerInfo));
\r
144 if (timer == J1939TP_EXPIRED) {
\r
145 timer = J1939TP_NOT_EXPIRED;
\r
146 ChannelInfoPtr->TxState->State = J1939TP_TX_WAIT_DT_BAM_CANIF_CONFIRM;
\r
147 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_TX_CONF_TIMEOUT);
\r
148 J1939Tp_Internal_SendDt(ChannelInfoPtr);
\r
158 switch (ChannelInfoPtr->RxState->State) {
\r
159 case J1939TP_RX_WAIT_CTS_CANIF_CONFIRM:
\r
160 case J1939TP_RX_RECEIVING_DT:
\r
161 case J1939TP_RX_WAIT_ENDOFMSGACK_CANIF_CONFIRM:
\r
162 timer = J1939Tp_Internal_IncAndCheckTimer(&(ChannelInfoPtr->RxState->TimerInfo));
\r
166 if (timer == J1939TP_EXPIRED) {
\r
167 timer = J1939TP_NOT_EXPIRED;
\r
168 ChannelInfoPtr->RxState->State = J1939TP_RX_IDLE;
\r
169 if (Channel->Protocol == J1939TP_PROTOCOL_CMDT) {
\r
170 J1939Tp_Internal_SendConnectionAbort(Channel->FcNPdu,ChannelInfoPtr->RxState->CurrentPgPtr->Pgn);
\r
171 PduR_J1939TpRxIndication(ChannelInfoPtr->RxState->CurrentPgPtr->NSdu,NTFRSLT_E_NOT_OK);
\r
179 void J1939Tp_TxConfirmation(PduIdType RxPdu) {
\r
180 /** @req J1939TP0030 */
\r
181 if (globalState.State == J1939TP_OFF) {
\r
184 const J1939Tp_RxPduInfoType* RxPduInfo = 0;
\r
185 if (J1939Tp_Internal_GetRxPduInfo(RxPdu, &RxPduInfo) != E_OK) {
\r
189 const J1939Tp_ChannelType* Channel = J1939Tp_Internal_GetChannel(RxPduInfo);
\r
190 J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr = J1939Tp_Internal_GetChannelState(RxPduInfo);
\r
191 switch (Channel->Direction) {
\r
193 J1939Tp_Internal_TxConfirmation_TxChannel(ChannelInfoPtr, RxPduInfo);
\r
196 J1939Tp_Internal_TxConfirmation_RxChannel(ChannelInfoPtr, RxPduInfo);
\r
203 static inline const J1939Tp_ChannelType* J1939Tp_Internal_GetChannel(const J1939Tp_RxPduInfoType* RxPduInfo) {
\r
204 return &(J1939Tp_ConfigPtr->Channels[RxPduInfo->ChannelIndex]);
\r
206 static inline J1939Tp_Internal_ChannelInfoType* J1939Tp_Internal_GetChannelState(const J1939Tp_RxPduInfoType* RxPduInfo) {
\r
207 return &(channelInfos[RxPduInfo->ChannelIndex]);
\r
209 static inline Std_ReturnType J1939Tp_Internal_ValidatePacketType(const J1939Tp_RxPduInfoType* RxPduInfo) {
\r
210 const J1939Tp_ChannelType* ChannelPtr = J1939Tp_Internal_GetChannel(RxPduInfo);
\r
211 switch (RxPduInfo->PacketType) {
\r
212 case J1939TP_REVERSE_CM:
\r
213 if (ChannelPtr->Direction != J1939TP_TX ) {
\r
218 if (ChannelPtr->Direction != J1939TP_RX) {
\r
223 if (ChannelPtr->Direction != J1939TP_RX) {
\r
232 static inline void J1939Tp_Internal_RxIndication_Direct(PduInfoType* PduInfoPtr, J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
233 if (PduInfoPtr->SduLength != DIRECT_TRANSMIT_SIZE) {
\r
236 const J1939Tp_PgType* Pg = ChannelInfoPtr->RxState->CurrentPgPtr;
\r
237 PduInfoType* rxPduInfo;
\r
238 BufReq_ReturnType r = PduR_J1939TpProvideRxBuffer(Pg->NSdu, DIRECT_TRANSMIT_SIZE, &rxPduInfo);
\r
239 if (r == BUFREQ_OK) {
\r
240 memcpy(rxPduInfo->SduDataPtr,&(PduInfoPtr),DIRECT_TRANSMIT_SIZE);
\r
241 PduR_J1939TpRxIndication(Pg->NSdu,NTFRSLT_OK);
\r
242 ChannelInfoPtr->RxState->State = J1939TP_RX_IDLE;
\r
245 static inline uint8 J1939Tp_Internal_GetDtPacketsInNextCts(uint8 receivedDtPackets, uint8 totalDtPacketsToReceive) {
\r
246 uint8 packetsLeft = totalDtPacketsToReceive - receivedDtPackets;
\r
247 if (packetsLeft < (J1939TP_PACKETS_PER_BLOCK)) {
\r
248 return packetsLeft;
\r
250 return J1939TP_PACKETS_PER_BLOCK;
\r
253 static inline void J1939Tp_Internal_RxIndication_Dt(PduInfoType* PduInfoPtr, J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
254 PduInfoType* rxPduInfo;
\r
255 if (ChannelInfoPtr->RxState->CurrentPgPtr == 0) {
\r
258 if (ChannelInfoPtr->RxState->State != J1939TP_RX_RECEIVING_DT) {
\r
261 PduIdType PduRSdu = ChannelInfoPtr->RxState->CurrentPgPtr->NSdu;
\r
262 uint8 requestSize = DT_DATA_SIZE;
\r
263 boolean lastMessage = false;
\r
265 ChannelInfoPtr->RxState->ReceivedDtCount++;
\r
266 uint8 expectedSeqNumber = ChannelInfoPtr->RxState->ReceivedDtCount;
\r
267 uint8 seqNumber = PduInfoPtr->SduDataPtr[DT_BYTE_SEQ_NUM];
\r
268 if (seqNumber != expectedSeqNumber) {
\r
269 ChannelInfoPtr->RxState->State = J1939TP_RX_IDLE;
\r
270 if (ChannelInfoPtr->ChannelConfPtr->Protocol == J1939TP_PROTOCOL_CMDT) {
\r
271 J1939Tp_PgnType pgn = ChannelInfoPtr->RxState->CurrentPgPtr->Pgn;
\r
272 J1939Tp_Internal_SendConnectionAbort(ChannelInfoPtr->ChannelConfPtr->FcNPdu,pgn);
\r
276 BufReq_ReturnType r = PduR_J1939TpProvideRxBuffer(PduRSdu, requestSize, &rxPduInfo);
\r
277 if (r == BUFREQ_OK) {
\r
278 memcpy(rxPduInfo->SduDataPtr,&(PduInfoPtr[DT_BYTE_DATA_1]),requestSize);
\r
280 if (J1939Tp_Internal_IsLastDtBeforeNextCts(ChannelInfoPtr->RxState)) {
\r
281 J1939Tp_PgnType pgn = ChannelInfoPtr->RxState->CurrentPgPtr->Pgn;
\r
282 uint8 requestPackets = J1939Tp_Internal_GetDtPacketsInNextCts(ChannelInfoPtr->RxState->ReceivedDtCount,ChannelInfoPtr->RxState->DtToReceiveCount);
\r
283 ChannelInfoPtr->RxState->State = J1939TP_RX_WAIT_CTS_CANIF_CONFIRM;
\r
284 J1939Tp_Internal_SendCts(ChannelInfoPtr, pgn, ChannelInfoPtr->RxState->ReceivedDtCount+1,requestPackets);
\r
286 else if (J1939Tp_Internal_IsLastDt(ChannelInfoPtr->RxState)) {
\r
287 lastMessage = true;
\r
288 J1939Tp_Internal_DtPayloadSizeType receivedBytes = ChannelInfoPtr->RxState->ReceivedDtCount*DT_DATA_SIZE;
\r
289 requestSize = ChannelInfoPtr->RxState->TotalMessageSize - receivedBytes;
\r
290 J1939Tp_Internal_SendEndOfMsgAck(ChannelInfoPtr);
\r
291 ChannelInfoPtr->RxState->State = J1939TP_RX_IDLE;
\r
292 PduR_J1939TpRxIndication(PduRSdu,NTFRSLT_OK);
\r
294 J1939Tp_Internal_RxSessionStartTimer(ChannelInfoPtr->RxState,J1939TP_T1_TIMEOUT_MS);
\r
298 static inline void J1939Tp_Internal_RxIndication_Cm(PduInfoType* PduInfoPtr, J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
299 const J1939Tp_PgType* pg = 0;
\r
300 J1939Tp_PgnType pgn = J1939Tp_Internal_GetPgn(&(PduInfoPtr->SduDataPtr[CM_PGN_BYTE_1]));
\r
301 uint8 pf = J1939Tp_Internal_GetPf(pgn);
\r
302 J1939Tp_ProtocolType protocol = J1939Tp_Internal_GetProtocol(pf);
\r
303 if (J1939Tp_Internal_GetPgFromPgn(ChannelInfoPtr->ChannelConfPtr,pgn,&pg) != E_OK) {
\r
306 /** @req J1939TP0173 **/
\r
307 if (protocol == J1939TP_PROTOCOL_BAM && pg->Channel->Protocol != protocol) {
\r
310 if (protocol == J1939TP_PROTOCOL_CMDT && pg->Channel->Protocol != protocol) {
\r
311 J1939Tp_Internal_SendConnectionAbort(pg->Channel->CmNPdu,pgn);
\r
313 uint8 Command = PduInfoPtr->SduDataPtr[CM_BYTE_CONTROL];
\r
315 /** @req J1939TP0043**/
\r
316 J1939Tp_Internal_DtPayloadSizeType messageSize = 0;
\r
317 messageSize = J1939Tp_Internal_GetRtsMessageSize(PduInfoPtr);
\r
319 if (Command == RTS_CONTROL_VALUE || Command == BAM_CONTROL_VALUE) {
\r
320 ChannelInfoPtr->RxState->ReceivedDtCount = 0;
\r
321 ChannelInfoPtr->RxState->DtToReceiveCount = PduInfoPtr->SduDataPtr[BAM_RTS_BYTE_NUM_PACKETS];
\r
322 ChannelInfoPtr->RxState->TotalMessageSize = messageSize;
\r
323 ChannelInfoPtr->RxState->CurrentPgPtr = pg;
\r
324 if (Command == RTS_CONTROL_VALUE) {
\r
325 ChannelInfoPtr->RxState->State = J1939TP_RX_WAIT_CTS_CANIF_CONFIRM;
\r
326 J1939Tp_Internal_RxSessionStartTimer(ChannelInfoPtr->RxState,J1939TP_TX_CONF_TIMEOUT);
\r
327 J1939Tp_Internal_SendCts(ChannelInfoPtr,pgn,CTS_START_SEQ_NUM,J1939TP_PACKETS_PER_BLOCK);
\r
329 } else if (Command == BAM_CONTROL_VALUE) {
\r
330 J1939Tp_Internal_RxSessionStartTimer(ChannelInfoPtr->RxState,J1939TP_T2_TIMEOUT_MS);
\r
331 ChannelInfoPtr->RxState->State = J1939TP_RX_RECEIVING_DT;
\r
333 } else if (Command == CONNABORT_BYTE_CONTROL) {
\r
334 ChannelInfoPtr->RxState->State = J1939TP_RX_IDLE;
\r
338 static inline void J1939Tp_Internal_RxIndication_ReverseCm(PduInfoType* PduInfoPtr, J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
339 const J1939Tp_PgType* pg = 0;
\r
340 J1939Tp_PgnType pgn = J1939Tp_Internal_GetPgn(&(PduInfoPtr->SduDataPtr[CM_PGN_BYTE_1]));
\r
341 if (J1939Tp_Internal_GetPgFromPgn(ChannelInfoPtr->ChannelConfPtr,pgn,&pg) != E_OK) {
\r
344 uint8 Command = PduInfoPtr->SduDataPtr[CM_BYTE_CONTROL];
\r
346 case CTS_CONTROL_VALUE:
\r
347 if (ChannelInfoPtr->TxState->State == J1939TP_TX_WAITING_FOR_CTS) {
\r
348 uint8 NumPacketsToSend = PduInfoPtr->SduDataPtr[CTS_BYTE_NUM_PACKETS];
\r
349 uint8 NextPacket = PduInfoPtr->SduDataPtr[CTS_BYTE_NEXT_PACKET];
\r
350 if (NumPacketsToSend == 0) {
\r
351 // Receiver wants to keep the connection open but cant receive packets
\r
352 /** @req J1939TP0195 */
\r
353 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T4_TIMEOUT_MS);
\r
354 } else if(J1939Tp_Internal_IsDtPacketAlreadySent(NextPacket,ChannelInfoPtr->TxState->SentDtCount)) {
\r
355 PduR_J1939TpTxConfirmation(pg->NSdu,NTFRSLT_E_NOT_OK);
\r
356 /** @req J1939TP0190 */
\r
357 J1939Tp_Internal_SendConnectionAbort(ChannelInfoPtr->ChannelConfPtr->CmNPdu,pgn);
\r
358 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
360 ChannelInfoPtr->TxState->DtToSendBeforeCtsCount = NumPacketsToSend;
\r
361 ChannelInfoPtr->TxState->State = J1939TP_TX_WAIT_DT_CANIF_CONFIRM;
\r
362 J1939Tp_Internal_SendDt(ChannelInfoPtr);
\r
363 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_TX_CONF_TIMEOUT);
\r
367 case ENDOFMSGACK_CONTROL_VALUE:
\r
368 if (ChannelInfoPtr->TxState->State == J1939TP_TX_WAITING_FOR_END_OF_MSG_ACK) {
\r
369 PduR_J1939TpTxConfirmation(pg->NSdu,NTFRSLT_OK);
\r
370 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
373 case CONNABORT_CONTROL_VALUE:
\r
374 PduR_J1939TpTxConfirmation(pg->NSdu,NTFRSLT_E_NOT_OK);
\r
375 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
382 /** @req J1939TP0180 */
\r
383 Std_ReturnType J1939Tp_ChangeParameterRequest(PduIdType SduId, TPParameterType Parameter, uint16 value) {
\r
384 return E_NOT_OK; /** @req J1939TP0181 */
\r
386 static inline void J1939Tp_Internal_TxConfirmation_RxChannel(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr, const J1939Tp_RxPduInfoType* RxPduInfo) {
\r
387 switch (RxPduInfo->PacketType ) {
\r
388 case J1939TP_REVERSE_CM:
\r
389 if (ChannelInfoPtr->RxState->State == J1939TP_RX_WAIT_CTS_CANIF_CONFIRM) {
\r
390 J1939Tp_Internal_RxSessionStartTimer(ChannelInfoPtr->RxState,J1939TP_T2_TIMEOUT_MS);
\r
391 ChannelInfoPtr->RxState->State = J1939TP_RX_RECEIVING_DT;
\r
398 static inline boolean J1939Tp_Internal_IsDtPacketAlreadySent(uint8 nextPacket, uint8 totalPacketsSent) {
\r
399 return nextPacket < totalPacketsSent;
\r
401 static inline Std_ReturnType J1939Tp_Internal_GetRxPduInfo(PduIdType RxPdu,const const J1939Tp_RxPduInfoType** RxPduInfo) {
\r
402 if (RxPdu < J1939TP_RX_PDU_COUNT) {
\r
403 *RxPduInfo = &(J1939Tp_ConfigPtr->RxPdus[RxPdu]);
\r
410 static inline Std_ReturnType J1939Tp_Internal_GetPgFromPgn(const J1939Tp_ChannelType* channel, J1939Tp_Internal_PgnType Pgn, const J1939Tp_PgType** Pg) {
\r
411 for (int i = 0; i < channel->PgCount; i++) {
\r
412 if (channel->Pgs[i]->Pgn == Pgn) {
\r
413 *Pg = channel->Pgs[i];
\r
421 static inline boolean J1939Tp_Internal_IsLastDtBeforeNextCts(J1939Tp_Internal_RxChannelInfoType* rxChannelInfo) {
\r
422 boolean finalDt = rxChannelInfo->ReceivedDtCount == rxChannelInfo->DtToReceiveCount;
\r
423 boolean sendNewCts = rxChannelInfo->ReceivedDtCount % J1939TP_PACKETS_PER_BLOCK == 0;
\r
424 return !finalDt && sendNewCts;
\r
428 static inline boolean J1939Tp_Internal_IsLastDt(J1939Tp_Internal_RxChannelInfoType* rxChannelInfo) {
\r
429 return (rxChannelInfo->DtToReceiveCount == rxChannelInfo->ReceivedDtCount);
\r
431 static inline void J1939Tp_Internal_TxConfirmation_TxChannel(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr, const J1939Tp_RxPduInfoType* RxPduInfo) {
\r
432 J1939Tp_Internal_TxChannelStateType State = ChannelInfoPtr->TxState->State;
\r
433 switch (RxPduInfo->PacketType ) {
\r
434 case J1939TP_REVERSE_CM:
\r
437 if (State == J1939TP_TX_WAIT_RTS_CANIF_CONFIRM) {
\r
438 ChannelInfoPtr->TxState->State = J1939TP_TX_WAITING_FOR_CTS;
\r
439 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T3_TIMEOUT_MS);
\r
440 } else if (State == J1939TP_TX_WAIT_BAM_CANIF_CONFIRM) {
\r
441 ChannelInfoPtr->TxState->State = J1939TP_TX_WAITING_FOR_T1_TIMEOUT;
\r
442 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T1_TIMEOUT_MS);
\r
446 if (State == J1939TP_TX_WAIT_DT_CANIF_CONFIRM) {
\r
447 ChannelInfoPtr->TxState->SentDtCount++;
\r
448 if (J1939Tp_Internal_LastDtSent(ChannelInfoPtr->TxState)) {
\r
449 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T3_TIMEOUT_MS);
\r
450 ChannelInfoPtr->TxState->State = J1939TP_TX_WAITING_FOR_END_OF_MSG_ACK;
\r
451 } else if (J1939Tp_Internal_WaitForCts(ChannelInfoPtr->TxState)) {
\r
452 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T3_TIMEOUT_MS);
\r
453 ChannelInfoPtr->TxState->State = J1939TP_TX_WAITING_FOR_CTS;
\r
455 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_TX_CONF_TIMEOUT);
\r
456 J1939Tp_Internal_SendDt(ChannelInfoPtr);
\r
459 else if (State == J1939TP_TX_WAIT_DT_BAM_CANIF_CONFIRM) {
\r
460 ChannelInfoPtr->TxState->SentDtCount++;
\r
461 if (J1939Tp_Internal_LastDtSent(ChannelInfoPtr->TxState)) {
\r
462 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
463 PduR_J1939TpTxConfirmation(ChannelInfoPtr->TxState->CurrentPgPtr->NSdu,NTFRSLT_OK);
\r
465 ChannelInfoPtr->TxState->State = J1939TP_TX_WAITING_FOR_T1_TIMEOUT;
\r
466 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_T1_TIMEOUT_MS);
\r
470 case J1939TP_DIRECT:
\r
471 if (State == J1939TP_TX_WAIT_DIRECT_SEND_CANIF_CONFIRM) {
\r
472 ChannelInfoPtr->TxState->State = J1939TP_TX_IDLE;
\r
473 PduR_J1939TpTxConfirmation(ChannelInfoPtr->TxState->CurrentPgPtr->NSdu, NTFRSLT_OK);
\r
480 static inline Std_ReturnType J1939Tp_Internal_GetPg(PduIdType TxSduId,J1939Tp_Internal_PgInfoType** PgInfo) {
\r
481 if (TxSduId < J1939TP_PG_COUNT) {
\r
482 *PgInfo = &(pgInfos[TxSduId]);
\r
487 Std_ReturnType J1939Tp_CancelTransmitRequest(PduIdType TxSduId) {
\r
488 /** @req J1939TP0179 **/
\r
489 J1939Tp_Internal_PgInfoType* PgInfo;
\r
490 if (J1939Tp_Internal_GetPg(TxSduId,&PgInfo) == E_NOT_OK) {
\r
493 PduR_J1939TpTxConfirmation(PgInfo->PgConfPtr->NSdu,NTFRSLT_E_CANCELATION_NOT_OK);
\r
496 Std_ReturnType J1939Tp_CancelReceiveRequest(PduIdType RxSduId) {
\r
497 /** @req J1939TP0178 **/
\r
498 J1939Tp_Internal_PgInfoType* PgInfo;
\r
499 if (J1939Tp_Internal_GetPg(RxSduId,&PgInfo) == E_NOT_OK) {
\r
502 PduR_J1939TpTxConfirmation(PgInfo->PgConfPtr->NSdu,NTFRSLT_E_CANCELATION_NOT_OK);
\r
505 /** @req J1939TP0096 */
\r
506 Std_ReturnType J1939Tp_Transmit(PduIdType TxSduId, const PduInfoType* TxInfoPtr) {
\r
507 #if J1939TP_DEV_ERROR_DETECT
\r
508 if (globalState.State == J1939TP_OFF) {
\r
509 J1939Tp_Internal_ReportError(J1939TP_TRANSMIT_ID,J1939TP_E_UNINIT);
\r
512 /** @req J1939TP0030 */
\r
513 if (globalState.State == J1939TP_OFF) {
\r
516 J1939Tp_Internal_PgInfoType* PgInfo;
\r
518 if (J1939Tp_Internal_GetPg(TxSduId,&PgInfo) == E_NOT_OK) {
\r
521 const J1939Tp_PgType* Pg = PgInfo->PgConfPtr;
\r
522 J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr = PgInfo->ChannelInfoPtr;
\r
523 /** @req J1939TP0101 **/
\r
524 if (ChannelInfoPtr->TxState->State != J1939TP_TX_IDLE) {
\r
527 if (TxInfoPtr->SduLength <= 8) { // direct transmit
\r
528 PduInfoType* ToSendTxInfoPtr;
\r
529 PduR_J1939TpProvideTxBuffer(Pg->NSdu, &ToSendTxInfoPtr, TxInfoPtr->SduLength);
\r
530 PduIdType CanIfPdu = Pg->DirectNPdu;
\r
531 ChannelInfoPtr->TxState->State = J1939TP_TX_WAIT_DIRECT_SEND_CANIF_CONFIRM;
\r
532 ChannelInfoPtr->TxState->CurrentPgPtr = Pg;
\r
533 CanIf_Transmit(CanIfPdu,ToSendTxInfoPtr);
\r
535 uint8 pf = J1939Tp_Internal_GetPf(Pg->Pgn);
\r
536 J1939Tp_ProtocolType protocol = J1939Tp_Internal_GetProtocol(pf);
\r
537 switch (protocol) { /** @req J1939TP0039*/
\r
538 case J1939TP_PROTOCOL_BAM:
\r
539 ChannelInfoPtr->TxState->State = J1939TP_TX_WAIT_BAM_CANIF_CONFIRM;
\r
540 ChannelInfoPtr->TxState->TotalMessageSize = TxInfoPtr->SduLength;
\r
541 ChannelInfoPtr->TxState->CurrentPgPtr = Pg;
\r
542 ChannelInfoPtr->TxState->SentDtCount = 0;
\r
543 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_TX_CONF_TIMEOUT);
\r
544 J1939Tp_Internal_SendBam(ChannelInfoPtr,TxInfoPtr);
\r
546 case J1939TP_PROTOCOL_CMDT:
\r
547 ChannelInfoPtr->TxState->State = J1939TP_TX_WAIT_RTS_CANIF_CONFIRM;
\r
548 ChannelInfoPtr->TxState->TotalMessageSize = TxInfoPtr->SduLength;
\r
549 ChannelInfoPtr->TxState->PduRPdu = TxSduId;
\r
550 ChannelInfoPtr->TxState->CurrentPgPtr = Pg;
\r
551 ChannelInfoPtr->TxState->SentDtCount = 0;
\r
552 J1939Tp_Internal_SendRts(ChannelInfoPtr,TxInfoPtr);
\r
553 J1939Tp_Internal_TxSessionStartTimer(ChannelInfoPtr->TxState,J1939TP_TX_CONF_TIMEOUT);
\r
559 static inline void J1939Tp_Internal_SendBam(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr,const PduInfoType* TxInfoPtr) {
\r
560 uint8 cmBamData[BAM_RTS_SIZE];
\r
561 cmBamData[BAM_RTS_BYTE_CONTROL] = BAM_CONTROL_VALUE;
\r
562 cmBamData[BAM_RTS_BYTE_LENGTH_1] = (uint8)(TxInfoPtr->SduLength & 0x00FF);
\r
563 cmBamData[BAM_RTS_BYTE_LENGTH_2] = (uint8)(TxInfoPtr->SduLength & 0xFF00);
\r
565 J1939Tp_PgnType pgn = ChannelInfoPtr->TxState->CurrentPgPtr->Pgn;
\r
566 cmBamData[BAM_RTS_BYTE_NUM_PACKETS] = J1939TP_Internal_GetNumDtPacketsToSend(TxInfoPtr->SduLength);
\r
567 cmBamData[BAM_RTS_BYTE_SAE_ASSIGN] = 0xFF;
\r
568 J1939Tp_Internal_SetPgn(&(cmBamData[BAM_RTS_BYTE_PGN_1]),pgn);
\r
570 PduInfoType cmBamPdu;
\r
571 cmBamPdu.SduLength = BAM_RTS_SIZE;
\r
572 cmBamPdu.SduDataPtr = cmBamData;
\r
574 CanIf_Transmit(ChannelInfoPtr->ChannelConfPtr->CmNPdu,&cmBamPdu);
\r
576 static inline uint16 J1939Tp_Internal_GetRtsMessageSize(PduInfoType* pduInfo) {
\r
577 return (((uint16)pduInfo->SduDataPtr[BAM_RTS_BYTE_LENGTH_1]) << 8) | pduInfo->SduDataPtr[BAM_RTS_BYTE_LENGTH_2];
\r
580 static inline boolean J1939Tp_Internal_WaitForCts(J1939Tp_Internal_TxChannelInfoType* TxChannelState) {
\r
581 return TxChannelState->SentDtCount == TxChannelState->DtToSendBeforeCtsCount;
\r
584 static inline uint8 J1939TP_Internal_GetNumDtPacketsToSend(uint16 messageSize) {
\r
585 uint8 packetsToSend = 0;
\r
586 packetsToSend = messageSize/DT_DATA_SIZE;
\r
587 if (messageSize % DT_DATA_SIZE != 0) {
\r
588 packetsToSend = packetsToSend + 1;
\r
590 return packetsToSend;
\r
592 static inline boolean J1939Tp_Internal_LastDtSent(J1939Tp_Internal_TxChannelInfoType* TxChannelState) {
\r
593 return J1939TP_Internal_GetNumDtPacketsToSend(TxChannelState->TotalMessageSize) == TxChannelState->SentDtCount;
\r
596 static inline Std_ReturnType J1939Tp_Internal_ConfGetPg(PduIdType NSduId, const J1939Tp_PgType* Pg) {
\r
597 if (NSduId < J1939TP_PG_COUNT) {
\r
598 Pg = &(J1939Tp_ConfigPtr->Pgs[NSduId]);
\r
605 static inline J1939Tp_Internal_TimerStatusType J1939Tp_Internal_IncAndCheckTimer(J1939Tp_Internal_TimerType* TimerInfo) {
\r
606 TimerInfo->Timer += J1939TP_MAIN_FUNCTION_PERIOD;
\r
607 if (TimerInfo->Timer >= TimerInfo->TimerExpire) {
\r
608 return J1939TP_EXPIRED;
\r
610 return J1939TP_NOT_EXPIRED;
\r
612 static inline uint8 J1939Tp_Internal_GetPf(J1939Tp_PgnType pgn) {
\r
613 return (uint8)(pgn >> 8);
\r
615 static J1939Tp_ProtocolType J1939Tp_Internal_GetProtocol(uint8 pf) {
\r
617 return J1939TP_PROTOCOL_CMDT;
\r
619 return J1939TP_PROTOCOL_BAM;
\r
624 static inline void J1939Tp_Internal_SendDt(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
625 uint8 requestLength = DT_DATA_SIZE;
\r
626 uint8 bytesLeftToSend = ChannelInfoPtr->TxState->TotalMessageSize - ChannelInfoPtr->TxState->SentDtCount * DT_DATA_SIZE;
\r
627 if (bytesLeftToSend < DT_DATA_SIZE){
\r
628 requestLength = bytesLeftToSend;
\r
630 // prepare dt message
\r
631 uint8 dtBuffer[DT_SIZE] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
\r
632 PduInfoType dtPduInfoBuffer;
\r
633 dtPduInfoBuffer.SduLength = DT_SIZE;
\r
634 dtPduInfoBuffer.SduDataPtr = dtBuffer;
\r
636 BufReq_ReturnType allocateBufferRes;
\r
637 PduInfoType* dataPduInfoBuffer;
\r
638 PduIdType Pdur_NSdu = ChannelInfoPtr->TxState->CurrentPgPtr->NSdu;
\r
639 allocateBufferRes = PduR_J1939TpProvideTxBuffer(Pdur_NSdu, &dataPduInfoBuffer, requestLength);
\r
640 if (allocateBufferRes == BUFREQ_OK) {
\r
641 dtPduInfoBuffer.SduDataPtr[DT_BYTE_SEQ_NUM] = ChannelInfoPtr->TxState->SentDtCount+1;
\r
642 memcpy(&(dtPduInfoBuffer.SduDataPtr[DT_BYTE_DATA_1]), dataPduInfoBuffer, requestLength);
\r
643 PduIdType CanIf_NSdu = ChannelInfoPtr->ChannelConfPtr->DtNPdu;
\r
644 CanIf_Transmit(CanIf_NSdu, &dtPduInfoBuffer);
\r
647 /* Todo: check for error */
\r
652 static inline void J1939Tp_Internal_SendRts(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr, const PduInfoType* TxInfoPtr) {
\r
653 uint8 cmRtsData[BAM_RTS_SIZE];
\r
654 cmRtsData[BAM_RTS_BYTE_CONTROL] = 16;
\r
655 cmRtsData[BAM_RTS_BYTE_LENGTH_1] = (uint8)(TxInfoPtr->SduLength >> 8);
\r
656 cmRtsData[BAM_RTS_BYTE_LENGTH_2] = (uint8)(TxInfoPtr->SduLength);
\r
658 J1939Tp_PgnType pgn = ChannelInfoPtr->TxState->CurrentPgPtr->Pgn;
\r
659 cmRtsData[BAM_RTS_BYTE_NUM_PACKETS] = J1939TP_Internal_GetNumDtPacketsToSend(TxInfoPtr->SduLength);
\r
660 cmRtsData[BAM_RTS_BYTE_SAE_ASSIGN] = 0xFF;
\r
661 J1939Tp_Internal_SetPgn(&(cmRtsData[BAM_RTS_BYTE_PGN_1]),pgn);
\r
663 PduInfoType cmRtsPdu;
\r
664 cmRtsPdu.SduLength = BAM_RTS_SIZE;
\r
665 cmRtsPdu.SduDataPtr = cmRtsData;
\r
667 CanIf_Transmit(ChannelInfoPtr->ChannelConfPtr->CmNPdu,&cmRtsPdu);
\r
670 static inline void J1939Tp_Internal_SendEndOfMsgAck(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr) {
\r
671 PduInfoType endofmsgInfo;
\r
672 uint8 endofmsgData[ENDOFMSGACK_SIZE];
\r
673 endofmsgInfo.SduLength = ENDOFMSGACK_SIZE;
\r
674 endofmsgInfo.SduDataPtr = endofmsgData;
\r
675 endofmsgData[ENDOFMSGACK_BYTE_CONTROL] = ENDOFMSGACK_CONTROL_VALUE;
\r
676 endofmsgData[ENDOFMSGACK_BYTE_TOTAL_MSG_SIZE_1] = ((uint8)(ChannelInfoPtr->RxState->TotalMessageSize)) << 8;
\r
677 endofmsgData[ENDOFMSGACK_BYTE_TOTAL_MSG_SIZE_2] = ((uint8)(ChannelInfoPtr->RxState->TotalMessageSize));
\r
678 endofmsgData[ENDOFMSGACK_BYTE_NUM_PACKETS] = ChannelInfoPtr->RxState->ReceivedDtCount;
\r
679 endofmsgData[ENDOFMSGACK_BYTE_SAE_ASSIGN] = 0xFF;
\r
680 J1939Tp_Internal_SetPgn(&(endofmsgData[ENDOFMSGACK_BYTE_PGN_1]),ChannelInfoPtr->RxState->CurrentPgPtr->Pgn);
\r
681 PduIdType CmNPdu = ChannelInfoPtr->ChannelConfPtr->FcNPdu;
\r
683 CanIf_Transmit(CmNPdu,&endofmsgInfo);
\r
687 * Send a response to the incoming RTS
\r
689 * @param RtsPduInfoPtr needs to be a valid RTS message
\r
691 static inline void J1939Tp_Internal_SendCts(J1939Tp_Internal_ChannelInfoType* ChannelInfoPtr, J1939Tp_PgnType Pgn, uint8 NextPacketSeqNum,uint8 NumPackets) {
\r
692 PduInfoType ctsInfo;
\r
693 uint8 ctsData[CTS_SIZE];
\r
694 ctsInfo.SduLength = CTS_SIZE;
\r
695 ctsInfo.SduDataPtr = ctsData;
\r
696 ctsData[CTS_BYTE_CONTROL] = CTS_CONTROL_VALUE;
\r
697 ctsData[CTS_BYTE_NUM_PACKETS] = NumPackets;
\r
698 ctsData[CTS_BYTE_NEXT_PACKET] = NextPacketSeqNum;
\r
699 ctsData[CTS_BYTE_SAE_ASSIGN_1] = 0xFF;
\r
700 ctsData[CTS_BYTE_SAE_ASSIGN_2] = 0xFF;
\r
701 J1939Tp_Internal_SetPgn(&(ctsData[BAM_RTS_BYTE_PGN_1]),Pgn);
\r
703 CanIf_Transmit(ChannelInfoPtr->ChannelConfPtr->FcNPdu,&ctsInfo);
\r
706 static inline void J1939Tp_Internal_SendConnectionAbort(PduIdType CmNPdu, J1939Tp_PgnType Pgn) {
\r
707 PduInfoType connAbortInfo;
\r
708 uint8 connAbortData[CONNABORT_SIZE];
\r
709 connAbortInfo.SduLength = CONNABORT_SIZE;
\r
710 connAbortInfo.SduDataPtr = connAbortData;
\r
711 connAbortData[CONNABORT_BYTE_CONTROL] = CTS_CONTROL_VALUE;
\r
712 connAbortData[CONNABORT_BYTE_SAE_ASSIGN_1] = 0xFF;
\r
713 connAbortData[CONNABORT_BYTE_SAE_ASSIGN_2] = 0xFF;
\r
714 connAbortData[CONNABORT_BYTE_SAE_ASSIGN_3] = 0xFF;
\r
715 connAbortData[CONNABORT_BYTE_SAE_ASSIGN_4] = 0xFF;
\r
716 J1939Tp_Internal_SetPgn(&(connAbortData[CONNABORT_BYTE_PGN_1]),Pgn);
\r
717 CanIf_Transmit(CmNPdu,&connAbortInfo);
\r
719 static inline void J1939Tp_Internal_TxSessionStartTimer(J1939Tp_Internal_TxChannelInfoType* Tx,uint16 TimerExpire) {
\r
720 Tx->TimerInfo.Timer = 0;
\r
721 Tx->TimerInfo.TimerExpire = TimerExpire;
\r
723 static inline void J1939Tp_Internal_RxSessionStartTimer(J1939Tp_Internal_RxChannelInfoType* Rx,uint16 TimerExpire) {
\r
724 Rx->TimerInfo.Timer = 0;
\r
725 Rx->TimerInfo.TimerExpire = TimerExpire;
\r
728 * set three bytes to a 18 bit pgn value
729 * @param PgnBytes must be three uint8 bytes
732 static inline void J1939Tp_Internal_SetPgn(uint8* PgnBytes,J1939Tp_PgnType pgn ) {
\r
733 PgnBytes[2] = pgn; /* get first byte */
\r
734 PgnBytes[1] = pgn >> 8; /* get next byte */
\r
735 PgnBytes[0] = (pgn >> 16) & 0x3; /* get next two bits */
\r
738 * return a 18 bit pgn value from three bytes
739 * @param PgnBytes must be three uint8 bytes
742 static inline J1939Tp_PgnType J1939Tp_Internal_GetPgn(uint8* PgnBytes) {
\r
743 J1939Tp_PgnType pgn = 0;
\r
744 pgn = ((uint32)PgnBytes[0]) << 16;
\r
745 pgn = pgn | (((uint32)PgnBytes[1]) << 8);
\r
746 pgn = pgn | ((uint32)PgnBytes[2]);
\r
750 static inline void J1939Tp_Internal_ReportError(uint8 ApiId, uint8 ErrorId) {
\r
751 #if (CANSM_DEV_ERROR_DETECT == STD_ON)
\r
752 Det_ReportError(MODULE_ID_J1939TP, 0, ApiId, ApiId);
\r