]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Lin/LinIf.c
First check in of lin for 5606s
[arc.git] / communication / Lin / LinIf.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 \r
18 \r
19 \r
20 \r
21 \r
22 \r
23 \r
24 #include "LinIf.h"\r
25 #include "LinIf_Types.h"\r
26 #include "LinIf_Cbk.h"\r
27 #include "LinIf_Cfg.h"\r
28 #include "Lin.h"\r
29 #include "LinSM_Cbk.h"\r
30 #if defined(USE_PDUR)\r
31 #include "PduR_LinIf.h"\r
32 #endif\r
33 #include "Det.h"\r
34 #if defined(USE_DEM)\r
35 #include "Dem.h"\r
36 #endif\r
37 \r
38 /* Development error macros. */\r
39 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )\r
40 #define VALIDATE(_exp,_api,_err ) \\r
41         if( !(_exp) ) { \\r
42           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
43           return; \\r
44         }\r
45 \r
46 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
47         if( !(_exp) ) { \\r
48           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
49           return (_rv); \\r
50         }\r
51 #else\r
52 #define VALIDATE(_exp,_api,_err )\r
53 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
54 #endif\r
55 \r
56 typedef enum {\r
57         LINIF_UNINIT,\r
58         LINIF_INIT,\r
59         LINIF_CHANNEL_UNINIT,\r
60         LINIF_CHANNEL_OPERATIONAL,\r
61         LINIF_CHANNEL_SLEEP_TRANS,\r
62         LINIF_CHANNEL_SLEEP,\r
63 }LinIf_StatusType;\r
64 \r
65 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;\r
66 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];\r
67 \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
71 \r
72 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];\r
73 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];\r
74 \r
75 void LinIf_Init( const void* ConfigPtr )\r
76 {\r
77         (void)ConfigPtr;\r
78         uint8 i;\r
79 \r
80         // Initalize driver\r
81         Lin_Init(0);\r
82 \r
83         // Call Lin_InitChannel\r
84         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
85         {\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
92         }\r
93         LinIfStatus = LINIF_INIT;\r
94 }\r
95 \r
96 void LinIf_DeInit()\r
97 {\r
98         uint8 i;\r
99 \r
100         // Call Lin_InitChannel\r
101         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
102         {\r
103                 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);\r
104         }\r
105         // Uninitalize driver\r
106         Lin_DeInit();\r
107 \r
108         LinIfStatus = LINIF_UNINIT;\r
109 }\r
110 \r
111 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)\r
112 {\r
113         (void)LinTxPduId;\r
114         (void)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
117         return E_OK;\r
118 }\r
119 \r
120 \r
121 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)\r
122 {\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
126 \r
127         newScheduleRequest[Channel] = TRUE;\r
128         newSchedule[Channel] = Schedule;\r
129         return E_OK;\r
130 }\r
131 \r
132 \r
133 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)\r
134 {\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
137 \r
138         if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {\r
139                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;\r
140         }\r
141         return E_OK;\r
142 }\r
143 \r
144 \r
145 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)\r
146 {\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
149 \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
154         }\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
157         else{\r
158                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;\r
159                 LinSM_WakeUp_Confirmation(Channel, TRUE);\r
160         }\r
161         return E_OK;\r
162 }\r
163 \r
164 void LinIf_MainFunction()\r
165 {\r
166         uint8 chIndex;\r
167         uint8 buf[8];\r
168         uint8 *Lin_SduPtr;\r
169 \r
170         if (LinIfStatus == LINIF_UNINIT) {\r
171                 return;\r
172         }\r
173 \r
174         for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)\r
175         {\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
180                         }\r
181                         else\r
182                         {\r
183                                 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;\r
184                                 LinSM_GotoSleep_Confirmation(chIndex, TRUE);\r
185                         }\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
190                         continue;\r
191                 }\r
192 \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
198                 }\r
199 \r
200                 // Normal scheduling\r
201                 if(currentDelayInTicks[chIndex] > 0){\r
202                         // Not time for sending yet\r
203                         currentDelayInTicks[chIndex]--;\r
204                         continue;\r
205                 }\r
206 \r
207 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
212                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
213 \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
224 #endif\r
225                                         }\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
233 #endif\r
234                                         }\r
235                                 }\r
236                                 // Update index after getting status of last frame\r
237                                 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;\r
238 \r
239                         }\r
240 \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
247                     }\r
248 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
253                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
254 \r
255                                 // Only UNCONDITIONAL frames is supported in first version\r
256                                 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){\r
257                                         // SendHeader\r
258                                         if(ptrFrame->LinIfChecksumType==ENHANCED){\r
259                                                 PduInfo.Cs = LIN_ENHANCED_CS;\r
260                                         }else{\r
261                                                 PduInfo.Cs = LIN_CLASSIC_CS;\r
262                                         }\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
268                                         }else{\r
269                                                 PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
270                                         }\r
271 \r
272 \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
278                                                 //TX\r
279                                             PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId, &outgoingPdu);\r
280                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
281                                                 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
282                                         }\r
283                                         else {\r
284                                                 //RX\r
285                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
286                                         }\r
287                                 }\r
288 \r
289                                 // Set new delay\r
290                                 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;\r
291                         }\r
292                 }\r
293         }\r
294         LinSM_TimerTick();\r
295 }\r
296 \r
297 \r
298 \r
299 \r
300 \r
301 \r
302 \r
303 \r