/****************************************************************************** * * Freescale Semiconductor Inc. * (c) Copyright 2008-2016 Freescale Semiconductor, Inc. * Copyright 2016-2017 NXP * ALL RIGHTS RESERVED. * ******************************************************************************/ /**************************************************************************//** * @addtogroup SCI_group * @{ ******************************************************************************/ /**************************************************************************//** * * @file bsp/SCI/lin_lld_sci.c * * @author FPT Software * * @brief SCI for LIN network * ******************************************************************************/ /****************************************************************************** * * History: * * 20101027 v1.0 First version * 20111005 v1.1 Updated hardware support, multi timers * *****************************************************************************/ #include "derivative.h" #include "DMK-BC316-77.h" #include "lin_lld_sci.h" #include "lin_hw_cfg.h" #include "lin_common_proto.h" #include "lin_lld_timesrv.h" #include "lin_cfg.h" #if (!defined(_MC9S12ZVML128_H) && !defined(_MC9S12ZVML31_H)) #pragma MESSAGE DISABLE C4800 /* Disable warning message with ID C4800 */ #endif /* End if (!defined(_MC9S12ZVML128_H) && !defined(_MC9S12ZVML31_H)) */ #if (LIN_MODE == _SLAVE_MODE_) #if (SCI_VERSION == SCI_V4 && __RESYN_EN==1) #include "lin_lld_resyn.h" #define Active_Edge_Rx_Disable() pSCI->scibdh.byte &= ~SCIBDH_RXEDGIE_MASK #define Active_Edge_Rx_Enable() pSCI->scibdh.byte |= SCIBDH_RXEDGIE_MASK #endif /* End (SCI_VERSION == SCI_V4 && __RESYN_EN==1) */ #if (AUTOBAUD == 1) #include "lin_lld_autobaud.h" extern l_u16 lin_max_frame_res_timeout_val_autobaud[8]; #endif /* End (1==AUTOBAUD) */ /***** Globle variable data *****/ /* pSCI func ifc checksum_mode state l_status cnt_byte *ptr current_pid *response_buffer pid_out tbit frame_timeout_cnt res_frame_timeout_cnt idle_timeout_cnt */ #if (SCI_VERSION != SCI_V5) /** * @var static l_bool func */ static l_bool func = 0; #endif /* End (SCI_VERSION != SCI_V5) */ /** * @var static tSCI *pSCI */ static tSCI *pSCI = (tSCI*)SCI_ADDR; /** * @var static l_u8 ifc */ static l_u8 ifc = 0xFF; /** * @var static l_u8 state */ static l_u8 state = UNINIT; /** * @var static lin_status l_status */ static lin_status l_status; /** * @var static l_u8 cnt_byte */ static l_u8 cnt_byte = 0; /** * @var static l_u8 *ptr */ static l_u8 *ptr = 0; /** * @var static l_u8 current_id */ static l_u8 current_id = 0x00; /** * @var static l_u8 *response_buffer */ static l_u8 *response_buffer = 0; /** * @var static l_u8 pid */ static l_u8 pid = 0x80; /** * @var static l_u16 tbit */ static l_u16 tbit = 0; /** * @var static l_u16 frame_timeout_cnt */ static l_u16 frame_timeout_cnt = 0; /** * @var static l_u16 res_frame_timeout_cnt */ static l_u16 res_frame_timeout_cnt = 0; /** * @var static l_u16 idle_timeout_cnt */ static l_u16 idle_timeout_cnt = 0; #if (SCI_VERSION == SCI_V4) /* Globle variable for resyn */ #if (__RESYN_EN) volatile static l_u8 resyn_flag = 0x00; extern l_u16 timer_value; #endif /* End Enable resych */ #endif /* End (SCI_VERSION == SCI_V4) */ extern const l_u16 lin_max_frame_res_timeout_val[8]; #if (SCI_VERSION != SCI_V2) extern l_u8 lin_lld_response_buffer[10]; #endif /* End (SCI_VERSION != SCI_V2) */ //user define extern unsigned char InitButtonCode; /***** LOW-LEVEL API *****/ void lin_lld_sci_init ( /* [IN] LIN interface name*/ l_ifc_handle iii ) { #if (SCI_VERSION == SCI_V2) /* Config */ ifc=(l_u8)iii; response_buffer=lin_lld_response_buffer; /* Set SCI is Master or Slave */ tbit=(l_u16)(1000000/LIN_BAUD_RATE); /* Initialize SCI */ /* Set baud rate */ pSCI->scibdh.byte = ((MCU_BUS_FREQ/LIN_BAUD_RATE/16)>>8)&0x1F; pSCI->scibdl.byte = (MCU_BUS_FREQ/LIN_BAUD_RATE/16)&0xFF; /* Enable use of 13bit breaks and SCI frame for LIN */ pSCI->scicr1.byte = 0x00; /* one start bit, eight data bits, one stop bit */ pSCI->scicr2.byte = ((SCICR2_TE_MASK | SCICR2_RE_MASK) | SCICR2_RIE_MASK); pSCI->scicr3.byte |= SCICR3_FEIE_MASK; /* Enable Frame Error interrupt */ /* Enter IDLE state */ lin_goto_idle_state(); #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) l_u16 tmp; /* Resyn initialization */ #if (__RESYN_EN == 1) /* enable/disable Resyn module */ initTrimSaturation(); TPM_CH2_init(); #endif /* enable/disable Resyn module */ /* Config */ ifc=(l_u8)iii; response_buffer=lin_lld_response_buffer; /* Set SCI is Master or Slave */ tbit=(1000000/LIN_BAUD_RATE); /* Initialize SCI */ /* Set baud rate */ tmp = MCU_BUS_FREQ/LIN_BAUD_RATE/16; pSCI->scibdh.byte = (tmp>>8)&0x1F; pSCI->scibdl.byte = tmp&0xFF; /* Enable use of 13bit breaks and SCI frame for LIN */ /* one start bit, eight data bits, one stop bit */ pSCI->scicr1.byte = 0x00; pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); /* clear LIN Break Detection flag */ pSCI->scisr2.byte |= (SCISR2_LBKDIF_MASK | SCISR2_BRK13_MASK | SCISR2_LBKDE_MASK); /* Enable Frame Error interrupt */ pSCI->scicr3.byte |= SCICR3_FEIE_MASK; /* enable LIN Break Detection interrupt */ pSCI->scibdh.byte |= SCIBDH_LBKDIE_MASK; /* Receive data not inverted */ pSCI->scisr2.bit.rxinv = 0; /* Enter IDLE state */ lin_goto_idle_state(); #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V5) l_u16 tmp; /* Config */ ifc=(l_u8)iii; response_buffer=lin_lld_response_buffer; /* Set SCI is Master or Slave */ tbit=(1000000/LIN_BAUD_RATE); /* Initialize SCI */ /* Set baud rate */ pSCI->scisr2.byte = 0x00; tmp = MCU_BUS_FREQ/LIN_BAUD_RATE/16; pSCI->scibdh.byte = (l_u8)(tmp>>8); pSCI->scibdl.byte = tmp&0xff; /* Enable SCI in wait mode and enable bit count after stop bit */ pSCI->scicr1.byte = SCICR1_ILT_MASK; /* Enable use of 13bit breaks and SCI frame for LIN */ pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); /* Enable mismatch error detection */ pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); /* Enable break detect circuit and timing bit error detection at 9th time stick */ pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); /* Enable tranceiver interrupt */ pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Enter IDLE state */ lin_goto_idle_state(); #endif /* End (SCI_VERSION == SCI_V5) */ #if (SCI_VERSION == SCI_V6) l_u16 tmp; #if ( defined(_MC9S12ZVL32_H) || defined(_MC9S12ZVL128_H) || \ defined(_MC9S12ZVMA_H) || defined(_MC9S12ZVMB_H)) #if (_SCI0_) /* Set up for LIN PHY */ /* Enable LIN PHY*/ LP0CR_LPE = 1; /* Turn on lin transmitter overcurrent interrupt */ LP0IE_LPOCIE = 1; #endif /* END SCI0 */ #endif /* END ifdef _MC9S12ZVL32_H */ #if (defined(_MC9S12VR64_H) || defined(_MC9S12VR32_H) || defined(_MC9S12VRP64_H) || defined(_MC9S12VRP48_H)) #if (_SCI0_) /* Set up for LIN PHY */ /* Enable LIN PHY*/ LPCR_LPE = 1; /* Turn on lin transmitter overcurrent interrupt */ LPIE_LPOCIE = 1; #endif /* END SCI0 */ #endif /* END if defined(_MC9S12VR64_H) || defined(_MC9S12VR32_H) || defined(_MC9S12VRP64_H) || defined(_MC9S12VRP48_H) */ /* Config */ ifc=(l_u8)iii; response_buffer=lin_lld_response_buffer; /* Set SCI is Master or Slave */ tbit=(1000000/LIN_BAUD_RATE); /* Initialize SCI */ /* Set baud rate */ pSCI->scisr2.byte = 0x00; #if (AUTOBAUD == 1) /* driver shall init slave with baudrate = 19200. Then it detect LIN Bus baudrate, then adjust accordingly */ tmp = MCU_BUS_FREQ/19200; #else tmp = MCU_BUS_FREQ/LIN_BAUD_RATE; #endif pSCI->scibdh.byte = (l_u8)(tmp>>8); pSCI->scibdl.byte = (l_u8)tmp&0xff; /* Enable SCI in wait mode and enable bit count after stop bit */ pSCI->scicr1.byte = SCICR1_ILT_MASK; /* Enable use of 13bit breaks and SCI frame for LIN */ pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); #if (AUTOBAUD == 1) /* Enable break detect flags */ pSCI->sciacr1.byte = SCIACR1_BKDIE_MASK; /* Enable break detect circuit */ pSCI->sciacr2.byte = SCIACR2_BKDFE_MASK; #else /* Enable mismatch error detection */ pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ //pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); pSCI->sciacr1.byte = (SCIACR1_RXEDGIE_MASK | SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK);//SCIACR1_RXEDGIE_MASK /* Enable break detect circuit and timing bit error detection at 9th time stick */ pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); #endif /* Enable transceiver interrupt */ pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Dummy read */ (void)pSCI->scisr1.byte; /****************************** *** x. AUTOBAUD *******************************/ #if (AUTOBAUD == 1) autobaud_init(); #endif /* End AUTOBAUD */ /* Enter IDLE state */ lin_goto_idle_state(); #endif /* End (SCI_VERSION == SCI_V6) */ } /* End of function lin_lld_sci_init( l_ifc_handle iii ) */ #if (AUTOBAUD == 1) volatile l_u8 baudrate_adjusted_flag = 0; void lin_lld_sci_init_autobaud (l_u16 baudrate) { l_u16 tmp; l_u8 i = 0; /* Set up for LIN PHY */ #if ( defined(_MC9S12ZVL32_H) || defined(_MC9S12ZVL128_H) || \ defined(_MC9S12ZVMA_H) || defined(_MC9S12ZVMB_H)) /* Enable LIN PHY*/ LP0CR_LPE = 1; #endif /* END ifdef _MC9S12ZVL32_H */ response_buffer=lin_lld_response_buffer; /* Set SCI is Master or Slave */ tbit=(1000000/baudrate); /* Initialize SCI */ /* Set baud rate */ pSCI->scisr2.byte = 0x00; tmp = (MCU_BUS_FREQ/baudrate); /*Change AMAP to 0 to access SCI_BDH, SCI_BDL*/ pSCI->scisr2.byte &= ~SCISR2_AMAP_MASK; /*Set new baudrate*/ pSCI->scibdh.byte = (l_u8)(tmp>>8); pSCI->scibdl.byte = tmp&0xff; /* Enable SCI in wait mode and enable bit count after stop bit */ pSCI->scicr1.byte = SCICR1_ILT_MASK; /* Enable use of 13bit breaks and SCI frame for LIN */ pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); /* Enable mismatch error detection */ pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); /* Enable break detect circuit and timing bit error detection at 9th time stick */ pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); /* Enable tranceiver interrupt */ pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); autobaud_current=baudrate; /* Ignore first frame if node was sleeping before receiving */ /* Enter Receive PID state */ if (RECV_SYN == state) { state = RECV_PID; } /* Set flag to indicate that baud rate was adjusted*/ baudrate_adjusted_flag = 1; for (i=0; i<8; i++) { lin_max_frame_res_timeout_val_autobaud[i] = lin_calc_max_res_timeout_cnt(autobaud_current, i+1); } frame_timeout_cnt =lin_max_frame_res_timeout_val_autobaud[7]; } /* End of function lin_lld_sci_init( l_ifc_handle iii ) */ #endif /* AUTOBAUD Init */ void lin_lld_sci_deinit () { state=UNINIT; lin_lld_sci_int_disable(); } void lin_lld_sci_tx_wake_up () { #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) l_u8 sci_flag_sr1; if((state == IDLE) || (state == SLEEP_MODE)) { sci_flag_sr1 = pSCI->scisr1.byte; /* Send wake signal byte=0x80 */ pSCI->scid.byte = SCID_R7_T7_MASK; /* Set Lin state to idle */ lin_goto_idle_state(); } #endif /* End (SCI_VERSION != SCI_V5) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) if((state == IDLE) || (state == SLEEP_MODE)) { /* Send wake signal byte=0x80 */ pSCI->scidrl.byte = SCIDRH_R8_MASK; /* Set Lin state to idle */ lin_goto_idle_state(); } #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_tx_wake_up() */ void lin_lld_sci_int_enable() { #if (SCI_VERSION == SCI_V2) /* Can't enable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } /* Enable SCI Channel*/ pSCI->scicr2.byte |= (SCICR2_RE_MASK | SCICR2_RIE_MASK); #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) /* Can't enable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } /* Enable SCI Channel*/ pSCI->scicr2.byte |= (SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Enable timeout interrupt 0 channel */ #if ((!defined(_MC9S12I32_H)) && (!defined(_MC9S12I128_H)) && (!defined(_MM9Z1J638_H)) && (!defined(_MC9S08RN60_H))) TPM1C0SC = 0x50; #endif /* End defined(_MC9S12I32_H) */ #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) /* Can't enable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } /* Enable SCI Channel*/ pSCI->scicr2.byte |= (SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Enable Timeout */ #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_int_enable() */ void lin_lld_sci_int_disable () { #if (SCI_VERSION == SCI_V2) /* Can't disable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } while(state != IDLE) {} /* Disable SCI Channel*/ pSCI->scicr2.byte &= ~(SCICR2_RE_MASK | SCICR2_RIE_MASK); #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) /* Can't disable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } while(state != IDLE) {} /* Disable SCI Channel*/ pSCI->scicr2.byte &= ~(SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Disable timeout interrupt 0 channel */ #if ((!defined(_MC9S12I32_H)) && (!defined(_MC9S12I128_H)) && (!defined(_MM9Z1J638_H)) && (!defined(_MC9S08RN60_H))) TPM1C0SC = 0x00; #endif /* if not defined(_MC9S12I128_H) */ #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) /* Can't disable in interrupt context */ if((state == PROC_CALLBACK) || (state==UNINIT) || (state==SLEEP_MODE)) { return; } while(state != IDLE) {} /* Disable SCI Channel*/ pSCI->scicr2.byte &= ~(SCICR2_RE_MASK | SCICR2_RIE_MASK); #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_int_disable() */ void lin_lld_sci_ignore_response () { lin_goto_idle_state(); } void lin_lld_sci_set_low_power_mode () { /* Configure Hw code */ /* Set Lin status = receiving data*/ state=SLEEP_MODE; } void lin_lld_sci_rx_response ( /* [IN] Length of response data expect to wait */ l_u8 msg_length ) { /* Put response length and pointer of response buffer into descriptor */ *(response_buffer)=msg_length; cnt_byte=0; ptr=response_buffer; /* Set Lin status = receiving data*/ state=RECV_DATA; } void lin_lld_sci_tx_response () { #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) /* calculate checksum */ response_buffer[*(response_buffer)+1] = lin_checksum(response_buffer, pid); cnt_byte=1; /* Send First byte */ pSCI->scid.byte = response_buffer[1]; /* Set LIN Status */ state = SEND_DATA; #endif /* End (SCI_VERSION != SCI_V5) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) /* calculate checksum */ response_buffer[*(response_buffer)+1] = lin_checksum(response_buffer, pid ); cnt_byte=1; /* Send First byte */ pSCI->scidrl.byte = response_buffer[1]; /* Set LIN Status */ state = SEND_DATA; #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_tx_response() */ l_u8 lin_lld_sci_get_status () { return l_status.byte; } l_u8 lin_lld_sci_get_state() { return state; } void lin_lld_sci_timeout () { /* Multi frame support */ #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) if (LD_CHECK_N_CR_TIMEOUT == tl_check_timeout_type) { if(0 == --tl_check_timeout) { /* update status of transport layer */ tl_service_status = LD_SERVICE_ERROR; tl_receive_msg_status = LD_N_CR_TIMEOUT; tl_rx_msg_status = LD_N_CR_TIMEOUT; tl_check_timeout_type = LD_NO_CHECK_TIMEOUT; tl_diag_state = LD_DIAG_IDLE; } } if (LD_CHECK_N_AS_TIMEOUT == tl_check_timeout_type) { if(0 == --tl_check_timeout) { /* update status of transport layer */ tl_service_status = LD_SERVICE_ERROR; tl_tx_msg_status = LD_N_AS_TIMEOUT; tl_check_timeout_type = LD_NO_CHECK_TIMEOUT; tl_diag_state = LD_DIAG_IDLE; } } #else /* Single Frame */ if (LD_CHECK_N_AS_TIMEOUT == tl_check_timeout_type) { if(0 == --tl_check_timeout) { /* update status of transport layer */ tl_service_status = LD_SERVICE_ERROR; tl_check_timeout_type = LD_NO_CHECK_TIMEOUT; } } #endif /* END (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) */ #if (SCI_VERSION == SCI_V2) switch(state) { case IDLE: if(idle_timeout_cnt==0) { /* Set LIN mode to sleep mode */ lin_goto_sleep_flg = 1; /* trigger callback */ CALLBACK_HANDLER(ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0x00); /* goback to IDLE, reset max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /* Set state to sleep mode */ state = SLEEP_MODE; } else { idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == frame_timeout_cnt) { lin_goto_idle_state(); } else { frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(res_frame_timeout_cnt == 0) { if(cnt_byte > 0) { /* set lin status: error_in_response */ l_status.byte |= LIN_STA_ERROR_RESP; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_NODATA_TIMEOUT, 0x00); } lin_goto_idle_state(); } else { res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) switch(state) { case IDLE: if(idle_timeout_cnt==0) { /* Set LIN mode to sleep mode */ lin_goto_sleep_flg = 1; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0xFF); /* goback to IDLE, reset max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /* disable LIN break detect interrupt */ pSCI->scisr2.bit.lbkde = 0; /* Set state to sleep mode */ state = SLEEP_MODE; } else { idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == frame_timeout_cnt) { lin_goto_idle_state(); } else { frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(0 == res_frame_timeout_cnt) { if(cnt_byte) { /* set lin status: error_in_response */ l_status.byte |= LIN_STA_ERROR_RESP; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_NODATA_TIMEOUT, current_id); } lin_goto_idle_state(); } else { res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) switch(state) { case IDLE: if(idle_timeout_cnt==0) { /* Set LIN mode to sleep mode */ lin_goto_sleep_flg = 1; NO_DATA_Sleep=1; //~{e( ?~}?~{?9~}?~{=f?f5<~}?~{ o??~} /* trigger callback */ CALLBACK_HANDLER(ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0xFF); /* goback to IDLE, reset max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /* Set state to sleep mode */ state = SLEEP_MODE; } else { idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == frame_timeout_cnt) { lin_goto_idle_state(); } else { frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(0 == res_frame_timeout_cnt) { if(cnt_byte > 0) { /* set lin status: error_in_response */ l_status.byte |= LIN_STA_ERROR_RESP; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_NODATA_TIMEOUT, current_id); } lin_goto_idle_state(); } else { res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_timeout() */ /*** INTERNAL FUNTIONS ***/ void lin_goto_idle_state () { #if (SCI_VERSION == SCI_V2) /* set lin status: ~bus_activity */ l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; state=IDLE; #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) /* set lin status: ~bus_activity */ l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; state=IDLE; /* Enable LBK detect */ pSCI->scisr2.bit.lbkde = 1; #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) /* set lin status: ~bus_activity */ l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; state=IDLE; #if (AUTOBAUD == 1) /* if baud rate was not adjusted successfully*/ if (baudrate_adjusted_flag < 1) { /* Enable SCI interface*/ /* Enable SCI in wait mode and enable bit count after stop bit */ pSCI->scicr1.byte = SCICR1_ILT_MASK; /* Enable use of 13bit breaks and SCI frame for LIN */ pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); /* Enable mismatch error detection */ pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); /* Enable break detect circuit and timing bit error detection at 9th time stick */ pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); /* Enable tranceiver interrupt */ pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); } #endif #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_goto_idle_state() */ #if (SCI_VERSION != SCI_V5) void lin_lld_sci_err_isr () { #if (SCI_VERSION == SCI_V2) l_u8 sci_flag_sr1; l_u8 tmp_byte; sci_flag_sr1 = pSCI->scisr1.byte; tmp_byte = pSCI->scid.byte; /****************************** *** 1. BREAK DETECTED *******************************/ if(0x00 == tmp_byte) { /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == state) { lin_goto_idle_state(); return; } /* reset lin status */ l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ frame_timeout_cnt = lin_max_frame_res_timeout_val[7]; /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ state=RECV_SYN; return; } /****************************** *** 3. FRAME ERROR DETECTED *******************************/ else { /* set lin status: error_in_response, framing_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* trigger callback */ if((state == RECV_DATA)||(state == SEND_DATA)||(state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_FRAME_ERR, current_id); } lin_goto_idle_state(); } #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) l_u8 sci_flag_sr1; l_u8 tmp_byte; sci_flag_sr1 = pSCI->scisr1.byte; tmp_byte = pSCI->scid.byte; if((sci_flag_sr1 & SCISR1_FE_MASK)||(sci_flag_sr1 & SCISR1_PF_MASK)) { if(sci_flag_sr1 & SCISR1_FE_MASK) { /* set lin status: error_in_response, framing_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* trigger callback */ if((state == RECV_DATA)||(state == SEND_DATA)||(state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_FRAME_ERR, current_id); } lin_goto_idle_state(); } if(sci_flag_sr1 & SCISR1_PF_MASK) { /* set lin status: error_in_response, framing_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_PARITY_ERR); /* trigger callback */ if((state == RECV_DATA)||(state == SEND_DATA)||(state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_CHECKSUM_ERR, current_id); } lin_goto_idle_state(); } } #endif /* End (SCI_VERSION == SCI_V4) */ } /* End function lin_lld_sci_err_isr() */ void lin_lld_sci_rx_isr () { #if (SCI_VERSION == SCI_V2) l_u8 sci_flag_sr1; l_u8 tmp_byte; sci_flag_sr1 = pSCI->scisr1.byte; tmp_byte = pSCI->scid.byte; /* Set max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /****************************** *** 4. BYTE RECIEVED *******************************/ if(0 != (sci_flag_sr1&SCISR1_RDRF_MASK)) { switch(state) { /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55 == tmp_byte) { state=RECV_PID; } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: /* checkparity and extrait PID */ current_id = lin_process_parity(tmp_byte, CHECK_PARITY); pid = tmp_byte; if(current_id !=0xFF) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_OK, current_id); /* Set Maximum response frame timeout */ res_frame_timeout_cnt = lin_max_frame_res_timeout_val[*(response_buffer) - 1]; } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* set lin status: parity_error */ l_status.byte |= LIN_STA_PARITY_ERR; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_ERR, 0x00); lin_goto_idle_state(); } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: ptr++; *(ptr)=tmp_byte; /* Check bytes received fully */ if(cnt_byte==(response_buffer[0])) { /* checksum checking */ if(lin_checksum(response_buffer, pid)==tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* set lin status: successful_transfer */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_RX_COMPLETED, current_id); if (SLEEP_MODE != state) { lin_goto_idle_state(); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* set lin status: error_in_response, checksum_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_CHECKSUM_ERR, current_id); lin_goto_idle_state(); } } cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: /* Check for READBACK error */ if (0U == (sci_flag_sr1 & SCISR1_TC_MASK)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); lin_goto_idle_state(); break; } else { if (tmp_byte != response_buffer[cnt_byte]) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); lin_goto_idle_state(); break; } } if(cnt_byte <= (response_buffer[0])) { /* Send data bytes and checksum */ cnt_byte++; pSCI->scid.byte = response_buffer[cnt_byte]; } else { /* TX transfer complete */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_TX_COMPLETED, current_id); lin_goto_idle_state(); } break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: if ((tmp_byte == 0xF0) || (tmp_byte == 0xE0) || (tmp_byte == 0xC0) || (tmp_byte == 0x80) || (tmp_byte == 0x00)) { /* Set idle timeout again */ lin_goto_idle_state(); } break; default: break; } } #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) l_u8 sci_flag_sr1; l_u8 sci_flag_sr2; l_u8 tmp_byte; /* Set max idle timeout */ idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /****************************** *** 1. BREAK DETECTED *******************************/ /* if the lbkdif is set */ sci_flag_sr2 = pSCI->scisr2.byte ; if((sci_flag_sr2 & SCISR2_RXEDGIF_MASK) && (!(sci_flag_sr2 & SCISR2_LBKDIF_MASK))) { /* Clear flag */ pSCI->scisr2.bit.rxedgif = 1; #if (__RESYN_EN == 1) /* Resynchronization */ if (resyn_flag & START_RESYN_MASK ) { /* start timer */ TPM_CH2_enable(); } if (resyn_flag) { /* increase falling_edge_num */ resyn_flag <<= 1; /* Store RESYN_FLAG for test */ } else /* if resyn_flag == STOP_RESYN_MASK */ { /* Disable Active Edge interrupt */ pSCI->scibdh.byte &= ~SCIBDH_RXEDGIE_MASK; } if (resyn_flag & FIN_RESYN_MASK) { /* store timer */ TPM_CH2_store(); /* Store timer value for test */ } #else /* if __RESYN_EN == 0 */ pSCI->scibdh.byte &= ~SCIBDH_RXEDGIE_MASK; /* Disable rx edged detection */ #endif /* End Resynchronization */ if (SLEEP_MODE == state) { lin_goto_idle_state(); lin_goto_sleep_flg = 0; } /* Enable Break interrupt */ pSCI->scibdh.byte |= SCIBDH_LBKDIE_MASK ; /* Receive data not inverted */ pSCI->scisr2.bit.rxinv = 0; /* check state of node is SLEEP_MODE */ return; } if(sci_flag_sr2 & SCISR2_LBKDIF_MASK) { /* Clear flag */ pSCI->scisr2.bit.lbkdif = 1; /* Enable Active Edge interrupt */ pSCI->scibdh.byte |= SCIBDH_RXEDGIE_MASK; /* Disable Break interrupt */ pSCI->scibdh.byte &= ~SCIBDH_LBKDIE_MASK ; /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == state) { lin_goto_idle_state(); return; } /* reset lin status */ l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ frame_timeout_cnt = lin_max_frame_res_timeout_val[7]; /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ /* Start resyn */ #if (__RESYN_EN == 1) resyn_flag = START_RESYN_MASK; #endif /* Enable Active Edge interrupt */ pSCI->scibdh.byte |= 0x40 ; /* SCIBDH_RXEDGIE_MASK; */ state=RECV_SYN; /* Disable LBK detect */ pSCI->scisr2.bit.lbkde = 0; return; } else { sci_flag_sr1 = pSCI->scisr1.byte; tmp_byte = pSCI->scid.byte; /****************************** *** 4. BYTE RECIEVED *******************************/ if(0 != (sci_flag_sr1&SCISR1_RDRF_MASK)) { switch(state) { /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55 == tmp_byte) { state=RECV_PID; #if (__RESYN_EN == 1) /* Update new trim value */ if (resyn_flag & FIN_RESYN_MASK) { compTrimCorrection(); ApplyTrimReg(); } resyn_flag = STOP_RESYN_MASK; #endif } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: /* checkparity and extrait PID */ current_id=lin_process_parity(tmp_byte, CHECK_PARITY); /* Keep the PID */ pid = tmp_byte; if(current_id !=0xFF) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_OK, current_id); /* Set Maximum response frame timeout */ res_frame_timeout_cnt = lin_max_frame_res_timeout_val[*(response_buffer) - 1]; } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* set lin status: parity_error */ l_status.byte |= LIN_STA_PARITY_ERR; /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_ERR, 0xFF); lin_goto_idle_state(); } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: ptr++; *(ptr)=tmp_byte; /* Check bytes received fully */ if(cnt_byte==(response_buffer[0])) { /* checksum checking */ if(lin_checksum(response_buffer, pid)==tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* set lin status: successful_transfer */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_RX_COMPLETED, current_id); if (SLEEP_MODE != state) { lin_goto_idle_state(); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* set lin status: error_in_response, checksum_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_CHECKSUM_ERR, current_id); lin_goto_idle_state(); } } cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: /* Check for READBACK error */ if (0==(sci_flag_sr1&SCISR1_TC_MASK)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); lin_goto_idle_state(); break; } else { if (tmp_byte != response_buffer[cnt_byte]) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); lin_goto_idle_state(); break; } } if(cnt_byte <= (response_buffer[0])) { /* Send data bytes and checksum */ cnt_byte++; pSCI->scid.byte = response_buffer[cnt_byte]; } else { /* TX transfer complete */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_TX_COMPLETED, current_id); lin_goto_idle_state(); } break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: if ((tmp_byte == 0xF0) || (tmp_byte == 0xE0) || (tmp_byte == 0xC0) || (tmp_byte == 0x80) || (tmp_byte == 0x00)) { /* Set idle timeout again */ lin_goto_idle_state(); /* Enable LIN break detect interrupt */ pSCI->scisr2.bit.lbkde = 1; } break; default: break; } } } #endif /* End (SCI_VERSION == SCI_V4) */ } /* End function lin_lld_sci_rx_isr() */ #endif /* End(SCI_VERSION != SCI_V5)*/ l_u8 MFS_RollingCounter=0; l_u8 MFS_CheckSum=0; #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) void lin_lld_sci_isr () { l_u8 sci_flag_sr1; l_u8 tmp_byte; l_u16 i; sci_flag_sr1 = pSCI->scisr1.byte; /* Set max idle timeout */ idle_timeout_cnt = _MAX_IDLE_TIMEOUT_; if(FLAG_GO_TO_Sleep==1) { PWM1_Init(); Sig_LI0_DI_KL_58xs_run=0; V_12_Ctrl=1; AD1_Init(); AD1_Start(); l_ifc_init(LI0); } M_ASK_S_Sleep=0; NO_DATA_Sleep=0; FLAG_GO_TO_Sleep=0; /****************************** *** 1. BREAK DETECTED *******************************/ if(0 != (pSCI->sciasr1.byte & SCIASR1_BKDIF_MASK)) { /* Clear the error flag */ pSCI->sciasr1.byte |= SCIASR1_BKDIF_MASK; /* Reset lin status */ l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ #if (AUTOBAUD == 1) frame_timeout_cnt = lin_max_frame_res_timeout_val_autobaud[7]; if (baudrate_adjusted_flag == 0) { /* Disable SCI receiver interface*/ pSCI->scicr2.byte &= ~( SCICR2_RE_MASK | SCICR2_RIE_MASK); pSCI->sciacr2.byte &= ~(SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); pSCI->sciacr1.byte &= ~(SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); autobaud_tmr_capture_index = 0; /* Capture only on failing edges */ stop_flag = 0; TIMER_CONTROL_EDG = 2U; TIMER_INT_ENA = 1; } #else frame_timeout_cnt = lin_max_frame_res_timeout_val[7]; #endif /* End (AUTOBAUD == 1)*/ /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == state) { lin_goto_idle_state(); return; } /* Handle error */ if((RECV_DATA == state) || (SEND_DATA == state) || (SEND_DATA_COMPLETED == state)) { /* Read dummy data to clear FE flags */ tmp_byte = pSCI->scidrl.byte; /* Set lin status: error_in_response, framing_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_FRAME_ERR, current_id); } state = RECV_SYN; return; } /****************************** *** 2. BIT ERROR DETECTED *******************************/ else { if( 0 != (pSCI->sciasr1.byte&SCIASR1_BERRIF_MASK)) { pSCI->sciasr1.byte |= SCIASR1_BERRIF_MASK; /* set lin status: error_in_response, readback_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_READBACK_ERR); if((state == SEND_DATA) || (state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); #if (LIN_PROTOCOL == PROTOCOL_J2602) /* if Bit error occurs when a logic 0 is accepted as stop bit, then this case causes Framing error too*/ /*In this case, wait for about 20 for loops, so that SCI hardware have enough time to set Framing error flag*/ for (i=0; i<200; i++); /* Check if Framing error flag is set */ if(0 != (pSCI->scisr1.byte&SCISR1_FE_MASK)) { return; } #endif } #if (AUTOBAUD == 1) /*Clear bit error if arise in worst case for first bit error due to baud rate evaluation */ if (baudrate_adjusted_flag < 2) { return; } else lin_goto_idle_state(); #else lin_goto_idle_state(); #endif return; } } /****************************** *** 3. FRAME ERROR DETECTED *******************************/ if(0 != (sci_flag_sr1&SCISR1_FE_MASK)) { /* Clear FE flags */ pSCI->scisr1.byte |= SCISR1_FE_MASK; tmp_byte = pSCI->scidrl.byte; /* set lin status: error_in_response, framing_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* trigger callback */ if((state == RECV_DATA)||(state == SEND_DATA) || (state == SEND_DATA_COMPLETED) ) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_FRAME_ERR, current_id); } lin_goto_idle_state(); } /****************************** *** 4. BYTE RECIEVED *******************************/ else if(0U != (sci_flag_sr1 & SCISR1_RDRF_MASK)) { tmp_byte = pSCI->scidrl.byte; switch(state) { /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55 == tmp_byte) { state = RECV_PID; } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: /* checkparity and extrait PID */ pid=tmp_byte; current_id = lin_process_parity(tmp_byte,CHECK_PARITY); if(current_id != 0xFFU) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ if(current_id == 0x0E) { InitButtonCode = 0; } /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_OK, current_id); /* Set Maximum response frame timeout */ #if (AUTOBAUD == 1) if (baudrate_adjusted_flag == 1U) { baudrate_adjusted_flag = 2U; /*Clear bit error if arise in worst case for first bit error due to baud rate evaluation */ pSCI->sciasr1.byte |= SCIASR1_BERRIF_MASK; } res_frame_timeout_cnt = lin_max_frame_res_timeout_val_autobaud[*(response_buffer) - 1]; #else res_frame_timeout_cnt = lin_max_frame_res_timeout_val[*(response_buffer) - 1]; #endif /* End (AUTOBAUD == 1)*/ } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* set lin status: parity_error */ l_status.byte |= LIN_STA_PARITY_ERR; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_PID_ERR, 0xFFU); lin_goto_idle_state(); } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: ptr++; *(ptr) = tmp_byte; /* Check bytes received fully */ if(cnt_byte==(response_buffer[0])) { /* checksum checking */ if(lin_checksum(response_buffer, pid) == tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* set lin status: successful_transfer */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_RX_COMPLETED, current_id); if (SLEEP_MODE != state) { lin_goto_idle_state(); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* set lin status: error_in_response, checksum_error */ l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_CHECKSUM_ERR, current_id); lin_goto_idle_state(); lin_pFrameBuf[7] |= 0x80; } //lin_pFrameBuf[5] = tmp_byte; //lin_pFrameBuf[6] = l_status.byte; } cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: if(current_id==0x0E) { if(cnt_byte==1) { MFS_RollingCounter++; if(MFS_RollingCounter==16) { MFS_RollingCounter=0; } l_u8_wr_LI0_MFL_Zaehler(MFS_RollingCounter); } if (cnt_byte==6) { if (lin_error_in_response == 1) { response_buffer[8] |= 0x80; } else { response_buffer[8] &= 0x7f; } response_buffer[9] = lin_checksum(response_buffer, lin_process_parity(current_id,MAKE_PARITY)); } } if (0 == (sci_flag_sr1&SCISR1_TC_MASK )) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); state = PROC_CALLBACK; lin_goto_idle_state(); break; } if(cnt_byte==(response_buffer[0])) { /* Send checksum byte */ pSCI->scidrl.byte = response_buffer[cnt_byte+1]; state= SEND_DATA_COMPLETED; } else { /* Send byte next */ cnt_byte++; pSCI->scidrl.byte = response_buffer[cnt_byte]; } break; /****************************** *** 4.7 SLAVE: Sending data compeleted *******************************/ case SEND_DATA_COMPLETED: /*******************************************/ /*** TX Buffer Empty - Checksum Sent ***/ /*******************************************/ if (0U == (sci_flag_sr1&SCISR1_TC_MASK)) { CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_READBACK_ERR, current_id); state = PROC_CALLBACK; lin_goto_idle_state(); break; } /* set lin status: successful_transfer */ l_status.byte |= LIN_STA_SUCC_TRANSFER; state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)ifc, LIN_LLD_TX_COMPLETED, current_id); lin_goto_idle_state(); lin_error_in_response = 0; lin_pFrameBuf[7] &= 0x7f; break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: /* if receive a wakeup signal*/ if ((tmp_byte == 0xFFU) || (tmp_byte == 0xFEU) || (tmp_byte == 0xFCU) || (tmp_byte == 0xF8U) || (tmp_byte == 0xF0U)|| (tmp_byte == 0xE0U)|| (tmp_byte == 0xC0U)|| (tmp_byte == 0x80U)|| (tmp_byte == 0x00U)) { /* Set lin bus to idle state */ lin_goto_idle_state(); } break; default: break; } } pSCI->sciasr1.byte |=0x80;// /****************************** *** 5. OVERRUN ERROR DETECTED *******************************/ if(0 != (sci_flag_sr1&SCISR1_OR_MASK)) { /* Read SCIDRL Register to clear OR flag*/ tmp_byte = pSCI->scidrl.byte; lin_goto_idle_state(); } } /* End function lin_lld_sci_isr() */ #endif /* End (SCI_VERSION == SCI_V5) */ #endif /* End (LIN_MODE == _SLAVE_MODE_) */ /*--------------------------------------------------------------------*/ #if (LIN_MODE == _MASTER_MODE_) /***** Globle variable data *****/ extern lin_node lin_node_descrs[NUM_OF_SCI_CHANNEL]; extern const l_u16 lin_max_frame_res_timeout_val[LIN_NUM_OF_IFCS][8]; #ifdef MULTI_TIMER_MODE extern const l_u16 max_idle_timeout[LIN_NUM_OF_IFCS]; #endif /* End MULTI_TIMER_MODE */ /***** LOW-LEVEL API *****/ void lin_lld_sci_init ( /* [IN] sci channel name */ sci_channel_name channel, /* [IN] LIN interface name*/ l_ifc_handle iii ) { #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) lin_node *lnode_p; tSCI* _pSCI; lin_configuration *lconf_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; lconf_p = (lin_configuration *)&lin_ifc_configuration[iii]; /* Config */ lnode_p->ifc=(l_u8)iii; lnode_p->response_buffer=lconf_p->response_buffer; /* Set SCI is Master or Slave */ lnode_p->func=(l_bool)lconf_p->function; lnode_p->tbit=(l_u16)(1000000/lconf_p->baud_rate); /* Initialize SCI */ /* Set baud rate */ _pSCI->scibdh.byte = ((MCU_BUS_FREQ/lconf_p->baud_rate/16)>>8)&0x1F; _pSCI->scibdl.byte = (MCU_BUS_FREQ/lconf_p->baud_rate/16)&0xFF; /* Enable use of 13bit breaks and SCI frame for LIN */ /* one start bit, eight data bits, one stop bit */ _pSCI->scicr1.byte = 0x00; _pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK); #if (SCI_VERSION == SCI_V2) /* clear LIN Break Detection flag and set BRK13 bit */ _pSCI->scisr2.byte |= SCISR2_BRK13_MASK; /* enable RX complete interrupt */ _pSCI->scicr2.byte |= SCICR2_RIE_MASK; /* Enable Frame Error interrupt */ _pSCI->scicr3.byte |= SCICR3_FEIE_MASK; #endif /* End (SCI_VERSION == SCI_V2)*/ #if (SCI_VERSION == SCI_V4) _pSCI->scisr2.byte |= (SCISR2_LBKDIF_MASK | SCISR2_BRK13_MASK | SCISR2_LBKDE_MASK); /* clear LIN Break Detection flag */ /* enable RX complete interrupt */ _pSCI->scicr2.byte |= SCICR2_RIE_MASK; /* Enable Frame Error interrupt */ _pSCI->scicr3.byte |= SCICR3_FEIE_MASK; /* enable LIN Break Detection interrupt */ _pSCI->scibdh.byte |= SCIBDH_LBKDIE_MASK; #endif /* End (SCI_VERSION == SCI_V4)*/ /* Enter IDLE state */ lin_goto_idle_state(channel); #endif /* End (SCI_VERSION != SCI_V5 && SCI_VERSION != SCI_V6) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V5) l_u16 tmp; lin_node *lnode_p; tSCI* _pSCI; lin_configuration *lconf_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; lconf_p = (lin_configuration *)&lin_ifc_configuration[iii]; /* Config */ lnode_p->ifc=(l_u8)iii; lnode_p->response_buffer=lconf_p->response_buffer; /* Set SCI is Master or Slave */ lnode_p->func=(l_bool)lconf_p->function; lnode_p->tbit=(l_u16)(1000000/lconf_p->baud_rate); /* Initialize SCI */ /* Set baud rate */ _pSCI->scisr2.byte = 0x00; tmp = (l_u16)(MCU_BUS_FREQ/lconf_p->baud_rate/16); _pSCI->scibdh.byte = (l_u8)(tmp>>8); _pSCI->scibdl.byte = tmp&0xff; /* Enable SCI in wait mode and enable bit count after stop bit */ _pSCI->scicr1.byte = SCICR1_ILT_MASK; /* Enable use of 13bit breaks and SCI frame for LIN */ _pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); /* Enable mismatch error detection */ _pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ _pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); /* Enable break detect circuit and timing bit error detection at 9th time stick */ _pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); /* Enable tranceiver interrupt */ _pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Enter IDLE state */ lin_goto_idle_state(channel); #endif /* End (SCI_VERSION != SCI_V5) */ #if (SCI_VERSION == SCI_V6) l_u16 tmp; lin_node *lnode_p; tSCI* _pSCI; lin_configuration *lconf_p; #if ( defined(_MC9S12ZVL32_H) || defined(_MC9S12ZVL128_H) || \ defined(_MC9S12ZVMA_H) || defined(_MC9S12ZVMB_H)) #if (_SCI0_) /* Set up for LIN PHY */ /* Enable LIN PHY*/ LP0CR_LPE = 1; /* Turn on lin transmitter overcurrent interrupt */ LP0IE_LPOCIE = 1; #endif /* END SCI0 */ #endif /* END ifdef _MC9S12ZVL32_H */ #if (defined(_MC9S12VR64_H)||defined(_MC9S12VR32_H)||defined(_MC9S12VRP64_H) || defined(_MC9S12VRP48_H)) #if (_SCI0_) /* Set up for LIN PHY */ /* Enable LIN PHY*/ LPCR_LPE = 1; /* Turn on lin transmitter overcurrent interrupt */ LPIE_LPOCIE = 1; #endif /* END SCI0 */ #endif /* END if (defined(_MC9S12VR64_H)||defined(_MC9S12VR32_H)||defined(_MC9S12VRP64_H) || defined(_MC9S12VRP48_H))*/ lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; lconf_p = (lin_configuration *)&lin_ifc_configuration[iii]; /* Config */ lnode_p->ifc=(l_u8)iii; lnode_p->response_buffer=lconf_p->response_buffer; /* Set SCI is Master or Slave */ lnode_p->func=(l_bool)lconf_p->function; lnode_p->tbit=(l_u16)(1000000/lconf_p->baud_rate); /* Initialize SCI */ /* Set baud rate */ _pSCI->scisr2.byte = 0x00; tmp = (l_u16)(MCU_BUS_FREQ/lconf_p->baud_rate); _pSCI->scibdh.byte = (l_u8)(tmp>>8); _pSCI->scibdl.byte = tmp&0xff; /* Enable SCI in wait mode and enable bit count after stop bit */ _pSCI->scicr1.byte = SCICR1_ILT_MASK ; /* Enable use of 13bit breaks and SCI frame for LIN */ _pSCI->scisr2.byte = (SCISR2_AMAP_MASK | SCISR2_BRK13_MASK); /* Enable mismatch error detection */ _pSCI->sciasr1.byte = SCIASR1_BERRIF_MASK; /* Enable bit error interrupt and break detect flags */ _pSCI->sciacr1.byte = (SCIACR1_BERRIE_MASK | SCIACR1_BKDIE_MASK); /* Enable break detect circuit and timing bit error detection at 9th time stick */ _pSCI->sciacr2.byte = (SCIACR2_BERRM0_MASK | SCIACR2_BKDFE_MASK); /* Enable tranceiver interrupt */ _pSCI->scicr2.byte = (SCICR2_TE_MASK | SCICR2_RE_MASK | SCICR2_RIE_MASK); /* Dummy read */ (void)_pSCI->scisr1.byte; /* Enter IDLE state */ lin_goto_idle_state(channel); #endif /* End (SCI_VERSION != SCI_V6) */ } /* End function lin_lld_sci_init(sci_channel_name channel, l_ifc_handle iii) */ void lin_lld_sci_deinit ( /* [IN] sci channel name */ sci_channel_name channel ) { #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) lin_node *lnode_p; #if (SCI_VERSION == SCI_V2) lnode_p = &lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V2) */ #if (SCI_VERSION == SCI_V4) lnode_p = (lin_node *)&lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V4) */ lnode_p->state=UNINIT; lin_lld_sci_int_disable(channel); #endif /* End (SCI_VERSION != SCI_V5) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; lnode_p->state=UNINIT; lin_lld_sci_int_disable(channel); #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_deinit(sci_channel_name channel) */ void lin_lld_sci_tx_header ( /* [IN] sci channel name */ sci_channel_name channel, /* [IN] PID to be send */ l_u8 pid_id ) { lin_node *lnode_p; #if (SCI_VERSION == SCI_V2) lnode_p = &lin_node_descrs[channel]; #else lnode_p = (lin_node *)&lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V2) */ /* Check the SCI is Master ? */ if(lnode_p->func) { return; } /* Make PID and put PID into the ongoing buffer */ lnode_p->current_id = pid_id; lnode_p->pid = lin_process_parity(pid_id, MAKE_PARITY); /* Set LIN Status */ lnode_p->state = SEND_BREAK; /* Send Break*/ lnode_p->pSCI->scicr2.byte |= SCICR2_SBK_MASK; lnode_p->pSCI->scicr2.byte &= ~SCICR2_SBK_MASK; } /* End function lin_lld_sci_tx_header(sci_channel_name channel, l_u8 pid_id) */ void lin_lld_sci_tx_wake_up ( /* [IN] sci channel name */ sci_channel_name channel ) { #if (SCI_VERSION == SCI_V2) lin_node *lnode_p; lnode_p = &lin_node_descrs[channel]; if((lnode_p->state == IDLE) || (lnode_p->state == SLEEP_MODE)) { /* Send wake signal byte=0x80 */ lnode_p->pSCI->scid.byte = 0x80; /* Set Lin state to idle */ lin_goto_idle_state(channel); } #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) lin_node *lnode_p; l_u8 sci_flag_sr1; lnode_p = (lin_node *)&lin_node_descrs[channel]; if((lnode_p->state == IDLE) || (lnode_p->state == SLEEP_MODE)) { sci_flag_sr1 = lnode_p->pSCI->scisr1.byte; /* Send wake signal byte=0x80 */ lnode_p->pSCI->scid.byte = SCID_R7_T7_MASK; /* Set Lin state to idle */ lin_goto_idle_state(channel); } #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; if((lnode_p->state == IDLE) || (lnode_p->state == SLEEP_MODE)) { /* Send wake signal byte=0x80 */ lnode_p->pSCI->scidrl.byte = SCIDRH_R8_MASK; /* Set Lin state to idle */ lin_goto_idle_state(channel); } #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_tx_wake_up(sci_channel_name channel) */ void lin_lld_sci_int_enable ( /* [IN] sci channel name */ sci_channel_name channel ) { lin_node *lnode_p; #if (SCI_VERSION == SCI_V2) lnode_p = &lin_node_descrs[channel]; #else lnode_p = (lin_node *)&lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V2) */ /* Can't enable in interrupt context */ if((lnode_p->state == PROC_CALLBACK) || (lnode_p->state==UNINIT) || (lnode_p->state==SLEEP_MODE)) { return; } /* Enable SCI Channel*/ lnode_p->pSCI->scicr2.byte |= (SCICR2_RE_MASK | SCICR2_RIE_MASK); } void lin_lld_sci_int_disable ( /* [IN] sci channel name */ sci_channel_name channel ) { lin_node *lnode_p; #if (SCI_VERSION == SCI_V2) lnode_p = &lin_node_descrs[channel]; #else lnode_p = (lin_node *)&lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V2) */ /* Can't disable in interrupt context */ if((lnode_p->state == PROC_CALLBACK) || (lnode_p->state==UNINIT) || (lnode_p->state==SLEEP_MODE)) { return; } while(lnode_p->state != IDLE) {} /* Disable SCI Channel*/ lnode_p->pSCI->scicr2.byte &= ~(SCICR2_RE_MASK | SCICR2_RIE_MASK); } void lin_lld_sci_ignore_response ( /* [IN] sci channel name */ sci_channel_name channel ) { lin_goto_idle_state(channel); } void lin_lld_sci_set_low_power_mode ( /* [IN] sci channel name */ sci_channel_name channel ) { tSCI* _pSCI; lin_node *lnode_p; /* Get Lin node descriptor */ lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; /* Configure Hw code */ /* Set Lin status = receiving data*/ lnode_p->state=SLEEP_MODE; } void lin_lld_sci_rx_response ( /* [IN] sci channel name */ sci_channel_name channel, /* [IN] Length of response data expect to wait */ l_u8 msg_length ) { lin_node *lnode_p; /* Get Lin node descriptor */ #if (SCI_VERSION == SCI_V2) lnode_p = &lin_node_descrs[channel]; #else lnode_p = (lin_node *)&lin_node_descrs[channel]; #endif /* End (SCI_VERSION == SCI_V2) */ /* Put response length and pointer of response buffer into descriptor */ *(lnode_p->response_buffer)=msg_length; lnode_p->cnt_byte=0; lnode_p->ptr=lnode_p->response_buffer; /* Set Lin status = receiving data*/ lnode_p->state=RECV_DATA; } void lin_lld_sci_tx_response ( /* [IN] sci channel name */ sci_channel_name channel) { #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; /* calculate checksum */ lnode_p->response_buffer[*(lnode_p->response_buffer)+1] = lin_checksum(lnode_p->response_buffer , lnode_p->pid); lnode_p->cnt_byte=1; /* Send First byte */ lnode_p->pSCI->scid.byte = lnode_p->response_buffer[1]; /* Set LIN Status */ lnode_p->state = SEND_DATA; #else lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; /* calculate checksum */ lnode_p->response_buffer[*(lnode_p->response_buffer)+1] = lin_checksum(lnode_p->response_buffer , lnode_p->pid ); lnode_p->cnt_byte=1; /* Send First byte */ lnode_p->pSCI->scidrl.byte = lnode_p->response_buffer[1]; /* Set LIN Status */ lnode_p->state = SEND_DATA; #endif /* End (SCI_VERSION != SCI_V5) */ } /* End function lin_lld_sci_tx_response(sci_channel_name channel) */ l_u8 lin_lld_sci_get_status ( /* [IN] sci channel name */ sci_channel_name channel ) { lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; return lnode_p->l_status.byte; } l_u8 lin_lld_sci_get_state(sci_channel_name channel) { lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; return lnode_p->state; } void lin_lld_sci_timeout ( /* [IN] sci channel name */ sci_channel_name channel ) { register lin_node *lnode_p; #ifdef MULTI_TIMER_MODE l_u8 i; #endif /* End MULTI_TIMER_MODE */ /* multi frame support */ lin_configuration * conf; lin_tl_descriptor *tl_conf; l_ifc_handle iii; lnode_p = (lin_node *)&lin_node_descrs[channel]; iii = (l_ifc_handle)lnode_p->ifc; conf = (lin_configuration *)&lin_ifc_configuration[iii]; /* Get TL configuration */ tl_conf = conf->tl_desc; #if (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_) if (LD_CHECK_N_CR_TIMEOUT == tl_conf->tl_check_timeout_type) { if(0 == --tl_conf->tl_check_timeout) { /* switch to normal table */ if (_MASTER_ == conf->function) { *(conf->active_schedule_id) = *(conf->previous_schedule_id); conf->schedule_start_entry[*(conf->active_schedule_id)] = 0; } /* update status of transport layer */ *conf->diagnostic_mode = DIAG_NONE; *conf->tl_service_status = LD_SERVICE_ERROR; tl_conf->tl_receive_msg_status = LD_N_CR_TIMEOUT; tl_conf->tl_rx_msg_status = LD_N_CR_TIMEOUT; tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT; } } if (LD_CHECK_N_AS_TIMEOUT == tl_conf->tl_check_timeout_type) { if(0 == --tl_conf->tl_check_timeout) { /* switch to normal table */ if (_MASTER_ == conf->function) { *(conf->active_schedule_id) = *(conf->previous_schedule_id); conf->schedule_start_entry[*(conf->active_schedule_id)] = 0; } /* update status of transport layer */ *conf->diagnostic_mode = DIAG_NONE; *conf->tl_service_status = LD_SERVICE_ERROR; tl_conf->tl_tx_msg_status = LD_N_AS_TIMEOUT; tl_conf->tl_check_timeout_type = LD_NO_CHECK_TIMEOUT; } } #else if (LD_CHECK_N_AS_TIMEOUT == tl_check_timeout_type_array[iii]) { if(0 == --tl_check_timeout_array[iii]) { tl_conf->tl_service_status = LD_SERVICE_ERROR; tl_check_timeout_type_array[iii] = LD_NO_CHECK_TIMEOUT; } } #endif /* End (_TL_FRAME_SUPPORT_ == _TL_MULTI_FRAME_)*/ #if (SCI_VERSION == SCI_V2) switch(lnode_p->state) { case IDLE: if(lnode_p->idle_timeout_cnt==0) { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0xFF); /* goback to IDLE, reset max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; } else { lnode_p->idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == lnode_p->frame_timeout_cnt) { lin_goto_idle_state(channel); } else { lnode_p->frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(lnode_p->res_frame_timeout_cnt == 0) { if(lnode_p->cnt_byte) { /* set lin status: error_in_response */ lnode_p->l_status.byte |= LIN_STA_ERROR_RESP; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_NODATA_TIMEOUT, lnode_p->current_id); } lin_goto_idle_state(channel); } else { lnode_p->res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) switch(lnode_p->state) { case IDLE: if(lnode_p->idle_timeout_cnt==0) { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0xFF); /* goback to IDLE, reset max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /* disable LIN break detect interrupt */ lnode_p->pSCI->scisr2.bit.lbkde = 0; } else { lnode_p->idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == lnode_p->frame_timeout_cnt) { lin_goto_idle_state(channel); } else { lnode_p->frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(0 == lnode_p->res_frame_timeout_cnt) { if(lnode_p->cnt_byte) { /* set lin status: error_in_response */ lnode_p->l_status.byte |= LIN_STA_ERROR_RESP; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_NODATA_TIMEOUT, lnode_p->current_id); } lin_goto_idle_state(channel); } else { lnode_p->res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) switch(lnode_p->state) { case IDLE: if(lnode_p->idle_timeout_cnt==0) { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_BUS_ACTIVITY_TIMEOUT, 0xFF); /* goback to IDLE, reset max idle timeout */ #ifdef MULTI_TIMER_MODE for(i=0; iidle_timeout_cnt=max_idle_timeout[i]; break; } #else lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; #endif /* End (TIMER_MODE == MULTI_TIMER) */ } else { lnode_p->idle_timeout_cnt--; } break; case SEND_PID: /* Master */ case RECV_SYN: case RECV_PID: case SEND_DATA: case SEND_DATA_COMPLETED: /* timeout send has occurred - change state of the node and inform core */ if(0 == lnode_p->frame_timeout_cnt) { lin_goto_idle_state(channel); } else { lnode_p->frame_timeout_cnt--; } break; case RECV_DATA: /* timeout receive has occurred - change state of the node and inform core */ if(0 == lnode_p->res_frame_timeout_cnt) { if(lnode_p->cnt_byte) { /* set lin status: error_in_response */ lnode_p->l_status.byte |= LIN_STA_ERROR_RESP; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_NODATA_TIMEOUT, lnode_p->current_id); } lin_goto_idle_state(channel); } else { lnode_p->res_frame_timeout_cnt--; } break; case PROC_CALLBACK: break; default: break; } #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_lld_sci_timeout(sci_channel_name channel) */ /*** INTERNAL FUNTIONS ***/ void lin_goto_idle_state ( /* [IN] sci channel name */ sci_channel_name channel ) { #if (SCI_VERSION == SCI_V2) lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; /* set lin status: ~bus_activity */ lnode_p->l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; lnode_p->state=IDLE; #endif /* End (SCI_VERSION == SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; /* set lin status: ~bus_activity */ lnode_p->l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; lnode_p->state=IDLE; /* Enable LBK detect */ lnode_p->pSCI->scisr2.bit.lbkde = 1; #endif /* End (SCI_VERSION == SCI_V4) */ /*--------------------------------------------------------------------*/ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) lin_node *lnode_p; tSCI* _pSCI; #ifdef MULTI_TIMER_MODE l_u8 i; #endif /* End MULTI_TIMER_MODE */ lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; /* set lin status: ~bus_activity */ lnode_p->l_status.byte &= ~LIN_STA_BUS_ACTIVITY; /* Set max idle timeout */ #ifdef MULTI_TIMER_MODE for(i=0; iidle_timeout_cnt=max_idle_timeout[i]; break; } #else lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; #endif /* End MULTI_TIMER_MODE */ lnode_p->state=IDLE; #endif /* End (SCI_VERSION == SCI_V5) */ } /* End function lin_goto_idle_state(sci_channel_name channel) */ #if ((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) void lin_lld_sci_err_isr ( /* [IN] sci channel name */ sci_channel_name channel ) { #if (SCI_VERSION == SCI_V2) l_u8 sci_flag_sr1; l_u8 tmp_byte; register lin_node *lnode_p; /* local pointer to the lin node descriptor */ volatile tSCI *_pSCI; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; sci_flag_sr1 = _pSCI->scisr1.byte; tmp_byte = _pSCI->scid.byte; /****************************** *** 1. BREAK DETECTED *******************************/ if(0x00 == tmp_byte) { /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == lnode_p->state) { lin_goto_idle_state(channel); return; } /* Reset lin status */ lnode_p->l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ lnode_p->frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][7]; /****************************** *** 1.1 MASTER NODE: Sending SYN field *******************************/ if(lnode_p->func == _MASTER_/* Master */) { lnode_p->state=SEND_PID; /* Send syn field */ _pSCI->scid.byte = 0x55; } /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ else { lnode_p->state=RECV_SYN; } return; } /****************************** *** 3. FRAME ERROR DETECTED *******************************/ else { /* set lin status: error_in_response, framing_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* Trigger callback */ if((lnode_p->state == RECV_DATA)||(lnode_p->state == SEND_DATA)||(lnode_p->state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_FRAME_ERR, lnode_p->current_id); } lin_goto_idle_state(channel); } #endif /* End (SCI_VERSION = SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) l_u8 sci_flag_sr1; l_u8 tmp_byte; /* local pointer to the lin node descriptor */ register lin_node *lnode_p; lnode_p = (lin_node *)&lin_node_descrs[channel]; sci_flag_sr1 = lnode_p->pSCI->scisr1.byte; tmp_byte = lnode_p->pSCI->scid.byte; /****************************** *** 3. FRAME ERROR DETECTED *******************************/ /* set lin status: error_in_response, framing_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* Trigger callback */ if((lnode_p->state == RECV_DATA)||(lnode_p->state == SEND_DATA)||(lnode_p->state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_FRAME_ERR, lnode_p->current_id); } lin_goto_idle_state(channel); #endif /* End (SCI_VERSION = SCI_V4) */ } /* End function lin_lld_sci_err_isr(sci_channel_name channel) */ void lin_lld_sci_rx_isr ( /* [IN] sci channel name */ sci_channel_name channel ) { #if (SCI_VERSION == SCI_V2) l_u8 sci_flag_sr1; l_u8 tmp_byte; /* local pointer to the lin node descriptor */ register lin_node *lnode_p; /* pointer to the SCI peripheral */ volatile tSCI* _pSCI; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; sci_flag_sr1 = _pSCI->scisr1.byte; tmp_byte = _pSCI->scid.byte; /* Set max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; /****************************** *** 4. BYTE RECIEVED *******************************/ if(0 != (sci_flag_sr1&SCISR1_RDRF_MASK)) { switch(lnode_p->state) { /****************************** *** 4.1 MASTER: Sending PID of frame *******************************/ case SEND_PID: lnode_p->state=RECV_PID; /* Send PID byte */ _pSCI->scid.byte = lnode_p->pid; break; /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55U == tmp_byte) { lnode_p->state=RECV_PID; } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(channel); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: if(lnode_p->func == _MASTER_) /*Master*/ { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer) - 1]; } else /* Slave node */ { /* checkparity and extrait PID */ lnode_p->current_id= lin_process_parity(tmp_byte, CHECK_PARITY); lnode_p->pid = tmp_byte; if(lnode_p->current_id != 0xFFU) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer) - 1]; } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* set lin status: parity_error */ lnode_p->l_status.byte |= LIN_STA_PARITY_ERR; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_ERR, 0x00); lin_goto_idle_state(channel); } } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: lnode_p->ptr++; *(lnode_p->ptr)=tmp_byte; /* Check bytes received fully */ if(lnode_p->cnt_byte==(lnode_p->response_buffer[0])) { /* checksum checking */ if(lin_checksum(lnode_p->response_buffer, lnode_p->pid)==tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* set lin status: successful_transfer */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_RX_COMPLETED, lnode_p->current_id); if (SLEEP_MODE != lnode_p->state) { lin_goto_idle_state(channel); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* set lin status: error_in_response, checksum_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_CHECKSUM_ERR, lnode_p->current_id); lin_goto_idle_state(channel); } } lnode_p->cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: /* Check for READBACK error */ if (0==(sci_flag_sr1&SCISR1_TC_MASK)) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lin_goto_idle_state(channel); break; } else { if (tmp_byte != lnode_p->response_buffer[lnode_p->cnt_byte]) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lin_goto_idle_state(channel); break; } } if(lnode_p->cnt_byte <= (lnode_p->response_buffer[0])) { /* Send data bytes and checksum */ lnode_p->cnt_byte++; _pSCI->scid.byte = lnode_p->response_buffer[lnode_p->cnt_byte]; } else { /* TX transfer complete */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_TX_COMPLETED, lnode_p->current_id); lin_goto_idle_state(channel); } break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: if ((tmp_byte == 0xF0U) || (tmp_byte == 0xE0U) || (tmp_byte == 0xC0U) || (tmp_byte == 0x80U) || (tmp_byte == 0x00U)) { /* Set idle timeout again */ lin_goto_idle_state(channel); } break; default: break; } } #endif /* End (SCI_VERSION = SCI_V2) */ /*--------------------------------------------------------------------*/ #if (SCI_VERSION == SCI_V4) l_u8 sci_flag_sr1; l_u8 sci_flag_sr2; l_u8 tmp_byte; register lin_node *lnode_p; /* local pointer to the lin node descriptor */ volatile tSCI* _pSCI; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; sci_flag_sr2 = _pSCI->scisr2.byte ; /* Set max idle timeout */ lnode_p->idle_timeout_cnt=_MAX_IDLE_TIMEOUT_; if((sci_flag_sr2 & SCISR2_RXEDGIF_MASK) && (!(sci_flag_sr2 & SCISR2_LBKDIF_MASK))) { /* Clear flag */ _pSCI->scisr2.bit.rxedgif = 1; /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == lnode_p->state) { lin_goto_idle_state(channel); } /* Enable Break interrupt */ _pSCI->scibdh.byte |= SCIBDH_LBKDIE_MASK ; /* Disable Active Edge interrupt */ _pSCI->scibdh.byte &= ~SCIBDH_RXEDGIE_MASK; /* Receive data not inverted */ _pSCI->scisr2.bit.rxinv = 0; return; } /* Check LBK flag */ if (1 == _pSCI->scisr2.bit.lbkdif) { /* Clear flag */ _pSCI->scisr2.bit.lbkdif = 1; /* Enable Active Edge interrupt */ _pSCI->scibdh.byte |= SCIBDH_RXEDGIE_MASK; /* Disable Break interrupt */ _pSCI->scibdh.byte &= ~SCIBDH_LBKDIE_MASK ; /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == lnode_p->state) { lin_goto_idle_state(channel); return; } /* Reset lin status */ lnode_p->l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ lnode_p->frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][7]; /****************************** *** 1.1 MASTER NODE: Sending SYN field *******************************/ if(lnode_p->func == 0/* Master */) { lnode_p->state=SEND_PID; /* Send syn field */ _pSCI->scid.byte = 0x55; } /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ else { lnode_p->state=RECV_SYN; } /* Disable LBK interrupt */ _pSCI->scisr2.bit.lbkde = 0; return; } else { sci_flag_sr1 = lnode_p->pSCI->scisr1.byte; tmp_byte = lnode_p->pSCI->scid.byte; /****************************** *** 4. BYTE RECIEVED *******************************/ if(0 != (sci_flag_sr1&SCISR1_RDRF_MASK)) { switch(lnode_p->state) { /****************************** *** 4.1 MASTER: Sending PID of frame *******************************/ case SEND_PID: lnode_p->state=RECV_PID; /* Send PID byte */ _pSCI->scid.byte = lnode_p->pid; break; /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55 == tmp_byte) { lnode_p->state=RECV_PID; } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(channel); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: if(!lnode_p->func) /*Master*/ { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer) - 1]; } else /* Slave node */ { /* checkparity and extrait PID */ lnode_p->current_id= lin_process_parity(tmp_byte, CHECK_PARITY); /* Keep the PID */ lnode_p->pid = tmp_byte; if(lnode_p->current_id !=0xFF) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer) - 1]; } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* Set lin status: parity_error */ lnode_p->l_status.byte |= LIN_STA_PARITY_ERR; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_ERR, 0xFF); lin_goto_idle_state(channel); } } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: lnode_p->ptr++; *(lnode_p->ptr)=tmp_byte; /* Check bytes received fully */ if(lnode_p->cnt_byte==(lnode_p->response_buffer[0])) { /* Checksum checking */ if(lin_checksum(lnode_p->response_buffer, lnode_p->pid)==tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* Set lin status: successful_transfer */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_RX_COMPLETED, lnode_p->current_id); if (SLEEP_MODE != lnode_p->state) { lin_goto_idle_state(channel); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* Set lin status: error_in_response, checksum_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_CHECKSUM_ERR, lnode_p->current_id); lin_goto_idle_state(channel); } } lnode_p->cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: /* Check for READBACK error */ if (0==(sci_flag_sr1&SCISR1_TC_MASK)) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lin_goto_idle_state(channel); break; } else { if (tmp_byte != lnode_p->response_buffer[lnode_p->cnt_byte]) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lin_goto_idle_state(channel); break; } } if(lnode_p->cnt_byte <= (lnode_p->response_buffer[0])) { /* Send data bytes and checksum */ lnode_p->cnt_byte++; _pSCI->scid.byte = lnode_p->response_buffer[lnode_p->cnt_byte]; } else { /* TX transfer complete */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_TX_COMPLETED, lnode_p->current_id); lin_goto_idle_state(channel); } break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: if ((tmp_byte == 0xF0U) || (tmp_byte == 0xE0U) || (tmp_byte == 0xC0U) || (tmp_byte == 0x80U) || (tmp_byte == 0x00U)) { /* Set idle timeout again */ lin_goto_idle_state(channel); /* Disable LIN break detect interrupt */ _pSCI->scisr2.bit.lbkde = 1; } break; default: break; } } } #endif /* End (SCI_VERSION = SCI_V4) */ } /* End function lin_lld_sci_rx_isr(sci_channel_name channel) */ #endif /* End((SCI_VERSION != SCI_V5) && (SCI_VERSION != SCI_V6)) */ #if ((SCI_VERSION == SCI_V5) || (SCI_VERSION == SCI_V6)) void lin_lld_sci_isr ( /* [IN] sci channel name */ sci_channel_name channel ) { l_u8 sci_flag_sr1; l_u8 tmp_byte; l_u8 i; /* Local pointer to the lin node descriptor */ register lin_node *lnode_p; /* Pointer to the SCI peripheral */ volatile tSCI* _pSCI; lnode_p = (lin_node *)&lin_node_descrs[channel]; _pSCI = lnode_p->pSCI; sci_flag_sr1 = _pSCI->scisr1.byte; /* Set max idle timeout */ #ifdef MULTI_TIMER_MODE for(i = 0; i < LIN_NUM_OF_IFCS; i++) if (channel == lin_virtual_ifc[i]) { lnode_p->idle_timeout_cnt = max_idle_timeout[i]; break; } #else lnode_p->idle_timeout_cnt = _MAX_IDLE_TIMEOUT_; #endif /* MULTI_TIMER_MODE */ /****************************** *** 1. BREAK DETECTED *******************************/ if(0 != (_pSCI->sciasr1.byte&SCIASR1_BKDIF_MASK)) { /* Clear the error flag */ _pSCI->sciasr1.byte |=SCIASR1_BKDIF_MASK; /* check state of node is SLEEP_MODE */ if (SLEEP_MODE == lnode_p->state) { lin_goto_idle_state(channel); return; } /* Handle error */ if((RECV_DATA == lnode_p->state) || (SEND_DATA == lnode_p->state) || (SEND_DATA_COMPLETED == lnode_p->state)) { /* Read dummy data to clear FE flags */ tmp_byte = _pSCI->scidrl.byte; /* Set lin status: error_in_response, framing_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_FRAME_ERR, lnode_p->current_id); } /* Reset lin status */ lnode_p->l_status.byte = LIN_STA_BUS_ACTIVITY; /* Set max frame timeout */ lnode_p->frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][7]; /****************************** *** 1.1 MASTER NODE: Sending SYN field *******************************/ if(lnode_p->func == 0/* Master */) { lnode_p->state=SEND_PID; /* Send syn field */ _pSCI->scidrl.byte = 0x55; } /****************************** *** 1.2 SLAVE NODE: Wait for SYN *******************************/ else { lnode_p->state=RECV_SYN; } return; } /****************************** *** 2. BIT ERROR DETECTED *******************************/ else if(0 != (_pSCI->sciasr1.byte&SCIASR1_BERRIF_MASK)) { _pSCI->sciasr1.byte |= SCIASR1_BERRIF_MASK; /* set lin status: error_in_response, readback_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_READBACK_ERR); if((lnode_p->state == SEND_DATA)||(lnode_p->state == SEND_DATA_COMPLETED)) { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); /* If Bit error occurs when a logic 0 is accepted as stop bit, then this case causes Framing error too*/ /* In this case, wait for about 20 for loops, so that SCI hardware have enough time to set Framing error flag*/ for (i=0; i<200; i++); /* Check if Framing error flag is set */ if(0 != (_pSCI->scisr1.byte&SCISR1_FE_MASK)) { return; } } lin_goto_idle_state(channel); return; } /****************************** *** 3. FRAME ERROR DETECTED *******************************/ if(0 != (sci_flag_sr1&SCISR1_FE_MASK)) { /* Clear FE flags */ _pSCI->scisr1.byte |= SCISR1_FE_MASK; tmp_byte = _pSCI->scidrl.byte; /* Set lin status: error_in_response, framing_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_FRAME_ERR); /* Trigger callback */ if((lnode_p->state == RECV_DATA)||(lnode_p->state == SEND_DATA) || (lnode_p->state == SEND_DATA_COMPLETED)) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_FRAME_ERR, lnode_p->current_id); } lin_goto_idle_state(channel); } /****************************** *** 4. BYTE RECIEVED *******************************/ else if(0 != (sci_flag_sr1&SCISR1_RDRF_MASK)) { tmp_byte = _pSCI->scidrl.byte; switch(lnode_p->state) { /****************************** *** 4.1 MASTER: Sending PID of frame *******************************/ case SEND_PID: lnode_p->state=RECV_PID; /* Send PID byte */ _pSCI->scidrl.byte = lnode_p->pid; break; /****************************** *** 4.2 SLAVE: Receiving SYN byte *******************************/ case RECV_SYN: if (0x55 == tmp_byte) { lnode_p->state=RECV_PID; } else { #if (LIN_PROTOCOL == PROTOCOL_J2602) CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); #endif /* End of (LIN_PROTOCOL == PROTOCOL_J2602) */ lin_goto_idle_state(channel); } break; /****************************** *** 4.3 SLAVE: Receiving PID *******************************/ case RECV_PID: if(!lnode_p->func) /*Master*/ { /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer)-1]; } else /* Slave node */ { /* Checkparity and extrait PID */ lnode_p->pid=tmp_byte; lnode_p->current_id = lin_process_parity(tmp_byte,CHECK_PARITY); if(lnode_p->current_id !=0xFF) { /*****************************************/ /*** ID received correctly - parity OK ***/ /*****************************************/ /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_OK, lnode_p->current_id); /* Set Maximum response frame timeout */ lnode_p->res_frame_timeout_cnt = lin_max_frame_res_timeout_val[lnode_p->ifc][*(lnode_p->response_buffer)-1]; } else { /*****************************************/ /*** ID Parity Error ***/ /*****************************************/ /* Set lin status: parity_error */ lnode_p->l_status.byte |= LIN_STA_PARITY_ERR; /* Crigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_PID_ERR, 0xFF); lin_goto_idle_state(channel); } } break; /****************************** *** 4.4 SLAVE: Receiving data *******************************/ case RECV_DATA: lnode_p->ptr++; *(lnode_p->ptr)=tmp_byte; /* Check bytes received fully */ if(lnode_p->cnt_byte==(lnode_p->response_buffer[0])) { /* Checksum checking */ if(lin_checksum(lnode_p->response_buffer, lnode_p->pid)==tmp_byte) { /*******************************************/ /*** RX Buffer Full - Checksum OK ***/ /*******************************************/ /* Set lin status: successful_transfer */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_RX_COMPLETED, lnode_p->current_id); if (SLEEP_MODE != lnode_p->state) { lin_goto_idle_state(channel); } } else { /*******************************************/ /*** RX Buffer Full - Checksum ERROR ***/ /*******************************************/ /* set lin status: error_in_response, checksum_error */ lnode_p->l_status.byte |= (LIN_STA_ERROR_RESP|LIN_STA_CHECKSUM_ERR); /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_CHECKSUM_ERR, lnode_p->current_id); lin_goto_idle_state(channel); } } lnode_p->cnt_byte++; break; /****************************** *** 4.5 SLAVE: Sending data *******************************/ case SEND_DATA: if (0 == (sci_flag_sr1&SCISR1_TC_MASK )) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lnode_p->state = PROC_CALLBACK; lin_goto_idle_state(channel); break; } if(lnode_p->cnt_byte==(lnode_p->response_buffer[0])) { /* Send checksum byte */ _pSCI->scidrl.byte = lnode_p->response_buffer[lnode_p->cnt_byte+1]; lnode_p->state= SEND_DATA_COMPLETED; } else { /* Send byte next */ lnode_p->cnt_byte++; _pSCI->scidrl.byte = lnode_p->response_buffer[lnode_p->cnt_byte]; } break; /****************************** *** 4.7 SLAVE: Sending data compeleted *******************************/ case SEND_DATA_COMPLETED: /*******************************************/ /*** TX Buffer Empty - Checksum Sent ***/ /*******************************************/ if (0 == (sci_flag_sr1&SCISR1_TC_MASK )) { CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_READBACK_ERR, lnode_p->current_id); lnode_p->state = PROC_CALLBACK; lin_goto_idle_state(channel); break; } /* set lin status: successful_transfer */ lnode_p->l_status.byte |= LIN_STA_SUCC_TRANSFER; lnode_p->state = PROC_CALLBACK; /* Trigger callback */ CALLBACK_HANDLER((l_ifc_handle)lnode_p->ifc, LIN_LLD_TX_COMPLETED, lnode_p->current_id); lin_goto_idle_state(channel); break; /****************************** *** 4.8 SLAVE: Low power mode *******************************/ case SLEEP_MODE: if ((tmp_byte == 0xFFU) || (tmp_byte == 0xFEU) || (tmp_byte == 0xFCU) || (tmp_byte == 0xF8U) || (tmp_byte == 0xF0U)|| (tmp_byte == 0xE0U)|| (tmp_byte == 0xC0U)|| (tmp_byte == 0x80U)|| (tmp_byte == 0x00U)) { /* Set idle timeout again */ lin_goto_idle_state(channel); } break; default: break; } } /****************************** *** 5. OVERRUN ERROR DETECTED *******************************/ if(0 != (sci_flag_sr1&SCISR1_OR_MASK)) { /* Read SCIDRL Register to clear OR flag*/ tmp_byte = _pSCI->scidrl.byte; lin_goto_idle_state(channel); } } /* End function lin_lld_sci_isr(sci_channel_name channel) */ #endif /* End (SCI_VERSION = SCI_V5) */ #endif /* End (LIN_MODE == _MASTER_MODE_) */ /** * @} */