]> rtime.felk.cvut.cz Git - arc.git/commitdiff
Updated LIN driver
authorjcar <devnull@localhost>
Fri, 14 Oct 2011 13:24:11 +0000 (15:24 +0200)
committerjcar <devnull@localhost>
Fri, 14 Oct 2011 13:24:11 +0000 (15:24 +0200)
arch/ppc/mpc55xx/drivers/Lin.c
boards/board_common.mk
boards/mpc5516it/build_config.mk
communication/Lin/LinIf.c
communication/Lin/LinSM.c
include/LinSM.h

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