]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Com/Com_Com.c
COM protection
[arc.git] / communication / Com / 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 <stdlib.h>\r
24 #include <string.h>\r
25 #include "Com_Arc_Types.h"\r
26 #include "Com.h"\r
27 #include "Com_Internal.h"\r
28 #include "Com_misc.h"\r
29 #include "debug.h"\r
30 #include "PduR.h"\r
31 #include "Det.h"\r
32 #include "Cpu.h"\r
33 \r
34 Com_BufferPduStateType Com_BufferPduState[COM_N_IPDUS];\r
35 \r
36 \r
37 uint8 Com_SendSignal(Com_SignalIdType SignalId, const void *SignalDataPtr) {\r
38         VALIDATE_SIGNAL(SignalId, 0x0a, E_NOT_OK);\r
39         // Store pointer to signal for easier coding.\r
40         const ComSignal_type * Signal = GET_Signal(SignalId);\r
41         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
42         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(Signal->ComIPduHandleId);\r
43 \r
44         if (isPduBufferLocked(getPduId(IPdu))) {\r
45                 return COM_BUSY;\r
46         }\r
47         //DEBUG(DEBUG_LOW, "Com_SendSignal: id %d, nBytes %d, BitPosition %d, intVal %d\n", SignalId, nBytes, signal->ComBitPosition, (uint32)*(uint8 *)SignalDataPtr);\r
48 \r
49         imask_t irq_state;\r
50 \r
51         Irq_Save(irq_state);\r
52         Com_WriteSignalDataToPdu(Signal->ComHandleId, SignalDataPtr);\r
53 \r
54         // If the signal has an update bit. Set it!\r
55         if (Signal->ComSignalArcUseUpdateBit) {\r
56                 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
57         }\r
58 \r
59         /*\r
60          * If signal has triggered transmit property, trigger a transmission!\r
61          */\r
62         if (Signal->ComTransferProperty == TRIGGERED) {\r
63                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;\r
64         }\r
65         Irq_Restore(irq_state);\r
66 \r
67         return E_OK;\r
68 }\r
69 \r
70 uint8 Com_ReceiveSignal(Com_SignalIdType SignalId, void* SignalDataPtr) {\r
71         VALIDATE_SIGNAL(SignalId, 0x0b, E_NOT_OK);\r
72         DEBUG(DEBUG_LOW, "Com_ReceiveSignal: SignalId %d\n", SignalId);\r
73 \r
74         const ComSignal_type * Signal = GET_Signal(SignalId);\r
75         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
76         if (isPduBufferLocked(getPduId(IPdu))) {\r
77                 return COM_BUSY;\r
78         }\r
79 \r
80         Com_ReadSignalDataFromPdu(SignalId, SignalDataPtr);\r
81 \r
82         return E_OK;\r
83 }\r
84 \r
85 uint8 Com_ReceiveDynSignal(Com_SignalIdType SignalId, void* SignalDataPtr, uint16* Length) {\r
86         const ComSignal_type * Signal = GET_Signal(SignalId);\r
87         Com_Arc_IPdu_type    *Arc_IPdu   = GET_ArcIPdu(Signal->ComIPduHandleId);\r
88         const ComIPdu_type   *IPdu       = GET_IPdu(Signal->ComIPduHandleId);\r
89     imask_t state;\r
90 \r
91         Com_SignalType signalType = Signal->ComSignalType;\r
92         if (signalType != UINT8_DYN || isPduBufferLocked(getPduId(IPdu))) {\r
93                 return COM_SERVICE_NOT_AVAILABLE;\r
94         }\r
95 \r
96     Irq_Save(state);\r
97 \r
98         if (*Length > Arc_IPdu->Com_Arc_DynSignalLength) {\r
99                 *Length = Arc_IPdu->Com_Arc_DynSignalLength;\r
100         }\r
101         uint8 startFromPduByte = (Signal->ComBitPosition) / 8;\r
102         memcpy(SignalDataPtr, IPdu->ComIPduDataPtr + startFromPduByte, *Length);\r
103 \r
104     Irq_Restore(state);\r
105 \r
106         return E_OK;\r
107 }\r
108 \r
109 uint8 Com_SendDynSignal(Com_SignalIdType SignalId, const void* SignalDataPtr, uint16 Length) {\r
110         const ComSignal_type * Signal = GET_Signal(SignalId);\r
111         Com_Arc_IPdu_type    *Arc_IPdu   = GET_ArcIPdu(Signal->ComIPduHandleId);\r
112         const ComIPdu_type   *IPdu       = GET_IPdu(Signal->ComIPduHandleId);\r
113     imask_t state;\r
114 \r
115         Com_SignalType signalType = Signal->ComSignalType;\r
116         if (signalType != UINT8_DYN) {\r
117                 return COM_SERVICE_NOT_AVAILABLE;\r
118         }\r
119         if (isPduBufferLocked(getPduId(IPdu))) {\r
120                 return COM_BUSY;\r
121         }\r
122         uint8 signalLength = Signal->ComBitSize / 8;\r
123         Com_BitPositionType bitPosition = Signal->ComBitPosition;\r
124         if (signalLength < Length) {\r
125                 return E_NOT_OK;\r
126         }\r
127         uint8 startFromPduByte = bitPosition / 8;\r
128 \r
129         Irq_Save(state);\r
130         memcpy((void *)(IPdu->ComIPduDataPtr + startFromPduByte), SignalDataPtr, Length);\r
131         Arc_IPdu->Com_Arc_DynSignalLength = Length;\r
132         // If the signal has an update bit. Set it!\r
133         if (Signal->ComSignalArcUseUpdateBit) {\r
134                 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
135         }\r
136          // If signal has triggered transmit property, trigger a transmission!\r
137         if (Signal->ComTransferProperty == TRIGGERED) {\r
138                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;\r
139         }\r
140     Irq_Restore(state);\r
141 \r
142     return E_OK;\r
143 }\r
144 \r
145 Std_ReturnType Com_TriggerTransmit(PduIdType ComTxPduId, PduInfoType *PduInfoPtr) {\r
146         PDU_ID_CHECK(ComTxPduId, 0x13, E_NOT_OK);\r
147         /*\r
148          * COM260: This function must not check the transmission mode of the I-PDU\r
149          * since it should be possible to use it regardless of the transmission mode.\r
150          */\r
151 \r
152         /*\r
153          * COM395: This function must override the IPdu callouts used in Com_TriggerIPduTransmit();\r
154          */\r
155         const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);\r
156 \r
157     imask_t state;\r
158     Irq_Save(state);\r
159 \r
160     memcpy(PduInfoPtr->SduDataPtr, IPdu->ComIPduDataPtr, IPdu->ComIPduSize);\r
161 \r
162     Irq_Restore(state);\r
163 \r
164         PduInfoPtr->SduLength = IPdu->ComIPduSize;\r
165         return E_OK;\r
166 }\r
167 \r
168 \r
169 //lint -esym(904, Com_TriggerIPduSend) //PC-Lint Exception of rule 14.7\r
170 void Com_TriggerIPduSend(PduIdType ComTxPduId) {\r
171         PDU_ID_CHECK(ComTxPduId, 0x17);\r
172 \r
173         const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);\r
174         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComTxPduId);\r
175     imask_t state;\r
176     Irq_Save(state);\r
177 \r
178         // Is the IPdu ready for transmission?\r
179         if (Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer == 0) {\r
180 \r
181         //lint --e(725) Suppress PC-Lint warning "Expected positive indentation...". What means?\r
182                 // Check callout status\r
183                 if (IPdu->ComIPduCallout != NULL) {\r
184                         if (!IPdu->ComIPduCallout(ComTxPduId, IPdu->ComIPduDataPtr)) {\r
185                                 // TODO Report error to DET.\r
186                                 // Det_ReportError();\r
187                             Irq_Restore(state);\r
188                                 return;\r
189                         }\r
190                 }\r
191                 PduInfoType PduInfoPackage;\r
192                 PduInfoPackage.SduDataPtr = (uint8 *)IPdu->ComIPduDataPtr;\r
193                 if (IPdu->ComIPduDynSignalRef != 0) {\r
194                         uint8 sizeWithoutDynSignal = IPdu->ComIPduSize - (IPdu->ComIPduDynSignalRef->ComBitSize/8);\r
195                         PduInfoPackage.SduLength = sizeWithoutDynSignal + Arc_IPdu->Com_Arc_DynSignalLength;\r
196                 } else {\r
197                         PduInfoPackage.SduLength = IPdu->ComIPduSize;\r
198                 }\r
199 \r
200                 // Send IPdu!\r
201                 if (PduR_ComTransmit(IPdu->ArcIPduOutgoingId, &PduInfoPackage) == E_OK) {\r
202                         // Clear all update bits for the contained signals\r
203                         for (uint8 i = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[i] != NULL); i++) {\r
204                                 if (IPdu->ComIPduSignalRef[i]->ComSignalArcUseUpdateBit) {\r
205                                         CLEARBIT(IPdu->ComIPduDataPtr, IPdu->ComIPduSignalRef[i]->ComUpdateBitPosition);\r
206                                 }\r
207                         }\r
208                 } else {\r
209                         UnlockTpBuffer(getPduId(IPdu));\r
210                 }\r
211 \r
212                 // Reset miminum delay timer.\r
213                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer = IPdu->ComTxIPdu.ComTxIPduMinimumDelayFactor;\r
214         } else {\r
215                 //DEBUG(DEBUG_MEDIUM, "failed (MDT)!\n", ComTxPduId);\r
216         }\r
217     Irq_Restore(state);\r
218 }\r
219 \r
220 //lint -esym(904, Com_RxIndication) //PC-Lint Exception of rule 14.7\r
221 void Com_RxIndication(PduIdType ComRxPduId, const PduInfoType* PduInfoPtr) {\r
222         PDU_ID_CHECK(ComRxPduId, 0x14);\r
223 \r
224         const ComIPdu_type *IPdu = GET_IPdu(ComRxPduId);\r
225         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);\r
226         imask_t state;\r
227         Irq_Save(state);\r
228 \r
229         // If Ipdu is stopped\r
230         if (!Arc_IPdu->Com_Arc_IpduStarted) {\r
231                 Irq_Restore(state);\r
232                 return;\r
233         }\r
234 \r
235         // Check callout status\r
236         if (IPdu->ComIPduCallout != NULL) {\r
237                 if (!IPdu->ComIPduCallout(ComRxPduId, PduInfoPtr->SduDataPtr)) {\r
238                         // TODO Report error to DET.\r
239                         // Det_ReportError();\r
240                         Irq_Restore(state);\r
241                         return;\r
242                 }\r
243         }\r
244 \r
245         // Copy IPDU data\r
246         memcpy((void *)IPdu->ComIPduDataPtr, PduInfoPtr->SduDataPtr, IPdu->ComIPduSize);\r
247 \r
248         Com_RxProcessSignals(IPdu,Arc_IPdu);\r
249 \r
250         Irq_Restore(state);\r
251 \r
252         return;\r
253 }\r
254 \r
255 void Com_TpRxIndication(PduIdType PduId, NotifResultType Result) {\r
256         PDU_ID_CHECK(PduId, 0x14);\r
257 \r
258         const ComIPdu_type *IPdu = GET_IPdu(PduId);\r
259         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(PduId);\r
260         imask_t state;\r
261 \r
262         Irq_Save(state);\r
263 \r
264         // If Ipdu is stopped\r
265         if (!Arc_IPdu->Com_Arc_IpduStarted) {\r
266                 Irq_Restore(state);\r
267                 return;\r
268         }\r
269 \r
270         // unlock buffer\r
271         UnlockTpBuffer(getPduId(IPdu));\r
272 \r
273         if (Result == NTFRSLT_OK) {\r
274                 Com_RxProcessSignals(IPdu,Arc_IPdu);\r
275         }\r
276 \r
277         Irq_Restore(state);\r
278 }\r
279 \r
280 void Com_TpTxConfirmation(PduIdType PduId, NotifResultType Result) {\r
281         PDU_ID_CHECK(PduId, 0x15);\r
282         const ComIPdu_type *IPdu = GET_IPdu(PduId);\r
283         (void)Result; // touch\r
284 \r
285         imask_t state;\r
286         Irq_Save(state);\r
287         UnlockTpBuffer(getPduId(IPdu));\r
288         Irq_Restore(state);\r
289 }\r
290 void Com_TxConfirmation(PduIdType ComTxPduId) {\r
291         PDU_ID_CHECK(ComTxPduId, 0x15);\r
292 \r
293         (void)ComTxPduId; // Nothing to be done. This is just to avoid Lint warning.\r
294 }\r
295 \r
296 \r
297 Std_ReturnType Com_SendSignalGroup(Com_SignalGroupIdType SignalGroupId) {\r
298 //#warning Com_SendSignalGroup should be performed atomically. Should we disable interrupts here?\r
299         const ComSignal_type * Signal = GET_Signal(SignalGroupId);\r
300         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(Signal->ComIPduHandleId);\r
301         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
302 \r
303         if (isPduBufferLocked(getPduId(IPdu))) {\r
304                 return COM_BUSY;\r
305         }\r
306 \r
307         // Copy shadow buffer to Ipdu data space\r
308         const ComGroupSignal_type *groupSignal;\r
309         imask_t irq_state;\r
310 \r
311         Irq_Save(irq_state);\r
312         for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {\r
313                 groupSignal = Signal->ComGroupSignal[i];\r
314 \r
315                 Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, groupSignal->ComHandleId, Signal->Com_Arc_ShadowBuffer);\r
316         }\r
317 \r
318         // If the signal has an update bit. Set it!\r
319         if (Signal->ComSignalArcUseUpdateBit) {\r
320                 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
321         }\r
322 \r
323         // If signal has triggered transmit property, trigger a transmission!\r
324         if (Signal->ComTransferProperty == TRIGGERED) {\r
325                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;\r
326         }\r
327         Irq_Restore(irq_state);\r
328 \r
329         return E_OK;\r
330 }\r
331 \r
332 \r
333 Std_ReturnType Com_ReceiveSignalGroup(Com_SignalGroupIdType SignalGroupId) {\r
334 //#warning Com_ReceiveSignalGroup should be performed atomically. Should we disable interrupts here?\r
335         const ComSignal_type * Signal = GET_Signal(SignalGroupId);\r
336         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
337 \r
338         if (isPduBufferLocked(getPduId(IPdu))) {\r
339                 return COM_BUSY;\r
340         }\r
341         // Copy Ipdu data buffer to shadow buffer.\r
342         const ComGroupSignal_type *groupSignal;\r
343         imask_t irq_state;\r
344 \r
345         Irq_Save(irq_state);\r
346         for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {\r
347                 groupSignal = Signal->ComGroupSignal[i];\r
348 \r
349                 Com_ReadSignalDataFromPdu(groupSignal->ComHandleId, (void *)Signal->Com_Arc_ShadowBuffer);\r
350         }\r
351         Irq_Restore(irq_state);\r
352 \r
353         return E_OK;\r
354 }\r
355 \r
356 void Com_UpdateShadowSignal(Com_SignalIdType SignalId, const void *SignalDataPtr) {\r
357         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(SignalId);\r
358 \r
359         Com_WriteSignalDataToPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer, 8);\r
360 }\r
361 \r
362 void Com_ReceiveShadowSignal(Com_SignalIdType SignalId, void *SignalDataPtr) {\r
363         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(SignalId);\r
364         uint8 pduSize = GET_IPdu(GET_Signal(SignalId)->ComIPduHandleId)->ComIPduSize;\r
365 \r
366         Com_ReadSignalDataFromPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer,pduSize);\r
367 }\r
368 \r
369 \r
370 \r