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
24 #include "LinIf_Cbk.h"
\r
25 #include "mpc55xx.h"
\r
30 #include "LinIf_Cbk.h"
\r
31 #if defined(USE_KERNEL)
\r
36 #define ESCI(exp) (volatile struct ESCI_tag *)(0xFFFA0000 + (0x4000 * exp))
\r
38 // LIN145: Reset -> LIN_UNINIT: After reset, the Lin module shall set its state to LIN_UNINIT.
\r
39 static Lin_DriverStatusType LinDriverStatus = LIN_UNINIT;
\r
41 static Lin_StatusType LinChannelStatus[LIN_CONTROLLER_CNT];
\r
42 static Lin_StatusType LinChannelOrderedStatus[LIN_CONTROLLER_CNT];
\r
44 static uint8* TxPtr[LIN_CONTROLLER_CNT];
\r
45 static uint8* TxCurrPtr[LIN_CONTROLLER_CNT];
\r
46 static uint8 TxSize[LIN_CONTROLLER_CNT];
\r
47 static uint8* RxPtr[LIN_CONTROLLER_CNT];
\r
48 static uint8* RxCurrPtr[LIN_CONTROLLER_CNT];
\r
49 static uint8 RxSize[LIN_CONTROLLER_CNT];
\r
51 /* Development error macros. */
\r
52 #if ( LIN_DEV_ERROR_DETECT == STD_ON )
\r
53 #define VALIDATE(_exp,_api,_err ) \
\r
55 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
59 #define VALIDATE_W_RV(_exp,_api,_err,_rv ) \
\r
61 Det_ReportError(MODULE_ID_LIN,0,_api,_err); \
\r
65 #define VALIDATE(_exp,_api,_err )
\r
66 #define VALIDATE_W_RV(_exp,_api,_err,_rv )
\r
69 typedef volatile union
\r
98 typedef volatile union {
\r
124 } LinSRtype; /* Status Register */
\r
127 void LinInterrupt(uint8 Channel)
\r
129 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
133 sr.R = esciHw->SR.R;
\r
137 if(sr.B.TXRDY == 1)
\r
141 if(sr.B.RXRDY == 1)
\r
165 esciHw->SR.R = tmp.R;
\r
166 esciHw->LCR.B.TXIE = 0; // Always disable Tx Interrupt
\r
169 if (LinChannelStatus[Channel]==LIN_TX_BUSY) {
\r
170 // Maybe transmit next byte
\r
171 if (TxSize[Channel] > 0 && sr.B.TXRDY) {
\r
172 tmpLtr.R = 0; // Clear
\r
173 tmpLtr.B4.T = *TxCurrPtr[Channel];
\r
174 TxCurrPtr[Channel]++; TxSize[Channel]--;
\r
175 esciHw->LCR.B.TXIE = 1; // Enable tx irq
\r
176 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
180 //Transmission complete
\r
181 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
182 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
183 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
185 LinChannelStatus[Channel] = LIN_TX_OK;
\r
187 esciHw->LCR.B.TXIE = 0; // Disable tx irq
\r
190 if (LinChannelOrderedStatus[Channel]==LIN_CH_SLEEP){
\r
191 LinChannelStatus[Channel] = LIN_CH_SLEEP;
\r
192 LinChannelOrderedStatus[Channel]=LIN_CH_OPERATIONAL;
\r
194 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
199 else if (LinChannelStatus[Channel]==LIN_RX_BUSY) {
\r
200 // Maybe receive next byte
\r
201 if (RxSize[Channel] > 0 && sr.B.RXRDY) {
\r
202 tmpLtr.R = esciHw->LRR.R;
\r
203 *RxCurrPtr[Channel] = tmpLtr.B5.D;
\r
204 RxCurrPtr[Channel]++; RxSize[Channel]--;
\r
205 } else if (RxSize[Channel] == 0 && sr.B.FRC == 1){
\r
207 LinChannelStatus[Channel] = LIN_RX_OK;
\r
208 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt
\r
209 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt
\r
214 if(sr.B.OR || sr.B.NF || sr.B.FE || sr.B.PF || sr.B.BERR || sr.B.STO || sr.B.PBERR ||
\r
215 sr.B.CERR || sr.B.CKERR || sr.B.OVFL) {
\r
216 static uint32 errCnt=0;
\r
218 if(LinChannelStatus[Channel]==LIN_RX_BUSY){
\r
219 LinChannelStatus[Channel] = LIN_RX_ERROR;
\r
220 }else if (LinChannelStatus[Channel]==LIN_TX_BUSY){
\r
221 LinChannelStatus[Channel] = LIN_TX_ERROR;
\r
224 // Resynchronize driver and clear all errors
\r
225 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared
\r
226 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared
\r
228 esciHw->SR.R=0xffffffff;
\r
232 static void LinInterruptA()
\r
234 LinInterrupt(LIN_CTRL_A);
\r
236 static void LinInterruptB()
\r
238 LinInterrupt(LIN_CTRL_B);
\r
240 static void LinInterruptC()
\r
242 LinInterrupt(LIN_CTRL_C);
\r
244 static void LinInterruptD()
\r
246 LinInterrupt(LIN_CTRL_D);
\r
248 static void LinInterruptE()
\r
250 LinInterrupt(LIN_CTRL_E);
\r
252 static void LinInterruptF()
\r
254 LinInterrupt(LIN_CTRL_F);
\r
256 static void LinInterruptG()
\r
258 LinInterrupt(LIN_CTRL_G);
\r
260 static void LinInterruptH()
\r
262 LinInterrupt(LIN_CTRL_H);
\r
265 static const void const * aIntFnc[] = {LinInterruptA,
\r
274 void Lin_Init( const Lin_ConfigType* Config )
\r
278 VALIDATE( (LinDriverStatus == LIN_UNINIT), LIN_INIT_SERVICE_ID, LIN_E_STATE_TRANSITION );
\r
279 //VALIDATE( (Config!=0), LIN_INIT_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
281 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
283 // LIN171: On entering the state LIN_INIT, the Lin module shall set each channel into
\r
284 // state LIN_CH_UNINIT.
\r
285 LinChannelStatus[i] = LIN_CH_UNINIT;
\r
286 LinChannelOrderedStatus[i]=LIN_CH_OPERATIONAL;
\r
295 //LIN146: LIN_UNINIT -> LIN_INIT: The Lin module shall transition from LIN_UNINIT
\r
296 // to LIN_INIT when the function Lin_Init is called.
\r
297 LinDriverStatus = LIN_INIT;
\r
303 // Make sure all allocated buffers are freed
\r
304 for (i=0;i<LIN_CONTROLLER_CNT;i++)
\r
306 if (RxPtr[i] != 0) {
\r
309 if (TxPtr[i] != 0) {
\r
313 LinDriverStatus = LIN_UNINIT;
\r
316 void Lin_WakeupValidation( void )
\r
321 void Lin_InitChannel( uint8 Channel, const Lin_ChannelConfigType* Config )
\r
323 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
329 VALIDATE( (Config!=0), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_POINTER );
\r
330 VALIDATE( (LinDriverStatus != LIN_UNINIT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_UNINIT );
\r
331 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_INIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
333 // Install the interrupt
\r
336 #if defined(USE_KERNEL)
\r
338 tid = Os_Arc_CreateIsr(aIntFnc[Channel],LIN_PRIO,"Lin");
\r
339 Irq_AttachIsr2(tid,NULL,SCI_E_COMB + Channel);
\r
341 Irq_InstallVector(aIntFnc[Channel],SCI_E_COMB + Channel,LIN_PRIO,CPU_Z1);
\r
346 #if defined(USE_KERNEL)
\r
348 tid = Os_Arc_CreateIsr(aIntFnc[Channel],LIN_PRIO,"Lin");
\r
349 Irq_AttachIsr2(tid,NULL,SCI_A_COMB + Channel);
\r
351 Irq_InstallVector(aIntFnc[Channel],SCI_A_COMB + Channel,LIN_PRIO,CPU_Z1);
\r
355 esciHw->CR2.B.MDIS = 0;/* The module is enabled by writing the ESCIx_CR2[MDIS] bit to 0. */
\r
357 esciHw->CR1.B.RE = 1;
\r
358 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
359 esciHw->CR1.B.PE = 0;
\r
360 esciHw->CR1.B.TIE = 0; /*ESCIx_CR1[TIE], ESCIx_CR1[TCIE], ESCIx_CR1[RIE] interrupt enable bits should be inactive.*/
\r
361 esciHw->CR1.B.TCIE = 0;
\r
362 esciHw->CR1.B.RIE = 0;
\r
363 /* Set up ESCIx_CR1 for LIN */
\r
365 * SCI Baud Rate. Used by the counter to determine the baud rate of the eSCI.
\r
366 * The formula for calculating the baud rate is:
\r
368 * eSCI system clock
\r
369 * SCI baud rate = -----------------------
\r
372 * where SBR can contain a value from 1 to 8191. After reset, the baud generator
\r
373 * is disabled until the TE bit or the RE bit is set for the first time. The baud
\r
374 * rate generator is disabled when SBR = 0x0.
\r
376 esciHw->CR1.B.SBR = McuE_GetPeripheralClock(Config->LinClockRef)/(16*Config->LinChannelBaudRate);
\r
377 esciHw->LCR.B.LIN = 1; /* Instead, the LIN interrupts should be used.Switch eSCI to LIN mode (ESCIx_LCR[LIN] = 1).*/
\r
379 esciHw->CR2.B.BRK13 = 1;/* The LIN standard requires that the break character always be 13 bits long
\r
380 (ESCIx_CR2[BRK13] = 1). The eSCI will work with BRK13=0, but it will violate LIN 2.0. */
\r
382 esciHw->LCR.B.LDBG = 0;/*Normally, bit errors should cause the LIN FSM to reset, stop driving the bus immediately, and stop
\r
383 further DMA requests until the BERR flag has been cleared. Set ESCIx_LCR[LDBG] = 0,*/
\r
384 esciHw->LCR.B.STIE = 1; // Enable some fault irq's
\r
385 esciHw->LCR.B.PBIE = 1;
\r
386 esciHw->LCR.B.CKIE = 1;
\r
387 esciHw->LCR.B.OFIE = 1;
\r
389 esciHw->CR2.B.SBSTP = 1;/*ESCIx_CR2[SBSTP] = 1, and ESCIx_CR2[BSTP] = 1 to accomplish these functions.*/
\r
390 esciHw->CR2.B.BSTP = 1;
\r
392 esciHw->CR2.B.FBR = 1; // Fast bit error detection provides superior error checking, so ESCIx_CR2[FBR] should be set;
\r
393 esciHw->CR2.B.BESM13 = 1; // normally it will be used with ESCIx_CR2[BESM13] = 1.*/
\r
395 /* The error indicators NF, FE, BERR, STO, PBERR, CERR, CKERR, and OVFL should be enabled. */
\r
396 /* TODO Should we have these interrupts or check the status register? */
\r
397 /*Initially a wakeup character may need to be transmitted on the LIN bus, so that the LIN slaves
\r
400 esciHw->CR1.B.TE = 1; /* Both transmitter and receiver are enabled (ESCIx_CR1[TE] = 1, ESCIx_CR1[RE] = 1). */
\r
402 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
405 void Lin_DeInitChannel( uint8 Channel )
\r
407 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
408 VALIDATE( (Channel < LIN_CONTROLLER_CNT), LIN_DEINIT_CHANNEL_SERVICE_ID, LIN_E_INVALID_CHANNEL );
\r
410 //LIN178: The function Lin_DeInitChannel shall only be executable when the LIN
\r
411 //channel state-machine is in state LIN_CH_OPERATIONAL.
\r
412 if(LinChannelStatus[Channel] != LIN_CH_UNINIT){
\r
413 esciHw->CR2.B.MDIS = 1;/* The module is disabled by writing the ESCIx_CR2[MDIS] bit to 1. */
\r
415 if (RxPtr[Channel] != 0) {
\r
416 free(RxPtr[Channel]);
\r
418 if (TxPtr[Channel] != 0) {
\r
419 free(TxPtr[Channel]);
\r
422 LinChannelStatus[Channel]=LIN_CH_UNINIT;
\r
426 Std_ReturnType Lin_SendHeader( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
430 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
433 imask_t state = McuE_EnterCriticalSection();
\r
434 if(LinChannelStatus[Channel] == LIN_TX_BUSY || LinChannelStatus[Channel] == LIN_TX_ERROR ||
\r
435 LinChannelStatus[Channel] == LIN_RX_BUSY || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
436 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
437 esciHw->LCR.B.LRES = 1; // LIN Resynchronize. First set then cleared
\r
438 esciHw->LCR.B.LRES = 0; // LIN Resynchronize. First set then cleared
\r
439 esciHw->LCR.B.TXIE = 0; // Disable tx irq
\r
440 esciHw->LCR.B.RXIE = 0; // Disable Rx Interrupt
\r
441 esciHw->LCR.B.FCIE = 0; // Disable Rx Interrupt
\r
443 esciHw->SR.R=0xffffffff;
\r
445 McuE_ExitCriticalSection(state);
\r
448 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
449 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
450 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
451 //Send header is used to wake the net in this implementation(no actual header is sent
\r
452 // VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_HEADER_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
453 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_HEADER_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
456 tmpLtr.R = 0; // Clear
\r
457 tmpLtr.B1.PID = PduInfoPtr->Pid;
\r
458 tmp.R = 0; // Clear ready flag before send
\r
460 esciHw->SR.R = tmp.R;
\r
461 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
464 tmpLtr.R = 0; // Clear
\r
465 tmpLtr.B2.L = PduInfoPtr->DI;
\r
466 tmp.R = 0; // Clear ready flag before send
\r
468 esciHw->SR.R = tmp.R;
\r
469 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
472 tmpLtr.R = 0; // Clear
\r
473 if (PduInfoPtr->Cs == LIN_ENHANCED_CS){ //Frame identifiers 60 (0x3C) to 61 (0x3D) shall always use classic checksum
\r
474 tmpLtr.B3.HDCHK = 1;
\r
476 tmpLtr.B3.CSUM = 1; // Append checksum to TX frame or verify for a RX
\r
477 tmpLtr.B3.CRC = 0; // Append two CRC bytes(Not LIN standard)
\r
478 if (PduInfoPtr->Drc == LIN_MASTER_RESPONSE)
\r
480 LinChannelStatus[Channel]=LIN_TX_BUSY;
\r
481 tmpLtr.B3.TX = 1; // TX frame
\r
482 tmpLtr.B3.TN = 0; // Timeout not valid for TX
\r
483 tmp.R = 0; // Clear ready flag before send
\r
485 esciHw->SR.R = tmp.R;
\r
486 esciHw->LCR.B.FCIE = 1; // // Enable frame complete
\r
487 esciHw->LCR.B.TXIE = 1; // Enable tx irq
\r
488 if (PduInfoPtr->DI > 0){
\r
489 if (TxPtr[Channel] != 0) {
\r
490 free(TxPtr[Channel]);
\r
492 TxCurrPtr[Channel] = TxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);
\r
493 TxSize[Channel] = PduInfoPtr->DI;
\r
494 memcpy(TxPtr[Channel],PduInfoPtr->SduPtr,PduInfoPtr->DI);
\r
496 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
502 LinChannelStatus[Channel]=LIN_RX_BUSY;
\r
503 if (RxPtr[Channel] != 0) {
\r
504 free(RxPtr[Channel]);
\r
506 RxCurrPtr[Channel] = RxPtr[Channel] = (uint8 *)malloc(PduInfoPtr->DI);
\r
507 RxSize[Channel] = PduInfoPtr->DI;
\r
509 tmpLtr.B3.TX = 0; // RX frame
\r
510 tmpLtr.B3.TN = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3
\r
511 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
513 tmpLtr.R = 0; // Clear
\r
514 tmpLtr.B4.T = (10*PduInfoPtr->DI + 45)*1.4; // Timeout. (10 × NDATA + 45) × 1.4 according to LIN1.3
\r
515 tmp.R = 0; // Clear ready flag before send
\r
517 esciHw->SR.R = tmp.R;
\r
518 esciHw->LTR.R=tmpLtr.R; // write to transmit reg
\r
519 esciHw->LCR.B.FCIE = 1; // Enable frame complete
\r
520 esciHw->LCR.B.RXIE = 1; // Enable rx irq
\r
526 Std_ReturnType Lin_SendResponse( uint8 Channel, Lin_PduType* PduInfoPtr )
\r
528 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
529 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
530 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
531 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
532 VALIDATE_W_RV( (PduInfoPtr != NULL), LIN_SEND_RESPONSE_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
534 // The response is sent from within the header in this implementation since this is a master only implementation
\r
538 Std_ReturnType Lin_GoToSleep( uint8 Channel )
\r
540 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
541 Lin_PduType PduInfo;
\r
542 uint8 data[8] = {0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
\r
544 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
545 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
546 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
547 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
549 if (LinChannelOrderedStatus[Channel]!=LIN_CH_SLEEP){
\r
550 LinChannelOrderedStatus[Channel]=LIN_CH_SLEEP;
\r
552 PduInfo.Cs = LIN_CLASSIC_CS;
\r
553 PduInfo.Pid = 0x3C;
\r
554 PduInfo.SduPtr = data;
\r
556 PduInfo.Drc = LIN_MASTER_RESPONSE;
\r
558 Lin_SendHeader(Channel, &PduInfo);
\r
559 Lin_SendResponse(Channel, &PduInfo);
\r
561 esciHw->LCR.B.WUIE = 1; // enable wake-up irq
\r
566 Std_ReturnType Lin_GoToSleepInternal( uint8 Channel )
\r
568 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
569 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
570 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
571 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_SLEEP), LIN_GO_TO_SLEEP_INTERNAL_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
572 Lin_GoToSleep(Channel);
\r
576 Std_ReturnType Lin_WakeUp( uint8 Channel )
\r
578 volatile struct ESCI_tag * esciHw = ESCI(Channel);
\r
579 Lin_PduType PduInfo;
\r
580 uint8 data[2] = {0xFF,0xFF};
\r
582 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
583 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_WAKE_UP_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
584 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_WAKE_UP_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
585 VALIDATE_W_RV( (LinChannelStatus[Channel] == LIN_CH_SLEEP), LIN_WAKE_UP_SERVICE_ID, LIN_E_STATE_TRANSITION, E_NOT_OK);
\r
587 esciHw->LCR.B.WUIE = 0; // disable wake-up irq
\r
588 esciHw->LCR.B.WU = 1; // send wake up
\r
589 esciHw->LCR.B.WUD0 = 1; // delimiter time
\r
590 esciHw->LCR.B.WUD1 = 0; // delimiter time
\r
592 // Just send any header to trigger the wakeup signal
\r
593 PduInfo.Cs = LIN_CLASSIC_CS;
\r
594 PduInfo.Pid = 0x00;
\r
595 PduInfo.SduPtr = data;
\r
597 PduInfo.Drc = LIN_SLAVE_RESPONSE;
\r
598 Lin_SendHeader(Channel, &PduInfo);
\r
600 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
604 Lin_StatusType Lin_GetStatus( uint8 Channel, uint8** Lin_SduPtr )
\r
606 VALIDATE_W_RV( (LinDriverStatus != LIN_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_UNINIT, E_NOT_OK);
\r
607 VALIDATE_W_RV( (LinChannelStatus[Channel] != LIN_CH_UNINIT), LIN_GETSTATUS_SERVICE_ID, LIN_E_CHANNEL_UNINIT, E_NOT_OK);
\r
608 VALIDATE_W_RV( (Channel < LIN_CONTROLLER_CNT), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_CHANNEL, E_NOT_OK);
\r
609 VALIDATE_W_RV( (Lin_SduPtr!=NULL), LIN_GETSTATUS_SERVICE_ID, LIN_E_INVALID_POINTER, E_NOT_OK);
\r
611 imask_t state = McuE_EnterCriticalSection();
\r
612 Lin_StatusType res = LinChannelStatus[Channel];
\r
613 // We can only check for valid sdu ptr when LIN_RX_OK
\r
614 if(LinChannelStatus[Channel] == LIN_RX_OK || LinChannelStatus[Channel] == LIN_RX_ERROR){
\r
615 *Lin_SduPtr = RxPtr[Channel];
\r
616 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
617 } else if(LinChannelStatus[Channel] == LIN_TX_OK || LinChannelStatus[Channel] == LIN_TX_ERROR){
\r
618 LinChannelStatus[Channel]=LIN_CH_OPERATIONAL;
\r
620 McuE_ExitCriticalSection(state);
\r