]> rtime.felk.cvut.cz Git - arc.git/blob - communication/CanNm/CanNm.c
#ifdef:ed all Det includes
[arc.git] / communication / CanNm / CanNm.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 //lint -emacro(904,CANNM_VALIDATE_INIT,CANNM_VALIDATE_CHANNEL,CANNM_VALIDATE_NOTNULL) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
17 \r
18 \r
19 /* Globally fulfilled requirements */\r
20 /** @req CANNM081 */\r
21 /** @req CANNM044 */\r
22 /** @req CANNM050 */\r
23 /** @req CANNM088 */\r
24 /** @req CANNM089 */\r
25 /** @req CANNM090 */\r
26 /** @req CANNM093 */\r
27 /** @req CANNM206 */\r
28 /** @req CANNM125 */\r
29 /** @req CANNM140 */\r
30 /** @req CANNM142 */\r
31 /** @req CANNM145 */\r
32 /** @req CANNM146 */\r
33 /** @req CANNM039 */\r
34 /** @req CANNM001.mandatory */\r
35 /** @req CANNM158 */\r
36 /** @req CANNM161 */\r
37 /** @req CANNM162 */\r
38 /** @req CANNM086 */\r
39 /** @req CANNM019 */\r
40 /** @req CANNM189 */\r
41 /** @req CANNM190 */\r
42 /** @req CANNM191 */\r
43 /** @req CANNM016 */\r
44 /** @req CANNM195 */\r
45 /** @req CANNM197.toolchain */\r
46 /** @req CANNM198.toolchain */\r
47 /** @req CANNM026 */\r
48 /** @req CANNM201 */\r
49 \r
50 #include "ComStack_Types.h"     /** @req CANNM082 */\r
51 #include "CanNm.h"                              /** @req CANNM082 */\r
52 #include "CanNm_Internal.h"\r
53 #include "Nm_Cbk.h"                             /** @req CANNM082 */\r
54 #include "NmStack_Types.h"              /** @req CANNM082 */\r
55 //#include SchM_CanNm.h                 //Not implemented. (CANNM082)\r
56 #include "MemMap.h"                             /** @req CANNM082 */\r
57 \r
58 /** @req CANNM083 */\r
59 #include "CanIf.h"\r
60 #include "Nm.h"\r
61 \r
62 #include <string.h>\r
63 \r
64 #if (CANNM_DEV_ERROR_DETECT == STD_ON)\r
65 #if defined(USE_DET)\r
66 #include "Det.h"                                /** @req CANNM082 */\r
67 #endif\r
68 #endif\r
69 #if defined(USE_DEM)\r
70 #include "Dem.h"                                /** @req CANNM082 */\r
71 #endif\r
72 \r
73 \r
74 static const CanNm_ConfigType* CanNm_ConfigPtr;\r
75 \r
76 //lint -save -e785 //PC-Lint exception: Too few initializers for aggregate...\r
77 CanNm_InternalType CanNm_Internal = {\r
78                 .InitStatus = CANNM_UNINIT,\r
79 };\r
80 //lint -restore\r
81 \r
82 /** Initialize the complete CanNm module, i.e. all channels which are activated */\r
83 /** @req CANNM041 */\r
84 void CanNm_Init( const CanNm_ConfigType * const cannmConfigPtr ){\r
85         CANNM_VALIDATE_NOTNULL(cannmConfigPtr, CANNM_SERVICEID_INIT);\r
86 \r
87         CanNm_ConfigPtr = cannmConfigPtr;  /**< @req CANNM060 */\r
88 \r
89         uint8 channel;\r
90         for (channel = 0; channel < CANNM_CHANNEL_COUNT; channel++) {\r
91                 const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[channel];\r
92                 CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[channel];\r
93                 if (ChannelConf->Active) {                        /**< @req CANNM204 */\r
94                         ChannelInternal->Mode = NM_MODE_BUS_SLEEP;    /**< @req CANNM144 */\r
95                         ChannelInternal->State = NM_STATE_BUS_SLEEP;  /**< @req CANNM141 */\r
96                         ChannelInternal->Requested = FALSE;           /**< @req CANNM143 */\r
97 \r
98                         /** @req CANNM085 */\r
99                         memset(ChannelInternal->TxMessageSdu, 0x00, 8);\r
100                         memset(ChannelInternal->RxMessageSdu, 0x00, 8);\r
101 \r
102                         /** @req CANNM025 */\r
103                         uint8* destUserData = CanNm_Internal_GetUserDataPtr(ChannelConf, ChannelInternal->TxMessageSdu);\r
104                         uint8 userDataLength = CanNm_Internal_GetUserDataLength(ChannelConf);\r
105                         memset(destUserData, 0xFF, userDataLength);\r
106 \r
107 #if (CANNM_NODE_ID_ENABLED == STD_ON)\r
108                         /** @req CANNM013 */\r
109                         if (ChannelConf->NidPosition != CANNM_PDU_OFF) {\r
110                                 ChannelInternal->TxMessageSdu[ChannelConf->NidPosition] = ChannelConf->NodeId;\r
111                         }\r
112 #endif\r
113                 } else {\r
114                         ChannelInternal->State = NM_STATE_UNINIT;\r
115                 }\r
116         }\r
117 \r
118         CanNm_Internal.InitStatus = CANNM_INIT;\r
119 \r
120         /** @req CANNM061 */\r
121         /** @req CANNM033 */\r
122 }\r
123 \r
124 /** Passive startup of the AUTOSAR CAN NM. It triggers the transition from Bus-\r
125   * Sleep Mode to the Network Mode in Repeat Message State.\r
126   * This service has no effect if the current state is not equal to Bus-Sleep Mode. In\r
127   * that case NM_E_NOT_EXECUTED is returned. */\r
128 Nm_ReturnType CanNm_PassiveStartUp( const NetworkHandleType nmChannelHandle ){\r
129         CANNM_VALIDATE_INIT(CANNM_SERVICEID_PASSIVESTARTUP);\r
130         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_PASSIVESTARTUP);\r
131 \r
132         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
133         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
134         Nm_ReturnType status = NM_E_OK;\r
135 \r
136         if (ChannelInternal->Mode == NM_MODE_BUS_SLEEP) {\r
137                 CanNm_Internal_BusSleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM128  @req CANNM095.3 */\r
138                 status = NM_E_OK;\r
139         } else {\r
140                 status = NM_E_NOT_EXECUTED;  /**< @req CANNM147 */\r
141         }\r
142         return status;\r
143 }\r
144 \r
145 /** Request the network, since ECU needs to communicate on the bus. Network\r
146   * state shall be changed to \91requested\92 */\r
147 Nm_ReturnType CanNm_NetworkRequest( const NetworkHandleType nmChannelHandle ){\r
148         CANNM_VALIDATE_INIT(CANNM_SERVICEID_NETWORKREQUEST);\r
149         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_NETWORKREQUEST);\r
150 \r
151         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
152         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
153 \r
154         ChannelInternal->Requested = TRUE;  /**< @req CANNM104 */\r
155 \r
156         if (ChannelInternal->Mode == NM_MODE_BUS_SLEEP) {\r
157                 CanNm_Internal_BusSleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM129  @req CANNM095.1 */\r
158         } else if (ChannelInternal->Mode == NM_MODE_PREPARE_BUS_SLEEP) {\r
159                 CanNm_Internal_PrepareBusSleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM123  @req CANNM095.2 */\r
160         } else if (ChannelInternal->Mode == NM_MODE_NETWORK) {\r
161                 if (ChannelInternal->State == NM_STATE_READY_SLEEP) {\r
162                         CanNm_Internal_ReadySleep_to_NormalOperation(ChannelConf, ChannelInternal);  /**< @req CANNM110 */\r
163                 }\r
164         } else {\r
165                 //Nothing to be done\r
166         }\r
167         return NM_E_OK;\r
168 }\r
169 \r
170 /** Release the network, since ECU doesn\92t have to communicate on the bus. Network\r
171   * state shall be changed to \91released\92. */\r
172 Nm_ReturnType CanNm_NetworkRelease( const NetworkHandleType nmChannelHandle ){\r
173         CANNM_VALIDATE_INIT(CANNM_SERVICEID_NETWORKRELEASE);\r
174         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_NETWORKRELEASE);\r
175         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
176         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
177 \r
178         ChannelInternal->Requested = FALSE;  /**< @req CANNM105 */\r
179 \r
180         if (ChannelInternal->Mode == NM_MODE_NETWORK) {\r
181                 if (ChannelInternal->State == NM_STATE_NORMAL_OPERATION) {\r
182                         CanNm_Internal_NormalOperation_to_ReadySleep(ChannelConf, ChannelInternal);  /**< @req CANNM118 */\r
183                 }\r
184         }\r
185         return NM_E_OK;\r
186 }\r
187 \r
188 /** Disable the NM PDU transmission ability due to a ISO14229 Communication\r
189   * Control (28hex) service */\r
190 Nm_ReturnType CanNm_DisableCommunication( const NetworkHandleType nmChannelHandle ){\r
191         CANNM_VALIDATE_INIT(CANNM_SERVICEID_DISABLECOMMUNICATION);\r
192         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_DISABLECOMMUNICATION);\r
193         return NM_E_NOT_OK;\r
194 }\r
195 \r
196 /** Enable the NM PDU transmission ability due to a ISO14229 Communication\r
197   * Control (28hex) service */\r
198 Nm_ReturnType CanNm_EnableCommunication( const NetworkHandleType nmChannelHandle ){\r
199         CANNM_VALIDATE_INIT(CANNM_SERVICEID_ENABLECOMMUNICATION);\r
200         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_ENABLECOMMUNICATION);\r
201         return NM_E_NOT_OK;\r
202 }\r
203 \r
204 #if (CANNM_USER_DATA_ENABLED == STD_ON)  /**< @req CANNM053.1 */\r
205 /** Set user data for NM messages transmitted next on the bus. */\r
206 /** @req CANNM159  @req CANNM015 */\r
207 Nm_ReturnType CanNm_SetUserData( const NetworkHandleType nmChannelHandle, const uint8* const nmUserDataPtr ){\r
208         CANNM_VALIDATE_INIT(CANNM_SERVICEID_SETUSERDATA);\r
209         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_SETUSERDATA);\r
210 \r
211         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
212         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
213         uint8* destUserData = CanNm_Internal_GetUserDataPtr(ChannelConf, ChannelInternal->TxMessageSdu);\r
214         uint8 userDataLength = CanNm_Internal_GetUserDataLength(ChannelConf);\r
215 \r
216         memcpy(destUserData, nmUserDataPtr, userDataLength);\r
217 \r
218         return NM_E_OK;\r
219 }\r
220 #endif\r
221 \r
222 #if (CANNM_USER_DATA_ENABLED == STD_ON)  /**< @req CANNM053.2 */\r
223 /** Get user data out of the most recently received NM message. */\r
224 /** @req CANNM160  @req CANNM031 */\r
225 Nm_ReturnType CanNm_GetUserData( const NetworkHandleType nmChannelHandle, uint8* const nmUserDataPtr ){\r
226         CANNM_VALIDATE_INIT(CANNM_SERVICEID_GETUSERDATA);\r
227         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_GETUSERDATA);\r
228 \r
229         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
230         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
231         uint8* sourceUserData = CanNm_Internal_GetUserDataPtr(ChannelConf, ChannelInternal->RxMessageSdu);\r
232         uint8 userDataLength = CanNm_Internal_GetUserDataLength(ChannelConf);\r
233 \r
234         memcpy(nmUserDataPtr, sourceUserData, userDataLength);\r
235 \r
236         return NM_E_OK;\r
237 }\r
238 #endif\r
239 \r
240 #if (CANNM_NODE_ID_ENABLED == STD_ON)\r
241 /** Get node identifier out of the most recently received NM PDU. */\r
242 /** @req CANNM132 */\r
243 Nm_ReturnType CanNm_GetNodeIdentifier( const NetworkHandleType nmChannelHandle, uint8 * const nmNodeIdPtr ){\r
244         CANNM_VALIDATE_INIT(CANNM_SERVICEID_GETNODEIDENTIFIER);\r
245         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_GETNODEIDENTIFIER);\r
246 \r
247         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
248         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
249         Nm_ReturnType status = NM_E_OK;\r
250 \r
251         if (ChannelConf->NidPosition == CANNM_PDU_OFF) {\r
252                 status = NM_E_NOT_EXECUTED;\r
253         } else {\r
254                 *nmNodeIdPtr = ChannelInternal->RxMessageSdu[ChannelConf->NidPosition];\r
255                 status = NM_E_OK;\r
256         }\r
257         return status;\r
258 }\r
259 \r
260 /** Get node identifier configured for the local node. */\r
261 /** @req CANNM133 */\r
262 Nm_ReturnType CanNm_GetLocalNodeIdentifier( const NetworkHandleType nmChannelHandle, uint8 * const nmNodeIdPtr ){\r
263         CANNM_VALIDATE_INIT(CANNM_SERVICEID_GETLOCALNODEIDENTIFIER);\r
264         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_GETLOCALNODEIDENTIFIER);\r
265 \r
266         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
267         *nmNodeIdPtr = ChannelConf->NodeId;\r
268 \r
269         return NM_E_OK;\r
270 }\r
271 #endif\r
272 \r
273 #if (CANNM_NODE_DETECTION_ENABLED == STD_ON)\r
274 /** Set Repeat Message Request Bit for NM messages transmitted next on the bus. */\r
275 /** @req CANNM135  @req CANNM136 */\r
276 Nm_ReturnType CanNm_RepeatMessageRequest( const NetworkHandleType nmChannelHandle ){\r
277         CANNM_VALIDATE_INIT(CANNM_SERVICEID_REPEATMESSAGEREQUEST);\r
278         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_REPEATMESSAGEREQUEST);\r
279 \r
280         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
281         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
282         Nm_ReturnType status = NM_E_NOT_EXECUTED;  /**< @req CANNM137 */\r
283 \r
284         if (ChannelConf->CbvPosition != CANNM_PDU_OFF) {\r
285                 if (ChannelInternal->State == NM_STATE_READY_SLEEP) {\r
286                         ChannelInternal->TxMessageSdu[ChannelConf->CbvPosition] = CANNM_CBV_REPEAT_MESSAGE_REQUEST;  /**< @req CANNM113 */\r
287                         CanNm_Internal_ReadySleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM112 */\r
288                         status = NM_E_OK;\r
289                 } else if (ChannelInternal->State == NM_STATE_NORMAL_OPERATION) {\r
290                         ChannelInternal->TxMessageSdu[ChannelConf->CbvPosition] = CANNM_CBV_REPEAT_MESSAGE_REQUEST;  /**< @req CANNM121 */\r
291                         CanNm_Internal_NormalOperation_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM120 */\r
292                         status = NM_E_OK;\r
293                 } else {\r
294                         //Nothing to be done\r
295                 }\r
296         }\r
297         return status;\r
298 }\r
299 #endif\r
300 \r
301 #if ((CANNM_NODE_ID_ENABLED == STD_ON) || (CANNM_NODE_DETECTION_ENABLED == STD_ON) || (CANNM_USER_DATA_ENABLED == STD_ON))\r
302 /** Get the whole PDU data out of the most recently received NM message. */\r
303 /** @req CANNM138  @req CANNM139 */\r
304 Nm_ReturnType CanNm_GetPduData( const NetworkHandleType nmChannelHandle, uint8 * const nmPduDataPtr ){\r
305         CANNM_VALIDATE_INIT(CANNM_SERVICEID_GETPDUDATA);\r
306         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_GETPDUDATA);\r
307 \r
308         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
309         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
310 \r
311         memcpy(nmPduDataPtr, ChannelInternal->RxMessageSdu, ChannelConf->PduLength);\r
312 \r
313         return NM_E_OK;\r
314 }\r
315 #endif\r
316 \r
317 /** Returns the state and the mode of the network management. */\r
318 /** @req CANNM091 */\r
319 Nm_ReturnType CanNm_GetState( const NetworkHandleType nmChannelHandle, Nm_StateType * const nmStatePtr, Nm_ModeType * const nmModePtr ){\r
320         CANNM_VALIDATE_INIT(CANNM_SERVICEID_GETSTATE);\r
321         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_GETSTATE);\r
322 \r
323         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
324         *nmStatePtr = ChannelInternal->State;\r
325         *nmModePtr = ChannelInternal->Mode;\r
326 \r
327         return NM_E_OK;\r
328 }\r
329 \r
330 /** Request bus synchronization. */\r
331 Nm_ReturnType CanNm_RequestBusSynchronization( const NetworkHandleType nmChannelHandle ){\r
332         CANNM_VALIDATE_INIT(CANNM_SERVICEID_REQUESTBUSSYNCHRONIZATION);\r
333         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_REQUESTBUSSYNCHRONIZATION);\r
334         // Not implemented\r
335         return NM_E_NOT_OK;\r
336 }\r
337 \r
338 /** Check if remote sleep indication takes place or not. */\r
339 Nm_ReturnType CanNm_CheckRemoteSleepIndication( const NetworkHandleType nmChannelHandle, boolean * const nmRemoteSleepIndPtr ){\r
340         CANNM_VALIDATE_INIT(CANNM_SERVICEID_CHECKREMOTESLEEPINDICATION);\r
341         CANNM_VALIDATE_CHANNEL(nmChannelHandle, CANNM_SERVICEID_CHECKREMOTESLEEPINDICATION);\r
342         (void)nmRemoteSleepIndPtr;\r
343         // Not implemented\r
344         return NM_E_NOT_OK;\r
345 }\r
346 \r
347 \r
348 // Functions called by CAN Interface\r
349 // ---------------------------------\r
350 \r
351 /** This service confirms a previous successfully processed CAN transmit request.\r
352   * This callback service is called by the CanIf and implemented by the CanNm. */\r
353 /** @req CANNM034.deferred */\r
354 void CanNm_TxConfirmation( PduIdType canNmTxPduId ){\r
355         CANNM_VALIDATE_INIT_NORV(CANNM_SERVICEID_TXCONFIRMATION);\r
356         CANNM_VALIDATE_CHANNEL_NORV(canNmTxPduId, CANNM_SERVICEID_TXCONFIRMATION);\r
357 \r
358         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[canNmTxPduId];\r
359         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[canNmTxPduId];\r
360 \r
361         if (ChannelInternal->Mode == NM_MODE_NETWORK) {\r
362                 CanNm_Internal_NetworkMode_to_NetworkMode(ChannelConf, ChannelInternal);  /**< @req CANNM099.1 */\r
363         }\r
364 }\r
365 \r
366 /** This service indicates a successful reception of a received NM message to the\r
367   * CanNm after passing all filters and validation checks.\r
368   * This callback service is called by the CAN Interface and implemented by the CanNm. */\r
369 void CanNm_RxIndication( PduIdType canNmRxPduId, const uint8 *canSduPtr ){\r
370         CANNM_VALIDATE_INIT_NORV(CANNM_SERVICEID_RXINDICATION);\r
371         CANNM_VALIDATE_CHANNEL_NORV(canNmRxPduId, CANNM_SERVICEID_RXINDICATION);\r
372 \r
373         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[canNmRxPduId];\r
374         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[canNmRxPduId];\r
375 \r
376         memcpy(ChannelInternal->RxMessageSdu, canSduPtr, ChannelConf->PduLength);  /**< @req CANNM035 */\r
377 \r
378         boolean repeatMessageBitIndication = FALSE;\r
379         if (ChannelConf->CbvPosition != CANNM_PDU_OFF) {\r
380                 uint8 cbv = ChannelInternal->RxMessageSdu[ChannelConf->CbvPosition];\r
381                 repeatMessageBitIndication = cbv & CANNM_CBV_REPEAT_MESSAGE_REQUEST;\r
382         }\r
383 \r
384         if (ChannelInternal->Mode == NM_MODE_BUS_SLEEP) {\r
385                 CanNm_Internal_BusSleep_to_BusSleep(ChannelConf, ChannelInternal);  /**< @req CANNM127.2 */\r
386         } else if (ChannelInternal->Mode == NM_MODE_PREPARE_BUS_SLEEP) {\r
387                 CanNm_Internal_PrepareBusSleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM124  @req CANNM095.4 */\r
388         } else if (ChannelInternal->Mode == NM_MODE_NETWORK) {\r
389                 CanNm_Internal_NetworkMode_to_NetworkMode(ChannelConf, ChannelInternal);  /**< @req CANNM098.1 */\r
390                 if (repeatMessageBitIndication) {\r
391                         if (ChannelInternal->State == NM_STATE_READY_SLEEP) {\r
392                                 CanNm_Internal_ReadySleep_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM111 */\r
393                         } else if (ChannelInternal->State == NM_STATE_NORMAL_OPERATION) {\r
394                                 CanNm_Internal_NormalOperation_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM119 */\r
395                         } else {\r
396                                 //Nothing to be done\r
397                         }\r
398                 }\r
399         } else {\r
400                 //Nothing to be done\r
401         }\r
402 #if (CANNM_PDU_RX_INDICATION_ENABLED == STD_ON)\r
403         // TODO: call NM rx indication\r
404 #endif\r
405 }\r
406 \r
407 \r
408 \r
409 \r
410 // ----------------------------------------------------------------------------\r
411 // Internal functions\r
412 // ----------------------------------------------------------------------------\r
413 // Accessed through CanNm_MainFunction_<channel>\r
414 void CanNm_MainFunction(NetworkHandleType nmChannelHandle);\r
415 \r
416 void CanNm_MainFunction( NetworkHandleType nmChannelHandle ) {\r
417         CANNM_VALIDATE_INIT_NORV(CANNM_SERVICEID_ARC_MAINFUNCTION);\r
418 \r
419         /** @req CANNM108 */\r
420 \r
421         const CanNm_ChannelType* ChannelConf = &CanNm_ConfigPtr->Channels[nmChannelHandle];\r
422         CanNm_Internal_ChannelType* ChannelInternal = &CanNm_Internal.Channels[nmChannelHandle];\r
423         if (ChannelInternal->Mode == NM_MODE_NETWORK) {\r
424                 CanNm_Internal_TickTimeoutTime(ChannelConf, ChannelInternal);\r
425 #if (CANNM_PASSIVE_MODE_ENABLED != STD_ON)                              /**< @req CANNM072 */\r
426                 if ((ChannelInternal->State == NM_STATE_REPEAT_MESSAGE) ||\r
427                         (ChannelInternal->State == NM_STATE_NORMAL_OPERATION)) {\r
428                         /** @req CANNM051 @req CANNM032  @req CANNM087.1  @req CANNM100.6 */\r
429                         CanNm_Internal_TickMessageCycleTime(ChannelConf, ChannelInternal);\r
430                 }\r
431 #endif\r
432                 if (ChannelInternal->State == NM_STATE_REPEAT_MESSAGE) {\r
433                         CanNm_Internal_TickRepeatMessageTime(ChannelConf, ChannelInternal);  /**< @req CANNM102.2 */\r
434                 }\r
435         } else if (ChannelInternal->Mode == NM_MODE_PREPARE_BUS_SLEEP) {\r
436                 CanNm_Internal_TickWaitBusSleepTime(ChannelConf, ChannelInternal);  /**< @req CANNM115.2 */\r
437         } else {\r
438                 //Nothing to be done\r
439         }\r
440 }\r
441 \r
442 // Timer helpers\r
443 // -------------\r
444 \r
445 static inline void CanNm_Internal_TickTimeoutTime( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
446         if (ChannelConf->MainFunctionPeriod >= ChannelInternal->TimeoutTimeLeft) {\r
447                 ChannelInternal->TimeoutTimeLeft = 0;\r
448                 if (ChannelInternal->State == NM_STATE_REPEAT_MESSAGE) {\r
449 #if defined(USE_DEM)\r
450                         Dem_ReportErrorStatus(CANNM_E_NETWORK_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
451 #endif\r
452                         CanNm_Internal_RepeatMessage_to_RepeatMessage(ChannelConf, ChannelInternal);  /**< @req CANNM101.1 */\r
453                 } else if (ChannelInternal->State == NM_STATE_NORMAL_OPERATION) {\r
454 #if defined(USE_DEM)\r
455                         Dem_ReportErrorStatus(CANNM_E_NETWORK_TIMEOUT, DEM_EVENT_STATUS_FAILED);\r
456 #endif\r
457                         CanNm_Internal_NormalOperation_to_NormalOperation(ChannelConf, ChannelInternal);  /**< @req CANNM117.1 */\r
458                 } else if (ChannelInternal->State == NM_STATE_READY_SLEEP) {\r
459                         CanNm_Internal_ReadySleep_to_PrepareBusSleep(ChannelConf, ChannelInternal);  /**< @req CANNM109 */\r
460                 } else {\r
461                         //Nothing to be done\r
462                 }\r
463         } else {\r
464                 ChannelInternal->TimeoutTimeLeft -= ChannelConf->MainFunctionPeriod;\r
465         }\r
466 }\r
467 \r
468 /** @req CANNM102.1 */\r
469 static inline void CanNm_Internal_TickRepeatMessageTime( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
470         if (ChannelConf->MainFunctionPeriod >= ChannelInternal->RepeatMessageTimeLeft) {\r
471                 ChannelInternal->RepeatMessageTimeLeft = 0;\r
472                 if (ChannelInternal->State == NM_STATE_REPEAT_MESSAGE) {\r
473                         if (ChannelInternal->Requested) {\r
474                                 CanNm_Internal_RepeatMessage_to_NormalOperation(ChannelConf, ChannelInternal);  /**< @req CANNM103 */\r
475                         } else {\r
476                                 CanNm_Internal_RepeatMessage_to_ReadySleep(ChannelConf, ChannelInternal);  /**< @req CANNM104 */\r
477                         }\r
478                 }\r
479         } else {\r
480                 ChannelInternal->RepeatMessageTimeLeft -= ChannelConf->MainFunctionPeriod;\r
481         }\r
482 }\r
483 \r
484 /** @req CANNM115.1 */\r
485 static inline void CanNm_Internal_TickWaitBusSleepTime( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
486         if (ChannelConf->MainFunctionPeriod >= ChannelInternal->WaitBusSleepTimeLeft) {\r
487                 ChannelInternal->WaitBusSleepTimeLeft = 0;\r
488                 if (ChannelInternal->Mode == NM_MODE_PREPARE_BUS_SLEEP) {\r
489                         CanNm_Internal_PrepareBusSleep_to_BusSleep(ChannelConf, ChannelInternal);\r
490                 }\r
491         } else {\r
492                 ChannelInternal->WaitBusSleepTimeLeft -= ChannelConf->MainFunctionPeriod;\r
493         }\r
494 }\r
495 \r
496 static inline void CanNm_Internal_TickMessageCycleTime( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
497         if (ChannelConf->MainFunctionPeriod >= ChannelInternal->MessageCycleTimeLeft) {\r
498                 ChannelInternal->MessageCycleTimeLeft = 0;\r
499                 if ((ChannelInternal->State == NM_STATE_REPEAT_MESSAGE) ||\r
500                         (ChannelInternal->State == NM_STATE_NORMAL_OPERATION)) {\r
501                         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleTime;  /**< @req CANNM040 */\r
502                         /** @req CANNM087.2  @req CANNM100.5 */\r
503                         CanNm_Internal_TransmitMessage(ChannelConf, ChannelInternal);\r
504                 }\r
505         } else {\r
506                 ChannelInternal->MessageCycleTimeLeft -= ChannelConf->MainFunctionPeriod;\r
507         }\r
508 }\r
509 \r
510 // Message helpers\r
511 // ---------------\r
512 \r
513 static inline void CanNm_Internal_TransmitMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
514         PduInfoType pdu = {\r
515                         .SduDataPtr = ChannelInternal->TxMessageSdu,\r
516                         .SduLength = ChannelConf->PduLength,\r
517         };\r
518         Std_ReturnType status = CanIf_Transmit(ChannelConf->CanIfPduId, &pdu);\r
519         (void)status;\r
520         // TODO: what to do if Transmit fails?\r
521 }\r
522 \r
523 static inline uint8 CanNm_Internal_GetUserDataOffset( const CanNm_ChannelType* ChannelConf ) {\r
524         uint8 userDataPos = 0;\r
525         userDataPos += (ChannelConf->NidPosition == CANNM_PDU_OFF) ? 0 : 1;\r
526         userDataPos += (ChannelConf->CbvPosition == CANNM_PDU_OFF) ? 0 : 1;\r
527         return userDataPos;\r
528 }\r
529 \r
530 static inline uint8* CanNm_Internal_GetUserDataPtr( const CanNm_ChannelType* ChannelConf, uint8* MessageSduPtr ) {\r
531         uint8 userDataOffset = CanNm_Internal_GetUserDataOffset(ChannelConf);\r
532         return &MessageSduPtr[userDataOffset];\r
533 }\r
534 \r
535 static inline uint8 CanNm_Internal_GetUserDataLength( const CanNm_ChannelType* ChannelConf ) {\r
536         uint8 userDataOffset = CanNm_Internal_GetUserDataOffset(ChannelConf);\r
537         return ChannelConf->PduLength - userDataOffset;\r
538 }\r
539 \r
540 static inline void CanNm_Internal_ClearCbv( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
541         if (ChannelConf->CbvPosition != CANNM_PDU_OFF) {\r
542                 ChannelInternal->TxMessageSdu[ChannelConf->CbvPosition] = 0x00;\r
543         }\r
544 }\r
545 \r
546 // Transition helpers\r
547 // ------------------\r
548 \r
549 static inline void CanNm_Internal_PrepareBusSleep_to_RepeatMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
550         ChannelInternal->Mode = NM_MODE_NETWORK;\r
551         ChannelInternal->State = NM_STATE_REPEAT_MESSAGE;\r
552         ChannelInternal->TimeoutTimeLeft = ChannelConf->TimeoutTime;  /**< @req CANNM096.1 */\r
553         ChannelInternal->RepeatMessageTimeLeft = ChannelConf->RepeatMessageTime;\r
554         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleOffsetTime;  /**< @req CANNM100.2 */\r
555         // Notify 'Network Mode'\r
556         Nm_NetworkMode(ChannelConf->NmNetworkHandle);  /**< @req CANNM097.1 */\r
557 }\r
558 \r
559 static inline void CanNm_Internal_PrepareBusSleep_to_BusSleep( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
560         ChannelInternal->Mode = NM_MODE_BUS_SLEEP;\r
561         ChannelInternal->State = NM_STATE_BUS_SLEEP;\r
562         // Notify 'Bus-Sleep Mode'\r
563         Nm_BusSleepMode(ChannelConf->NmNetworkHandle);  /**< @req CANNM126 */\r
564 }\r
565 \r
566 static inline void CanNm_Internal_BusSleep_to_RepeatMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
567         ChannelInternal->Mode = NM_MODE_NETWORK;\r
568         ChannelInternal->State = NM_STATE_REPEAT_MESSAGE;\r
569         ChannelInternal->TimeoutTimeLeft = ChannelConf->TimeoutTime;  /**< @req CANNM096.2 */\r
570         ChannelInternal->RepeatMessageTimeLeft = ChannelConf->RepeatMessageTime;\r
571         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleOffsetTime;  /**< @req CANNM100.1 */\r
572         // Notify 'Network Mode'\r
573         Nm_NetworkMode(ChannelConf->NmNetworkHandle);  /**< @req CANNM097.2 */\r
574 }\r
575 static inline void CanNm_Internal_BusSleep_to_BusSleep( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
576         // Notify 'Network Start'\r
577         Nm_NetworkStartIndication(ChannelConf->NmNetworkHandle);  /**< @req CANNM127.1 */\r
578         (void) ChannelInternal; //Just to avoid 715 PC-Lint warning about not used.\r
579 }\r
580 \r
581 static inline void CanNm_Internal_RepeatMessage_to_RepeatMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
582         ChannelInternal->TimeoutTimeLeft = ChannelConf->TimeoutTime;  /**< @req CANNM101.2 */\r
583         // TODO: Notify 'Network Timeout'?\r
584 }\r
585 static inline void CanNm_Internal_RepeatMessage_to_ReadySleep( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
586         ChannelInternal->Mode = NM_MODE_NETWORK;\r
587         ChannelInternal->State = NM_STATE_READY_SLEEP;\r
588 #if (CANNM_NODE_DETECTION_ENABLED == STD_ON)\r
589         /** @req CANNM107.1 */\r
590         CanNm_Internal_ClearCbv(ChannelConf, ChannelInternal);\r
591 #endif\r
592 }\r
593 static inline void CanNm_Internal_RepeatMessage_to_NormalOperation( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
594         ChannelInternal->Mode = NM_MODE_NETWORK;\r
595         ChannelInternal->State = NM_STATE_NORMAL_OPERATION;\r
596 #if (CANNM_NODE_DETECTION_ENABLED == STD_ON)\r
597         /** @req CANNM107.2 */\r
598         CanNm_Internal_ClearCbv(ChannelConf, ChannelInternal);\r
599 #endif\r
600 }\r
601 \r
602 static inline void CanNm_Internal_NormalOperation_to_RepeatMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
603         ChannelInternal->Mode = NM_MODE_NETWORK;\r
604         ChannelInternal->State = NM_STATE_REPEAT_MESSAGE;\r
605         ChannelInternal->RepeatMessageTimeLeft = ChannelConf->RepeatMessageTime;\r
606         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleOffsetTime;  /**< @req CANNM100.3 */\r
607 }\r
608 static inline void CanNm_Internal_NormalOperation_to_ReadySleep( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
609         ChannelInternal->Mode = NM_MODE_NETWORK;\r
610         ChannelInternal->State = NM_STATE_READY_SLEEP;\r
611         (void) ChannelConf; //Just to avoid 715 PC-Lint warning about not used.\r
612 }\r
613 static inline void CanNm_Internal_NormalOperation_to_NormalOperation( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
614         ChannelInternal->TimeoutTimeLeft = ChannelConf->TimeoutTime;  /**< @req CANNM117.2 */\r
615 }\r
616 \r
617 static inline void CanNm_Internal_ReadySleep_to_NormalOperation( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
618         ChannelInternal->Mode = NM_MODE_NETWORK;\r
619         ChannelInternal->State = NM_STATE_NORMAL_OPERATION;\r
620         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleOffsetTime;  /**< @req CANNM116 */\r
621 }\r
622 static inline void CanNm_Internal_ReadySleep_to_PrepareBusSleep( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
623         ChannelInternal->Mode = NM_MODE_PREPARE_BUS_SLEEP;\r
624         ChannelInternal->State = NM_STATE_PREPARE_BUS_SLEEP;\r
625         ChannelInternal->WaitBusSleepTimeLeft = ChannelConf->WaitBusSleepTime;\r
626         // Notify 'Prepare Bus-Sleep Mode'\r
627         Nm_PrepareBusSleepMode(ChannelConf->NmNetworkHandle);  /**< @req CANNM114 */\r
628 }\r
629 static inline void CanNm_Internal_ReadySleep_to_RepeatMessage( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
630         ChannelInternal->Mode = NM_MODE_NETWORK;\r
631         ChannelInternal->State = NM_STATE_REPEAT_MESSAGE;\r
632         ChannelInternal->RepeatMessageTimeLeft = ChannelConf->RepeatMessageTime;\r
633         ChannelInternal->MessageCycleTimeLeft = ChannelConf->MessageCycleOffsetTime;  /**< @req CANNM100.4 */\r
634 }\r
635 \r
636 static inline void CanNm_Internal_NetworkMode_to_NetworkMode( const CanNm_ChannelType* ChannelConf, CanNm_Internal_ChannelType* ChannelInternal ) {\r
637         ChannelInternal->TimeoutTimeLeft = ChannelConf->TimeoutTime;  /**< @req CANNM098.2 @req CANNM099.2 */\r
638 }\r