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
25 #include "LinIf_Types.h"
\r
26 #include "LinIf_Cbk.h"
\r
27 #include "LinIf_Cfg.h"
\r
29 #include "LinSM_Cbk.h"
\r
30 #include "PduR_LinIf.h"
\r
32 #if defined(USE_DEM)
\r
36 /* Development error macros. */
\r
37 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )
\r
38 #define VALIDATE(_exp,_api,_err ) \
\r
40 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
44 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
46 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
50 #define VALIDATE(_exp,_api,_err )
\r
51 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
57 LINIF_CHANNEL_UNINIT,
\r
58 LINIF_CHANNEL_OPERATIONAL,
\r
59 LINIF_CHANNEL_SLEEP_TRANS,
\r
60 LINIF_CHANNEL_SLEEP,
\r
63 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;
\r
64 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];
\r
66 static LinIf_ScheduleTableType *currentSchedule[LINIF_CONTROLLER_CNT];
\r
67 static uint16 currentIndex[LINIF_CONTROLLER_CNT];
\r
68 static uint16 currentDelayInTicks[LINIF_CONTROLLER_CNT];
\r
70 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];
\r
71 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];
\r
73 void LinIf_Init( const void* ConfigPtr )
\r
80 // Call Lin_InitChannel
\r
81 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
83 Lin_InitChannel(LinIfChannelCfg[i].LinIfChannelId, LinIfChannelCfg[i].LinIfChannelRef);
\r
84 LinIfChannelStatus[i] = LINIF_CHANNEL_OPERATIONAL;
\r
85 currentSchedule[i] = 0;
\r
86 currentIndex[i] = 0;
\r
87 currentDelayInTicks[i] = 0;
\r
88 newScheduleRequest[i] = FALSE;
\r
90 LinIfStatus = LINIF_INIT;
\r
97 // Call Lin_InitChannel
\r
98 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
100 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);
\r
102 // Uninitalize driver
\r
105 LinIfStatus = LINIF_UNINIT;
\r
108 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)
\r
110 // Sporadic frames not supported in this release
\r
111 //printf("LinIf_Transmit received request. Id: %d, Data: %d\n", LinTxPduId, *(PduInfoPtr->SduDataPtr));
\r
116 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)
\r
118 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
119 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
120 VALIDATE_W_RV( (LinIfChannelStatus[Channel] != LINIF_CHANNEL_SLEEP && LinIfChannelStatus[Channel] != LINIF_CHANNEL_SLEEP_TRANS), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_SCHEDULE_REQUEST_ERROR, E_NOT_OK);
\r
122 newScheduleRequest[Channel] = TRUE;
\r
123 newSchedule[Channel] = Schedule;
\r
128 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)
\r
130 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
131 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
133 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {
\r
134 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;
\r
140 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)
\r
142 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
143 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
145 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_SLEEP) {
\r
146 Lin_WakeUp(LinIfChannelCfg[Channel].LinIfChannelId);
\r
147 currentIndex[Channel] = 0;
\r
148 currentDelayInTicks[Channel] = 0;
\r
150 // LINIF432: The function LinIf_WakeUp shall do nothing and return E_OK when the
\r
151 // referenced channel is not in the sleep state.
\r
153 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;
\r
154 LinSM_WakeUp_Confirmation(Channel, TRUE);
\r
159 void LinIf_MainFunction()
\r
165 if (LinIfStatus == LINIF_UNINIT) {
\r
169 for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)
\r
171 // Check if there are any pending sleep transitions
\r
172 if (LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP_TRANS) {
\r
173 if (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP){
\r
174 Lin_GoToSleep(LinIfChannelCfg[chIndex].LinIfChannelId);
\r
178 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;
\r
179 LinSM_GotoSleep_Confirmation(chIndex, TRUE);
\r
181 // Set NULL schedule at sleep
\r
182 currentIndex[chIndex] = 0;
\r
183 currentDelayInTicks[chIndex] = 0;
\r
184 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[0];
\r
188 // Check if there are any wakeup transitions
\r
189 if ((LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP) &&
\r
190 (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP)) {
\r
191 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_OPERATIONAL;
\r
192 LinSM_WakeUp_Confirmation(chIndex, TRUE);
\r
195 // Normal scheduling
\r
196 if(currentDelayInTicks[chIndex] > 0){
\r
197 // Not time for sending yet
\r
198 currentDelayInTicks[chIndex]--;
\r
203 if(LinIfChannelStatus[chIndex] == LINIF_CHANNEL_OPERATIONAL) {
\r
204 //Check if NULL schedule is present otherwise check status of last sent
\r
205 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
206 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
207 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
209 // Handle received and sent frames
\r
210 if(ptrFrame->LinIfPduDirection == LinIfRxPdu){
\r
211 if(Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) == LIN_RX_OK){
\r
212 PduInfoType outgoingPdu;
\r
213 outgoingPdu.SduDataPtr = Lin_SduPtr;
\r
214 outgoingPdu.SduLength = ptrFrame->LinIfLength;
\r
215 PduR_LinIfRxIndication(ptrFrame->LinIfTxTargetPduId,&outgoingPdu);
\r
216 }else{// RX_ERROR or BUSY
\r
217 #if defined(USE_DEM)
\r
218 Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);
\r
221 } else if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
222 Lin_StatusType status = Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr);
\r
223 if(status == LIN_TX_OK){
\r
224 PduR_LinIfTxConfirmation(ptrFrame->LinIfTxTargetPduId);
\r
225 }else{// TX_ERROR or BUSY
\r
226 #if defined(USE_DEM)
\r
227 Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);
\r
231 // Update index after getting status of last frame
\r
232 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;
\r
236 //Set new schedule if ordered
\r
237 if(newScheduleRequest[chIndex] == TRUE){
\r
238 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[newSchedule[chIndex]];
\r
239 currentIndex[chIndex] = 0;
\r
240 newScheduleRequest[chIndex]=FALSE;
\r
241 LinSM_ScheduleRequest_Confirmation(chIndex);
\r
244 // Handle new transmissions
\r
245 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
246 Lin_PduType PduInfo;
\r
247 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
248 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
250 // Only UNCONDITIONAL frames is supported in first version
\r
251 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){
\r
253 if(ptrFrame->LinIfChecksumType==ENHANCED){
\r
254 PduInfo.Cs = LIN_ENHANCED_CS;
\r
256 PduInfo.Cs = LIN_CLASSIC_CS;
\r
258 PduInfo.Pid = ptrFrame->LinIfPid;
\r
259 PduInfo.SduPtr = buf; // Data will be added in PduR_LinIfTriggerTransmit
\r
260 PduInfo.DI = ptrFrame->LinIfLength;
\r
261 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
262 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
264 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
268 // Maybe send response also
\r
269 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
270 PduInfoType outgoingPdu;
\r
271 outgoingPdu.SduDataPtr = PduInfo.SduPtr;
\r
272 outgoingPdu.SduLength = PduInfo.DI;
\r
274 PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId, &outgoingPdu);
\r
275 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
276 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
280 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
285 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;
\r