]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Com/Com.c
2f405e9d3bcadd9187218cca94125c9cca2e17a4
[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 \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 earliest deadline.\r
88                 earliestDeadline = 0xffffffffu;\r
89                 firstTimeout = 0xffffffffu;\r
90 \r
91                 // Initialize the memory with the default value.\r
92                 if (IPdu->ComIPduDirection == SEND) {\r
93                         memset(Arc_IPdu->ComIPduDataPtr, IPdu->ComTxIPdu.ComTxIPduUnusedAreasDefault, IPdu->ComIPduSize);\r
94                 }\r
95 \r
96                 // For each signal in this PDU.\r
97                 //Arc_IPdu->NComIPduSignalRef = 0;\r
98                 for (uint16 j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL) ; j++) {\r
99                         Signal = IPdu->ComIPduSignalRef[j];\r
100                         Com_Arc_Signal_type * Arc_Signal = GET_ArcSignal(Signal->ComHandleId);\r
101 \r
102                         // If this signal already has been configured this is most likely an error.\r
103                         if (Arc_Signal->ComIPduDataPtr != NULL) {\r
104                                 // DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_INVALID_SIGNAL_CONFIGURATION);\r
105                                 // failure = 1;\r
106                         }\r
107 \r
108                         // Configure signal deadline monitoring if used.\r
109                         if (Signal->ComTimeoutFactor > 0) {\r
110 \r
111                                 if (Signal->ComSignalArcUseUpdateBit) {\r
112                                         // This signal uses an update bit, and hence has its own deadline monitoring.\r
113                                         Arc_Signal->Com_Arc_DeadlineCounter = Signal->ComFirstTimeoutFactor; // Configure the deadline counter\r
114                                         Arc_Signal->ComTimeoutFactor = Signal->ComTimeoutFactor;\r
115 \r
116                                 } else {\r
117                                         // This signal does not use an update bit, and should therefore use per I-PDU deadline monitoring.\r
118                                         // Find the earliest deadline for this I-PDU and setup the deadline later.\r
119                                         if (earliestDeadline > Signal->ComTimeoutFactor) {\r
120                                                 earliestDeadline = Signal->ComTimeoutFactor;\r
121                                         }\r
122                                         if (firstTimeout > Signal->ComFirstTimeoutFactor) {\r
123                                                 firstTimeout = Signal->ComFirstTimeoutFactor;\r
124                                         }\r
125                                 }\r
126                         }\r
127 \r
128                         // Increment helper counters\r
129                     //Arc_IPdu->NComIPduSignalRef = j + 1;\r
130 \r
131                         Arc_Signal->ComIPduDataPtr = Arc_IPdu->ComIPduDataPtr;\r
132                         Arc_Signal->ComIPduHandleId = i;\r
133 \r
134                         // Clear update bits\r
135                         if (Signal->ComSignalArcUseUpdateBit) {\r
136                                 CLEARBIT(Arc_IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
137                         }\r
138 \r
139                         // If this signal is a signal group\r
140                         if (Signal->Com_Arc_IsSignalGroup) {\r
141 \r
142                                 // For each group signal of this signal group.\r
143                                 for(uint8 h = 0; Signal->ComGroupSignal[h] != NULL; h++) {\r
144                                         GroupSignal = Signal->ComGroupSignal[h];\r
145                                         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(GroupSignal->ComHandleId);\r
146                                         // Set pointer to shadow buffer\r
147                                         Arc_GroupSignal->Com_Arc_ShadowBuffer = Arc_Signal->Com_Arc_ShadowBuffer;\r
148                                         // Initialize group signal data.\r
149                                         Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, GroupSignal->ComHandleId, GroupSignal->ComSignalInitValue);\r
150                                 }\r
151 \r
152                         } else {\r
153                                 // Initialize signal data.\r
154                                 Com_WriteSignalDataToPdu(Signal->ComHandleId, Signal->ComSignalInitValue);\r
155                         }\r
156                 }\r
157 \r
158                 // Configure per I-PDU based deadline monitoring.\r
159                 for (uint16 j = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[j] != NULL); j++) {\r
160                         Signal = IPdu->ComIPduSignalRef[j];\r
161                         Com_Arc_Signal_type * Arc_Signal = GET_ArcSignal(Signal->ComHandleId);\r
162 \r
163                         if ( (Signal->ComTimeoutFactor > 0) && (!Signal->ComSignalArcUseUpdateBit) ) {\r
164                                 Arc_Signal->ComTimeoutFactor = earliestDeadline;\r
165                                 Arc_Signal->Com_Arc_DeadlineCounter = firstTimeout;\r
166                         }\r
167                 }\r
168         }\r
169         for (uint16 i = 0; i < COM_N_IPDUS; i++) {\r
170                 Com_BufferPduState[i].currentPosition = 0;\r
171                 Com_BufferPduState[i].locked = false;\r
172         }\r
173 \r
174         // An error occurred.\r
175         if (failure) {\r
176                 DEBUG(DEBUG_LOW, "--Initialization of COM failed--\n");\r
177                 //DET_REPORTERROR(COM_MODULE_ID, COM_INSTANCE_ID, 0x01, COM_E_INVALID_FILTER_CONFIGURATION);\r
178         } else {\r
179                 DEBUG(DEBUG_LOW, "--Initialization of COM completed--\n");\r
180         }\r
181 }\r
182 \r
183 \r
184 void Com_DeInit( void ) {\r
185 \r
186 }\r
187 \r
188 void Com_IpduGroupStart(Com_PduGroupIdType IpduGroupId,boolean Initialize) {\r
189         (void)Initialize; // Nothing to be done. This is just to avoid Lint warning.\r
190         for (uint16 i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) {\r
191                 if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) {\r
192                         Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 1;\r
193                 }\r
194         }\r
195 }\r
196 \r
197 void Com_IpduGroupStop(Com_PduGroupIdType IpduGroupId) {\r
198         for (uint16 i = 0; !ComConfig->ComIPdu[i].Com_Arc_EOL; i++) {\r
199                 if (ComConfig->ComIPdu[i].ComIPduGroupRef == IpduGroupId) {\r
200                         Com_Arc_Config.ComIPdu[i].Com_Arc_IpduStarted = 0;\r
201                 }\r
202         }\r
203 }\r
204 \r
205 /**\r
206  *
207  * @param PduId
208  * @param PduInfoPtr
209  * @param RetryInfoPtr not supported
210  * @param TxDataCntPtr
211  * @return
212  */\r
213 BufReq_ReturnType Com_CopyTxData(PduIdType PduId, PduInfoType* PduInfoPtr, RetryInfoType* RetryInfoPtr, PduLengthType* TxDataCntPtr) {\r
214         imask_t state;\r
215         Irq_Save(state);\r
216         BufReq_ReturnType r = BUFREQ_OK;\r
217         const ComIPdu_type *IPdu = GET_IPdu(PduId);\r
218         boolean dirOk = ComConfig->ComIPdu[PduId].ComIPduDirection == SEND;\r
219         boolean sizeOk = IPdu->ComIPduSize >= Com_BufferPduState[PduId].currentPosition + PduInfoPtr->SduLength;\r
220         if (dirOk && sizeOk) {\r
221                 void* source = GET_ArcIPdu(PduId)->ComIPduDataPtr;\r
222                 memcpy(PduInfoPtr->SduDataPtr,source + Com_BufferPduState[PduId].currentPosition, PduInfoPtr->SduLength);\r
223                 Com_BufferPduState[PduId].currentPosition += PduInfoPtr->SduLength;\r
224                 *TxDataCntPtr = IPdu->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
225         } else {\r
226                 r = BUFREQ_NOT_OK;\r
227         }\r
228         Irq_Restore(state);\r
229         return r;\r
230 }\r
231 BufReq_ReturnType Com_CopyRxData(PduIdType PduId, const PduInfoType* PduInfoPtr, PduLengthType* RxBufferSizePtr) {\r
232         imask_t state;\r
233         Irq_Save(state);\r
234         BufReq_ReturnType r = BUFREQ_OK;\r
235         uint8 remainingBytes = GET_IPdu(PduId)->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
236         boolean sizeOk = remainingBytes >= PduInfoPtr->SduLength;\r
237         boolean dirOk = GET_IPdu(PduId)->ComIPduDirection == RECEIVE;\r
238         boolean lockOk = isPduBufferLocked(PduId);\r
239         if (dirOk && lockOk && sizeOk) {\r
240                 memcpy(GET_ArcIPdu(PduId)->ComIPduDataPtr+Com_BufferPduState[PduId].currentPosition, PduInfoPtr->SduDataPtr, PduInfoPtr->SduLength);\r
241                 Com_BufferPduState[PduId].currentPosition += PduInfoPtr->SduLength;\r
242                 *RxBufferSizePtr = GET_IPdu(PduId)->ComIPduSize - Com_BufferPduState[PduId].currentPosition;\r
243         } else {\r
244                 r = BUFREQ_NOT_OK;\r
245         }\r
246         return r;\r
247         Irq_Restore(state);\r
248 }\r
249 BufReq_ReturnType Com_StartOfReception(PduIdType ComRxPduId, PduLengthType TpSduLength, PduLengthType* RxBufferSizePtr) {\r
250         PduLengthType ComIPduSize;\r
251         imask_t state;\r
252         Irq_Save(state);\r
253         BufReq_ReturnType r = BUFREQ_OK;\r
254         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);\r
255         if (Arc_IPdu->Com_Arc_IpduStarted) {\r
256                 if (GET_IPdu(ComRxPduId)->ComIPduDirection == RECEIVE) {\r
257                         if (!Com_BufferPduState[ComRxPduId].locked) {\r
258                                 ComIPduSize = GET_IPdu(ComRxPduId)->ComIPduSize;\r
259                                 if (ComIPduSize >= TpSduLength) {\r
260                                         Com_BufferPduState[ComRxPduId].locked = true;\r
261                                         *RxBufferSizePtr = ComIPduSize;\r
262                                         Com_BufferPduState[ComRxPduId].locked = true;\r
263                                 } else {\r
264                                         r = BUFREQ_OVFL;\r
265                                 }\r
266                         } else {\r
267                                 r = BUFREQ_BUSY;\r
268                         }\r
269                 }\r
270         } else {\r
271                 r = BUFREQ_NOT_OK;\r
272         }\r
273         Irq_Restore(state);\r
274         return r;\r
275 }\r