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