From 9995c72909bbc4fee881c700b5349f031249f6a6 Mon Sep 17 00:00:00 2001 From: lidun <1084178170@qq.com> Date: Thu, 21 Mar 2024 09:35:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9UDS=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E7=9A=84=E6=9B=B4=E6=96=B0=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: lidun <1084178170@qq.com> --- UDS/diagnosis_mid.c | 2725 ++++++++++++++++++++++--------------------- UDS/uds_api.c | Bin 16384 -> 11312 bytes UDS/uds_dtc.h | Bin 12288 -> 4719 bytes 3 files changed, 1368 insertions(+), 1357 deletions(-) diff --git a/UDS/diagnosis_mid.c b/UDS/diagnosis_mid.c index f5df57d..05ce200 100644 --- a/UDS/diagnosis_mid.c +++ b/UDS/diagnosis_mid.c @@ -1,1357 +1,1368 @@ -#include "uds_config.h" -#include "uds_nvm.h" -#include "BSP_CAN.h" -#include "crc.h" -#if BOOTLOADER_CODE_FLAG == 0 -#include "can.h" -#include "Car_CANIDInfo.h" - -const uint8_t SWFingerPrint[12] __attribute__((at(APP_FlagAddress))) = - {'S','5','0','8','_','D','C','U','2','4','0','1'}; -#else - -#endif - - -//INT32U g_ulRand=0; -DIDs gDIDCache; - - -//uint8_t g_testerprogramdateflag = false; -//uint8_t g_testerserialnubnerflag = false; - -//extern INT8U strMcuAppst[4]; -//extern INT8U strMcuAppDate[4]; -extern INT32U ParseCanRxCnt; -extern uint32_t FBL_AppSize; - - -//_HSCANERROR HsCanError; -uint32_t g_ulCanStatus; - -VehicleInfo2UdsType vehicleInfo2uds; -UdsInfo2VehicleType udsInfo2Vehicle = { - .NcmRxEnable = true, - .NcmTxEnable = true, - .NmcmRxEnable = true, - .NmcmTxEnable = true, - .UdsOffLine = true, -}; - - -uint16_t diagStart_InitTimer = DIAG_START_INIT_TIME; -uint16_t diagStart_Timer = DIAG_START_TIME; -DTC_STRUCT dtcComm; -DTC_StatusType dtcStatusBak; -DTC_Fault_Flags faultInfo; //故障信息 -DTC_Options dtcOptions; -const uint32_t DTC_LIST_TABLE[DTC_ID_NUM] = { - DTC_FOREACH(GENERATE_DTC_VALUE_ARRAY) -}; -uint8_t dtcsnapshotNumberTotal; -uint16_t dtcSnapshotDataBuf[DTC_ID_NUM]; -static uint16_t BMS_CommLossTimer = 0; -static uint16_t VCU_CommLossTimer = 0; - -void UdsDidUpdateVehicle(void) -{ - udsInfo2Vehicle.ChargeTempProtVal = gDIDCache.DID_DCUVariousTempProtectVal[0]; - udsInfo2Vehicle.BoardTempProtVal = gDIDCache.DID_DCUVariousTempProtectVal[1]; - udsInfo2Vehicle.DCVoltProtVal = WORD(gDIDCache.DID_DCVoltProtectVal[0], gDIDCache.DID_DCVoltProtectVal[1]); - udsInfo2Vehicle.InsulDetVoltVal = WORD(gDIDCache.DID_InsulationDectVolt[0], gDIDCache.DID_InsulationDectVolt[1]); -} - -void UdsDtcUpdateVehicle(void) -{ - uint8_t index; - uint8_t num, list[DTC_ID_NUM]; - static DTC_Fault_Flags fflag = {.w = 0}; - - if (fflag.w != faultInfo.w) { - fflag = faultInfo; - num = 0; - for (index = 0; index < DTC_ID_NUM; index++) { - if (dtcComm.DTCStatus.recordData[index].status == ((1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC))) { - list[num++] = index + 1; - } - } - udsInfo2Vehicle.DTCNum = num; - memset(udsInfo2Vehicle.DTCList, 0, DTC_ID_NUM); - memcpy(udsInfo2Vehicle.DTCList, list, num); - } -} - -void DID_SignalInit(void) -{ - uint8_t i; - uint8_t index; - uint16_t size; - uint8_t *cachePtr, *didPtr; - uint8_t *nvmDidPtr; - DIDS_NvmType *dids; - Param_NvmType *param; - - EE_Read(NVM_IMAGE_DID_ADDR, (uint8_t **)&dids); - cachePtr = (uint8_t *)&gDIDCache; - - for (i = 0; i < DID_StoreInFlash_NUM; i++) { - index = GetDIDIndexByID(DIDStoreInFlashId[i]); - - if (index != 0xff) { - didPtr = cachePtr + DIDOffset[index]; - size = DIDStoreInFlashSize[i]; - nvmDidPtr = (uint8_t *)dids + DIDStoreInFlashOffset[i]; - - if (CRC16_DataCheck(nvmDidPtr, size) == 0) { - memcpy(didPtr, nvmDidPtr, size); - } - } - } - UdsDidUpdateVehicle(); - - EE_Read(NVM_IMAGE_PARAM_ADDR, (uint8_t **)¶m); - if (CRC16_DataCheck((uint8_t *)param, sizeof(Param_NvmType)-2) == 0) { - UdsParam.SA_FailureCounter = param->Param.SA_FailureCounter; - UdsService.KeyErrCnt = UdsParam.SA_FailureCounter; - if (UDS_27SERVICE_ERR_NUM_MAX <= UdsService.KeyErrCnt) { - UdsService.KeyErrLockTimer = UDS_27SERVICE_KEY_ERRLOCK_TIME; - UdsService.KeyLockFlg = true; - } - } else { - UdsService.KeyErrLockTimer = 0; - UdsService.KeyLockFlg = false; - UdsService.KeyErrCnt = 0; - } -} - -void DTC_SignalInit(void) -{ -#if BOOTLOADER_CODE_FLAG == 0 - uint8_t index; - uint8_t size; - DTCS_NvmType *dtc, *dtcBak; - - EE_Read(NVM_IMAGE_DTC_ADDR, (uint8_t **)&dtc); - size = sizeof(DTC_RecordDataBufType); - - for (index = 0; index < DTC_ID_NUM; index++) { - if (CRC16_DataCheck((uint8_t *)&dtc->DTC_Status.recordData[index], size - 2) == 0) { - memcpy((uint8_t *)&dtcComm.DTCStatus.recordData[index], (uint8_t *)&dtc->DTC_Status.recordData[index], size); - memcpy((uint8_t *)&dtcStatusBak.recordData[index], (uint8_t *)&dtc->DTC_Status.recordData[index], size); - } - - if (dtcComm.DTCStatus.recordData[index].status == ((1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC))) { - faultInfo.w |= 1 << index; - } - } - // UdsDtcUpdateVehicle(); - // diagStart_InitTimer = DIAG_START_INIT_TIME; - // diagStart_Timer = DIAG_START_TIME; - dtcOptions.w = 0xffffffff; - SnapshotRecordNumberGet(dtcComm.DTCStatus.recordData, dtcSnapshotDataBuf, &dtcsnapshotNumberTotal); -#endif -} - -void UDS_ServiceInit(void) -{ - // //ECU 上电或复位后默认处于闭锁状态,同时错误计数器重置为零。 - // UdsService.KeyErrLockTimer = 0; - // UdsService.KeyLockFlg = false; - // UdsService.KeyErrCnt = 0; - - UdsService.SessionDiagModel = _UDS_DEFAULT_SESSION; - UdsService.SeedKeyIsOK = 0; - UdsService.AlreadSendSeed = false; - UdsService.GenerateSeedReq_Non = false; - UdsService.SessionTimer = 0; - UdsService.NcmDisRxAndTx = 0; - UdsService.NmcmDisRxAndTx = 0; - UdsService.DisDTCRecord = 0; -} - -void DTC_SignalRecover(void) -{ - -} - - -void GenRand(void) -{ - -} - - -#if BOOTLOADER_CODE_FLAG == 0 - -void SnapshotRecordLoad(DTC_RecordDataBufType *record) -{ - record->snapshot = vehicleInfo2uds.Snapshot; -} - -uint8_t SnapshotRecordFill(uint8_t *data, DTC_SnapshotType *snapshot) -{ - uint8_t j = 0; - uint16_t dataId; - - dataId = 0xCF00; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->BatVolt; - dataId = 0xCF01; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->SOCH; - data[j++] = snapshot->SOCL; - dataId = 0xCF02; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->DCInVolH; - data[j++] = snapshot->DCInVolL; - dataId = 0xCF03; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->GunSts; - dataId = 0xCF04; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->DCRealySts; - dataId = 0xCF05; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->ACRealySts; - dataId = 0xCF06; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->CC2ResistorH; - data[j++] = snapshot->CC2ResistorL; - dataId = 0xCF07; - data[j++] = (uint8_t)(dataId >> 8); - data[j++] = (uint8_t)(dataId & 0x00ff); - data[j++] = snapshot->CommSts; - - return j; -} - -void SnapshotRecordNumberGet(DTC_RecordDataBufType *record_data, uint16_t *dataBuf, uint8_t *num) -{ - uint8_t i = 0; - uint8_t k = 0, j = 0; - uint16_t temp; - - *num = 0; - for (i=0; i(uint8_t)dataBuf[k+1]) { - temp = dataBuf[k+1]; - dataBuf[k+1] = dataBuf[k]; - dataBuf[k] = temp; - } - } - } - } -} - -uint8_t DiagDtcReportSnapshotFill(uint8_t sub_func, DTC_RecordDataBufType *record_data, uint8_t *data_buf, uint8_t *length) -{ - uint8_t ii = 0; - uint8_t ret = 1; - uint8_t num = 0, index; - uint32_t dtc_record; - uint16_t *snap_buf = dtcSnapshotDataBuf; - - data_buf[(*length)++] = DIAG_SERVE_READ_DTC|0x40; - data_buf[(*length)++] = sub_func; - - SnapshotRecordNumberGet(record_data, snap_buf, &num); - - for (ii=0; ii>8); - dtc_record = DTC_LIST_TABLE[index]; - data_buf[(*length)++] = (uint8_t)(dtc_record>>16); - data_buf[(*length)++] = (uint8_t)(dtc_record>>8); - data_buf[(*length)++] = (uint8_t)(dtc_record>>0); - data_buf[(*length)++] = record_data[index].snapNumber; - } - return 0; -} - -uint8_t DiagDtcSnapshotRecordFill(uint8_t sub_func, DTC_MaskRecordTpye mask_record, - uint8_t snap_record_num, DTC_RecordDataBufType *record_data, uint8_t *data_buf, uint8_t *length) -{ - uint8_t ii = 0; - uint8_t ret = 1; - - data_buf[(*length)++] = DIAG_SERVE_READ_DTC|0x40; - data_buf[(*length)++] = sub_func; - - for (ii=0; ii= DTC_ID_NUM) { - return; - } - if (dtc_record_data->status != status) { - if (status == ((1<snapNumber) { - (*snapshot_number_total)++; - dtc_record_data->snapNumber = *snapshot_number_total; - } - - if (dtc_record_data->extended.FaultCounter != 0xff) { - dtc_record_data->extended.FaultCounter ++; - } - } - // dtc_record_data->extended.FaultAgingCounter = 0; - } - - dtc_record_data->status = status; -} - - -//电压正且非busoff、电源ON下 -void DiagFaultsMonitor(void) -{ - - // if (CheckIsBatteryHigh())return; - - // if (CheckIsBatteryLow())return; - - // if (CheckIsIgnON()) { - - if (vehicleInfo2uds.InOverVoltFault) { - faultInfo.b.fINPUT_OVERVOLTAGE = 1; - } else { - faultInfo.b.fINPUT_OVERVOLTAGE = 0; - } - - if (vehicleInfo2uds.InUnderVoltFault) { - faultInfo.b.fINPUT_UNDERVOLTAGE = 1; - } else { - faultInfo.b.fINPUT_UNDERVOLTAGE = 0; - } - - if (vehicleInfo2uds.ChargeTempDerateFault) { - faultInfo.b.fCHARGE_TEMP_DERATE = 1; - } else { - faultInfo.b.fCHARGE_TEMP_DERATE = 0; - } - - if (vehicleInfo2uds.InterTempDerateFault) { - faultInfo.b.fINTER_TEMP_DERATE = 1; - } else { - faultInfo.b.fINTER_TEMP_DERATE = 0; - } - - if (vehicleInfo2uds.InterOverTempFault) { - faultInfo.b.fINTER_OVERTEMP = 1; - } else { - faultInfo.b.fINTER_OVERTEMP = 0; - } - - if (vehicleInfo2uds.ChargeOverTempFault) { - faultInfo.b.fCHARGE_OVERTEMP = 1; - } else { - faultInfo.b.fCHARGE_OVERTEMP = 0; - } - - if (vehicleInfo2uds.DcPosRelayAdhFault) { - faultInfo.b.fDC_POS_RELAY_ADH = 1; - } else { - faultInfo.b.fDC_POS_RELAY_ADH = 0; - } - - if (vehicleInfo2uds.DcNegRelayAdhFault) { - faultInfo.b.fDC_NEG_RELAY_ADH = 1; - } else { - faultInfo.b.fDC_NEG_RELAY_ADH = 0; - } - - if (vehicleInfo2uds.AcPosRelayAdhFault) { - faultInfo.b.fAC_POS_RELAY_ADH = 1; - } else { - faultInfo.b.fAC_POS_RELAY_ADH = 0; - } - - if (vehicleInfo2uds.AcNegRelayAdhFault) { - faultInfo.b.fAC_NEG_RELAY_ADH = 1; - } else { - faultInfo.b.fAC_NEG_RELAY_ADH = 0; - } - - if (vehicleInfo2uds.HvInterlockFault) { - faultInfo.b.fHV_INTERLOCK = 1; - } else { - faultInfo.b.fHV_INTERLOCK = 0; - } - - if (vehicleInfo2uds.CcCc2RelayCtrlInv) { - faultInfo.b.fCC_CC2_RELAY_CTRL_INV = 1; - } else { - faultInfo.b.fCC_CC2_RELAY_CTRL_INV = 0; - } - - if (vehicleInfo2uds.CpCc1RelayCtrlInv) { - faultInfo.b.fCP_CC1_RELAY_CTRL_INV = 1; - } else { - faultInfo.b.fCP_CC1_RELAY_CTRL_INV = 0; - } - - if (CheckIsCanBusoff()) { - if (vehicleInfo2uds.BusoffCnt >= 8) - { - faultInfo.b.fECU_ENTER_BUSOFF = 1; - } - } else { - faultInfo.b.fECU_ENTER_BUSOFF = 0; - } - - if (CheckIsCanBusoff())return; - - // if (diagStart_Timer) { - // diagStart_Timer --; - // if (diagStart_Timer == 0) { - // BMS_CommLossTimer = 0; - // } - // return; - // } else { - if (++BMS_CommLossTimer > 200) { - faultInfo.b.fBMS_COMM_LOSE = 1; - BMS_CommLossTimer = 0; - } - if (++VCU_CommLossTimer > 300) { - faultInfo.b.fVCU_COMM_LOSE = 1; - VCU_CommLossTimer = 0; - } - // } - // } else { - // diagStart_Timer = DIAG_START_TIME; - // } - -} - -void Uds_SetMsgMonitorTimer(uint16_t msgid) -{ -#if BOOTLOADER_CODE_FLAG == 0 - if (!udsInfo2Vehicle.NcmRxEnable) return; - switch (msgid) { - case Bms_104: - faultInfo.b.fBMS_COMM_LOSE = 0; - BMS_CommLossTimer = 0; - break; - case Vcu_state_111: - faultInfo.b.fVCU_COMM_LOSE = 0; - VCU_CommLossTimer = 0; - default: - break; - } -#endif -} - -void GetBatteryStatus(void) -{ - if (CheckIsBatteryHigh()) { - faultInfo.b.fECU_VOLTAGE_HIGH = 1; - } else { - faultInfo.b.fECU_VOLTAGE_HIGH = 0; - } - - if (CheckIsBatteryLow()) { - faultInfo.b.fECU_VOLTAGE_LOW = 1; - } else { - faultInfo.b.fECU_VOLTAGE_LOW = 0; - } -} - -#if 0 -void DtcAging_Process(void) -{ - uint8_t index; - DTC_RecordDataBufType *dtc_record_data; - static uint8_t ignStsBak = 1; - - if (ignStsBak != vehicleInfo2uds.IgnSts) { - ignStsBak = vehicleInfo2uds.IgnSts; - - if (vehicleInfo2uds.IgnSts) { - for (index = 0; index < DTC_ID_NUM; index++) { - dtc_record_data = &dtcComm.DTCStatus.recordData[index]; - if (dtc_record_data->status == (1 << DTC_STATUS_Confirmed_DTC)) { - dtc_record_data->extended.FaultAgingCounter++; - if (dtc_record_data->extended.FaultAgingCounter >= 40) { - dtc_record_data->extended.FaultAgingCounter = 0; - dtc_record_data->status = 0; - if (dtc_record_data->extended.FaultCounterOfAge != 0xff) { - dtc_record_data->extended.FaultCounterOfAge++; - } - } - } - } - } - } -} -#endif - -void ClearHardwareFault(void) -{ - UdsApi_HardwareFault_ForceClear(); -} - -void GetFaultInfo(void) -{ - uint8_t shift, status; - uint8_t size; - uint16_t crc16; - DTC_Fault_Flags littleFault; - DTC_RecordDataBufType *pDtcRecordData; - static uint8_t wrIndex = 0; - static uint8_t timer100ms; - - if (diagStart_InitTimer > 0) { //电压正常后才计数 - diagStart_InitTimer --; - - return; - } - GetBatteryStatus(); - - DiagFaultsMonitor(); - - if (UdsService.DisDTCRecord) { - return; - } - - // DtcAging_Process(); - - if (DTC_ID_NUM <= 32) { - //littleFault.w= BigLittleSwap32(faultInfo.w); - littleFault.w = faultInfo.w; - - for (shift = 0; shift < DTC_ID_NUM; shift++) { - - if ((littleFault.w >> shift) & 0x00000001) { - status = (1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC); //当前故障 - } else { - status = dtcComm.DTCStatus.recordData[shift].status & (~(1 << DTC_STATUS_Test_Failed)); - } - - DiagUpdateDtcValue(shift, status); - } - } else { - //超出32个的,需要特殊处理 - } - - size = sizeof(DTC_RecordDataBufType); - pDtcRecordData = &dtcComm.DTCStatus.recordData[wrIndex]; - if (pDtcRecordData->status != dtcStatusBak.recordData[wrIndex].status \ - /*|| pDtcRecordData->extended.FaultAgingCounter != dtcStatusBak.recordData[wrIndex].extended.FaultAgingCounter*/) { - crc16 = CRC_Cal16_WithCfg((uint8_t *)pDtcRecordData, size - 2); - pDtcRecordData->crc16[0] = (uint8_t)crc16; - pDtcRecordData->crc16[1] = (uint8_t)(crc16 >> 8); - - dtcStatusBak.recordData[wrIndex].status = pDtcRecordData->status; - // dtcStatusBak.recordData[wrIndex].extended.FaultAgingCounter = pDtcRecordData->extended.FaultAgingCounter; - EE_Write(NVM_IMAGE_DTC_ADDR + (size * wrIndex), (uint8_t *)pDtcRecordData, size, NULL); - } - wrIndex++; - if (wrIndex >= DTC_ID_NUM) { - wrIndex = 0; - } - - if (++timer100ms >= 10) { - timer100ms = 0; - UdsDtcUpdateVehicle(); - } -} - - -void ClearDtc(void) -{ - uint8_t shift; - uint16_t crc16; - DTC_RecordDataBufType *pDtcRecordData; - - faultInfo.w = 0; - dtcsnapshotNumberTotal = 0; - for (shift = 0; shift < DTC_ID_NUM; shift++) { - pDtcRecordData = &dtcComm.DTCStatus.recordData[shift]; - - memset((uint8_t *)pDtcRecordData, 0x00, sizeof(DTC_RecordDataBufType) - 2); - crc16 = CRC_Cal16_WithCfg((uint8_t *)pDtcRecordData, sizeof(DTC_RecordDataBufType) - 2); - pDtcRecordData->crc16[0] = (uint8_t)crc16; - pDtcRecordData->crc16[1] = (uint8_t)(crc16 >> 8); - } - - memcpy((uint8_t *)&dtcStatusBak, (uint8_t *)&dtcComm.DTCStatus, sizeof(DTC_StatusType)); - EE_Write(NVM_IMAGE_DTC_ADDR, (uint8_t *)&dtcComm.DTCStatus, sizeof(DTC_StatusType), NULL); - ClearHardwareFault(); -} - - -bool GetDtcStatusMask(uint8_t *pOut, uint8_t *len, uint8_t subFunc, uint8_t mask) -{ - bool retValue = FALSE; - uint8_t ii = 0; - uint8_t j = 0; - - dtcComm.DTCcount.map = 0; - pOut[j++] = DIAG_SERVE_READ_DTC | 0x40; - pOut[j++] = subFunc; - pOut[j++] = DTC_STATUS_Support_Bit_Status; - - for (ii = 0; ii < DTC_ID_NUM; ii++) { - /*if (((dtcComm.DTCStatus[ii]&DTC_STATUS_Support_Bit_Status) == (mask&DTC_STATUS_Support_Bit_Status))\ - ||(subFunc == DTC_ReportSupportedDTCs))*/ - if ((dtcComm.DTCStatus.recordData[ii].status & mask) \ - || (dtcComm.DTCStatus.recordData[ii].status == mask)\ - || (subFunc == DTC_ReportSupportedDTCs)) { - if ((dtcOptions.w >> ii) & 0x00000001) { - retValue = TRUE; - dtcComm.DTCcount.map++; - pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 16); - pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 8); - pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 0); - pOut[j++] = dtcComm.DTCStatus.recordData[ii].status; - } - } - } - - *len = j; - return retValue; -} -#endif - -void DiagDIDStoreFlash(uint16_t id) -{ - uint8_t didIndex, nvmDidIndex; - //uint16_t offset; - uint16_t size; - uint8_t *cachePtr, *didPtr, *nvmDidPtr = NULL; - uint16_t crc16; - bool storage_flag = false; - - nvmDidIndex = GetDIDStoreInFlashIndexByID(id); - - if (nvmDidIndex != 0xFF) { - didIndex = GetDIDIndexByID(id); - - if (didIndex != 0xFF) { - size = DIDSize[didIndex]; - cachePtr = (uint8_t *)&gDIDCache; - didPtr = cachePtr + DIDOffset[didIndex]; - crc16 = CRC_Cal16_WithCfg(didPtr, size); - didPtr[size] = (uint8_t)crc16; - size++; - didPtr[size] = (uint8_t)(crc16 >> 8); - size++; - nvmDidPtr = (uint8_t *)NVM_IMAGE_DID_ADDR + DIDStoreInFlashOffset[nvmDidIndex]; - - if (nvmDidPtr != NULL) { - EE_Write(nvmDidPtr, didPtr, size, NULL); - } - UdsDidUpdateVehicle(); - } - } -} - -void CheckDtcHsCanError(void) -{ - static uint16_t Timer100msCnt = 0; -#if BOOTLOADER_CODE_FLAG == 0 - static uint16_t Timer10msCnt = 0; -#endif - uint16_t crc16; - - -#if BOOTLOADER_CODE_FLAG == 0 - - if (++Timer10msCnt >= 10) { - Timer10msCnt = 0; - GetFaultInfo(); - // IgnChangeProcess(); 没有老化 - } - gDIDCache.DID_CurrentDCVolt[0] = MSB(vehicleInfo2uds.CurrDcVolt); - gDIDCache.DID_CurrentDCVolt[1] = LSB(vehicleInfo2uds.CurrDcVolt); - gDIDCache.DID_DCUVariousCurrentTempVal[0] = vehicleInfo2uds.ChargeTemp; - gDIDCache.DID_DCUVariousCurrentTempVal[1] = vehicleInfo2uds.BoardTemp; - -#endif - if (++Timer100msCnt >= 100) { - Timer100msCnt = 0; - - if (UdsParam.SA_FailureCounter != UdsService.KeyErrCnt) { - UdsParam.SA_FailureCounter = UdsService.KeyErrCnt; - crc16 = CRC_Cal16_WithCfg((uint8_t *)&UdsParam, sizeof(UdsParam) - 2); - UdsParam.crc16[0] = (uint8_t)crc16; - UdsParam.crc16[1] = (uint8_t)(crc16 >> 8); - EE_Write(NVM_IMAGE_PARAM_ADDR, (uint8_t*)&UdsParam, sizeof(UdsParam), NULL); - } - } - - if ((UdsService.UdsTxFlg == true) && (UdsService.UdsTxCompFlg == true)) { - UdsService.UdsTxFlg = false; - UdsService.UdsTxCompFlg = false; - HAL_UDS_Tx_Callback(); - //UdsQueueCanOut(); - UdsService.TxCompFlg = true; - //Debug("HAL_UDS_Tx_Callback \r\n"); // - } -} - -#if BOOTLOADER_CODE_FLAG == 0 -INT8U Get0x19SerDiagData(INT8U *pOut, INT8U Type, INT8U *pdata) -{ - INT8U RstLen = 0; -// INT16U i=0; -// INT32U dtc_code = 0; -// INT8U num = 0; - uint8_t dtcReportSubFunction; - uint8_t dtcRecordNumber; - uint8_t dtcStatusMask; - DTC_MaskRecordTpye dtcMaskRecord; - - dtcReportSubFunction = Type; - dtcStatusMask = pdata[1]; - - switch (dtcReportSubFunction) { - case DTC_ReportNumberOfDTCByStatusMask: - case DTC_ReportDTCByStatusMask: - case DTC_ReportSupportedDTCs: - if (GetDtcStatusMask(pOut, &RstLen, dtcReportSubFunction, dtcStatusMask) == FALSE) { - RstLen = 0; - pOut[RstLen++] = DIAG_SERVE_READ_DTC | 0x40; //0x59; - pOut[RstLen++] = dtcReportSubFunction; - pOut[RstLen++] = DTC_STATUS_Support_Bit_Status; - } - - if (dtcReportSubFunction == DTC_ReportNumberOfDTCByStatusMask) { - RstLen = 0; - pOut[RstLen++] = DIAG_SERVE_READ_DTC|0x40;//0x59; - pOut[RstLen++] = dtcReportSubFunction; - pOut[RstLen++] = DTC_STATUS_Support_Bit_Status; - pOut[RstLen++] = ISO15031_6_DTCformat; - pOut[RstLen++] = dtcComm.DTCcount.b.DTCcountHighByte; - pOut[RstLen++] = dtcComm.DTCcount.b.DTCcountLowByte; - } - - break; - case DTC_ReportDTCSnapshotIdentification: - DiagDtcReportSnapshotFill(dtcReportSubFunction, dtcComm.DTCStatus.recordData, pOut, &RstLen); - break; - case DTC_ReportDTCSnapshotRecordByDTCNumber: - dtcMaskRecord.DTCHightByte = pdata[1]; - dtcMaskRecord.DTCMiddleByte = pdata[2]; - dtcMaskRecord.DTCLowByte = pdata[3]; - dtcRecordNumber = pdata[4]; - if (DiagDtcSnapshotRecordFill(dtcReportSubFunction, dtcMaskRecord, dtcRecordNumber, - dtcComm.DTCStatus.recordData, pOut, &RstLen) != 0) { - RstLen = 0; - } - break; - case DTC_ReportDTCExtendedDataRecordByDTCNumber: - dtcMaskRecord.DTCHightByte = pdata[1]; - dtcMaskRecord.DTCMiddleByte = pdata[2]; - dtcMaskRecord.DTCLowByte = pdata[3]; - dtcRecordNumber = pdata[4]; - if (DiagDtcExtendedDataRecordFill(dtcReportSubFunction, dtcMaskRecord, dtcRecordNumber, - dtcComm.DTCStatus.recordData, pOut, &RstLen) != 0) { - RstLen = 0; - } - break; - default: - break; - } - - return RstLen; -} -#endif - - - -INT16U Get0x22SerDiagData(INT8U *pOut) -{ - INT16U RstLen = 0; - INT16U ReqId = 0; -// INT16U length = 0; - uint8_t i; - uint8_t *cachePtr; - uint8_t size; - - ReqId = ((UdsService.ReqCmdBuf[0] << 8) + UdsService.ReqCmdBuf[1]); - - pOut[RstLen++] = 0x62; - pOut[RstLen++] = ((ReqId >> 8) & 0xFF); - pOut[RstLen++] = (ReqId & 0xFF); - - cachePtr = (uint8_t *)&gDIDCache; - - for (i = 0; i < DID_NUM; i++) { - if (ReqId == DIDId[i]) { - break; - } - } - - if (i == DID_NUM) { - RstLen = 2; - } else { -#if BOOTLOADER_CODE_FLAG - - if (!CheckIsSupportBootloaderRead_Sid22(ReqId)) { - RstLen = 2; - } - -#endif - } - - if (RstLen != 2) { - size = DIDSize[i]; - - memcpy(&pOut[RstLen], (cachePtr + DIDOffset[i]), size); - RstLen += size; - } - - return RstLen; -} - -#if BOOTLOADER_CODE_FLAG - -INT8U Set0x36DiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) -{ - uint8_t /*i=0,*/ucErrCode = 0; - uint8_t sn = 0; - - - sn = pIn[0]; - UdsUpData.totalRecvLength += (UdsService.RxDlc - 2); - - if (CheckIsBatteryHigh()) { - ucErrCode = 0x92; - } else if (CheckIsBatteryLow()) { - ucErrCode = 0x93; - } else if (UdsService.RxDlc > (FMC_PAGE_SIZE + 2)) { - ucErrCode = 0x13; - } else if ((UdsUpData.DownloadSeq != DOWNLOAD_SEQUENCE_34) && (UdsUpData.DownloadSeq != DOWNLOAD_SEQUENCE_36)) { - ucErrCode = 0x24; - } else if (sn != UdsUpData.Sn) { - ucErrCode = 0x73; - } else if (UdsUpData.totalRecvLength > FBL_AppSize) { - ucErrCode = 0x71; - } else { - UdsUpData.RxProgramFlag = true; - UdsUpData.DownloadSeq = DOWNLOAD_SEQUENCE_36; - memcpy(UdsUpData.Buf, &TP_Buffer[2], (UdsService.RxDlc - 2)); - ucErrCode = 0x78; - } - - return ucErrCode; - -} -#endif - -INT8U Set0x31DiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) -{ - - uint8_t service_buf[50]; - uint8_t /*i=0,*/ucErrCode = 0, ucRsp = 0; - uint16_t ReqId = 0; - uint16_t dlen = 0; - uint8_t result = 0; - - if (UdsService.RxDlc < 4) { - return 0x13; - } - - ucRsp = pIn[0]; - ReqId = pIn[1] << 8 | pIn[2]; - - service_buf[dlen++] = 0x71; - service_buf[dlen++] = pIn[0]; - service_buf[dlen++] = pIn[1]; - service_buf[dlen++] = pIn[2]; - -#if BOOTLOADER_CODE_FLAG == 0 - - static bool routineStartFlg = false; - if(0x01 == ucRsp) { - ReqId = pIn[1]<<8 | pIn[2]; - if((true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0203))\ - ||(true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0204)) - ||(true == CheckUdsDlcIsOk(UdsService.RxDlc,5) && (ReqId == 0x0207))) { - if (UdsService.SeedKeyIsOK) { - if (true == CheckVechileStatus()) { - switch (ReqId) { - case 0x0204: - result = 0x00; //correctResult - service_buf[dlen++] = result; - break; - case 0x0207: - if (pIn[3] <= 1) { - result = 0x00; //correctResult - udsInfo2Vehicle.DCDCEnable = pIn[3]; - } else { - result = 0x01; //incorrectResult - } - service_buf[dlen++] = result; - - break; - case 0x0203: - // if (UdsService.BattErrFlg == false) { - UdsService.ChkProgPreconditionFlg = true; - UdsService.ProgrammingPassTimer = PROGRAMMING_PASS_TIMEOUT_TIME; - // } - result = 0x00; //correctResult - service_buf[dlen++] = result; - break; - default: - break; - } - } else { - ucErrCode = 0x22; - } - if (!ucErrCode) { - routineStartFlg = true; - } - } else { - ucErrCode = 0x33; - } - } else if ((ReqId == 0x0203) || (ReqId == 0x0204) || (ReqId == 0x0207)) { - ucErrCode = 0x13; - } else { - ucErrCode = 0x31; - } - } else if(0x03 == ucRsp) { - ReqId = pIn[1]<<8 | pIn[2]; - if ((true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0204))) { - if (UdsService.SeedKeyIsOK) { - if (true == CheckVechileStatus()) { - if (true == routineStartFlg) { - routineStartFlg = false; - switch (ReqId) { - case 0x0204: - result = vehicleInfo2uds.OtaModeSts; - service_buf[dlen++] = result; - break; - default: - break; - } - } else { - ucErrCode = 0x24; - } - } else { - ucErrCode = 0x22; - } - } else { - ucErrCode = 0x33; - } - } else if ((ReqId == 0x0204)) { - ucErrCode = 0x13; - } else { - ucErrCode = 0x31; - } - } else if (0x02 == ucRsp) { - if ((true == CheckUdsDlcIsOk(UdsService.RxDlc, 4) && (ReqId == 0x0204))) { - if (UdsService.SeedKeyIsOK) { - switch (ReqId) { - case 0x0204: - result = 0x00; //correctResult - service_buf[dlen++] = result; - break; - default: - break; - } - } else { - ucErrCode = 0x33; - } - } else if ((ReqId == 0x0204)) { - ucErrCode = 0x13; - } else { - ucErrCode = 0x31; - } - } else { - if (true == UdsService.PhyFlg) { - UdsService.PhyFlg = false; - ucErrCode = 0x12; - } - } - -#endif - *RLen = dlen; - - if (ucErrCode == 0) { - memcpy(pOut, service_buf, dlen); - } - - return ucErrCode; - -} - -INT8U Set0x2EDidDiagData(INT8U *pIn, INT16U PLen) -{ - INT8U Rst = 0; - INT16U ReqId = 0; - - ReqId = ((pIn[0] << 8) + pIn[1]); - -#if BOOTLOADER_CODE_FLAG == 0 - if (ReqId == DIDId[VehicleIdentificationNumber]) { - if(PLen == DIDSize[VehicleIdentificationNumber]) { - if (UdsService.SeedKeyIsOK) { - if (CheckVechileStatus()) { - memcpy(gDIDCache.DID_VehicleIdentificationNumber,&pIn[2],PLen); - } else { - Rst = 0x22; - } - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else if (ReqId == DIDId[EOLData]) { - if(PLen == DIDSize[EOLData]) { - if (UdsService.SeedKeyIsOK) { - if (CheckVechileStatus()) { - memcpy(gDIDCache.DID_EOLData,&pIn[2],PLen); - } else { - Rst = 0x22; - } - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else if (ReqId == DIDId[DCUVariousTempProtectVal]) { - if(PLen == DIDSize[DCUVariousTempProtectVal]) { - if (UdsService.SeedKeyIsOK) { - if (CheckVechileStatus()) { - memcpy(gDIDCache.DID_DCUVariousTempProtectVal,&pIn[2],PLen); - } else { - Rst = 0x22; - } - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else if (ReqId == DIDId[DCVoltProtectVal]) { - if(PLen == DIDSize[DCVoltProtectVal]) { - if (UdsService.SeedKeyIsOK) { - if (CheckVechileStatus()) { - memcpy(gDIDCache.DID_DCVoltProtectVal,&pIn[2],PLen); - } else { - Rst = 0x22; - } - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else if (ReqId == DIDId[InsulationDectVolt]) { - if(PLen == DIDSize[InsulationDectVolt]) { - if (UdsService.SeedKeyIsOK) { - if (CheckVechileStatus()) { - memcpy(gDIDCache.DID_InsulationDectVolt,&pIn[2],PLen); - } else { - Rst = 0x22; - } - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else { - Rst = 0x31; - } - -#else - if (ReqId == DIDId[FingerPrint]) { - if(PLen == DIDSize[FingerPrint]) { - if (UdsService.SeedKeyIsOK) { - memcpy(gDIDCache.DID_FingerPrint,&pIn[2],PLen); - } else { - Rst = 0x33; - } - } else { - Rst = 0x13; - } - } else { - Rst = 0x31; - } - -#endif - - if (Rst == 0) { - DiagDIDStoreFlash(ReqId); - } - - return Rst; -} - -#if BOOTLOADER_CODE_FLAG == 0 -INT8U Set0x2FDiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) -{ - INT8U ucErrCode = 0; - - return ucErrCode; -} -#endif - -void UdsQueueCanOut(void) -{ - //if(Frame_Tx_Complete != false) return; - //if(TP_Tx_Message_DLC) return; - while ((UdsQueueData.In != UdsQueueData.Out)) { - if (UdsQueueData.Out >= CAN0_MAX_RX) { - UdsQueueData.Out = 0; - } - - gUdsBusOffCanOutBak = UdsQueueData.Out; - ParseUdsCan(UdsQueueData.CanMsg[UdsQueueData.Out]); - UdsQueueData.Out++; - ParseCanRxCnt++; - // break; - } - - //return; -} - - -uint8_t GenerateSID27SeedValue(uint8_t *seed) -{ - uint32_t random; - - random *= UdsApi_GetRandom(); - if (random == 0xffffffff) { - random *= 0xaa; - } else if (random == 0) { - random += UdsApi_GetRandom(); - } - seed[0] = (uint8_t)(random >> 0); - seed[1] = (uint8_t)(random >> 16); - seed[2] = (uint8_t)(random >> 8); - seed[3] = (uint8_t)(random >> 0); - return 0; -} - -#if BOOTLOADER_CODE_FLAG - extern void RAMFLASHInit(void); -#endif - -uint8_t GenerateSID27KeyValue(uint8_t levelType,uint8_t *seed,uint8_t *key) -{ - uint8_t i = 0; - - uint8_t cal[4] = {0}; - uint8_t xor_data[4] = {0x90,0x23,0xB0,0x21}; - - if(levelType == 1) { //Level 1 - for (i=0;i<4;i++) - { - cal[i] = seed[i] ^ xor_data[i]; - } - key[0] = ((cal[0]&0x0f)<<4) | (cal[1] & 0xf0); - key[1] = ((cal[1]&0x0f)<<4) | ((cal[2] & 0xf0)>>4); - key[2] = ((cal[2]&0xf0)) | ((cal[3] & 0xf0)>>4); - key[3] = ((cal[3]&0x0f)<<4) | (cal[0] & 0x0f); - } else { //FBL_Level - for (i=0;i<4;i++) - { - cal[i] = seed[i] ^ xor_data[i]; - } - key[0] = ((cal[0] & 0x0f) << 4) | (cal[1] & 0x0f); - key[1] = ((cal[1] & 0xf0) >> 4) | ((cal[2] & 0x0f) << 4); - key[2] = ((cal[2] & 0xf0) >> 4) | ((cal[3] & 0xf0)); - key[3] = ((cal[3] & 0x0f)) | ((cal[0] & 0xf0) >> 4); - } - - return 0; -} - -//extern EReturnMsg bsp_flash_erase_sector(INT32U nFlashAddr); -//extern EReturnMsg bsp_flash_write_buff(INT32U nFlashAddr, INT8U *pBuff, INT32U nLen); -//extern EReturnMsg bsp_flash_read_buff(INT32U nFlashAddr, INT8U *pBuff, INT32U nLen); - -uint8_t EE_Write(uint8_t *pImage, const uint8_t *pData, uint32_t Len, void (*pCbFn)(uint32_t)) -{ - uds_service_nvm_write(pImage, pData, Len, pCbFn); - return TRUE; -} - - -uint8_t EE_Read(uint8_t *pImage, uint8_t **pData) -{ - if (NVM_IMAGE_DTC_ADDR == pImage) { - *pData = (uint8_t *)NVM_IMAGE_DTC_ADDR; - } else if (NVM_IMAGE_DID_ADDR == pImage) { - *pData = (uint8_t *)NVM_IMAGE_DID_ADDR; - } else if (NVM_IMAGE_PARAM_ADDR == pImage) { - *pData = (uint8_t *)NVM_IMAGE_PARAM_ADDR; - } else { - return FALSE; - } - - return TRUE; -} - -void SetUdsUpdataFlag(void) -{ -#if (BOOTLOADER_CODE_FLAG == 0) - SetExternProgrammingRequest(); -#endif - -} - - -bool CheckVechileStatus(void) -{ - bool cbRst = false; - // uint16_t speed = WORD(vehicleInfo2uds.Snapshot.VehSpeedH, vehicleInfo2uds.Snapshot.VehSpeedL); - - // if (speed <= 80) { - // cbRst = true; - // } - cbRst = true; - - return cbRst; -} - -bool CheckIsBatteryLow(void) -{ - bool bRst = false; - - if (vehicleInfo2uds.BattLow) { - bRst = true; - } - - return bRst; -} - -bool CheckIsBatteryHigh(void) -{ - bool bRst = false; - - if (vehicleInfo2uds.BattHigh) { - bRst = true; - } - - return bRst; -} - -bool CheckIsIgnON(void) -{ - bool bRst = false; - - if (vehicleInfo2uds.IgnSts) { - bRst = true; - } - - return bRst; -} - -//bool CheckIsIgnOff2ON(void) -//{ -// bool bRst=false; -// -// if (vehicleInfo2uds.IgnOff2On) { -// bRst = true; -// } -// return bRst; -//} -#if BOOTLOADER_CODE_FLAG == 0 - - -bool CheckIsCanBusoff(void) -{ - bool bRst = false; - - if (vehicleInfo2uds.BusoffCnt) { - bRst = true; - } - - return bRst; -} - -#endif - +#include "uds_config.h" +#include "uds_nvm.h" +#include "BSP_CAN.h" +#include "crc.h" +#if BOOTLOADER_CODE_FLAG == 0 +#include "can.h" +#include "Car_CANIDInfo.h" + +const uint8_t SWFingerPrint[12] __attribute__((at(APP_FlagAddress))) = + {'S','5','0','8','_','D','C','U','2','4','0','1'}; +#else + +#endif + + +//INT32U g_ulRand=0; +DIDs gDIDCache; + + +//uint8_t g_testerprogramdateflag = false; +//uint8_t g_testerserialnubnerflag = false; + +//extern INT8U strMcuAppst[4]; +//extern INT8U strMcuAppDate[4]; +extern INT32U ParseCanRxCnt; +extern uint32_t FBL_AppSize; + + +//_HSCANERROR HsCanError; +uint32_t g_ulCanStatus; + +VehicleInfo2UdsType vehicleInfo2uds; +UdsInfo2VehicleType udsInfo2Vehicle = { + .NcmRxEnable = true, + .NcmTxEnable = true, + .NmcmRxEnable = true, + .NmcmTxEnable = true, + .UdsOffLine = true, +}; + + +uint16_t diagStart_InitTimer = DIAG_START_INIT_TIME; +uint16_t diagStart_Timer = DIAG_START_TIME; +DTC_STRUCT dtcComm; +DTC_StatusType dtcStatusBak; +DTC_Fault_Flags faultInfo; //故障信息 +DTC_Options dtcOptions; +const uint32_t DTC_LIST_TABLE[DTC_ID_NUM] = { + DTC_FOREACH(GENERATE_DTC_VALUE_ARRAY) +}; +uint8_t dtcsnapshotNumberTotal; +uint16_t dtcSnapshotDataBuf[DTC_ID_NUM]; +static uint16_t BMS_CommLossTimer = 0; +static uint16_t VCU_CommLossTimer = 0; + +void UdsDidUpdateVehicle(void) +{ + udsInfo2Vehicle.ChargeTempProtVal = gDIDCache.DID_DCUVariousTempProtectVal[0]; + udsInfo2Vehicle.BoardTempProtVal = gDIDCache.DID_DCUVariousTempProtectVal[1]; + udsInfo2Vehicle.DCVoltProtVal = WORD(gDIDCache.DID_DCVoltProtectVal[0], gDIDCache.DID_DCVoltProtectVal[1]); + udsInfo2Vehicle.InsulDetVoltVal = WORD(gDIDCache.DID_InsulationDectVolt[0], gDIDCache.DID_InsulationDectVolt[1]); +} + +void UdsDtcUpdateVehicle(void) +{ + uint8_t index; + uint8_t num, list[DTC_ID_NUM]; + static DTC_Fault_Flags fflag = {.w = 0}; + + if (fflag.w != faultInfo.w) { + fflag = faultInfo; + num = 0; + for (index = 0; index < DTC_ID_NUM; index++) { + if (dtcComm.DTCStatus.recordData[index].status == ((1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC))) { + list[num++] = index + 1; + } + } + udsInfo2Vehicle.DTCNum = num; + memset(udsInfo2Vehicle.DTCList, 0, DTC_ID_NUM); + memcpy(udsInfo2Vehicle.DTCList, list, num); + } +} + +void DID_SignalInit(void) +{ + uint8_t i; + uint8_t index; + uint16_t size; + uint8_t *cachePtr, *didPtr; + uint8_t *nvmDidPtr; + DIDS_NvmType *dids; + Param_NvmType *param; + + EE_Read(NVM_IMAGE_DID_ADDR, (uint8_t **)&dids); + cachePtr = (uint8_t *)&gDIDCache; + + for (i = 0; i < DID_StoreInFlash_NUM; i++) { + index = GetDIDIndexByID(DIDStoreInFlashId[i]); + + if (index != 0xff) { + didPtr = cachePtr + DIDOffset[index]; + size = DIDStoreInFlashSize[i]; + nvmDidPtr = (uint8_t *)dids + DIDStoreInFlashOffset[i]; + + if (CRC16_DataCheck(nvmDidPtr, size) == 0) { + memcpy(didPtr, nvmDidPtr, size); + } + } + } + UdsDidUpdateVehicle(); + + EE_Read(NVM_IMAGE_PARAM_ADDR, (uint8_t **)¶m); + if (CRC16_DataCheck((uint8_t *)param, sizeof(Param_NvmType)-2) == 0) { + UdsParam.SA_FailureCounter = param->Param.SA_FailureCounter; + UdsService.KeyErrCnt = UdsParam.SA_FailureCounter; + if (UDS_27SERVICE_ERR_NUM_MAX <= UdsService.KeyErrCnt) { + UdsService.KeyErrLockTimer = UDS_27SERVICE_KEY_ERRLOCK_TIME; + UdsService.KeyLockFlg = true; + } + } else { + UdsService.KeyErrLockTimer = 0; + UdsService.KeyLockFlg = false; + UdsService.KeyErrCnt = 0; + } +} + +void DTC_SignalInit(void) +{ +#if BOOTLOADER_CODE_FLAG == 0 + uint8_t index; + uint8_t size; + DTCS_NvmType *dtc, *dtcBak; + + EE_Read(NVM_IMAGE_DTC_ADDR, (uint8_t **)&dtc); + size = sizeof(DTC_RecordDataBufType); + + for (index = 0; index < DTC_ID_NUM; index++) { + if (CRC16_DataCheck((uint8_t *)&dtc->DTC_Status.recordData[index], size - 2) == 0) { + memcpy((uint8_t *)&dtcComm.DTCStatus.recordData[index], (uint8_t *)&dtc->DTC_Status.recordData[index], size); + memcpy((uint8_t *)&dtcStatusBak.recordData[index], (uint8_t *)&dtc->DTC_Status.recordData[index], size); + } + + if (dtcComm.DTCStatus.recordData[index].status == ((1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC))) { + faultInfo.w |= 1 << index; + } + } + // UdsDtcUpdateVehicle(); + // diagStart_InitTimer = DIAG_START_INIT_TIME; + // diagStart_Timer = DIAG_START_TIME; + dtcOptions.w = 0xffffffff; + SnapshotRecordNumberGet(dtcComm.DTCStatus.recordData, dtcSnapshotDataBuf, &dtcsnapshotNumberTotal); +#endif +} + +void UDS_ServiceInit(void) +{ + // //ECU 上电或复位后默认处于闭锁状态,同时错误计数器重置为零。 + // UdsService.KeyErrLockTimer = 0; + // UdsService.KeyLockFlg = false; + // UdsService.KeyErrCnt = 0; + + UdsService.SessionDiagModel = _UDS_DEFAULT_SESSION; + UdsService.SeedKeyIsOK = 0; + UdsService.AlreadSendSeed = false; + UdsService.GenerateSeedReq_Non = false; + UdsService.SessionTimer = 0; + UdsService.NcmDisRxAndTx = 0; + UdsService.NmcmDisRxAndTx = 0; + UdsService.DisDTCRecord = 0; +} + +void DTC_SignalRecover(void) +{ + +} + + +void GenRand(void) +{ + +} + + +#if BOOTLOADER_CODE_FLAG == 0 + +void SnapshotRecordLoad(DTC_RecordDataBufType *record) +{ + record->snapshot = vehicleInfo2uds.Snapshot; +} + +uint8_t SnapshotRecordFill(uint8_t *data, DTC_SnapshotType *snapshot) +{ + uint8_t j = 0; + uint16_t dataId; + + dataId = 0xCF00; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->BatVolt; + dataId = 0xCF01; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->SOCH; + data[j++] = snapshot->SOCL; + dataId = 0xCF02; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->DCInVolH; + data[j++] = snapshot->DCInVolL; + dataId = 0xCF03; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->GunSts; + dataId = 0xCF04; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->DCRealySts; + dataId = 0xCF05; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->ACRealySts; + dataId = 0xCF06; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->CC2ResistorH; + data[j++] = snapshot->CC2ResistorL; + dataId = 0xCF07; + data[j++] = (uint8_t)(dataId >> 8); + data[j++] = (uint8_t)(dataId & 0x00ff); + data[j++] = snapshot->CommSts; + + return j; +} + +void SnapshotRecordNumberGet(DTC_RecordDataBufType *record_data, uint16_t *dataBuf, uint8_t *num) +{ + uint8_t i = 0; + uint8_t k = 0, j = 0; + uint16_t temp; + + *num = 0; + for (i=0; i(uint8_t)dataBuf[k+1]) { + temp = dataBuf[k+1]; + dataBuf[k+1] = dataBuf[k]; + dataBuf[k] = temp; + } + } + } + } +} + +uint8_t DiagDtcReportSnapshotFill(uint8_t sub_func, DTC_RecordDataBufType *record_data, uint8_t *data_buf, uint8_t *length) +{ + uint8_t ii = 0; + uint8_t ret = 1; + uint8_t num = 0, index; + uint32_t dtc_record; + uint16_t *snap_buf = dtcSnapshotDataBuf; + + data_buf[(*length)++] = DIAG_SERVE_READ_DTC|0x40; + data_buf[(*length)++] = sub_func; + + SnapshotRecordNumberGet(record_data, snap_buf, &num); + + for (ii=0; ii>8); + dtc_record = DTC_LIST_TABLE[index]; + data_buf[(*length)++] = (uint8_t)(dtc_record>>16); + data_buf[(*length)++] = (uint8_t)(dtc_record>>8); + data_buf[(*length)++] = (uint8_t)(dtc_record>>0); + data_buf[(*length)++] = record_data[index].snapNumber; + } + return 0; +} + +uint8_t DiagDtcSnapshotRecordFill(uint8_t sub_func, DTC_MaskRecordTpye mask_record, + uint8_t snap_record_num, DTC_RecordDataBufType *record_data, uint8_t *data_buf, uint8_t *length) +{ + uint8_t ii = 0; + uint8_t ret = 1; + + data_buf[(*length)++] = DIAG_SERVE_READ_DTC|0x40; + data_buf[(*length)++] = sub_func; + + for (ii=0; ii= DTC_ID_NUM) { + return; + } + if (dtc_record_data->status != status) { + if (status == ((1<snapNumber) { + (*snapshot_number_total)++; + dtc_record_data->snapNumber = *snapshot_number_total; + } + + if (dtc_record_data->extended.FaultCounter != 0xff) { + dtc_record_data->extended.FaultCounter ++; + } + } + // dtc_record_data->extended.FaultAgingCounter = 0; + } + + dtc_record_data->status = status; +} + + +//电压正且非busoff、电源ON下 +void DiagFaultsMonitor(void) +{ + + // if (CheckIsBatteryHigh())return; + + // if (CheckIsBatteryLow())return; + + // if (CheckIsIgnON()) { + + if (vehicleInfo2uds.InOverVoltFault) { + faultInfo.b.fINPUT_OVERVOLTAGE = 1; + } else { + faultInfo.b.fINPUT_OVERVOLTAGE = 0; + } + + if (vehicleInfo2uds.InUnderVoltFault) { + faultInfo.b.fINPUT_UNDERVOLTAGE = 1; + } else { + faultInfo.b.fINPUT_UNDERVOLTAGE = 0; + } + + if (vehicleInfo2uds.ChargeTempDerateFault) { + faultInfo.b.fCHARGE_TEMP_DERATE = 1; + } else { + faultInfo.b.fCHARGE_TEMP_DERATE = 0; + } + + if (vehicleInfo2uds.InterTempDerateFault) { + faultInfo.b.fINTER_TEMP_DERATE = 1; + } else { + faultInfo.b.fINTER_TEMP_DERATE = 0; + } + + if (vehicleInfo2uds.InterOverTempFault) { + faultInfo.b.fINTER_OVERTEMP = 1; + } else { + faultInfo.b.fINTER_OVERTEMP = 0; + } + + if (vehicleInfo2uds.ChargeOverTempFault) { + faultInfo.b.fCHARGE_OVERTEMP = 1; + } else { + faultInfo.b.fCHARGE_OVERTEMP = 0; + } + + if (vehicleInfo2uds.DcPosRelayAdhFault) { + faultInfo.b.fDC_POS_RELAY_ADH = 1; + } else { + faultInfo.b.fDC_POS_RELAY_ADH = 0; + } + + if (vehicleInfo2uds.DcNegRelayAdhFault) { + faultInfo.b.fDC_NEG_RELAY_ADH = 1; + } else { + faultInfo.b.fDC_NEG_RELAY_ADH = 0; + } + + if (vehicleInfo2uds.AcPosRelayAdhFault) { + faultInfo.b.fAC_POS_RELAY_ADH = 1; + } else { + faultInfo.b.fAC_POS_RELAY_ADH = 0; + } + + if (vehicleInfo2uds.AcNegRelayAdhFault) { + faultInfo.b.fAC_NEG_RELAY_ADH = 1; + } else { + faultInfo.b.fAC_NEG_RELAY_ADH = 0; + } + + if (vehicleInfo2uds.HvInterlockFault) { + faultInfo.b.fHV_INTERLOCK = 1; + } else { + faultInfo.b.fHV_INTERLOCK = 0; + } + + if (vehicleInfo2uds.CcCc2RelayCtrlInv) { + faultInfo.b.fCC_CC2_RELAY_CTRL_INV = 1; + } else { + faultInfo.b.fCC_CC2_RELAY_CTRL_INV = 0; + } + + if (vehicleInfo2uds.CpCc1RelayCtrlInv) { + faultInfo.b.fCP_CC1_RELAY_CTRL_INV = 1; + } else { + faultInfo.b.fCP_CC1_RELAY_CTRL_INV = 0; + } + + if (CheckIsCanBusoff()) { + if (vehicleInfo2uds.BusoffCnt >= 8) + { + faultInfo.b.fECU_ENTER_BUSOFF = 1; + } + } else { + faultInfo.b.fECU_ENTER_BUSOFF = 0; + } + + if (CheckIsCanBusoff() || CheckIsBatteryHigh() || CheckIsBatteryLow()) { + BMS_CommLossTimer = 0; + VCU_CommLossTimer = 0; + return; + } + + // if (diagStart_Timer) { + // diagStart_Timer --; + // if (diagStart_Timer == 0) { + // BMS_CommLossTimer = 0; + // } + // return; + // } else { + if (++BMS_CommLossTimer > 200) { + faultInfo.b.fBMS_COMM_LOSE = 1; + BMS_CommLossTimer = 0; + } + if (++VCU_CommLossTimer > 300) { + faultInfo.b.fVCU_COMM_LOSE = 1; + VCU_CommLossTimer = 0; + } + // } + // } else { + // diagStart_Timer = DIAG_START_TIME; + // } + +} + +void Uds_SetMsgMonitorTimer(uint16_t msgid) +{ +#if BOOTLOADER_CODE_FLAG == 0 + if (!udsInfo2Vehicle.NcmRxEnable) return; + switch (msgid) { + case Bms_104: + faultInfo.b.fBMS_COMM_LOSE = 0; + BMS_CommLossTimer = 0; + break; + case Vcu_state_111: + faultInfo.b.fVCU_COMM_LOSE = 0; + VCU_CommLossTimer = 0; + default: + break; + } +#endif +} + +void ClearMsgMonitorTimer(void) +{ + BMS_CommLossTimer = 0; + VCU_CommLossTimer = 0; +} + +void GetBatteryStatus(void) +{ + if (CheckIsBatteryHigh()) { + faultInfo.b.fECU_VOLTAGE_HIGH = 1; + } else { + faultInfo.b.fECU_VOLTAGE_HIGH = 0; + } + + if (CheckIsBatteryLow()) { + faultInfo.b.fECU_VOLTAGE_LOW = 1; + } else { + faultInfo.b.fECU_VOLTAGE_LOW = 0; + } +} + +#if 0 +void DtcAging_Process(void) +{ + uint8_t index; + DTC_RecordDataBufType *dtc_record_data; + static uint8_t ignStsBak = 1; + + if (ignStsBak != vehicleInfo2uds.IgnSts) { + ignStsBak = vehicleInfo2uds.IgnSts; + + if (vehicleInfo2uds.IgnSts) { + for (index = 0; index < DTC_ID_NUM; index++) { + dtc_record_data = &dtcComm.DTCStatus.recordData[index]; + if (dtc_record_data->status == (1 << DTC_STATUS_Confirmed_DTC)) { + dtc_record_data->extended.FaultAgingCounter++; + if (dtc_record_data->extended.FaultAgingCounter >= 40) { + dtc_record_data->extended.FaultAgingCounter = 0; + dtc_record_data->status = 0; + if (dtc_record_data->extended.FaultCounterOfAge != 0xff) { + dtc_record_data->extended.FaultCounterOfAge++; + } + } + } + } + } + } +} +#endif + +void ClearHardwareFault(void) +{ + UdsApi_HardwareFault_ForceClear(); +} + +void GetFaultInfo(void) +{ + uint8_t shift, status; + uint8_t size; + uint16_t crc16; + DTC_Fault_Flags littleFault; + DTC_RecordDataBufType *pDtcRecordData; + static uint8_t wrIndex = 0; + static uint8_t timer100ms; + + if (diagStart_InitTimer > 0) { //电压正常后才计数 + diagStart_InitTimer --; + + return; + } + GetBatteryStatus(); + + DiagFaultsMonitor(); + + if (UdsService.DisDTCRecord) { + return; + } + + // DtcAging_Process(); + + if (DTC_ID_NUM <= 32) { + //littleFault.w= BigLittleSwap32(faultInfo.w); + littleFault.w = faultInfo.w; + + for (shift = 0; shift < DTC_ID_NUM; shift++) { + + if ((littleFault.w >> shift) & 0x00000001) { + status = (1 << DTC_STATUS_Test_Failed) | (1 << DTC_STATUS_Confirmed_DTC); //当前故障 + } else { + status = dtcComm.DTCStatus.recordData[shift].status & (~(1 << DTC_STATUS_Test_Failed)); + } + + DiagUpdateDtcValue(shift, status); + } + } else { + //超出32个的,需要特殊处理 + } + + size = sizeof(DTC_RecordDataBufType); + pDtcRecordData = &dtcComm.DTCStatus.recordData[wrIndex]; + if (pDtcRecordData->status != dtcStatusBak.recordData[wrIndex].status \ + /*|| pDtcRecordData->extended.FaultAgingCounter != dtcStatusBak.recordData[wrIndex].extended.FaultAgingCounter*/) { + crc16 = CRC_Cal16_WithCfg((uint8_t *)pDtcRecordData, size - 2); + pDtcRecordData->crc16[0] = (uint8_t)crc16; + pDtcRecordData->crc16[1] = (uint8_t)(crc16 >> 8); + + dtcStatusBak.recordData[wrIndex].status = pDtcRecordData->status; + // dtcStatusBak.recordData[wrIndex].extended.FaultAgingCounter = pDtcRecordData->extended.FaultAgingCounter; + EE_Write(NVM_IMAGE_DTC_ADDR + (size * wrIndex), (uint8_t *)pDtcRecordData, size, NULL); + } + wrIndex++; + if (wrIndex >= DTC_ID_NUM) { + wrIndex = 0; + } + + if (++timer100ms >= 10) { + timer100ms = 0; + UdsDtcUpdateVehicle(); + } +} + + +void ClearDtc(void) +{ + uint8_t shift; + uint16_t crc16; + DTC_RecordDataBufType *pDtcRecordData; + + faultInfo.w = 0; + dtcsnapshotNumberTotal = 0; + for (shift = 0; shift < DTC_ID_NUM; shift++) { + pDtcRecordData = &dtcComm.DTCStatus.recordData[shift]; + + memset((uint8_t *)pDtcRecordData, 0x00, sizeof(DTC_RecordDataBufType) - 2); + crc16 = CRC_Cal16_WithCfg((uint8_t *)pDtcRecordData, sizeof(DTC_RecordDataBufType) - 2); + pDtcRecordData->crc16[0] = (uint8_t)crc16; + pDtcRecordData->crc16[1] = (uint8_t)(crc16 >> 8); + } + + memcpy((uint8_t *)&dtcStatusBak, (uint8_t *)&dtcComm.DTCStatus, sizeof(DTC_StatusType)); + EE_Write(NVM_IMAGE_DTC_ADDR, (uint8_t *)&dtcComm.DTCStatus, sizeof(DTC_StatusType), NULL); + ClearHardwareFault(); + ClearMsgMonitorTimer(); +} + + +bool GetDtcStatusMask(uint8_t *pOut, uint8_t *len, uint8_t subFunc, uint8_t mask) +{ + bool retValue = FALSE; + uint8_t ii = 0; + uint8_t j = 0; + + dtcComm.DTCcount.map = 0; + pOut[j++] = DIAG_SERVE_READ_DTC | 0x40; + pOut[j++] = subFunc; + pOut[j++] = DTC_STATUS_Support_Bit_Status; + + for (ii = 0; ii < DTC_ID_NUM; ii++) { + /*if (((dtcComm.DTCStatus[ii]&DTC_STATUS_Support_Bit_Status) == (mask&DTC_STATUS_Support_Bit_Status))\ + ||(subFunc == DTC_ReportSupportedDTCs))*/ + if ((dtcComm.DTCStatus.recordData[ii].status & mask) \ + || (dtcComm.DTCStatus.recordData[ii].status == mask)\ + || (subFunc == DTC_ReportSupportedDTCs)) { + if ((dtcOptions.w >> ii) & 0x00000001) { + retValue = TRUE; + dtcComm.DTCcount.map++; + pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 16); + pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 8); + pOut[j++] = (uint8_t)(DTC_LIST_TABLE[ii] >> 0); + pOut[j++] = dtcComm.DTCStatus.recordData[ii].status; + } + } + } + + *len = j; + return retValue; +} +#endif + +void DiagDIDStoreFlash(uint16_t id) +{ + uint8_t didIndex, nvmDidIndex; + //uint16_t offset; + uint16_t size; + uint8_t *cachePtr, *didPtr, *nvmDidPtr = NULL; + uint16_t crc16; + bool storage_flag = false; + + nvmDidIndex = GetDIDStoreInFlashIndexByID(id); + + if (nvmDidIndex != 0xFF) { + didIndex = GetDIDIndexByID(id); + + if (didIndex != 0xFF) { + size = DIDSize[didIndex]; + cachePtr = (uint8_t *)&gDIDCache; + didPtr = cachePtr + DIDOffset[didIndex]; + crc16 = CRC_Cal16_WithCfg(didPtr, size); + didPtr[size] = (uint8_t)crc16; + size++; + didPtr[size] = (uint8_t)(crc16 >> 8); + size++; + nvmDidPtr = (uint8_t *)NVM_IMAGE_DID_ADDR + DIDStoreInFlashOffset[nvmDidIndex]; + + if (nvmDidPtr != NULL) { + EE_Write(nvmDidPtr, didPtr, size, NULL); + } + UdsDidUpdateVehicle(); + } + } +} + +void CheckDtcHsCanError(void) +{ + static uint16_t Timer100msCnt = 0; +#if BOOTLOADER_CODE_FLAG == 0 + static uint16_t Timer10msCnt = 0; +#endif + uint16_t crc16; + + +#if BOOTLOADER_CODE_FLAG == 0 + + if (++Timer10msCnt >= 10) { + Timer10msCnt = 0; + GetFaultInfo(); + // IgnChangeProcess(); 没有老化 + } + gDIDCache.DID_CurrentDCVolt[0] = MSB(vehicleInfo2uds.CurrDcVolt); + gDIDCache.DID_CurrentDCVolt[1] = LSB(vehicleInfo2uds.CurrDcVolt); + gDIDCache.DID_DCUVariousCurrentTempVal[0] = vehicleInfo2uds.ChargeTemp; + gDIDCache.DID_DCUVariousCurrentTempVal[1] = vehicleInfo2uds.BoardTemp; + +#endif + if (++Timer100msCnt >= 100) { + Timer100msCnt = 0; + + if (UdsParam.SA_FailureCounter != UdsService.KeyErrCnt) { + UdsParam.SA_FailureCounter = UdsService.KeyErrCnt; + crc16 = CRC_Cal16_WithCfg((uint8_t *)&UdsParam, sizeof(UdsParam) - 2); + UdsParam.crc16[0] = (uint8_t)crc16; + UdsParam.crc16[1] = (uint8_t)(crc16 >> 8); + EE_Write(NVM_IMAGE_PARAM_ADDR, (uint8_t*)&UdsParam, sizeof(UdsParam), NULL); + } + } + + if ((UdsService.UdsTxFlg == true) && (UdsService.UdsTxCompFlg == true)) { + UdsService.UdsTxFlg = false; + UdsService.UdsTxCompFlg = false; + HAL_UDS_Tx_Callback(); + //UdsQueueCanOut(); + UdsService.TxCompFlg = true; + //Debug("HAL_UDS_Tx_Callback \r\n"); // + } +} + +#if BOOTLOADER_CODE_FLAG == 0 +INT8U Get0x19SerDiagData(INT8U *pOut, INT8U Type, INT8U *pdata) +{ + INT8U RstLen = 0; +// INT16U i=0; +// INT32U dtc_code = 0; +// INT8U num = 0; + uint8_t dtcReportSubFunction; + uint8_t dtcRecordNumber; + uint8_t dtcStatusMask; + DTC_MaskRecordTpye dtcMaskRecord; + + dtcReportSubFunction = Type; + dtcStatusMask = pdata[1]; + + switch (dtcReportSubFunction) { + case DTC_ReportNumberOfDTCByStatusMask: + case DTC_ReportDTCByStatusMask: + case DTC_ReportSupportedDTCs: + if (GetDtcStatusMask(pOut, &RstLen, dtcReportSubFunction, dtcStatusMask) == FALSE) { + RstLen = 0; + pOut[RstLen++] = DIAG_SERVE_READ_DTC | 0x40; //0x59; + pOut[RstLen++] = dtcReportSubFunction; + pOut[RstLen++] = DTC_STATUS_Support_Bit_Status; + } + + if (dtcReportSubFunction == DTC_ReportNumberOfDTCByStatusMask) { + RstLen = 0; + pOut[RstLen++] = DIAG_SERVE_READ_DTC|0x40;//0x59; + pOut[RstLen++] = dtcReportSubFunction; + pOut[RstLen++] = DTC_STATUS_Support_Bit_Status; + pOut[RstLen++] = ISO15031_6_DTCformat; + pOut[RstLen++] = dtcComm.DTCcount.b.DTCcountHighByte; + pOut[RstLen++] = dtcComm.DTCcount.b.DTCcountLowByte; + } + + break; + case DTC_ReportDTCSnapshotIdentification: + DiagDtcReportSnapshotFill(dtcReportSubFunction, dtcComm.DTCStatus.recordData, pOut, &RstLen); + break; + case DTC_ReportDTCSnapshotRecordByDTCNumber: + dtcMaskRecord.DTCHightByte = pdata[1]; + dtcMaskRecord.DTCMiddleByte = pdata[2]; + dtcMaskRecord.DTCLowByte = pdata[3]; + dtcRecordNumber = pdata[4]; + if (DiagDtcSnapshotRecordFill(dtcReportSubFunction, dtcMaskRecord, dtcRecordNumber, + dtcComm.DTCStatus.recordData, pOut, &RstLen) != 0) { + RstLen = 0; + } + break; + case DTC_ReportDTCExtendedDataRecordByDTCNumber: + dtcMaskRecord.DTCHightByte = pdata[1]; + dtcMaskRecord.DTCMiddleByte = pdata[2]; + dtcMaskRecord.DTCLowByte = pdata[3]; + dtcRecordNumber = pdata[4]; + if (DiagDtcExtendedDataRecordFill(dtcReportSubFunction, dtcMaskRecord, dtcRecordNumber, + dtcComm.DTCStatus.recordData, pOut, &RstLen) != 0) { + RstLen = 0; + } + break; + default: + break; + } + + return RstLen; +} +#endif + + + +INT16U Get0x22SerDiagData(INT8U *pOut) +{ + INT16U RstLen = 0; + INT16U ReqId = 0; +// INT16U length = 0; + uint8_t i; + uint8_t *cachePtr; + uint8_t size; + + ReqId = ((UdsService.ReqCmdBuf[0] << 8) + UdsService.ReqCmdBuf[1]); + + pOut[RstLen++] = 0x62; + pOut[RstLen++] = ((ReqId >> 8) & 0xFF); + pOut[RstLen++] = (ReqId & 0xFF); + + cachePtr = (uint8_t *)&gDIDCache; + + for (i = 0; i < DID_NUM; i++) { + if (ReqId == DIDId[i]) { + break; + } + } + + if (i == DID_NUM) { + RstLen = 2; + } else { +#if BOOTLOADER_CODE_FLAG + + if (!CheckIsSupportBootloaderRead_Sid22(ReqId)) { + RstLen = 2; + } + +#endif + } + + if (RstLen != 2) { + size = DIDSize[i]; + + memcpy(&pOut[RstLen], (cachePtr + DIDOffset[i]), size); + RstLen += size; + } + + return RstLen; +} + +#if BOOTLOADER_CODE_FLAG + +INT8U Set0x36DiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) +{ + uint8_t /*i=0,*/ucErrCode = 0; + uint8_t sn = 0; + + + sn = pIn[0]; + UdsUpData.totalRecvLength += (UdsService.RxDlc - 2); + + if (CheckIsBatteryHigh()) { + ucErrCode = 0x92; + } else if (CheckIsBatteryLow()) { + ucErrCode = 0x93; + } else if (UdsService.RxDlc > (FMC_PAGE_SIZE + 2)) { + ucErrCode = 0x13; + } else if ((UdsUpData.DownloadSeq != DOWNLOAD_SEQUENCE_34) && (UdsUpData.DownloadSeq != DOWNLOAD_SEQUENCE_36)) { + ucErrCode = 0x24; + } else if (sn != UdsUpData.Sn) { + ucErrCode = 0x73; + } else if (UdsUpData.totalRecvLength > FBL_AppSize) { + ucErrCode = 0x71; + } else { + UdsUpData.RxProgramFlag = true; + UdsUpData.DownloadSeq = DOWNLOAD_SEQUENCE_36; + memcpy(UdsUpData.Buf, &TP_Buffer[2], (UdsService.RxDlc - 2)); + ucErrCode = 0x78; + } + + return ucErrCode; + +} +#endif + +INT8U Set0x31DiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) +{ + + uint8_t service_buf[50]; + uint8_t /*i=0,*/ucErrCode = 0, ucRsp = 0; + uint16_t ReqId = 0; + uint16_t dlen = 0; + uint8_t result = 0; + + if (UdsService.RxDlc < 4) { + return 0x13; + } + + ucRsp = pIn[0]; + ReqId = pIn[1] << 8 | pIn[2]; + + service_buf[dlen++] = 0x71; + service_buf[dlen++] = pIn[0]; + service_buf[dlen++] = pIn[1]; + service_buf[dlen++] = pIn[2]; + +#if BOOTLOADER_CODE_FLAG == 0 + + static bool routineStartFlg = false; + if(0x01 == ucRsp) { + ReqId = pIn[1]<<8 | pIn[2]; + if((true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0203))\ + ||(true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0204)) + ||(true == CheckUdsDlcIsOk(UdsService.RxDlc,5) && (ReqId == 0x0207))) { + if (UdsService.SeedKeyIsOK) { + if (true == CheckVechileStatus()) { + switch (ReqId) { + case 0x0204: + result = 0x00; //correctResult + service_buf[dlen++] = result; + break; + case 0x0207: + if (pIn[3] <= 1) { + result = 0x00; //correctResult + udsInfo2Vehicle.DCDCEnable = pIn[3]; + } else { + result = 0x01; //incorrectResult + } + service_buf[dlen++] = result; + + break; + case 0x0203: + // if (UdsService.BattErrFlg == false) { + UdsService.ChkProgPreconditionFlg = true; + UdsService.ProgrammingPassTimer = PROGRAMMING_PASS_TIMEOUT_TIME; + // } + result = 0x00; //correctResult + service_buf[dlen++] = result; + break; + default: + break; + } + } else { + ucErrCode = 0x22; + } + if (!ucErrCode) { + routineStartFlg = true; + } + } else { + ucErrCode = 0x33; + } + } else if ((ReqId == 0x0203) || (ReqId == 0x0204) || (ReqId == 0x0207)) { + ucErrCode = 0x13; + } else { + ucErrCode = 0x31; + } + } else if(0x03 == ucRsp) { + ReqId = pIn[1]<<8 | pIn[2]; + if ((true == CheckUdsDlcIsOk(UdsService.RxDlc,4) && (ReqId == 0x0204))) { + if (UdsService.SeedKeyIsOK) { + if (true == CheckVechileStatus()) { + if (true == routineStartFlg) { + routineStartFlg = false; + switch (ReqId) { + case 0x0204: + result = vehicleInfo2uds.OtaModeSts; + service_buf[dlen++] = result; + break; + default: + break; + } + } else { + ucErrCode = 0x24; + } + } else { + ucErrCode = 0x22; + } + } else { + ucErrCode = 0x33; + } + } else if ((ReqId == 0x0204)) { + ucErrCode = 0x13; + } else { + ucErrCode = 0x31; + } + } else if (0x02 == ucRsp) { + if ((true == CheckUdsDlcIsOk(UdsService.RxDlc, 4) && (ReqId == 0x0204))) { + if (UdsService.SeedKeyIsOK) { + switch (ReqId) { + case 0x0204: + result = 0x00; //correctResult + service_buf[dlen++] = result; + break; + default: + break; + } + } else { + ucErrCode = 0x33; + } + } else if ((ReqId == 0x0204)) { + ucErrCode = 0x13; + } else { + ucErrCode = 0x31; + } + } else { + if (true == UdsService.PhyFlg) { + UdsService.PhyFlg = false; + ucErrCode = 0x12; + } + } + +#endif + *RLen = dlen; + + if (ucErrCode == 0) { + memcpy(pOut, service_buf, dlen); + } + + return ucErrCode; + +} + +INT8U Set0x2EDidDiagData(INT8U *pIn, INT16U PLen) +{ + INT8U Rst = 0; + INT16U ReqId = 0; + + ReqId = ((pIn[0] << 8) + pIn[1]); + +#if BOOTLOADER_CODE_FLAG == 0 + if (ReqId == DIDId[VehicleIdentificationNumber]) { + if(PLen == DIDSize[VehicleIdentificationNumber]) { + if (UdsService.SeedKeyIsOK) { + if (CheckVechileStatus()) { + memcpy(gDIDCache.DID_VehicleIdentificationNumber,&pIn[2],PLen); + } else { + Rst = 0x22; + } + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else if (ReqId == DIDId[EOLData]) { + if(PLen == DIDSize[EOLData]) { + if (UdsService.SeedKeyIsOK) { + if (CheckVechileStatus()) { + memcpy(gDIDCache.DID_EOLData,&pIn[2],PLen); + } else { + Rst = 0x22; + } + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else if (ReqId == DIDId[DCUVariousTempProtectVal]) { + if(PLen == DIDSize[DCUVariousTempProtectVal]) { + if (UdsService.SeedKeyIsOK) { + if (CheckVechileStatus()) { + memcpy(gDIDCache.DID_DCUVariousTempProtectVal,&pIn[2],PLen); + } else { + Rst = 0x22; + } + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else if (ReqId == DIDId[DCVoltProtectVal]) { + if(PLen == DIDSize[DCVoltProtectVal]) { + if (UdsService.SeedKeyIsOK) { + if (CheckVechileStatus()) { + memcpy(gDIDCache.DID_DCVoltProtectVal,&pIn[2],PLen); + } else { + Rst = 0x22; + } + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else if (ReqId == DIDId[InsulationDectVolt]) { + if(PLen == DIDSize[InsulationDectVolt]) { + if (UdsService.SeedKeyIsOK) { + if (CheckVechileStatus()) { + memcpy(gDIDCache.DID_InsulationDectVolt,&pIn[2],PLen); + } else { + Rst = 0x22; + } + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else { + Rst = 0x31; + } + +#else + if (ReqId == DIDId[FingerPrint]) { + if(PLen == DIDSize[FingerPrint]) { + if (UdsService.SeedKeyIsOK) { + memcpy(gDIDCache.DID_FingerPrint,&pIn[2],PLen); + } else { + Rst = 0x33; + } + } else { + Rst = 0x13; + } + } else { + Rst = 0x31; + } + +#endif + + if (Rst == 0) { + DiagDIDStoreFlash(ReqId); + } + + return Rst; +} + +#if BOOTLOADER_CODE_FLAG == 0 +INT8U Set0x2FDiagData(INT8U *pIn, INT16U PLen, INT8U *pOut, INT16U *RLen) +{ + INT8U ucErrCode = 0; + + return ucErrCode; +} +#endif + +void UdsQueueCanOut(void) +{ + //if(Frame_Tx_Complete != false) return; + //if(TP_Tx_Message_DLC) return; + while ((UdsQueueData.In != UdsQueueData.Out)) { + if (UdsQueueData.Out >= CAN0_MAX_RX) { + UdsQueueData.Out = 0; + } + + gUdsBusOffCanOutBak = UdsQueueData.Out; + ParseUdsCan(UdsQueueData.CanMsg[UdsQueueData.Out]); + UdsQueueData.Out++; + ParseCanRxCnt++; + // break; + } + + //return; +} + + +uint8_t GenerateSID27SeedValue(uint8_t *seed) +{ + uint32_t random; + + random *= UdsApi_GetRandom(); + if (random == 0xffffffff) { + random *= 0xaa; + } else if (random == 0) { + random += UdsApi_GetRandom(); + } + seed[0] = (uint8_t)(random >> 0); + seed[1] = (uint8_t)(random >> 16); + seed[2] = (uint8_t)(random >> 8); + seed[3] = (uint8_t)(random >> 0); + return 0; +} + +#if BOOTLOADER_CODE_FLAG + extern void RAMFLASHInit(void); +#endif + +uint8_t GenerateSID27KeyValue(uint8_t levelType,uint8_t *seed,uint8_t *key) +{ + uint8_t i = 0; + + uint8_t cal[4] = {0}; + uint8_t xor_data[4] = {0x90,0x23,0xB0,0x21}; + + if(levelType == 1) { //Level 1 + for (i=0;i<4;i++) + { + cal[i] = seed[i] ^ xor_data[i]; + } + key[0] = ((cal[0]&0x0f)<<4) | (cal[1] & 0xf0); + key[1] = ((cal[1]&0x0f)<<4) | ((cal[2] & 0xf0)>>4); + key[2] = ((cal[2]&0xf0)) | ((cal[3] & 0xf0)>>4); + key[3] = ((cal[3]&0x0f)<<4) | (cal[0] & 0x0f); + } else { //FBL_Level + for (i=0;i<4;i++) + { + cal[i] = seed[i] ^ xor_data[i]; + } + key[0] = ((cal[0] & 0x0f) << 4) | (cal[1] & 0x0f); + key[1] = ((cal[1] & 0xf0) >> 4) | ((cal[2] & 0x0f) << 4); + key[2] = ((cal[2] & 0xf0) >> 4) | ((cal[3] & 0xf0)); + key[3] = ((cal[3] & 0x0f)) | ((cal[0] & 0xf0) >> 4); + } + + return 0; +} + +//extern EReturnMsg bsp_flash_erase_sector(INT32U nFlashAddr); +//extern EReturnMsg bsp_flash_write_buff(INT32U nFlashAddr, INT8U *pBuff, INT32U nLen); +//extern EReturnMsg bsp_flash_read_buff(INT32U nFlashAddr, INT8U *pBuff, INT32U nLen); + +uint8_t EE_Write(uint8_t *pImage, const uint8_t *pData, uint32_t Len, void (*pCbFn)(uint32_t)) +{ + uds_service_nvm_write(pImage, pData, Len, pCbFn); + return TRUE; +} + + +uint8_t EE_Read(uint8_t *pImage, uint8_t **pData) +{ + if (NVM_IMAGE_DTC_ADDR == pImage) { + *pData = (uint8_t *)NVM_IMAGE_DTC_ADDR; + } else if (NVM_IMAGE_DID_ADDR == pImage) { + *pData = (uint8_t *)NVM_IMAGE_DID_ADDR; + } else if (NVM_IMAGE_PARAM_ADDR == pImage) { + *pData = (uint8_t *)NVM_IMAGE_PARAM_ADDR; + } else { + return FALSE; + } + + return TRUE; +} + +void SetUdsUpdataFlag(void) +{ +#if (BOOTLOADER_CODE_FLAG == 0) + SetExternProgrammingRequest(); +#endif + +} + + +bool CheckVechileStatus(void) +{ + bool cbRst = false; + // uint16_t speed = WORD(vehicleInfo2uds.Snapshot.VehSpeedH, vehicleInfo2uds.Snapshot.VehSpeedL); + + // if (speed <= 80) { + // cbRst = true; + // } + cbRst = true; + + return cbRst; +} + +bool CheckIsBatteryLow(void) +{ + bool bRst = false; + + if (vehicleInfo2uds.BattLow) { + bRst = true; + } + + return bRst; +} + +bool CheckIsBatteryHigh(void) +{ + bool bRst = false; + + if (vehicleInfo2uds.BattHigh) { + bRst = true; + } + + return bRst; +} + +bool CheckIsIgnON(void) +{ + bool bRst = false; + + if (vehicleInfo2uds.IgnSts) { + bRst = true; + } + + return bRst; +} + +//bool CheckIsIgnOff2ON(void) +//{ +// bool bRst=false; +// +// if (vehicleInfo2uds.IgnOff2On) { +// bRst = true; +// } +// return bRst; +//} +#if BOOTLOADER_CODE_FLAG == 0 + + +bool CheckIsCanBusoff(void) +{ + bool bRst = false; + + if (vehicleInfo2uds.BusoffCnt) { + bRst = true; + } + + return bRst; +} + +#endif + diff --git a/UDS/uds_api.c b/UDS/uds_api.c index 953d98924703faf44d7b6ae00021c7c146ab8afd..4a3c480018023284dcc20c18a5ce10de9f05241e 100644 GIT binary patch literal 11312 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 literal 16384 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 diff --git a/UDS/uds_dtc.h b/UDS/uds_dtc.h index 7d1f7542ac5d352e2f7d3fadec04b705a31d2193..0c3c0109048783902bb64e2ac740d46530a6be1b 100644 GIT binary patch literal 4719 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