]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Lin.c
90530383c04a0851d0955013300d8d8588663daf
[arc.git] / arch / ppc / mpc55xx / drivers / Lin.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 /* ERRATA for REV_A of 551x chip. Will use a GPT timer for timeout handling */\r
30 \r
31 #ifdef MPC551X_ERRATA_REV_A\r
32 #include "Gpt.h"\r
33 \r
34 static Gpt_ChannelType LinChannelTimeOutGptChannelId[ LIN_CONTROLLER_CNT ];\r
35 static uint32          LinChannelBitTimeInTicks[ LIN_CONTROLLER_CNT ];\r
36 #endif\r
37 \r
38 #define LIN_MAX_MSG_LENGTH 8\r
39 \r
40 #ifdef CFG_MPC5567\r
41 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFB0000 + (0x4000 * exp))\r
42 #else\r
43 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))\r
44 #endif\r
45 \r
46 /* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */\r
47 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;\r
48 \r
49 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];\r
50 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];\r
51 \r
52 /* static buffers, holds one frame at a time */\r
53 static uint8 LinBufTx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];\r
54 static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];\r
55 \r
56 static uint8 *TxCurrPtr[LIN_CONTROLLER_CNT];\r
57 static uint8  TxSize[LIN_CONTROLLER_CNT];\r
58 static uint8 *RxCurrPtr[LIN_CONTROLLER_CNT];\r
59 static uint8  RxSize[LIN_CONTROLLER_CNT];\r
60 \r
61 /* Development error macros. */\r
62 #if ( LIN_DEV_ERROR_DETECT == STD_ON )\r
63 #define VALIDATE(_exp,_api,_err ) \\r
64         if( !(_exp) ) { \\r
65           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
66           return; \\r
67         }\r
68 \r
69 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
70         if( !(_exp) ) { \\r
71           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
72           return (_rv); \\r
73         }\r
74 #else\r
75 #define VALIDATE(_exp,_api,_err )\r
76 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
77 #endif\r
78 \r
79 typedef volatile union\r
80 {\r
81   uint32_t R;\r
82   struct {\r
83           uint32_t PID:8;\r
84           uint32_t :24;\r
85   } B1;\r
86   struct {\r
87           uint32_t L:8;\r
88           uint32_t :24;\r
89   } B2;\r
90   struct {\r
91           uint32_t HDCHK:1;\r
92           uint32_t CSUM:1;\r
93           uint32_t CRC:1;\r
94           uint32_t TX:1;\r
95           uint32_t TN:4;\r
96           uint32_t :24;\r
97   } B3;\r
98   struct {\r
99           uint32_t T:8;\r
100           uint32_t :24;\r
101   } B4;\r
102   struct {\r
103           uint32_t D:8;\r
104           uint32_t :24;\r
105   } B5;\r
106 }LinLTRType;\r
107 \r
108 typedef volatile union {\r
109     vuint32_t R;\r
110     struct {\r
111         vuint32_t TDRE:1;\r
112         vuint32_t TC:1;\r
113         vuint32_t RDRF:1;\r
114         vuint32_t IDLE:1;\r
115         vuint32_t OR:1;\r
116         vuint32_t NF:1;\r
117         vuint32_t FE:1;\r
118         vuint32_t PF:1;\r
119           vuint32_t:3;\r
120         vuint32_t BERR:1;\r
121           vuint32_t:3;\r
122         vuint32_t RAF:1;\r
123         vuint32_t RXRDY:1;\r
124         vuint32_t TXRDY:1;\r
125         vuint32_t LWAKE:1;\r
126         vuint32_t STO:1;\r
127         vuint32_t PBERR:1;\r
128         vuint32_t CERR:1;\r
129         vuint32_t CKERR:1;\r
130         vuint32_t FRC:1;\r
131           vuint32_t:7;\r
132         vuint32_t OVFL:1;\r
133     } B;\r
134 } LinSRtype;   /* Status Register */\r
135 \r
136 static void ResyncDriver(uint8 Channel)\r
137 {\r
138         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
139 \r
140         esciHw->LCR.B.TXIE = 0; /* Disable tx irq */\r
141         esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */\r
142         esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */\r
143 \r
144         /* Disable transmitter and receiver. */\r
145         esciHw->CR1.B.TE = 0;\r
146         esciHw->CR1.B.RE = 0;\r
147 \r
148         /* Clear flags  */\r
149         esciHw->SR.R = esciHw->SR.R;\r
150 \r
151         /* Prepare module for resynchronization. */\r
152         esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */\r
153         /* Resynchronize module. */\r
154         esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */\r
155 \r
156         /* Enable transmitter and receiver. */\r
157         esciHw->CR1.B.TE = 1;\r
158         esciHw->CR1.B.RE = 1;\r
159 \r
160 #if 0 /* This needs if we Disable Fast Bit Error Detection otherwise SR will not be cleared properly....strange */\r
161         volatile uint32 i;\r
162         for(i=0; i < 10000; ){\r
163           i++;\r
164         }\r
165 #endif\r
166 \r
167         /* Clear set flags again */\r
168         esciHw->SR.R = esciHw->SR.R;\r
169 }\r
170 \r
171 \r
172 void LinInterrupt(uint8 Channel)\r
173 {\r
174         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
175         LinSRtype sr, tmp;\r
176         LinLTRType tmpLtr;\r
177 #ifdef MPC551X_ERRATA_REV_A\r
178         uint8 stopTimeOutTimer = FALSE;\r
179 #endif \r
180 \r
181         sr.R = esciHw->SR.R;\r
182 \r
183         /* Clear flags */\r
184         tmp.R = 0;\r
185         if(sr.B.TXRDY == 1){tmp.B.TXRDY = 1;}\r
186         if(sr.B.RXRDY == 1){tmp.B.RXRDY = 1;}\r
187         if(sr.B.TC == 1){tmp.B.TC = 1;}\r
188         if(sr.B.RDRF == 1){tmp.B.RDRF = 1;}\r
189         if(sr.B.IDLE == 1){tmp.B.IDLE = 1;}\r
190         if(sr.B.OVFL == 1){tmp.B.OVFL = 1;}\r
191         if(sr.B.FRC == 1){tmp.B.FRC = 1;}\r
192 \r
193         esciHw->SR.R = tmp.R;\r
194         esciHw->LCR.B.TXIE = 0; /* Always disable Tx Interrupt */\r
195 \r
196         /* TX */\r
197         if (LinChannelStatus[Channel]==LIN_TX_BUSY) {\r
198                 /* Maybe transmit next byte */\r
199                 if (TxSize[Channel] > 0 && sr.B.TXRDY) {\r
200                         tmpLtr.R = 0; /* Clear */\r
201                         tmpLtr.B4.T = *TxCurrPtr[Channel];\r
202                         TxCurrPtr[Channel]++; TxSize[Channel]--;\r
203                         esciHw->LCR.B.TXIE = 1; /* Enable tx irq */\r
204                         esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
205                 }\r
206                 else {\r
207                         if(sr.B.FRC == 1){\r
208                                 /* Transmission complete */\r
209                                 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){\r
210                                         LinChannelStatus[Channel] = LIN_CH_SLEEP;\r
211                                         LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;\r
212                                 }else {\r
213                                         LinChannelStatus[Channel] = LIN_TX_OK;\r
214                                 }\r
215                                 esciHw->LCR.B.TXIE = 0; /* Disable tx irq */\r
216                         }\r
217                         else{\r
218                                 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){\r
219                                         LinChannelStatus[Channel] = LIN_CH_SLEEP;\r
220                                         LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;\r
221                                 }else {\r
222                                         LinChannelStatus[Channel] = LIN_TX_ERROR;\r
223                                 }\r
224                         }\r
225 #ifdef MPC551X_ERRATA_REV_A\r
226                         /* Transmission is over. */\r
227                         stopTimeOutTimer = TRUE;\r
228 #endif \r
229                 }\r
230         }       /* RX */\r
231         else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {\r
232           /* Maybe receive next byte */\r
233                 if (RxSize[Channel] > 0 && sr.B.RXRDY) {\r
234                         tmpLtr.R = esciHw->LRR.R;\r
235                         *RxCurrPtr[Channel] = tmpLtr.B5.D;\r
236                         RxCurrPtr[Channel]++; RxSize[Channel]--;\r
237                 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){\r
238                         /* receive complete */\r
239                         LinChannelStatus[Channel] = LIN_RX_OK;\r
240                         esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */\r
241                         esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */\r
242 #ifdef MPC551X_ERRATA_REV_A\r
243                         /* Transmission is over. */\r
244                         stopTimeOutTimer = TRUE;\r
245 #endif \r
246                 }\r
247         }\r
248 \r
249         /* Error handling\r
250          * OR    - Overrun\r
251          * NF    \96 Noise fault\r
252          * FE    \96 Framing Error\r
253          * PF    \96 Parity fault\r
254          * BERR  \96 Bit error (read back)\r
255          * STO   \96 Slave Timeout\r
256          * PBERR \96 Physical bit error\r
257          * CERR  \96 CRC error\r
258          * CKERR \96 Checksum error\r
259          * OVFL  \96 Overflow flag\r
260          */\r
261         if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||\r
262            sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {\r
263                 static uint32 errCnt=0;\r
264                 errCnt++;\r
265                 if(LinChannelStatus[Channel]==LIN_RX_BUSY){\r
266                         LinChannelStatus[Channel] = LIN_RX_ERROR;\r
267                 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){\r
268                         LinChannelStatus[Channel] = LIN_TX_ERROR;\r
269                 }\r
270 \r
271                 /* Clear flags  */\r
272                 esciHw->SR.R=0xffffffff;\r
273 \r
274                 /* Resynchronize driver in GetStatus call */\r
275 \r
276 #ifndef MPC551X_ERRATA_REV_A\r
277         }\r
278 #else\r
279                 /* Transmission is over. */\r
280                 stopTimeOutTimer = TRUE;\r
281         }\r
282 \r
283         /* Handle LIN Wake Up reset manually. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632]. */\r
284         if( sr.B.LWAKE )\r
285         {\r
286                 /* Resynchronize driver. */\r
287                 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared */\r
288                 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared */\r
289 \r
290                 /* Transmission is over. */\r
291                 stopTimeOutTimer = TRUE;\r
292         }\r
293 \r
294         if( TRUE == stopTimeOutTimer )\r
295         {\r
296                 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );\r
297         }\r
298 #endif\r
299 }\r
300 \r
301 static void LinInterruptA()\r
302 {\r
303         LinInterrupt(LIN_CTRL_A);\r
304 }\r
305 static void LinInterruptB()\r
306 {\r
307         LinInterrupt(LIN_CTRL_B);\r
308 }\r
309 #ifndef CFG_MPC5567\r
310 static void LinInterruptC()\r
311 {\r
312         LinInterrupt(LIN_CTRL_C);\r
313 }\r
314 static void LinInterruptD()\r
315 {\r
316         LinInterrupt(LIN_CTRL_D);\r
317 }\r
318 static void LinInterruptE()\r
319 {\r
320         LinInterrupt(LIN_CTRL_E);\r
321 }\r
322 static void LinInterruptF()\r
323 {\r
324         LinInterrupt(LIN_CTRL_F);\r
325 }\r
326 static void LinInterruptG()\r
327 {\r
328         LinInterrupt(LIN_CTRL_G);\r
329 }\r
330 static void LinInterruptH()\r
331 {\r
332         LinInterrupt(LIN_CTRL_H);\r
333 }\r
334 #endif\r
335 \r
336 #ifdef MPC551X_ERRATA_REV_A\r
337 void LinTimeOutInterrupt( uint8 channel )\r
338 {\r
339         /* We ended up here because of that the eSCI module for the given channel has stopped internally.\r
340         * Now we have to reset the LIN module state machine ourself.\r
341         * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */\r
342 \r
343         volatile struct ESCI_tag *esciHw = ESCI( channel );\r
344 \r
345         /* Make sure that the timer it stopped (e.g. if by mistake setup as continuously). */\r
346         Gpt_StopTimer( LinChannelTimeOutGptChannelId[ channel ] );\r
347 \r
348         /* Disable transmitter and receiver. */\r
349         esciHw->CR1.B.TE = 0;\r
350         esciHw->CR1.B.RE = 0;\r
351 \r
352         /* Prepare module for resynchronization. */\r
353         esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */\r
354 \r
355         /* Enable transmitter and receiver. */\r
356         esciHw->CR1.B.TE = 1;\r
357         esciHw->CR1.B.RE = 1;\r
358 \r
359         /* Resynchronize module. */\r
360         esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */\r
361 }\r
362 \r
363 void LinTimeOutInterruptA()\r
364 {\r
365   LinTimeOutInterrupt( LIN_CTRL_A );\r
366 }\r
367 void LinTimeOutInterruptB()\r
368 {\r
369   LinTimeOutInterrupt( LIN_CTRL_B );\r
370 }\r
371 void LinTimeOutInterruptC()\r
372 {\r
373   LinTimeOutInterrupt( LIN_CTRL_C );\r
374 }\r
375 void LinTimeOutInterruptD()\r
376 {\r
377   LinTimeOutInterrupt( LIN_CTRL_D );\r
378 }\r
379 void LinTimeOutInterruptE()\r
380 {\r
381   LinTimeOutInterrupt( LIN_CTRL_E );\r
382 }\r
383 void LinTimeOutInterruptF()\r
384 {\r
385   LinTimeOutInterrupt( LIN_CTRL_F );\r
386 }\r
387 void LinTimeOutInterruptG()\r
388 {\r
389   LinTimeOutInterrupt( LIN_CTRL_G );\r
390 }\r
391 void LinTimeOutInterruptH()\r
392 {\r
393   LinTimeOutInterrupt( LIN_CTRL_H );\r
394 }\r
395 #endif\r
396 \r
397 void Lin_Init( const Lin_ConfigType* Config )\r
398 {\r
399         uint8 i;\r
400 \r
401         VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );\r
402         /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */\r
403 \r
404         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
405         {\r
406                 /* LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into\r
407                  * state LIN_CH_UNINIT. */\r
408                 LinChannelStatus[i] = LIN_CH_UNINIT;\r
409                 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;\r
410                 TxCurrPtr[i] = 0;\r
411                 TxSize[i] = 0;\r
412                 RxCurrPtr[i] = 0;\r
413                 RxSize[i] = 0;\r
414 #ifdef MPC551X_ERRATA_REV_A\r
415                 LinChannelTimeOutGptChannelId[ i ] = 0;\r
416                 LinChannelBitTimeInTicks[ i ] = 0;\r
417 #endif\r
418         }\r
419 \r
420         /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT\r
421          * to LIN_INIT when the function Lin_Init is called. */\r
422         LinDriverStatus = LIN_INIT;\r
423 }\r
424 void Lin_DeInit()\r
425 {\r
426   LinDriverStatus = LIN_UNINIT;\r
427 }\r
428 \r
429 void Lin_WakeupValidation( void )\r
430 {\r
431 \r
432 }\r
433 \r
434 void Lin_InitChannel(  uint8 Channel,   const Lin_ChannelConfigType* Config )\r
435 {\r
436         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
437         enum\r
438         {\r
439           LIN_PRIO = 3\r
440         };\r
441 \r
442         VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );\r
443         VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );\r
444         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
445 \r
446         /* Install the interrupt */\r
447         switch(Channel){\r
448         case 0:\r
449 #ifdef CFG_MPC5567\r
450                 ISR_INSTALL_ISR2("LinIsr", LinInterruptA, (IrqType)(ESCI_A_COMB0),LIN_PRIO, 0);\r
451 #else\r
452                 ISR_INSTALL_ISR2("LinIsr", LinInterruptA, (IrqType)(SCI_A_COMB),LIN_PRIO, 0);\r
453 #endif\r
454                 break;\r
455         case 1:\r
456 #ifdef CFG_MPC5567\r
457                 ISR_INSTALL_ISR2("LinIsr", LinInterruptB, (IrqType)(ESCI_A_COMB1),LIN_PRIO, 0);\r
458 #else\r
459                 ISR_INSTALL_ISR2("LinIsr", LinInterruptB, (IrqType)(SCI_B_COMB),LIN_PRIO, 0);\r
460 #endif\r
461                 break;\r
462         case 2:\r
463 #ifndef CFG_MPC5567\r
464                 ISR_INSTALL_ISR2("LinIsr", LinInterruptC, (IrqType)(SCI_C_COMB),LIN_PRIO, 0);\r
465 #endif\r
466                 break;\r
467         case 3:\r
468 #ifndef CFG_MPC5567\r
469                 ISR_INSTALL_ISR2("LinIsr", LinInterruptD, (IrqType)(SCI_D_COMB),LIN_PRIO, 0);\r
470 #endif\r
471                 break;\r
472         case 4:\r
473 #ifndef CFG_MPC5567\r
474                 ISR_INSTALL_ISR2("LinIsr", LinInterruptE, (IrqType)(SCI_E_COMB),LIN_PRIO, 0);\r
475 #endif\r
476                 break;\r
477         case 5:\r
478 #ifndef CFG_MPC5567\r
479                 ISR_INSTALL_ISR2("LinIsr", LinInterruptF, (IrqType)(SCI_F_COMB),LIN_PRIO, 0);\r
480 #endif\r
481                 break;\r
482         case 6:\r
483 #ifndef CFG_MPC5567\r
484                 ISR_INSTALL_ISR2("LinIsr", LinInterruptG, (IrqType)(SCI_G_COMB+2),LIN_PRIO, 0);\r
485 #endif\r
486                 break;\r
487         case 7:\r
488 #ifndef CFG_MPC5567\r
489                 ISR_INSTALL_ISR2("LinIsr", LinInterruptH, (IrqType)(SCI_H_COMB+3),LIN_PRIO, 0);\r
490 #endif\r
491                 break;\r
492         default:\r
493                 break;\r
494         }\r
495 \r
496         esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */\r
497 \r
498         esciHw->CR1.B.RE = 1;\r
499         esciHw->CR1.B.M = 0; /* The data format bit ESCIx_CR1[M], is set to 0 (8 data bits), and the parity is disabled (PE = 0).*/\r
500         esciHw->CR1.B.PE = 0;\r
501         esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/\r
502         esciHw->CR1.B.TCIE = 0;\r
503         esciHw->CR1.B.RIE = 0;\r
504           /* Set up ESCIx_CR1 for LIN */\r
505           /*\r
506            * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.\r
507            * The formula for calculating the baud rate is:\r
508            *\r
509            *                      eSCI system clock\r
510            * SCI baud rate =   -----------------------\r
511            *                          16 × SBR\r
512            *\r
513            * where SBR can contain a value from 1 to 8191. After reset, the baud generator\r
514            * is disabled until the TE bit or the RE bit is set for the first time. The baud\r
515            * rate generator is disabled when SBR = 0x0.\r
516            */\r
517         esciHw->CR1.B.SBR  = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);\r
518         esciHw->LCR.B.LIN = 1;  /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/\r
519 \r
520         esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long\r
521         (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */\r
522 \r
523 #ifdef MPC551X_ERRATA_REV_A\r
524         esciHw->LCR.B.LDBG = 1; /* Enable LIN debug => Disable automatic reset of the LIN FSM. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632] */\r
525         esciHw->CR2.B.FBR = 1;  /* Disable Fast Bit Error Detection. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8635] */\r
526 #else\r
527         esciHw->LCR.B.LDBG = 0; /* Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop\r
528                                  * further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/\r
529         esciHw->CR2.B.FBR = 1;    /* Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set; */\r
530 #endif\r
531         esciHw->LCR.B.STIE = 1; /* Enable some fault irq's */\r
532         esciHw->LCR.B.PBIE = 1;\r
533         esciHw->LCR.B.CKIE = 1;\r
534         esciHw->LCR.B.OFIE = 1;\r
535 \r
536         esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/\r
537         esciHw->CR2.B.BSTP = 1;\r
538 \r
539         esciHw->CR2.B.BESM13 = 1; /* normally it will be used with ESCIx_CR2[BESM13] = 1.*/\r
540 \r
541         /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */\r
542         /* Should we have these interrupts or check the status register? */\r
543         /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves\r
544         activate.*/\r
545 \r
546         esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */\r
547 \r
548         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
549 #ifdef MPC551X_ERRATA_REV_A\r
550         LinChannelTimeOutGptChannelId[ Channel ] = Config->LinTimeOutGptChannelId;\r
551         LinChannelBitTimeInTicks[ Channel ] = McuE_GetPeripheralClock( Config->LinClockRef / Config->LinChannelBaudRate ) / Config->LinChannelBaudRate;\r
552 #endif\r
553 }\r
554 \r
555 void Lin_DeInitChannel( uint8 Channel )\r
556 {\r
557         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
558         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
559 \r
560 #ifdef MPC551X_ERRATA_REV_A\r
561         /* Make sure that the timer is stopped. */\r
562         Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );\r
563 #endif\r
564 \r
565         /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN\r
566          * channel state-machine is in state LIN_CH_OPERATIONAL. */\r
567         if(LinChannelStatus[Channel] != LIN_CH_UNINIT){\r
568                 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */\r
569 \r
570                 LinChannelStatus[Channel]=LIN_CH_UNINIT;\r
571         }\r
572 }\r
573 \r
574 Std_ReturnType Lin_SendHeader(  uint8 Channel,  Lin_PduType* PduInfoPtr )\r
575 {\r
576     LinSRtype tmp;\r
577     LinLTRType tmpLtr;\r
578         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
579         imask_t state;\r
580 \r
581         /* LIN021 */\r
582     Irq_Save(state);\r
583         if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||\r
584            LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR)\r
585         {\r
586                 ResyncDriver(Channel);\r
587                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
588         }\r
589     Irq_Restore(state);\r
590 \r
591 \r
592         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
593         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
594         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
595         /* Send header is used to wake the net in this implementation(no actual header is sent */\r
596         /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */\r
597         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
598 \r
599         /* Byte 1 */\r
600         tmpLtr.R = 0; /* Clear */\r
601         tmpLtr.B1.PID = PduInfoPtr->Pid;\r
602         tmp.R = 0; /* Clear ready flag before send */\r
603         tmp.B.TXRDY = 1;\r
604         esciHw->SR.R = tmp.R;\r
605         esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
606 \r
607         /* Byte 2 */\r
608         tmpLtr.R = 0; /* Clear */\r
609         tmpLtr.B2.L = PduInfoPtr->DI;\r
610         tmp.R = 0; /* Clear ready flag before send */\r
611         tmp.B.TXRDY = 1;\r
612         esciHw->SR.R = tmp.R;\r
613         esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
614 \r
615         /* Byte 3 */\r
616         tmpLtr.R = 0; /* Clear */\r
617         if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */\r
618                 tmpLtr.B3.HDCHK = 1;\r
619         }\r
620         tmpLtr.B3.CSUM = 1; /* Append checksum to TX frame or verify for a RX */\r
621         tmpLtr.B3.CRC = 0; /* Append two CRC bytes(Not LIN standard) */\r
622 \r
623         /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */\r
624         uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10);\r
625 \r
626         if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)\r
627         {\r
628                 LinChannelStatus[Channel]=LIN_TX_BUSY;\r
629                 tmpLtr.B3.TX = 1; /* TX frame */\r
630                 tmpLtr.B3.TN = 0; /* Timeout not valid for TX */\r
631                 tmp.R = 0; /* Clear ready flag before send */\r
632                 tmp.B.TXRDY = 1;\r
633                 esciHw->SR.R = tmp.R;\r
634                 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */\r
635                 esciHw->LCR.B.TXIE = 1; /* Enable tx irq */\r
636                 if (PduInfoPtr->DI > 0){\r
637                         TxCurrPtr[Channel] = LinBufTx[Channel];\r
638                         TxSize[Channel] = PduInfoPtr->DI;\r
639                         memcpy(TxCurrPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);\r
640                 }\r
641                 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
642         }\r
643 \r
644 \r
645         else\r
646         {\r
647                 LinChannelStatus[Channel]=LIN_RX_BUSY;\r
648                 RxCurrPtr[Channel] = LinBufRx[Channel];\r
649                 RxSize[Channel] = PduInfoPtr->DI;\r
650 \r
651                 tmpLtr.B3.TX = 0; /* RX frame */\r
652                 tmpLtr.B3.TN = timeOutValue >> 8;     /* Most significant bits to be set here. */\r
653                 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
654                 /* Byte 4 for RX */\r
655                 tmpLtr.R = 0; /* Clear */\r
656         tmpLtr.B4.T = timeOutValue & 0xFF;   /* Least significant bits to be set here. */\r
657                 tmp.R = 0; /* Clear ready flag before send */\r
658                 tmp.B.TXRDY = 1;\r
659                 esciHw->SR.R = tmp.R;\r
660                 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */\r
661                 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */\r
662                 esciHw->LCR.B.RXIE = 1; /* Enable rx irq */\r
663         }\r
664 \r
665 #ifdef MPC551X_ERRATA_REV_A\r
666         /* Set up the GPT to twice as long time. Normally this time out shall not be needed but there are two\r
667         * Erratas telling us that the LIN message timeout (written above to byte 3 and 4) is sometimes not used\r
668         * by the LIN module and the LIN module state machine will then wait in infinity.\r
669         * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */\r
670         Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );\r
671         Gpt_StartTimer( LinChannelTimeOutGptChannelId[ Channel ], LinChannelBitTimeInTicks[ Channel ] * timeOutValue * 2 );\r
672 #endif\r
673 \r
674         return E_OK;\r
675 }\r
676 \r
677 Std_ReturnType Lin_SendResponse(  uint8 Channel,   Lin_PduType* PduInfoPtr )\r
678 {\r
679         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
680         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
681         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
682         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
683         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
684 \r
685         /* The response is sent from within the header in this implementation since this is a master only implementation */\r
686         return E_OK;\r
687 }\r
688 \r
689 Std_ReturnType Lin_GoToSleep(  uint8 Channel )\r
690 {\r
691         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
692         Lin_PduType PduInfo;\r
693         uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};\r
694 \r
695         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
696         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
697         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
698         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
699 \r
700         if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){\r
701                 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;\r
702 \r
703                 PduInfo.Cs = LIN_CLASSIC_CS;\r
704                 PduInfo.Pid = 0x3C;\r
705                 PduInfo.SduPtr = data;\r
706                 PduInfo.DI = 8;\r
707                 PduInfo.Drc = LIN_MASTER_RESPONSE;\r
708 \r
709                 Lin_SendHeader(Channel,  &PduInfo);\r
710                 Lin_SendResponse(Channel,  &PduInfo);\r
711 \r
712                 esciHw->LCR.B.WUIE = 1; /* enable wake-up irq */\r
713         }\r
714         return E_OK;\r
715 }\r
716 \r
717 Std_ReturnType Lin_GoToSleepInternal(  uint8 Channel )\r
718 {\r
719         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
720         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
721         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
722         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
723         Lin_GoToSleep(Channel);\r
724         return E_OK;\r
725 }\r
726 \r
727 Std_ReturnType Lin_WakeUp( uint8 Channel )\r
728 {\r
729         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
730         Lin_PduType PduInfo;\r
731         uint8 data[2] = {0xFF,0xFF};\r
732 \r
733         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
734         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
735         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
736         VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
737 \r
738         esciHw->LCR.B.WUIE = 0; /* disable wake-up irq */\r
739         esciHw->LCR.B.WU = 1; /* send wake up */\r
740         esciHw->LCR.B.WUD0 = 1; /* delimiter time */\r
741         esciHw->LCR.B.WUD1 = 0; /* delimiter time */\r
742 \r
743         /* Just send any header to trigger the wakeup signal */\r
744         PduInfo.Cs = LIN_CLASSIC_CS;\r
745         PduInfo.Pid = 0x00;\r
746         PduInfo.SduPtr = data;\r
747         PduInfo.DI = 2;\r
748         PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
749         Lin_SendHeader(Channel,  &PduInfo);\r
750 \r
751         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
752         return E_OK;\r
753 }\r
754 \r
755 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )\r
756 {\r
757         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
758         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
759         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
760         VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
761 \r
762         imask_t state;\r
763     Irq_Save(state);\r
764         Lin_StatusType res = LinChannelStatus[Channel];\r
765         /* We can only check for valid sdu ptr when LIN_RX_OK */\r
766         if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
767                 *Lin_SduPtr = LinBufRx[Channel];\r
768                 if(LinChannelStatus[Channel] == LIN_RX_ERROR){\r
769                         ResyncDriver(Channel);\r
770                 }\r
771                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
772         } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){\r
773                 if(LinChannelStatus[Channel] == LIN_TX_ERROR){\r
774                         ResyncDriver(Channel);\r
775                 }\r
776                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
777         }\r
778     Irq_Restore(state);\r
779         return res;\r
780 }\r
781 \r
782 \r
783 \r
784 \r
785 \r