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