]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Com/Com.c
COM protection
[arc.git] / communication / Com / Com.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 \r
17 //lint -esym(960,8.7)   PC-Lint misunderstanding of Misra 8.7 for Com_SystenEndianness and endianess_test\r
18 \r
19 \r
20 \r
21 \r
22 \r
23 #include <assert.h>\r
24 #include <stdlib.h>\r
25 //#include <stdio.h>\r
26 #include <string.h>\r
27 #include "Com.h"\r
28 #include "Com_Arc_Types.h"\r
29 #include "Com_Internal.h"\r
30 #include "Com_misc.h"\r
31 #include "debug.h"\r
32 #include "Cpu.h"\r
33 \r
34 \r
35 /* TODO: Better way to get endianness across all compilers? */\r
36 static const uint32_t endianness_test = 0xdeadbeefU;\r
37 ComSignalEndianess_type Com_SystemEndianness;\r
38 \r
39 \r
40 const Com_ConfigType * ComConfig;\r
41 \r
42 \r
43 void Com_Init(const Com_ConfigType *config ) {\r
44         DEBUG(DEBUG_LOW, "--Initialization of COM--\n");\r
45 \r
46         ComConfig = config;\r
47 \r
48         uint8 failure = 0;\r
49 \r
50         uint32 firstTimeout;\r
51 \r
52         //lint --e(928) PC-Lint exception Misra 11.4, Must be like this. /tojo\r
53         uint8 endiannessByte = *(const uint8 *)&endianness_test;\r
54         if      ( endiannessByte == 0xef ) { Com_SystemEndianness = COM_LITTLE_ENDIAN; }\r
55         else if ( endiannessByte == 0xde ) { Com_SystemEndianness = COM_BIG_ENDIAN; }\r
56         else {\r
57                 // No other endianness supported\r
58                 //lint --e(506) PC-Lint exception Misra 13.7, 14.1, Allow boolean to always be false.\r
59                 assert(0);\r
60         }\r
61 \r
62         // Initialize each IPdu\r
63         //ComIPdu_type *IPdu;\r
64         //Com_Arc_IPdu_type *Arc_IPdu;\r
65         const ComSignal_type *Signal;\r
66         const ComGroupSignal_type *GroupSignal;\r
67         for (uint16 i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) {\r
68 \r
69                 const ComIPdu_type *IPdu = GET_IPdu(i);\r
70                 Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(i);\r
71                 Arc_IPdu->Com_Arc_DynSignalLength = 0;\r
72 \r
73                 if (i >= COM_N_IPDUS) {\r
74                         DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_TOO_MANY_IPDU);\r
75                         failure = 1;\r
76                         break;\r
77                 }\r
78 \r
79                 // If this is a TX and cyclic IPdu, configure the first deadline.\r
80                 if ( (IPdu->ComIPduDirection == SEND) &&\r
81                                 ( (IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeMode == PERIODIC) || (IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeMode == MIXED) )) {\r
82                         //IPdu->Com_Arc_TxIPduTimers.ComTxModeTimePeriodTimer = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeTimeOffsetFactor;\r
83                         Arc_IPdu->Com_Arc_TxIPduTimers.ComTxModeTimePeriodTimer = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeTimeOffsetFactor;\r
84                 }\r
85 \r
86 \r
87                 // Reset firstTimeout.\r
88                 firstTimeout = 0xffffffffu;\r
89 \r
90                 // Initialize the memory with the default value.\r
91                 if (IPdu->ComIPduDirection == SEND) {\r
92                         memset((void *)IPdu->ComIPduDataPtr, IPdu->ComTxIPdu.ComTxIPduUnusedAreasDefault, IPdu->ComIPduSize);\r
93                 }\r
94 \r
95                 // For each signal in this PDU.\r
96                 //Arc_IPdu->NComIPduSignalRef = 0;\r
97                 for (uint16 j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL) ; j++) {\r
98                         Signal = IPdu->ComIPduSignalRef[j];\r
99                         Com_Arc_Signal_type * Arc_Signal = GET_ArcSignal(Signal->ComHandleId);\r
100 \r
101                         // Configure signal deadline monitoring if used.\r
102                         if (Signal->ComTimeoutFactor > 0) {\r
103 \r
104                                 if (Signal->ComSignalArcUseUpdateBit) {\r
105                                         // This signal uses an update bit, and hence has its own deadline monitoring.\r
106                                         Arc_Signal->Com_Arc_DeadlineCounter = Signal->ComFirstTimeoutFactor; // Configure the deadline counter\r
107 \r
108                                 } else {\r
109                                         // This signal does not use an update bit, and should therefore use per I-PDU deadline monitoring.\r
110                                         if (firstTimeout > Signal->ComFirstTimeoutFactor) {\r
111                                                 firstTimeout = Signal->ComFirstTimeoutFactor;\r
112                                         }\r
113                                 }\r
114                         }\r
115 \r
116                         // Clear update bits\r
117                         if (Signal->ComSignalArcUseUpdateBit) {\r
118                                 CLEARBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
119                         }\r
120 \r
121                         // If this signal is a signal group\r
122                         if (Signal->Com_Arc_IsSignalGroup) {\r
123 \r
124                                 // For each group signal of this signal group.\r
125                                 for(uint8 h = 0; Signal->ComGroupSignal[h] != NULL; h++) {\r
126                                         GroupSignal = Signal->ComGroupSignal[h];\r
127                                         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(GroupSignal->ComHandleId);\r
128                                         // Set pointer to shadow buffer\r
129                                         Arc_GroupSignal->Com_Arc_ShadowBuffer = (void *)Signal->Com_Arc_ShadowBuffer;\r
130                                         // Initialize group signal data.\r
131                                         Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, GroupSignal->ComHandleId, GroupSignal->ComSignalInitValue);\r
132                                 }\r
133 \r
134                         } else {\r
135                                 // Initialize signal data.\r
136                                 Com_WriteSignalDataToPdu(Signal->ComHandleId, Signal->ComSignalInitValue);\r
137                         }\r
138                 }\r
139 \r
140                 // Configure per I-PDU based deadline monitoring.\r
141                 for (uint16 j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL); j++) {\r
142                         Signal = IPdu->ComIPduSignalRef[j];\r
143                         Com_Arc_Signal_type * Arc_Signal = GET_ArcSignal(Signal->ComHandleId);\r
144 \r
145                         if ( (Signal->ComTimeoutFactor > 0) && (!Signal->ComSignalArcUseUpdateBit) ) {\r
146                                 Arc_Signal->Com_Arc_DeadlineCounter = firstTimeout;\r
147                         }\r
148                 }\r
149         }\r
150         for (uint16 i = 0; i < COM_N_IPDUS; i++) {\r
151                 Com_BufferPduState[i].currentPosition = 0;\r
152                 Com_BufferPduState[i].locked = false;\r
153         }\r
154 \r
155         // An error occurred.\r
156         if (failure) {\r
157                 DEBUG(DEBUG_LOW, "--Initialization of COM failed--\n");\r
158                 //DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_INVALID_FILTER_CONFIGURATION);\r
159         } else {\r
160                 DEBUG(DEBUG_LOW, "--Initialization of COM completed--\n");\r
161         }\r
162 }\r
163 \r
164 \r
165 void Com_DeInit( void ) {\r
166 \r
167 }\r
168 \r
169 void Com_IpduGroupStart(Com_PduGroupIdType IpduGroupId,boolean Initialize) {\r
170         (void)Initialize; // Nothing to be done. This is just to avoid Lint warning.\r
171         for (uint16 i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) {\r
172                 if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) {\r
173                         Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 1;\r
174                         break;\r
175                 }\r
176         }\r
177 }\r
178 \r
179 void Com_IpduGroupStop(Com_PduGroupIdType IpduGroupId) {\r
180         for (uint16 i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) {\r
181                 if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) {\r
182                         Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 0;\r
183                         break;\r
184                 }\r
185         }\r
186 }\r
187 \r
188 /**\r
189  *
190  * @param PduId
191  * @param PduInfoPtr
192  * @param RetryInfoPtr not supported
193  * @param TxDataCntPtr
194  * @return
195  */\r
196 BufReq_ReturnType Com_CopyTxData(PduIdType PduId, PduInfoType* PduInfoPtr, RetryInfoType* RetryInfoPtr, PduLengthType* TxDataCntPtr) {\r
197         imask_t state;\r
198         BufReq_ReturnType r = BUFREQ_OK;\r
199         const ComIPdu_type *IPdu = GET_IPdu(PduId);\r
200         boolean dirOk = ComConfig->ComIPdu[PduId].ComIPduDirection == SEND;\r
201         boolean sizeOk;\r
202 \r
203         Irq_Save(state);\r
204 \r
205         sizeOk = IPdu->ComIPduSize >= Com_BufferPduState[PduId].currentPosition + PduInfoPtr->SduLength;\r
206         Com_BufferPduState[PduId].locked = true;\r
207         if (dirOk && sizeOk) {\r
208                 void* source = (void *)IPdu->ComIPduDataPtr;\r
209                 memcpy(PduInfoPtr->SduDataPtr,source + Com_BufferPduState[PduId].currentPosition, PduInfoPtr->SduLength);\r
210                 Com_BufferPduState[PduId].currentPosition += PduInfoPtr->SduLength;\r
211                 *TxDataCntPtr = IPdu->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
212         } else {\r
213                 r = BUFREQ_NOT_OK;\r
214         }\r
215         Irq_Restore(state);\r
216         return r;\r
217 }\r
218 BufReq_ReturnType Com_CopyRxData(PduIdType PduId, const PduInfoType* PduInfoPtr, PduLengthType* RxBufferSizePtr) {\r
219         imask_t state;\r
220         BufReq_ReturnType r = BUFREQ_OK;\r
221         uint8 remainingBytes;\r
222         boolean sizeOk;\r
223         boolean dirOk;\r
224         boolean lockOk;\r
225 \r
226         Irq_Save(state);\r
227 \r
228         remainingBytes = GET_IPdu(PduId)->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
229         sizeOk = remainingBytes >= PduInfoPtr->SduLength;\r
230     dirOk = GET_IPdu(PduId)->ComIPduDirection == RECEIVE;\r
231         lockOk = isPduBufferLocked(PduId);\r
232         if (dirOk && lockOk && sizeOk) {\r
233                 memcpy((void *)(GET_IPdu(PduId)->ComIPduDataPtr+Com_BufferPduState[PduId].currentPosition), PduInfoPtr->SduDataPtr, PduInfoPtr->SduLength);\r
234                 Com_BufferPduState[PduId].currentPosition += PduInfoPtr->SduLength;\r
235                 *RxBufferSizePtr = GET_IPdu(PduId)->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
236         } else {\r
237                 r = BUFREQ_NOT_OK;\r
238         }\r
239         Irq_Restore(state);\r
240         return r;\r
241 }\r
242 \r
243 static void Com_SetDynSignalLength(PduIdType ComRxPduId,PduLengthType TpSduLength) {\r
244         const ComIPdu_type *IPdu = GET_IPdu(ComRxPduId);\r
245         if (IPdu->ComIPduDynSignalRef == 0) {\r
246                 return;\r
247         }\r
248         const ComSignal_type * const dynSignal = IPdu->ComIPduDynSignalRef;\r
249         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);\r
250         Arc_IPdu->Com_Arc_DynSignalLength = TpSduLength - (dynSignal->ComBitPosition/8);\r
251         return;\r
252 }\r
253 \r
254 BufReq_ReturnType Com_StartOfReception(PduIdType ComRxPduId, PduLengthType TpSduLength, PduLengthType* RxBufferSizePtr) {\r
255         PduLengthType ComIPduSize;\r
256         imask_t state;\r
257         BufReq_ReturnType r = BUFREQ_OK;\r
258         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);\r
259 \r
260         Irq_Save(state);\r
261         if (Arc_IPdu->Com_Arc_IpduStarted) {\r
262                 if (GET_IPdu(ComRxPduId)->ComIPduDirection == RECEIVE) {\r
263                         if (!Com_BufferPduState[ComRxPduId].locked) {\r
264                                 ComIPduSize = GET_IPdu(ComRxPduId)->ComIPduSize;\r
265                                 if (ComIPduSize >= TpSduLength) {\r
266                                         Com_BufferPduState[ComRxPduId].locked = true;\r
267                                         *RxBufferSizePtr = ComIPduSize;\r
268                                         Com_SetDynSignalLength(ComRxPduId,TpSduLength);\r
269                                 } else {\r
270                                         r = BUFREQ_OVFL;\r
271                                 }\r
272                         } else {\r
273                                 r = BUFREQ_BUSY;\r
274                         }\r
275                 }\r
276         } else {\r
277                 r = BUFREQ_NOT_OK;\r
278         }\r
279         Irq_Restore(state);\r
280         return r;\r
281 }\r