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 #if defined(USE_PDUR)
\r
31 #include "PduR_LinIf.h"
\r
34 #if defined(USE_DEM)
\r
38 /* Development error macros. */
\r
39 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )
\r
40 #define VALIDATE(_exp,_api,_err ) \
\r
42 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
46 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
48 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
52 #define VALIDATE(_exp,_api,_err )
\r
53 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
59 LINIF_CHANNEL_UNINIT,
\r
60 LINIF_CHANNEL_OPERATIONAL,
\r
61 LINIF_CHANNEL_SLEEP_TRANS,
\r
62 LINIF_CHANNEL_SLEEP,
\r
65 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;
\r
66 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];
\r
68 static LinIf_ScheduleTableType *currentSchedule[LINIF_CONTROLLER_CNT];
\r
69 static uint16 currentIndex[LINIF_CONTROLLER_CNT];
\r
70 static uint16 currentDelayInTicks[LINIF_CONTROLLER_CNT];
\r
72 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];
\r
73 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];
\r
75 void LinIf_Init( const void* ConfigPtr )
\r
83 // Call Lin_InitChannel
\r
84 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
86 Lin_InitChannel(LinIfChannelCfg[i].LinIfChannelId, LinIfChannelCfg[i].LinIfChannelRef);
\r
87 LinIfChannelStatus[i] = LINIF_CHANNEL_OPERATIONAL;
\r
88 currentSchedule[i] = 0;
\r
89 currentIndex[i] = 0;
\r
90 currentDelayInTicks[i] = 0;
\r
91 newScheduleRequest[i] = FALSE;
\r
93 LinIfStatus = LINIF_INIT;
\r
100 // Call Lin_InitChannel
\r
101 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
103 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);
\r
105 // Uninitalize driver
\r
108 LinIfStatus = LINIF_UNINIT;
\r
111 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)
\r
115 // Sporadic frames not supported in this release
\r
116 //printf("LinIf_Transmit received request. Id: %d, Data: %d\n", LinTxPduId, *(PduInfoPtr->SduDataPtr));
\r
121 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)
\r
123 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
124 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
125 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
127 newScheduleRequest[Channel] = TRUE;
\r
128 newSchedule[Channel] = Schedule;
\r
133 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)
\r
135 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
136 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
138 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {
\r
139 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;
\r
145 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)
\r
147 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
148 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
150 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_SLEEP) {
\r
151 Lin_WakeUp(LinIfChannelCfg[Channel].LinIfChannelId);
\r
152 currentIndex[Channel] = 0;
\r
153 currentDelayInTicks[Channel] = 0;
\r
155 // LINIF432: The function LinIf_WakeUp shall do nothing and return E_OK when the
\r
156 // referenced channel is not in the sleep state.
\r
158 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;
\r
159 LinSM_WakeUp_Confirmation(Channel, TRUE);
\r
164 void LinIf_MainFunction()
\r
170 if (LinIfStatus == LINIF_UNINIT) {
\r
174 for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)
\r
176 // Check if there are any pending sleep transitions
\r
177 if (LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP_TRANS) {
\r
178 if (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP){
\r
179 Lin_GoToSleep(LinIfChannelCfg[chIndex].LinIfChannelId);
\r
183 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;
\r
184 LinSM_GotoSleep_Confirmation(chIndex, TRUE);
\r
186 // Set NULL schedule at sleep
\r
187 currentIndex[chIndex] = 0;
\r
188 currentDelayInTicks[chIndex] = 0;
\r
189 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[0];
\r
193 // Check if there are any wakeup transitions
\r
194 if ((LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP) &&
\r
195 (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP)) {
\r
196 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_OPERATIONAL;
\r
197 LinSM_WakeUp_Confirmation(chIndex, TRUE);
\r
200 // Normal scheduling
\r
201 if(currentDelayInTicks[chIndex] > 0){
\r
202 // Not time for sending yet
\r
203 currentDelayInTicks[chIndex]--;
\r
208 if(LinIfChannelStatus[chIndex] == LINIF_CHANNEL_OPERATIONAL) {
\r
209 //Check if NULL schedule is present otherwise check status of last sent
\r
210 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
211 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
212 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
214 // Handle received and sent frames
\r
215 if(ptrFrame->LinIfPduDirection == LinIfRxPdu){
\r
216 if(Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) == LIN_RX_OK){
\r
217 PduInfoType outgoingPdu;
\r
218 outgoingPdu.SduDataPtr = Lin_SduPtr;
\r
219 outgoingPdu.SduLength = ptrFrame->LinIfLength;
\r
220 PduR_LinIfRxIndication(ptrFrame->LinIfTxTargetPduId,&outgoingPdu);
\r
221 }else{// RX_ERROR or BUSY
\r
222 #if defined(USE_DEM)
\r
223 Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);
\r
226 } else if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
227 Lin_StatusType status = Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr);
\r
228 if(status == LIN_TX_OK){
\r
229 PduR_LinIfTxConfirmation(ptrFrame->LinIfTxTargetPduId);
\r
230 }else{// TX_ERROR or BUSY
\r
231 #if defined(USE_DEM)
\r
232 Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);
\r
236 // Update index after getting status of last frame
\r
237 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;
\r
241 //Set new schedule if ordered
\r
242 if(newScheduleRequest[chIndex] == TRUE){
\r
243 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[newSchedule[chIndex]];
\r
244 currentIndex[chIndex] = 0;
\r
245 newScheduleRequest[chIndex]=FALSE;
\r
246 LinSM_ScheduleRequest_Confirmation(chIndex);
\r
249 // Handle new transmissions
\r
250 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
251 Lin_PduType PduInfo;
\r
252 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
253 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
255 // Only UNCONDITIONAL frames is supported in first version
\r
256 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){
\r
258 if(ptrFrame->LinIfChecksumType==ENHANCED){
\r
259 PduInfo.Cs = LIN_ENHANCED_CS;
\r
261 PduInfo.Cs = LIN_CLASSIC_CS;
\r
263 PduInfo.Pid = ptrFrame->LinIfPid;
\r
264 PduInfo.SduPtr = buf; // Data will be added in PduR_LinIfTriggerTransmit
\r
265 PduInfo.DI = ptrFrame->LinIfLength;
\r
266 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
267 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
269 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
273 // Maybe send response also
\r
274 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
275 PduInfoType outgoingPdu;
\r
276 outgoingPdu.SduDataPtr = PduInfo.SduPtr;
\r
277 outgoingPdu.SduLength = PduInfo.DI;
\r
279 PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId, &outgoingPdu);
\r
280 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
281 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
285 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
290 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;
\r