1 /* -------------------------------- Arctic Core ------------------------------
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
6 * This source code is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by the
8 * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * -------------------------------- Arctic Core ------------------------------*/
24 #include "LinIf_Cbk.h"
\r
25 #include "mpc55xx.h"
\r
30 #include "LinIf_Cbk.h"
\r
32 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))
\r
34 // LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT.
\r
35 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;
\r
37 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];
\r
38 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];
\r
40 static uint8* TxPtr[LIN_CONTROLLER_CNT];
\r
41 static uint8* TxCurrPtr[LIN_CONTROLLER_CNT];
\r
42 static uint8 TxSize[LIN_CONTROLLER_CNT];
\r
43 static uint8* RxPtr[LIN_CONTROLLER_CNT];
\r
44 static uint8* RxCurrPtr[LIN_CONTROLLER_CNT];
\r
45 static uint8 RxSize[LIN_CONTROLLER_CNT];
\r
47 /* Development error macros. */
\r
48 #if ( LIN_DEV_ERROR_DETECT == STD_ON )
\r
49 #define VALIDATE(_exp,_api,_err ) \
\r
51 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
55 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
57 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
61 #define VALIDATE(_exp,_api,_err )
\r
62 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
65 typedef volatile union
\r
94 typedef volatile union {
\r
120 } LinSRtype; /* Status Register */
\r
123 void LinInterrupt(uint8 Channel)
\r
125 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
129 sr.R = esciHw->SR.R;
\r
133 if(sr.B.TXRDY == 1)
\r
137 if(sr.B.RXRDY == 1)
\r
161 esciHw->SR.R = tmp.R;
\r
162 esciHw->LCR.B.TXIE = 0; // Always disable Tx Interrupt
\r
165 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
166 // Maybe transmit next byte
\r
167 if (TxSize[Channel] > 0 && sr.B.TXRDY) {
\r
168 tmpLtr.R = 0; // Clear
\r
169 tmpLtr.B4.T = *TxCurrPtr[Channel];
\r
170 TxCurrPtr[Channel]++; TxSize[Channel]--;
\r
171 esciHw->LCR.B.TXIE = 1; // Enable tx irq
\r
172 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
176 //Transmission complete
\r
177 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
178 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
179 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
181 LinChannelStatus[Channel] = LIN_TX_OK;
\r
183 esciHw->LCR.B.TXIE = 0; // Disable tx irq
\r
186 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
187 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
188 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
190 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
195 else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
196 // Maybe receive next byte
\r
197 if (RxSize[Channel] > 0 && sr.B.RXRDY) {
\r
198 tmpLtr.R = esciHw->LRR.R;
\r
199 *RxCurrPtr[Channel] = tmpLtr.B5.D;
\r
200 RxCurrPtr[Channel]++; RxSize[Channel]--;
\r
201 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){
\r
203 LinChannelStatus[Channel] = LIN_RX_OK;
\r
204 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt
\r
205 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt
\r
210 if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||
\r
211 sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {
\r
212 static uint32 errCnt=0;
\r
214 if(LinChannelStatus[Channel]==LIN_RX_BUSY){
\r
215 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
216 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){
\r
217 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
220 // Resynchronize driver and clear all errors
\r
221 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared
\r
222 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared
\r
224 esciHw->SR.R=0xffffffff;
\r
228 static void LinInterruptA()
\r
230 LinInterrupt(LIN_CTRL_A);
\r
232 static void LinInterruptB()
\r
234 LinInterrupt(LIN_CTRL_B);
\r
236 static void LinInterruptC()
\r
238 LinInterrupt(LIN_CTRL_C);
\r
240 static void LinInterruptD()
\r
242 LinInterrupt(LIN_CTRL_D);
\r
244 static void LinInterruptE()
\r
246 LinInterrupt(LIN_CTRL_E);
\r
248 static void LinInterruptF()
\r
250 LinInterrupt(LIN_CTRL_F);
\r
252 static void LinInterruptG()
\r
254 LinInterrupt(LIN_CTRL_G);
\r
256 static void LinInterruptH()
\r
258 LinInterrupt(LIN_CTRL_H);
\r
261 static const void const * aIntFnc[] = {LinInterruptA,
\r
270 void Lin_Init( const Lin_ConfigType* Config )
\r
274 VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );
\r
275 //VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
277 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
279 // LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into
\r
280 // state LIN_CH_UNINIT.
\r
281 LinChannelStatus[i] = LIN_CH_UNINIT;
\r
282 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;
\r
291 //LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT
\r
292 // to LIN_INIT when the function Lin_Init is called.
\r
293 LinDriverStatus = LIN_INIT;
\r
299 // Make sure all allocated buffers are freed
\r
300 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
302 if (RxPtr[i] != 0) {
\r
305 if (TxPtr[i] != 0) {
\r
309 LinDriverStatus = LIN_UNINIT;
\r
312 void Lin_WakeupValidation( void )
\r
317 void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config )
\r
319 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
325 VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
326 VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );
\r
327 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
329 // Install the interrupt
\r
332 IntCtrl_InstallVector(aIntFnc[Channel],SCI_E_COMB + Channel,LIN_PRIO,CPU_Z1);
\r
336 IntCtrl_InstallVector(aIntFnc[Channel],SCI_A_COMB + Channel,LIN_PRIO,CPU_Z1);
\r
339 esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */
\r
341 esciHw->CR1.B.RE = 1;
\r
342 esciHw->CR1.B.M = 0; /* The data format bit ESCIx_CR1[M], is set to 0 (8 data bits), and the parity is disabled (PE = 0).*/
\r
343 esciHw->CR1.B.PE = 0;
\r
344 esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/
\r
345 esciHw->CR1.B.TCIE = 0;
\r
346 esciHw->CR1.B.RIE = 0;
\r
347 /* Set up ESCIx_CR1 for LIN */
\r
349 * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.
\r
350 * The formula for calculating the baud rate is:
\r
352 * eSCI system clock
\r
353 * SCI baud rate = -----------------------
\r
356 * where SBR can contain a value from 1 to 8191. After reset, the baud generator
\r
357 * is disabled until the TE bit or the RE bit is set for the first time. The baud
\r
358 * rate generator is disabled when SBR = 0x0.
\r
360 esciHw->CR1.B.SBR = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);
\r
361 esciHw->LCR.B.LIN = 1; /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/
\r
363 esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long
\r
364 (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */
\r
366 esciHw->LCR.B.LDBG = 0;/*Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop
\r
367 further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/
\r
368 esciHw->LCR.B.STIE = 1; // Enable some fault irq's
\r
369 esciHw->LCR.B.PBIE = 1;
\r
370 esciHw->LCR.B.CKIE = 1;
\r
371 esciHw->LCR.B.OFIE = 1;
\r
373 esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/
\r
374 esciHw->CR2.B.BSTP = 1;
\r
376 esciHw->CR2.B.FBR = 1; // Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set;
\r
377 esciHw->CR2.B.BESM13 = 1; // normally it will be used with ESCIx_CR2[BESM13] = 1.*/
\r
379 /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */
\r
380 /* TODO Should we have these interrupts or check the status register? */
\r
381 /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves
\r
384 esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */
\r
386 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
389 void Lin_DeInitChannel( uint8 Channel )
\r
391 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
392 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
394 //LIN178: The function Lin_DeInitChannel shall only be executable when the LIN
\r
395 //channel state-machine is in state LIN_CH_OPERATIONAL.
\r
396 if(LinChannelStatus[Channel] != LIN_CH_UNINIT){
\r
397 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */
\r
399 if (RxPtr[Channel] != 0) {
\r
400 free(RxPtr[Channel]);
\r
402 if (TxPtr[Channel] != 0) {
\r
403 free(TxPtr[Channel]);
\r
406 LinChannelStatus[Channel]=LIN_CH_UNINIT;
\r
410 Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
414 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
417 imask_t state = McuE_EnterCriticalSection();
\r
418 if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||
\r
419 LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
420 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
421 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared
\r
422 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared
\r
423 esciHw->LCR.B.TXIE = 0; // Disable tx irq
\r
424 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt
\r
425 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt
\r
427 esciHw->SR.R=0xffffffff;
\r
429 McuE_ExitCriticalSection(state);
\r
432 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
433 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
434 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
435 //Send header is used to wake the net in this implementation(no actual header is sent
\r
436 // VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
437 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
440 tmpLtr.R = 0; // Clear
\r
441 tmpLtr.B1.PID = PduInfoPtr->Pid;
\r
442 tmp.R = 0; // Clear ready flag before send
\r
444 esciHw->SR.R = tmp.R;
\r
445 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
448 tmpLtr.R = 0; // Clear
\r
449 tmpLtr.B2.L = PduInfoPtr->DI;
\r
450 tmp.R = 0; // Clear ready flag before send
\r
452 esciHw->SR.R = tmp.R;
\r
453 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
456 tmpLtr.R = 0; // Clear
\r
457 if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ //Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum
\r
458 tmpLtr.B3.HDCHK = 1;
\r
460 tmpLtr.B3.CSUM = 1; // Append checksum to TX frame or verify for a RX
\r
461 tmpLtr.B3.CRC = 0; // Append two CRC bytes(Not LIN standard)
\r
462 if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)
\r
464 LinChannelStatus[Channel]=LIN_TX_BUSY;
\r
465 tmpLtr.B3.TX = 1; // TX frame
\r
466 tmpLtr.B3.TN = 0; // Timeout not valid for TX
\r
467 tmp.R = 0; // Clear ready flag before send
\r
469 esciHw->SR.R = tmp.R;
\r
470 esciHw->LCR.B.FCIE = 1; // // Enable frame complete
\r
471 esciHw->LCR.B.TXIE = 1; // Enable tx irq
\r
472 if (PduInfoPtr->DI > 0){
\r
473 if (TxPtr[Channel] != 0) {
\r
474 free(TxPtr[Channel]);
\r
476 TxCurrPtr[Channel] = TxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);
\r
477 TxSize[Channel] = PduInfoPtr->DI;
\r
478 memcpy(TxPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);
\r
480 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
486 LinChannelStatus[Channel]=LIN_RX_BUSY;
\r
487 if (RxPtr[Channel] != 0) {
\r
488 free(RxPtr[Channel]);
\r
490 RxCurrPtr[Channel] = RxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);
\r
491 RxSize[Channel] = PduInfoPtr->DI;
\r
493 tmpLtr.B3.TX = 0; // RX frame
\r
494 tmpLtr.B3.TN = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3
\r
495 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
497 tmpLtr.R = 0; // Clear
\r
498 tmpLtr.B4.T = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3
\r
499 tmp.R = 0; // Clear ready flag before send
\r
501 esciHw->SR.R = tmp.R;
\r
502 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
503 esciHw->LCR.B.FCIE = 1; // Enable frame complete
\r
504 esciHw->LCR.B.RXIE = 1; // Enable rx irq
\r
510 Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
512 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
513 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
514 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
515 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
516 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
518 // The response is sent from within the header in this implementation since this is a master only implementation
\r
522 Std_ReturnType Lin_GoToSleep( uint8 Channel )
\r
524 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
525 Lin_PduType PduInfo;
\r
526 uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
\r
528 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
529 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
530 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
531 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
533 if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){
\r
534 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;
\r
536 PduInfo.Cs = LIN_CLASSIC_CS;
\r
537 PduInfo.Pid = 0x3C;
\r
538 PduInfo.SduPtr = data;
\r
540 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
542 Lin_SendHeader(Channel, &PduInfo);
\r
543 Lin_SendResponse(Channel, &PduInfo);
\r
545 esciHw->LCR.B.WUIE = 1; // enable wake-up irq
\r
550 Std_ReturnType Lin_GoToSleepInternal( uint8 Channel )
\r
552 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
553 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
554 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
555 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
556 Lin_GoToSleep(Channel);
\r
560 Std_ReturnType Lin_WakeUp( uint8 Channel )
\r
562 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
563 Lin_PduType PduInfo;
\r
564 uint8 data[2] = {0xFF,0xFF};
\r
566 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
567 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
568 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
569 VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
571 esciHw->LCR.B.WUIE = 0; // disable wake-up irq
\r
572 esciHw->LCR.B.WU = 1; // send wake up
\r
573 esciHw->LCR.B.WUD0 = 1; // delimiter time
\r
574 esciHw->LCR.B.WUD1 = 0; // delimiter time
\r
576 // Just send any header to trigger the wakeup signal
\r
577 PduInfo.Cs = LIN_CLASSIC_CS;
\r
578 PduInfo.Pid = 0x00;
\r
579 PduInfo.SduPtr = data;
\r
581 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
582 Lin_SendHeader(Channel, &PduInfo);
\r
584 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
588 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )
\r
590 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
591 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
592 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
593 VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
595 imask_t state = McuE_EnterCriticalSection();
\r
596 Lin_StatusType res = LinChannelStatus[Channel];
\r
597 // We can only check for valid sdu ptr when LIN_RX_OK
\r
598 if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
599 *Lin_SduPtr = RxPtr[Channel];
\r
600 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
601 } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
602 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
604 McuE_ExitCriticalSection(state);
\r