/*! * @file tp_cca.c * @brief TP layer file according to the 15765-2. * */ #include "uds_config.h" /*! * Macro. Minumum of the first frame data length */ #define MINIMUM_FIRST_FRAME_DATA_LENGTH 8 /*! * Macro. Dynamic tp para update enable */ #define DYNAMIC_TP_PARA_UPDATE_ENABLE 0 static uint8_t TP_Tx_Message_Status; /*!< Transmit Message Status */ static uint8_t TP_Tx_Block_Size; /*!< Transmit Block Size */ static uint8_t TP_Tx_Block_Size_Constant; /*!< Transmit Block Size Constant */ static uint8_t TP_Tx_Separation_Time_Min_Constant; /*!< Min of Transmit Separation time constant */ static uint8_t TP_Tx_Separation_Time_min; /*!< Min of Transmit Separation time */ static uint8_t TP_Tx_Sequence_Number; /*!< Transmit sequence number */ static uint8_t TP_Transmit_Sub_State; /*!< Transmit sub state */ uint16_t TP_Tx_Message_DLC; /*!< Transmit Message DLC */ static uint8_t TP_Tx_Frame_Type; /*!< Transmit Frame Type */ static uint16_t TP_Tx_Index; /*!< Transmit Index */ static uint8_t TP_Tx_Frame_DLC; /*!< Transmit Frame DLC */ //static uint8_t TP_Transmit_Message_Number_Physical; /*!< Transmit transmit message physical number */ static uint8_t TP_Rx_Message_Status; /*!< Receive message Status */ static uint16_t TP_Rx_Block_Size; /*!< Receive Block Size */ //static uint16_t TP_Rx_Block_Size_Parameter; /*!< Receive Block size Parameter */ //static uint8_t TP_Rx_Seperation_Time_Parameter; /*!< Receive Seperation Time Parameter */ static uint8_t TP_Rx_Sequence_Number; /*!< Receive sequence number */ static uint8_t TP_Receive_Sub_State; /*!< Receive sub state */ static uint16_t TP_Rx_Message_DLC; /*!< Receive Message DLC */ static uint8_t TP_Rx_Frame_Type; /*!< Receive Frame type */ uint16_t TP_Rx_Index; /*!< Receive Index */ static uint16_t TP_Rx_Frame_DLC; /*!< Receive Frame DLC */ //static uint8_t TP_Receive_Message_Number_Physical; /*!< Receive Message Number Physical */ //static uint8_t TP_Receivet_Message_Number_Functional; /*!< Receive Message Number Functional */ uint16_t TP_Rx_Message_Length; /*!< Receive Message Length */ static uint16_t TPN_As_Timer; /*!< AS Timer */ static uint16_t TPN_Ar_Timer; /*!< Ar Timer */ static uint16_t TPN_Bs_Timer; /*!< Bs Timer */ static uint16_t TPN_Cr_Timer; /*!< Cr Timer */ static uint8_t TP_State; /*!< State of tp layer */ static uint16_t TP_Data_Count; /*!< Data Count */ static uint16_t TP_Next_Loop_Count; /*!< Next Loop Count */ static uint8_t Flow_Status; /*!< Flow Status */ static uint8_t TP_Result; /*!< Result */ static uint8_t TP_Change_Parameter_Result; /*!< Change parameter Result */ static uint8_t TP_Request_Type; /*!< Request type */ bool Frame_Tx_Complete; /*!< Frame transmit complete flag */ static bool Frame_Available; /*!< Frame available flag */ static bool Load_Consecutive_Frame; /*!< Load CF flag */ static uint8_t TP_Tx_Buffer_Status; /*!< Tx Buffer Status */ static uint8_t TP_Rx_Buffer_Status; /*!< Rx Buffer Status */ static uint8_t TP_N_As_Timer_Control; /*!< As Timer Control */ static uint8_t TP_N_Ar_Timer_Control; /*!< Ar Timer Control */ static uint8_t TP_N_Bs_Timer_Control; /*!< Bs Timer Control */ static uint8_t TP_N_Cr_Timer_Control; /*!< Cr Timer Control */ static bool Update_Tp_Parameter_Req = DYNAMIC_TP_PARA_UPDATE_ENABLE; uint8_t TP_Buffer[TP_BUFFER_SIZE]; /*!< TP Buffer */ //uint8_t TP_Tx_Buffer[TP_BUFFER_SIZE]; static uint8_t TP_Frame_Array[FRAME_DATA_SIZE]; /*!< Frame Buffer */ /* functions local to TP Module */ static void TP_Transmit_Single_OR_First_Frame (void); static void TP_Receive_Single_OR_First_Frame (void); static void TP_Transmit_Consecutive_Frame (void); static void TP_Receive_Consecutive_Frame (void); static void TP_Check_Rx_Message_Length (void); static void TP_Transmit_Flow_Control (void); static void TP_Update_Timers (void); static bool TP_Received_DLC_Check (void); static uint8_t TP_STmin_Calculate (void); static void TP_Idle_State_Process (void); static void TP_Wait_For_SFORFF_TxConf_State_Process (void); static void TP_Wait_For_FCFrame_Rx_State_Process (void); static void TP_Transmit_CF_State_Process (void); static void TP_Wait_For_CF_TxConf_State_Process (void); static void TP_Wait_For_STmin_State_Process (void); static void TP_Wait_For_FC_TXconf_State_Process (void); static void TP_Rx_CF_State_Process (void); static void TP_Wait_For_DataRead_State_Process (void); static void TP_Tx_To_Idle_Init (uint8_t TP_Result); static void TP_FC_Frame_Process (void); static void TP_Rx_To_Idle_Init (uint8_t TP_Result); static void TP_Transmit_Single_Frame (void); static void TP_Transmit_First_Frame (void); static void TP_Receive_Single_Frame (void); static void TP_Receive_First_Frame (void); static void TP_Tx_Load_CF_Data_Process (void); static void TP_Tx_Load_Remaining_Bytes_OF_CF_Process (void); static void TP_Tx_Load_Remaining_Bytes_OF_Last_CF_Process (void); static void TP_Load_TL_Buffer_Start_NAs_Timer (void); static void TP_Update_SN_and_BS (void); static void TP_Tx_CF_Data_Process (void); static void TP_Tx_Last_CF_Data_Process (void); static void TP_Rx_Unload_CF_Data_Process (void); static void TP_Rx_Unload_Remaining_Bytes_OF_CF_Process (void); static void TP_Rx_Unload_Remaining_Bytes_OF_Last_CF_Process (void); static void TP_Rx_CF_Data_Process (void); static void TP_Rx_Last_CF_Data_Process (void); /*! * @brief TP_Init * Read the message numbers from the TL config table, Initialize * the state to idle, transmit and recieve status init, buffer status init, * Timers disabling, loads the default value's of BS and STmin to * variables. */ void TP_Init (void) { /* Reads the Message number/Index from the TL config table */ #ifdef TP_DIAG_PHYSICAL_MSG_SUPPORT // TP_Transmit_Message_Number_Physical = 8; // TP_Receive_Message_Number_Physical = 8; #endif #ifdef TP_DIAG_FUNCTIONAL_MSG_SUPPORT // TP_Receivet_Message_Number_Functional = 8; #endif TP_State = TP_Idle_State; TP_Tx_Message_Status = TP_TRANSMIT_IDLE; TP_Rx_Message_Status = TP_RECEIVE_IDLE; TP_Tx_Buffer_Status = EMPTY; TP_Rx_Buffer_Status = EMPTY; Frame_Tx_Complete = false; // Frame_Tx_Complete_Flag_For_Reset = false; Frame_Available = false; TP_N_As_Timer_Control = TIMER_STOP; TP_N_Ar_Timer_Control = TIMER_STOP; TP_N_Bs_Timer_Control = TIMER_STOP; TP_N_Cr_Timer_Control = TIMER_STOP; Flow_Status = CLEAR_TO_SEND; /* default block size for receive. */ // TP_Rx_Block_Size_Parameter = TP_RX_BLOCK_SIZE_MAX; /* default STmin for receive. */ // TP_Rx_Seperation_Time_Parameter = TP_RX_SEPARATION_TIME_MIN; Load_Consecutive_Frame = false; }/* End of TP_Init*/ void TP_Task(void) { //U32 context = hwi_disable_interrupts_savestate(); switch (TP_State) { case TP_Idle_State: TP_Idle_State_Process(); break; case TP_Wait_For_SFORFF_TxConf_State: TP_Wait_For_SFORFF_TxConf_State_Process(); break; case TP_Wait_For_FCFrame_Rx_State: TP_Wait_For_FCFrame_Rx_State_Process(); break; case TP_Transmit_CF_State: TP_Transmit_CF_State_Process(); break; case TP_Wait_For_CF_TxConf_State: TP_Wait_For_CF_TxConf_State_Process(); break; case TP_Wait_For_STmin_State: TP_Wait_For_STmin_State_Process(); break; case TP_Wait_For_FC_TXconf_State: TP_Wait_For_FC_TXconf_State_Process(); break; case TP_Rx_CF_State: TP_Rx_CF_State_Process(); break; case TP_Wait_For_DataRead_State: TP_Wait_For_DataRead_State_Process(); break; default: break; } //hwi_restore_interrupts( context ); } /*! * @brief TP_Periodic_Task * Main task which handles both transmit and receive portion of * Network Layer */ void TP_Periodic_Task (void) { TP_Update_Timers(); TP_Task(); }/* End of TP_Periodic_Task*/ /*! * @brief TP_Idle_State_Process * This function handles TP_Idle_State * */ static void TP_Idle_State_Process (void) { if (Frame_Available == true) { Frame_Available = false; TP_Receive_Single_OR_First_Frame(); } } /*! * @brief TP_Wait_For_SFORFF_TxConf_State_Process * This function handles TP_Wait_For_SFORFF_TxConf_State */ static void TP_Wait_For_SFORFF_TxConf_State_Process (void) { if (TPN_As_Timer == 0) { TP_Result = N_TIMEOUT_A; TP_Tx_To_Idle_Init (TP_Result); } else if (Frame_Tx_Complete == true) { Frame_Tx_Complete = false; TP_N_As_Timer_Control = TIMER_STOP; if (TP_Tx_Frame_Type == SINGLE_FRAME) { TP_Result = N_OK; TP_Tx_To_Idle_Init (TP_Result); } else if (TP_Tx_Frame_Type == FIRST_FRAME) { Update_Tp_Parameter_Req = TRUE; TP_State = TP_Wait_For_FCFrame_Rx_State; } else { /* do nothing */ } } else { /* do nothing */ } } /*! * @brief TP_Wait_For_FCFrame_Rx_State_Process * This function handles TP_Wait_For_FCFrame_Rx_State */ static void TP_Wait_For_FCFrame_Rx_State_Process (void) { uint8_t FlowControlStatus; if (TPN_Bs_Timer == 0) { TP_Result = N_TIMEOUTBs; TP_Tx_To_Idle_Init (TP_Result); } else if (Frame_Available == true) { Frame_Available = false; TP_Rx_Frame_Type = TP_Frame_Array[0] & FRAME_TYPE_MASK; if (TP_Rx_Frame_Type == FLOW_CONTROL_FRAME) { TP_N_Bs_Timer_Control = TIMER_STOP; FlowControlStatus = TP_Frame_Array[0] & FLOW_STATUS_MASK; if (false == TP_Received_DLC_Check()) { TP_Result = N_WRONG_DLC; TP_Tx_To_Idle_Init (TP_Result); } else { if (FlowControlStatus >= RESERVED) { TP_Result = N_INVALID_FS; TP_Tx_To_Idle_Init (TP_Result); } else if (FlowControlStatus == OVERFLOW) { TP_Result = N_BUFFER_OVFLW; TP_Tx_To_Idle_Init (TP_Result); } else if (FlowControlStatus == WAIT) { if (N_WAIT_FRAME_TX_MAX == 0) { TP_Result = N_WFT_OVRN; TP_Tx_To_Idle_Init (TP_Result); } /* A count of 1 less is loaded as Bs timeout was exceeding max set */ TPN_Bs_Timer = (N_Bs_TIMER_COUNT) - 1; TP_N_Bs_Timer_Control = TIMER_RUN; } else if (FlowControlStatus == CLEAR_TO_SEND) { TP_FC_Frame_Process(); } else { /* do nothing */ } } } } else { /* do nothing */ } } /*! * @brief TP_Transmit_CF_State_Process * This function handles TP_Transmit_CF_State */ static void TP_Transmit_CF_State_Process (void) { TP_Transmit_Consecutive_Frame(); if (TP_Transmit_Sub_State == TP_TX_LOAD_CF_DATA) { TP_State = TP_Wait_For_CF_TxConf_State; } } /*! * @brief TP_Wait_For_CF_TxConf_State_Process * This function handles TP_Wait_For_CF_TxConf_State */ static void TP_Wait_For_CF_TxConf_State_Process (void) { if (TPN_As_Timer == 0) { TP_Result = N_TIMEOUT_A; TP_Tx_To_Idle_Init (TP_Result); } else if ( (Frame_Tx_Complete == true) || (Load_Consecutive_Frame == true)) { TP_N_As_Timer_Control = TIMER_STOP; Frame_Tx_Complete = false; if (TP_Tx_Message_DLC == 0) { TP_Result = N_OK; TP_Tx_To_Idle_Init (TP_Result); } else if ( (TP_Tx_Block_Size_Constant != 0) && (TP_Tx_Block_Size == 0)) { Update_Tp_Parameter_Req = DYNAMIC_TP_PARA_UPDATE_ENABLE; TP_State = TP_Wait_For_FCFrame_Rx_State; } else if ( (TP_Tx_Separation_Time_Min_Constant == ZERO_LOOP_COUNT) || (TP_Tx_Separation_Time_Min_Constant == ONE_LOOP_COUNT)) { TP_Transmit_Consecutive_Frame(); if (TP_Transmit_Sub_State == TP_TX_LOAD_CF_DATA) { Load_Consecutive_Frame = false; } else { Load_Consecutive_Frame = true; } } else if (TP_Tx_Separation_Time_Min_Constant == TWO_LOOP_COUNT) { TP_State = TP_Transmit_CF_State; } else if (TP_Tx_Separation_Time_Min_Constant > TWO_LOOP_COUNT) { TP_Tx_Separation_Time_min--; TP_State = TP_Wait_For_STmin_State; } else { /* do nothing */ } } else { /* do nothing */ } } /*! * @brief TP_Wait_For_STmin_State_Process * This function handles TP_Wait_For_STmin_State */ static void TP_Wait_For_STmin_State_Process (void) { TP_Tx_Separation_Time_min--; if (TP_Tx_Separation_Time_min <= 1) { TP_State = TP_Transmit_CF_State; TP_Tx_Separation_Time_min = TP_Tx_Separation_Time_Min_Constant; } } /*! * @brief TP_Wait_For_FC_TXconf_State_Process * This function handles TP_Wait_For_FC_TXconf_State */ static void TP_Wait_For_FC_TXconf_State_Process (void) { if (Frame_Tx_Complete == true) { Frame_Tx_Complete = false; TP_N_Ar_Timer_Control = TIMER_STOP; TP_State = TP_Rx_CF_State; TPN_Cr_Timer = N_Cr_TIMER_COUNT; TP_N_Cr_Timer_Control = TIMER_RUN; } else if (TPN_Ar_Timer == 0) { TP_Result = N_TIMEOUT_A; TP_Rx_To_Idle_Init (TP_Result); } else { /* do nothing */ } } /*! * @brief TP_Rx_CF_State_Process * This function handles TP_Rx_CF_State */ static void TP_Rx_CF_State_Process (void) { if (TPN_Cr_Timer == 0) { TP_Result = N_TIMEOUTCr; TP_Rx_To_Idle_Init (TP_Result); } else if (Frame_Available == true) { Frame_Available = false; TP_N_Cr_Timer_Control = TIMER_STOP; TP_Rx_Frame_Type = TP_Frame_Array[0] & FRAME_TYPE_MASK; if ( (TP_Rx_Frame_Type == SINGLE_FRAME) || (TP_Rx_Frame_Type == FIRST_FRAME)) { TP_Result = N_UNEXP_PDU; TP_Rx_To_Idle_Init (TP_Result); TP_Receive_Single_OR_First_Frame(); } else if (TP_Rx_Frame_Type == CONSECUTIVE_FRAME) { if (false == TP_Received_DLC_Check()) { TP_Result = N_WRONG_DLC; TP_Rx_To_Idle_Init (TP_Result); } else { if (TP_Rx_Sequence_Number == (TP_Frame_Array[0] & SEQUENCE_NUMBER_MASK)) { TP_Receive_Sub_State = TP_RX_UNLOAD_CF_DATA; TP_Receive_Consecutive_Frame(); TPN_Cr_Timer = N_Cr_TIMER_COUNT; TP_N_Cr_Timer_Control = TIMER_RUN; if (TP_Receive_Sub_State == TP_RX_UNLOAD_CF_DATA) { TP_Check_Rx_Message_Length(); } } else { TP_Result = N_WRONG_SN; TP_Rx_To_Idle_Init (TP_Result); } } } else { /* do nothing */ } } else { /* do nothing */ } } /*! * @brief TP_Wait_For_DataRead_State_Process * This function handles TP_Wait_For_DataRead_State */ static void TP_Wait_For_DataRead_State_Process (void) { if (TPN_Cr_Timer == 0) { TP_Result = N_TIMEOUTCr; TP_Rx_To_Idle_Init (TP_Result); } else if (Frame_Available == true) { Frame_Available = false; TP_Result = TP_BUFFER_OVER_FLOW; TP_Rx_To_Idle_Init (TP_Result); } else { TP_Receive_Consecutive_Frame(); if (TP_Receive_Sub_State == TP_RX_UNLOAD_CF_DATA) { TP_Check_Rx_Message_Length(); } } } /*! * @brief TP_Tx_To_Idle_Init * This function handles TP transmit variables initialization * when transmit operation is completed suceesfully / unsuceesfully * * @param TP_Result TP Result */ static void TP_Tx_To_Idle_Init (uint8_t TP_Result) { UCB_TP_N_USData_Confirm (TP_Result); TP_State = TP_Idle_State; TP_Tx_Message_Status = TP_TRANSMIT_IDLE; TP_Tx_Buffer_Status = EMPTY; Frame_Tx_Complete = false; } /*! * @brief TP_FC_Frame_Process * This function handles flow control parameter processing */ static void TP_FC_Frame_Process (void) { if (Update_Tp_Parameter_Req) { TP_Tx_Block_Size_Constant = TP_Frame_Array[1]; /* function to calcualte stmin */ TP_Tx_Separation_Time_Min_Constant = TP_STmin_Calculate(); } TP_Tx_Block_Size = TP_Tx_Block_Size_Constant; TP_Tx_Separation_Time_min = TP_Tx_Separation_Time_Min_Constant; TP_Transmit_Sub_State = TP_TX_LOAD_CF_DATA; TP_Transmit_Consecutive_Frame(); if (TP_Transmit_Sub_State == TP_TX_LOAD_CF_DATA) { TP_State = TP_Wait_For_CF_TxConf_State; } else { TP_State = TP_Transmit_CF_State; } } /*! * @brief TP_Rx_To_Idle_Init * This function handles TP receive variables initialization * when receive operation is completed suceesfully / unsuceesfully */ static void TP_Rx_To_Idle_Init (uint8_t TP_Result) { UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); TP_State = TP_Idle_State; TP_Rx_Message_Status = TP_RECEIVE_IDLE; TP_Rx_Buffer_Status = EMPTY; } /*! * @brief TP_Transmit_Single_OR_First_Frame * This function handles transmission of 'single' or 'first' * frame */ static void TP_Transmit_Single_OR_First_Frame (void) { if (TP_Tx_Frame_Type == SINGLE_FRAME) { TP_Transmit_Single_Frame(); } else if (TP_Tx_Frame_Type == FIRST_FRAME) { TP_Transmit_First_Frame(); } else { /* do nothing */ } /* for CF1 count starts with '1'. Becomes '0' if it reaches 16 */ TP_Tx_Sequence_Number = 1; /* TL API is called to set DLC */ HAL_UDS_Set_Tx_DLC (TP_Tx_Frame_DLC); HAL_UDS_Set_Tx_Buf (TP_Frame_Array); /* TL API is called to transmit a frame */ TP_State = TP_Wait_For_SFORFF_TxConf_State; TPN_As_Timer = N_As_TIMER_COUNT; TP_N_As_Timer_Control = TIMER_RUN; }/* End of TP_Transmit_Single_OR_First_Frame*/ /*! * @brief TP_Transmit_Single_Frame * This function handles transmission of 'single' frame */ static void TP_Transmit_Single_Frame (void) { uint8_t Frame_Array_Index, Data_Count ; /* store N_PCI and message length in the first byte of Frame buffer */ TP_Frame_Array[0] = (uint8_t) (SINGLE_FRAME | TP_Tx_Message_DLC); Data_Count = 1; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Tx_Message_DLC; Frame_Array_Index++) { /* copy the data bytes from TP buffer to frame buffer */ TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; Data_Count++; } /* DLC of the frame to be transmitted: Data bytes + N_PCI */ TP_Tx_Frame_DLC = (uint8_t) (TP_Tx_Message_DLC + 1); if (PADDING_OPERATION == true) { if (Data_Count <= CAN_FRAME_BYTES_UPPER_RANGE) { /* padd the remaining space in the frame buffer */ for (; Data_Count <= CAN_FRAME_BYTES_UPPER_RANGE; Data_Count++) { TP_Frame_Array[Data_Count] = PADDING_BYTE; } /* DLC of the frame to be transmitted: DLC Max bytes */ TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; } } } /*! * @brief TP_Transmit_First_Frame * This function handles transmission of 'first' frame */ static void TP_Transmit_First_Frame (void) { uint8_t Frame_Array_Index; /*store N_PCI and message length in the first and second byte of Frame buffer*/ TP_Frame_Array[0] = (uint8_t) (FIRST_FRAME | ( (TP_Tx_Message_DLC & 0X0F00) >> 8)); TP_Frame_Array[1] = (uint8_t) (TP_Tx_Message_DLC & 0X00FF); for (Frame_Array_Index = 2; Frame_Array_Index <= CAN_FRAME_BYTES_UPPER_RANGE; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; } /* DLC of the frame to be transmitted: DLC Max bytes */ TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; } /*! * @brief TP_Receive_Single_OR_First_Frame * This function handles reception of 'single' or 'first' frame */ static void TP_Receive_Single_OR_First_Frame (void) { /* first byte: MSB Nibble indicates frame type :-N_PCI */ TP_Rx_Frame_Type = TP_Frame_Array[0] & FRAME_TYPE_MASK; TP_Rx_Index = 0; TP_Request_Type = PHYSICAL_ADDRESS_TYPE; UdsService.FrameType=TP_Rx_Frame_Type; if (TP_Rx_Frame_Type == SINGLE_FRAME) { TP_Receive_Single_Frame(); } else if (TP_Rx_Frame_Type == FIRST_FRAME) { TP_Receive_First_Frame(); } else { /* do nothing */ } }/* End of TP_Receive_Single_OR_First_Frame*/ /*! * @brief TP_Receive_Single_Frame * This function handles reception of 'single' frame */ static void TP_Receive_Single_Frame (void)//THT { uint8_t Frame_Array_Index; /* first byte: LSB Nibble indicates data length */ TP_Rx_Message_DLC = TP_Frame_Array[0] & SINGLE_FRAME_DATA_LENGTH_MASK; //UdsService.RxDlc = TP_Rx_Message_DLC; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Rx_Message_DLC; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; } if (false == TP_Received_DLC_Check()) { TP_Result = N_WRONG_DLC; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } else { TP_Result = N_OK; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } } /*! * @brief TP_Receive_First_Frame * This function handles reception of 'first' frame */ static void TP_Receive_First_Frame (void) { uint8_t Frame_Array_Index; TP_Rx_Message_DLC = ( (uint16_t) ( (TP_Frame_Array[0] & FIRST_FRAME_DATA_LENGTH_MSB_NIBBLE_MASK) << 8) | TP_Frame_Array[1]); TP_Rx_Message_Length = TP_Rx_Message_DLC; if ( (RECEIVE_MULTI_BUFFER_SUPPORT == false) && (TP_Rx_Message_DLC > TP_BUFFER_SIZE)) { TP_Result = TP_RX_LENGTH_INVALID; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); Flow_Status = OVERFLOW; TP_Transmit_Flow_Control(); Flow_Status = CLEAR_TO_SEND; TP_State = TP_Idle_State; } else { if (TP_Rx_Message_DLC >= MINIMUM_FIRST_FRAME_DATA_LENGTH) { if (false == TP_Received_DLC_Check()) { TP_Result = N_WRONG_DLC; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } else { for (Frame_Array_Index = 2; Frame_Array_Index <= CAN_FRAME_BYTES_UPPER_RANGE; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Message_Length--; TP_Rx_Index++; } TP_Rx_Sequence_Number = 1; /* User call back function to notify the first frame of multiframe message arrival */ UCB_TP_N_USData_FF_Indication (TP_Rx_Message_DLC); TP_Rx_Message_Status = TP_RECEIVE_START; /* After receiveing first frame this API is called to transmit flow control frame */ TP_Transmit_Flow_Control(); } } } } /*! * @brief TP_Transmit_Consecutive_Frame * Handles the consecutive frame transmission with respect to * total message length and the TP buffer */ static void TP_Transmit_Consecutive_Frame (void) { switch (TP_Transmit_Sub_State) { case TP_TX_LOAD_CF_DATA: TP_Tx_Load_CF_Data_Process(); break; case TP_TX_LOAD_REMAINING_BYTES_OF_CF: TP_Tx_Load_Remaining_Bytes_OF_CF_Process(); break; case TP_TX_LOAD_REMAINING_BYTES_OF_LAST_CF: TP_Tx_Load_Remaining_Bytes_OF_Last_CF_Process(); break; default: break; }/* end of TP_Transmit_Sub_State switch */ }/* End of TP_Transmit_Consecutive_Frame*/ /*! * @brief TP_Tx_Load_CF_Data_Process * Handles the consecutive frame transmission with respect to * total message length and the TP buffer */ static void TP_Tx_Load_CF_Data_Process (void) { TP_Frame_Array[0] = CONSECUTIVE_FRAME | TP_Tx_Sequence_Number; TP_Data_Count = TP_BUFFER_SIZE - TP_Tx_Index; if (TP_Tx_Message_DLC >= CONSECUTIVE_FRAME_DATA_BYTE) { TP_Tx_CF_Data_Process(); } else if (TP_Tx_Message_DLC < CONSECUTIVE_FRAME_DATA_BYTE) { TP_Tx_Last_CF_Data_Process(); } else { /* do nothing */ } } /*! * @brief TP_Tx_CF_Data_Process * Checks the data availability in TP buffer and loads the CF * accordingly when CF is other than last CF */ static void TP_Tx_CF_Data_Process (void) { uint8_t Frame_Array_Index; if (TP_Data_Count < CONSECUTIVE_FRAME_DATA_BYTE) { TP_Next_Loop_Count = 1; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Data_Count; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; TP_Next_Loop_Count++; } TP_Transmit_Sub_State = TP_TX_LOAD_REMAINING_BYTES_OF_CF; TP_Tx_Buffer_Status = EMPTY; UCB_TP_Transmit_Buffer_Empty(); TP_Tx_Index = 0; } else if (TP_Data_Count >= CONSECUTIVE_FRAME_DATA_BYTE) { for (Frame_Array_Index = 1; Frame_Array_Index <= CAN_FRAME_BYTES_UPPER_RANGE; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; } TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; TP_Load_TL_Buffer_Start_NAs_Timer(); TP_State = TP_Wait_For_CF_TxConf_State; TP_Update_SN_and_BS(); } else { /* do nothing */ } } /*! * @brief TP_Tx_Last_CF_Data_Process * Checks the data availability in TP buffer and loads the CF * accordingly for last CF */ static void TP_Tx_Last_CF_Data_Process (void)//THT { uint8_t Frame_Array_Index, Data_Count, TempLoopCount; if (TP_Data_Count >= TP_Tx_Message_DLC) { Data_Count = 1; TempLoopCount = (uint8_t) TP_Tx_Message_DLC; for (Frame_Array_Index = 1; Frame_Array_Index <= TempLoopCount; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; Data_Count++; } TP_Tx_Frame_DLC = TempLoopCount; if (PADDING_OPERATION == true) { for (; Data_Count <= CAN_FRAME_BYTES_UPPER_RANGE; Data_Count++) { TP_Frame_Array[Data_Count] = PADDING_BYTE; } TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; } TP_Load_TL_Buffer_Start_NAs_Timer(); TP_State = TP_Wait_For_CF_TxConf_State; } else if (TP_Data_Count < TP_Tx_Message_DLC) { TP_Next_Loop_Count = 1; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Data_Count; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; TP_Next_Loop_Count++; } TP_Transmit_Sub_State = TP_TX_LOAD_REMAINING_BYTES_OF_LAST_CF; TP_Tx_Buffer_Status = EMPTY; UCB_TP_Transmit_Buffer_Empty(); TP_Tx_Index = 0; } else { /* do nothing */ } } /*! * @brief TP_Tx_Load_Remaining_Bytes_OF_CF_Process * Handles the consecutive frame transmission with respect to * remaining bytes of CF */ static void TP_Tx_Load_Remaining_Bytes_OF_CF_Process (void) { if (TP_Tx_Buffer_Status == FILLED) { for (; TP_Next_Loop_Count <= CAN_FRAME_BYTES_UPPER_RANGE; TP_Next_Loop_Count++) { TP_Frame_Array[TP_Next_Loop_Count] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; } TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; TP_Load_TL_Buffer_Start_NAs_Timer(); TP_Transmit_Sub_State = TP_TX_LOAD_CF_DATA; TP_State = TP_Wait_For_CF_TxConf_State; TP_Update_SN_and_BS(); } } /*! * @brief TP_Tx_Load_Remaining_Bytes_OF_Last_CF_Process * Handles the consecutive frame transmission with respect to * remaining bytes of last CF */ static void TP_Tx_Load_Remaining_Bytes_OF_Last_CF_Process (void) { uint8_t Data_Count; //uint8_t TempLoopCount; if (TP_Tx_Buffer_Status == FILLED) { Data_Count = (uint8_t) TP_Next_Loop_Count; //TempLoopCount = (uint8_t) TP_Tx_Message_DLC; TP_Tx_Frame_DLC = (uint8_t) (TP_Next_Loop_Count + TP_Tx_Message_DLC); for (; TP_Next_Loop_Count < TP_Tx_Frame_DLC ; TP_Next_Loop_Count++) { TP_Frame_Array[TP_Next_Loop_Count] = TP_Buffer[TP_Tx_Index]; TP_Tx_Index++; TP_Tx_Message_DLC--; Data_Count++; } if (PADDING_OPERATION == true) { for (; Data_Count <= CAN_FRAME_BYTES_UPPER_RANGE; Data_Count++) { TP_Frame_Array[Data_Count] = PADDING_BYTE; } TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; } TP_Load_TL_Buffer_Start_NAs_Timer(); TP_Transmit_Sub_State = TP_TX_LOAD_CF_DATA; TP_State = TP_Wait_For_CF_TxConf_State; } } /*! * @brief TP_Load_TL_Buffer_Start_NAs_Timer * Loads the frame into TL s/w buffer and starts the NAs timer * counter. */ static void TP_Load_TL_Buffer_Start_NAs_Timer (void) { HAL_UDS_Set_Tx_DLC (TP_Tx_Frame_DLC); HAL_UDS_Set_Tx_Buf (TP_Frame_Array); TPN_As_Timer = N_As_TIMER_COUNT; TP_N_As_Timer_Control = TIMER_RUN; } /*! * @brief TP_Update_SN_and_BS * updates the sequence number and the block size parameters */ static void TP_Update_SN_and_BS (void) { TP_Tx_Sequence_Number++; if (TP_Tx_Sequence_Number == SEQUENCE_NUMBER_MAX) { TP_Tx_Sequence_Number = 0; } if (TP_Tx_Block_Size_Constant != 0) { TP_Tx_Block_Size--; } } /*! * @brief TP_Receive_Consecutive_Frame * Handles the consecutive frame reception with respect to total * message length and the TP buffer */ static void TP_Receive_Consecutive_Frame (void) { switch (TP_Receive_Sub_State) { case TP_RX_UNLOAD_CF_DATA: TP_Rx_Unload_CF_Data_Process(); break; case TP_RX_UNLOAD_REMAINING_BYTES_OF_CF: TP_Rx_Unload_Remaining_Bytes_OF_CF_Process(); break; case TP_RX_UNLOAD_REMAINING_BYTES_OF_LAST_CF: TP_Rx_Unload_Remaining_Bytes_OF_Last_CF_Process(); break; default: break; }/* end of TP_Receive_Sub_State switch */ }/* End of TP_Receive_Consecutive_Frame */ /*! * @brief TP_Rx_Unload_CF_Data_Process * Handles the consecutive frame reception with respect to total * message length and the TP buffer */ static void TP_Rx_Unload_CF_Data_Process (void) { TP_Data_Count = TP_BUFFER_SIZE - TP_Rx_Index; if (TP_Rx_Message_Length >= CONSECUTIVE_FRAME_DATA_BYTE) { TP_Rx_CF_Data_Process(); } else if (TP_Rx_Message_Length < CONSECUTIVE_FRAME_DATA_BYTE) { TP_Rx_Last_CF_Data_Process(); } else { /* do nothing */ } } /*! * @brief TP_Rx_CF_Data_Process * Checks the memory availability in TP buffer and unloads the CF * accordingly when CF is other than last CF ( From TL to TP Buffer) */ static void TP_Rx_CF_Data_Process (void) { uint8_t Frame_Array_Index; if (TP_Data_Count < CONSECUTIVE_FRAME_DATA_BYTE) { TP_Next_Loop_Count = 1; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Data_Count; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; TP_Rx_Message_Length--; TP_Next_Loop_Count++; } if(!TP_Rx_Message_Length) { UdsService.MultFrameComp=1; } TP_Receive_Sub_State = TP_RX_UNLOAD_REMAINING_BYTES_OF_CF; TP_State = TP_Wait_For_DataRead_State; TP_Rx_Buffer_Status = FILLED; #ifdef RX_MULTI_BUFFER_SUPPORT UCB_TP_Receive_Buffer_Filled(); #endif TP_Rx_Index = 0; } else if (TP_Data_Count >= CONSECUTIVE_FRAME_DATA_BYTE) { for (Frame_Array_Index = 1; Frame_Array_Index <= CAN_FRAME_BYTES_UPPER_RANGE; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; TP_Rx_Message_Length--; // THT } if(!TP_Rx_Message_Length) { UdsService.MultFrameComp=1; } } else { /* do nothing */ } } /*! * @brief TP_Rx_Last_CF_Data_Process * Checks the memory availability in TP buffer and unloads the CF * accordingly for last CF ( From TL to TP Buffer) */ static void TP_Rx_Last_CF_Data_Process (void) { uint8_t TempLoopCount, Frame_Array_Index; if (TP_Data_Count >= TP_Rx_Message_Length) { TempLoopCount = (uint8_t) TP_Rx_Message_Length; for (Frame_Array_Index = 1; Frame_Array_Index <= TempLoopCount; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; TP_Rx_Message_Length--; } if(!TP_Rx_Message_Length)//THT { UdsService.MultFrameComp=1; } } else if (TP_Data_Count < TP_Rx_Message_Length) { TP_Next_Loop_Count = 1; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Data_Count; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; TP_Rx_Message_Length--; TP_Next_Loop_Count++; } TP_Receive_Sub_State = TP_RX_UNLOAD_REMAINING_BYTES_OF_LAST_CF; TP_State = TP_Wait_For_DataRead_State; TP_Rx_Buffer_Status = FILLED; #ifdef RX_MULTI_BUFFER_SUPPORT UCB_TP_Receive_Buffer_Filled(); #endif TP_Rx_Index = 0; } else { /* do nothing */ } } /*! * @brief TP_Rx_Unload_Remaining_Bytes_Of_CFProcess * Handles the consecutive frame reception with respect to * remaining bytes of CF */ static void TP_Rx_Unload_Remaining_Bytes_OF_CF_Process (void) { if (TP_Rx_Buffer_Status == EMPTY) { for (; TP_Next_Loop_Count <= CAN_FRAME_BYTES_UPPER_RANGE; TP_Next_Loop_Count++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[TP_Next_Loop_Count]; TP_Rx_Index++; TP_Rx_Message_Length--; } TP_Receive_Sub_State = TP_RX_UNLOAD_CF_DATA; TP_State = TP_Rx_CF_State; } } /*! * @brief TP_Rx_Unload_Remaining_Bytes_OF_Last_CF_Process * Handles the consecutive frame reception with respect to * remaining bytes of last CF */ static void TP_Rx_Unload_Remaining_Bytes_OF_Last_CF_Process (void) { uint8_t TempLoopCount; //uint8_t Data_Count; if (TP_Rx_Buffer_Status == EMPTY) { // Data_Count = 0; TempLoopCount = (uint8_t) TP_Rx_Message_Length; for (; TP_Next_Loop_Count <= (TempLoopCount + 1); TP_Next_Loop_Count++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[TP_Next_Loop_Count]; TP_Rx_Index++; TP_Rx_Message_Length--; } TP_Receive_Sub_State = TP_RX_UNLOAD_CF_DATA; TP_State = TP_Rx_CF_State; } } /*! * @brief TP_Transmit_Buffer_Filled * Sets the TP buffer to true state. After filling the buffer, * application will call the function to indicate TP layer that buffer has * been filled. */ void TP_Transmit_Buffer_Filled (void) { TP_Tx_Buffer_Status = FILLED; }/* End of TP_Transmit_Buffer_Filled*/ /*! * @brief TP_Receive_Buffer_Read * Clears the TP buffer to false state. After emptying the buffer, * application will call the function to indicate TP layer that buffer is * emptied. */ void TP_Receive_Buffer_Read (void) { TP_Rx_Buffer_Status = EMPTY; }/* End of TP_Receive_Buffer_Read */ /*! * @brief TP_Check_Rx_Message_Length * This API checks for the remaining length. If all the bytes are * received it goes to idle stste. Otherwise it goes to a state to receive * next CF */ static void TP_Check_Rx_Message_Length (void) { if (TP_Rx_Message_Length == 0) { TP_N_Cr_Timer_Control = TIMER_STOP; TP_State = TP_Idle_State; TP_Rx_Message_Status = TP_RECEIVE_IDLE; TP_Rx_Buffer_Status = EMPTY; TP_Result = N_OK; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } else { if (TP_RX_BLOCK_SIZE_MAX == 0) { TP_State = TP_Rx_CF_State; } else { TP_Rx_Block_Size--; if (TP_Rx_Block_Size == 0) { TP_Transmit_Flow_Control(); TP_State = TP_Wait_For_FC_TXconf_State; } } TP_Rx_Sequence_Number++; if (TP_Rx_Sequence_Number == SEQUENCE_NUMBER_MAX) { TP_Rx_Sequence_Number = 0; } } }/* End of TP_Check_Rx_Message_Length */ /*! * @brief TP_Transmit_Flow_Control * This API is responsible for framing the flowcontrol message * and transmitting to the transmitter using TL API's */ static void TP_Transmit_Flow_Control (void) { uint8_t Frame_Array_Index; /* frame a control-frame using modifiable parameters */ /* store N_PCI and flow status, as first byte */ TP_Frame_Array[0] = FLOW_CONTROL_FRAME | Flow_Status; /* store ECU's BS parameter for receiving, as second byte */ TP_Frame_Array[1] = TP_RX_BLOCK_SIZE_MAX; // 20190315 lbin /* store ECU's STmin parameter for receiving, as third byte */ TP_Frame_Array[2] = TP_RX_SEPARATION_TIME_MIN;//TP_Rx_Seperation_Time_Parameter; /* store BS to another variable */ TP_Rx_Block_Size = TP_RX_BLOCK_SIZE_MAX; TP_Tx_Frame_DLC = FLOW_CONTROL_N_PCI_PLUS_DATA_BYTE; if (PADDING_OPERATION == true) { for (Frame_Array_Index = 3; Frame_Array_Index <= CAN_FRAME_BYTES_UPPER_RANGE; Frame_Array_Index++) { TP_Frame_Array[Frame_Array_Index] = PADDING_BYTE; } TP_Tx_Frame_DLC = NW_DLC_MAX_BYTES; } HAL_UDS_Set_Tx_ID(0); HAL_UDS_Set_Tx_DLC (TP_Tx_Frame_DLC); HAL_UDS_Set_Tx_Buf (TP_Frame_Array); TP_State = TP_Wait_For_FC_TXconf_State; TPN_Ar_Timer = N_Ar_TIMER_COUNT; TP_N_Ar_Timer_Control = TIMER_RUN; }/* End of TP_Transmit_Flow_Control */ /*! * @brief TP_Received_DLC_Check * This API checks for the received DLC.If the received DLC is * less than the expected DLC it returns false. Otherwise it returns true. */ static bool TP_Received_DLC_Check (void) { bool ReceivedDLCResult = false; //uint8_t len=0; switch (TP_Rx_Frame_Type)//THT { case SINGLE_FRAME: //len = (TP_Rx_Message_DLC + SINGLE_FRAME_N_PCI_BYTE); if (TP_Rx_Message_DLC != 0) { if (TP_Rx_Frame_DLC < (TP_Rx_Message_DLC + SINGLE_FRAME_N_PCI_BYTE)) { ReceivedDLCResult = false; } else { ReceivedDLCResult = true; } } break; case FIRST_FRAME: if (TP_Rx_Frame_DLC < FIRST_FRAME_N_PCI_PLUS_DATA_BYTE) { ReceivedDLCResult = false; } else { ReceivedDLCResult = true; } break; case CONSECUTIVE_FRAME: if (TP_Rx_Message_Length >= CONSECUTIVE_FRAME_DATA_BYTE) { if (TP_Rx_Frame_DLC < CONSECUTIVE_FRAME_N_PCI_PLUS_DATA_BYTE) { ReceivedDLCResult = false; } else { ReceivedDLCResult = true; } } else { if (TP_Rx_Frame_DLC < (TP_Rx_Message_Length + CONSECUTIVE_FRAME_N_PCI_BYTE)) { ReceivedDLCResult = false; } else { ReceivedDLCResult = true; } } break; case FLOW_CONTROL_FRAME: if (TP_Rx_Frame_DLC < FLOW_CONTROL_N_PCI_PLUS_DATA_BYTE) { ReceivedDLCResult = false; } else { ReceivedDLCResult = true; } break; default: break; } return (ReceivedDLCResult); }/* End of TP_Received_DLC_Check */ /*! * @brief TP_Update_Timers * If the timers are enabled, timercount for each timer is * decremented. Timers are: N_As, N_Ar, N_Bs and N_Cr */ static void TP_Update_Timers (void) { if (TP_N_As_Timer_Control == TIMER_RUN) { if (TPN_As_Timer > 0) { TPN_As_Timer--; } else { // _P101 = 0x00; TBD-PVD : Timer needs to be identified. } } if (TP_N_Ar_Timer_Control == TIMER_RUN) { if (TPN_Ar_Timer > 0) { TPN_Ar_Timer--; } } if (TP_N_Bs_Timer_Control == TIMER_RUN) { if (TPN_Bs_Timer > 0) { TPN_Bs_Timer--; } } if (TP_N_Cr_Timer_Control == TIMER_RUN) { if (TPN_Cr_Timer > 0) { TPN_Cr_Timer--; } } }/* End of TP_Update_Timers */ /*! * @brief TP_GetBufferSize * User calls this API to get the size of the buffer. * decremented. Timers are: N_As, N_Ar, N_Bs and N_Cr * * @return TP Buffer size */ uint16_t TP_Get_Message_Buffer_Size (void) { return (TP_BUFFER_SIZE); /* size of the TP_Buffer as configured in the config file */ }/* End of TP_Get_Message_Buffer_Size */ /*! * @brief TP_GetBufferPointer * User calls this API to get the pointer(address)of the * TP_Buffer. * * @return Address of the TP buffer */ uint8_t *TP_Get_Message_Buffer_Pointer (void) { //memset(TP_Tx_Buffer,0x0,TP_BUFFER_SIZE); // memcpy(TP_Tx_Buffer,TP_Buffer,TP_BUFFER_SIZE); // memset(TP_Buffer,0x0,TP_BUFFER_SIZE); return (TP_Buffer); /* returns the starting address of the TP buffer */ }/* End of TP_Get_Message_Buffer_Pointer */ /*! * @brief TP_Get_Request_Type * User calls this API to get the type of * request(physical/functional). * * @return Address of the TP buffer */ uint8_t TP_Get_Request_Type (void) { return (TP_Request_Type); /* returns the type of request */ }/* End of TP_Get_Request_Type */ /*! * @brief TP_N_USData_Request * User calls this API to transmit a message. It passes the length * of the message to be transmitted. * * @param TPTransmitMessageLength Transmit message length */ void TP_N_USData_Request (uint16_t TPTransmitMessageLength) { TP_Tx_Message_DLC = TPTransmitMessageLength; if (TP_Tx_Message_DLC <= MAXIMUM_SINGLE_FRAME_DATA_BYTE) { TP_Tx_Frame_Type = SINGLE_FRAME; } else { TP_Tx_Frame_Type = FIRST_FRAME; } TP_Tx_Message_Status = TP_TRANSMIT_START; TP_Tx_Index = 0; if (TP_Tx_Buffer_Status == FILLED) { TP_Transmit_Single_OR_First_Frame(); } else { TP_Result = TP_BUFFER_NOT_FILLED; UCB_TP_N_USData_Confirm (TP_Result); TP_Tx_Message_Status = TP_TRANSMIT_IDLE; } }/* End of TP_N_USData_Request */ /*! * @brief TP_D_UUData_Confirm * This is a callback function called by TL after transmitting * a message corresponding to TP. Flag is set to inform the TP about frame * transmission completion. * */ void TP_D_UUData_Confirm (void) { Frame_Tx_Complete = true; TP_N_As_Timer_Control = TIMER_STOP; if ( (TP_State == TP_Wait_For_SFORFF_TxConf_State) && (TP_Tx_Frame_Type == FIRST_FRAME)) { UCB_TP_N_USData_FF_Confirmation(); } if ( ( (TP_State == TP_Wait_For_SFORFF_TxConf_State) && (TP_Tx_Frame_Type == FIRST_FRAME)) || ( (TP_Tx_Block_Size_Constant != 0) && (TP_Tx_Block_Size == 0))) { TPN_Bs_Timer = N_Bs_TIMER_COUNT; TP_N_Bs_Timer_Control = TIMER_RUN; TP_Tx_Message_Status = WAITINGFORFLOWCONTROL; } if ( ( (TP_Tx_Message_Status == TP_TRANSMIT_START) && (TP_Tx_Separation_Time_Min_Constant == 0)) || (SINGLE_FRAME == TP_Tx_Frame_Type) || ( (TP_State == TP_Wait_For_CF_TxConf_State) && (0 == TP_Tx_Message_DLC))) { /* to transmit 2nd CF onwards if stmin =0......*/ /* to handle next request within loop time of response */ TP_Task(); } if ( (TP_Rx_Message_Status == TP_RECEIVE_START) && (TP_State == TP_Wait_For_FC_TXconf_State)) { /* to notify flow control tx so that cf's can be received(any time)*/ TP_Task(); } }/* End of TP_D_UUData_Confirm */ /*! * @brief TP_D_UUData_Indication_Physical * This is a callback function called by TL after receiving * a message(Physical) corresponding to TP. If the ECU is transmitting, * and if it receives a frame it is ignored. Flag is set to inform the TP about * frame arrival.Data is copied from the software buffer to TP's Frame buffer. * */ bool TpRxFlg=false; uint8_t g_ucTpRxStatusCnt; void TP_D_UUData_Indication_Physical (void) { //uint8_t Frame_Array_Index; uint8_t FlowControlStatus; if (TP_Tx_Message_Status != TP_TRANSMIT_START) { Frame_Available = true; TP_Rx_Frame_DLC = HAL_UDS_Rx_DLC(); HAL_UDS_Get_Buf(TP_Frame_Array); FlowControlStatus = TP_Frame_Array[0] & FLOW_STATUS_MASK; if ( (TP_Tx_Message_Status == WAITINGFORFLOWCONTROL) && (FlowControlStatus == CLEAR_TO_SEND)) { TP_Tx_Message_Status = TP_TRANSMIT_START; } if ( (TP_Rx_Message_Status == TP_RECEIVE_START)) { TP_Task(); /* to receive cf's......*/ } g_ucTpRxStatusCnt=0; TpRxFlg=true; UdsService.PhyFlg = true; //Debug("UDS REC:\r\n"); // } else { if(++g_ucTpRxStatusCnt>=2) { UDS_Service_Init(); TP_Init(); //TP_Rx_To_Idle_Init(TP_Result); //Debug("UDS g_ucTpRxStatusCnt:\r\n"); g_ucTpRxStatusCnt=0; TP_Tx_Message_Status=TP_TRANSMIT_IDLE; TP_State =TP_Idle_State; HAL_Response_Pocessing = false; } } }/* End of TP_D_UUData_Indication_Physical */ #ifdef TP_DIAG_FUNCTIONAL_MSG_SUPPORT /*! * @brief TP_D_UUData_Indication_Functional * This is a callback function called by TL after receiving * a message(functional) corresponding to TP. If the ECU is transmitting, * and if it receives a frame it is ignored. Flag is set to inform the TP about * frame arrival. Data is copied from the software buffer to TP's Frame buffer */ void TP_D_UUData_Indication_Functional (void) { // uint8_t *ReceivedMessageAddress; uint8_t Frame_Array_Index; uint8_t FlowControlStatus; if (TP_Tx_Message_Status != TP_TRANSMIT_START) //if ((TP_Tx_Message_Status == TP_TRANSMIT_IDLE)||(TP_Tx_Message_Status != TP_TRANSMIT_START)) { if ((UdsService.PhyFlg == true) && (TP_Rx_Message_Status == TP_RECEIVE_START)) { return; } TP_Rx_Frame_DLC = HAL_UDS_Rx_DLC(); HAL_UDS_Get_Buf(TP_Frame_Array); TP_Rx_Frame_Type = TP_Frame_Array[0] & FRAME_TYPE_MASK; TP_Rx_Index = 0; UdsService.RxDlc = TP_Rx_Message_DLC; UdsService.PhyFlg = false; FlowControlStatus = TP_Frame_Array[0] & FLOW_STATUS_MASK; if ( (TP_Tx_Message_Status == WAITINGFORFLOWCONTROL) && (FlowControlStatus == CLEAR_TO_SEND)) { TP_Tx_Message_Status = TP_TRANSMIT_START; } if ( (TP_Rx_Message_Status == TP_RECEIVE_START)) { TP_Task(); /* to receive cf's......*/ } if (TP_Rx_Frame_Type == SINGLE_FRAME) { TP_Rx_Message_DLC = TP_Frame_Array[0] & SINGLE_FRAME_DATA_LENGTH_MASK; for (Frame_Array_Index = 1; Frame_Array_Index <= TP_Rx_Message_DLC; Frame_Array_Index++) { TP_Buffer[TP_Rx_Index] = TP_Frame_Array[Frame_Array_Index]; TP_Rx_Index++; } if (false == TP_Received_DLC_Check()) { TP_Result = N_WRONG_DLC; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } else { TP_Request_Type = FUNCTIONAL_ADDRESS_TYPE; TP_Result = N_OK; UCB_TP_N_USData_Indication (TP_Rx_Message_DLC, TP_Result); } } } }/* End of TP_D_UUData_Indication_Functional */ #endif /*! * @brief TP_N_Change_Parameters_Request * This API is called by user to change the parameter values of * the parameters BlockSize and the Minimum SeparationTime * * @param Parameter Parameter * @param ParameterValue Parameter Value */ void TP_N_Change_Parameters_Request (uint8_t Parameter, uint16_t ParameterValue) { /* if it is in the multiframe receive mode, change is not permitted */ if (TP_Rx_Message_Status != TP_RECEIVE_START) { switch (Parameter) { case N_BLOCKSIZE: if ((ParameterValue <= 0xff)) { // TP_Rx_Block_Size_Parameter = (uint8_t) ParameterValue; TP_Change_Parameter_Result = N_OK_R; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); } else { TP_Change_Parameter_Result = N_WRONG_VALUE; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); } break; case N_SEPERATIONTIME: if ((ParameterValue <= 0xff)) { // TP_Rx_Seperation_Time_Parameter = (uint8_t) ParameterValue; TP_Change_Parameter_Result = N_OK_R; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); //Debug("TP_Rx_Seperation_Time_Parameter=%d",TP_Rx_Seperation_Time_Parameter); } else { TP_Change_Parameter_Result = N_WRONG_VALUE; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); } break; default: TP_Change_Parameter_Result = N_WRONG_PARAMETER; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); break; } } else { TP_Change_Parameter_Result = N_RX_ON; UCB_TP_N_Change_Parameter_Confirm (Parameter, TP_Change_Parameter_Result); } }/* End of TP_N_Change_Parameters_Request */ static uint8_t TP_STmin_Calculate (void) { uint8_t TP_STmin_Result,TP_FC_STmin; TP_FC_STmin = TP_Frame_Array[2]; if (TP_FC_STmin != 0) { if (TP_FC_STmin > 0x7F) { TP_FC_STmin = 0x7F; } TP_STmin_Result = TP_FC_STmin / CALL_RATE_TP; TP_STmin_Result += 1; } else { if (STmin_ZERO == CALL_RATE_TP) { TP_STmin_Result = 1; } else { TP_STmin_Result = 0; } } return (TP_STmin_Result); }/*/TP_STmin_Calculate*/