]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Lin.c
Initial commit.
[arc.git] / arch / ppc / mpc55xx / drivers / Lin.c
1 /* -------------------------------- Arctic Core ------------------------------
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com
3  *
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>
5  *
6  * This source code is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License version 2 as published by the
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13  * for more details.
14  * -------------------------------- Arctic Core ------------------------------*/
15
16
17
18
19
20
21
22
23 #include "Lin.h"\r
24 #include "LinIf_Cbk.h"\r
25 #include "mpc55xx.h"\r
26 #include "Det.h"\r
27 #include "Mcu.h"\r
28 #include <stdlib.h>\r
29 #include <string.h>\r
30 #include "LinIf_Cbk.h"\r
31 \r
32 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))\r
33 \r
34 // LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT.\r
35 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;\r
36 \r
37 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];\r
38 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];\r
39 \r
40 static uint8* TxPtr[LIN_CONTROLLER_CNT];\r
41 static uint8* TxCurrPtr[LIN_CONTROLLER_CNT];\r
42 static uint8 TxSize[LIN_CONTROLLER_CNT];\r
43 static uint8* RxPtr[LIN_CONTROLLER_CNT];\r
44 static uint8* RxCurrPtr[LIN_CONTROLLER_CNT];\r
45 static uint8 RxSize[LIN_CONTROLLER_CNT];\r
46 \r
47 /* Development error macros. */\r
48 #if ( LIN_DEV_ERROR_DETECT == STD_ON )\r
49 #define VALIDATE(_exp,_api,_err ) \\r
50         if( !(_exp) ) { \\r
51           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
52           return; \\r
53         }\r
54 \r
55 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \\r
56         if( !(_exp) ) { \\r
57           Det_ReportError(MODULE_ID_LIN,0,_api,_err); \\r
58           return (_rv); \\r
59         }\r
60 #else\r
61 #define VALIDATE(_exp,_api,_err )\r
62 #define VALIDATE_W_RV(_exp,_api,_err,_rv )\r
63 #endif\r
64 \r
65 typedef volatile union\r
66 {\r
67   uint32_t R;\r
68   struct {\r
69           uint32_t PID:8;\r
70           uint32_t :24;\r
71   } B1;\r
72   struct {\r
73           uint32_t L:8;\r
74           uint32_t :24;\r
75   } B2;\r
76   struct {\r
77           uint32_t HDCHK:1;\r
78           uint32_t CSUM:1;\r
79           uint32_t CRC:1;\r
80           uint32_t TX:1;\r
81           uint32_t TN:1;\r
82           uint32_t :24;\r
83   } B3;\r
84   struct {\r
85           uint32_t T:8;\r
86           uint32_t :24;\r
87   } B4;\r
88   struct {\r
89           uint32_t D:8;\r
90           uint32_t :24;\r
91   } B5;\r
92 }LinLTRType;\r
93 \r
94 typedef volatile union {\r
95     vuint32_t R;\r
96     struct {\r
97         vuint32_t TDRE:1;\r
98         vuint32_t TC:1;\r
99         vuint32_t RDRF:1;\r
100         vuint32_t IDLE:1;\r
101         vuint32_t OR:1;\r
102         vuint32_t NF:1;\r
103         vuint32_t FE:1;\r
104         vuint32_t PF:1;\r
105           vuint32_t:3;\r
106         vuint32_t BERR:1;\r
107           vuint32_t:3;\r
108         vuint32_t RAF:1;\r
109         vuint32_t RXRDY:1;\r
110         vuint32_t TXRDY:1;\r
111         vuint32_t LWAKE:1;\r
112         vuint32_t STO:1;\r
113         vuint32_t PBERR:1;\r
114         vuint32_t CERR:1;\r
115         vuint32_t CKERR:1;\r
116         vuint32_t FRC:1;\r
117           vuint32_t:7;\r
118         vuint32_t OVFL:1;\r
119     } B;\r
120 } LinSRtype;   /* Status Register */\r
121 \r
122 \r
123 void LinInterrupt(uint8 Channel)\r
124 {\r
125         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
126         LinSRtype sr, tmp;\r
127         LinLTRType tmpLtr;\r
128 \r
129         sr.R = esciHw->SR.R;\r
130 \r
131         // Clear flags\r
132         tmp.R = 0;\r
133         if(sr.B.TXRDY == 1)\r
134         {\r
135           tmp.B.TXRDY = 1;\r
136         }\r
137         if(sr.B.RXRDY == 1)\r
138         {\r
139           tmp.B.RXRDY = 1;\r
140         }\r
141         if(sr.B.TC == 1)\r
142         {\r
143           tmp.B.TC = 1;\r
144         }\r
145         if(sr.B.RDRF == 1)\r
146         {\r
147           tmp.B.RDRF = 1;\r
148         }\r
149         if(sr.B.IDLE == 1)\r
150         {\r
151           tmp.B.IDLE = 1;\r
152         }\r
153         if(sr.B.OVFL == 1)\r
154         {\r
155           tmp.B.OVFL = 1;\r
156         }\r
157         if(sr.B.FRC == 1)\r
158         {\r
159           tmp.B.FRC = 1;\r
160         }\r
161         esciHw->SR.R = tmp.R;\r
162         esciHw->LCR.B.TXIE = 0; // Always disable Tx Interrupt\r
163 \r
164         // TX\r
165         if (LinChannelStatus[Channel]==LIN_TX_BUSY) {\r
166                 // Maybe transmit next byte\r
167                 if (TxSize[Channel] > 0 && sr.B.TXRDY) {\r
168                         tmpLtr.R = 0; // Clear\r
169                         tmpLtr.B4.T = *TxCurrPtr[Channel];\r
170                         TxCurrPtr[Channel]++; TxSize[Channel]--;\r
171                         esciHw->LCR.B.TXIE = 1; // Enable tx irq\r
172                         esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
173                 }\r
174                 else {\r
175                         if(sr.B.FRC == 1){\r
176                                 //Transmission complete\r
177                                 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){\r
178                                         LinChannelStatus[Channel] = LIN_CH_SLEEP;\r
179                                         LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;\r
180                                 }else {\r
181                                         LinChannelStatus[Channel] = LIN_TX_OK;\r
182                                 }\r
183                                 esciHw->LCR.B.TXIE = 0; // Disable tx irq\r
184                         }\r
185                         else{\r
186                                 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){\r
187                                         LinChannelStatus[Channel] = LIN_CH_SLEEP;\r
188                                         LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;\r
189                                 }else {\r
190                                         LinChannelStatus[Channel] = LIN_TX_ERROR;\r
191                                 }\r
192                         }\r
193                 }\r
194         }       //RX\r
195         else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {\r
196           // Maybe receive next byte\r
197                 if (RxSize[Channel] > 0 && sr.B.RXRDY) {\r
198                         tmpLtr.R = esciHw->LRR.R;\r
199                         *RxCurrPtr[Channel] = tmpLtr.B5.D;\r
200                         RxCurrPtr[Channel]++; RxSize[Channel]--;\r
201                 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){\r
202                         //receive complete\r
203                         LinChannelStatus[Channel] = LIN_RX_OK;\r
204                         esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt\r
205                         esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt\r
206                 }\r
207         }\r
208 \r
209         // Error handling\r
210         if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||\r
211            sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {\r
212                 static uint32 errCnt=0;\r
213                 errCnt++;\r
214                 if(LinChannelStatus[Channel]==LIN_RX_BUSY){\r
215                         LinChannelStatus[Channel] = LIN_RX_ERROR;\r
216                 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){\r
217                         LinChannelStatus[Channel] = LIN_TX_ERROR;\r
218                 }\r
219 \r
220                 // Resynchronize driver and clear all errors\r
221                 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared\r
222                 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared\r
223                 // Clear flags\r
224                 esciHw->SR.R=0xffffffff;\r
225         }\r
226 }\r
227 \r
228 static void LinInterruptA()\r
229 {\r
230         LinInterrupt(LIN_CTRL_A);\r
231 }\r
232 static void LinInterruptB()\r
233 {\r
234         LinInterrupt(LIN_CTRL_B);\r
235 }\r
236 static void LinInterruptC()\r
237 {\r
238         LinInterrupt(LIN_CTRL_C);\r
239 }\r
240 static void LinInterruptD()\r
241 {\r
242         LinInterrupt(LIN_CTRL_D);\r
243 }\r
244 static void LinInterruptE()\r
245 {\r
246         LinInterrupt(LIN_CTRL_E);\r
247 }\r
248 static void LinInterruptF()\r
249 {\r
250         LinInterrupt(LIN_CTRL_F);\r
251 }\r
252 static void LinInterruptG()\r
253 {\r
254         LinInterrupt(LIN_CTRL_G);\r
255 }\r
256 static void LinInterruptH()\r
257 {\r
258         LinInterrupt(LIN_CTRL_H);\r
259 }\r
260 \r
261 static const void const * aIntFnc[] =  {LinInterruptA,\r
262                                                                                 LinInterruptB,\r
263                                                                                 LinInterruptC,\r
264                                                                                 LinInterruptD,\r
265                                                                                 LinInterruptE,\r
266                                                                                 LinInterruptF,\r
267                                                                                 LinInterruptG,\r
268                                                                                 LinInterruptH,};\r
269 \r
270 void Lin_Init( const Lin_ConfigType* Config )\r
271 {\r
272         uint8 i;\r
273 \r
274         VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );\r
275         //VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER );\r
276 \r
277         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
278         {\r
279                 // LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into\r
280                 // state LIN_CH_UNINIT.\r
281                 LinChannelStatus[i] = LIN_CH_UNINIT;\r
282                 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;\r
283                 TxPtr[i] = 0;\r
284                 TxCurrPtr[i] = 0;\r
285                 TxSize[i] = 0;\r
286                 RxPtr[i] = 0;\r
287                 RxCurrPtr[i] = 0;\r
288                 RxSize[i] = 0;\r
289         }\r
290 \r
291         //LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT\r
292         // to LIN_INIT when the function Lin_Init is called.\r
293         LinDriverStatus = LIN_INIT;\r
294 }\r
295 void Lin_DeInit()\r
296 {\r
297         uint8 i;\r
298 \r
299         // Make sure all allocated buffers are freed\r
300         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
301         {\r
302                 if (RxPtr[i] != 0)      {\r
303                         free(RxPtr[i]);\r
304                 }\r
305                 if (TxPtr[i] != 0)      {\r
306                         free(TxPtr[i]);\r
307                 }\r
308         }\r
309         LinDriverStatus = LIN_UNINIT;\r
310 }\r
311 \r
312 void Lin_WakeupValidation( void )\r
313 {\r
314 \r
315 }\r
316 \r
317 void Lin_InitChannel(  uint8 Channel,   const Lin_ChannelConfigType* Config )\r
318 {\r
319         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
320         enum\r
321         {\r
322           LIN_PRIO = 3\r
323         };\r
324 \r
325         VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );\r
326         VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );\r
327         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
328 \r
329         // Install the interrupt\r
330         if (Channel > 3)\r
331         {\r
332           IntCtrl_InstallVector(aIntFnc[Channel],SCI_E_COMB + Channel,LIN_PRIO,CPU_Z1);\r
333         }\r
334         else\r
335         {\r
336           IntCtrl_InstallVector(aIntFnc[Channel],SCI_A_COMB + Channel,LIN_PRIO,CPU_Z1);\r
337         }\r
338 \r
339         esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */\r
340 \r
341         esciHw->CR1.B.RE = 1;\r
342         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
343         esciHw->CR1.B.PE = 0;\r
344         esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/\r
345         esciHw->CR1.B.TCIE = 0;\r
346         esciHw->CR1.B.RIE = 0;\r
347           /* Set up ESCIx_CR1 for LIN */\r
348           /*\r
349            * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.\r
350            * The formula for calculating the baud rate is:\r
351            *\r
352            *                      eSCI system clock\r
353            * SCI baud rate =   -----------------------\r
354            *                          16 × SBR\r
355            *\r
356            * where SBR can contain a value from 1 to 8191. After reset, the baud generator\r
357            * is disabled until the TE bit or the RE bit is set for the first time. The baud\r
358            * rate generator is disabled when SBR = 0x0.\r
359            */\r
360         esciHw->CR1.B.SBR  = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);\r
361         esciHw->LCR.B.LIN = 1;  /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/\r
362 \r
363         esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long\r
364         (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */\r
365 \r
366         esciHw->LCR.B.LDBG = 0;/*Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop\r
367         further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/\r
368         esciHw->LCR.B.STIE = 1; // Enable some fault irq's\r
369         esciHw->LCR.B.PBIE = 1;\r
370         esciHw->LCR.B.CKIE = 1;\r
371         esciHw->LCR.B.OFIE = 1;\r
372 \r
373         esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/\r
374         esciHw->CR2.B.BSTP = 1;\r
375 \r
376         esciHw->CR2.B.FBR = 1;    // Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set;\r
377         esciHw->CR2.B.BESM13 = 1; // normally it will be used with ESCIx_CR2[BESM13] = 1.*/\r
378 \r
379         /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */\r
380         /* TODO Should we have these interrupts or check the status register? */\r
381         /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves\r
382         activate.*/\r
383 \r
384         esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */\r
385 \r
386         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
387 }\r
388 \r
389 void Lin_DeInitChannel( uint8 Channel )\r
390 {\r
391         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
392         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
393 \r
394         //LIN178: The function Lin_DeInitChannel shall only be executable when the LIN\r
395         //channel state-machine is in state LIN_CH_OPERATIONAL.\r
396         if(LinChannelStatus[Channel] != LIN_CH_UNINIT){\r
397                 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */\r
398 \r
399                 if (RxPtr[Channel] != 0)        {\r
400                         free(RxPtr[Channel]);\r
401                 }\r
402                 if (TxPtr[Channel] != 0)        {\r
403                         free(TxPtr[Channel]);\r
404                 }\r
405 \r
406                 LinChannelStatus[Channel]=LIN_CH_UNINIT;\r
407         }\r
408 }\r
409 \r
410 Std_ReturnType Lin_SendHeader(  uint8 Channel,  Lin_PduType* PduInfoPtr )\r
411 {\r
412   LinSRtype tmp;\r
413   LinLTRType tmpLtr;\r
414         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
415 \r
416         // LIN021\r
417         imask_t state = McuE_EnterCriticalSection();\r
418         if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||\r
419            LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
420                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
421                 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared\r
422                 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared\r
423                 esciHw->LCR.B.TXIE = 0; // Disable tx irq\r
424                 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt\r
425                 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt\r
426                 // Clear flags\r
427                 esciHw->SR.R=0xffffffff;\r
428         }\r
429         McuE_ExitCriticalSection(state);\r
430 \r
431 \r
432         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
433         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
434         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
435         //Send header is used to wake the net in this implementation(no actual header is sent\r
436         // VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
437         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
438 \r
439         // Byte 1\r
440         tmpLtr.R = 0; // Clear\r
441         tmpLtr.B1.PID = PduInfoPtr->Pid;\r
442         tmp.R = 0; // Clear ready flag before send\r
443         tmp.B.TXRDY = 1;\r
444         esciHw->SR.R = tmp.R;\r
445         esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
446 \r
447         // Byte 2\r
448         tmpLtr.R = 0; // Clear\r
449         tmpLtr.B2.L = PduInfoPtr->DI;\r
450         tmp.R = 0; // Clear ready flag before send\r
451         tmp.B.TXRDY = 1;\r
452         esciHw->SR.R = tmp.R;\r
453         esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
454 \r
455         // Byte 3\r
456         tmpLtr.R = 0; // Clear\r
457         if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ //Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum\r
458                 tmpLtr.B3.HDCHK = 1;\r
459         }\r
460         tmpLtr.B3.CSUM = 1; // Append checksum to TX frame or verify for a RX\r
461         tmpLtr.B3.CRC = 0; // Append two CRC bytes(Not LIN standard)\r
462         if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)\r
463         {\r
464                 LinChannelStatus[Channel]=LIN_TX_BUSY;\r
465                 tmpLtr.B3.TX = 1; // TX frame\r
466                 tmpLtr.B3.TN = 0; // Timeout not valid for TX\r
467                 tmp.R = 0; // Clear ready flag before send\r
468                 tmp.B.TXRDY = 1;\r
469                 esciHw->SR.R = tmp.R;\r
470                 esciHw->LCR.B.FCIE = 1; // // Enable frame complete\r
471                 esciHw->LCR.B.TXIE = 1; // Enable tx irq\r
472                 if (PduInfoPtr->DI > 0){\r
473                         if (TxPtr[Channel] != 0)  {\r
474                                 free(TxPtr[Channel]);\r
475                         }\r
476                         TxCurrPtr[Channel] = TxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);\r
477                         TxSize[Channel] = PduInfoPtr->DI;\r
478                         memcpy(TxPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);\r
479                 }\r
480                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
481         }\r
482 \r
483 \r
484         else\r
485         {\r
486                 LinChannelStatus[Channel]=LIN_RX_BUSY;\r
487                 if (RxPtr[Channel] != 0)        {\r
488                         free(RxPtr[Channel]);\r
489                 }\r
490                 RxCurrPtr[Channel] = RxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);\r
491                 RxSize[Channel] = PduInfoPtr->DI;\r
492 \r
493                 tmpLtr.B3.TX = 0; // RX frame\r
494                 tmpLtr.B3.TN = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3\r
495                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
496                 // Byte 4 for RX\r
497                 tmpLtr.R = 0; // Clear\r
498                 tmpLtr.B4.T = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3\r
499                 tmp.R = 0; // Clear ready flag before send\r
500                 tmp.B.TXRDY = 1;\r
501                 esciHw->SR.R = tmp.R;\r
502                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
503                 esciHw->LCR.B.FCIE = 1; // Enable frame complete\r
504                 esciHw->LCR.B.RXIE = 1; // Enable rx irq\r
505         }\r
506 \r
507         return E_OK;\r
508 }\r
509 \r
510 Std_ReturnType Lin_SendResponse(  uint8 Channel,   Lin_PduType* PduInfoPtr )\r
511 {\r
512         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
513         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
514         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
515         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
516         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
517 \r
518         // The response is sent from within the header in this implementation since this is a master only implementation\r
519         return E_OK;\r
520 }\r
521 \r
522 Std_ReturnType Lin_GoToSleep(  uint8 Channel )\r
523 {\r
524         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
525         Lin_PduType PduInfo;\r
526         uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};\r
527 \r
528         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
529         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
530         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
531         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
532 \r
533         if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){\r
534                 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;\r
535 \r
536                 PduInfo.Cs = LIN_CLASSIC_CS;\r
537                 PduInfo.Pid = 0x3C;\r
538                 PduInfo.SduPtr = data;\r
539                 PduInfo.DI = 8;\r
540                 PduInfo.Drc = LIN_MASTER_RESPONSE;\r
541 \r
542                 Lin_SendHeader(Channel,  &PduInfo);\r
543                 Lin_SendResponse(Channel,  &PduInfo);\r
544 \r
545                 esciHw->LCR.B.WUIE = 1; // enable wake-up irq\r
546         }\r
547         return E_OK;\r
548 }\r
549 \r
550 Std_ReturnType Lin_GoToSleepInternal(  uint8 Channel )\r
551 {\r
552         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
553         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
554         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
555         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
556         Lin_GoToSleep(Channel);\r
557         return E_OK;\r
558 }\r
559 \r
560 Std_ReturnType Lin_WakeUp( uint8 Channel )\r
561 {\r
562         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
563         Lin_PduType PduInfo;\r
564         uint8 data[2] = {0xFF,0xFF};\r
565 \r
566         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
567         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
568         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
569         VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
570 \r
571         esciHw->LCR.B.WUIE = 0; // disable wake-up irq\r
572         esciHw->LCR.B.WU = 1; // send wake up\r
573         esciHw->LCR.B.WUD0 = 1; // delimiter time\r
574         esciHw->LCR.B.WUD1 = 0; // delimiter time\r
575 \r
576         // Just send any header to trigger the wakeup signal\r
577         PduInfo.Cs = LIN_CLASSIC_CS;\r
578         PduInfo.Pid = 0x00;\r
579         PduInfo.SduPtr = data;\r
580         PduInfo.DI = 2;\r
581         PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
582         Lin_SendHeader(Channel,  &PduInfo);\r
583 \r
584         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
585         return E_OK;\r
586 }\r
587 \r
588 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )\r
589 {\r
590         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
591         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
592         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
593         VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
594 \r
595         imask_t state = McuE_EnterCriticalSection();\r
596         Lin_StatusType res = LinChannelStatus[Channel];\r
597         // We can only check for valid sdu ptr when LIN_RX_OK\r
598         if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
599                 *Lin_SduPtr = RxPtr[Channel];\r
600                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
601         } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){\r
602                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
603         }\r
604         McuE_ExitCriticalSection(state);\r
605         return res;\r
606 }\r
607 \r
608 \r
609 \r
610 \r
611 \r