/*************************************************** * Include files ***************************************************/ #include #include #include /* For memcpy */ #include "cantp.h" #include "cantp_user.h" #include "xl_mcan.h" #include "uds.h" #include "did.h" #include "fbl_ap.h" #include "fbl_def.h" #include "nvm.h" #include "countdowntimer.h" #ifdef ENABLE_BOOTLOADER #endif /*************************************************** * Local Defines ***************************************************/ typedef enum { SESSION_CONTROL = 0x10, ECU_RESET = 0x11, CLEAR_DIAGNOSTIC_INFORMATION = 0x14, READ_DTC_INFORMATION = 0x19, READ_DATA_BY_IDENTIFIER = 0x22, SECURITY_ACCESS = 0x27, COMMUNICATION_CONTROL = 0x28, WRITE_DATA_BY_IDENTIFIER = 0x2E, ROUTINE_CONTROL = 0x31, TESTER_PRESENT = 0x3E, CONTROL_DTC_SETTING = 0x85, IN_OUT_CONTROL_BY_IDENTIFIER = 0x2F, /* READDATASTREAM = 0x2A, READMEMORYBYADDRESS = 0x23, WRITEMEMORYBYADDRESS = 0x3D,*/ REQUEST_DOWNLOAD = 0x34, TRANSFER_DATA = 0x36, REQUEST_TRANSFER_EXIT = 0x37, } UDS_SID_e; typedef enum READ_SID { READ_DATA_BY_ID = 0x22, READ_DATA_BY_ADDRESS = 0x23, MAX_READ_SID = 0 } READ_SID_e; typedef enum UDS_SESSION { DEFAULT = 1, PROGRAMMING = 2, EXTENDED = 3, } UDS_SESSIONS_e; typedef enum UDS_RESP_PENDING { ERASE_RESP_PENDING = 0x01, WRITE_RAM_RESP_PENDING = 0x02, WRITE_FLASH_RESP_PENDING = 0x04, CHECK_PROGRAMMING_INTERGRITY_PENDING = 0x08, RESP_PENDING_MAX = 0x00 } UDS_RESP_PENDING_Te; /* These define the index into */ enum UDS_RQ_FRAME_IDX { UDS_RQ_BYTE0, UDS_RQ_BYTE1, UDS_RQ_BYTE2, UDS_RQ_BYTE3, UDS_RQ_BYTE4, UDS_RQ_BYTE5, UDS_RQ_BYTE6, UDS_RQ_BYTE7, UDS_RQ_BYTE8, UDS_RQ_BYTE9, UDS_RQ_BYTE10, UDS_RQ_BYTE11 }; typedef enum { NRC_GENERAL_REJECT = 0x10, NRC_SERVICE_NOT_SUPPORTED = 0x11, NRC_SUBFUNCTION_NOT_SUPPORTED = 0x12, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT = 0x13, NRC_CONDITIONS_NOT_CORRECT = 0x22, NRC_REQUEST_SEQUENCE_ERROR = 0x24, NRC_REQUEST_OUT_OF_RANGE = 0x31, NRC_SECURITY_ACCESS_DENIED = 0x33, NRC_INVALID_KEY = 0x35, NRC_EXCEEDED_NUMBER_OF_ATTEMPTS = 0x36, NRC_BUSY_REPEAT_REQUEST = 0x21, NRC_REQUIRED_TIME_DELAY_NOT_EXPIRED = 0x37, NRC_TRANSFER_DATA_SUSPENDED = 0x71, NRC_GENERAL_PROGRAMMING_FAILURE = 0x72, NRC_WRONG_BLOCK_SEQUENCE_COUNTER = 0x73, NRC_SERVICE_BUSY = 0x78, NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION = 0x7F } NEGA_RESP_Code_e; typedef struct Read_DID_set { uint16_t DID_Value; uint16_t DID_Table_Index; } Read_DID_set_t; #define REQUEST_LEVEL_ONE_SEED 0x01 #define SEND_LEVEL_ONE_KEY 0x02 #define REQUEST_LEVEL_TWO_SEED 0x09 #define SEND_LEVEL_TWO_KEY 0x0A #define SECURITY_ACCESS_STEP_MAX 0xff typedef enum SECURITY_ACCESS_STATE { SECURITY_ACCESS_LOCKED, /* SECURITY_ACCESS_WAIT_KEY1, */ /* SECURITY_ACCESS_WAIT_KEY2, */ SECURITY_ACCESS_UNLOCK_LEVEL_1, SECURITY_ACCESS_UNLOCK_LEVEL_2 } SECURITY_ACCESS_STATE_e; typedef enum { TRANFER_IDLE, TRANFER_START, TRANFER_END } UDS_TRANFER_DATA_STATE_Te; typedef enum { PRGRAMMING_FAIL, PRGRAMMING_OK, PRGRAMMING_STATE_MAX } FBL_PRGRAMMING_STATE_Te; typedef struct Program_State { uint8_t ECU_SW_State; uint8_t ECU_RAM_ROM_State; } Program_State_t; typedef struct Calibration_state { uint32_t cmd; uint32_t calibrating_flag; } Calibration_state_t; #define RSP_DATA_LEN (6) #define UDS_TASK_RATE (10) #define CANTP_RX_BUFFER_SIZE (266) #define FBL_RX_BUFFER_SIZE (256) #define CANTP_TX_BUFFER_SIZE (128) #define MAX_READ_DID_SET_SIZE (25) #define SID_SIZE (1) // ÕýÏìÓ¦ID #define GET_RESPONSE_SERVICE_ID(SID) (0x40 + SID) #define P2SERVER_TIMEROUT (50u) #define P2SERVER_PENDING_TIMEROUT (5000u) #define ENTRY_SLEEP_MODE_TIMEOU (30000 / UDS_TASK_RATE) #define SECURITY_ACCESS_WAIT_TIME (10000 / UDS_TASK_RATE) #define MAX_SECURITY_FAULT_CNT (3) #define STOPALLDIDREQSIZE (2) #define SIZE_OF_SID_DID (3) #if 0 #define SEED_SIZE sizeof(uint32_t) #define KEY_SIZE sizeof(uint32_t) #define LEVEL1_SEED_MASK 0x521025A0 #define LEVEL1_KEY 0x6dfb5320u #define LEVEL2_SEED_MASK 0x2035446A #define LEVEL2_KEY 0x9e8e7b22u #else /* дËÀµÄseed key */ // #define SEED_SIZE sizeof(uint16_t) // #define KEY_SIZE sizeof(uint16_t) // #define LEVEL1_SEED 0x0CA2u // #define LEVEL1_KEY 0xB342u // #define LEVEL2_SEED 0x0CA2u // #define LEVEL2_KEY 0xB342u #define SEED_SIZE sizeof(uint32_t) #define KEY_SIZE sizeof(uint32_t) #define LEVEL1_MASK 0x521025a0u #define LEVEL2_MASK 0x2035446au #define LEVEL1_SEED 0x11223344u #define LEVEL1_KEY 0x20AA097Bu #define LEVEL2_SEED 0x11223344u #define LEVEL2_KEY 0x70237577u #endif #define REQUEST_DOWNLOAD_MSG_SIZE (0x0B) #define DOWNLOAD_RAM ((uint8_t)0x10u) #define DOWNLOAD_FLASH ((uint8_t)0x40u) /*****************************************************************************/ /* Global Variable Declaration */ /*****************************************************************************/ static uint32_t eraseAddress; /* Actual transfer address */ static uint32_t eraseRemainder; /* Number of remaining transfer bytes */ static UDS_RESP_PENDING_Te UDS_L_ResponsePendingRequest_e; static UDS_RESP_PENDING_Te UDS_L_ResponsePendingRelease_e; static SECURITY_ACCESS_STATE_e UDS_O_SecurityAccessState_e = SECURITY_ACCESS_LOCKED; static bool UDS_L_ProgrammingPreconditionCheckOK_b = true; static UDS_CONTOL_TYPE_e UDS_L_CommunicationControlType_e = EnableRxAndTx; static uint8_t UDS_L_SecurityFault_cnt; static uint8_t UDS_L_SecurityStartDelay = 0; static uint8_t UDS_L_SecurityAccessStep_e = SECURITY_ACCESS_STEP_MAX; /*****************************************************************************/ /* Local Variables Definition */ /*****************************************************************************/ static uint8_t UDS_L_SupplyVoltage = 120u; static uint16_t UDS_L_VehicleSpeed = 0u; /* Timer value to keep the session in extended session */ static uint16_t TesterPresentTimer_u16; /* Current diagnostic session */ static UDS_SESSIONS_e UDS_L_Diag_session_e; /* Read data stream request received */ static uint16_t SecurityAcessTimer_u16; static uint16_t UDS_NS_SessionTimeout_u16; /* CANTP buffer */ static uint8_t UDS_L_rx_buffer[CANTP_RX_BUFFER_SIZE]; static uint8_t UDS_L_tx_buffer[CANTP_TX_BUFFER_SIZE]; /* Message buffer */ static uint8_t UDS_L_rx_msg_buffer[CANTP_RX_BUFFER_SIZE]; static uint16_t UDS_L_rx_msg_size; static uint8_t UDS_L_tx_msg_buffer[CANTP_TX_BUFFER_SIZE]; static uint16_t UDS_L_tx_msg_size; /* CANTP Stack */ static CANTP_Stack_t UDS_L_tp_stack; /* static uint16_t UDS_L_ReadDidSetSize_u16 = 0U; */ static Read_DID_set_t UDS_L_ReadDIDSet_t; /* Current processing request SID */ static uint8_t UDS_L_Current_SID __attribute__((__unused__)); static uint16_t ResponsePendingTimer_u16; static bool UDS_L_TransferDataInProgressing_b = false; static bool UDS_L_CRCCheckFail_b = false; static uint32_t UDS_L_CRCReceived = 0; static UDS_TRANFER_DATA_STATE_Te UDS_L_TransferDataState_e; static uint8_t expectedSequenceCnt; /* Block sequence counter */ static uint8_t currentSequenceCnt; /* Current Block sequence counter */ static FBL_ADDR_TYPE transferAddress; /* Actual transfer address */ static FBL_MEMSIZE_TYPE transferRemainder; /* Number of remaining transfer bytes */ static uint8_t transferType; /* Download into RAM/Flash or upload */ static uint8_t currentbuffId; /* Download into RAM/Flash or upload */ static FBL_ADDR_TYPE eraseAddress; /* Actual transfer address */ static FBL_MEMSIZE_TYPE eraseRemainder; /* Number of remaining transfer bytes */ static FBL_ADDR_TYPE DownloadAddress; /* Actual transfer address */ static FBL_MEMSIZE_TYPE DownloadLength; /* Number of remaining transfer bytes */ /*****************************************************************************/ /* Local Function Prototypes */ /*****************************************************************************/ static void UDS_UpdateVehicleStatus(void); /* Read data by DID */ static void UDS_ReadData(uint8_t *payload); /* Write data by DID */ static void UDS_WriteDataByIdentifier(uint8_t *payload); static void UDS_WriteF1DIDdata(uint8_t *p_src, uint16_t DID_TableIndex) __attribute__((__unused__)); /*0x11 service*/ static void UDS_ECURest(uint8_t *payload); /*0x31 service*/ static void UDS_RoutineControl(uint8_t *payload); /* Tester present(SID:3E) message handling */ static void UDS_TesterPresent(uint8_t *payload); /* Diagnostic session control */ static void UDS_SessionControl(uint8_t *payload); /* Extended session timer handling */ static void UDS_SessionTiming(void); /*security Access fault timer*/ static void UDS_SecurityAccessTiming(void); /*calibration respons wait calibration finsh command*/ static void UDS_CalibrationResp(void); /* Dispatcher when a CAN message is received */ /* static void UDS_MsgDispatch(void); */ /* Compose and send negative response */ static void UDS_SendNegResp(NEGA_RESP_Code_e reason); /* Flip endianness of memory locations based on the size */ static void UDS_FlipEndian(void *address, uint16_t size); /* Compose and send out the requested DID data */ static void UDS_SendDidData(void); /* Build DID data set */ static bool UDS_BuildDidSet(uint8_t *payload); /* Switch to default session */ static void UDS_SwitchtoDefaultSession(uint8_t resetcmd); /*Security access*/ static void UDS_ControlDTCSetting(uint8_t *payload); static void UDS_CommunicationControl(uint8_t *payload); static void UDS_ReadDTCInformation(uint8_t *payload); static void UDS_ReportDTCNumByStatusMask(uint8_t *payload); static void UDS_ReportDTCByStatusMask(uint8_t *payload); static void UDS_ReportSupportedDTCs(uint8_t *payload); static void UDS_ClearDTCInformation(uint8_t *payload); static void UDS_IOControlByIdentifierg(uint8_t *payload); #if 0 static void CANTP_zeroRestOfFrame(TP_PDU_t *msg); #endif static void UDS_RespTxMessage(void); static void UDS_SecurityAccess(uint8_t *payload); static void UDS_CheckProgrammingIntergrity(uint8_t *payload); static void UDS_CheckProgrammingDependence(uint8_t *payload); static void UDS_CheckProgrammingPrecondition(void); static void UDS_EraseMemory(uint8_t *payload); static void UDS_HardwareReset(void) __attribute__((__unused__)); static void UDS_SoftwareReset(void) __attribute__((__unused__)); static void UDS_RequestDownload(uint8_t *payload) __attribute__((__unused__)); static void UDS_TransferData(uint8_t *payload) __attribute__((__unused__)); static void UDS_RequestTransferExit(uint8_t *payload) __attribute__((__unused__)); static uint8_t UDS_SendF1DIDdata(uint8_t *Copy_position, uint16_t DID_idx); static void UDS_StringCopy(char *p_src, char *p_dest, uint8_t max_size); static void UDS_ResponseTiming(void); /* static void UDS_SetEraseResult(uint8_t mem_operation_type, uint8_t partition, int8_t success); static void UDS_SetWriteResult(uint8_t mem_operation_type, uint8_t partition, int8_t success); static void UDS_SetCRCCheckResult(uint8_t mem_peration_type, uint8_t partition, int8_t success); */ /************************ new add ************************/ #define SESSION_CONTROL_MIN_LEN (0x02u) #define ECU_RESET_MIN_LEN (0x02u) #define CLEAR_DIAGNOSTIC_INFORMATION_MIN_LEN (0x04u) /* 3 Bytes DTC */ #define READ_DTC_INFORMATION_MIN_LEN (0x02u) #define READ_DATA_BY_IDENTIFIER_MIN_LEN (0x03u) #define SECURITY_ACCESS_MIN_LEN (0x02u) #define COMMUNICATION_CONTROL_MIN_LEN (0x03u) #define WRITE_DATA_BY_IDENTIFIER_MIN_LEN (0x04u) #define ROUTINE_CONTROL_MIN_LEN (0x04u) #define TESTER_PRESENT_MIN_LEN (0x02u) #define CONTROL_DTC_SETTING_MIN_LEN (0x02u) #define REQUEST_DOWNLOAD_MIN_LEN (0xB) #define TRANSFER_DATA_MIN_LEN (0XC) #define REQUEST_TRANSFER_EXIT_MIN_LEN (0X01) typedef struct { uint8_t uds_sid; /* uint8_t uds_min_len; */ // void (*uds_service)(uint8_t msg_buf[]); void (*uds_service)(uint8_t *payload); bool std_spt; /* default session support */ bool ext_spt; /* extended session support */ bool fun_spt; /* function address support */ bool ssp_spt; /* subfunction suppress PosRsp bit support */ SECURITY_ACCESS_STATE_e uds_sa; /* security access */ } uds_service_t; /* clang-format off */ static const uds_service_t uds_service_list[] = { // service id function default extend fun_add ssp_spt SECURITY LEVEL {SESSION_CONTROL, UDS_SessionControl, true, true, false, true, SECURITY_ACCESS_LOCKED}, {ECU_RESET, UDS_ECURest, false, true, false, true, SECURITY_ACCESS_LOCKED}, {READ_DATA_BY_IDENTIFIER, UDS_ReadData, true, true, false, false, SECURITY_ACCESS_LOCKED}, {SECURITY_ACCESS, UDS_SecurityAccess, false, true, false, false, SECURITY_ACCESS_LOCKED}, // {COMMUNICATION_CONTROL, UDS_CommunicationControl, false, true, true, true, SECURITY_ACCESS_LOCKED}, {WRITE_DATA_BY_IDENTIFIER, UDS_WriteDataByIdentifier, false, true, false, false, SECURITY_ACCESS_UNLOCK_LEVEL_1}, {ROUTINE_CONTROL, UDS_RoutineControl, false, true, false, false, SECURITY_ACCESS_UNLOCK_LEVEL_2}, {TESTER_PRESENT, UDS_TesterPresent, true, true, true, true, SECURITY_ACCESS_LOCKED}, // {CONTROL_DTC_SETTING, UDS_ControlDTCSetting, false, true, false, true, SECURITY_ACCESS_LOCKED}, {REQUEST_DOWNLOAD, UDS_RequestDownload, false, true, false, false, SECURITY_ACCESS_UNLOCK_LEVEL_2}, {TRANSFER_DATA, UDS_TransferData, false, true, false, false, SECURITY_ACCESS_UNLOCK_LEVEL_2}, {REQUEST_TRANSFER_EXIT, UDS_RequestTransferExit, false, true, false, false, SECURITY_ACCESS_UNLOCK_LEVEL_2}, }; /* clang-format on */ #define UDS_SERVICE_NUM (sizeof(uds_service_list) / sizeof(uds_service_list[0])) typedef enum { /* net target address type ÍøÂçÄ¿µÄµØÖ·ÀàÐÍ */ N_TATYPE_NONE = 0, N_TATYPE_PHYSICAL, /* ÎïÀíѰַ */ N_TATYPE_FUNCTIONAL /* ¹¦ÄÜѰַ */ } n_tatype_t; #define REPORT_DTC_NUMBER_BY_STATUS_MASK (0x01) #define REPORT_DTC_BY_STATUS_MASK (0x02) #define REPORT_DTC_SNOPSHOT_BY_DTC_NUMBER (0x04) #define REPORT_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER (0x06) #define REPORT_SUPPORTED_DTC (0x0a) #define UDS_REQUEST_SEED (0x01) #define UDS_SEND_KEY (0x02) /* »ñÈ¡ÒÖÖÆÕýÏìÓ¦±êʶλ =0²»ÒÖÖÆ =1ÒÖÖÆ */ #define UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(byte) (((byte) >> 7u) & 0x01u) /* »ñÈ¡×Ó¹¦ÄÜ */ #define UDS_GET_SUB_FUNCTION(byte) ((byte)&0x7fu) /* Õý·´À¡ÒÖÖÆ±êʶλ =true ²»·¢ËÍÕýÏìÓ¦ =false ·¢ËÍÕýÏìÓ¦ */ static bool ssp_flg; static bool uds_check_len(uint8_t msg_buf[], uint16_t msg_dlc) { bool result; uint8_t subfunction; uint8_t sid; sid = msg_buf[0]; subfunction = UDS_GET_SUB_FUNCTION(msg_buf[1]); switch (sid) { case SESSION_CONTROL: { if (msg_dlc == SESSION_CONTROL_MIN_LEN) { result = true; } else { result = false; } } break; case ECU_RESET: { if (msg_dlc == ECU_RESET_MIN_LEN) { result = true; } else { result = false; } } break; case CLEAR_DIAGNOSTIC_INFORMATION: { if (msg_dlc == CLEAR_DIAGNOSTIC_INFORMATION_MIN_LEN) { result = true; } else { result = false; } } break; case READ_DTC_INFORMATION: { if ((subfunction == REPORT_DTC_NUMBER_BY_STATUS_MASK && msg_dlc != (READ_DTC_INFORMATION_MIN_LEN + 1)) || (subfunction == REPORT_DTC_BY_STATUS_MASK && msg_dlc != (READ_DTC_INFORMATION_MIN_LEN + 1)) || (subfunction == REPORT_SUPPORTED_DTC && msg_dlc != READ_DTC_INFORMATION_MIN_LEN)) { result = false; } else { result = true; } } break; case READ_DATA_BY_IDENTIFIER: { if (msg_dlc == READ_DATA_BY_IDENTIFIER_MIN_LEN) { result = true; } else { result = false; } } break; case SECURITY_ACCESS: { if ((subfunction == UDS_REQUEST_SEED && msg_dlc != SECURITY_ACCESS_MIN_LEN) || (subfunction == UDS_SEND_KEY && msg_dlc != (SECURITY_ACCESS_MIN_LEN + KEY_SIZE))) { result = false; } else { result = true; } } break; case COMMUNICATION_CONTROL: { if (msg_dlc == COMMUNICATION_CONTROL_MIN_LEN) { result = true; } else { result = false; } } break; case WRITE_DATA_BY_IDENTIFIER: { if (msg_dlc >= WRITE_DATA_BY_IDENTIFIER_MIN_LEN) { result = true; } else { result = false; } } break; case ROUTINE_CONTROL: if (msg_dlc >= ROUTINE_CONTROL_MIN_LEN) { result = true; } else { result = false; } break; case TESTER_PRESENT: { if (msg_dlc == TESTER_PRESENT_MIN_LEN) { result = true; } else { result = false; } } break; case CONTROL_DTC_SETTING: { if (msg_dlc == CONTROL_DTC_SETTING_MIN_LEN) { result = true; } else { result = false; } } break; case REQUEST_DOWNLOAD: if (msg_dlc == REQUEST_DOWNLOAD_MIN_LEN) { result = true; } else { result = false; } break; case TRANSFER_DATA: result = true; break; case REQUEST_TRANSFER_EXIT: result = true; break; default: result = false; break; } return result; } static void uds_data_indication(uint8_t msg_buf[], uint16_t msg_dlc, uint8_t ta_type) { /* uint8_t *payload = UDS_L_rx_msg_buffer; */ /* On any request, reset the S3 timer if current session is extended */ /* session */ if ((UDS_L_Diag_session_e == EXTENDED) || (UDS_L_Diag_session_e == PROGRAMMING)) { /* Reset the tester present waiting timer. If current session is */ /* extended session */ CDT_RESET(TesterPresentTimer_u16, UDS_NS_SessionTimeout_u16 / UDS_TASK_RATE); } uint8_t i; uint8_t sid; uint8_t ssp; bool find_sid; bool session_spt; sid = msg_buf[0]; UDS_L_Current_SID = sid; ssp = UDS_GET_SUB_FUNCTION_SUPPRESS_POSRSP(msg_buf[1]); find_sid = false; for (i = 0; i < UDS_SERVICE_NUM; i++) { if (sid == uds_service_list[i].uds_sid) { /* UDS_L_Diag_session_e = EXTENDED; */ if (UDS_L_Diag_session_e == DEFAULT) { session_spt = uds_service_list[i].std_spt; } else { session_spt = uds_service_list[i].ext_spt; } if (session_spt == true) { if (ta_type == N_TATYPE_FUNCTIONAL && uds_service_list[i].fun_spt == false) { /* ¹¦ÄÜѰַÇҸ÷þÎñ²»Ö§³Ö¹¦ÄÜѰַ */ /* uds_no_response(); */ } else { if (uds_check_len(msg_buf, msg_dlc)) { if (UDS_O_SecurityAccessState_e >= uds_service_list[i].uds_sa) { if (uds_service_list[i].ssp_spt == true && ssp == 0x01) { ssp_flg = true; } else { ssp_flg = false; } uds_service_list[i].uds_service(msg_buf); } else { /* uds_negative_rsp(sid, NRC_SECURITY_ACCESS_DENIED); */ UDS_SendNegResp(NRC_SECURITY_ACCESS_DENIED); } } else { /* uds_negative_rsp(sid, NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT); */ UDS_SendNegResp(NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT); } } } else { /* uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION); */ UDS_SendNegResp(NRC_SERVICE_NOT_SUPPORTED_IN_ACTIVE_SESSION); } find_sid = true; break; } } if (find_sid == false) { /* uds_negative_rsp(sid, NRC_SERVICE_NOT_SUPPORTED); */ UDS_SendNegResp(NRC_SERVICE_NOT_SUPPORTED); } } /*********************** new add end ***********************/ /*************************************************** * Extern Function Definition Starts Here ***************************************************/ /* extern void UDS_GetCommunicationControlType(unsigned char *type); extern void UDS_RxFunIdMessage(TP_PDU_t *msg); */ /*****************************************************************************/ /* NAME : extern void UDS_Init(void) */ /* */ /* DESCRIPTION : */ /* Initialization function for FACT module */ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Initialize the variables */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/16/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /* (2) Date: 08/16/2014 Fogbugz: case#: 1766 */ /* Add version registration by Tom Tao */ /*****************************************************************************/ extern void UDS_Init(void) { /* uint8_t i; */ /* Tester present timer */ CDT_RESET(SecurityAcessTimer_u16, SECURITY_ACCESS_WAIT_TIME); // power on wait 10s TesterPresentTimer_u16 = 0; UDS_NS_SessionTimeout_u16 = 5000; UDS_L_SecurityFault_cnt = 0; UDS_L_SecurityStartDelay = 0; UDS_L_Diag_session_e = DEFAULT; UDS_O_SecurityAccessState_e = SECURITY_ACCESS_LOCKED; UDS_L_Current_SID = 0; UDS_L_ProgrammingPreconditionCheckOK_b = true; UDS_L_TransferDataState_e = TRANFER_IDLE; UDS_L_CRCCheckFail_b = false; UDS_L_ResponsePendingRequest_e = RESP_PENDING_MAX; UDS_L_ResponsePendingRelease_e = RESP_PENDING_MAX; UDS_L_TransferDataInProgressing_b = false; UDS_L_ReadDIDSet_t.DID_Table_Index = 0; UDS_L_ReadDIDSet_t.DID_Value = 0; /* Initialize CANTP stack with FACT CAN buffer */ CANTP_Init(&UDS_L_tp_stack, UDS_L_rx_buffer, CANTP_RX_BUFFER_SIZE, UDS_L_tx_buffer, CANTP_TX_BUFFER_SIZE); CANTP_InitIds(&UDS_L_tp_stack, 0, /* CAN channel 0 */ UDS_PHY_REQ_RID, /* phy req id*/ UDS_RESP_TID, /* phy resp id*/ UDS_FUN_REQ_RID); /* fun req id*/ UDS_InitDIDMapRO(DID_NS_ActiveDiagSession, &UDS_L_Diag_session_e, 1); } /*****************************************************************************/ /* NAME : extern void UDS_Task_10ms(void) */ /* */ /* DESCRIPTION : */ /* Factory diagnosis task called in every 10ms */ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Call routine function in FACT module */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/16/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ extern void UDS_Task_10ms(void *p) { UDS_SessionTiming(); UDS_SecurityAccessTiming(); UDS_ResponseTiming(); } static void UDS_RxTask_1ms(void) { static TP_PDU_t msg_rx_temp = {0}; CAN_PDU_t msg_can_temp = {0}; uint8_t msg_num = MCAN_GetReceiveMessageCounter(MCAN); while (msg_num--) { MCAN_ReceiveData(MCAN, (MCAN_MsgTypeDef *)(&msg_can_temp)); msg_rx_temp.arbId = msg_can_temp.MCAN_ID; msg_rx_temp.dlc = msg_can_temp.MCAN_DLC; for (TP_uint8_t i = 0; i < msg_can_temp.MCAN_DLC; i++) { msg_rx_temp.frame[i] = msg_can_temp.MCAN_Data[i]; } if (msg_rx_temp.arbId == UDS_PHY_REQ_RID) { UDS_RxMessage(&msg_rx_temp); } else { UDS_RxFunIdMessage(&msg_rx_temp); } } } /*****************************************************************************/ /* NAME : extern void UDS_Task_1ms(void) */ /* */ /* DESCRIPTION : */ /* Factory diagnosis task called in every 1ms */ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Call routine function in FACT module */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/30/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ extern void UDS_Task_1ms(void *p) { /* Call tp task first to free up buffer */ CANTP_Task_1ms(&UDS_L_tp_stack); UDS_RxTask_1ms(); /* * This block of stuff controls whether the NVM is allowed to write data or * not. This was added to allow the tester to shut off writes to dynamic * NVM areas (in case during manufacturing there is a situation where * DTCs are being constantly cleared / written for example). Stopping the * writes will allow the current NVM writes to finish but further write * attempts will be blocked. This has to happen from 1msec task for the * following reasons: * 1. If it is not in same timeslice as the request, there will be a window * where the actual state does not match the data being returned to the * tester. This could mean that the local RAM data indicates the NVM is * not dirty, but if you're only updating the 'dirty' state every 20msec * another app could have requested a write in previous 19 of the 20 msec, * meaning we could return 'not busy' while a write was actually pending. * 2. The factory DIDs don't wind up triggering callbacks, they are linked * to data. It would be better if we worked like Vector and ran a callback * instead of just returning data, so that we could (on receiving a particular * DID) make the call into NVM directly and not through a timed task. */ } /********************************************************* UDS_RxMessage() ************ * Each call is responsible for updating the rsp_data_size and rsp_data[] buffer if * they do not want the standard ACK. ***************************************************************************************/ extern void UDS_RxMessage(TP_PDU_t *msg) { bool Msg_Recv_Comp_b; uint8_t *Rcv_Buffer_Ptr = UDS_L_rx_msg_buffer; /* Process the message with CANTP function */ CANTP_RxFrame(&UDS_L_tp_stack, msg); /* Check if a message has been received completely */ Msg_Recv_Comp_b = CANTP_IsRxComplete(&UDS_L_tp_stack, &Rcv_Buffer_Ptr, &UDS_L_rx_msg_size); if (Msg_Recv_Comp_b != false) { /*cantp rx buff to UDS_L_rx_msg_buffer*/ memcpy(UDS_L_rx_msg_buffer, Rcv_Buffer_Ptr, UDS_L_rx_msg_size); /* Call Message dispatcher */ /* UDS_MsgDispatch(); */ uds_data_indication(UDS_L_rx_msg_buffer, UDS_L_rx_msg_size, N_TATYPE_PHYSICAL); } } extern void UDS_RxFunIdMessage(TP_PDU_t *msg) { uint8_t *Rcv_Buffer_Ptr = msg->frame; /*as Single Frame*/ if ((msg->frame[1] == TESTER_PRESENT)) // only support 3E { UDS_L_rx_msg_size = (Rcv_Buffer_Ptr[0] & 0x0f); /*cantp rx buff to UDS_L_rx_msg_buffer*/ memcpy(UDS_L_rx_msg_buffer, &Rcv_Buffer_Ptr[1], UDS_L_rx_msg_size); /* Call Message dispatcher */ /* UDS_MsgDispatch(); */ uds_data_indication(UDS_L_rx_msg_buffer, UDS_L_rx_msg_size, N_TATYPE_FUNCTIONAL); } } #if 1 /* ²ð·Ö */ /** * @brief * * @param DIDitem * @param nvBlockID * @param address * @param size */ extern void UDS_InitDIDMapRW(UDS_DIDList_e DIDitem, uint16_t nvBlockID, void *address, uint16_t size) { uint16_t i; /* Make sure DID table still has space. If current DID table * size is already larger than specified, do not update DID table */ if (DIDTable_Entry_Count_u16 >= UDS_DID_TABLE_SIZE) { return; } /* Look for existing table item with the same DID */ for (i = 0; i < DIDTable_Entry_Count_u16; i++) { if (DIDtable[i].DidEnum == DIDitem) { return; } } /* If there is no such DID, add the new DID into the table */ if ((i == DIDTable_Entry_Count_u16) && (DIDTable_Entry_Count_u16 < UDS_DID_TABLE_SIZE)) { /* Assign enumeration, address, size to the table */ DIDtable[DIDTable_Entry_Count_u16].DidEnum = DIDitem; DIDtable[DIDTable_Entry_Count_u16].nvBlockID = nvBlockID; DIDtable[DIDTable_Entry_Count_u16].address = address; DIDtable[DIDTable_Entry_Count_u16].size = size; DIDtable[DIDTable_Entry_Count_u16].access = READWRITE; /* Calculate CRC */ /* DIDtable[DIDTable_Entry_Count_u16].crc = CRC16_Calc(&address, size); */ DIDTable_Entry_Count_u16++; } } /*****************************************************************************/ /* NAME : extern void UDS_InitDIDMap(UDS_DIDList_e DIDitem, */ /* const void *address, uint16_t size) */ /* */ /* DESCRIPTION : */ /* Function to be called by individual tasks to establish connection*/ /* between the variables to read and the enumeration */ /* INPUTS : */ /* enum DidEnum : enumeration value of DID items */ /* uint16_t address: DID item address */ /* uint16_t size : DID item size */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Add DID table items */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 08/13/2014 Fogbugz: case#: 1791 */ /* Initial release by Tom Tao */ /*****************************************************************************/ extern void UDS_InitDIDMapRO(UDS_DIDList_e DIDitem, const void *address, uint16_t size) { uint16_t i; /* Make sure DID table still has space. If current DID table * size is already larger than specified, do not update DID table */ if (DIDTable_Entry_Count_u16 >= UDS_DID_TABLE_SIZE) { return; } /* Look for existing table item with the same DID */ for (i = 0; i < DIDTable_Entry_Count_u16; i++) { if (DIDtable[i].DidEnum == DIDitem) { return; } } /* If there is no such DID, add the new DID into the table */ if ((i == DIDTable_Entry_Count_u16) && (DIDTable_Entry_Count_u16 < UDS_DID_TABLE_SIZE)) { /* Assign enumeration, address, size to the table */ DIDtable[DIDTable_Entry_Count_u16].DidEnum = DIDitem; DIDtable[DIDTable_Entry_Count_u16].nvBlockID = 0xFF; DIDtable[DIDTable_Entry_Count_u16].address = (void *)address; DIDtable[DIDTable_Entry_Count_u16].size = size; DIDtable[DIDTable_Entry_Count_u16].access = READONLY; /* Calculate CRC */ /* DIDtable[DIDTable_Entry_Count_u16].crc = CRC16_Calc((void *)&address, size); */ DIDTable_Entry_Count_u16++; } } #endif extern void UDS_SwitchtoProgrammingSession(void) { UDS_L_Diag_session_e = PROGRAMMING; CDT_RESET(TesterPresentTimer_u16, UDS_NS_SessionTimeout_u16 / UDS_TASK_RATE); } extern void UDS_ResponseEntryProgrammingSession(void) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(SESSION_CONTROL); UDS_L_tx_msg_buffer[1] = UDS_L_Diag_session_e; UDS_L_tx_msg_buffer[2] = 0x00; UDS_L_tx_msg_buffer[3] = 0x01; UDS_L_tx_msg_buffer[4] = 0; UDS_L_tx_msg_buffer[5] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x06; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } /*****************************************************************************/ /* Local Function definitions */ /*****************************************************************************/ /*****************************************************************************/ /* NAME : static void UDS_SessionTiming(void) */ /* */ /* DESCRIPTION : */ /* Decrease the session timer if it's not expired, if the timer */ /* expires, set the session back to default session */ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Add DID table items */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/16/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SessionTiming(void) { /* Decrease tester present waiting timer, if timer expired, set Factory * diag session to default session */ if (UDS_L_Diag_session_e != DEFAULT) { /* CDT_RESET(EntrySleepModeTimer_u16,ENTRY_SLEEP_MODE_TIMEOU); */ if (CDT_HASEXPIRED(TesterPresentTimer_u16) == false) { CDT_EXPIRED(TesterPresentTimer_u16); if (CDT_HASEXPIRED(TesterPresentTimer_u16) != false) { UDS_SwitchtoDefaultSession(false); } } else { UDS_SwitchtoDefaultSession(false); } } else { CDT_RESET(TesterPresentTimer_u16, 0); } } /*****************************************************************************/ /* NAME : static void UDS_SecurityAccessTiming(void) */ /* */ /* DESCRIPTION : */ /* Decrease the security Access timer if it's not expired, if the timer */ /* expires, set the UDS_SecurityFault_cnt-- */ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 08/10/2017 Fogbugz: case#: */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SecurityAccessTiming(void) { if ((UDS_L_SecurityFault_cnt != 0) || (UDS_L_SecurityStartDelay == 1)) { if (CDT_EXPIRED(SecurityAcessTimer_u16) == true) { UDS_L_SecurityFault_cnt--; UDS_L_SecurityStartDelay = 0; } else { } } } /*****************************************************************************/ /* NAME : static void UDS_ReadData(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* This function reads the data by enumeration value and place the */ /* result in the transmit buffer to send out response */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Read data by identifier */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/16/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_ReadData(uint8_t *payload) { bool DIDnotFound = false; /* Build up the DID set while set the flag for DID found */ DIDnotFound = UDS_BuildDidSet(payload); /* DIDnotFound == false means all requested DID have been found in */ /* DID table, thus their indexes have been stored in */ /* UDS_L_ReadDIDSet_t[x].DID_Table_Index */ if (DIDnotFound == false) { /* Compose a tx message to send out all requested DID data */ UDS_SendDidData(); } else { /* A requested DID item cannot be found in the DID table. */ /* All current data should be abandoned */ memset(UDS_L_tx_msg_buffer, 0, CANTP_TX_BUFFER_SIZE); /* Send a negative response */ UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); } } /*****************************************************************************/ /* NAME : static void UDS_WriteDataByIdentifier(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* This function writes the data passed by user to the data item */ /* specified by DID value */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Write data by identifier */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/16/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_WriteDataByIdentifier(uint8_t *payload) { uint16_t i; uint16_t DID_u16; uint16_t Index_to_be_written; if ((UDS_L_Diag_session_e == DEFAULT) || ((UDS_O_SecurityAccessState_e != SECURITY_ACCESS_UNLOCK_LEVEL_1) && (UDS_O_SecurityAccessState_e != SECURITY_ACCESS_UNLOCK_LEVEL_2))) { /* Send a negative response.*/ UDS_SendNegResp(NRC_SECURITY_ACCESS_DENIED); return; } /* 2nd and 3rd byte specifies the DID */ DID_u16 = payload[1] << 8 | payload[2]; for (i = 0; i < DIDTable_Entry_Count_u16; i++) { if (DIDtable[i].DidEnum == DID_u16) { /* Record index i */ Index_to_be_written = i; break; /* DID data found, stop the search */ } else { /* Otherwise, keep on looking */ } } /* i == DIDTable_Entry_Count_u16 means no data with the DID is found */ if (i == DIDTable_Entry_Count_u16) { /* Send out negative response */ UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); } else if (DIDtable[Index_to_be_written].access == READONLY) { /* Send out negative response */ UDS_SendNegResp(NRC_CONDITIONS_NOT_CORRECT); } else { /* Check the total received message size should be equal to */ /* SID+DID+DataSize */ if (UDS_L_rx_msg_size != (DIDtable[Index_to_be_written].size + SIZE_OF_SID_DID)) { /* Send out negative response */ UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); } else { /* UDS_WriteF1DIDdata(&payload[3], Index_to_be_written); */ memcpy(DIDtable[Index_to_be_written].address, &payload[3], DIDtable[Index_to_be_written].size); /* Write the change to NVM */ if (DIDtable[Index_to_be_written].nvBlockID != 0xFF) { DID_SetWriteSaveFlag(); } UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(WRITE_DATA_BY_IDENTIFIER); UDS_L_tx_msg_buffer[1] = payload[1]; UDS_L_tx_msg_buffer[2] = payload[2]; /* Specify the send payload size */ UDS_L_tx_msg_size = 3; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } } } static uint8_t UDS_SendF1DIDdata(uint8_t *Copy_position, uint16_t DID_idx) { #if 1 uint8_t rtn_length = 0; char *ptr_src = NULL; uint16_t F1DID = 0; uint8_t length = 0; F1DID = (uint16_t)(DIDtable[DID_idx].DidEnum & 0x0000FFFFu); ptr_src = DIDtable[DID_idx].address; length = DIDtable[DID_idx].size; UDS_FlipEndian(&(F1DID), sizeof(F1DID)); /* Copy requested DID into transmission buffer */ memcpy(Copy_position, &(F1DID), sizeof(F1DID)); Copy_position = Copy_position + sizeof(F1DID); rtn_length += 2; switch (((uint16_t)(DIDtable[DID_idx].DidEnum & 0x0000FFFFu))) { // case DID_UDS_NS_VINDataIdentifier: /*0xF190*/ // case DID_UDS_NS_DUNSIdentification: // case DID_UDS_NS_MTC: // case DID_UDS_NS_ManufacturersModeFlag: // case DID_UDS_NS_ECUPartNumber: // case DID_UDS_NS_SupplierECUSoftwareVersionNumber: // UDS_StringCopy(ptr_src, (char *)Copy_position, length); // break; // case DID_UDS_NS_BaseModelPartNumber: // case DID_UDS_NS_EndModelPartNumber: // memcpy(Copy_position, ptr_src, 4); // UDS_FlipEndian(Copy_position, 4); // break; // case DID_UDS_NS_BaseModelPartNumberVersionCode: // case DID_UDS_NS_EndModelPartNumberVersionCode: // memcpy(Copy_position, ptr_src, 2); // UDS_FlipEndian(Copy_position, 2); // break; // case DID_UDS_NS_RepairShopCode: // memcpy(Copy_position, ptr_src, 8); // break; // case DID_UDS_NS_ProgrammingDate: // memcpy(Copy_position, ptr_src, 4); break; default: break; } rtn_length += length; #endif return 0; } /*****************************************************************************/ /* NAME : static void UDS_SendDidData(void) */ /* */ /* DESCRIPTION : */ /* This function composes the payload of requested DID data and */ /* pass the payload for CANTP to send */ /* INPUTS : */ /* void */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Compose and send payload */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/18/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SendDidData(void) { uint16_t i = 0; uint16_t SendDataSize = 1; /* Reserve for the Response ID */ uint8_t *Copy_position; /* Specifies the starting address of copying */ /* Use a word to store the least significant 2 bytes of enum value */ uint16_t TwoByteDID = 0; /* Initialize the starting position of the copy, reserve the SID size */ Copy_position = UDS_L_tx_msg_buffer + SID_SIZE; /* Have a simple variable to store the intended index */ i = UDS_L_ReadDIDSet_t.DID_Table_Index; /* Parse out only the least significant 2 bytes */ TwoByteDID = (uint16_t)(DIDtable[i].DidEnum & 0x0000FFFFu); if ((TwoByteDID & 0xff00u) == 0xf100u) { UDS_SendF1DIDdata(Copy_position, i); SendDataSize = SendDataSize + sizeof(TwoByteDID); } else { /* Flip the two byte DID */ UDS_FlipEndian(&(TwoByteDID), sizeof(TwoByteDID)); /* Copy requested DID into transmission buffer */ memcpy(Copy_position, &(TwoByteDID), sizeof(TwoByteDID)); /* Update the copying position */ Copy_position = Copy_position + sizeof(TwoByteDID); SendDataSize = SendDataSize + sizeof(TwoByteDID); /* First copy the DID data into tx buffer */ memcpy(Copy_position, DIDtable[i].address, DIDtable[i].size); /* Flip endianness of the data to be sent IN THE TX BUFFER */ /* NOTE that we should not flip at DIDtable[i].address because */ /* it will crash the original data stored there */ UDS_FlipEndian(Copy_position, DIDtable[i].size); Copy_position = Copy_position + DIDtable[i].size; } SendDataSize = SendDataSize + DIDtable[i].size; /* Specify read data by DID response ID */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(READ_DATA_BY_IDENTIFIER); /* Specify the send payload size */ UDS_L_tx_msg_size = SendDataSize; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } static void UDS_RespTxMessage(void) { if (ssp_flg == true) /* ÒÖÖÆÕýÏìÓ¦, ²»·¢ËÍÕýÏìÓ¦ */ return; if (!CANTP_TxMessage(&UDS_L_tp_stack, UDS_L_tx_msg_buffer, UDS_L_tx_msg_size)) { UDS_SendNegResp(NRC_BUSY_REPEAT_REQUEST); } } /*****************************************************************************/ /* NAME : static void UDS_TesterPresent(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* This function resets the tester present timer */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Read data stream by identifier */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/18/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_TesterPresent(uint8_t *payload) { /* Reset the tester present waiting timer. If current session is */ /* extended session */ CDT_RESET(TesterPresentTimer_u16, UDS_NS_SessionTimeout_u16 / UDS_TASK_RATE); uint8_t sub_func = UDS_GET_SUB_FUNCTION(payload[UDS_RQ_BYTE1]); switch (sub_func) { case 0x00: UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(TESTER_PRESENT); UDS_L_tx_msg_buffer[1] = 0x00; UDS_L_tx_msg_size = 2; UDS_RespTxMessage(); break; default: UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); break; } } /*****************************************************************************/ /* NAME : static void UDS_SessionControl(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* Factory diagnosis session control */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Change session based on the third byte value of CAN msg */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 06/18/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SessionControl(uint8_t *payload) { uint16_t cnt = 5000u; /* Change session based on CAN message request */ bool UDS_SessionSetOk_b = false; uint8_t sub_func = UDS_GET_SUB_FUNCTION(payload[UDS_RQ_BYTE1]); switch (sub_func) { case EXTENDED: if ((UDS_L_Diag_session_e == DEFAULT) || (UDS_L_Diag_session_e == EXTENDED)) { UDS_L_Diag_session_e = EXTENDED; /* Reset the tester present waiting timer. */ CDT_RESET(TesterPresentTimer_u16, UDS_NS_SessionTimeout_u16 / UDS_TASK_RATE); UDS_SessionSetOk_b = true; } else { UDS_SendNegResp(NRC_CONDITIONS_NOT_CORRECT); } break; case PROGRAMMING: /* UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); */ if (((UDS_L_Diag_session_e == EXTENDED) || (UDS_L_Diag_session_e == PROGRAMMING))) { CDT_RESET(TesterPresentTimer_u16, UDS_NS_SessionTimeout_u16 / UDS_TASK_RATE); UDS_L_Diag_session_e = PROGRAMMING; UDS_SessionSetOk_b = true; FblSetFblProgramRequestFlag(); } else if ((UDS_L_Diag_session_e == DEFAULT)) /*DEFAULT session can not trans to PROGRAMMING*/ { UDS_SendNegResp(NRC_CONDITIONS_NOT_CORRECT); } else { } break; case DEFAULT: if (UDS_L_Diag_session_e == PROGRAMMING) { UDS_L_Diag_session_e = DEFAULT; UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(SESSION_CONTROL); UDS_L_tx_msg_buffer[1] = UDS_L_Diag_session_e; UDS_L_tx_msg_buffer[2] = 0; UDS_L_tx_msg_buffer[3] = 0; UDS_L_tx_msg_buffer[4] = 0; UDS_L_tx_msg_buffer[5] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x06; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); FblClrFblProgramRequestFlag(); while (cnt--) { ; /// wait send command send out and then reset } UDS_SwitchtoDefaultSession(true); while (1) ; } else { UDS_SwitchtoDefaultSession(false); } TesterPresentTimer_u16 = 0; break; default: UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); break; } if (UDS_SessionSetOk_b == true) { /* Compose the response payload */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(SESSION_CONTROL); UDS_L_tx_msg_buffer[1] = UDS_L_Diag_session_e; UDS_L_tx_msg_buffer[2] = 0; UDS_L_tx_msg_buffer[3] = 0; UDS_L_tx_msg_buffer[4] = 0; UDS_L_tx_msg_buffer[5] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x06; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } } /*****************************************************************************/ /* NAME : UDS_SecurityAccess(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* Security Access */ /* INPUTS : */ /* void */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 08/03/2017 Fogbugz: case#: */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SecurityAccess(uint8_t *payload) { if (UDS_L_Diag_session_e == DEFAULT) { /* Send a negative response.*/ UDS_SendNegResp(NRC_SECURITY_ACCESS_DENIED); return; } if ((UDS_L_SecurityFault_cnt == 3) || (UDS_L_SecurityStartDelay == 1)) { UDS_SendNegResp(NRC_REQUIRED_TIME_DELAY_NOT_EXPIRED); return; } uint32_t ReceiveKey = 0; uint8_t sub_func = UDS_GET_SUB_FUNCTION(payload[UDS_RQ_BYTE1]); switch (sub_func) { case REQUEST_LEVEL_ONE_SEED: case SEND_LEVEL_ONE_KEY: UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); // only support LEVEL 2 return; break; case REQUEST_LEVEL_TWO_SEED: UDS_L_SecurityAccessStep_e = REQUEST_LEVEL_TWO_SEED; /* Compose the response payload */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(SECURITY_ACCESS); UDS_L_tx_msg_buffer[1] = UDS_L_SecurityAccessStep_e; #if 0 UDS_L_tx_msg_buffer[2] = (uint8_t)(LEVEL2_SEED >> 8); UDS_L_tx_msg_buffer[3] = (uint8_t)(LEVEL2_SEED); #endif for (int i = 0; i < SEED_SIZE; i++) { UDS_L_tx_msg_buffer[2 + i] = (uint8_t)(LEVEL2_SEED >> ((SEED_SIZE - i - 1) * 8)); } /* Specify the send payload size */ /* UDS_L_tx_msg_size = 0x04; */ UDS_L_tx_msg_size = 2 + SEED_SIZE; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); break; case SEND_LEVEL_TWO_KEY: if (UDS_L_SecurityAccessStep_e != REQUEST_LEVEL_TWO_SEED) { UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); return; } /* ReceiveKey = payload[UDS_RQ_BYTE2]; */ /* ReceiveKey = (ReceiveKey << 8) | payload[UDS_RQ_BYTE3]; */ for (int i = 0; i < KEY_SIZE; i++) { ReceiveKey = ReceiveKey << 8 | payload[2 + i]; } if (ReceiveKey == LEVEL2_KEY) { /*right key*/ UDS_L_SecurityFault_cnt = 0; UDS_O_SecurityAccessState_e = SECURITY_ACCESS_UNLOCK_LEVEL_2; UDS_L_SecurityAccessStep_e = SECURITY_ACCESS_STEP_MAX; /* Compose the response payload */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(SECURITY_ACCESS); UDS_L_tx_msg_buffer[1] = SEND_LEVEL_TWO_KEY; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } else { UDS_SendNegResp(NRC_INVALID_KEY); if (++UDS_L_SecurityFault_cnt >= MAX_SECURITY_FAULT_CNT) { UDS_L_SecurityFault_cnt = MAX_SECURITY_FAULT_CNT; CDT_RESET(SecurityAcessTimer_u16, SECURITY_ACCESS_WAIT_TIME); UDS_SendNegResp(NRC_EXCEEDED_NUMBER_OF_ATTEMPTS); } } break; default: break; } } static void UDS_Reset(uint8_t ResetType) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ECU_RESET); UDS_L_tx_msg_buffer[1] = ResetType; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ // UDS_RespTxMessage(); if (ssp_flg == false) // ûÓÐÕýÏìÓ¦ÒÖÖÆ { TP_PDU_t msg; msg.arbId = UDS_RESP_TID; msg.extended = false; msg.RTR = false; msg.dlc = 8; msg.frame[0] = 0x03; msg.frame[1] = GET_RESPONSE_SERVICE_ID(ECU_RESET); msg.frame[2] = ResetType; for (int i = 0; i < 200; i++) // È·±£·¢³öÏìÓ¦ { UDS_WriteData(&msg, 0); } } CPU_HardReset(); } static void UDS_HardwareReset(void) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ECU_RESET); UDS_L_tx_msg_buffer[1] = 0x01; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); CPU_HardReset(); } static void UDS_SoftwareReset(void) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ECU_RESET); UDS_L_tx_msg_buffer[1] = 0x02; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); CPU_HardReset(); } static void UDS_ECURest(uint8_t *payload) { uint8_t sub_func = UDS_GET_SUB_FUNCTION(payload[UDS_RQ_BYTE1]); uint8_t reset_type = payload[UDS_RQ_BYTE1]; switch (sub_func) { case 0x01: // Hard Reset UDS_Reset(reset_type); break; case 0x02: // Key On Off Reset // UDS_Reset(reset_type); UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); break; case 0x03: // Soft Reset UDS_Reset(reset_type); break; case 0x04: // Enable Rapid Power Shutdown UDS_Reset(reset_type); break; default: UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); break; } } /*****************************************************************************/ /* NAME : static void UDS_RoutineControl(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* Factory routine control */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 09/09/06 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_RoutineControl(uint8_t *payload) { uint16_t RoutineID = 0; if ((UDS_L_Diag_session_e == DEFAULT) || ((UDS_O_SecurityAccessState_e != SECURITY_ACCESS_UNLOCK_LEVEL_1) && (UDS_O_SecurityAccessState_e != SECURITY_ACCESS_UNLOCK_LEVEL_2))) { /* Send a negative response.*/ UDS_SendNegResp(NRC_SECURITY_ACCESS_DENIED); return; } RoutineID = (uint16_t)payload[UDS_RQ_BYTE2] << 8 | (uint16_t)payload[UDS_RQ_BYTE3]; switch (RoutineID) { case 0xf001: UDS_CheckProgrammingIntergrity(payload); break; case 0xff02: UDS_CheckProgrammingPrecondition(); break; case 0xff00: UDS_EraseMemory(payload); break; case 0xff01: UDS_CheckProgrammingDependence(payload); /* UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); */ break; default: UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); break; } } static void UDS_ResponseTiming(void) { if (RESP_PENDING_MAX != UDS_L_ResponsePendingRequest_e) { if (CDT_EXPIRED(ResponsePendingTimer_u16) == true) { /**/ CDT_RESET(ResponsePendingTimer_u16, P2SERVER_PENDING_TIMEROUT); UDS_SendNegResp(NRC_TRANSFER_DATA_SUSPENDED); } else { if ((UDS_L_ResponsePendingRequest_e & CHECK_PROGRAMMING_INTERGRITY_PENDING) != 0) { if (transferType == DOWNLOAD_FLASH) { UDS_L_CRCCheckFail_b = !MEM_PartitionCRCOK((uint8_t)MEM_PARTITION_CODEFLASH, UDS_L_CRCReceived); if (UDS_L_CRCCheckFail_b == false) { NVM_ReInitFlashDriveRam(); // CLEAR FLASH DRIVE IN RAM } } else { UDS_L_CRCCheckFail_b = !MEM_PartitionCRCOK((uint8_t)MEM_PARTITION_RAM, UDS_L_CRCReceived); if (UDS_L_CRCCheckFail_b == true) { NVM_ReInitFlashDriveRam(); // CLEAR FLASH DRIVE IN RAM } } UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ROUTINE_CONTROL); UDS_L_tx_msg_buffer[1] = 0x01; UDS_L_tx_msg_buffer[2] = 0xf0; UDS_L_tx_msg_buffer[3] = 0x01; UDS_L_tx_msg_buffer[4] = (uint8_t)UDS_L_CRCCheckFail_b; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x05; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); UDS_L_ResponsePendingRequest_e &= (~CHECK_PROGRAMMING_INTERGRITY_PENDING); UDS_L_ResponsePendingRelease_e &= (~CHECK_PROGRAMMING_INTERGRITY_PENDING); } } } else { CDT_RESET(ResponsePendingTimer_u16, P2SERVER_PENDING_TIMEROUT); } } /*****************************************************************************/ /* NAME : static void UDS_CommunicationControl(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* Factory communication control */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Change communication based on the third byte value of CAN msg */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 07/31/2017 Fogbugz: case#: */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_CommunicationControl(uint8_t *payload) { if (UDS_L_Diag_session_e != EXTENDED) { /* Send a negative response.*/ UDS_SendNegResp(NRC_SECURITY_ACCESS_DENIED); return; } uint8_t ControlType = UDS_GET_SUB_FUNCTION(payload[UDS_RQ_BYTE1]); uint8_t CommunicationType = payload[UDS_RQ_BYTE2]; if ((ControlType != (uint8_t)EnableRxAndTx) || (CommunicationType != NormalCommunicationMessage) && (CommunicationType != NetManageCommMessage) && (CommunicationType != BothCommunicationMessage)) { UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); return; } if (payload[UDS_RQ_BYTE2] == NetManageCommMessage) { UDS_SendNegResp(NRC_SUBFUNCTION_NOT_SUPPORTED); return; } /* Change communnication type based on CAN message request */ UDS_L_CommunicationControlType_e = (UDS_CONTOL_TYPE_e)ControlType; /* Compose the response payload */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(COMMUNICATION_CONTROL); UDS_L_tx_msg_buffer[1] = UDS_L_CommunicationControlType_e; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } extern void UDS_GetCommunicationControlType(unsigned char *type) { *type = (unsigned char)(UDS_L_CommunicationControlType_e & 0x3); } static void UDS_EraseMemory(uint8_t *payload) { uint8_t lengthFormat = 0; uint8_t addrFormat = 0; uint8_t i = 0; int8_t erase_state = OP_STATUS_FAIL; lengthFormat = (uint8_t)((payload[UDS_RQ_BYTE4] & 0xf0) >> 4); addrFormat = (uint8_t)(payload[UDS_RQ_BYTE4] & 0x0f); eraseAddress = 0; eraseRemainder = 0; if (Nvm_Flags.flash_driver_loaded == 0) { /*flash not load to ram*/ UDS_SendNegResp(NRC_CONDITIONS_NOT_CORRECT); return; } for (i = 0; i < lengthFormat; i++) { eraseAddress <<= 8; eraseAddress |= payload[i + UDS_RQ_BYTE5]; } for (i = 0; i < addrFormat; i++) { eraseRemainder <<= 8; eraseRemainder |= payload[i + UDS_RQ_BYTE5 + lengthFormat]; } eraseRemainder += (64 - (eraseRemainder % 64)); if ((eraseAddress != APPCODE_START) || (eraseRemainder == 0)) { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } UDS_SendNegResp(NRC_SERVICE_BUSY); erase_state = NVM_EraseData(eraseAddress, eraseRemainder); if (erase_state == OP_STATUS_OK) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ROUTINE_CONTROL); UDS_L_tx_msg_buffer[1] = 0x01; UDS_L_tx_msg_buffer[2] = 0xff; UDS_L_tx_msg_buffer[3] = 0x00; UDS_L_tx_msg_buffer[4] = 0; // 0:ok 1£ºerror /* Specify the send payload size */ UDS_L_tx_msg_size = 5; UDS_RespTxMessage(); } else { UDS_SendNegResp(NRC_GENERAL_PROGRAMMING_FAILURE); } } static void UDS_CheckProgrammingIntergrity(uint8_t *payload) { #if 0 int8_t crc_state=OP_STATUS_FAIL; bool crc_result=false; FBL_UDS_O_transferCRC=(uint32_t)payload[4]<<24|(uint32_t)payload[5]<<16|(uint32_t)payload[6]<<8|(uint32_t)payload[7]; //crc_state=MEM_CodeCRCCheck(transferAddress+4,transferRemainder,FBL_UDS_SetCRCCheckResult); #if 0 if(crc_state==OP_STATUS_OK) { FBL_UDS_L_ResponsePendingRequest_e|=CHECK_PROGRAMMING_INTERGRITY_PENDING; UDS_SendNegResp(RESPONSEPENDING); } else { UDS_SendNegResp(GENERALPROGRAMMINGFAILURE); } #endif UDS_L_tx_msg_buffer[0] = RESP_ID_ROUTINE_CONTROL; UDS_L_tx_msg_buffer[1] = 0x01; UDS_L_tx_msg_buffer[2] = 0xf0; UDS_L_tx_msg_buffer[3] =0x01; if(transferType==DOWNLOAD_FLASH) { crc_result=MEM_PartitionCRCOK((uint8_t)MEM_PARTITION_CODEFLASH); } else { crc_result=MEM_PartitionCRCOK((uint8_t)MEM_PARTITION_RAM); } //UDS_L_tx_msg_buffer[4] = (uint8_t)(!crc_result); UDS_L_tx_msg_buffer[4] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x05; /* Compose a response message and send a positive */ /* response with the request data */ if(FBL_CANTP_TxMessage(&UDS_L_tp_stack, UDS_L_tx_msg_buffer, UDS_L_tx_msg_size)) { FBL_UDS_L_ResponsePendingRequest_e &=(~CHECK_PROGRAMMING_INTERGRITY_PENDING); FBL_UDS_L_ResponsePendingRelease_e &=(~CHECK_PROGRAMMING_INTERGRITY_PENDING); } #endif UDS_L_CRCReceived = (uint32_t)payload[4] << 24 | (uint32_t)payload[5] << 16 | (uint32_t)payload[6] << 8 | (uint32_t)payload[7]; UDS_L_ResponsePendingRequest_e |= CHECK_PROGRAMMING_INTERGRITY_PENDING; CDT_RESET(ResponsePendingTimer_u16, P2SERVER_PENDING_TIMEROUT); } static void UDS_CheckProgrammingDependence(uint8_t *payload) { UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ROUTINE_CONTROL); UDS_L_tx_msg_buffer[1] = 0x01; UDS_L_tx_msg_buffer[2] = 0xff; UDS_L_tx_msg_buffer[3] = 0x01; UDS_L_tx_msg_buffer[4] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x05; /* Compose a response message and send a positive */ UDS_RespTxMessage(); } static void UDS_CheckProgrammingPrecondition() { UDS_L_ProgrammingPreconditionCheckOK_b = true; /* always is true,maybe need check shiftpostion,speed and so on */ /* Compose the response payload */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(ROUTINE_CONTROL); UDS_L_tx_msg_buffer[1] = 0x01; UDS_L_tx_msg_buffer[2] = 0xff; UDS_L_tx_msg_buffer[3] = 0x02; UDS_L_tx_msg_buffer[4] = 0; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x05; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } static void UDS_RequestDownload(uint8_t *payload) { uint8_t lengthFormat; uint16_t receive_size = 0; lengthFormat = (uint8_t)((payload[UDS_RQ_BYTE2] & 0xf0) >> 4); if (payload[UDS_RQ_BYTE2] != 0x44) { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } if (UDS_L_rx_msg_size != REQUEST_DOWNLOAD_MSG_SIZE) { UDS_SendNegResp(NRC_INVALID_MESSAGE_LENGTH_OR_FORMAT); return; } if (UDS_L_TransferDataInProgressing_b == true) { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } expectedSequenceCnt = 0x01; currentSequenceCnt = 0x01; transferAddress = ((uint32_t)payload[UDS_RQ_BYTE3]) << 24 | ((uint32_t)payload[UDS_RQ_BYTE4]) << 16 | ((uint32_t)payload[UDS_RQ_BYTE5]) << 8 | ((uint32_t)payload[UDS_RQ_BYTE6]); transferRemainder = ((uint32_t)payload[UDS_RQ_BYTE7]) << 24 | ((uint32_t)payload[UDS_RQ_BYTE8]) << 16 | ((uint32_t)payload[UDS_RQ_BYTE9]) << 8 | ((uint32_t)payload[UDS_RQ_BYTE10]); if (transferRemainder == 0) { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } DownloadAddress = transferAddress; DownloadLength = transferRemainder; if (transferAddress == FLASH_DRIVER_START_ADDR) { transferType = DOWNLOAD_RAM; } else if (transferAddress == APPCODE_START) { transferType = DOWNLOAD_FLASH; } else { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } if (transferType == DOWNLOAD_FLASH) { /*flash driver is loaded?*/ if ((Nvm_Flags.flash_driver_loaded == 0)) { UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); return; } if ((transferAddress != APPCODE_START) || (transferAddress + transferRemainder > APPLICATION_END_ADDR)) { UDS_SendNegResp(NRC_REQUEST_OUT_OF_RANGE); return; } } else if ((transferType == DOWNLOAD_RAM)) { if ((transferRemainder > (uint32_t)RAM_FALSH_DRIVE_LENGHT) || ((tFblAddress)flashCode != transferAddress)) { // FblErrStatSetError(FBL_ERR_FLASHCODE_EXCEEDS_MEMORY); UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); return; } else { } } DID_UpdateAtpProgramCnt(); /*always from buff 0*/ currentbuffId = 0; UDS_L_TransferDataState_e = TRANFER_START; receive_size = FBL_RX_BUFFER_SIZE + 2; /*RESPONSE*/ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(REQUEST_DOWNLOAD); // UDS_L_tx_msg_buffer[1] = lengthFormat<<4; UDS_L_tx_msg_buffer[1] = 0x20; UDS_L_tx_msg_buffer[2] = (uint8_t)(receive_size >> 8); /*max length of block size,256Byte*/ UDS_L_tx_msg_buffer[3] = ((uint8_t)receive_size); /* Specify the send payload size */ UDS_L_tx_msg_size = 0x04; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } static void UDS_TransferData(uint8_t *payload) { uint8_t partition_id; uint32_t loadlength = 0; uint8_t i = 0; MEM_OPERATION_Ts operation_write; int8_t write_result = OP_STATUS_FAIL; /* Check if the requested sequence number is expected */ if (payload[UDS_RQ_BYTE1] != expectedSequenceCnt) { /* Check if sequence number corresponds to a retry */ if (payload[UDS_RQ_BYTE1] == currentSequenceCnt) { /* Handle the retries here */ /* Repetition of last transferData request */ /* Simply send a positive response without loading data to memory */ UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(TRANSFER_DATA); UDS_L_tx_msg_buffer[1] = currentSequenceCnt; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } else /* Sequence number is not for a retry */ { /* Send a WrongSequenceError */ UDS_SendNegResp(NRC_WRONG_BLOCK_SEQUENCE_COUNTER); return; } } if (transferRemainder == 0) //||(transferAddress>=startaddr+length) { /*already receive all data*/ UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); return; } if (transferType == DOWNLOAD_FLASH) { if (transferAddress >= APPLICATION_END_ADDR) { /*already receive all data*/ UDS_SendNegResp(NRC_REQUEST_SEQUENCE_ERROR); return; } partition_id = (uint8_t)MEM_PARTITION_CODEFLASH; } else { partition_id = (uint8_t)MEM_PARTITION_RAM; } /*COPY TP RX BUFF DATA TO MEM_TRMP BUFF*/ if (transferType == DOWNLOAD_FLASH) { if ((UDS_L_rx_msg_size - 2) < FBL_RX_BUFFER_SIZE) { for (i = 0; i < (FBL_RX_BUFFER_SIZE + 2 - UDS_L_rx_msg_size); i++) { payload[UDS_L_rx_msg_size + i] = 0xff; } } else { } loadlength = FBL_RX_BUFFER_SIZE; } else { // loadlength+=((uint32_t)(UDS_L_rx_msg_size-2)); loadlength = ((uint32_t)(UDS_L_rx_msg_size - 2)); } memcpy((void *)&Mem_PartionTempBuff[currentbuffId][0], &payload[UDS_RQ_BYTE2], loadlength); operation_write.p_buffer = &Mem_PartionTempBuff[currentbuffId][0]; operation_write.partition_id = partition_id; operation_write.mem_operation_id = NVM_OP_TYPE_WRITE; operation_write.start_addr = transferAddress; operation_write.size_in_bytes = loadlength; operation_write.pfn_complete_cbk = NULL; operation_write.current_sequenc = expectedSequenceCnt; operation_write.prev_seqence = currentSequenceCnt; // UDS_SendNegResp(NRC_SERVICE_BUSY); // first send busy write_result = NEM_WriteData(&operation_write); // todo write all data at this function if (write_result == OP_STATUS_OK) { transferAddress += loadlength; transferRemainder -= (UDS_L_rx_msg_size - 2); // transferRemainder-=loadlength; if (transferRemainder == 0) { UDS_L_TransferDataState_e = TRANFER_END; } if (currentbuffId == 0) { currentbuffId = 1; } else { currentbuffId = 0; } /* Memorize current counter */ currentSequenceCnt = expectedSequenceCnt; /* Sequence counter value of next transferData request */ expectedSequenceCnt++; UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(TRANSFER_DATA); UDS_L_tx_msg_buffer[1] = currentSequenceCnt; /* Specify the send payload size */ UDS_L_tx_msg_size = 0x02; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); } else { UDS_SendNegResp(NRC_GENERAL_PROGRAMMING_FAILURE); } } static void UDS_RequestTransferExit(uint8_t *payload) { if (transferType == DOWNLOAD_FLASH) { transferAddress = APPCODE_START; transferRemainder = 0; } else { transferAddress = FLASH_DRIVER_START_ADDR; transferRemainder = 0; } UDS_L_TransferDataInProgressing_b = false; UDS_L_TransferDataState_e = TRANFER_IDLE; // transferType=0; expectedSequenceCnt = 0x01; currentSequenceCnt = 0x01; UDS_L_tx_msg_buffer[0] = GET_RESPONSE_SERVICE_ID(REQUEST_TRANSFER_EXIT); /* Specify the send payload size */ UDS_L_tx_msg_size = 0x01; /* Compose a response message and send a positive */ /* response with the request data */ UDS_RespTxMessage(); DID_UpdateProgramCnt(); } /*****************************************************************************/ /* NAME : static void UDS_SendNegResp(NEGA_RESP_Code_e reason) */ /* */ /* DESCRIPTION : */ /* This function composes and send a negative response */ /* INPUTS : */ /* NEGA_RESP_Code_e reason: Negative response reason */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Send negative response */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 07/29/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SendNegResp(NEGA_RESP_Code_e reason) { TP_PDU_t out = {0}; /* Pack and send CAN message */ out.arbId = UDS_RESP_TID; out.extended = false; out.RTR = false; out.dlc = 8; out.frame[0] = 3; out.frame[1] = 0x7F; out.frame[2] = UDS_L_rx_msg_buffer[0]; out.frame[3] = (uint8_t)reason; #if 0 CANTP_zeroRestOfFrame(&out); #endif UDS_WriteData(&out, 0); } /*****************************************************************************/ /* NAME : static void UDS_FlipEndian(void *address, uint16_t size) */ /* */ /* DESCRIPTION : */ /* Function to flip the endianness of a set of memory locations */ /* and put the flipped number back to *address location */ /* INPUTS : */ /* void* address : Start address of the memory location */ /* uint16_t size : Memory size */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* [1] Flip endianness */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 07/31/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_FlipEndian(void *address, uint16_t size) { uint8_t temp = 0; uint8_t i = 0; for (i = size; i > size / 2; i--) { temp = ((uint8_t *)address)[size - i]; ((uint8_t *)address)[size - i] = ((uint8_t *)address)[i - 1]; ((uint8_t *)address)[i - 1] = temp; } } /*****************************************************************************/ /* NAME : static void UDS_BuildDidSet(uint8_t * payload) */ /* */ /* DESCRIPTION : */ /* This function builds up the set of requested DID */ /* INPUTS : */ /* uint8_t * payload: pointer to the payload starting address */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Build requested DID set */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 07/31/2014 Fogbugz: case#: 1575 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static bool UDS_BuildDidSet(uint8_t *payload) { #if 1 uint16_t i = 0; bool DIDnotFoundflag = false; /* Set the initial value of requested DID set size */ /* UDS_L_ReadDidSetSize_u16 = 0; */ UDS_L_ReadDIDSet_t.DID_Value = payload[1] << 8 | payload[2]; /* For each requested DID, verify it can be found in current DID table */ for (i = 0; (i < UDS_DID_TABLE_SIZE) && (DIDtable[i].DidEnum != UDS_L_ReadDIDSet_t.DID_Value); i++) { /* break; */ } /* i == DIDTable_Entry_Count_u16 means no data with the DID is found */ if (i == UDS_DID_TABLE_SIZE) { /* Flag the fact that there is DID that cannot be found */ DIDnotFoundflag = true; } else { /* Continue with next requested DID */ UDS_L_ReadDIDSet_t.DID_Table_Index = i; } return (DIDnotFoundflag); #else bool not_found = true; UDS_L_ReadDIDSet_t.DID_Value = payload[1] << 8 | payload[2]; uint16_t i; for (i = 0; i < UDS_DID_TABLE_SIZE; i++) { if (UDS_L_ReadDIDSet_t.DID_Value == DIDtable[i].DidEnum) { UDS_L_ReadDIDSet_t.DID_Table_Index = i; not_found = false; break; } } return not_found; #endif } /*****************************************************************************/ /* NAME : static void UDS_SwitchtoDefaultSession(void) */ /* */ /* DESCRIPTION : */ /* This function handles the operations to switch to default session*/ /* INPUTS : */ /* None */ /* OUTPUTS : */ /* None */ /* RETURN : */ /* void */ /* PROCESS : */ /* Build requested DID set */ /* NOTES : */ /* None */ /* REVISION HISTORY : */ /* (1) Date: 10/30/2014 Fogbugz: case#: 2283 */ /* Initial release by Tom Tao */ /*****************************************************************************/ static void UDS_SwitchtoDefaultSession(uint8_t restcmd) { UDS_L_Diag_session_e = DEFAULT; UDS_L_ProgrammingPreconditionCheckOK_b = false; if (restcmd == true) { CPU_HardReset(); } } static void UDS_StringCopy(char *p_src, char *p_dest, uint8_t max_size) { uint8_t pn_len = 0u; uint8_t i = 0u; if ((p_src != NULL) && (p_dest != NULL) && (max_size > 0)) { /* get the length of the string, limited to max_size */ pn_len = strnlen(p_src, max_size); /* p_src=p_src+pn_len; */ /* copy source into dest */ for (i = 0u; i < pn_len; i++) { *p_dest++ = *p_src++; } for (i = pn_len; i < max_size; i++) { *p_dest++ = '\0'; } } } /* end of _UDS_H */