]> rtime.felk.cvut.cz Git - arc.git/blob - communication/Lin/LinIf.c
Initial commit.
[arc.git] / communication / Lin / LinIf.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
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>.
9  *
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
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
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 \r
33 /* Development error macros. */\r
34 #if ( LINIF_DEV_ERROR_DETECT == STD_ON )\r
35 #define VALIDATE(_exp,_api,_err ) \\r
36         if( !(_exp) ) { \\r
37           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
38           return; \\r
39         }\r
40 \r
41 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
42         if( !(_exp) ) { \\r
43           Det_ReportError(MODULE_ID_LINIF,0,_api,_err); \\r
44           return (_rv); \\r
45         }\r
46 #else\r
47 #define VALIDATE(_exp,_api,_err )\r
48 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
49 #endif\r
50 \r
51 typedef enum {\r
52         LINIF_UNINIT,\r
53         LINIF_INIT,\r
54         LINIF_CHANNEL_UNINIT,\r
55         LINIF_CHANNEL_OPERATIONAL,\r
56         LINIF_CHANNEL_SLEEP_TRANS,\r
57         LINIF_CHANNEL_SLEEP,\r
58 }LinIf_StatusType;\r
59 \r
60 static LinIf_StatusType LinIfStatus = LINIF_UNINIT;\r
61 static LinIf_StatusType LinIfChannelStatus[LINIF_CONTROLLER_CNT];\r
62 \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
66 \r
67 static boolean newScheduleRequest[LINIF_CONTROLLER_CNT];\r
68 static LinIf_SchHandleType newSchedule[LINIF_CONTROLLER_CNT];\r
69 \r
70 void LinIf_Init( const void* ConfigPtr )\r
71 {\r
72         uint8 i;\r
73 \r
74         // Initalize driver\r
75         Lin_Init(0);\r
76 \r
77         // Call Lin_InitChannel\r
78         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
79         {\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
86         }\r
87         LinIfStatus = LINIF_INIT;\r
88 }\r
89 \r
90 void LinIf_DeInit()\r
91 {\r
92         uint8 i;\r
93 \r
94         // Call Lin_InitChannel\r
95         for (i=0;i<LINIF_CONTROLLER_CNT;i++)\r
96         {\r
97                 Lin_DeInitChannel(LinIfChannelCfg[i].LinIfChannelId);\r
98         }\r
99         // Uninitalize driver\r
100         Lin_DeInit();\r
101 \r
102         LinIfStatus = LINIF_UNINIT;\r
103 }\r
104 \r
105 Std_ReturnType LinIf_Transmit(PduIdType LinTxPduId,const PduInfoType* PduInfoPtr)\r
106 {\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
109         return E_OK;\r
110 }\r
111 \r
112 \r
113 Std_ReturnType LinIf_ScheduleRequest(NetworkHandleType Channel,LinIf_SchHandleType Schedule)\r
114 {\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
118 \r
119         newScheduleRequest[Channel] = TRUE;\r
120         newSchedule[Channel] = Schedule;\r
121         return E_OK;\r
122 }\r
123 \r
124 \r
125 Std_ReturnType LinIf_GotoSleep(NetworkHandleType Channel)\r
126 {\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
129 \r
130         if (LinIfChannelStatus[Channel] == LINIF_CHANNEL_OPERATIONAL) {\r
131                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_SLEEP_TRANS;\r
132         }\r
133         return E_OK;\r
134 }\r
135 \r
136 \r
137 Std_ReturnType LinIf_WakeUp(NetworkHandleType Channel)\r
138 {\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
141 \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
146         }\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
149         else{\r
150                 LinIfChannelStatus[Channel] = LINIF_CHANNEL_OPERATIONAL;\r
151                 LinSM_WakeUp_Confirmation(Channel, TRUE);\r
152         }\r
153         return E_OK;\r
154 }\r
155 \r
156 void LinIf_MainFunction()\r
157 {\r
158         uint8 chIndex;\r
159         uint8 buf[8];\r
160         uint8 *Lin_SduPtr;\r
161 \r
162         if (LinIfStatus == LINIF_UNINIT) {\r
163                 return;\r
164         }\r
165 \r
166         for (chIndex = 0; chIndex < LINIF_CONTROLLER_CNT; chIndex++)\r
167         {\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
172                         }\r
173                         else\r
174                         {\r
175                                 LinIfChannelStatus[chIndex] = LINIF_CHANNEL_SLEEP;\r
176                                 LinSM_GotoSleep_Confirmation(chIndex, TRUE);\r
177                         }\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
182                         continue;\r
183                 }\r
184 \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
190                 }\r
191 \r
192                 // Normal scheduling\r
193                 if(currentDelayInTicks[chIndex] > 0){\r
194                         // Not time for sending yet\r
195                         currentDelayInTicks[chIndex]--;\r
196                         continue;\r
197                 }\r
198 \r
199 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
204                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
205 \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
212                                         }\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
219                                         }\r
220                                 }\r
221                                 // Update index after getting status of last frame\r
222                                 currentIndex[chIndex] = (currentIndex[chIndex] + 1) % currentSchedule[chIndex]->LinIfNofEntries;\r
223 \r
224                         }\r
225 \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
232                     }\r
233 \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 *)&currentSchedule[chIndex]->LinIfEntry[currentIndex[chIndex]];\r
238                             LinIf_FrameType *ptrFrame = (LinIf_FrameType *)&LinIfFrameCfg[ptrEntry->LinIfFrameRef];\r
239 \r
240                                 // Only UNCONDITIONAL frames is supported in first version\r
241                                 if (ptrFrame->LinIfFrameType == UNCONDITIONAL){\r
242                                         // SendHeader\r
243                                         if(ptrFrame->LinIfChecksumType==ENHANCED){\r
244                                                 PduInfo.Cs = LIN_ENHANCED_CS;\r
245                                         }else{\r
246                                                 PduInfo.Cs = LIN_CLASSIC_CS;\r
247                                         }\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
253                                         }else{\r
254                                                 PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
255                                         }\r
256 \r
257 \r
258                                         // Maybe send response also\r
259                                         if(ptrFrame->LinIfPduDirection == LinIfTxPdu){\r
260                                                 //TX\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
264                                         }\r
265                                         else {\r
266                                                 //RX\r
267                                             Lin_SendHeader(LinIfChannelCfg[chIndex].LinIfChannelId,  &PduInfo);\r
268                                         }\r
269                                 }\r
270 \r
271                                 // Set new delay\r
272                                 currentDelayInTicks[chIndex] = ptrEntry->LinIfDelay / LinIfGlobalConfig.LinIfTimeBase - 1;\r
273                         }\r
274                 }\r
275         }\r
276         LinSM_TimerTick();\r
277 }\r
278 \r
279 \r
280 \r
281 \r
282 \r
283 \r
284 \r
285 \r