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