* 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
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
} 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
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
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
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
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
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
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
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
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
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
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
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
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
\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