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
41 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFB0000 + (0x4000 * exp))
\r
43 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))
\r
46 /* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */
\r
47 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;
\r
49 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];
\r
50 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];
\r
52 /* static buffers, holds one frame at a time */
\r
53 static uint8 LinBufTx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];
\r
54 static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];
\r
56 static uint8 *TxCurrPtr[LIN_CONTROLLER_CNT];
\r
57 static uint8 TxSize[LIN_CONTROLLER_CNT];
\r
58 static uint8 *RxCurrPtr[LIN_CONTROLLER_CNT];
\r
59 static uint8 RxSize[LIN_CONTROLLER_CNT];
\r
61 /* Development error macros. */
\r
62 #if ( LIN_DEV_ERROR_DETECT == STD_ON )
\r
63 #define VALIDATE(_exp,_api,_err ) \
\r
65 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
69 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
71 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
75 #define VALIDATE(_exp,_api,_err )
\r
76 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
79 typedef volatile union
\r
108 typedef volatile union {
\r
134 } LinSRtype; /* Status Register */
\r
136 static void ResyncDriver(uint8 Channel)
\r
138 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
140 esciHw->LCR.B.TXIE = 0; /* Disable tx irq */
\r
141 esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */
\r
142 esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */
\r
144 /* Disable transmitter and receiver. */
\r
145 esciHw->CR1.B.TE = 0;
\r
146 esciHw->CR1.B.RE = 0;
\r
149 esciHw->SR.R = esciHw->SR.R;
\r
151 /* Prepare module for resynchronization. */
\r
152 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */
\r
153 /* Resynchronize module. */
\r
154 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */
\r
156 /* Enable transmitter and receiver. */
\r
157 esciHw->CR1.B.TE = 1;
\r
158 esciHw->CR1.B.RE = 1;
\r
160 #if 0 /* This needs if we Disable Fast Bit Error Detection otherwise SR will not be cleared properly....strange */
\r
162 for(i=0; i < 10000; ){
\r
167 /* Clear set flags again */
\r
168 esciHw->SR.R = esciHw->SR.R;
\r
172 void LinInterrupt(uint8 Channel)
\r
174 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
177 #ifdef MPC551X_ERRATA_REV_A
\r
178 uint8 stopTimeOutTimer = FALSE;
\r
181 sr.R = esciHw->SR.R;
\r
185 if(sr.B.TXRDY == 1){tmp.B.TXRDY = 1;}
\r
186 if(sr.B.RXRDY == 1){tmp.B.RXRDY = 1;}
\r
187 if(sr.B.TC == 1){tmp.B.TC = 1;}
\r
188 if(sr.B.RDRF == 1){tmp.B.RDRF = 1;}
\r
189 if(sr.B.IDLE == 1){tmp.B.IDLE = 1;}
\r
190 if(sr.B.OVFL == 1){tmp.B.OVFL = 1;}
\r
191 if(sr.B.FRC == 1){tmp.B.FRC = 1;}
\r
193 esciHw->SR.R = tmp.R;
\r
194 esciHw->LCR.B.TXIE = 0; /* Always disable Tx Interrupt */
\r
197 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
198 /* Maybe transmit next byte */
\r
199 if (TxSize[Channel] > 0 && sr.B.TXRDY) {
\r
200 tmpLtr.R = 0; /* Clear */
\r
201 tmpLtr.B4.T = *TxCurrPtr[Channel];
\r
202 TxCurrPtr[Channel]++; TxSize[Channel]--;
\r
203 esciHw->LCR.B.TXIE = 1; /* Enable tx irq */
\r
204 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
208 /* Transmission complete */
\r
209 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
210 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
211 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
213 LinChannelStatus[Channel] = LIN_TX_OK;
\r
215 esciHw->LCR.B.TXIE = 0; /* Disable tx irq */
\r
218 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
219 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
220 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
222 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
225 #ifdef MPC551X_ERRATA_REV_A
\r
226 /* Transmission is over. */
\r
227 stopTimeOutTimer = TRUE;
\r
231 else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
232 /* Maybe receive next byte */
\r
233 if (RxSize[Channel] > 0 && sr.B.RXRDY) {
\r
234 tmpLtr.R = esciHw->LRR.R;
\r
235 *RxCurrPtr[Channel] = tmpLtr.B5.D;
\r
236 RxCurrPtr[Channel]++; RxSize[Channel]--;
\r
237 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){
\r
238 /* receive complete */
\r
239 LinChannelStatus[Channel] = LIN_RX_OK;
\r
240 esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */
\r
241 esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */
\r
242 #ifdef MPC551X_ERRATA_REV_A
\r
243 /* Transmission is over. */
\r
244 stopTimeOutTimer = TRUE;
\r
251 * NF
\96 Noise fault
\r
252 * FE
\96 Framing Error
\r
253 * PF
\96 Parity fault
\r
254 * BERR
\96 Bit error (read back)
\r
255 * STO
\96 Slave Timeout
\r
256 * PBERR
\96 Physical bit error
\r
257 * CERR
\96 CRC error
\r
258 * CKERR
\96 Checksum error
\r
259 * OVFL
\96 Overflow flag
\r
261 if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||
\r
262 sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {
\r
263 static uint32 errCnt=0;
\r
265 if(LinChannelStatus[Channel]==LIN_RX_BUSY){
\r
266 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
267 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){
\r
268 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
272 esciHw->SR.R=0xffffffff;
\r
274 /* Resynchronize driver in GetStatus call */
\r
276 #ifndef MPC551X_ERRATA_REV_A
\r
279 /* Transmission is over. */
\r
280 stopTimeOutTimer = TRUE;
\r
283 /* Handle LIN Wake Up reset manually. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632]. */
\r
286 /* Resynchronize driver. */
\r
287 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared */
\r
288 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared */
\r
290 /* Transmission is over. */
\r
291 stopTimeOutTimer = TRUE;
\r
294 if( TRUE == stopTimeOutTimer )
\r
296 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
301 static void LinInterruptA()
\r
303 LinInterrupt(LIN_CTRL_A);
\r
305 static void LinInterruptB()
\r
307 LinInterrupt(LIN_CTRL_B);
\r
309 #ifndef CFG_MPC5567
\r
310 static void LinInterruptC()
\r
312 LinInterrupt(LIN_CTRL_C);
\r
314 static void LinInterruptD()
\r
316 LinInterrupt(LIN_CTRL_D);
\r
318 static void LinInterruptE()
\r
320 LinInterrupt(LIN_CTRL_E);
\r
322 static void LinInterruptF()
\r
324 LinInterrupt(LIN_CTRL_F);
\r
326 static void LinInterruptG()
\r
328 LinInterrupt(LIN_CTRL_G);
\r
330 static void LinInterruptH()
\r
332 LinInterrupt(LIN_CTRL_H);
\r
336 #ifdef MPC551X_ERRATA_REV_A
\r
337 void LinTimeOutInterrupt( uint8 channel )
\r
339 /* We ended up here because of that the eSCI module for the given channel has stopped internally.
\r
340 * Now we have to reset the LIN module state machine ourself.
\r
341 * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */
\r
343 volatile struct ESCI_tag *esciHw = ESCI( channel );
\r
345 /* Make sure that the timer it stopped (e.g. if by mistake setup as continuously). */
\r
346 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ channel ] );
\r
348 /* Disable transmitter and receiver. */
\r
349 esciHw->CR1.B.TE = 0;
\r
350 esciHw->CR1.B.RE = 0;
\r
352 /* Prepare module for resynchronization. */
\r
353 esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */
\r
355 /* Enable transmitter and receiver. */
\r
356 esciHw->CR1.B.TE = 1;
\r
357 esciHw->CR1.B.RE = 1;
\r
359 /* Resynchronize module. */
\r
360 esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */
\r
363 void LinTimeOutInterruptA()
\r
365 LinTimeOutInterrupt( LIN_CTRL_A );
\r
367 void LinTimeOutInterruptB()
\r
369 LinTimeOutInterrupt( LIN_CTRL_B );
\r
371 void LinTimeOutInterruptC()
\r
373 LinTimeOutInterrupt( LIN_CTRL_C );
\r
375 void LinTimeOutInterruptD()
\r
377 LinTimeOutInterrupt( LIN_CTRL_D );
\r
379 void LinTimeOutInterruptE()
\r
381 LinTimeOutInterrupt( LIN_CTRL_E );
\r
383 void LinTimeOutInterruptF()
\r
385 LinTimeOutInterrupt( LIN_CTRL_F );
\r
387 void LinTimeOutInterruptG()
\r
389 LinTimeOutInterrupt( LIN_CTRL_G );
\r
391 void LinTimeOutInterruptH()
\r
393 LinTimeOutInterrupt( LIN_CTRL_H );
\r
397 void Lin_Init( const Lin_ConfigType* Config )
\r
401 VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );
\r
402 /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */
\r
404 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
406 /* LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into
\r
407 * state LIN_CH_UNINIT. */
\r
408 LinChannelStatus[i] = LIN_CH_UNINIT;
\r
409 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;
\r
414 #ifdef MPC551X_ERRATA_REV_A
\r
415 LinChannelTimeOutGptChannelId[ i ] = 0;
\r
416 LinChannelBitTimeInTicks[ i ] = 0;
\r
420 /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT
\r
421 * to LIN_INIT when the function Lin_Init is called. */
\r
422 LinDriverStatus = LIN_INIT;
\r
426 LinDriverStatus = LIN_UNINIT;
\r
429 void Lin_WakeupValidation( void )
\r
434 void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config )
\r
436 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
442 VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
443 VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );
\r
444 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
446 /* Install the interrupt */
\r
450 ISR_INSTALL_ISR2("LinIsr", LinInterruptA, (IrqType)(ESCI_A_COMB0),LIN_PRIO, 0);
\r
452 ISR_INSTALL_ISR2("LinIsr", LinInterruptA, (IrqType)(SCI_A_COMB),LIN_PRIO, 0);
\r
457 ISR_INSTALL_ISR2("LinIsr", LinInterruptB, (IrqType)(ESCI_A_COMB1),LIN_PRIO, 0);
\r
459 ISR_INSTALL_ISR2("LinIsr", LinInterruptB, (IrqType)(SCI_B_COMB),LIN_PRIO, 0);
\r
463 #ifndef CFG_MPC5567
\r
464 ISR_INSTALL_ISR2("LinIsr", LinInterruptC, (IrqType)(SCI_C_COMB),LIN_PRIO, 0);
\r
468 #ifndef CFG_MPC5567
\r
469 ISR_INSTALL_ISR2("LinIsr", LinInterruptD, (IrqType)(SCI_D_COMB),LIN_PRIO, 0);
\r
473 #ifndef CFG_MPC5567
\r
474 ISR_INSTALL_ISR2("LinIsr", LinInterruptE, (IrqType)(SCI_E_COMB),LIN_PRIO, 0);
\r
478 #ifndef CFG_MPC5567
\r
479 ISR_INSTALL_ISR2("LinIsr", LinInterruptF, (IrqType)(SCI_F_COMB),LIN_PRIO, 0);
\r
483 #ifndef CFG_MPC5567
\r
484 ISR_INSTALL_ISR2("LinIsr", LinInterruptG, (IrqType)(SCI_G_COMB+2),LIN_PRIO, 0);
\r
488 #ifndef CFG_MPC5567
\r
489 ISR_INSTALL_ISR2("LinIsr", LinInterruptH, (IrqType)(SCI_H_COMB+3),LIN_PRIO, 0);
\r
496 esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */
\r
498 esciHw->CR1.B.RE = 1;
\r
499 esciHw->CR1.B.M = 0; /* The data format bit ESCIx_CR1[M], is set to 0 (8 data bits), and the parity is disabled (PE = 0).*/
\r
500 esciHw->CR1.B.PE = 0;
\r
501 esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/
\r
502 esciHw->CR1.B.TCIE = 0;
\r
503 esciHw->CR1.B.RIE = 0;
\r
504 /* Set up ESCIx_CR1 for LIN */
\r
506 * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.
\r
507 * The formula for calculating the baud rate is:
\r
509 * eSCI system clock
\r
510 * SCI baud rate = -----------------------
\r
513 * where SBR can contain a value from 1 to 8191. After reset, the baud generator
\r
514 * is disabled until the TE bit or the RE bit is set for the first time. The baud
\r
515 * rate generator is disabled when SBR = 0x0.
\r
517 esciHw->CR1.B.SBR = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);
\r
518 esciHw->LCR.B.LIN = 1; /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/
\r
520 esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long
\r
521 (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */
\r
523 #ifdef MPC551X_ERRATA_REV_A
\r
524 esciHw->LCR.B.LDBG = 1; /* Enable LIN debug => Disable automatic reset of the LIN FSM. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632] */
\r
525 esciHw->CR2.B.FBR = 1; /* Disable Fast Bit Error Detection. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8635] */
\r
527 esciHw->LCR.B.LDBG = 0; /* Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop
\r
528 * further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/
\r
529 esciHw->CR2.B.FBR = 1; /* Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set; */
\r
531 esciHw->LCR.B.STIE = 1; /* Enable some fault irq's */
\r
532 esciHw->LCR.B.PBIE = 1;
\r
533 esciHw->LCR.B.CKIE = 1;
\r
534 esciHw->LCR.B.OFIE = 1;
\r
536 esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/
\r
537 esciHw->CR2.B.BSTP = 1;
\r
539 esciHw->CR2.B.BESM13 = 1; /* normally it will be used with ESCIx_CR2[BESM13] = 1.*/
\r
541 /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */
\r
542 /* Should we have these interrupts or check the status register? */
\r
543 /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves
\r
546 esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */
\r
548 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
549 #ifdef MPC551X_ERRATA_REV_A
\r
550 LinChannelTimeOutGptChannelId[ Channel ] = Config->LinTimeOutGptChannelId;
\r
551 LinChannelBitTimeInTicks[ Channel ] = McuE_GetPeripheralClock( Config->LinClockRef / Config->LinChannelBaudRate ) / Config->LinChannelBaudRate;
\r
555 void Lin_DeInitChannel( uint8 Channel )
\r
557 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
558 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
560 #ifdef MPC551X_ERRATA_REV_A
\r
561 /* Make sure that the timer is stopped. */
\r
562 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
565 /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN
\r
566 * channel state-machine is in state LIN_CH_OPERATIONAL. */
\r
567 if(LinChannelStatus[Channel] != LIN_CH_UNINIT){
\r
568 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */
\r
570 LinChannelStatus[Channel]=LIN_CH_UNINIT;
\r
574 Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
578 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
583 if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||
\r
584 LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR)
\r
586 ResyncDriver(Channel);
\r
587 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
589 Irq_Restore(state);
\r
592 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
593 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
594 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
595 /* Send header is used to wake the net in this implementation(no actual header is sent */
\r
596 /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */
\r
597 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
600 tmpLtr.R = 0; /* Clear */
\r
601 tmpLtr.B1.PID = PduInfoPtr->Pid;
\r
602 tmp.R = 0; /* Clear ready flag before send */
\r
604 esciHw->SR.R = tmp.R;
\r
605 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
608 tmpLtr.R = 0; /* Clear */
\r
609 tmpLtr.B2.L = PduInfoPtr->DI;
\r
610 tmp.R = 0; /* Clear ready flag before send */
\r
612 esciHw->SR.R = tmp.R;
\r
613 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
616 tmpLtr.R = 0; /* Clear */
\r
617 if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */
\r
618 tmpLtr.B3.HDCHK = 1;
\r
620 tmpLtr.B3.CSUM = 1; /* Append checksum to TX frame or verify for a RX */
\r
621 tmpLtr.B3.CRC = 0; /* Append two CRC bytes(Not LIN standard) */
\r
623 /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */
\r
624 uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10);
\r
626 if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)
\r
628 LinChannelStatus[Channel]=LIN_TX_BUSY;
\r
629 tmpLtr.B3.TX = 1; /* TX frame */
\r
630 tmpLtr.B3.TN = 0; /* Timeout not valid for TX */
\r
631 tmp.R = 0; /* Clear ready flag before send */
\r
633 esciHw->SR.R = tmp.R;
\r
634 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */
\r
635 esciHw->LCR.B.TXIE = 1; /* Enable tx irq */
\r
636 if (PduInfoPtr->DI > 0){
\r
637 TxCurrPtr[Channel] = LinBufTx[Channel];
\r
638 TxSize[Channel] = PduInfoPtr->DI;
\r
639 memcpy(TxCurrPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);
\r
641 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
647 LinChannelStatus[Channel]=LIN_RX_BUSY;
\r
648 RxCurrPtr[Channel] = LinBufRx[Channel];
\r
649 RxSize[Channel] = PduInfoPtr->DI;
\r
651 tmpLtr.B3.TX = 0; /* RX frame */
\r
652 tmpLtr.B3.TN = timeOutValue >> 8; /* Most significant bits to be set here. */
\r
653 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
654 /* Byte 4 for RX */
\r
655 tmpLtr.R = 0; /* Clear */
\r
656 tmpLtr.B4.T = timeOutValue & 0xFF; /* Least significant bits to be set here. */
\r
657 tmp.R = 0; /* Clear ready flag before send */
\r
659 esciHw->SR.R = tmp.R;
\r
660 esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */
\r
661 esciHw->LCR.B.FCIE = 1; /* Enable frame complete */
\r
662 esciHw->LCR.B.RXIE = 1; /* Enable rx irq */
\r
665 #ifdef MPC551X_ERRATA_REV_A
\r
666 /* Set up the GPT to twice as long time. Normally this time out shall not be needed but there are two
\r
667 * Erratas telling us that the LIN message timeout (written above to byte 3 and 4) is sometimes not used
\r
668 * by the LIN module and the LIN module state machine will then wait in infinity.
\r
669 * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */
\r
670 Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] );
\r
671 Gpt_StartTimer( LinChannelTimeOutGptChannelId[ Channel ], LinChannelBitTimeInTicks[ Channel ] * timeOutValue * 2 );
\r
677 Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
679 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
680 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
681 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
682 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
683 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
685 /* The response is sent from within the header in this implementation since this is a master only implementation */
\r
689 Std_ReturnType Lin_GoToSleep( uint8 Channel )
\r
691 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
692 Lin_PduType PduInfo;
\r
693 uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
\r
695 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
696 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
697 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
698 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
700 if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){
\r
701 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;
\r
703 PduInfo.Cs = LIN_CLASSIC_CS;
\r
704 PduInfo.Pid = 0x3C;
\r
705 PduInfo.SduPtr = data;
\r
707 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
709 Lin_SendHeader(Channel, &PduInfo);
\r
710 Lin_SendResponse(Channel, &PduInfo);
\r
712 esciHw->LCR.B.WUIE = 1; /* enable wake-up irq */
\r
717 Std_ReturnType Lin_GoToSleepInternal( uint8 Channel )
\r
719 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
720 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
721 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
722 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
723 Lin_GoToSleep(Channel);
\r
727 Std_ReturnType Lin_WakeUp( uint8 Channel )
\r
729 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
730 Lin_PduType PduInfo;
\r
731 uint8 data[2] = {0xFF,0xFF};
\r
733 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
734 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
735 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
736 VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
738 esciHw->LCR.B.WUIE = 0; /* disable wake-up irq */
\r
739 esciHw->LCR.B.WU = 1; /* send wake up */
\r
740 esciHw->LCR.B.WUD0 = 1; /* delimiter time */
\r
741 esciHw->LCR.B.WUD1 = 0; /* delimiter time */
\r
743 /* Just send any header to trigger the wakeup signal */
\r
744 PduInfo.Cs = LIN_CLASSIC_CS;
\r
745 PduInfo.Pid = 0x00;
\r
746 PduInfo.SduPtr = data;
\r
748 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
749 Lin_SendHeader(Channel, &PduInfo);
\r
751 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
755 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )
\r
757 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
758 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
759 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
760 VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
764 Lin_StatusType res = LinChannelStatus[Channel];
\r
765 /* We can only check for valid sdu ptr when LIN_RX_OK */
\r
766 if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
767 *Lin_SduPtr = LinBufRx[Channel];
\r
768 if(LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
769 ResyncDriver(Channel);
\r
771 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
772 } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
773 if(LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
774 ResyncDriver(Channel);
\r
776 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
778 Irq_Restore(state);
\r