#include "at32f403a_407.h" #include "settings_api.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 #include #include SemaphoreHandle_t flash_mutex; // Системные настройки sys_settings_t sys_settings; // Общая структура настроек settings_t settings; modbus_t mb_port_settings; // void init_settings(void) { flash_mutex = xSemaphoreCreateMutex(); } // Загрузка структуры настроек из flesh 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 = settings->critical_section_crc; // Рассчитываем CRC для структуры настроек newCRC = settings_get_crc(settings); // Если CRC не совпадают нужно прошивать дефолтные настройки if (loadCRC != newCRC) { need_default = true; } // Прошиваем дефолтные настройки если нужно if (need_default) { settings_set_all_default(); settings_save(settings); } } // 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.critical_section_crc = settings_get_crit_sec_crc(&settings); } // -------------------------------------------------------------------------- // // Настройки по умолчанию // 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; } } // -------------------------------------------------------------------------- // // Запись структуры настроек во flash void settings_save(settings_t *settings) { xSemaphoreTake(flash_mutex, portMAX_DELAY); settings->critical_section_crc = settings_get_crit_sec_crc(settings); settings_write_to_flash((uint8_t*)settings, sizeof(settings_t)); xSemaphoreGive(flash_mutex); } // void 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; for (uint8_t i = 0; i < 3; i++) { 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); break; } 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) break; } } // Очистка сектора настроек 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); } } // 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; } }