1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
6 * This source code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * -------------------------------- Arctic Core ------------------------------*/
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
33 /* Development error macros. */
\r
34 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )
\r
35 #define VALIDATE(_exp,_api,_err ) \
\r
37 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
41 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
43 Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \
\r
47 #define VALIDATE(_exp,_api,_err )
\r
48 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
54 LINIF_CHANNEL_UNINIT,
\r
55 LINIF_CHANNEL_OPERATIONAL,
\r
56 LINIF_CHANNEL_SLEEP_TRANS,
\r
57 LINIF_CHANNEL_SLEEP,
\r
60 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;
\r
61 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];
\r
63 static LinIf_ScheduleTableType *currentSchedule[LINIF_CONTROLLER_CNT];
\r
64 static uint16 currentIndex[LINIF_CONTROLLER_CNT];
\r
65 static uint16 currentDelayInTicks[LINIF_CONTROLLER_CNT];
\r
67 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];
\r
68 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];
\r
70 void LinIf_Init( const void* ConfigPtr )
\r
77 // Call Lin_InitChannel
\r
78 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
80 Lin_InitChannel(LinIfChannelCfg[i].LinIfChannelId, LinIfChannelCfg[i].LinIfChannelRef);
\r
81 LinIfChannelStatus[i] = LINIF_CHANNEL_OPERATIONAL;
\r
82 currentSchedule[i] = 0;
\r
83 currentIndex[i] = 0;
\r
84 currentDelayInTicks[i] = 0;
\r
85 newScheduleRequest[i] = FALSE;
\r
87 LinIfStatus = LINIF_INIT;
\r
94 // Call Lin_InitChannel
\r
95 for (i=0;i<LINIF_CONTROLLER_CNT;i++)
\r
97 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);
\r
99 // Uninitalize driver
\r
102 LinIfStatus = LINIF_UNINIT;
\r
105 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)
\r
107 // Sporadic frames not supported in this release
\r
108 //printf("LinIf_Transmit received request. Id: %d, Data: %d\n", LinTxPduId, *(PduInfoPtr->SduDataPtr));
\r
113 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)
\r
115 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
116 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
117 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
119 newScheduleRequest[Channel] = TRUE;
\r
120 newSchedule[Channel] = Schedule;
\r
125 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)
\r
127 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
128 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
130 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {
\r
131 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;
\r
137 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)
\r
139 VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);
\r
140 VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);
\r
142 if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_SLEEP) {
\r
143 Lin_WakeUp(LinIfChannelCfg[Channel].LinIfChannelId);
\r
144 currentIndex[Channel] = 0;
\r
145 currentDelayInTicks[Channel] = 0;
\r
147 // LINIF432: The function LinIf_WakeUp shall do nothing and return E_OK when the
\r
148 // referenced channel is not in the sleep state.
\r
150 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;
\r
151 LinSM_WakeUp_Confirmation(Channel, TRUE);
\r
156 void LinIf_MainFunction()
\r
162 if (LinIfStatus == LINIF_UNINIT) {
\r
166 for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)
\r
168 // Check if there are any pending sleep transitions
\r
169 if (LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP_TRANS) {
\r
170 if (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP){
\r
171 Lin_GoToSleep(LinIfChannelCfg[chIndex].LinIfChannelId);
\r
175 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;
\r
176 LinSM_GotoSleep_Confirmation(chIndex, TRUE);
\r
178 // Set NULL schedule at sleep
\r
179 currentIndex[chIndex] = 0;
\r
180 currentDelayInTicks[chIndex] = 0;
\r
181 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[0];
\r
185 // Check if there are any wakeup transitions
\r
186 if ((LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP) &&
\r
187 (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP)) {
\r
188 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_OPERATIONAL;
\r
189 LinSM_WakeUp_Confirmation(chIndex, TRUE);
\r
192 // Normal scheduling
\r
193 if(currentDelayInTicks[chIndex] > 0){
\r
194 // Not time for sending yet
\r
195 currentDelayInTicks[chIndex]--;
\r
200 if(LinIfChannelStatus[chIndex] == LINIF_CHANNEL_OPERATIONAL) {
\r
201 //Check if NULL schedule is present otherwise check status of last sent
\r
202 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
203 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
204 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
206 // Handle received and sent frames
\r
207 if(ptrFrame->LinIfPduDirection == LinIfRxPdu){
\r
208 if(Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) == LIN_RX_OK){
\r
209 PduR_LinIfRxIndication(ptrFrame->LinIfTxTargetPduId,Lin_SduPtr);
\r
210 }else{// RX_ERROR or BUSY
\r
211 Det_ReportError(MODULE_ID_LINIF,0,LINIF_MAINFUNCTION_SERVICE_ID,LINIF_E_RESPONSE);
\r
213 } else if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
214 Lin_StatusType status = Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr);
\r
215 if(status == LIN_TX_OK){
\r
216 PduR_LinIfTxConfirmation(ptrFrame->LinIfTxTargetPduId);
\r
217 }else{// TX_ERROR or BUSY
\r
218 Det_ReportError(MODULE_ID_LINIF,0,LINIF_MAINFUNCTION_SERVICE_ID,LINIF_E_RESPONSE);
\r
221 // Update index after getting status of last frame
\r
222 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;
\r
226 //Set new schedule if ordered
\r
227 if(newScheduleRequest[chIndex] == TRUE){
\r
228 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[newSchedule[chIndex]];
\r
229 currentIndex[chIndex] = 0;
\r
230 newScheduleRequest[chIndex]=FALSE;
\r
231 LinSM_ScheduleRequest_Confirmation(chIndex);
\r
234 // Handle new transmissions
\r
235 if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){
\r
236 Lin_PduType PduInfo;
\r
237 LinIfEntryType *ptrEntry = (LinIfEntryType *)¤tSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];
\r
238 LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];
\r
240 // Only UNCONDITIONAL frames is supported in first version
\r
241 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){
\r
243 if(ptrFrame->LinIfChecksumType==ENHANCED){
\r
244 PduInfo.Cs = LIN_ENHANCED_CS;
\r
246 PduInfo.Cs = LIN_CLASSIC_CS;
\r
248 PduInfo.Pid = ptrFrame->LinIfPid;
\r
249 PduInfo.SduPtr = buf; // Data will be added in PduR_LinIfTriggerTransmit
\r
250 PduInfo.DI = ptrFrame->LinIfLength;
\r
251 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
252 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
254 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
258 // Maybe send response also
\r
259 if(ptrFrame->LinIfPduDirection == LinIfTxPdu){
\r
261 PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId,PduInfo.SduPtr);
\r
262 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
263 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
267 Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId, &PduInfo);
\r
272 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;
\r