// // Created by cfif on 23.01.2026. // #include "DiagnosticTask.h" #include "CmsisRtosThreadUtils.h" #include "StatusData.h" #include "StatusError.h" #include "HVAC_model.h" #include "SystemDelayInterface.h" #define LOG_SIGN "DIAGNOSTIC" #define LOGGER env->logger void Diagnostic_Init(tDiagnostic *env, tLoggerInterface *logger) { env->logger = logger; env->access = osMutexNew(NULL); // for (uint8_t i = 0; i < COUNT_DTC_CODE_ERROR; ++i) { // Тест DTC не был выполнен в текущем цикле работы // dtc_state_error[i] = UDS_dtc_mask_testNotCompletedThisOperationCycle; // } // InitThreadAtrStatic(&env->thread.attr, "Diagnostic", env->thread.controlBlock, env->thread.stack, // osPriorityNormal); } uint32_t diagnostic_ClearDiagnosticInformation_14(tDiagnostic *env) { if (osMutexAcquire(env->access, 5000) == osOK) { // for (uint8_t i = 0; i < COUNT_DTC_CODE_ERROR; ++i) { // Тест DTC не был выполнен с момента последней очистки // dtc_state_error[i] |= UDS_dtc_mask_testNotCompletedSinceLastClear; // dtc_state_FIX_error[i] |= UDS_dtc_mask_testNotCompletedSinceLastClear; // } osMutexRelease(env->access); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Access error diagnostic_ClearDiagnosticInformation_14"); } return 0; } uint32_t diagnostic_UDS_ReadDTCInformation_19_count(tDiagnostic *env, tDiagnosticDTC *diagnosticDTC) { uint32_t countDTC = 0; if (osMutexAcquire(env->access, 5000) == osOK) { for (uint8_t i = 0; i < COUNT_DTC_CODE_ERROR; ++i) { if (env->isNoBitsDTC) { if (dtc_state_FIX_error[i] & (diagnosticDTC->mask)) { ++countDTC; } } else { if (dtc_state_error[i] & (diagnosticDTC->mask)) { ++countDTC; } } } osMutexRelease(env->access); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Access error diagnostic_ClearDiagnosticInformation_14"); } return countDTC; } uint32_t diagnostic_UDS_ReadDTCInformation_19_dtc(tDiagnostic *env, tDiagnosticDTC *diagnosticDTC) { uint32_t size = 0; if (osMutexAcquire(env->access, 5000) == osOK) { for (uint8_t i = 0; i < COUNT_DTC_CODE_ERROR; ++i) { if (env->isNoBitsDTC) { if (dtc_state_FIX_error[i] & (diagnosticDTC->mask)) { diagnosticDTC->dataResponse[size] = dtc_codes[i].DTCHighByte; diagnosticDTC->dataResponse[size + 1] = dtc_codes[i].DTCMiddleByte; diagnosticDTC->dataResponse[size + 2] = dtc_codes[i].DTCLowByte; diagnosticDTC->dataResponse[size + 3] = dtc_state_error[i] & (diagnosticDTC->mask); size += 4; } } else { if (dtc_state_error[i] & (diagnosticDTC->mask)) { diagnosticDTC->dataResponse[size] = dtc_codes[i].DTCHighByte; diagnosticDTC->dataResponse[size + 1] = dtc_codes[i].DTCMiddleByte; diagnosticDTC->dataResponse[size + 2] = dtc_codes[i].DTCLowByte; diagnosticDTC->dataResponse[size + 3] = dtc_state_error[i] & (diagnosticDTC->mask); size += 4; } } } osMutexRelease(env->access); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Access error diagnostic_UDS_ReadDTCInformation_19_dtc"); } return size; } uint32_t diagnostic_UDS_ReadDTCSupportDTC_19_dtc(tDiagnostic *env, tDiagnosticDTC *diagnosticDTC) { uint32_t size = 0; if (osMutexAcquire(env->access, 5000) == osOK) { for (uint8_t i = 0; i < COUNT_DTC_CODE_ERROR; ++i) { diagnosticDTC->dataResponse[size] = dtc_codes[i].DTCHighByte; diagnosticDTC->dataResponse[size + 1] = dtc_codes[i].DTCMiddleByte; diagnosticDTC->dataResponse[size + 2] = dtc_codes[i].DTCLowByte; diagnosticDTC->dataResponse[size + 3] = 0; size += 4; } osMutexRelease(env->access); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Access error diagnostic_UDS_ReadDTCSupportDTC_19_dtc"); } return size; } void set_NoBitsDTC(tDiagnostic *env, bool noBitsDTC) { if (osMutexAcquire(env->access, 5000) == osOK) { env->isNoBitsDTC = noBitsDTC; memcpy(dtc_state_FIX_error, dtc_state_error, sizeof(dtc_state_error)); osMutexRelease(env->access); } else { LoggerInfoStatic(LOGGER, LOG_SIGN, "Access error setBitsDTC"); } } static bool isVINError(char *VIN) { if (VIN == NULL) { return false; // NULL — не ошибка (ещё нет данных) } // Пустой VIN (нули) — ещё не собран → НЕ ошибка if (memcmp(VIN, "00000000000000000", 17) == 0) { return false; // НЕ ошибка! } // Проверка на совпадение с эталоном if (memcmp(VIN, statusData.ecu.Vehicle_Identification, 17) == 0) { return false; // Валидный - не ошибка } // VIN собран, но не совпадает с эталоном - ОШИБКА return true; } void set_Dtc_state(tDiagnostic *env, CCU_Errors_t *CCU_Errors, uint8_t *dtc_state_error_model, char *VIN) { if (osMutexAcquire(env->access, 5000) == osOK) { bool vin_timeout = ccu_candb_error_rx.VEH_VIN; bool vin_error = isVINError(VIN); // DTC = 1 только если: // - VIN собран, но невалидный // - ИЛИ таймаут (сообщение VIN вообще не приходит) if (vin_error || vin_timeout) { dtc_state_error_model[DTC_VIN_INVALID_CONFIG] = 1; CCU_Errors->CCU_VinRecordErr_Stat = 1; } else { dtc_state_error_model[DTC_VIN_INVALID_CONFIG] = 0; CCU_Errors->CCU_VinRecordErr_Stat = 0; } memcpy(dtc_state_error, dtc_state_error_model, sizeof(dtc_state_error)); osMutexRelease(env->access); } else { LoggerErrorStatic(LOGGER, LOG_SIGN, "Access error set_Dtc_state_error"); } }