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