1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
17 #include "LinIf_Cbk.h"
\r
18 #include "mpc55xx.h"
\r
23 #include "LinIf_Cbk.h"
\r
29 /* ERRATA for REV_A of 551x chip. Will use a GPT timer for timeout handling */
\r
31 #ifdef MPC551X_ERRATA_REV_A
\r
34 static Gpt_ChannelType LinChannelTimeOutGptChannelId[ LIN_CONTROLLER_CNT ];
\r
35 static uint32 LinChannelBitTimeInTicks[ LIN_CONTROLLER_CNT ];
\r
38 #define LIN_MAX_MSG_LENGTH 8
\r
40 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))
\r
42 /* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */
\r
43 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;
\r
45 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];
\r
46 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];
\r
48 /* static buffers, holds one frame at a time */
\r
49 static uint8 LinBufTx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];
\r
50 static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];
\r
52 static uint8 *TxCurrPtr[LIN_CONTROLLER_CNT];
\r
53 static uint8 TxSize[LIN_CONTROLLER_CNT];
\r
54 static uint8 *RxCurrPtr[LIN_CONTROLLER_CNT];
\r
55 static uint8 RxSize[LIN_CONTROLLER_CNT];
\r
57 /* Development error macros. */
\r
58 #if ( LIN_DEV_ERROR_DETECT == STD_ON )
\r
59 #define VALIDATE(_exp,_api,_err ) \
\r
61 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
65 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
67 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
71 #define VALIDATE(_exp,_api,_err )
\r
72 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
75 typedef volatile union
\r
104 typedef volatile union {
\r
130 } LinSRtype; /* Status Register */
\r
132 static void ResyncDriver(uint8 Channel)
\r
134 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
136 esciHw->LCR.B.TXIE = 0; /* Disable tx irq */
\r
137 esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */
\r
138 esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */
\r
140 /* Disable transmitter and receiver. */
\r
141 esciHw->CR1.B.TE = 0;
\r
142 esciHw->CR1.B.RE = 0;
\r
145 esciHw->SR.R = esciHw->SR.R;
\r
147 /* Prepare module for resynchronization. */
\r
148 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */
\r
149 /* Resynchronize module. */
\r
150 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */
\r
152 /* Enable transmitter and receiver. */
\r
153 esciHw->CR1.B.TE = 1;
\r
154 esciHw->CR1.B.RE = 1;
\r
156 #if 0 /* This needs if we Disable Fast Bit Error Detection otherwise SR will not be cleared properly....strange */
\r
158 for(i=0; i < 10000; ){
\r
163 /* Clear set flags again */
\r
164 esciHw->SR.R = esciHw->SR.R;
\r
168 void LinInterrupt(uint8 Channel)
\r
170 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
173 #ifdef MPC551X_ERRATA_REV_A
\r
174 uint8 stopTimeOutTimer = FALSE;
\r
177 sr.R = esciHw->SR.R;
\r
181 if(sr.B.TXRDY == 1){tmp.B.TXRDY = 1;}
\r
182 if(sr.B.RXRDY == 1){tmp.B.RXRDY = 1;}
\r
183 if(sr.B.TC == 1){tmp.B.TC = 1;}
\r
184 if(sr.B.RDRF == 1){tmp.B.RDRF = 1;}
\r
185 if(sr.B.IDLE == 1){tmp.B.IDLE = 1;}
\r
186 if(sr.B.OVFL == 1){tmp.B.OVFL = 1;}
\r
187 if(sr.B.FRC == 1){tmp.B.FRC = 1;}
\r
189 esciHw->SR.R = tmp.R;
\r
190 esciHw->LCR.B.TXIE = 0; /* Always disable Tx Interrupt */
\r
193 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
194 /* Maybe transmit next byte */
\r
195 if (TxSize[Channel] > 0 && sr.B.TXRDY) {
\r
196 tmpLtr.R = 0; /* Clear */
\r
197 tmpLtr.B4.T = *TxCurrPtr[Channel];
\r
198 TxCurrPtr[Channel]++; TxSize[Channel]--;
\r
199 esciHw->LCR.B.TXIE = 1; /* Enable tx irq */
\r
200 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
204 /* Transmission complete */
\r
205 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
206 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
207 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
209 LinChannelStatus[Channel] = LIN_TX_OK;
\r
211 esciHw->LCR.B.TXIE = 0; /* Disable tx irq */
\r
214 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
215 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
216 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
218 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
221 #ifdef MPC551X_ERRATA_REV_A
\r
222 /* Transmission is over. */
\r
223 stopTimeOutTimer = TRUE;
\r
227 else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
228 /* Maybe receive next byte */
\r
229 if (RxSize[Channel] > 0 && sr.B.RXRDY) {
\r
230 tmpLtr.R = esciHw->LRR.R;
\r
231 *RxCurrPtr[Channel] = tmpLtr.B5.D;
\r
232 RxCurrPtr[Channel]++; RxSize[Channel]--;
\r
233 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){
\r
234 /* receive complete */
\r
235 LinChannelStatus[Channel] = LIN_RX_OK;
\r
236 esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */
\r
237 esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */
\r
238 #ifdef MPC551X_ERRATA_REV_A
\r
239 /* Transmission is over. */
\r
240 stopTimeOutTimer = TRUE;
\r
247 * NF
\96 Noise fault
\r
248 * FE
\96 Framing Error
\r
249 * PF
\96 Parity fault
\r
250 * BERR
\96 Bit error (read back)
\r
251 * STO
\96 Slave Timeout
\r
252 * PBERR
\96 Physical bit error
\r
253 * CERR
\96 CRC error
\r
254 * CKERR
\96 Checksum error
\r
255 * OVFL
\96 Overflow flag
\r
257 if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||
\r
258 sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {
\r
259 static uint32 errCnt=0;
\r
261 if(LinChannelStatus[Channel]==LIN_RX_BUSY){
\r
262 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
263 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){
\r
264 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
268 esciHw->SR.R=0xffffffff;
\r
270 /* Resynchronize driver in GetStatus call */
\r
272 #ifndef MPC551X_ERRATA_REV_A
\r
275 /* Transmission is over. */
\r
276 stopTimeOutTimer = TRUE;
\r
279 /* Handle LIN Wake Up reset manually. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632]. */
\r
282 /* Resynchronize driver. */
\r
283 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared */
\r
284 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared */
\r
286 /* Transmission is over. */
\r
287 stopTimeOutTimer = TRUE;
\r
290 if( TRUE == stopTimeOutTimer )
\r
292 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
297 static void LinInterruptA()
\r
299 LinInterrupt(LIN_CTRL_A);
\r
301 static void LinInterruptB()
\r
303 LinInterrupt(LIN_CTRL_B);
\r
305 static void LinInterruptC()
\r
307 LinInterrupt(LIN_CTRL_C);
\r
309 static void LinInterruptD()
\r
311 LinInterrupt(LIN_CTRL_D);
\r
313 static void LinInterruptE()
\r
315 LinInterrupt(LIN_CTRL_E);
\r
317 static void LinInterruptF()
\r
319 LinInterrupt(LIN_CTRL_F);
\r
321 static void LinInterruptG()
\r
323 LinInterrupt(LIN_CTRL_G);
\r
325 static void LinInterruptH()
\r
327 LinInterrupt(LIN_CTRL_H);
\r
330 #ifdef MPC551X_ERRATA_REV_A
\r
331 void LinTimeOutInterrupt( uint8 channel )
\r
333 /* We ended up here because of that the eSCI module for the given channel has stopped internally.
\r
334 * Now we have to reset the LIN module state machine ourself.
\r
335 * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */
\r
337 volatile struct ESCI_tag *esciHw = ESCI( channel );
\r
339 /* Make sure that the timer it stopped (e.g. if by mistake setup as continuously). */
\r
340 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ channel ] );
\r
342 /* Disable transmitter and receiver. */
\r
343 esciHw->CR1.B.TE = 0;
\r
344 esciHw->CR1.B.RE = 0;
\r
346 /* Prepare module for resynchronization. */
\r
347 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */
\r
349 /* Enable transmitter and receiver. */
\r
350 esciHw->CR1.B.TE = 1;
\r
351 esciHw->CR1.B.RE = 1;
\r
353 /* Resynchronize module. */
\r
354 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */
\r
357 void LinTimeOutInterruptA()
\r
359 LinTimeOutInterrupt( LIN_CTRL_A );
\r
361 void LinTimeOutInterruptB()
\r
363 LinTimeOutInterrupt( LIN_CTRL_B );
\r
365 void LinTimeOutInterruptC()
\r
367 LinTimeOutInterrupt( LIN_CTRL_C );
\r
369 void LinTimeOutInterruptD()
\r
371 LinTimeOutInterrupt( LIN_CTRL_D );
\r
373 void LinTimeOutInterruptE()
\r
375 LinTimeOutInterrupt( LIN_CTRL_E );
\r
377 void LinTimeOutInterruptF()
\r
379 LinTimeOutInterrupt( LIN_CTRL_F );
\r
381 void LinTimeOutInterruptG()
\r
383 LinTimeOutInterrupt( LIN_CTRL_G );
\r
385 void LinTimeOutInterruptH()
\r
387 LinTimeOutInterrupt( LIN_CTRL_H );
\r
391 void Lin_Init( const Lin_ConfigType* Config )
\r
395 VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );
\r
396 /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */
\r
398 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
400 /* LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into
\r
401 * state LIN_CH_UNINIT. */
\r
402 LinChannelStatus[i] = LIN_CH_UNINIT;
\r
403 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;
\r
408 #ifdef MPC551X_ERRATA_REV_A
\r
409 LinChannelTimeOutGptChannelId[ i ] = 0;
\r
410 LinChannelBitTimeInTicks[ i ] = 0;
\r
414 /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT
\r
415 * to LIN_INIT when the function Lin_Init is called. */
\r
416 LinDriverStatus = LIN_INIT;
\r
420 LinDriverStatus = LIN_UNINIT;
\r
423 void Lin_WakeupValidation( void )
\r
428 void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config )
\r
430 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
436 VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
437 VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );
\r
438 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
440 /* Install the interrupt */
\r
443 ISR_INSTALL_ISR2("LinIsr", LinInterruptA, (IrqType)(SCI_A_COMB),LIN_PRIO, 0);
\r
446 ISR_INSTALL_ISR2("LinIsr", LinInterruptB, (IrqType)(SCI_B_COMB),LIN_PRIO, 0);
\r
449 ISR_INSTALL_ISR2("LinIsr", LinInterruptC, (IrqType)(SCI_C_COMB),LIN_PRIO, 0);
\r
452 ISR_INSTALL_ISR2("LinIsr", LinInterruptD, (IrqType)(SCI_D_COMB),LIN_PRIO, 0);
\r
455 ISR_INSTALL_ISR2("LinIsr", LinInterruptE, (IrqType)(SCI_E_COMB),LIN_PRIO, 0);
\r
458 ISR_INSTALL_ISR2("LinIsr", LinInterruptF, (IrqType)(SCI_F_COMB),LIN_PRIO, 0);
\r
461 ISR_INSTALL_ISR2("LinIsr", LinInterruptG, (IrqType)(SCI_G_COMB+2),LIN_PRIO, 0);
\r
464 ISR_INSTALL_ISR2("LinIsr", LinInterruptH, (IrqType)(SCI_H_COMB+3),LIN_PRIO, 0);
\r
470 esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */
\r
472 esciHw->CR1.B.RE = 1;
\r
473 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
474 esciHw->CR1.B.PE = 0;
\r
475 esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/
\r
476 esciHw->CR1.B.TCIE = 0;
\r
477 esciHw->CR1.B.RIE = 0;
\r
478 /* Set up ESCIx_CR1 for LIN */
\r
480 * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.
\r
481 * The formula for calculating the baud rate is:
\r
483 * eSCI system clock
\r
484 * SCI baud rate = -----------------------
\r
487 * where SBR can contain a value from 1 to 8191. After reset, the baud generator
\r
488 * is disabled until the TE bit or the RE bit is set for the first time. The baud
\r
489 * rate generator is disabled when SBR = 0x0.
\r
491 esciHw->CR1.B.SBR = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);
\r
492 esciHw->LCR.B.LIN = 1; /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/
\r
494 esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long
\r
495 (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */
\r
497 #ifdef MPC551X_ERRATA_REV_A
\r
498 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
499 esciHw->CR2.B.FBR = 1; /* Disable Fast Bit Error Detection. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8635] */
\r
501 esciHw->LCR.B.LDBG = 0; /* Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop
\r
502 * further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/
\r
503 esciHw->CR2.B.FBR = 1; /* Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set; */
\r
505 esciHw->LCR.B.STIE = 1; /* Enable some fault irq's */
\r
506 esciHw->LCR.B.PBIE = 1;
\r
507 esciHw->LCR.B.CKIE = 1;
\r
508 esciHw->LCR.B.OFIE = 1;
\r
510 esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/
\r
511 esciHw->CR2.B.BSTP = 1;
\r
513 esciHw->CR2.B.BESM13 = 1; /* normally it will be used with ESCIx_CR2[BESM13] = 1.*/
\r
515 /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */
\r
516 /* Should we have these interrupts or check the status register? */
\r
517 /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves
\r
520 esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */
\r
522 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
523 #ifdef MPC551X_ERRATA_REV_A
\r
524 LinChannelTimeOutGptChannelId[ Channel ] = Config->LinTimeOutGptChannelId;
\r
525 LinChannelBitTimeInTicks[ Channel ] = McuE_GetPeripheralClock( Config->LinClockRef / Config->LinChannelBaudRate ) / Config->LinChannelBaudRate;
\r
529 void Lin_DeInitChannel( uint8 Channel )
\r
531 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
532 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
534 #ifdef MPC551X_ERRATA_REV_A
\r
535 /* Make sure that the timer is stopped. */
\r
536 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
539 /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN
\r
540 * channel state-machine is in state LIN_CH_OPERATIONAL. */
\r
541 if(LinChannelStatus[Channel] != LIN_CH_UNINIT){
\r
542 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */
\r
544 LinChannelStatus[Channel]=LIN_CH_UNINIT;
\r
548 Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
552 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
557 if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||
\r
558 LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR)
\r
560 ResyncDriver(Channel);
\r
561 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
563 Irq_Restore(state);
\r
566 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
567 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
568 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
569 /* Send header is used to wake the net in this implementation(no actual header is sent */
\r
570 /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */
\r
571 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
574 tmpLtr.R = 0; /* Clear */
\r
575 tmpLtr.B1.PID = PduInfoPtr->Pid;
\r
576 tmp.R = 0; /* Clear ready flag before send */
\r
578 esciHw->SR.R = tmp.R;
\r
579 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
582 tmpLtr.R = 0; /* Clear */
\r
583 tmpLtr.B2.L = PduInfoPtr->DI;
\r
584 tmp.R = 0; /* Clear ready flag before send */
\r
586 esciHw->SR.R = tmp.R;
\r
587 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
590 tmpLtr.R = 0; /* Clear */
\r
591 if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */
\r
592 tmpLtr.B3.HDCHK = 1;
\r
594 tmpLtr.B3.CSUM = 1; /* Append checksum to TX frame or verify for a RX */
\r
595 tmpLtr.B3.CRC = 0; /* Append two CRC bytes(Not LIN standard) */
\r
597 /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */
\r
598 uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10);
\r
600 if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)
\r
602 LinChannelStatus[Channel]=LIN_TX_BUSY;
\r
603 tmpLtr.B3.TX = 1; /* TX frame */
\r
604 tmpLtr.B3.TN = 0; /* Timeout not valid for TX */
\r
605 tmp.R = 0; /* Clear ready flag before send */
\r
607 esciHw->SR.R = tmp.R;
\r
608 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */
\r
609 esciHw->LCR.B.TXIE = 1; /* Enable tx irq */
\r
610 if (PduInfoPtr->DI > 0){
\r
611 TxCurrPtr[Channel] = LinBufTx[Channel];
\r
612 TxSize[Channel] = PduInfoPtr->DI;
\r
613 memcpy(TxCurrPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);
\r
615 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
621 LinChannelStatus[Channel]=LIN_RX_BUSY;
\r
622 RxCurrPtr[Channel] = LinBufRx[Channel];
\r
623 RxSize[Channel] = PduInfoPtr->DI;
\r
625 tmpLtr.B3.TX = 0; /* RX frame */
\r
626 tmpLtr.B3.TN = timeOutValue >> 8; /* Most significant bits to be set here. */
\r
627 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
628 /* Byte 4 for RX */
\r
629 tmpLtr.R = 0; /* Clear */
\r
630 tmpLtr.B4.T = timeOutValue & 0xFF; /* Least significant bits to be set here. */
\r
631 tmp.R = 0; /* Clear ready flag before send */
\r
633 esciHw->SR.R = tmp.R;
\r
634 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
635 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */
\r
636 esciHw->LCR.B.RXIE = 1; /* Enable rx irq */
\r
639 #ifdef MPC551X_ERRATA_REV_A
\r
640 /* Set up the GPT to twice as long time. Normally this time out shall not be needed but there are two
\r
641 * Erratas telling us that the LIN message timeout (written above to byte 3 and 4) is sometimes not used
\r
642 * by the LIN module and the LIN module state machine will then wait in infinity.
\r
643 * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */
\r
644 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
645 Gpt_StartTimer( LinChannelTimeOutGptChannelId[ Channel ], LinChannelBitTimeInTicks[ Channel ] * timeOutValue * 2 );
\r
651 Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
653 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
654 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
655 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
656 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
657 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
659 /* The response is sent from within the header in this implementation since this is a master only implementation */
\r
663 Std_ReturnType Lin_GoToSleep( uint8 Channel )
\r
665 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
666 Lin_PduType PduInfo;
\r
667 uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
\r
669 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
670 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
671 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
672 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
674 if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){
\r
675 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;
\r
677 PduInfo.Cs = LIN_CLASSIC_CS;
\r
678 PduInfo.Pid = 0x3C;
\r
679 PduInfo.SduPtr = data;
\r
681 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
683 Lin_SendHeader(Channel, &PduInfo);
\r
684 Lin_SendResponse(Channel, &PduInfo);
\r
686 esciHw->LCR.B.WUIE = 1; /* enable wake-up irq */
\r
691 Std_ReturnType Lin_GoToSleepInternal( uint8 Channel )
\r
693 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
694 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
695 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
696 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
697 Lin_GoToSleep(Channel);
\r
701 Std_ReturnType Lin_WakeUp( uint8 Channel )
\r
703 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
704 Lin_PduType PduInfo;
\r
705 uint8 data[2] = {0xFF,0xFF};
\r
707 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
708 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
709 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
710 VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
712 esciHw->LCR.B.WUIE = 0; /* disable wake-up irq */
\r
713 esciHw->LCR.B.WU = 1; /* send wake up */
\r
714 esciHw->LCR.B.WUD0 = 1; /* delimiter time */
\r
715 esciHw->LCR.B.WUD1 = 0; /* delimiter time */
\r
717 /* Just send any header to trigger the wakeup signal */
\r
718 PduInfo.Cs = LIN_CLASSIC_CS;
\r
719 PduInfo.Pid = 0x00;
\r
720 PduInfo.SduPtr = data;
\r
722 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
723 Lin_SendHeader(Channel, &PduInfo);
\r
725 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
729 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )
\r
731 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
732 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
733 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
734 VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
738 Lin_StatusType res = LinChannelStatus[Channel];
\r
739 /* We can only check for valid sdu ptr when LIN_RX_OK */
\r
740 if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
741 *Lin_SduPtr = LinBufRx[Channel];
\r
742 if(LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
743 ResyncDriver(Channel);
\r
745 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
746 } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
747 if(LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
748 ResyncDriver(Channel);
\r
750 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
752 Irq_Restore(state);
\r