]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Lin/LinIf.c
Updated LIN driver
[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         uint8 i;\r
78 \r
79         // Initalize driver\r
80         Lin_Init(0);\r
81 \r
82         // Call Lin_InitChannel\r
83         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
84         {\r
85                 Lin_InitChannel(LinIfChannelCfg[i].LinIfChannelId, LinIfChannelCfg[i].LinIfChannelRef);\r
86                 LinIfChannelStatus[i] = LINIF_CHANNEL_OPERATIONAL;\r
87                 currentSchedule[i] = 0;\r
88                 currentIndex[i] = 0;\r
89                 currentDelayInTicks[i] = 0;\r
90                 newScheduleRequest[i] = FALSE;\r
91         }\r
92         LinIfStatus = LINIF_INIT;\r
93 }\r
94 \r
95 void LinIf_DeInit()\r
96 {\r
97         uint8 i;\r
98 \r
99         // Call Lin_InitChannel\r
100         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
101         {\r
102                 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);\r
103         }\r
104         // Uninitalize driver\r
105         Lin_DeInit();\r
106 \r
107         LinIfStatus = LINIF_UNINIT;\r
108 }\r
109 \r
110 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)\r
111 {\r
112         // Sporadic frames not supported in this release\r
113         //printf("LinIf_Transmit received request. Id: %d, Data: %d\n", LinTxPduId, *(PduInfoPtr->SduDataPtr));\r
114         return E_OK;\r
115 }\r
116 \r
117 \r
118 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)\r
119 {\r
120         VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);\r
121         VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_SCHEDULEREQUEST_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);\r
122         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
123 \r
124         newScheduleRequest[Channel] = TRUE;\r
125         newSchedule[Channel] = Schedule;\r
126         return E_OK;\r
127 }\r
128 \r
129 \r
130 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)\r
131 {\r
132         VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);\r
133         VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_GOTOSLEEP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);\r
134 \r
135         if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {\r
136                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;\r
137         }\r
138         return E_OK;\r
139 }\r
140 \r
141 \r
142 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)\r
143 {\r
144         VALIDATE_W_RV( (LinIfStatus != LINIF_UNINIT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_UNINIT, E_NOT_OK);\r
145         VALIDATE_W_RV( (Channel < LINIF_CONTROLLER_CNT), LINIF_WAKEUP_SERVICE_ID, LINIF_E_NONEXISTENT_CHANNEL, E_NOT_OK);\r
146 \r
147         if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_SLEEP) {\r
148                 Lin_WakeUp(LinIfChannelCfg[Channel].LinIfChannelId);\r
149                 currentIndex[Channel] = 0;\r
150                 currentDelayInTicks[Channel] = 0;\r
151         }\r
152   // LINIF432: The function LinIf_WakeUp shall do nothing and return E_OK when the\r
153   // referenced channel is not in the sleep state.\r
154         else{\r
155                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;\r
156                 LinSM_WakeUp_Confirmation(Channel, TRUE);\r
157         }\r
158         return E_OK;\r
159 }\r
160 \r
161 void LinIf_MainFunction()\r
162 {\r
163         uint8 chIndex;\r
164         uint8 buf[8];\r
165         uint8 *Lin_SduPtr;\r
166 \r
167         if (LinIfStatus == LINIF_UNINIT) {\r
168                 return;\r
169         }\r
170 \r
171         for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)\r
172         {\r
173                 // Check if there are any pending sleep transitions\r
174                 if (LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP_TRANS) {\r
175                         if (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP){\r
176                                 Lin_GoToSleep(LinIfChannelCfg[chIndex].LinIfChannelId);\r
177                         }\r
178                         else\r
179                         {\r
180                                 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;\r
181                                 LinSM_GotoSleep_Confirmation(chIndex, TRUE);\r
182                         }\r
183                         // Set NULL schedule at sleep\r
184                         currentIndex[chIndex] = 0;\r
185                         currentDelayInTicks[chIndex] = 0;\r
186                 currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[0];\r
187                         continue;\r
188                 }\r
189 \r
190                 // Check if there are any wakeup transitions\r
191                 if ((LinIfChannelStatus[chIndex] == LINIF_CHANNEL_SLEEP) &&\r
192         (Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) != LIN_CH_SLEEP)) {\r
193                         LinIfChannelStatus[chIndex] = LINIF_CHANNEL_OPERATIONAL;\r
194                         LinSM_WakeUp_Confirmation(chIndex, TRUE);\r
195                 }\r
196 \r
197                 // Normal scheduling\r
198                 if(currentDelayInTicks[chIndex] > 0){\r
199                         // Not time for sending yet\r
200                         currentDelayInTicks[chIndex]--;\r
201                         continue;\r
202                 }\r
203 \r
204 \r
205                 if(LinIfChannelStatus[chIndex] == LINIF_CHANNEL_OPERATIONAL) {\r
206                         //Check if NULL schedule is present otherwise check status of last sent\r
207                         if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){\r
208                                 LinIfEntryType *ptrEntry = (LinIfEntryType *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
209                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
210 \r
211                                 // Handle received and sent frames\r
212                                 if(ptrFrame->LinIfPduDirection == LinIfRxPdu){\r
213                                         if(Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr) == LIN_RX_OK){\r
214                                                 PduInfoType outgoingPdu;\r
215                                                 outgoingPdu.SduDataPtr = Lin_SduPtr;\r
216                                                 outgoingPdu.SduLength = ptrFrame->LinIfLength;\r
217                                                 PduR_LinIfRxIndication(ptrFrame->LinIfTxTargetPduId,&outgoingPdu);\r
218                                         }else{// RX_ERROR or BUSY\r
219 #if defined(USE_DEM)\r
220                                         Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);\r
221 #endif\r
222                                         }\r
223                                 } else if(ptrFrame->LinIfPduDirection == LinIfTxPdu){\r
224                                         Lin_StatusType status = Lin_GetStatus(LinIfChannelCfg[chIndex].LinIfChannelId, &Lin_SduPtr);\r
225                                         if(status == LIN_TX_OK){\r
226                                                 PduR_LinIfTxConfirmation(ptrFrame->LinIfTxTargetPduId);\r
227                                         }else{// TX_ERROR or BUSY\r
228 #if defined(USE_DEM)\r
229                                         Dem_ReportErrorStatus(LINIF_E_RESPONSE, DEM_EVENT_STATUS_FAILED);\r
230 #endif\r
231                                         }\r
232                                 }\r
233                                 // Update index after getting status of last frame\r
234                                 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;\r
235 \r
236                         }\r
237 \r
238                         //Set new schedule if ordered\r
239                     if(newScheduleRequest[chIndex] == TRUE){\r
240                         currentSchedule[chIndex] = (LinIf_ScheduleTableType *)&LinIfScheduleTableCfg[newSchedule[chIndex]];\r
241                         currentIndex[chIndex] = 0;\r
242                         newScheduleRequest[chIndex]=FALSE;\r
243                         LinSM_ScheduleRequest_Confirmation(chIndex);\r
244                     }\r
245 \r
246                     // Handle new transmissions\r
247                         if(!(currentSchedule[chIndex] == 0 || currentSchedule[chIndex]->LinIfEntry == 0)){\r
248                                 Lin_PduType PduInfo;\r
249                                 LinIfEntryType *ptrEntry = (LinIfEntryType *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
250                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
251 \r
252                                 // Only UNCONDITIONAL frames is supported in first version\r
253                                 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){\r
254                                         // SendHeader\r
255                                         if(ptrFrame->LinIfChecksumType==ENHANCED){\r
256                                                 PduInfo.Cs = LIN_ENHANCED_CS;\r
257                                         }else{\r
258                                                 PduInfo.Cs = LIN_CLASSIC_CS;\r
259                                         }\r
260                                         PduInfo.Pid = ptrFrame->LinIfPid;\r
261                                         PduInfo.SduPtr = buf; // Data will be added in PduR_LinIfTriggerTransmit\r
262                                         PduInfo.DI = ptrFrame->LinIfLength;\r
263                                         if(ptrFrame->LinIfPduDirection == LinIfTxPdu){\r
264                                                 PduInfo.Drc = LIN_MASTER_RESPONSE;\r
265                                         }else{\r
266                                                 PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
267                                         }\r
268 \r
269 \r
270                                         // Maybe send response also\r
271                                         if(ptrFrame->LinIfPduDirection == LinIfTxPdu){\r
272                                                 PduInfoType outgoingPdu;\r
273                                                 outgoingPdu.SduDataPtr = PduInfo.SduPtr;\r
274                                                 outgoingPdu.SduLength = PduInfo.DI;\r
275                                                 //TX\r
276                                             PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId, &outgoingPdu);\r
277                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
278                                                 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
279                                         }\r
280                                         else {\r
281                                                 //RX\r
282                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
283                                         }\r
284                                 }\r
285 \r
286                                 // Set new delay\r
287                                 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;\r
288                         }\r
289                 }\r
290         }\r
291         LinSM_TimerTick();\r
292 }\r
293 \r
294 \r
295 \r
296 \r
297 \r
298 \r
299 \r
300 \r