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