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
19 #if defined(USE_DET)
\r
25 #include "LinIf_Cbk.h"
\r
31 #define LIN_MAX_MSG_LENGTH 8
\r
33 #define LINFLEX(exp) (volatile struct LINFLEX_tag *)(0xFFE40000 + (0x4000 * exp))
\r
35 /* LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT. */
\r
36 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;
\r
38 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];
\r
40 /* static buffers, holds one frame at a time */
\r
41 static uint8 LinBufRx[LIN_CONTROLLER_CNT][LIN_MAX_MSG_LENGTH];
\r
43 typedef volatile union {
\r
50 vuint16_t RBSY:1; // LCH vuint16_t RXBUSY:1;
\r
51 vuint16_t RPS:1; // LCH vuint16_t RDI:1;
\r
59 } LinSRtype; /* LINFLEX LIN Status Register */
\r
61 typedef volatile union {
\r
76 } LinESRType; /* LINFLEX LIN Error Status Register */
\r
79 /* Development error macros. */
\r
80 #if ( LIN_DEV_ERROR_DETECT == STD_ON )
\r
81 #define VALIDATE(_exp,_api,_err ) \
\r
83 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
87 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
89 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
93 #define VALIDATE(_exp,_api,_err )
\r
94 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
97 static void ResyncDriver(uint8 Channel)
\r
100 /* volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel); */
\r
101 /* In case we need to re-init or re-sync driver because of error or hangup it should be done here */
\r
105 void LinInterruptRx(uint8 Channel)
\r
107 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
109 if (1 == LINFLEXHw->LINSR.B.DRF) {
\r
111 LINFLEXHw->LINSR.B.DRF = 1;
\r
113 if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
114 /* receive complete */
\r
115 LinChannelStatus[Channel] = LIN_RX_OK;
\r
118 /* Other interrupt cause */
\r
119 LINFLEXHw->LINSR.R = 0xffffffff;
\r
120 if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
121 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
126 void LinInterruptTx(uint8 Channel)
\r
128 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
130 if (1 == LINFLEXHw->LINSR.B.DTF) {
\r
132 LINFLEXHw->LINSR.B.DTF = 1;
\r
134 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
135 /* transmit complete */
\r
136 LinChannelStatus[Channel] = LIN_TX_OK;
\r
139 /* Other interrupt cause */
\r
140 LINFLEXHw->LINSR.R = 0xffffffff;
\r
141 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
142 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
147 void LinInterruptErr(uint8 Channel)
\r
149 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
151 /* Error handling */
\r
152 static uint32 errCnt=0;
\r
154 if(LinChannelStatus[Channel]==LIN_RX_BUSY){
\r
155 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
156 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){
\r
157 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
161 LINFLEXHw->LINESR.R=0xffffffff;
\r
164 static void LinInterruptRxA(){LinInterruptRx(LIN_CTRL_A);}
\r
165 static void LinInterruptTxA(){LinInterruptTx(LIN_CTRL_A);}
\r
166 static void LinInterruptErrA(){LinInterruptErr(LIN_CTRL_A);}
\r
168 static void LinInterruptRxB(){LinInterruptRx(LIN_CTRL_B);}
\r
169 static void LinInterruptTxB(){LinInterruptTx(LIN_CTRL_B);}
\r
170 static void LinInterruptErrB(){LinInterruptErr(LIN_CTRL_B);}
\r
172 #if defined (CFG_MPC560XB)
\r
173 static void LinInterruptRxC(){LinInterruptRx(LIN_CTRL_C);}
\r
174 static void LinInterruptTxC(){LinInterruptTx(LIN_CTRL_C);}
\r
175 static void LinInterruptErrC(){LinInterruptErr(LIN_CTRL_C);}
\r
177 static void LinInterruptRxD(){LinInterruptRx(LIN_CTRL_D);}
\r
178 static void LinInterruptTxD(){LinInterruptTx(LIN_CTRL_D);}
\r
179 static void LinInterruptErrD(){LinInterruptErr(LIN_CTRL_D);}
\r
182 #if defined (CFG_MPC5606B)
\r
183 static void LinInterruptRxE(){LinInterruptRx(LIN_CTRL_E);}
\r
184 static void LinInterruptTxE(){LinInterruptTx(LIN_CTRL_E);}
\r
185 static void LinInterruptErrE(){LinInterruptErr(LIN_CTRL_E);}
\r
187 static void LinInterruptRxF(){LinInterruptRx(LIN_CTRL_F);}
\r
188 static void LinInterruptTxF(){LinInterruptTx(LIN_CTRL_F);}
\r
189 static void LinInterruptErrF(){LinInterruptErr(LIN_CTRL_F);}
\r
191 static void LinInterruptRxG(){LinInterruptRx(LIN_CTRL_G);}
\r
192 static void LinInterruptTxG(){LinInterruptTx(LIN_CTRL_G);}
\r
193 static void LinInterruptErrG(){LinInterruptErr(LIN_CTRL_G);}
\r
195 static void LinInterruptRxH(){LinInterruptRx(LIN_CTRL_H);}
\r
196 static void LinInterruptTxH(){LinInterruptTx(LIN_CTRL_H);}
\r
197 static void LinInterruptErrH(){LinInterruptErr(LIN_CTRL_H);}
\r
200 void Lin_Init( const Lin_ConfigType* Config )
\r
205 VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );
\r
206 /* VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER ); */
\r
208 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
210 /* LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into
\r
211 * state LIN_CH_UNINIT. */
\r
212 LinChannelStatus[i] = LIN_CH_UNINIT;
\r
215 /* LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT
\r
216 * to LIN_INIT when the function Lin_Init is called. */
\r
217 LinDriverStatus = LIN_INIT;
\r
222 LinDriverStatus = LIN_UNINIT;
\r
225 void Lin_WakeupValidation( void )
\r
230 void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config )
\r
232 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
238 VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
239 VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );
\r
240 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
242 /* Install the interrupt */
\r
245 ISR_INSTALL_ISR2("LinIsrRxA", LinInterruptRxA, (IrqType)(LINFLEX_0_RXI),LIN_PRIO, 0);
\r
246 ISR_INSTALL_ISR2("LinIsrTxA", LinInterruptTxA, (IrqType)(LINFLEX_0_TXI),LIN_PRIO, 0);
\r
247 ISR_INSTALL_ISR2("LinIsrErrA", LinInterruptErrA, (IrqType)(LINFLEX_0_ERR),LIN_PRIO, 0);
\r
250 ISR_INSTALL_ISR2("LinIsrRxB", LinInterruptRxB, (IrqType)(LINFLEX_1_RXI),LIN_PRIO, 0);
\r
251 ISR_INSTALL_ISR2("LinIsrTxB", LinInterruptTxB, (IrqType)(LINFLEX_1_TXI),LIN_PRIO, 0);
\r
252 ISR_INSTALL_ISR2("LinIsrErrB", LinInterruptErrB, (IrqType)(LINFLEX_1_ERR),LIN_PRIO, 0);
\r
254 #if defined (CFG_MPC560XB)
\r
256 ISR_INSTALL_ISR2("LinIsrRxC", LinInterruptRxC, (IrqType)(LINFLEX_2_RXI),LIN_PRIO, 0);
\r
257 ISR_INSTALL_ISR2("LinIsrTxC", LinInterruptTxC, (IrqType)(LINFLEX_2_TXI),LIN_PRIO, 0);
\r
258 ISR_INSTALL_ISR2("LinIsrErrC", LinInterruptErrC, (IrqType)(LINFLEX_2_ERR),LIN_PRIO, 0);
\r
261 ISR_INSTALL_ISR2("LinIsrRxD", LinInterruptRxD, (IrqType)(LINFLEX_3_RXI),LIN_PRIO, 0);
\r
262 ISR_INSTALL_ISR2("LinIsrTxD", LinInterruptTxD, (IrqType)(LINFLEX_3_TXI),LIN_PRIO, 0);
\r
263 ISR_INSTALL_ISR2("LinIsrErrD", LinInterruptErrD, (IrqType)(LINFLEX_3_ERR),LIN_PRIO, 0);
\r
266 #if defined (CFG_MPC5606B)
\r
268 ISR_INSTALL_ISR2("LinIsrRxE", LinInterruptRxE, (IrqType)(LINFLEX_4_RXI),LIN_PRIO, 0);
\r
269 ISR_INSTALL_ISR2("LinIsrTxE", LinInterruptTxE, (IrqType)(LINFLEX_4_TXI),LIN_PRIO, 0);
\r
270 ISR_INSTALL_ISR2("LinIsrErrE", LinInterruptErrE, (IrqType)(LINFLEX_4_ERR),LIN_PRIO, 0);
\r
273 ISR_INSTALL_ISR2("LinIsrRxF", LinInterruptRxF, (IrqType)(LINFLEX_5_RXI),LIN_PRIO, 0);
\r
274 ISR_INSTALL_ISR2("LinIsrTxF", LinInterruptTxF, (IrqType)(LINFLEX_5_TXI),LIN_PRIO, 0);
\r
275 ISR_INSTALL_ISR2("LinIsrErrF", LinInterruptErrF, (IrqType)(LINFLEX_5_ERR),LIN_PRIO, 0);
\r
278 ISR_INSTALL_ISR2("LinIsrRxG", LinInterruptRxG, (IrqType)(LINFLEX_6_RXI),LIN_PRIO, 0);
\r
279 ISR_INSTALL_ISR2("LinIsrTxG", LinInterruptTxG, (IrqType)(LINFLEX_6_TXI),LIN_PRIO, 0);
\r
280 ISR_INSTALL_ISR2("LinIsrErrG", LinInterruptErrG, (IrqType)(LINFLEX_6_ERR),LIN_PRIO, 0);
\r
283 ISR_INSTALL_ISR2("LinIsrRxH", LinInterruptRxH, (IrqType)(LINFLEX_7_RXI),LIN_PRIO, 0);
\r
284 ISR_INSTALL_ISR2("LinIsrTxH", LinInterruptTxH, (IrqType)(LINFLEX_7_TXI),LIN_PRIO, 0);
\r
285 ISR_INSTALL_ISR2("LinIsrErrH", LinInterruptErrH, (IrqType)(LINFLEX_7_ERR),LIN_PRIO, 0);
\r
293 /* configure and enable channel */
\r
294 LINFLEXHw->LINCR1.B.INIT = 1; /* Go to init mode */
\r
295 LINFLEXHw->LINCR1.R = 1; /* Clear all */
\r
296 LINFLEXHw->LINCR1.B.MBL = 3; /* 13 bit synch */
\r
297 LINFLEXHw->LINCR1.B.MME = 1; /* Master mode */
\r
298 LINFLEXHw->LINCR1.B.CCD = 0;
\r
299 LINFLEXHw->LINCR1.B.CFD = 0;
\r
300 LINFLEXHw->LINCR1.B.LASE = 0;
\r
301 LINFLEXHw->LINCR1.B.AWUM = 0;
\r
302 LINFLEXHw->LINCR1.B.BF = 0;
\r
303 LINFLEXHw->LINCR1.B.SLFM = 0;
\r
304 LINFLEXHw->LINCR1.B.LBKM = 0;
\r
305 LINFLEXHw->LINCR1.B.SBDT = 0;
\r
306 LINFLEXHw->LINCR1.B.RBLM = 0;
\r
307 LINFLEXHw->LINCR1.B.SLEEP = 0;
\r
309 LINFLEXHw->LINIER.R = 0; /* Reset all bits */
\r
310 LINFLEXHw->LINIER.B.BEIE = 1; /* Bit error */
\r
311 LINFLEXHw->LINIER.B.CEIE = 1; /* Checksum error */
\r
312 LINFLEXHw->LINIER.B.HEIE = 1; /* Header error */
\r
313 LINFLEXHw->LINIER.B.BOIE = 1; /* Buffer overrun error */
\r
314 LINFLEXHw->LINIER.B.FEIE = 1; /* Framing error */
\r
316 LINFLEXHw->LINIER.B.DRIE = 1; /* Data Reception Complete */
\r
317 LINFLEXHw->LINIER.B.DTIE = 1; /* Data Transmitted */
\r
320 * Tx/ Rx baud = fperiph_set_1_clk / (16 × LFDIV)
\r
322 * To program LFDIV = 25.62d,
\r
323 * LINFBRR = 16 × 0.62 = 9.92, nearest real number 10d = 0xA
\r
324 * LINIBRR = mantissa (25.620d) = 25d = 0x19
\r
326 float lfdiv = (float)McuE_GetPeripheralClock( PERIPHERAL_CLOCK_LIN_A) / (float)((16*Config->LinChannelBaudRate));
\r
328 LINFLEXHw->LINFBRR.B.DIV_F = (uint8)((lfdiv - (uint32)lfdiv) * 16); /* Fraction bits */
\r
329 LINFLEXHw->LINIBRR.B.DIV_M = (uint16)lfdiv; /* Integer bits */
\r
331 LINFLEXHw->LINCR2.R = 0; /* Reset all bits */
\r
332 LINFLEXHw->LINCR2.B.IOBE = 1; /* Idle on bit error */
\r
333 LINFLEXHw->LINCR2.B.IOPE = 1; /* Idle on parity error */
\r
336 LINFLEXHw->LINSR.R = 0xffffffff; /* Reset all bits */
\r
337 LINFLEXHw->LINESR.R = 0xffffffff; /* Reset all bits */
\r
339 LINFLEXHw->LINCR1.B.INIT = 0; /* Go to normal mode */
\r
341 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
344 void Lin_DeInitChannel( uint8 Channel )
\r
346 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
347 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
349 /* LIN178: The function Lin_DeInitChannel shall only be executable when the LIN
\r
350 * channel state-machine is in state LIN_CH_OPERATIONAL. */
\r
351 if(LinChannelStatus[Channel] != LIN_CH_UNINIT){
\r
353 LINFLEXHw->LINCR1.R = 0; /* Reset all bits */
\r
354 LINFLEXHw->LINIER.R = 0; /* Reset all bits */
\r
355 LINFLEXHw->LINSR.R = 0xffffffff; /* Reset all bits */
\r
356 LINFLEXHw->LINESR.R = 0xffffffff; /* Reset all bits */
\r
358 LinChannelStatus[Channel]=LIN_CH_UNINIT;
\r
362 Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
364 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
369 if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||
\r
370 LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR)
\r
372 ResyncDriver(Channel);
\r
373 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
375 Irq_Restore(state);
\r
378 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
379 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
380 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
381 /* Send header is used to wake the net in this implementation(no actual header is sent */
\r
382 /* VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK); */
\r
383 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
385 /* Calculate the time out value for the frame.(10 × NDATA + 45) × 1.4 according to LIN1.3 */
\r
386 uint16 timeOutValue = (uint16)( ( ( 10 * PduInfoPtr->DI + 45 ) * 14 ) / 10);
\r
388 LINFLEXHw->BIDR.R = 0; /* Clear reg */
\r
391 if (PduInfoPtr->Cs != LIN_ENHANCED_CS){ /*Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum */
\r
392 LINFLEXHw->BIDR.B.CCS = 1;
\r
395 LINFLEXHw->BIDR.B.DFL = PduInfoPtr->DI - 1;
\r
398 LINFLEXHw->BIDR.B.ID = PduInfoPtr->Pid; /* Without parity bit */
\r
401 if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)
\r
403 LINFLEXHw->BIDR.B.DIR = 1;
\r
405 /* write to buffer reg */
\r
406 for(int i = 0; i < PduInfoPtr->DI;i++)
\r
408 /* convenient with freescale reg file */
\r
412 LINFLEXHw->BDRL.B.DATA0 = PduInfoPtr->SduPtr[0];
\r
415 LINFLEXHw->BDRL.B.DATA1 = PduInfoPtr->SduPtr[1];
\r
418 LINFLEXHw->BDRL.B.DATA2 = PduInfoPtr->SduPtr[2];
\r
421 LINFLEXHw->BDRL.B.DATA3 = PduInfoPtr->SduPtr[3];
\r
424 LINFLEXHw->BDRM.B.DATA4 = PduInfoPtr->SduPtr[4];
\r
427 LINFLEXHw->BDRM.B.DATA5 = PduInfoPtr->SduPtr[5];
\r
430 LINFLEXHw->BDRM.B.DATA6 = PduInfoPtr->SduPtr[6];
\r
433 LINFLEXHw->BDRM.B.DATA7 = PduInfoPtr->SduPtr[7];
\r
438 LinChannelStatus[Channel]=LIN_TX_BUSY;
\r
442 LinChannelStatus[Channel]=LIN_RX_BUSY;
\r
445 /* Request transmission of header */
\r
446 LINFLEXHw->LINCR2.B.HTRQ = 1;
\r
451 Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
453 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
454 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
455 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
456 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
457 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
459 /* The response is sent from within the header in this implementation since this is a master only implementation */
\r
463 Std_ReturnType Lin_GoToSleep( uint8 Channel )
\r
465 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
467 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
468 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
469 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
470 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
472 LINFLEXHw->LINCR1.B.SLEEP = 1;
\r
474 LINFLEXHw->LINIER.B.WUIE = 1; /* enable wake-up irq */
\r
476 LinChannelStatus[Channel]=LIN_CH_SLEEP;
\r
481 Std_ReturnType Lin_GoToSleepInternal( uint8 Channel )
\r
483 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
484 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
485 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
486 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
487 Lin_GoToSleep(Channel);
\r
491 Std_ReturnType Lin_WakeUp( uint8 Channel )
\r
493 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
495 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
496 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
497 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
498 VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
500 /* Disable wake interrupt */
\r
501 LINFLEXHw->LINIER.B.WUIE = 0;
\r
502 /* Clear sleep bit */
\r
503 LINFLEXHw->LINCR1.B.SLEEP = 0;
\r
505 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
509 static void CopyToBuffer(uint8 *buf, volatile struct LINFLEX_tag * LINFLEXHw)
\r
511 for(int i = 0; i < 8;i++)
\r
513 /* convenient with freescale reg file */
\r
517 buf[0] = LINFLEXHw->BDRL.B.DATA0;
\r
520 buf[1] = LINFLEXHw->BDRL.B.DATA1;
\r
523 buf[2] = LINFLEXHw->BDRL.B.DATA2;
\r
526 buf[3] = LINFLEXHw->BDRL.B.DATA3;
\r
529 buf[4] = LINFLEXHw->BDRM.B.DATA4;
\r
532 buf[5] = LINFLEXHw->BDRM.B.DATA5;
\r
535 buf[6] = LINFLEXHw->BDRM.B.DATA6;
\r
538 buf[7] = LINFLEXHw->BDRM.B.DATA7;
\r
544 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )
\r
546 volatile struct LINFLEX_tag * LINFLEXHw = LINFLEX(Channel);
\r
548 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, LIN_NOT_OK);
\r
549 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, LIN_NOT_OK);
\r
550 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, LIN_NOT_OK);
\r
551 VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, LIN_NOT_OK);
\r
555 Lin_StatusType res = LinChannelStatus[Channel];
\r
556 /* We can only check for valid sdu ptr when LIN_RX_OK */
\r
557 if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
558 CopyToBuffer(LinBufRx[Channel], LINFLEXHw);
\r
559 *Lin_SduPtr = LinBufRx[Channel];
\r
560 if(LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
561 ResyncDriver(Channel);
\r
563 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
564 } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
565 if(LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
566 ResyncDriver(Channel);
\r
568 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
570 Irq_Restore(state);
\r