]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Com/Com_Com.c
Ticket #1138 com should not check if buffers are locked if pdu is deferred
[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 \r
77         uint8 r = E_OK;\r
78         const void* pduDataPtr = 0;\r
79         if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {\r
80                 pduDataPtr = IPdu->ComIPduDeferredDataPtr;\r
81         } else {\r
82                 if (isPduBufferLocked(getPduId(IPdu))) {\r
83                         r = COM_BUSY;\r
84                 }\r
85                 pduDataPtr = IPdu->ComIPduDataPtr;\r
86         }\r
87         Com_ReadSignalDataFromPduBuffer(\r
88                         SignalId,\r
89                         FALSE,\r
90                         SignalDataPtr,\r
91                         pduDataPtr,\r
92                         IPdu->ComIPduSize);\r
93 \r
94         return r;\r
95 }\r
96 \r
97 uint8 Com_ReceiveDynSignal(Com_SignalIdType SignalId, void* SignalDataPtr, uint16* Length) {\r
98         const ComSignal_type * Signal = GET_Signal(SignalId);\r
99         Com_Arc_IPdu_type    *Arc_IPdu   = GET_ArcIPdu(Signal->ComIPduHandleId);\r
100         const ComIPdu_type   *IPdu       = GET_IPdu(Signal->ComIPduHandleId);\r
101     imask_t state;\r
102 \r
103         Com_SignalType signalType = Signal->ComSignalType;\r
104         if (signalType != UINT8_DYN) {\r
105                 return COM_SERVICE_NOT_AVAILABLE;\r
106         }\r
107 \r
108     Irq_Save(state);\r
109 \r
110         if (*Length > Arc_IPdu->Com_Arc_DynSignalLength) {\r
111                 *Length = Arc_IPdu->Com_Arc_DynSignalLength;\r
112         }\r
113         uint8 startFromPduByte = (Signal->ComBitPosition) / 8;\r
114         uint8 r = E_OK;\r
115         const void* pduDataPtr = 0;\r
116         if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {\r
117                 pduDataPtr = IPdu->ComIPduDeferredDataPtr;\r
118         } else {\r
119                 if (isPduBufferLocked(getPduId(IPdu))) {\r
120                         r = COM_BUSY;\r
121                 }\r
122                 pduDataPtr = IPdu->ComIPduDataPtr;\r
123         }\r
124         memcpy(SignalDataPtr, pduDataPtr + startFromPduByte, *Length);\r
125 \r
126     Irq_Restore(state);\r
127 \r
128         return r;\r
129 }\r
130 \r
131 uint8 Com_SendDynSignal(Com_SignalIdType SignalId, const void* SignalDataPtr, uint16 Length) {\r
132         const ComSignal_type * Signal = GET_Signal(SignalId);\r
133         Com_Arc_IPdu_type    *Arc_IPdu   = GET_ArcIPdu(Signal->ComIPduHandleId);\r
134         const ComIPdu_type   *IPdu       = GET_IPdu(Signal->ComIPduHandleId);\r
135     imask_t state;\r
136 \r
137         Com_SignalType signalType = Signal->ComSignalType;\r
138         if (signalType != UINT8_DYN) {\r
139                 return COM_SERVICE_NOT_AVAILABLE;\r
140         }\r
141         if (isPduBufferLocked(getPduId(IPdu))) {\r
142                 return COM_BUSY;\r
143         }\r
144         uint8 signalLength = Signal->ComBitSize / 8;\r
145         Com_BitPositionType bitPosition = Signal->ComBitPosition;\r
146         if (signalLength < Length) {\r
147                 return E_NOT_OK;\r
148         }\r
149         uint8 startFromPduByte = bitPosition / 8;\r
150 \r
151         Irq_Save(state);\r
152         memcpy((void *)(IPdu->ComIPduDataPtr + startFromPduByte), SignalDataPtr, Length);\r
153         Arc_IPdu->Com_Arc_DynSignalLength = Length;\r
154         // If the signal has an update bit. Set it!\r
155         if (Signal->ComSignalArcUseUpdateBit) {\r
156                 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
157         }\r
158          // If signal has triggered transmit property, trigger a transmission!\r
159         if (Signal->ComTransferProperty == TRIGGERED) {\r
160                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;\r
161         }\r
162     Irq_Restore(state);\r
163 \r
164     return E_OK;\r
165 }\r
166 \r
167 Std_ReturnType Com_TriggerTransmit(PduIdType ComTxPduId, PduInfoType *PduInfoPtr) {\r
168         PDU_ID_CHECK(ComTxPduId, 0x13, E_NOT_OK);\r
169         /*\r
170          * COM260: This function must not check the transmission mode of the I-PDU\r
171          * since it should be possible to use it regardless of the transmission mode.\r
172          */\r
173 \r
174         /*\r
175          * COM395: This function must override the IPdu callouts used in Com_TriggerIPduTransmit();\r
176          */\r
177         const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);\r
178 \r
179     imask_t state;\r
180     Irq_Save(state);\r
181 \r
182     memcpy(PduInfoPtr->SduDataPtr, IPdu->ComIPduDataPtr, IPdu->ComIPduSize);\r
183 \r
184     Irq_Restore(state);\r
185 \r
186         PduInfoPtr->SduLength = IPdu->ComIPduSize;\r
187         return E_OK;\r
188 }\r
189 \r
190 \r
191 //lint -esym(904, Com_TriggerIPduSend) //PC-Lint Exception of rule 14.7\r
192 void Com_TriggerIPduSend(PduIdType ComTxPduId) {\r
193         PDU_ID_CHECK(ComTxPduId, 0x17);\r
194 \r
195         const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);\r
196         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComTxPduId);\r
197     imask_t state;\r
198     Irq_Save(state);\r
199 \r
200         // Is the IPdu ready for transmission?\r
201         if (Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer == 0) {\r
202 \r
203         //lint --e(725) Suppress PC-Lint warning "Expected positive indentation...". What means?\r
204                 // Check callout status\r
205                 if (IPdu->ComIPduCallout != NULL) {\r
206                         if (!IPdu->ComIPduCallout(ComTxPduId, IPdu->ComIPduDataPtr)) {\r
207                                 // TODO Report error to DET.\r
208                                 // Det_ReportError();\r
209                             Irq_Restore(state);\r
210                                 return;\r
211                         }\r
212                 }\r
213                 PduInfoType PduInfoPackage;\r
214                 PduInfoPackage.SduDataPtr = (uint8 *)IPdu->ComIPduDataPtr;\r
215                 if (IPdu->ComIPduDynSignalRef != 0) {\r
216                         uint8 sizeWithoutDynSignal = IPdu->ComIPduSize - (IPdu->ComIPduDynSignalRef->ComBitSize/8);\r
217                         PduInfoPackage.SduLength = sizeWithoutDynSignal + Arc_IPdu->Com_Arc_DynSignalLength;\r
218                 } else {\r
219                         PduInfoPackage.SduLength = IPdu->ComIPduSize;\r
220                 }\r
221 \r
222                 // Send IPdu!\r
223                 if (PduR_ComTransmit(IPdu->ArcIPduOutgoingId, &PduInfoPackage) == E_OK) {\r
224                         // Clear all update bits for the contained signals\r
225                         for (uint8 i = 0; (IPdu->ComIPduSignalRef != NULL) && (IPdu->ComIPduSignalRef[i] != NULL); i++) {\r
226                                 if (IPdu->ComIPduSignalRef[i]->ComSignalArcUseUpdateBit) {\r
227                                         CLEARBIT(IPdu->ComIPduDataPtr, IPdu->ComIPduSignalRef[i]->ComUpdateBitPosition);\r
228                                 }\r
229                         }\r
230                 } else {\r
231                         UnlockTpBuffer(getPduId(IPdu));\r
232                 }\r
233 \r
234                 // Reset miminum delay timer.\r
235                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer = IPdu->ComTxIPdu.ComTxIPduMinimumDelayFactor;\r
236         } else {\r
237                 //DEBUG(DEBUG_MEDIUM, "failed (MDT)!\n", ComTxPduId);\r
238         }\r
239     Irq_Restore(state);\r
240 }\r
241 \r
242 //lint -esym(904, Com_RxIndication) //PC-Lint Exception of rule 14.7\r
243 void Com_RxIndication(PduIdType ComRxPduId, const PduInfoType* PduInfoPtr) {\r
244         PDU_ID_CHECK(ComRxPduId, 0x14);\r
245 \r
246         const ComIPdu_type *IPdu = GET_IPdu(ComRxPduId);\r
247         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);\r
248         imask_t state;\r
249         Irq_Save(state);\r
250 \r
251         // If Ipdu is stopped\r
252         if (!Arc_IPdu->Com_Arc_IpduStarted) {\r
253                 Irq_Restore(state);\r
254                 return;\r
255         }\r
256 \r
257         // Check callout status\r
258         if (IPdu->ComIPduCallout != NULL) {\r
259                 if (!IPdu->ComIPduCallout(ComRxPduId, PduInfoPtr->SduDataPtr)) {\r
260                         // TODO Report error to DET.\r
261                         // Det_ReportError();\r
262                         Irq_Restore(state);\r
263                         return;\r
264                 }\r
265         }\r
266 \r
267         // Copy IPDU data\r
268         memcpy(IPdu->ComIPduDataPtr, PduInfoPtr->SduDataPtr, IPdu->ComIPduSize);\r
269 \r
270         Com_RxProcessSignals(IPdu,Arc_IPdu);\r
271 \r
272         Irq_Restore(state);\r
273 \r
274         return;\r
275 }\r
276 \r
277 void Com_TpRxIndication(PduIdType PduId, NotifResultType Result) {\r
278         PDU_ID_CHECK(PduId, 0x14);\r
279 \r
280         const ComIPdu_type *IPdu = GET_IPdu(PduId);\r
281         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(PduId);\r
282         imask_t state;\r
283 \r
284         Irq_Save(state);\r
285 \r
286         // If Ipdu is stopped\r
287         if (!Arc_IPdu->Com_Arc_IpduStarted) {\r
288                 Irq_Restore(state);\r
289                 return;\r
290         }\r
291         if (Result == NTFRSLT_OK) {\r
292                 if (IPdu->ComIPduSignalProcessing == IMMEDIATE) {\r
293                         // irqs needs to be disabled until signal notifications have been called\r
294                         // Otherwise a new Tp session can start and fill up pdus\r
295                         UnlockTpBuffer(getPduId(IPdu));\r
296                 }\r
297                 // In deferred mode, buffers are unlocked in mainfunction\r
298                 Com_RxProcessSignals(IPdu,Arc_IPdu);\r
299         } else {\r
300                 UnlockTpBuffer(getPduId(IPdu));\r
301         }\r
302         Irq_Restore(state);\r
303 \r
304 }\r
305 \r
306 void Com_TpTxConfirmation(PduIdType PduId, NotifResultType Result) {\r
307         PDU_ID_CHECK(PduId, 0x15);\r
308         (void)Result; // touch\r
309 \r
310         imask_t state;\r
311         Irq_Save(state);\r
312         UnlockTpBuffer(PduId);\r
313         Irq_Restore(state);\r
314 }\r
315 void Com_TxConfirmation(PduIdType ComTxPduId) {\r
316         PDU_ID_CHECK(ComTxPduId, 0x15);\r
317 \r
318         (void)ComTxPduId; // Nothing to be done. This is just to avoid Lint warning.\r
319 }\r
320 \r
321 \r
322 Std_ReturnType Com_SendSignalGroup(Com_SignalGroupIdType SignalGroupId) {\r
323 //#warning Com_SendSignalGroup should be performed atomically. Should we disable interrupts here?\r
324         const ComSignal_type * Signal = GET_Signal(SignalGroupId);\r
325         Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(Signal->ComIPduHandleId);\r
326         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
327 \r
328         if (isPduBufferLocked(getPduId(IPdu))) {\r
329                 return COM_BUSY;\r
330         }\r
331 \r
332         // Copy shadow buffer to Ipdu data space\r
333         const ComGroupSignal_type *groupSignal;\r
334         imask_t irq_state;\r
335 \r
336         Irq_Save(irq_state);\r
337         for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {\r
338                 groupSignal = Signal->ComGroupSignal[i];\r
339 \r
340                 Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, groupSignal->ComHandleId, Signal->Com_Arc_ShadowBuffer);\r
341         }\r
342 \r
343         // If the signal has an update bit. Set it!\r
344         if (Signal->ComSignalArcUseUpdateBit) {\r
345                 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);\r
346         }\r
347 \r
348         // If signal has triggered transmit property, trigger a transmission!\r
349         if (Signal->ComTransferProperty == TRIGGERED) {\r
350                 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;\r
351         }\r
352         Irq_Restore(irq_state);\r
353 \r
354         return E_OK;\r
355 }\r
356 \r
357 \r
358 Std_ReturnType Com_ReceiveSignalGroup(Com_SignalGroupIdType SignalGroupId) {\r
359 //#warning Com_ReceiveSignalGroup should be performed atomically. Should we disable interrupts here?\r
360         const ComSignal_type * Signal = GET_Signal(SignalGroupId);\r
361         const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);\r
362 \r
363         if (isPduBufferLocked(getPduId(IPdu))) {\r
364                 return COM_BUSY;\r
365         }\r
366         // Copy Ipdu data buffer to shadow buffer.\r
367         const ComGroupSignal_type *groupSignal;\r
368         imask_t irq_state;\r
369 \r
370         Irq_Save(irq_state);\r
371         for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {\r
372                 groupSignal = Signal->ComGroupSignal[i];\r
373 \r
374                 Com_ReadSignalDataFromPdu(groupSignal->ComHandleId, (void *)Signal->Com_Arc_ShadowBuffer);\r
375         }\r
376         Irq_Restore(irq_state);\r
377 \r
378         return E_OK;\r
379 }\r
380 \r
381 void Com_UpdateShadowSignal(Com_SignalIdType SignalId, const void *SignalDataPtr) {\r
382         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(SignalId);\r
383 \r
384         Com_WriteSignalDataToPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer, 8);\r
385 }\r
386 \r
387 void Com_ReceiveShadowSignal(Com_SignalIdType SignalId, void *SignalDataPtr) {\r
388         Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(SignalId);\r
389         uint8 pduSize = GET_IPdu(GET_Signal(SignalId)->ComIPduHandleId)->ComIPduSize;\r
390 \r
391         Com_ReadSignalDataFromPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer,pduSize);\r
392 }\r
393 \r
394 \r
395 \r