/* * Module_ChargerSelfTest.c * * Created on: 2021年9月24日 * Author: 7978 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /*標準輸入輸出定義*/ #include /*標準函數庫定義*/ #include /*Unix 標準函數定義*/ #include /*檔控制定義*/ #include /*PPSIX 終端控制定義*/ #include /*錯誤號定義*/ #include #include #include #include #include #include #include #include "../../define.h" #include "Module_ChargerSelfTest.h" #include "Config.h" #include "Common.h" #define SELFTEST_TIMEOUT 60 // unit: 1s #define VERSION_RETRY_TIMEOUT 180 // unit: 1s #define CABINET_ROLE_TIMEOUT 3 // unit: 1s #define PSU_SELF_TIMEOUT 60 // unit: 1s #define PSU_RETRY_TIMEOUT 60 // unit: 1s #define MAX_PSU_RETRY_CNT 3 #define EMG_BTN_INTERVAL 1 // unit: 1s struct SysConfigAndInfo *ShmSysConfigAndInfo; struct StatusCodeData *ShmStatusCodeData; struct PsuData *ShmPsuData; struct PrimaryMcuData *ShmPrimaryMcuData; struct FanModuleData *ShmFanModuleData; struct RelayModuleData *ShmRelayModuleData[2]; struct LedModuleData *ShmLedModuleData; ChargerInfoData *ShmChargerInfo; PsuGroupCollectionData *ShmGroupCollection; struct OCPP16Data *ShmOCPP16Data; struct OCPP20Data *ShmOCPP20Data; int InitShareMemory(void) { int result = PASS; int MeterSMId; //creat ShmSysConfigAndInfo if ((MeterSMId = shmget(ShmSysConfigAndInfoKey, sizeof(struct SysConfigAndInfo), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmSysConfigAndInfo NG"); #endif result = FAIL; } else if ((ShmSysConfigAndInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmSysConfigAndInfo NG"); #endif result = FAIL; } else { } // initial status code share memory if ((MeterSMId = shmget(ShmStatusCodeKey, sizeof(struct StatusCodeData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmget ShmStatusCodeData NG"); #endif return 0; } else if ((ShmStatusCodeData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("[main]CreatShareMemory:shmat ShmStatusCodeData NG"); #endif return 0; } // initial psu share memory if ((MeterSMId = shmget(ShmPsuKey, sizeof(struct PsuData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmPsuData NG"); #endif result = FAIL; } else if ((ShmPsuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmPsuData NG"); #endif result = FAIL; } // initial DO360 RC1 share memory if ((MeterSMId = shmget(ShmRelayBdKey, sizeof(struct RelayModuleData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmRelayModuleData NG"); #endif result = FAIL; } else if ((ShmRelayModuleData[0] = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmRelayModuleData NG"); #endif result = FAIL; } // initial DO360 RC2 share memory if ((MeterSMId = shmget(ShmRelay2BdKey, sizeof(struct RelayModuleData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmRelay2ModuleData NG"); #endif result = FAIL; } else if ((ShmRelayModuleData[1] = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmRelay2ModuleData NG"); #endif result = FAIL; } // initial fan board share memory if ((MeterSMId = shmget(ShmFanBdKey, sizeof(struct FanModuleData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmFanModuleData NG"); #endif result = FAIL; } else if ((ShmFanModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmFanModuleData NG"); #endif result = FAIL; } // initial led board share memory if ((MeterSMId = shmget(ShmLedBdKey, sizeof(struct LedModuleData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmLedModuleData NG"); #endif result = FAIL; } else if ((ShmLedModuleData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmLedModuleData NG"); #endif result = FAIL; } // initial primary share memory if ((MeterSMId = shmget(ShmPrimaryMcuKey, sizeof(struct PrimaryMcuData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmget ShmPrimaryMcuData NG"); #endif result = FAIL; } else if ((ShmPrimaryMcuData = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmPrimaryMcuData NG"); #endif result = FAIL; } if ((MeterSMId = shmget(SM_ChargerInfoKey, sizeof(ChargerInfoData), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmat ChargerInfoData NG"); #endif result = FAIL; } else if ((ShmChargerInfo = shmat(MeterSMId, NULL, 0)) == (void *) -1) { #ifdef SystemLogMessage LOG_ERROR("shmat ChargerInfoData NG"); #endif result = FAIL; } if ((MeterSMId = shmget(ShmOcppModuleKey, sizeof(struct OCPP16Data), 0777)) < 0) { #ifdef SystemLogMessage LOG_ERROR("shmat ShmOCPP16Data NG"); #endif result = FAIL; } else if ((ShmOCPP16Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { LOG_ERROR("shmat ShmOCPP16Data NG"); result = FAIL; } if ((MeterSMId = shmget(ShmOcpp20ModuleKey, sizeof(struct OCPP20Data), 0777)) < 0) { LOG_ERROR("[main]CreatShareMemory:shmget OCPP20Data NG\n"); result = FAIL; } else if ((ShmOCPP20Data = shmat(MeterSMId, NULL, 0)) == (void *) -1) { LOG_ERROR("[main]CreatShareMemory:shmat OCPP20Data NG\n"); result = FAIL; } if(result == PASS) { ShmGroupCollection = &ShmChargerInfo->PsuGrouping.GroupCollection[0]; } return result; } void SetSelfTestSate(unsigned char selfTest) { if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE || selfTest == _STEST_FAIL) { ShmSysConfigAndInfo->SysInfo.SelfTestSeq = selfTest; } ShmChargerInfo->Control.SelfTestStep = selfTest; } int main(void) { if(InitShareMemory() == FAIL) { #ifdef SystemLogMessage LOG_ERROR("InitShareMemory NG"); #endif sleep(5); return 0; } bool _selfTestTimeout = false, _versionCheck = false, _switchCheck = false, _emgBtn = false; char _selfTest = 0, _preTest = -1, psuRetryCnt = 0; struct timespec _SelfTest_time, _TestStep_time; LOG_INFO("Charger Start Self Test..."); ShmChargerInfo->Control.SysCtrl.bits.NeedSelfTest = YES; GetClockTime(&_SelfTest_time); ShmChargerInfo->Control.SelfTestStep = ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_FAIL ? ShmSysConfigAndInfo->SysInfo.SelfTestSeq : _STEST_VERSION; while(1) { if(!ShmChargerInfo->Control.SysCtrl.bits.NeedSelfTest) { sleep(1); continue; } if(!_selfTestTimeout && ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { if(ShmSysConfigAndInfo->SysInfo.FirmwareUpdate == YES || ShmOCPP16Data->MsMsg.bits.UpdateFirmwareReq == YES) { _selfTestTimeout = true; LOG_INFO("Charger need firmware upgrade, stop self test!"); } else if(ShmPrimaryMcuData->InputDet.bits.EmergencyButton == ABNORMAL) { _selfTestTimeout = true; _emgBtn = true; LOG_INFO("Emergency button is pressed, stop self test!"); } } if(ShmChargerInfo->Control.TestCtrl.bits.ChargingSimulation) { if(ShmSysConfigAndInfo->SysInfo.SelfTestSeq != _STEST_COMPLETE) { ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_COMPLETE; ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; for(int i = 0; i < CONNECTOR_QUANTITY; i++) { ShmChargerInfo->Control.GunAvailable[i] = YES; } LOG_INFO("Self Test Pass In Simulation Mode!"); } sleep(1); continue; } _selfTest = ShmChargerInfo->Control.SelfTestStep; switch(_selfTest) { case _STEST_VERSION: if(_preTest != _selfTest) { GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [VersionTest]"); } if ((ShmChargerInfo->Control.SysCtrl.bits.FanBoardDisable || ShmFanModuleData->SelfTest_Comp) && (ShmChargerInfo->Control.SysCtrl.bits.RelayBoardDisable || ShmRelayModuleData[0]->SelfTest_Comp) && (ShmChargerInfo->Control.SysCtrl.bits.RelayBoardDisable || ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable == false || ShmRelayModuleData[1]->SelfTest_Comp) && ShmPrimaryMcuData->SelfTest_Comp) { _versionCheck = true; if(!_switchCheck) { SetSelfTestSate(_STEST_CabinetSwitch); LOG_INFO("Self test version check ok"); } else { // bypass cabinet switch detection SetSelfTestSate(_STEST_FAIL); LOG_INFO("VersionTest OK, Soft Reset And Retry!"); } } else { if(_selfTestTimeout) { if(_switchCheck) { // self test timeout, set status code for timeout reason if(!ShmChargerInfo->Control.SysCtrl.bits.FanBoardDisable && !ShmFanModuleData->SelfTest_Comp) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FanboardStestFail == NO) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.FanboardStestFail = YES; LOG_INFO("FanBoard Self Test Fail!"); } } if((!ShmChargerInfo->Control.SysCtrl.bits.RelayBoardDisable && !ShmRelayModuleData[0]->SelfTest_Comp) || (!ShmChargerInfo->Control.SysCtrl.bits.RelayBoardDisable && ShmChargerInfo->Control.SysCtrl.bits.SecondRelayBoardEnable && !ShmRelayModuleData[1]->SelfTest_Comp)) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RelayboardStestFail == NO) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.RelayboardStestFail = YES; LOG_INFO("RelayBoard Self Test Fail!"); } } if(!ShmPrimaryMcuData->SelfTest_Comp) { if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail == NO) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PrimaryStestFail = YES; LOG_INFO("Primary Self Test Fail!"); } } if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { LOG_INFO("Booting Completed, Version Self Test Fail!"); } ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL; ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= VERSION_RETRY_TIMEOUT) { // bypass cabinet switch detection SetSelfTestSate(_STEST_FAIL); LOG_INFO("Version check still timeout, try soft reset and retry!"); } } else { SetSelfTestSate(_STEST_CabinetSwitch); LOG_INFO("Version Self Test Timeout, Need Check Cabinet Switch Value"); } } } break; case _STEST_CabinetSwitch: if(_preTest != _selfTest) { ShmChargerInfo->Control.PrimaryCtrl.bits.CabinetSwitchDetect = YES; GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [SwitchDetect]"); } if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= CABINET_ROLE_TIMEOUT) { _switchCheck = true; char *str_cabinet_role[] = {STR_CABINET_ROLE_NONE, STR_CABINET_ROLE_MASTER, STR_CABINET_ROLE_SLAVE}; ShmChargerInfo->Control.CabinetRole = ShmChargerInfo->Control.CabinetSwitch <= _CROLE_SLAVE ? ShmChargerInfo->Control.CabinetSwitch : _CROLE_SINGLE; //ShmChargerInfo->Control.CabinetRole = _CROLE_MASTER; //ShmChargerInfo->Control.CabinetRole = _CROLE_SLAVE; ShmChargerInfo->Control.PrimaryCtrl.bits.CabinetSwitchDetect = NO; LOG_INFO("Cabinet Role: [%s], Switch Value: %d", ShmChargerInfo->Control.CabinetRole <= _CROLE_SLAVE ? str_cabinet_role[ShmChargerInfo->Control.CabinetRole] : "Unknown", ShmChargerInfo->Control.CabinetSwitch); if(_versionCheck) { if(!_emgBtn) { if(ShmChargerInfo->Control.CabinetRole == _CROLE_SLAVE) { SetSelfTestSate(_STEST_COMPLETE); } else { if(!ShmStatusCodeData->AlarmCode.AlarmEvents.bits.DcInputUVP) { SetSelfTestSate(_STEST_PSU_DETECT); } else { LOG_INFO("DC Input UVP, Bypass PSU Self-Test"); SetSelfTestSate(_STEST_COMPLETE); } } } else { SetSelfTestSate(_STEST_EMG_BTN); } } else { if(!_emgBtn) { SetSelfTestSate(_STEST_VERSION); } else { SetSelfTestSate(_STEST_EMG_BTN); } } } break; case _STEST_AC_CONTACTOR: if(_preTest != _selfTest) { ShmChargerInfo->Control.RelayCtrl.bits.AcContactor = ON; GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [AcContactor]"); } SetSelfTestSate(_STEST_PSU_DETECT); break; case _STEST_PSU_DETECT: if(_preTest != _selfTest) { ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK = NO; ShmChargerInfo->Control.PsuCtrl.bits.NeedSelfTest = YES; ShmChargerInfo->Control.RelayCtrl.bits.AcContactor = ON; GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [PsuDetect]"); } if(ShmPsuData->Work_Step >= GET_SYS_CAP) { SetSelfTestSate(_STEST_PSU_CAP); } else { if(_emgBtn) { SetSelfTestSate(_STEST_EMG_BTN); break; } if(_selfTestTimeout) { // self test timeout, set status code for timeout reason if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail == NO) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail = YES; if(!ShmSysConfigAndInfo->SysInfo.AcContactorStatus) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.AcContactStestFail = YES; LOG_INFO("Ac Contactor Self Test Fail!"); } LOG_INFO("PSU Self Test Fail!"); } if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { LOG_INFO("Booting Completed, PSU Self Test Fail!"); } ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL; ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= PSU_SELF_TIMEOUT) { SetSelfTestSate(_STEST_PSU_RETRY); } } } break; case _STEST_PSU_CAP: if(_preTest != _selfTest) { GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [PsuCapability]"); } if(ShmChargerInfo->Control.PsuCtrl.bits.SelfTestOK == YES) { SetSelfTestSate(_STEST_COMPLETE); } else { if(_emgBtn) { SetSelfTestSate(_STEST_EMG_BTN); break; } if(_selfTestTimeout) { // self test timeout, set status code for timeout reason if(ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail == NO) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.PsuModuleStestFail = YES; LOG_INFO("PSU Self Test Fail!"); } if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { LOG_INFO("Booting Completed, PSU Self Test Fail!"); } ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL; ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; } if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= PSU_SELF_TIMEOUT) { SetSelfTestSate(_STEST_PSU_RETRY); } } break; case _STEST_PSU_RETRY: if(_preTest != _selfTest) { psuRetryCnt++; ShmChargerInfo->Control.RelayCtrl.bits.AcContactor = OFF; GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [PsuRetry]"); } if(_emgBtn) { SetSelfTestSate(_STEST_EMG_BTN); break; } if(psuRetryCnt > MAX_PSU_RETRY_CNT) { SetSelfTestSate(_STEST_FAIL); } if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= (PSU_RETRY_TIMEOUT)) { SetSelfTestSate(_STEST_PSU_DETECT); } break; case _STEST_EMG_BTN: if(_preTest != _selfTest) { ShmStatusCodeData->AlarmCode.AlarmEvents.bits.EmergencyStopTrip = true; GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [EmgBtn Fail]"); } ShmSysConfigAndInfo->SysInfo.SelfTestSeq = _STEST_FAIL; ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; if(GetTimeoutValue(_TestStep_time) / uSEC_VAL >= EMG_BTN_INTERVAL) { if(ShmPrimaryMcuData->InputDet.bits.EmergencyButton == NORMAL) { // bypass cabinet switch detection SetSelfTestSate(_STEST_FAIL); LOG_INFO("Emergency button recover, Soft Reset!"); } GetClockTime(&_TestStep_time); } break; case _STEST_FAIL: if(_preTest != _selfTest) { GetClockTime(&_TestStep_time); LOG_INFO("SelfTest Process [SelfTestFail]"); } // stop here // self test fail, need soft reset ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true; break; case _STEST_COMPLETE: if(_preTest != _selfTest) { LOG_INFO("SelfTest Process [SelfTestDone]"); } if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { ShmSysConfigAndInfo->SysInfo.BootingStatus = BOOT_COMPLETE; } if(_selfTestTimeout) { // stop here // self test completed but timeout, need soft reset ShmChargerInfo->Control.SysCtrl.bits.NeedSoftReset = true; } break; default: if(_preTest != _selfTest) { LOG_INFO("SelfTest Process [Unknown]"); } SetSelfTestSate(_STEST_VERSION); break; } if(ShmSysConfigAndInfo->SysInfo.BootingStatus != BOOT_COMPLETE) { if(GetTimeoutValue(_SelfTest_time) / uSEC_VAL >= SELFTEST_TIMEOUT) { _selfTestTimeout = true; } } _preTest = _selfTest; usleep(10000); } return 0; }