From: jcar Date: Fri, 14 Oct 2011 13:24:11 +0000 (+0200) Subject: Updated LIN driver X-Git-Url: http://rtime.felk.cvut.cz/gitweb/arc.git/commitdiff_plain/bd5a928b524a2cec63152b5063977a7351646746 Updated LIN driver --- diff --git a/arch/ppc/mpc55xx/drivers/Lin.c b/arch/ppc/mpc55xx/drivers/Lin.c index 4963f1d4..2f4661fe 100644 --- a/arch/ppc/mpc55xx/drivers/Lin.c +++ b/arch/ppc/mpc55xx/drivers/Lin.c @@ -13,13 +13,6 @@ * for more details. * -------------------------------- Arctic Core ------------------------------*/ - - - - - - - #include "Lin.h" #include "LinIf_Cbk.h" #include "mpc55xx.h" @@ -28,25 +21,38 @@ #include #include #include "LinIf_Cbk.h" -#if defined(USE_KERNEL) #include "Os.h" #include "isr.h" +#include "irq.h" +#include "arc.h" + +/* ERRATA for REV_A of 551x chip. Will use a GPT timer for timeout handling */ + +#ifdef MPC551X_ERRATA_REV_A +#include "Gpt.h" + +static Gpt_ChannelType LinChannelTimeOutGptChannelId[ LIN_CONTROLLER_CNT ]; +static uint32 LinChannelBitTimeInTicks[ LIN_CONTROLLER_CNT ]; #endif +#define LIN_MAX_MSG_LENGTH 8 + #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp)) -// LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. +/* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */ static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT; static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT]; static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT]; -static uint8* TxPtr[LIN_CONTROLLER_CNT]; -static uint8* TxCurrPtr[LIN_CONTROLLER_CNT]; -static uint8 TxSize[LIN_CONTROLLER_CNT]; -static uint8* RxPtr[LIN_CONTROLLER_CNT]; -static uint8* RxCurrPtr[LIN_CONTROLLER_CNT]; -static uint8 RxSize[LIN_CONTROLLER_CNT]; +/* static buffers, holds one frame at a time */ +static uint8 LinBufTx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH]; +static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH]; + +static uint8 *TxCurrPtr[LIN_CONTROLLER_CNT]; +static uint8 TxSize[LIN_CONTROLLER_CNT]; +static uint8 *RxCurrPtr[LIN_CONTROLLER_CNT]; +static uint8 RxSize[LIN_CONTROLLER_CNT]; /* Development error macros. */ #if ( LIN_DEV_ERROR_DETECT == STD_ON ) @@ -82,7 +88,7 @@ typedef volatile union uint32_t CSUM:1; uint32_t CRC:1; uint32_t TX:1; - uint32_t TN:1; + uint32_t TN:4; uint32_t :24; } B3; struct { @@ -123,68 +129,86 @@ typedef volatile union { } B; } LinSRtype; /* Status Register */ +static void ResyncDriver(uint8 Channel) +{ + volatile struct ESCI_tag * esciHw = ESCI(Channel); + + esciHw->LCR.B.TXIE = 0; /* Disable tx irq */ + esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */ + esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */ + + /* Disable transmitter and receiver. */ + esciHw->CR1.B.TE = 0; + esciHw->CR1.B.RE = 0; + + /* Clear flags */ + esciHw->SR.R = esciHw->SR.R; + + /* Prepare module for resynchronization. */ + esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */ + /* Resynchronize module. */ + esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */ + + /* Enable transmitter and receiver. */ + esciHw->CR1.B.TE = 1; + esciHw->CR1.B.RE = 1; + +#if 0 /* This needs if we Disable Fast Bit Error Detection otherwise SR will not be cleared properly....strange */ + volatile uint32 i; + for(i=0; i < 10000; ){ + i++; + } +#endif + + /* Clear set flags again */ + esciHw->SR.R = esciHw->SR.R; +} + void LinInterrupt(uint8 Channel) { volatile struct ESCI_tag * esciHw = ESCI(Channel); LinSRtype sr, tmp; LinLTRType tmpLtr; +#ifdef MPC551X_ERRATA_REV_A + uint8 stopTimeOutTimer = FALSE; +#endif sr.R = esciHw->SR.R; - // Clear flags + /* Clear flags */ tmp.R = 0; - if(sr.B.TXRDY == 1) - { - tmp.B.TXRDY = 1; - } - if(sr.B.RXRDY == 1) - { - tmp.B.RXRDY = 1; - } - if(sr.B.TC == 1) - { - tmp.B.TC = 1; - } - if(sr.B.RDRF == 1) - { - tmp.B.RDRF = 1; - } - if(sr.B.IDLE == 1) - { - tmp.B.IDLE = 1; - } - if(sr.B.OVFL == 1) - { - tmp.B.OVFL = 1; - } - if(sr.B.FRC == 1) - { - tmp.B.FRC = 1; - } + if(sr.B.TXRDY == 1){tmp.B.TXRDY = 1;} + if(sr.B.RXRDY == 1){tmp.B.RXRDY = 1;} + if(sr.B.TC == 1){tmp.B.TC = 1;} + if(sr.B.RDRF == 1){tmp.B.RDRF = 1;} + if(sr.B.IDLE == 1){tmp.B.IDLE = 1;} + if(sr.B.OVFL == 1){tmp.B.OVFL = 1;} + if(sr.B.FRC == 1){tmp.B.FRC = 1;} + esciHw->SR.R = tmp.R; - esciHw->LCR.B.TXIE = 0; // Always disable Tx Interrupt + esciHw->LCR.B.TXIE = 0; /* Always disable Tx Interrupt */ - // TX + /* TX */ if (LinChannelStatus[Channel]==LIN_TX_BUSY) { - // Maybe transmit next byte + /* Maybe transmit next byte */ if (TxSize[Channel] > 0 && sr.B.TXRDY) { - tmpLtr.R = 0; // Clear + tmpLtr.R = 0; /* Clear */ tmpLtr.B4.T = *TxCurrPtr[Channel]; TxCurrPtr[Channel]++; TxSize[Channel]--; - esciHw->LCR.B.TXIE = 1; // Enable tx irq - esciHw->LTR.R=tmpLtr.R; // write to transmit reg + esciHw->LCR.B.TXIE = 1; /* Enable tx irq */ + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ } else { if(sr.B.FRC == 1){ - //Transmission complete + /* Transmission complete */ if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){ LinChannelStatus[Channel] = LIN_CH_SLEEP; LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL; }else { LinChannelStatus[Channel] = LIN_TX_OK; } - esciHw->LCR.B.TXIE = 0; // Disable tx irq + esciHw->LCR.B.TXIE = 0; /* Disable tx irq */ } else{ if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){ @@ -194,23 +218,42 @@ void LinInterrupt(uint8 Channel) LinChannelStatus[Channel] = LIN_TX_ERROR; } } +#ifdef MPC551X_ERRATA_REV_A + /* Transmission is over. */ + stopTimeOutTimer = TRUE; +#endif } - } //RX + } /* RX */ else if (LinChannelStatus[Channel]==LIN_RX_BUSY) { - // Maybe receive next byte + /* Maybe receive next byte */ if (RxSize[Channel] > 0 && sr.B.RXRDY) { tmpLtr.R = esciHw->LRR.R; *RxCurrPtr[Channel] = tmpLtr.B5.D; RxCurrPtr[Channel]++; RxSize[Channel]--; } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){ - //receive complete + /* receive complete */ LinChannelStatus[Channel] = LIN_RX_OK; - esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt - esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt + esciHw->LCR.B.RXIE = 0; /* Disable Rx Interrupt */ + esciHw->LCR.B.FCIE = 0; /* Disable Rx Interrupt */ +#ifdef MPC551X_ERRATA_REV_A + /* Transmission is over. */ + stopTimeOutTimer = TRUE; +#endif } } - // Error handling + /* Error handling + * OR - Overrun + * NF – Noise fault + * FE – Framing Error + * PF – Parity fault + * BERR – Bit error (read back) + * STO – Slave Timeout + * PBERR – Physical bit error + * CERR – CRC error + * CKERR – Checksum error + * OVFL – Overflow flag + */ if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR || sr.B.CERR || sr.B.CKERR || sr.B.OVFL) { static uint32 errCnt=0; @@ -221,12 +264,34 @@ void LinInterrupt(uint8 Channel) LinChannelStatus[Channel] = LIN_TX_ERROR; } - // Resynchronize driver and clear all errors - esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared - esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared - // Clear flags + /* Clear flags */ esciHw->SR.R=0xffffffff; + + /* Resynchronize driver in GetStatus call */ + +#ifndef MPC551X_ERRATA_REV_A + } +#else + /* Transmission is over. */ + stopTimeOutTimer = TRUE; + } + + /* Handle LIN Wake Up reset manually. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8632]. */ + if( sr.B.LWAKE ) + { + /* Resynchronize driver. */ + esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared */ + esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared */ + + /* Transmission is over. */ + stopTimeOutTimer = TRUE; } + + if( TRUE == stopTimeOutTimer ) + { + Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] ); + } +#endif } static void LinInterruptA() @@ -262,47 +327,97 @@ static void LinInterruptH() LinInterrupt(LIN_CTRL_H); } +#ifdef MPC551X_ERRATA_REV_A +void LinTimeOutInterrupt( uint8 channel ) +{ + /* We ended up here because of that the eSCI module for the given channel has stopped internally. + * Now we have to reset the LIN module state machine ourself. + * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */ + + volatile struct ESCI_tag *esciHw = ESCI( channel ); + + /* Make sure that the timer it stopped (e.g. if by mistake setup as continuously). */ + Gpt_StopTimer( LinChannelTimeOutGptChannelId[ channel ] ); + + /* Disable transmitter and receiver. */ + esciHw->CR1.B.TE = 0; + esciHw->CR1.B.RE = 0; + + /* Prepare module for resynchronization. */ + esciHw->LCR.B.LRES = 1; /* LIN Resynchronize. First set then cleared. */ + + /* Enable transmitter and receiver. */ + esciHw->CR1.B.TE = 1; + esciHw->CR1.B.RE = 1; + + /* Resynchronize module. */ + esciHw->LCR.B.LRES = 0; /* LIN Resynchronize. First set then cleared. */ +} + +void LinTimeOutInterruptA() +{ + LinTimeOutInterrupt( LIN_CTRL_A ); +} +void LinTimeOutInterruptB() +{ + LinTimeOutInterrupt( LIN_CTRL_B ); +} +void LinTimeOutInterruptC() +{ + LinTimeOutInterrupt( LIN_CTRL_C ); +} +void LinTimeOutInterruptD() +{ + LinTimeOutInterrupt( LIN_CTRL_D ); +} +void LinTimeOutInterruptE() +{ + LinTimeOutInterrupt( LIN_CTRL_E ); +} +void LinTimeOutInterruptF() +{ + LinTimeOutInterrupt( LIN_CTRL_F ); +} +void LinTimeOutInterruptG() +{ + LinTimeOutInterrupt( LIN_CTRL_G ); +} +void LinTimeOutInterruptH() +{ + LinTimeOutInterrupt( LIN_CTRL_H ); +} +#endif void Lin_Init( const Lin_ConfigType* Config ) { uint8 i; VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION ); - //VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); + /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */ for (i=0;i LIN_INIT: The Lin module shall transition from LIN_UNINIT - // to LIN_INIT when the function Lin_Init is called. + /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT + * to LIN_INIT when the function Lin_Init is called. */ LinDriverStatus = LIN_INIT; } void Lin_DeInit() { - uint8 i; - - // Make sure all allocated buffers are freed - for (i=0;iCR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */ @@ -363,9 +494,15 @@ void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config ) esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */ - esciHw->LCR.B.LDBG = 0;/*Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop - further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/ - esciHw->LCR.B.STIE = 1; // Enable some fault irq's +#ifdef MPC551X_ERRATA_REV_A + 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] */ + esciHw->CR2.B.FBR = 1; /* Disable Fast Bit Error Detection. See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8635] */ +#else + esciHw->LCR.B.LDBG = 0; /* Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop + * further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/ + esciHw->CR2.B.FBR = 1; /* Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set; */ +#endif + esciHw->LCR.B.STIE = 1; /* Enable some fault irq's */ esciHw->LCR.B.PBIE = 1; esciHw->LCR.B.CKIE = 1; esciHw->LCR.B.OFIE = 1; @@ -373,17 +510,20 @@ void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config ) esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/ esciHw->CR2.B.BSTP = 1; - esciHw->CR2.B.FBR = 1; // Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set; - esciHw->CR2.B.BESM13 = 1; // normally it will be used with ESCIx_CR2[BESM13] = 1.*/ + esciHw->CR2.B.BESM13 = 1; /* normally it will be used with ESCIx_CR2[BESM13] = 1.*/ /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */ - /* TODO Should we have these interrupts or check the status register? */ + /* Should we have these interrupts or check the status register? */ /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves activate.*/ esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */ LinChannelStatus[Channel]=LIN_CH_OPERATIONAL; +#ifdef MPC551X_ERRATA_REV_A + LinChannelTimeOutGptChannelId[ Channel ] = Config->LinTimeOutGptChannelId; + LinChannelBitTimeInTicks[ Channel ] = McuE_GetPeripheralClock( Config->LinClockRef / Config->LinChannelBaudRate ) / Config->LinChannelBaudRate; +#endif } void Lin_DeInitChannel( uint8 Channel ) @@ -391,18 +531,16 @@ void Lin_DeInitChannel( uint8 Channel ) volatile struct ESCI_tag * esciHw = ESCI(Channel); VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL ); - //LIN178: The function Lin_DeInitChannel shall only be executable when the LIN - //channel state-machine is in state LIN_CH_OPERATIONAL. +#ifdef MPC551X_ERRATA_REV_A + /* Make sure that the timer is stopped. */ + Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] ); +#endif + + /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN + * channel state-machine is in state LIN_CH_OPERATIONAL. */ if(LinChannelStatus[Channel] != LIN_CH_UNINIT){ esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */ - if (RxPtr[Channel] != 0) { - free(RxPtr[Channel]); - } - if (TxPtr[Channel] != 0) { - free(TxPtr[Channel]); - } - LinChannelStatus[Channel]=LIN_CH_UNINIT; } } @@ -414,18 +552,13 @@ Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr ) volatile struct ESCI_tag * esciHw = ESCI(Channel); imask_t state; - // LIN021 + /* LIN021 */ Irq_Save(state); if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR || - LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR){ + LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR) + { + ResyncDriver(Channel); LinChannelStatus[Channel]=LIN_CH_OPERATIONAL; - esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared - esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared - esciHw->LCR.B.TXIE = 0; // Disable tx irq - esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt - esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt - // Clear flags - esciHw->SR.R=0xffffffff; } Irq_Restore(state); @@ -433,78 +566,85 @@ Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr ) VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK); VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK); VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK); - //Send header is used to wake the net in this implementation(no actual header is sent - // VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); + /* Send header is used to wake the net in this implementation(no actual header is sent */ + /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */ VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK); - // Byte 1 - tmpLtr.R = 0; // Clear + /* Byte 1 */ + tmpLtr.R = 0; /* Clear */ tmpLtr.B1.PID = PduInfoPtr->Pid; - tmp.R = 0; // Clear ready flag before send + tmp.R = 0; /* Clear ready flag before send */ tmp.B.TXRDY = 1; esciHw->SR.R = tmp.R; - esciHw->LTR.R=tmpLtr.R; // write to transmit reg + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ - // Byte 2 - tmpLtr.R = 0; // Clear + /* Byte 2 */ + tmpLtr.R = 0; /* Clear */ tmpLtr.B2.L = PduInfoPtr->DI; - tmp.R = 0; // Clear ready flag before send + tmp.R = 0; /* Clear ready flag before send */ tmp.B.TXRDY = 1; esciHw->SR.R = tmp.R; - esciHw->LTR.R=tmpLtr.R; // write to transmit reg + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ - // Byte 3 - tmpLtr.R = 0; // Clear - if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ //Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum + /* Byte 3 */ + tmpLtr.R = 0; /* Clear */ + if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */ tmpLtr.B3.HDCHK = 1; } - tmpLtr.B3.CSUM = 1; // Append checksum to TX frame or verify for a RX - tmpLtr.B3.CRC = 0; // Append two CRC bytes(Not LIN standard) + tmpLtr.B3.CSUM = 1; /* Append checksum to TX frame or verify for a RX */ + tmpLtr.B3.CRC = 0; /* Append two CRC bytes(Not LIN standard) */ + + /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */ + uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10); + if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE) { LinChannelStatus[Channel]=LIN_TX_BUSY; - tmpLtr.B3.TX = 1; // TX frame - tmpLtr.B3.TN = 0; // Timeout not valid for TX - tmp.R = 0; // Clear ready flag before send + tmpLtr.B3.TX = 1; /* TX frame */ + tmpLtr.B3.TN = 0; /* Timeout not valid for TX */ + tmp.R = 0; /* Clear ready flag before send */ tmp.B.TXRDY = 1; esciHw->SR.R = tmp.R; - esciHw->LCR.B.FCIE = 1; // // Enable frame complete - esciHw->LCR.B.TXIE = 1; // Enable tx irq + esciHw->LCR.B.FCIE = 1; /* Enable frame complete */ + esciHw->LCR.B.TXIE = 1; /* Enable tx irq */ if (PduInfoPtr->DI > 0){ - if (TxPtr[Channel] != 0) { - free(TxPtr[Channel]); - } - TxCurrPtr[Channel] = TxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI); + TxCurrPtr[Channel] = LinBufTx[Channel]; TxSize[Channel] = PduInfoPtr->DI; - memcpy(TxPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI); + memcpy(TxCurrPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI); } - esciHw->LTR.R=tmpLtr.R; // write to transmit reg + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ } else { LinChannelStatus[Channel]=LIN_RX_BUSY; - if (RxPtr[Channel] != 0) { - free(RxPtr[Channel]); - } - RxCurrPtr[Channel] = RxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI); + RxCurrPtr[Channel] = LinBufRx[Channel]; RxSize[Channel] = PduInfoPtr->DI; - tmpLtr.B3.TX = 0; // RX frame - tmpLtr.B3.TN = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3 - esciHw->LTR.R=tmpLtr.R; // write to transmit reg - // Byte 4 for RX - tmpLtr.R = 0; // Clear - tmpLtr.B4.T = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3 - tmp.R = 0; // Clear ready flag before send + tmpLtr.B3.TX = 0; /* RX frame */ + tmpLtr.B3.TN = timeOutValue >> 8; /* Most significant bits to be set here. */ + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ + /* Byte 4 for RX */ + tmpLtr.R = 0; /* Clear */ + tmpLtr.B4.T = timeOutValue & 0xFF; /* Least significant bits to be set here. */ + tmp.R = 0; /* Clear ready flag before send */ tmp.B.TXRDY = 1; esciHw->SR.R = tmp.R; - esciHw->LTR.R=tmpLtr.R; // write to transmit reg - esciHw->LCR.B.FCIE = 1; // Enable frame complete - esciHw->LCR.B.RXIE = 1; // Enable rx irq + esciHw->LTR.R=tmpLtr.R; /* write to transmit reg */ + esciHw->LCR.B.FCIE = 1; /* Enable frame complete */ + esciHw->LCR.B.RXIE = 1; /* Enable rx irq */ } +#ifdef MPC551X_ERRATA_REV_A + /* Set up the GPT to twice as long time. Normally this time out shall not be needed but there are two + * Erratas telling us that the LIN message timeout (written above to byte 3 and 4) is sometimes not used + * by the LIN module and the LIN module state machine will then wait in infinity. + * See [Freescale Device Errata MPC5510ACE, Rev. 10 APR 2009, errata ID: 8173 and 4968]. */ + Gpt_StopTimer( LinChannelTimeOutGptChannelId[ Channel ] ); + Gpt_StartTimer( LinChannelTimeOutGptChannelId[ Channel ], LinChannelBitTimeInTicks[ Channel ] * timeOutValue * 2 ); +#endif + return E_OK; } @@ -516,7 +656,7 @@ Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr ) VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK); - // The response is sent from within the header in this implementation since this is a master only implementation + /* The response is sent from within the header in this implementation since this is a master only implementation */ return E_OK; } @@ -543,7 +683,7 @@ Std_ReturnType Lin_GoToSleep( uint8 Channel ) Lin_SendHeader(Channel, &PduInfo); Lin_SendResponse(Channel, &PduInfo); - esciHw->LCR.B.WUIE = 1; // enable wake-up irq + esciHw->LCR.B.WUIE = 1; /* enable wake-up irq */ } return E_OK; } @@ -569,12 +709,12 @@ Std_ReturnType Lin_WakeUp( uint8 Channel ) VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK); VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); - esciHw->LCR.B.WUIE = 0; // disable wake-up irq - esciHw->LCR.B.WU = 1; // send wake up - esciHw->LCR.B.WUD0 = 1; // delimiter time - esciHw->LCR.B.WUD1 = 0; // delimiter time + esciHw->LCR.B.WUIE = 0; /* disable wake-up irq */ + esciHw->LCR.B.WU = 1; /* send wake up */ + esciHw->LCR.B.WUD0 = 1; /* delimiter time */ + esciHw->LCR.B.WUD1 = 0; /* delimiter time */ - // Just send any header to trigger the wakeup signal + /* Just send any header to trigger the wakeup signal */ PduInfo.Cs = LIN_CLASSIC_CS; PduInfo.Pid = 0x00; PduInfo.SduPtr = data; @@ -588,19 +728,25 @@ Std_ReturnType Lin_WakeUp( uint8 Channel ) Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr ) { - imask_t state; VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK); VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK); VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK); VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK); + imask_t state; Irq_Save(state); Lin_StatusType res = LinChannelStatus[Channel]; - // We can only check for valid sdu ptr when LIN_RX_OK + /* We can only check for valid sdu ptr when LIN_RX_OK */ if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){ - *Lin_SduPtr = RxPtr[Channel]; + *Lin_SduPtr = LinBufRx[Channel]; + if(LinChannelStatus[Channel] == LIN_RX_ERROR){ + ResyncDriver(Channel); + } LinChannelStatus[Channel]=LIN_CH_OPERATIONAL; } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){ + if(LinChannelStatus[Channel] == LIN_TX_ERROR){ + ResyncDriver(Channel); + } LinChannelStatus[Channel]=LIN_CH_OPERATIONAL; } Irq_Restore(state); diff --git a/boards/board_common.mk b/boards/board_common.mk index d7ccb648..b21189a7 100644 --- a/boards/board_common.mk +++ b/boards/board_common.mk @@ -154,14 +154,19 @@ obj-$(USE_DET) += Det.o # Lin obj-$(USE_LIN) += Lin_PBcfg.o obj-$(USE_LIN) += Lin_Lcfg.o -obj-$(USE_LIN) += LinIf_Lcfg.o -obj-$(USE_LIN) += LinIf_PBcfg.o -obj-$(USE_LIN) += LinSM_Lcfg.o -obj-$(USE_LIN) += LinSM_PBcfg.o -obj-$(USE_LIN) += LinSM_Cfg.o obj-$(USE_LIN) += Lin.o -obj-$(USE_LIN) += LinIf.o -obj-$(USE_LIN) += LinSM.o + +# LinIf +obj-$(USE_LINIF) += LinIf_Lcfg.o +obj-$(USE_LINIF) += LinIf_PBcfg.o +obj-$(USE_LINIF) += LinIf.o + +# LinSm +obj-$(USE_LINSM) += LinSM_Lcfg.o +obj-$(USE_LINSM) += LinSM_PBcfg.o +obj-$(USE_LINSM) += LinSM_Cfg.o +obj-$(USE_LINSM) += LinSM.o + vpath-y += $(ROOTDIR)/drivers/Lin/ vpath-y += $(ROOTDIR)/communication/Lin inc-y += $(ROOTDIR)/communication/ComM diff --git a/boards/mpc5516it/build_config.mk b/boards/mpc5516it/build_config.mk index 31c0b0d2..22b3c97b 100644 --- a/boards/mpc5516it/build_config.mk +++ b/boards/mpc5516it/build_config.mk @@ -13,9 +13,9 @@ CFG=PPC BOOKE E200Z1 MPC55XX MPC5516 BRD_MPC5516IT # Memory + Peripherals MOD_AVAIL+=ADC DIO DMA CAN GPT LIN MCU PORT PWM WDG NVM MEMIF FEE FLS SPI EEP # System + Communication + Diagnostic -MOD_AVAIL+=CANIF CANTP COM DCM DEM DET ECUM IOHWAB KERNEL PDUR WDGM RTE +MOD_AVAIL+=CANIF CANTP LINIF COM DCM DEM DET ECUM IOHWAB KERNEL PDUR WDGM RTE # Network management -MOD_AVAIL+=COMM NM CANNM CANSM EA +MOD_AVAIL+=COMM NM CANNM CANSM EA LINSM # Additional MOD_AVAIL+= RAMLOG diff --git a/communication/Lin/LinIf.c b/communication/Lin/LinIf.c index d1667aaa..fd609e12 100644 --- a/communication/Lin/LinIf.c +++ b/communication/Lin/LinIf.c @@ -27,7 +27,9 @@ #include "LinIf_Cfg.h" #include "Lin.h" #include "LinSM_Cbk.h" +#if defined(USE_PDUR) #include "PduR_LinIf.h" +#endif #include "Det.h" #if defined(USE_DEM) #include "Dem.h" diff --git a/communication/Lin/LinSM.c b/communication/Lin/LinSM.c index a4e928e0..b1e0cc93 100644 --- a/communication/Lin/LinSM.c +++ b/communication/Lin/LinSM.c @@ -27,7 +27,9 @@ #include "Lin_Cfg.h" #include "LinSM_Cbk.h" #include "LinIf_Types.h" +#if defined(USE_COM) #include "Com.h" +#endif #include "ComM_Types.h" #include "ComStack_Types.h" #include "Com_Types.h" diff --git a/include/LinSM.h b/include/LinSM.h index 143d3138..6fe03d16 100644 --- a/include/LinSM.h +++ b/include/LinSM.h @@ -34,7 +34,9 @@ #include "Std_Types.h" #include "LinSM_Cfg.h" #include "Com_Types.h" +#if defined(USE_COM) #include "Com.h" +#endif #include "ComM_Types.h" #include "LinIf.h"