]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/LinFlex.c
Lin corrections after successful lin mcal tests
[arc.git] / arch / ppc / mpc55xx / drivers / LinFlex.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 #include "Lin.h"\r
17 #include "LinIf_Cbk.h"\r
18 #include "mpc55xx.h"\r
19 #include "Det.h"\r
20 #include "Mcu.h"\r
21 #include <stdlib.h>\r
22 #include <string.h>\r
23 #include "LinIf_Cbk.h"\r
24 #include "Os.h"\r
25 #include "isr.h"\r
26 #include "irq.h"\r
27 #include "arc.h"\r
28 \r
29 #define LIN_MAX_MSG_LENGTH 8\r
30 \r
31 #define LINFLEX(exp) (volatile struct LINFLEX_tag *)(0xFFE40000 + (0x4000 * exp))\r
32 \r
33 /* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */\r
34 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;\r
35 \r
36 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];\r
37 \r
38 /* static buffers, holds one frame at a time */\r
39 static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];\r
40 \r
41 typedef volatile union {\r
42     vuint16_t R;\r
43     struct {\r
44         vuint16_t LINS:4;\r
45           vuint16_t:2;\r
46         vuint16_t RMB:1;\r
47           vuint16_t:1;\r
48         vuint16_t RBSY:1;      // LCH vuint16_t RXBUSY:1;\r
49         vuint16_t RPS:1;       // LCH vuint16_t RDI:1;\r
50         vuint16_t WUF:1;\r
51         vuint16_t DBFF:1;\r
52         vuint16_t DBEF:1;\r
53         vuint16_t DRF:1;\r
54         vuint16_t DTF:1;\r
55         vuint16_t HRF:1;\r
56     } B;\r
57 } LinSRtype;   /* LINFLEX LIN Status Register */\r
58 \r
59 typedef volatile union {\r
60     vuint16_t R;\r
61     struct {\r
62         vuint16_t SZF:1;\r
63         vuint16_t OCF:1;\r
64         vuint16_t BEF:1;\r
65         vuint16_t CEF:1;\r
66         vuint16_t SFEF:1;\r
67         vuint16_t SDEF:1;\r
68         vuint16_t IDPEF:1;\r
69         vuint16_t FEF:1;\r
70         vuint16_t BOF:1;\r
71           vuint16_t:6;\r
72         vuint16_t NF:1;\r
73     } B;\r
74 } LinESRType;                      /* LINFLEX LIN Error Status Register */\r
75 \r
76 \r
77 /* Development error macros. */\r
78 #if ( LIN_DEV_ERROR_DETECT == STD_ON )\r
79 #define VALIDATE(_exp,_api,_err ) \\r
80         if( !(_exp) ) { \\r
81           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
82           return; \\r
83         }\r
84 \r
85 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
86         if( !(_exp) ) { \\r
87           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
88           return (_rv); \\r
89         }\r
90 #else\r
91 #define VALIDATE(_exp,_api,_err )\r
92 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
93 #endif\r
94 \r
95 static void ResyncDriver(uint8 Channel)\r
96 {\r
97         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
98 \r
99          /* Disable tx irq */\r
100          /* Disable Rx Interrupt */\r
101          /* Disable Rx Interrupt */\r
102 \r
103         /* Disable transmitter and receiver. */\r
104 \r
105         /* Clear flags  */\r
106 \r
107         /* Prepare module for resynchronization. */\r
108          /* LIN Resynchronize. First set then cleared. */\r
109         /* Resynchronize module. */\r
110          /* LIN Resynchronize. First set then cleared. */\r
111 \r
112         /* Enable transmitter and receiver. */\r
113 \r
114         /* Clear set flags again */\r
115 }\r
116 \r
117 \r
118 void LinInterruptRx(uint8 Channel)\r
119 {\r
120         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
121 \r
122         if (1 == LINFLEXHw->LINSR.B.DRF) {\r
123                 /* Clear flags */\r
124                 LINFLEXHw->LINSR.B.DRF = 1;\r
125 \r
126                 if (LinChannelStatus[Channel]==LIN_RX_BUSY) {\r
127                         /* receive complete */\r
128                         LinChannelStatus[Channel] = LIN_RX_OK;\r
129                 }\r
130         }else{\r
131                 /* Other interrupt cause */\r
132                 LINFLEXHw->LINSR.R = 0xffffffff;\r
133                 if (LinChannelStatus[Channel]==LIN_RX_BUSY) {\r
134                         LinChannelStatus[Channel] = LIN_RX_ERROR;\r
135                 }\r
136         }\r
137 }\r
138 \r
139 void LinInterruptTx(uint8 Channel)\r
140 {\r
141         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
142 \r
143         if (1 == LINFLEXHw->LINSR.B.DTF) {\r
144                 /* Clear flags */\r
145                 LINFLEXHw->LINSR.B.DTF = 1;\r
146 \r
147                 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {\r
148                         /* transmit complete */\r
149                         LinChannelStatus[Channel] = LIN_TX_OK;\r
150                 }\r
151         }else{\r
152                 /* Other interrupt cause */\r
153                 LINFLEXHw->LINSR.R = 0xffffffff;\r
154                 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {\r
155                         LinChannelStatus[Channel] = LIN_TX_ERROR;\r
156                 }\r
157         }\r
158 }\r
159 \r
160 void LinInterruptErr(uint8 Channel)\r
161 {\r
162     volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
163 \r
164     /* Error handling */\r
165         static uint32 errCnt=0;\r
166         errCnt++;\r
167         if(LinChannelStatus[Channel]==LIN_RX_BUSY){\r
168                 LinChannelStatus[Channel] = LIN_RX_ERROR;\r
169         }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){\r
170                 LinChannelStatus[Channel] = LIN_TX_ERROR;\r
171         }\r
172 \r
173         /* Clear flags  */\r
174         LINFLEXHw->LINESR.R=0xffffffff;\r
175 }\r
176 \r
177 static void LinInterruptRxA(){LinInterruptRx(LIN_CTRL_A);}\r
178 static void LinInterruptTxA(){LinInterruptTx(LIN_CTRL_A);}\r
179 static void LinInterruptErrA(){LinInterruptErr(LIN_CTRL_A);}\r
180 \r
181 static void LinInterruptRxB(){LinInterruptRx(LIN_CTRL_B);}\r
182 static void LinInterruptTxB(){LinInterruptTx(LIN_CTRL_B);}\r
183 static void LinInterruptErrB(){LinInterruptErr(LIN_CTRL_B);}\r
184 \r
185 void Lin_Init( const Lin_ConfigType* Config )\r
186 {\r
187         (void)Config;\r
188         uint8 i;\r
189 \r
190         VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );\r
191         /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */\r
192 \r
193         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
194         {\r
195                 /* LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into\r
196                  * state LIN_CH_UNINIT. */\r
197                 LinChannelStatus[i] = LIN_CH_UNINIT;\r
198         }\r
199 \r
200         /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT\r
201          * to LIN_INIT when the function Lin_Init is called. */\r
202         LinDriverStatus = LIN_INIT;\r
203 }\r
204 \r
205 void Lin_DeInit()\r
206 {\r
207   LinDriverStatus = LIN_UNINIT;\r
208 }\r
209 \r
210 void Lin_WakeupValidation( void )\r
211 {\r
212 \r
213 }\r
214 \r
215 void Lin_InitChannel(  uint8 Channel,   const Lin_ChannelConfigType* Config )\r
216 {\r
217         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
218         enum\r
219         {\r
220           LIN_PRIO = 3\r
221         };\r
222 \r
223         VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );\r
224         VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );\r
225         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
226 \r
227         /* Install the interrupt */\r
228         switch(Channel){\r
229         case 0:\r
230                 ISR_INSTALL_ISR2("LinIsrRxA", LinInterruptRxA, (IrqType)(LINFLEX_0_RXI),LIN_PRIO, 0);\r
231                 ISR_INSTALL_ISR2("LinIsrTxA", LinInterruptTxA, (IrqType)(LINFLEX_0_TXI),LIN_PRIO, 0);\r
232                 ISR_INSTALL_ISR2("LinIsrErrA", LinInterruptErrA, (IrqType)(LINFLEX_0_ERR),LIN_PRIO, 0);\r
233                 break;\r
234         case 1:\r
235                 ISR_INSTALL_ISR2("LinIsrRxB", LinInterruptRxB, (IrqType)(LINFLEX_1_RXI),LIN_PRIO, 0);\r
236                 ISR_INSTALL_ISR2("LinIsrTxB", LinInterruptTxB, (IrqType)(LINFLEX_1_TXI),LIN_PRIO, 0);\r
237                 ISR_INSTALL_ISR2("LinIsrErrB", LinInterruptErrB, (IrqType)(LINFLEX_1_ERR),LIN_PRIO, 0);\r
238                 break;\r
239         default:\r
240                 break;\r
241         }\r
242 \r
243         /* configure and enable channel */\r
244         LINFLEXHw->LINCR1.B.INIT = 1; /* Go to init mode */\r
245         LINFLEXHw->LINCR1.R = 1; /* Clear all */\r
246         LINFLEXHw->LINCR1.B.MBL = 3; /* 13 bit synch */\r
247         LINFLEXHw->LINCR1.B.MME = 1; /* Master mode */\r
248         LINFLEXHw->LINCR1.B.CCD = 0;\r
249         LINFLEXHw->LINCR1.B.CFD = 0;\r
250         LINFLEXHw->LINCR1.B.LASE = 0;\r
251         LINFLEXHw->LINCR1.B.AWUM = 0;\r
252         LINFLEXHw->LINCR1.B.BF = 0;\r
253         LINFLEXHw->LINCR1.B.SLFM = 0;\r
254         LINFLEXHw->LINCR1.B.LBKM = 0;\r
255         LINFLEXHw->LINCR1.B.SBDT = 0;\r
256         LINFLEXHw->LINCR1.B.RBLM = 0;\r
257         LINFLEXHw->LINCR1.B.SLEEP = 0;\r
258 \r
259         LINFLEXHw->LINIER.R = 0; /* Reset all bits */\r
260         LINFLEXHw->LINIER.B.BEIE = 1; /* Bit error */\r
261         LINFLEXHw->LINIER.B.CEIE = 1; /* Checksum error */\r
262         LINFLEXHw->LINIER.B.HEIE = 1; /* Header error */\r
263         LINFLEXHw->LINIER.B.BOIE = 1; /* Buffer overrun error */\r
264         LINFLEXHw->LINIER.B.FEIE = 1; /* Framing error */\r
265 \r
266         LINFLEXHw->LINIER.B.DRIE = 1; /* Data Reception Complete */\r
267         LINFLEXHw->LINIER.B.DTIE = 1; /* Data Transmitted */\r
268 \r
269         /*\r
270          * Tx/ Rx baud = fperiph_set_1_clk / (16 × LFDIV)\r
271          *\r
272          * To program LFDIV = 25.62d,\r
273          * LINFBRR = 16 × 0.62 = 9.92, nearest real number 10d = 0xA\r
274          * LINIBRR = mantissa (25.620d) = 25d = 0x19\r
275          */\r
276         float lfdiv = (float)McuE_GetPeripheralClock( PERIPHERAL_CLOCK_LIN_A) / (float)((16*Config->LinChannelBaudRate));\r
277 \r
278         LINFLEXHw->LINFBRR.B.DIV_F = (uint8)((lfdiv - (uint32)lfdiv) * 16); /* Fraction bits */\r
279         LINFLEXHw->LINIBRR.B.DIV_M = (uint16)lfdiv; /* Integer bits */\r
280 \r
281         LINFLEXHw->LINCR2.R = 0; /* Reset all bits */\r
282         LINFLEXHw->LINCR2.B.IOBE = 1; /* Idle on bit error */\r
283         LINFLEXHw->LINCR2.B.IOPE = 1; /* Idle on parity error */\r
284 \r
285         /* Status regs */\r
286     LINFLEXHw->LINSR.R = 0xffffffff; /* Reset all bits */\r
287     LINFLEXHw->LINESR.R = 0xffffffff; /* Reset all bits */\r
288 \r
289         LINFLEXHw->LINCR1.B.INIT = 0; /* Go to normal mode */\r
290 \r
291         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
292 }\r
293 \r
294 void Lin_DeInitChannel( uint8 Channel )\r
295 {\r
296         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
297         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
298 \r
299         /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN\r
300          * channel state-machine is in state LIN_CH_OPERATIONAL. */\r
301         if(LinChannelStatus[Channel] != LIN_CH_UNINIT){\r
302                 /* Disable */\r
303         LINFLEXHw->LINCR1.R = 0; /* Reset all bits */\r
304             LINFLEXHw->LINIER.R = 0; /* Reset all bits */\r
305             LINFLEXHw->LINSR.R = 0xffffffff; /* Reset all bits */\r
306             LINFLEXHw->LINESR.R = 0xffffffff; /* Reset all bits */\r
307 \r
308                 LinChannelStatus[Channel]=LIN_CH_UNINIT;\r
309         }\r
310 }\r
311 \r
312 Std_ReturnType Lin_SendHeader(  uint8 Channel,  Lin_PduType* PduInfoPtr )\r
313 {\r
314         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
315         imask_t state;\r
316 \r
317         /* LIN021 */\r
318     Irq_Save(state);\r
319         if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||\r
320            LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR)\r
321         {\r
322                 ResyncDriver(Channel);\r
323                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
324         }\r
325     Irq_Restore(state);\r
326 \r
327 \r
328         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
329         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
330         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
331         /* Send header is used to wake the net in this implementation(no actual header is sent */\r
332         /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */\r
333         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
334 \r
335         /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */\r
336         uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10);\r
337 \r
338         LINFLEXHw->BIDR.R = 0; /* Clear reg */\r
339 \r
340         /* Checksum */\r
341         if (PduInfoPtr->Cs != LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */\r
342                 LINFLEXHw->BIDR.B.CCS = 1;\r
343         }\r
344         /* Length */\r
345         LINFLEXHw->BIDR.B.DFL = PduInfoPtr->DI - 1;\r
346 \r
347         /* Id */\r
348         LINFLEXHw->BIDR.B.ID = PduInfoPtr->Pid; /* Without parity bit */\r
349 \r
350         /* Direction */\r
351         if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)\r
352         {\r
353                 LINFLEXHw->BIDR.B.DIR = 1;\r
354 \r
355                 /* write to buffer reg */\r
356                 for(int i = 0; i < PduInfoPtr->DI;i++)\r
357                 {\r
358                         /* convenient with freescale reg file */\r
359                         switch(i)\r
360                         {\r
361                         case 0:\r
362                                 LINFLEXHw->BDRL.B.DATA0 = PduInfoPtr->SduPtr[0];\r
363                                 break;\r
364                         case 1:\r
365                                 LINFLEXHw->BDRL.B.DATA1 = PduInfoPtr->SduPtr[1];\r
366                                 break;\r
367                         case 2:\r
368                                 LINFLEXHw->BDRL.B.DATA2 = PduInfoPtr->SduPtr[2];\r
369                                 break;\r
370                         case 3:\r
371                                 LINFLEXHw->BDRL.B.DATA3 = PduInfoPtr->SduPtr[3];\r
372                                 break;\r
373                         case 4:\r
374                                 LINFLEXHw->BDRM.B.DATA4 = PduInfoPtr->SduPtr[4];\r
375                                 break;\r
376                         case 5:\r
377                                 LINFLEXHw->BDRM.B.DATA5 = PduInfoPtr->SduPtr[5];\r
378                                 break;\r
379                         case 6:\r
380                                 LINFLEXHw->BDRM.B.DATA6 = PduInfoPtr->SduPtr[6];\r
381                                 break;\r
382                         case 7:\r
383                                 LINFLEXHw->BDRM.B.DATA7 = PduInfoPtr->SduPtr[7];\r
384                                 break;\r
385                         }\r
386                 }\r
387 \r
388                 LinChannelStatus[Channel]=LIN_TX_BUSY;\r
389         }\r
390         else\r
391         {\r
392                 LinChannelStatus[Channel]=LIN_RX_BUSY;\r
393         }\r
394 \r
395         /* Request transmission of header */\r
396         LINFLEXHw->LINCR2.B.HTRQ = 1;\r
397 \r
398         return E_OK;\r
399 }\r
400 \r
401 Std_ReturnType Lin_SendResponse(  uint8 Channel,   Lin_PduType* PduInfoPtr )\r
402 {\r
403         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
404         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
405         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
406         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
407         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
408 \r
409         /* The response is sent from within the header in this implementation since this is a master only implementation */\r
410         return E_OK;\r
411 }\r
412 \r
413 Std_ReturnType Lin_GoToSleep(  uint8 Channel )\r
414 {\r
415         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
416 \r
417         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
418         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
419         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
420         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
421 \r
422         LINFLEXHw->LINCR1.B.SLEEP = 1;\r
423 \r
424         LINFLEXHw->LINIER.B.WUIE = 1; /* enable wake-up irq */\r
425 \r
426     LinChannelStatus[Channel]=LIN_CH_SLEEP;\r
427 \r
428     return E_OK;\r
429 }\r
430 \r
431 Std_ReturnType Lin_GoToSleepInternal(  uint8 Channel )\r
432 {\r
433         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
434         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
435         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
436         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
437         Lin_GoToSleep(Channel);\r
438         return E_OK;\r
439 }\r
440 \r
441 Std_ReturnType Lin_WakeUp( uint8 Channel )\r
442 {\r
443         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
444 \r
445         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
446         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
447         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
448         VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
449 \r
450         /* Disable wake interrupt */\r
451         LINFLEXHw->LINIER.B.WUIE = 0;\r
452         /* Clear sleep bit */\r
453         LINFLEXHw->LINCR1.B.SLEEP = 0;\r
454 \r
455         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
456         return E_OK;\r
457 }\r
458 \r
459 static void CopyToBuffer(uint8 *buf, volatile struct LINFLEX_tag * LINFLEXHw)\r
460 {\r
461         for(int i = 0; i < 8;i++)\r
462         {\r
463                 /* convenient with freescale reg file */\r
464                 switch(i)\r
465                 {\r
466                 case 0:\r
467                          buf[0] = LINFLEXHw->BDRL.B.DATA0;\r
468                         break;\r
469                 case 1:\r
470                          buf[1] = LINFLEXHw->BDRL.B.DATA1;\r
471                         break;\r
472                 case 2:\r
473                          buf[2] = LINFLEXHw->BDRL.B.DATA2;\r
474                         break;\r
475                 case 3:\r
476                          buf[3] = LINFLEXHw->BDRL.B.DATA3;\r
477                         break;\r
478                 case 4:\r
479                          buf[4] = LINFLEXHw->BDRM.B.DATA4;\r
480                         break;\r
481                 case 5:\r
482                          buf[5] = LINFLEXHw->BDRM.B.DATA5;\r
483                         break;\r
484                 case 6:\r
485                          buf[6] = LINFLEXHw->BDRM.B.DATA6;\r
486                         break;\r
487                 case 7:\r
488                          buf[7] = LINFLEXHw->BDRM.B.DATA7;\r
489                         break;\r
490                 }\r
491         }\r
492 }\r
493 \r
494 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )\r
495 {\r
496         volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);\r
497 \r
498         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, LIN_NOT_OK);\r
499         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, LIN_NOT_OK);\r
500         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, LIN_NOT_OK);\r
501         VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, LIN_NOT_OK);\r
502 \r
503         imask_t state;\r
504     Irq_Save(state);\r
505         Lin_StatusType res = LinChannelStatus[Channel];\r
506         /* We can only check for valid sdu ptr when LIN_RX_OK */\r
507         if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
508                 CopyToBuffer(LinBufRx[Channel], LINFLEXHw);\r
509                 *Lin_SduPtr = LinBufRx[Channel];\r
510                 if(LinChannelStatus[Channel] == LIN_RX_ERROR){\r
511                         ResyncDriver(Channel);\r
512                 }\r
513                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
514         } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){\r
515                 if(LinChannelStatus[Channel] == LIN_TX_ERROR){\r
516                         ResyncDriver(Channel);\r
517                 }\r
518                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
519         }\r
520     Irq_Restore(state);\r
521         return res;\r
522 }\r
523 \r
524 \r
525 \r
526 \r
527 \r