]> rtime.felk.cvut.cz Git - arc.git/blob - arch/ppc/mpc55xx/drivers/Lin.c
4963f1d48a09cd819f3e596c826bee5abb3e7e45
[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 \r
266 void Lin_Init( const Lin_ConfigType* Config )\r
267 {\r
268         uint8 i;\r
269 \r
270         VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );\r
271         //VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER );\r
272 \r
273         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
274         {\r
275                 // LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into\r
276                 // state LIN_CH_UNINIT.\r
277                 LinChannelStatus[i] = LIN_CH_UNINIT;\r
278                 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;\r
279                 TxPtr[i] = 0;\r
280                 TxCurrPtr[i] = 0;\r
281                 TxSize[i] = 0;\r
282                 RxPtr[i] = 0;\r
283                 RxCurrPtr[i] = 0;\r
284                 RxSize[i] = 0;\r
285         }\r
286 \r
287         //LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT\r
288         // to LIN_INIT when the function Lin_Init is called.\r
289         LinDriverStatus = LIN_INIT;\r
290 }\r
291 void Lin_DeInit()\r
292 {\r
293         uint8 i;\r
294 \r
295         // Make sure all allocated buffers are freed\r
296         for (i=0;i<LIN_CONTROLLER_CNT;i++)\r
297         {\r
298                 if (RxPtr[i] != 0)      {\r
299                         free(RxPtr[i]);\r
300                 }\r
301                 if (TxPtr[i] != 0)      {\r
302                         free(TxPtr[i]);\r
303                 }\r
304         }\r
305         LinDriverStatus = LIN_UNINIT;\r
306 }\r
307 \r
308 void Lin_WakeupValidation( void )\r
309 {\r
310 \r
311 }\r
312 \r
313 void Lin_InitChannel(  uint8 Channel,   const Lin_ChannelConfigType* Config )\r
314 {\r
315         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
316         enum\r
317         {\r
318           LIN_PRIO = 3\r
319         };\r
320 \r
321         VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );\r
322         VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );\r
323         VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );\r
324 \r
325 \r
326         // Install the interrupt\r
327         switch (Channel) {\r
328                 case 0: ISR_INSTALL_ISR2( "LinA", LinInterruptA, SCI_A_COMB, LIN_PRIO, 0 ); break;\r
329                 case 1: ISR_INSTALL_ISR2( "LinB", LinInterruptB, SCI_B_COMB, LIN_PRIO, 0 ); break;\r
330                 case 2: ISR_INSTALL_ISR2( "LinC", LinInterruptC, SCI_C_COMB, LIN_PRIO, 0 ); break;\r
331                 case 3: ISR_INSTALL_ISR2( "LinD", LinInterruptD, SCI_D_COMB, LIN_PRIO, 0 ); break;\r
332                 case 4: ISR_INSTALL_ISR2( "LinE", LinInterruptE, SCI_E_COMB, LIN_PRIO, 0 ); break;\r
333                 case 5: ISR_INSTALL_ISR2( "LinF", LinInterruptF, SCI_F_COMB, LIN_PRIO, 0 ); break;\r
334                 case 6: ISR_INSTALL_ISR2( "LinG", LinInterruptG, SCI_G_COMB, LIN_PRIO, 0 ); break;\r
335                 case 7: ISR_INSTALL_ISR2( "LinH", LinInterruptH, SCI_H_COMB, LIN_PRIO, 0 ); break;\r
336                 default: assert(0); break;\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         imask_t state;\r
416 \r
417         // LIN021\r
418     Irq_Save(state);\r
419         if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||\r
420            LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
421                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
422                 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared\r
423                 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared\r
424                 esciHw->LCR.B.TXIE = 0; // Disable tx irq\r
425                 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt\r
426                 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt\r
427                 // Clear flags\r
428                 esciHw->SR.R=0xffffffff;\r
429         }\r
430     Irq_Restore(state);\r
431 \r
432 \r
433         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
434         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
435         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
436         //Send header is used to wake the net in this implementation(no actual header is sent\r
437         // VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
438         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
439 \r
440         // Byte 1\r
441         tmpLtr.R = 0; // Clear\r
442         tmpLtr.B1.PID = PduInfoPtr->Pid;\r
443         tmp.R = 0; // Clear ready flag before send\r
444         tmp.B.TXRDY = 1;\r
445         esciHw->SR.R = tmp.R;\r
446         esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
447 \r
448         // Byte 2\r
449         tmpLtr.R = 0; // Clear\r
450         tmpLtr.B2.L = PduInfoPtr->DI;\r
451         tmp.R = 0; // Clear ready flag before send\r
452         tmp.B.TXRDY = 1;\r
453         esciHw->SR.R = tmp.R;\r
454         esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
455 \r
456         // Byte 3\r
457         tmpLtr.R = 0; // Clear\r
458         if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ //Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum\r
459                 tmpLtr.B3.HDCHK = 1;\r
460         }\r
461         tmpLtr.B3.CSUM = 1; // Append checksum to TX frame or verify for a RX\r
462         tmpLtr.B3.CRC = 0; // Append two CRC bytes(Not LIN standard)\r
463         if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)\r
464         {\r
465                 LinChannelStatus[Channel]=LIN_TX_BUSY;\r
466                 tmpLtr.B3.TX = 1; // TX frame\r
467                 tmpLtr.B3.TN = 0; // Timeout not valid for TX\r
468                 tmp.R = 0; // Clear ready flag before send\r
469                 tmp.B.TXRDY = 1;\r
470                 esciHw->SR.R = tmp.R;\r
471                 esciHw->LCR.B.FCIE = 1; // // Enable frame complete\r
472                 esciHw->LCR.B.TXIE = 1; // Enable tx irq\r
473                 if (PduInfoPtr->DI > 0){\r
474                         if (TxPtr[Channel] != 0)  {\r
475                                 free(TxPtr[Channel]);\r
476                         }\r
477                         TxCurrPtr[Channel] = TxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);\r
478                         TxSize[Channel] = PduInfoPtr->DI;\r
479                         memcpy(TxPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);\r
480                 }\r
481                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
482         }\r
483 \r
484 \r
485         else\r
486         {\r
487                 LinChannelStatus[Channel]=LIN_RX_BUSY;\r
488                 if (RxPtr[Channel] != 0)        {\r
489                         free(RxPtr[Channel]);\r
490                 }\r
491                 RxCurrPtr[Channel] = RxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);\r
492                 RxSize[Channel] = PduInfoPtr->DI;\r
493 \r
494                 tmpLtr.B3.TX = 0; // RX frame\r
495                 tmpLtr.B3.TN = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3\r
496                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
497                 // Byte 4 for RX\r
498                 tmpLtr.R = 0; // Clear\r
499                 tmpLtr.B4.T = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3\r
500                 tmp.R = 0; // Clear ready flag before send\r
501                 tmp.B.TXRDY = 1;\r
502                 esciHw->SR.R = tmp.R;\r
503                 esciHw->LTR.R=tmpLtr.R; // write to transmit reg\r
504                 esciHw->LCR.B.FCIE = 1; // Enable frame complete\r
505                 esciHw->LCR.B.RXIE = 1; // Enable rx irq\r
506         }\r
507 \r
508         return E_OK;\r
509 }\r
510 \r
511 Std_ReturnType Lin_SendResponse(  uint8 Channel,   Lin_PduType* PduInfoPtr )\r
512 {\r
513         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
514         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
515         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
516         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
517         VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
518 \r
519         // The response is sent from within the header in this implementation since this is a master only implementation\r
520         return E_OK;\r
521 }\r
522 \r
523 Std_ReturnType Lin_GoToSleep(  uint8 Channel )\r
524 {\r
525         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
526         Lin_PduType PduInfo;\r
527         uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};\r
528 \r
529         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
530         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
531         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
532         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
533 \r
534         if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){\r
535                 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;\r
536 \r
537                 PduInfo.Cs = LIN_CLASSIC_CS;\r
538                 PduInfo.Pid = 0x3C;\r
539                 PduInfo.SduPtr = data;\r
540                 PduInfo.DI = 8;\r
541                 PduInfo.Drc = LIN_MASTER_RESPONSE;\r
542 \r
543                 Lin_SendHeader(Channel,  &PduInfo);\r
544                 Lin_SendResponse(Channel,  &PduInfo);\r
545 \r
546                 esciHw->LCR.B.WUIE = 1; // enable wake-up irq\r
547         }\r
548         return E_OK;\r
549 }\r
550 \r
551 Std_ReturnType Lin_GoToSleepInternal(  uint8 Channel )\r
552 {\r
553         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
554         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
555         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
556         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
557         Lin_GoToSleep(Channel);\r
558         return E_OK;\r
559 }\r
560 \r
561 Std_ReturnType Lin_WakeUp( uint8 Channel )\r
562 {\r
563         volatile struct ESCI_tag * esciHw = ESCI(Channel);\r
564         Lin_PduType PduInfo;\r
565         uint8 data[2] = {0xFF,0xFF};\r
566 \r
567         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
568         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
569         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
570         VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);\r
571 \r
572         esciHw->LCR.B.WUIE = 0; // disable wake-up irq\r
573         esciHw->LCR.B.WU = 1; // send wake up\r
574         esciHw->LCR.B.WUD0 = 1; // delimiter time\r
575         esciHw->LCR.B.WUD1 = 0; // delimiter time\r
576 \r
577         // Just send any header to trigger the wakeup signal\r
578         PduInfo.Cs = LIN_CLASSIC_CS;\r
579         PduInfo.Pid = 0x00;\r
580         PduInfo.SduPtr = data;\r
581         PduInfo.DI = 2;\r
582         PduInfo.Drc = LIN_SLAVE_RESPONSE;\r
583         Lin_SendHeader(Channel,  &PduInfo);\r
584 \r
585         LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
586         return E_OK;\r
587 }\r
588 \r
589 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )\r
590 {\r
591         imask_t state;\r
592         VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);\r
593         VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);\r
594         VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);\r
595         VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);\r
596 \r
597     Irq_Save(state);\r
598         Lin_StatusType res = LinChannelStatus[Channel];\r
599         // We can only check for valid sdu ptr when LIN_RX_OK\r
600         if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){\r
601                 *Lin_SduPtr = RxPtr[Channel];\r
602                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
603         } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){\r
604                 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;\r
605         }\r
606     Irq_Restore(state);\r
607         return res;\r
608 }\r
609 \r
610 \r
611 \r
612 \r
613 \r