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