#include "at32f403a_407.h" #include "settings_api.h" #include "settings_dio.h" #include "settings_ao.h" #include "settings_ai.h" #include "sys_api.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "semphr.h" #include "common_config.h" #include "common.h" #include "at32_uid.h" #include "hash.h" #include "utility.h" #include "log_api.h" #include #include #include #include SemaphoreHandle_t flash_mutex; // Флаг подтверждения новых сетевых параметров пользователем bool fConfirmWebParams = false; // Системные настройки sys_settings_t sys_settings; // Копия системных настроек sys_settings_t temp_sys_settings; // Общая структура настроек settings_t settings; // Настройки порта UART - RS485 (Modbus) в человеческом формате modbus_t mb_port_settings; // void init_settings(void) { flash_mutex = xSemaphoreCreateMutex(); } // Загрузка структуры настроек из flash void settings_load(settings_t *settings) { uint32_t loadCRC; // CRC из flash uint32_t newCRC; // CRC загруженной структуры настроек bool need_default = false; settings_read_from_flash((uint8_t*)settings, sizeof(settings_t)); // Считываем CRC из флеш памяти loadCRC = (*(uint32_t*)CRC_ADDRESS); // Рассчитываем CRC для структуры настроек newCRC = settings_get_crc(settings); // Если CRC не совпадают нужно прошивать дефолтные настройки if (loadCRC != newCRC) { need_default = true; } // CRC совпала, проверяем контрольное слово если слово не совпадает // то это значит, что поплыла структура нстроек, прошиваем дефолт else if (settings->control_word != SETTINGS_CONTROL_WORD) { need_default = true; } // CRC и контрольное слово совпали, проверяем номер версии настроек. // Если версия в настройках и прошивке не совпадают // (при обновлении изменили структуру настроек), прошиваем дефолт else if (settings->settings_version != SETTINGS_VERSION) { need_default = true; } // Прошиваем дефолтные настройки если нужно if (need_default) { settings_set_all_default(); settings_save(settings); } #if 1 //SETTINGS_Print(); #endif } // void settings_read_from_flash(uint8_t *data, uint32_t size) { uint32_t baseAddress = SETTINGS_SECTOR; for (uint32_t i = 0; i < size; i++) *data++ = (*(uint32_t*)baseAddress++);; } // uint32_t settings_get_crc(settings_t *settings) { crc_data_reset(); return crc_block_calculate((uint32_t*)settings, sizeof(settings_t)/4 - 1); } // uint32_t settings_get_crit_sec_crc(settings_t *settings) { crc_data_reset(); uint32_t critsec_len = (uint32_t)((uint8_t *)(&settings->critical_section_crc) - (uint8_t *)settings) / 4; return crc_block_calculate((uint32_t *)settings, critsec_len); } // Сброс всех настроек в значения по умолчанию void settings_set_all_default(void) { settings_set_modbus_def(&settings.com_settings.mb_port); settings.settings_version = SETTINGS_VERSION; settings.critical_section_crc = settings_get_crit_sec_crc(&settings); settings.control_word = SETTINGS_CONTROL_WORD; #if defined (MDIO_88) settings_dio_set_all_default(); #endif #if defined (MAI_12) settings_ai_set_all_default(); #endif } // -------------------------------------------------------------------------- // // Настройки по умолчанию // void settings_set_modbus_def(uint16_t *mb_port) { modbus_t mb_settings; mb_settings.baud = BRD_115200; mb_settings.parity = NO_PAR; mb_settings.databits = DATABITS_8; mb_settings.stopbits = STOP_1; settings_conv_modbus_def(&mb_settings, mb_port); } // void settings_conv_modbus_def(modbus_t *mb_settings, uint16_t *mb_port) { uint16_t param = 0; // Количестро стоп бит (0-1 биты) if (mb_settings->stopbits == STOP_1) param = 0x00; else if (mb_settings->stopbits == STOP_2) param = 0x02; // Длина слова (2ой бит) param |= 0x00 << 2; // Контроль четности (3-4 биты) if (mb_settings->parity == NO_PAR) param |= 0x00 << 3; else if (mb_settings->parity == EVEN_PAR) param |= 0x02 << 3; else if (mb_settings->parity == ODD_PAR) param |= 0x03 << 3; // Скорость (5 - 7 биты) switch (mb_settings->baud) { case BRD_2400 : param |= 0x00 << 5; break; case BRD_4800 : param |= 0x01 << 5; break; case BRD_9600 : param |= 0x02 << 5; break; case BRD_19200 : param |= 0x03 << 5; break; case BRD_38400 : param |= 0x04 << 5; break; case BRD_57600 : param |= 0x05 << 5; break; case BRD_115200 : param |= 0x06 << 5; break; default : break; } *mb_port = param; } // Установка параметров Modbus void settings_set_modbus_params(uint16_t mb_port) { uint16_t param = 0; // Количестро стоп бит (0-1 биты) param = 0x0003 & mb_port; if (param == 0x00) mb_port_settings.stopbits = STOP_1; else if (param == 0x02) mb_port_settings.stopbits = STOP_2; // Длина слова (2ой бит) param = (0x0004 & mb_port) >> 2; mb_port_settings.databits = DATABITS_8; // Контроль четности (3-4 биты) param = (0x0018 & mb_port) >> 3; if (param == 0x00) mb_port_settings.parity = NO_PAR; else if (param == 0x02) mb_port_settings.parity = EVEN_PAR; else if (param == 0x03) mb_port_settings.parity = ODD_PAR; // Скорость (5 - 7 биты) param = (0x00E0 & mb_port) >> 5; switch (param) { case 0x00 : mb_port_settings.baud = BRD_2400; break; case 0x01 : mb_port_settings.baud = BRD_4800; break; case 0x02 : mb_port_settings.baud = BRD_9600; break; case 0x03 : mb_port_settings.baud = BRD_19200; break; case 0x04 : mb_port_settings.baud = BRD_38400; break; case 0x05 : mb_port_settings.baud = BRD_57600; break; case 0x06 : mb_port_settings.baud = BRD_115200; break; default : break; } } // uint32_t settings_get_mb_baud(modbus_t *mb_settings) { switch (mb_settings->baud) { case BRD_1200 : return 1200; break; case BRD_2400 : return 2400; break; case BRD_4800 : return 4800; break; case BRD_9600 : return 9600; break; case BRD_19200 : return 19200; break; case BRD_38400 : return 38400; break; case BRD_57600 : return 57600; break; case BRD_115200 : return 115200; break; case BRD_230400 : return 230400; break; case BRD_460800 : return 460800; break; default : return 115200; break; } } // eMBParity settings_get_mb_par(modbus_t *mb_settings) { switch (mb_settings->parity) { case NO_PAR : return MB_PAR_NONE; break; case ODD_PAR : return MB_PAR_ODD; break; case EVEN_PAR : return MB_PAR_EVEN; break; default : return MB_PAR_NONE; break; } } // void settings_init_mb_port(uint8_t mb_addr) { uint32_t baud = settings_get_mb_baud(&mb_port_settings); eMBParity par = settings_get_mb_par(&mb_port_settings); eMBInit(MB_RTU, mb_addr, 4, baud, par, mb_port_settings.stopbits); } // -------------------------------------------------------------------------- // // Запись структуры настроек во flash bool settings_save(settings_t *settings) { bool ret = false; xSemaphoreTake(flash_mutex, portMAX_DELAY); settings->critical_section_crc = settings_get_crit_sec_crc(settings); ret = settings_write_to_flash((uint8_t*)settings, sizeof(settings_t)); xSemaphoreGive(flash_mutex); return ret; } // bool settings_save_with_log(void) { bool ret; // Изменились ли настройки bool change = settings_is_changed(&settings); // Сохранение настроек ret = settings_save(&settings); if (change) { log_add_entry(LOG_CHANGE_CONFIG, (log_event_state_t)ret, 0, 0); } return ret; } // bool settings_write_to_flash(uint8_t *data, uint32_t size) { uint32_t baseAddress = SETTINGS_SECTOR; uint32_t checkCrc = 0; uint32_t crc = settings_get_crc((settings_t*)data); flash_status_type status; uint8_t *ptr = data; flash_unlock(); settings_erase_flash_sector(); for (uint32_t i = 0; i < size; i++) if ((status = flash_byte_program(baseAddress++, *data++)) != FLASH_OPERATE_DONE) { DBG printf("FLASH_ProgramByte error: status = %d\r\n", status); return false; } if ((status = flash_word_program((uint32_t)CRC_ADDRESS, crc)) != FLASH_OPERATE_DONE) { DBG printf("FLASH_ProgramWord error: status = %d\r\n", status); } flash_lock(); /* Считываем что записали */ settings_read_from_flash(ptr, sizeof(settings_t)); checkCrc = settings_get_crc((settings_t*)ptr); /* Проверяем CRC того что было записано */ if ((checkCrc != crc) || (status != FLASH_OPERATE_DONE)) { return false; } return true; } // Очистка сектора настроек void settings_erase_flash_sector(void) { flash_status_type status; if ((status = flash_sector_erase(SETTINGS_SECTOR)) != FLASH_OPERATE_DONE) { DBG printf("SETTINGS_EraseFlashSector error: status = %d/r/n", status); } } // bool settings_is_changed(settings_t *new_settings) { uint32_t baseAddress = SETTINGS_SECTOR; uint32_t settings_size = sizeof(settings_t); uint8_t old_data; uint8_t new_data; uint8_t *ptr = (uint8_t*)new_settings; for (uint32_t i = 0; i < settings_size; i++) { old_data = (*(uint32_t*)baseAddress++); new_data = *ptr++; if (old_data != new_data) return true; } return false; } // -------------------------------------------------------------------------- // void settings_print(void) { uint16_t foo = settings.com_settings.mb_port; printf("\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n"); printf(" Общие настройки для bootloader и FW"); printf("\r\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\r\n\n"); printf("Настройки порта (Modbus): 0x%X\r\n", settings.com_settings.mb_port); // stop bits foo = settings.com_settings.mb_port & MB_STOP_BIT_MASK; if (foo == MB_STOP_BIT_1) printf("\tStop bits: STOP_1\r\n"); else if (foo == MB_STOP_BIT_2) printf("\tStop bits: STOP_2\r\n"); // parity foo = settings.com_settings.mb_port & MB_PARITY_MASK; if (foo == MB_NO_PAR) printf("\tParity: NO_PAR\r\n"); else if (foo == MB_EVEN_PAR) printf("\tParity: EVEN_PAR\r\n"); else if (foo == MB_ODD_PAR) printf("\tParity: ODD_PAR\r\n"); // baudrate foo = settings.com_settings.mb_port & MB_BRD_MASK; switch (foo) { case MB_BRD_2400 : printf("\tBaudrate: 2400\r\n"); break; case MB_BRD_4800 : printf("\tBaudrate: 4800\r\n"); break; case MB_BRD_9600 : printf("\tBaudrate: 9600\r\n"); break; case MB_BRD_19200 : printf("\tBaudrate: 19200\r\n"); break; case MB_BRD_38400 : printf("\tBaudrate: 38400\r\n"); break; case MB_BRD_57600 : printf("\tBaudrate: 57600\r\n"); break; case MB_BRD_115200 : printf("\tBaudrate: 115200\r\n"); break; default : break; } //printf("Модель: %s\r\n", settings.com_settings.model); }