/********************************* (C) ROTEK *********************************** * @module settings_api * @file settings_api.c * @version 1.0.0 * @date XX.XX.XXXX * $brief Settings ******************************************************************************* * @history Version Author Comment * XX.XX.XXXX 1.0.0 Telenkov D.A. First release. ******************************************************************************* */ #include "stm32f4xx.h" #include "settings_api.h" #include "common_config.h" #include "snmp_api.h" #include "trap_api.h" #include "log.h" #include "FreeRTOS.h" #include "task.h" #include #include #ifdef PRINTF_STDLIB #include #endif #ifdef PRINTF_CUSTOM #include "tinystdio.h" #endif #define DBG if(0) /** * @brief Флаг подтверждения новых сетевых параметров пользователем */ bool fConfirmWebParams = false; /** * @brief Общая структура настроек */ SETTINGS_t sSettings; /** * @brief Установить параметры обновления ПО по умолчанию */ void SETTINGS_SetBootParamsDef(void) { sSettings.bootParams.loadMode = 0; sSettings.bootParams.bootTry = 0; } /** * @brief Установить параметры сетевого подключения по умолчанию */ void SETTINGS_SetWebParamsDef(void) { strcpy(sSettings.sWebParams.ip, "192.168.1.2"); strcpy(sSettings.sWebParams.gate, "192.168.1.1"); strcpy(sSettings.sWebParams.mask, "255.255.255.0"); sSettings.sWebParams.dhcpEnable = 1; } /** * @brief Установить временные параметры сетевого подключения по умолчанию */ void SETTINGS_SetTempWebParamsDef(void) { strcpy(sSettings.sWebParams.ip, "192.168.1.2"); strcpy(sSettings.sWebParams.gate, "192.168.1.1"); strcpy(sSettings.sWebParams.mask, "255.255.255.0"); sSettings.sWebParams.dhcpEnable = 1; } /** * @brief Установить параметры SNMP по умолчанию */ void SETTINGS_SetSnmpDef(void) { strcpy(sSettings.sSnmp.sysDescr, ""); strcpy(sSettings.sSnmp.readCommunity, "public"); strcpy(sSettings.sSnmp.writeCommunity, "public"); strcpy(sSettings.sSnmp.sysContact, ""); strcpy(sSettings.sSnmp.sysName, "BT6702"); strcpy(sSettings.sSnmp.sysLocation, ""); strcpy(sSettings.sSnmp.managerIP, "0.0.0.0"); strcpy(sSettings.sSnmp.managerIP2, "0.0.0.0"); strcpy(sSettings.sSnmp.managerIP3, "0.0.0.0"); strcpy(sSettings.sSnmp.managerIP4, "0.0.0.0"); strcpy(sSettings.sSnmp.managerIP5, "0.0.0.0"); } /** * @brief Установить Информацию об устройстве по умолчанию */ void SETTINGS_SetInfoDef(void) { strcpy(sSettings.sInfo.productionData, "09.10.2015"); strcpy(sSettings.sInfo.mac, DEVICE_MAC); strcpy(sSettings.sInfo.serialNumber, SERIAL); strcpy(sSettings.sInfo.comments, ""); } /** * @brief Установить флаги по умолчанию */ void SETTINGS_SetFlagsDef(void) { sSettings.sFlags.netsettingsChanged = false; } /** * @brief Установить значение сервисных настроек по умолчанию */ void SETTINGS_SetServiceDef(void) { uint8_t user_id; for (user_id = 0; user_id < MAX_WEB_USERS; user_id++) { switch (user_id) { /* First users in the system is always ADMIN. * Others are USER */ case 0: sSettings.sAuth[user_id].level = ADMIN; strcpy(sSettings.sAuth[user_id].login, "admin"); strcpy(sSettings.sAuth[user_id].password, "12345"); break; case 1: default: sSettings.sAuth[user_id].level = USER; strcpy(sSettings.sAuth[user_id].login, "user"); strcpy(sSettings.sAuth[user_id].password, "1234"); break; } } } /** * @brief Установить параметры SNTP по умолчанию */ void SETTINGS_SetSntpDef(void) { sSettings.sSNTP.sntpEnable = true; strcpy(sSettings.sSNTP.ip, "88.147.254.235"); sSettings.sSNTP.timeZone = 3.0; strcpy(sSettings.sSNTP.data, "none"); } /** * @brief Установить параметры настроек сухих контактов / реле по умолчанию */ void SETTINGS_SetINOUTSDef(void) { sSettings.sInOuts.ro_type_source[0] = CRITICAL; sSettings.sInOuts.ro_type_source[1] = SNMP_SET; sSettings.sInOuts.din_type_act[0] = SNMP_TRAP; } /** * @brief Установить параметры RADIUS по умолчанию */ void SETTINGS_SetRADIUSDef(void) { sSettings.sRADIUS.Auth_enable = true; sSettings.sRADIUS.RDSEnable = true; strcpy(sSettings.sRADIUS.ServerIP, "127.0.0.1"); sSettings.sRADIUS.port = 1227; sSettings.sRADIUS.key_access = 123; strcpy(sSettings.sRADIUS.rds_password, "12345"); } /** * @brief Сброс настроек в значения по умолчанию */ void SETTINGS_SetDefault(void) { SETTINGS_SetWebParamsDef(); SETTINGS_SetTempWebParamsDef(); SETTINGS_SetSnmpDef(); SETTINGS_SetServiceDef(); SETTINGS_SetSntpDef(); SETTINGS_SetINOUTSDef(); SETTINGS_SetRADIUSDef(); sSettings.CritSecCRC = SETTINGS_GetCritSecCRC(); } /** * @brief Сброс всех настроек в значения по умолчанию кроме сетевых настроек */ void SETTINGS_SetPartDefault(void) { SETTINGS_SetBootParamsDef(); SETTINGS_SetSnmpDef(); SETTINGS_SetFlagsDef(); // SETTINGS_SetServiceDef(); SETTINGS_SetSntpDef(); SETTINGS_SetINOUTSDef(); SETTINGS_SetRADIUSDef(); sSettings.CritSecCRC = SETTINGS_GetCritSecCRC(); sSettings.controlWorld = SETTINGS_CONTROL_WORD; } /** * @brief Сброс всех настроек в значения по умолчанию */ void SETTINGS_SetAllDefault(void) { SETTINGS_SetBootParamsDef(); SETTINGS_SetWebParamsDef(); SETTINGS_SetTempWebParamsDef(); SETTINGS_SetSnmpDef(); SETTINGS_SetInfoDef(); SETTINGS_SetFlagsDef(); SETTINGS_SetServiceDef(); SETTINGS_SetSntpDef(); SETTINGS_SetINOUTSDef(); SETTINGS_SetRADIUSDef(); sSettings.CritSecCRC = SETTINGS_GetCritSecCRC(); sSettings.controlWorld = SETTINGS_CONTROL_WORD; } /** * @brief Установка настроек для отладки */ void SETTINGS_SetDefaultDebug(void) { SETTINGS_SetWebParamsDef(); SETTINGS_SetTempWebParamsDef(); SETTINGS_SetSnmpDef(); SETTINGS_SetBootParamsDef(); SETTINGS_SetFlagsDef(); //SETTINGS_SetServiceDef(); SETTINGS_SetSntpDef(); SETTINGS_SetINOUTSDef(); SETTINGS_SetRADIUSDef(); //SETTINGS_SetInfoDef(); sSettings.CritSecCRC = SETTINGS_GetCritSecCRC(); sSettings.controlWorld = SETTINGS_CONTROL_WORD; } /** * @brief Запись структуры настроек во flesh */ void SETTINGS_Save(void) { /* Calc critical section CRC and store to the settings structure */ sSettings.CritSecCRC = SETTINGS_GetCritSecCRC(); SETTINGS_WriteToFlash((uint8_t*)&sSettings, sizeof(sSettings)); } /** * @brief Загрузка структуры настроек из flesh */ void SETTINGS_Load(void) { uint32_t loadCRC; // CRC из flash uint32_t newCRC; // CRC загруженной структуры настроек SETTINGS_ReadFromFlash((uint8_t*)&sSettings, sizeof(sSettings)); /* Считываем CRC из флеш памяти */ loadCRC = (*(uint32_t*)CRC_ADDRESS); /* Рассчитываем CRC для структуры настроек */ newCRC = SETTINGS_GetCRC(); if (loadCRC != newCRC) { SETTINGS_SetAllDefault(); SETTINGS_Save(); } } /** * @brief */ void SETTINGS_WriteToFlash(uint8_t *data, uint32_t size) { uint32_t baseAddress = SETTINGS_SECTOR; uint32_t checkCrc = 0; uint32_t crc = SETTINGS_GetCRC(); bool fAlarm = 0; FLASH_Status status; for (uint8_t i = 0; i < 3; i++) { fAlarm = 0; FLASH_Unlock(); SETTINGS_EraseFlashSector(); for (uint32_t i = 0; i < size; i++) if ((status = FLASH_ProgramByte(baseAddress++, *data++)) != FLASH_COMPLETE) { DBG printf("FLASH_ProgramByte error: status = %d\r\n", status); break; } if ((status = FLASH_ProgramWord((uint32_t)CRC_ADDRESS, crc)) != FLASH_COMPLETE) { DBG printf("FLASH_ProgramWord error: status = %d\r\n", status); } FLASH_Lock(); /* Считываем что записали */ SETTINGS_ReadFromFlash((uint8_t*)&sSettings, sizeof(sSettings)); checkCrc = SETTINGS_GetCRC(); /* Проверяем CRC того что было записано */ if (checkCrc == crc) break; else fAlarm = 1; // Авария } /* Произошел сбой при записи - висим */ if (fAlarm) while (1) {}; } /** * @brief */ void SETTINGS_ReadFromFlash(uint8_t *data, uint32_t size) { uint32_t baseAddress = SETTINGS_SECTOR; for (uint32_t i = 0; i < size; i++) *data++ = (*(uint32_t*)baseAddress++);; } /** * @brief Очистка сектора настроек * @retval */ void SETTINGS_EraseFlashSector(void) { FLASH_Status status; if ((status = FLASH_EraseSector(FLASH_Sector_1, VoltageRange_3)) != FLASH_COMPLETE) { DBG printf("SETTINGS_EraseFlashSector error: status = %d/r/n", status); } } /** * @brief * @retval */ uint32_t SETTINGS_GetCRC(void) { CRC_ResetDR(); return CRC_CalcBlockCRC((uint32_t*)&sSettings, sizeof(sSettings)/4 - 1); } /** * @brief * @retval */ uint32_t SETTINGS_GetCritSecCRC(void) { CRC_ResetDR(); uint32_t critsec_len = (uint32_t)((uint8_t *)(&sSettings.CritSecCRC) - (uint8_t *)&sSettings) / 4; return CRC_CalcBlockCRC((uint32_t *)&sSettings, critsec_len); } /** * @brief Сброс флага boottry в регистре RTC */ void SETTINGS_ResetBootTry(void) { uint8_t bootTry = RTC_ReadBackupRegister(RTC_BKP_DR2); if (bootTry > 0 ) { bootTry = 0; RTC_WriteBackupRegister(RTC_BKP_DR2, 0); /* Check FW update flag */ if (RTC_ReadBackupRegister(RTC_BKP_DR3)) { /* Отправка трапа об успешном обновлении ПО */ SNMP_SendUserTrap(FW_VERSION_UPDATED); log_event_data(LOG_UPDATE_SOFT, "Успешно"); /* Clear FW update flag */ RTC_WriteBackupRegister(RTC_BKP_DR3, 0); } } /* if (sSettings.bootParams.bootTry != 0) { sSettings.bootParams.bootTry = 0; // Отправка трапа об успешном обновлении ПО SNMP_SendUserTrap(FW_VERSION_UPDATED); //taskENTER_CRITICAL(); SETTINGS_Save(); //taskEXIT_CRITICAL(); } */ } /** * @brief Преобразует mac адрес строкового формата в массив uint8_t * @param mac - буфер для вывода mac адреса */ void SETTINGS_GetMac(uint8_t *mac) { char dummy[2]; char *macPtr = sSettings.sInfo.mac; for (uint8_t i = 0; i < 6; i++) { strncpy(dummy, macPtr+i*3, 2); mac[i] = (uint8_t)strtol(dummy, NULL, 16); } } /** * @brief Установить дату производства */ void SETTINGS_SetProDate(char *proDate, uint8_t len) { memset(sSettings.sInfo.productionData, 0, 40); memcpy(sSettings.sInfo.productionData, proDate, len); } /** * @brief Установить статус тестирования "T2OK" */ void SETTINGS_SetT2OK(void) { memset(sSettings.sFlags.testState, 0, 16); memcpy(sSettings.sFlags.testState, "T2OK", 4); } /** * @brief Включить DHCP */ void SETTINGS_SetDHCPOn(void) { sSettings.sWebParams.dhcpEnable = 1; } /********************************* (C) ROTEK **********************************/