1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
17 //lint -esym(960,8.7) PC-Lint misunderstanding of Misra 8.7 for Com_SystenEndianness and endianess_test
\r
25 #include "Com_Arc_Types.h"
\r
27 #include "Com_Internal.h"
\r
28 #include "Com_misc.h"
\r
34 Com_BufferPduStateType Com_BufferPduState[COM_N_IPDUS];
\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
44 if (isPduBufferLocked(getPduId(IPdu))) {
\r
47 //DEBUG(DEBUG_LOW, "Com_SendSignal: id %d, nBytes %d, BitPosition %d, intVal %d\n", SignalId, nBytes, signal->ComBitPosition, (uint32)*(uint8 *)SignalDataPtr);
\r
51 Irq_Save(irq_state);
\r
52 Com_WriteSignalDataToPdu(Signal->ComHandleId, SignalDataPtr);
\r
54 // If the signal has an update bit. Set it!
\r
55 if (Signal->ComSignalArcUseUpdateBit) {
\r
56 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);
\r
60 * If signal has triggered transmit property, trigger a transmission!
\r
62 if (Signal->ComTransferProperty == TRIGGERED) {
\r
63 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduNumberOfRepetitionsLeft = IPdu->ComTxIPdu.ComTxModeTrue.ComTxModeNumberOfRepetitions + 1;
\r
65 Irq_Restore(irq_state);
\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
74 const ComSignal_type * Signal = GET_Signal(SignalId);
\r
75 const ComIPdu_type *IPdu = GET_IPdu(Signal->ComIPduHandleId);
\r
78 const void* pduDataPtr = 0;
\r
79 if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {
\r
80 pduDataPtr = IPdu->ComIPduDeferredDataPtr;
\r
82 if (isPduBufferLocked(getPduId(IPdu))) {
\r
85 pduDataPtr = IPdu->ComIPduDataPtr;
\r
87 Com_ReadSignalDataFromPduBuffer(
\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
103 Com_SignalType signalType = Signal->ComSignalType;
\r
104 if (signalType != UINT8_DYN) {
\r
105 return COM_SERVICE_NOT_AVAILABLE;
\r
110 if (*Length > Arc_IPdu->Com_Arc_DynSignalLength) {
\r
111 *Length = Arc_IPdu->Com_Arc_DynSignalLength;
\r
113 uint8 startFromPduByte = (Signal->ComBitPosition) / 8;
\r
115 const void* pduDataPtr = 0;
\r
116 if (IPdu->ComIPduSignalProcessing == DEFERRED && IPdu->ComIPduDirection == RECEIVE) {
\r
117 pduDataPtr = IPdu->ComIPduDeferredDataPtr;
\r
119 if (isPduBufferLocked(getPduId(IPdu))) {
\r
122 pduDataPtr = IPdu->ComIPduDataPtr;
\r
124 memcpy(SignalDataPtr, pduDataPtr + startFromPduByte, *Length);
\r
126 Irq_Restore(state);
\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
137 Com_SignalType signalType = Signal->ComSignalType;
\r
138 if (signalType != UINT8_DYN) {
\r
139 return COM_SERVICE_NOT_AVAILABLE;
\r
141 if (isPduBufferLocked(getPduId(IPdu))) {
\r
144 uint8 signalLength = Signal->ComBitSize / 8;
\r
145 Com_BitPositionType bitPosition = Signal->ComBitPosition;
\r
146 if (signalLength < Length) {
\r
149 uint8 startFromPduByte = bitPosition / 8;
\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
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
162 Irq_Restore(state);
\r
167 Std_ReturnType Com_TriggerTransmit(PduIdType ComTxPduId, PduInfoType *PduInfoPtr) {
\r
168 PDU_ID_CHECK(ComTxPduId, 0x13, E_NOT_OK);
\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
175 * COM395: This function must override the IPdu callouts used in Com_TriggerIPduTransmit();
\r
177 const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);
\r
182 memcpy(PduInfoPtr->SduDataPtr, IPdu->ComIPduDataPtr, IPdu->ComIPduSize);
\r
184 Irq_Restore(state);
\r
186 PduInfoPtr->SduLength = IPdu->ComIPduSize;
\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
195 const ComIPdu_type *IPdu = GET_IPdu(ComTxPduId);
\r
196 Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComTxPduId);
\r
200 // Is the IPdu ready for transmission?
\r
201 if (Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer == 0) {
\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
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
219 PduInfoPackage.SduLength = IPdu->ComIPduSize;
\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
231 UnlockTpBuffer(getPduId(IPdu));
\r
234 // Reset miminum delay timer.
\r
235 Arc_IPdu->Com_Arc_TxIPduTimers.ComTxIPduMinimumDelayTimer = IPdu->ComTxIPdu.ComTxIPduMinimumDelayFactor;
\r
237 //DEBUG(DEBUG_MEDIUM, "failed (MDT)!\n", ComTxPduId);
\r
239 Irq_Restore(state);
\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
246 const ComIPdu_type *IPdu = GET_IPdu(ComRxPduId);
\r
247 Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(ComRxPduId);
\r
251 // If Ipdu is stopped
\r
252 if (!Arc_IPdu->Com_Arc_IpduStarted) {
\r
253 Irq_Restore(state);
\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
268 memcpy(IPdu->ComIPduDataPtr, PduInfoPtr->SduDataPtr, IPdu->ComIPduSize);
\r
270 Com_RxProcessSignals(IPdu,Arc_IPdu);
\r
272 Irq_Restore(state);
\r
277 void Com_TpRxIndication(PduIdType PduId, NotifResultType Result) {
\r
278 PDU_ID_CHECK(PduId, 0x14);
\r
280 const ComIPdu_type *IPdu = GET_IPdu(PduId);
\r
281 Com_Arc_IPdu_type *Arc_IPdu = GET_ArcIPdu(PduId);
\r
286 // If Ipdu is stopped
\r
287 if (!Arc_IPdu->Com_Arc_IpduStarted) {
\r
288 Irq_Restore(state);
\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
297 // In deferred mode, buffers are unlocked in mainfunction
\r
298 Com_RxProcessSignals(IPdu,Arc_IPdu);
\r
300 UnlockTpBuffer(getPduId(IPdu));
\r
302 Irq_Restore(state);
\r
306 void Com_TpTxConfirmation(PduIdType PduId, NotifResultType Result) {
\r
307 PDU_ID_CHECK(PduId, 0x15);
\r
308 (void)Result; // touch
\r
312 UnlockTpBuffer(PduId);
\r
313 Irq_Restore(state);
\r
315 void Com_TxConfirmation(PduIdType ComTxPduId) {
\r
316 PDU_ID_CHECK(ComTxPduId, 0x15);
\r
318 (void)ComTxPduId; // Nothing to be done. This is just to avoid Lint warning.
\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
328 if (isPduBufferLocked(getPduId(IPdu))) {
\r
332 // Copy shadow buffer to Ipdu data space
\r
333 const ComGroupSignal_type *groupSignal;
\r
336 Irq_Save(irq_state);
\r
337 for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {
\r
338 groupSignal = Signal->ComGroupSignal[i];
\r
340 Com_WriteGroupSignalDataToPdu(Signal->ComHandleId, groupSignal->ComHandleId, Signal->Com_Arc_ShadowBuffer);
\r
343 // If the signal has an update bit. Set it!
\r
344 if (Signal->ComSignalArcUseUpdateBit) {
\r
345 SETBIT(IPdu->ComIPduDataPtr, Signal->ComUpdateBitPosition);
\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
352 Irq_Restore(irq_state);
\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
363 if (isPduBufferLocked(getPduId(IPdu))) {
\r
366 // Copy Ipdu data buffer to shadow buffer.
\r
367 const ComGroupSignal_type *groupSignal;
\r
370 Irq_Save(irq_state);
\r
371 for (uint8 i = 0; Signal->ComGroupSignal[i] != NULL; i++) {
\r
372 groupSignal = Signal->ComGroupSignal[i];
\r
374 Com_ReadSignalDataFromPdu(groupSignal->ComHandleId, (void *)Signal->Com_Arc_ShadowBuffer);
\r
376 Irq_Restore(irq_state);
\r
381 void Com_UpdateShadowSignal(Com_SignalIdType SignalId, const void *SignalDataPtr) {
\r
382 Com_Arc_GroupSignal_type *Arc_GroupSignal = GET_ArcGroupSignal(SignalId);
\r
384 Com_WriteSignalDataToPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer, 8);
\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
391 Com_ReadSignalDataFromPduBuffer(SignalId, TRUE, SignalDataPtr, (void *)Arc_GroupSignal->Com_Arc_ShadowBuffer,pduSize);
\r