]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Lin/LinIf.c
Updated LinIf to new PduR API.
[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 #include "PduR_LinIf.h"\r
31 #include "Det.h"\r
32 #if defined(USE_DEM)\r
33 #include "Dem.h"\r
34 #endif\r
35 \r
36 /* Development error macros. */\r
37 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )\r
38 #define VALIDATE(_exp,_api,_err ) \\r
39         if( !(_exp) ) { \\r
40           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
41           return; \\r
42         }\r
43 \r
44 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
45         if( !(_exp) ) { \\r
46           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
47           return (_rv); \\r
48         }\r
49 #else\r
50 #define VALIDATE(_exp,_api,_err )\r
51 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
52 #endif\r
53 \r
54 typedef enum {\r
55         LINIF_UNINIT,\r
56         LINIF_INIT,\r
57         LINIF_CHANNEL_UNINIT,\r
58         LINIF_CHANNEL_OPERATIONAL,\r
59         LINIF_CHANNEL_SLEEP_TRANS,\r
60         LINIF_CHANNEL_SLEEP,\r
61 }LinIf_StatusType;\r
62 \r
63 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;\r
64 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];\r
65 \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
69 \r
70 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];\r
71 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];\r
72 \r
73 void LinIf_Init( const void* ConfigPtr )\r
74 {\r
75         uint8 i;\r
76 \r
77         // Initalize driver\r
78         Lin_Init(0);\r
79 \r
80         // Call Lin_InitChannel\r
81         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
82         {\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
89         }\r
90         LinIfStatus = LINIF_INIT;\r
91 }\r
92 \r
93 void LinIf_DeInit()\r
94 {\r
95         uint8 i;\r
96 \r
97         // Call Lin_InitChannel\r
98         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
99         {\r
100                 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);\r
101         }\r
102         // Uninitalize driver\r
103         Lin_DeInit();\r
104 \r
105         LinIfStatus = LINIF_UNINIT;\r
106 }\r
107 \r
108 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)\r
109 {\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
112         return E_OK;\r
113 }\r
114 \r
115 \r
116 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)\r
117 {\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
121 \r
122         newScheduleRequest[Channel] = TRUE;\r
123         newSchedule[Channel] = Schedule;\r
124         return E_OK;\r
125 }\r
126 \r
127 \r
128 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)\r
129 {\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
132 \r
133         if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {\r
134                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;\r
135         }\r
136         return E_OK;\r
137 }\r
138 \r
139 \r
140 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)\r
141 {\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
144 \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
149         }\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
152         else{\r
153                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;\r
154                 LinSM_WakeUp_Confirmation(Channel, TRUE);\r
155         }\r
156         return E_OK;\r
157 }\r
158 \r
159 void LinIf_MainFunction()\r
160 {\r
161         uint8 chIndex;\r
162         uint8 buf[8];\r
163         uint8 *Lin_SduPtr;\r
164 \r
165         if (LinIfStatus == LINIF_UNINIT) {\r
166                 return;\r
167         }\r
168 \r
169         for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)\r
170         {\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
175                         }\r
176                         else\r
177                         {\r
178                                 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;\r
179                                 LinSM_GotoSleep_Confirmation(chIndex, TRUE);\r
180                         }\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
185                         continue;\r
186                 }\r
187 \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
193                 }\r
194 \r
195                 // Normal scheduling\r
196                 if(currentDelayInTicks[chIndex] > 0){\r
197                         // Not time for sending yet\r
198                         currentDelayInTicks[chIndex]--;\r
199                         continue;\r
200                 }\r
201 \r
202 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
207                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
208 \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
219 #endif\r
220                                         }\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
228 #endif\r
229                                         }\r
230                                 }\r
231                                 // Update index after getting status of last frame\r
232                                 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;\r
233 \r
234                         }\r
235 \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
242                     }\r
243 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
248                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
249 \r
250                                 // Only UNCONDITIONAL frames is supported in first version\r
251                                 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){\r
252                                         // SendHeader\r
253                                         if(ptrFrame->LinIfChecksumType==ENHANCED){\r
254                                                 PduInfo.Cs = LIN_ENHANCED_CS;\r
255                                         }else{\r
256                                                 PduInfo.Cs = LIN_CLASSIC_CS;\r
257                                         }\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
263                                         }else{\r
264                                                 PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
265                                         }\r
266 \r
267 \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
273                                                 //TX\r
274                                             PduR_LinIfTriggerTransmit(ptrFrame->LinIfTxTargetPduId, &outgoingPdu);\r
275                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
276                                                 Lin_SendResponse(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
277                                         }\r
278                                         else {\r
279                                                 //RX\r
280                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
281                                         }\r
282                                 }\r
283 \r
284                                 // Set new delay\r
285                                 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;\r
286                         }\r
287                 }\r
288         }\r
289         LinSM_TimerTick();\r
290 }\r
291 \r
292 \r
293 \r
294 \r
295 \r
296 \r
297 \r
298 \r