Init
This commit is contained in:
commit
07c1d35d7c
|
|
@ -0,0 +1,639 @@
|
||||||
|
//
|
||||||
|
// Created by cfif on 22.08.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "GetGsmFirmware.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "FirmwareLoader.h"
|
||||||
|
#include "ld_adr.h"
|
||||||
|
#include "InternalFlashPage.h"
|
||||||
|
#include "AtGsm_NetworkRegistrationStatus.h"
|
||||||
|
#include "AtGsmOperatorSelection.h"
|
||||||
|
#include "SystemDelayInterface.h"
|
||||||
|
#include "AtGsmSimComA7600_DefinePdpContext.h"
|
||||||
|
|
||||||
|
#define LOG_SIGN "UPDATE"
|
||||||
|
#define LOGGER &env->log->logger
|
||||||
|
|
||||||
|
#define FIRMWARE_MAIN_ADDR (0x08000000 + BOOT_AREA_LENGTH)
|
||||||
|
#define FIRMWARE_MAIN_RECOVERY_ADDR (FIRMWARE_MAIN_ADDR + FIRMWARE_MAIN_AREA_LENGTH)
|
||||||
|
|
||||||
|
#define FIRMWARE_TELE_MAIN_ADDR (FIRMWARE_MAIN_RECOVERY_ADDR + FIRMWARE_MAIN_UPDATE_AREA_LENGTH)
|
||||||
|
#define FIRMWARE_TELE_RECOVERY_ADDR (FIRMWARE_MAIN_ADDR + FIRMWARE_MAIN_AREA_LENGTH)
|
||||||
|
|
||||||
|
tFirmwareLoader FIRMWARE_UVEOS_LOADER;
|
||||||
|
|
||||||
|
static uint32_t GetGsmFirmwareCrc32(const uint8_t *buf, size_t size) {
|
||||||
|
uint32_t crc = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
crc += buf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool WaitNetworkRegistration(tGsmFirmware *env, tAtCmd *gsmAt, uint16_t timeReg) {
|
||||||
|
|
||||||
|
uint32_t timeEnd = SystemGetMs() + timeReg;
|
||||||
|
|
||||||
|
tAtGsm_NetworkRegistrationReportMode mode;
|
||||||
|
tAtGsm_NetworkRegistrationState state;
|
||||||
|
|
||||||
|
while (timeEnd > SystemGetMs()) {
|
||||||
|
if (AtGsm_NetworkRegistrationStatus(gsmAt, &mode, &state)) {
|
||||||
|
if (state == AT_NETWORK_REGISTRATION_STATE_REGISTERED_HOME ||
|
||||||
|
state == AT_NETWORK_REGISTRATION_STATE_REGISTERED_ROAMING) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Получена регистрация")
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SystemDelayMs(60);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool NetworkRequire(tGsmFirmware *env, tAtCmd *gsmAt) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
if (osMutexAcquire(gsmAt->access, 2000) == osOK) {
|
||||||
|
|
||||||
|
if (!WaitNetworkRegistration(env, gsmAt, 2000)) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Включение регистрации в сети");
|
||||||
|
for (uint8_t i = 0; i < 5; ++i) {
|
||||||
|
AtGsm_OperatorSelectionAutomatic(gsmAt);
|
||||||
|
SystemDelayMs(150);
|
||||||
|
}
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ждем сеть...");
|
||||||
|
if (WaitNetworkRegistration(env, gsmAt, 2000)) {
|
||||||
|
result = true;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Регистрация в сети получена");
|
||||||
|
} else {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Регистрация в сети не получена");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
result = true;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Регистрация в сети присутствует");
|
||||||
|
}
|
||||||
|
|
||||||
|
osMutexRelease(gsmAt->access);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getFileSizeFirmware(tGsmFirmware *env, tAtCmd *gsmAt, char *firmware_php_path_req, uint8_t *firmware_buf) {
|
||||||
|
|
||||||
|
char url[128];
|
||||||
|
url[0] = '\0';
|
||||||
|
strcat(url, firmware_php_path_req);
|
||||||
|
strcat(url, "?file=");
|
||||||
|
|
||||||
|
if (env->firmwareType == FIRMWARE_UVEOS) {
|
||||||
|
strcat(url, firmware_php_uveos_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->firmwareType == FIRMWARE_TELE) {
|
||||||
|
strcat(url, firmware_php_tele_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcat(url, "&return_size=1");
|
||||||
|
|
||||||
|
int FileSizeCurrent = 0;
|
||||||
|
int connection_step = 0;
|
||||||
|
|
||||||
|
while (connection_step < connect_http_retry) {
|
||||||
|
Gsm_HttpGet_Close(gsmAt);
|
||||||
|
size_t fileSize = Gsm_HttpGet_Open(gsmAt, url, strlen(url));
|
||||||
|
|
||||||
|
if (fileSize > 0) {
|
||||||
|
|
||||||
|
size_t read = Gsm_HttpGet_Read(gsmAt, firmware_buf, 2048);
|
||||||
|
if (read > 0) {
|
||||||
|
|
||||||
|
FileSizeCurrent = atoi((char *) firmware_buf);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++connection_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
++connection_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FileSizeCurrent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int getMetadataFirmware(tGsmFirmware *env, tAtCmd *gsmAt, char *firmware_php_path_req, int sizeFileFirmware,
|
||||||
|
uint8_t *firmware_buf) {
|
||||||
|
char buf[12];
|
||||||
|
|
||||||
|
char url[128];
|
||||||
|
url[0] = '\0';
|
||||||
|
strcat(url, firmware_php_path_req);
|
||||||
|
strcat(url, "?offset=");
|
||||||
|
int offsetMeta = sizeFileFirmware - FIRMWARE_META_LENGTH;
|
||||||
|
utoa(offsetMeta, buf, 10);
|
||||||
|
strcat(url, buf);
|
||||||
|
strcat(url, "&limit=");
|
||||||
|
utoa(FIRMWARE_META_LENGTH, buf, 10);
|
||||||
|
strcat(url, buf);
|
||||||
|
strcat(url, "&file=");
|
||||||
|
if (env->firmwareType == FIRMWARE_UVEOS) {
|
||||||
|
strcat(url, firmware_php_uveos_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->firmwareType == FIRMWARE_TELE) {
|
||||||
|
strcat(url, firmware_php_tele_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
int connection_step = 0;
|
||||||
|
|
||||||
|
size_t fileSizeMeta = 0;
|
||||||
|
|
||||||
|
while (connection_step < connect_http_retry) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Gsm_HttpGet_Close(gsmAt);
|
||||||
|
fileSizeMeta = Gsm_HttpGet_Open(gsmAt, url, strlen(url));
|
||||||
|
|
||||||
|
if (fileSizeMeta > 0) {
|
||||||
|
|
||||||
|
size_t read = Gsm_HttpGet_Read(gsmAt, firmware_buf, 2048);
|
||||||
|
if (read > 0) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++connection_step;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
++connection_step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (int) fileSizeMeta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool
|
||||||
|
getFileBodyFirmware(tGsmFirmware *env, bool isDoGsmFirmware) {
|
||||||
|
|
||||||
|
|
||||||
|
if (env->Server.length < 1) {
|
||||||
|
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Не введен адреса сервера обновления");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NetworkRequire(env, env->gsmAt)) {
|
||||||
|
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Начало обновления прошивки");
|
||||||
|
} else {
|
||||||
|
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Нет регистрации в сети");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(env->firmwareStats, 0, sizeof(tFirmwareStats));
|
||||||
|
|
||||||
|
AtCommandResult res = AtGsmSimComA7600_PdpActivate(env->gsmAt, 2);
|
||||||
|
|
||||||
|
res = AtGsmSimComA7600_DefinePdpContext(env->gsmAt, 2, AtGsmSimComA7600_PdpType_IP,
|
||||||
|
env->Apn.data,
|
||||||
|
env->Apn.length);
|
||||||
|
|
||||||
|
res = AtGsmSimComA7600_PdpActivate(env->gsmAt, 2);
|
||||||
|
|
||||||
|
uint32_t connection_step = 0;
|
||||||
|
size_t FileSizeCurrent = 0;
|
||||||
|
|
||||||
|
while ((FileSizeCurrent == 0) && (connection_step < connect_http_retry)) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FileSizeCurrent = getFileSizeFirmware(env, env->gsmAt, env->Server.data, env->firmware_buf);
|
||||||
|
|
||||||
|
if (FileSizeCurrent == 0) {
|
||||||
|
++env->firmwareStats->stat_err_open;
|
||||||
|
++connection_step;
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Получение размера прошивки. Ошибка соединения с сервером. Попытка: %d из %d",
|
||||||
|
connection_step, connect_http_retry);
|
||||||
|
SystemDelayMs(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileSizeCurrent == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
connection_step = 0;
|
||||||
|
size_t FileSizeMeta = 0;
|
||||||
|
|
||||||
|
while ((FileSizeMeta == 0) && (connection_step < connect_http_retry)) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
FileSizeMeta = getMetadataFirmware(env, env->gsmAt, env->Server.data, (int) FileSizeCurrent, env->firmware_buf);
|
||||||
|
|
||||||
|
if (FileSizeMeta == 0) {
|
||||||
|
++env->firmwareStats->stat_err_open;
|
||||||
|
++connection_step;
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Получение метаданных прошивки. Ошибка соединения с сервером. Попытка: %d из %d",
|
||||||
|
connection_step, connect_http_retry);
|
||||||
|
SystemDelayMs(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (FileSizeMeta == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Проверка нужно ли обновляться
|
||||||
|
if (env->isExaminationFirmware) {
|
||||||
|
|
||||||
|
tFirmwareLoader FIRMWARE_HTTP;
|
||||||
|
FirmwareLoader_Init(&FIRMWARE_HTTP, FIRMWARE_META_LENGTH, 0, (uint32_t) &env->firmware_buf[0]);
|
||||||
|
FirmwareLoader_LoadMetadata(&FIRMWARE_HTTP, &FIRMWARE_HTTP.update);
|
||||||
|
|
||||||
|
uint32_t httpCrc32 = *FIRMWARE_HTTP.update.metadata.crc;
|
||||||
|
uint32_t uveosCrc32 = *FIRMWARE_UVEOS_LOADER.main.metadata.crc;
|
||||||
|
|
||||||
|
bool sameNames =
|
||||||
|
(*FIRMWARE_UVEOS_LOADER.main.metadata.nameLength == *FIRMWARE_HTTP.update.metadata.nameLength) &&
|
||||||
|
memcmp(
|
||||||
|
FIRMWARE_UVEOS_LOADER.main.metadata.name,
|
||||||
|
FIRMWARE_HTTP.update.metadata.name,
|
||||||
|
*FIRMWARE_HTTP.update.metadata.nameLength) == 0;
|
||||||
|
|
||||||
|
if ((uveosCrc32 == httpCrc32) && sameNames) {
|
||||||
|
env->isAbortOld = true;
|
||||||
|
LoggerStrInfoStatic(LOGGER, LOG_SIGN, "Прошивка в обновлении не нуждается");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDoGsmFirmware) {
|
||||||
|
if (osMutexAcquire(env->access, 5000) == osOK) {
|
||||||
|
|
||||||
|
if (FirmwareLoader_ClearUpdateFlash(&FIRMWARE_UVEOS_LOADER)) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "ПЗУ очищено");
|
||||||
|
} else {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка очистки ПЗУ");
|
||||||
|
++env->firmwareStats->stat_err_write;
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Очистка ПЗУ не требуется");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
char url[128];
|
||||||
|
char buf[12];
|
||||||
|
|
||||||
|
uint32_t portion_full = FileSizeCurrent / portion_size;
|
||||||
|
uint32_t portion_size_tail = FileSizeCurrent % portion_size;
|
||||||
|
|
||||||
|
if (portion_size_tail > 0)
|
||||||
|
++portion_full;
|
||||||
|
|
||||||
|
uint32_t limit = portion_size;
|
||||||
|
connection_step = 0;
|
||||||
|
|
||||||
|
if (!isDoGsmFirmware) {
|
||||||
|
env->offset = 0;
|
||||||
|
env->portion_step = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
env->firmwareStats->stat_err_open = 0;
|
||||||
|
env->firmwareStats->stat_err_read = 0;
|
||||||
|
env->firmwareStats->stat_err_crc = 0;
|
||||||
|
env->firmwareStats->stat_err_write = 0;
|
||||||
|
|
||||||
|
// Цикл по всем порциям
|
||||||
|
while ((env->portion_step < portion_full) && (connection_step < connect_http_retry)) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Gsm_HttpGet_Close(env->gsmAt);
|
||||||
|
|
||||||
|
url[0] = '\0';
|
||||||
|
strcat(url, env->Server.data);
|
||||||
|
strcat(url, "?offset=");
|
||||||
|
utoa(env->offset, buf, 10);
|
||||||
|
strcat(url, buf);
|
||||||
|
strcat(url, "&limit=");
|
||||||
|
utoa(limit, buf, 10);
|
||||||
|
strcat(url, buf);
|
||||||
|
strcat(url, "&file=");
|
||||||
|
if (env->firmwareType == FIRMWARE_UVEOS) {
|
||||||
|
strcat(url, firmware_php_uveos_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->firmwareType == FIRMWARE_TELE) {
|
||||||
|
strcat(url, firmware_php_tele_req);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t fileSize = Gsm_HttpGet_Open(env->gsmAt, url, strlen(url));
|
||||||
|
|
||||||
|
if (fileSize == limit + 4) {
|
||||||
|
|
||||||
|
size_t read = Gsm_HttpGet_Read(env->gsmAt, env->firmware_buf, fileSize);
|
||||||
|
|
||||||
|
if (read == fileSize) {
|
||||||
|
|
||||||
|
uint32_t crc_recv = ((uint32_t *) &env->firmware_buf[limit])[0];
|
||||||
|
uint32_t crc_calc = GetGsmFirmwareCrc32(env->firmware_buf, limit);
|
||||||
|
|
||||||
|
if (crc_recv != crc_calc) {
|
||||||
|
++env->firmwareStats->stat_err_crc;
|
||||||
|
++connection_step;
|
||||||
|
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Ошибка контрольной суммы данных от сервера. Попытка: %d из %d",
|
||||||
|
connection_step, connect_http_retry);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection_step = 0;
|
||||||
|
++env->portion_step;
|
||||||
|
|
||||||
|
if (osMutexAcquire(env->access, 5000) == osOK) {
|
||||||
|
|
||||||
|
if (sInternalFlashPage_Write(FIRMWARE_UVEOS_LOADER.update.address, env->offset, env->firmware_buf,
|
||||||
|
limit) == limit) {
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN, "Загружено: %d из %d", env->portion_step, portion_full);
|
||||||
|
} else {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка записи в ПЗУ");
|
||||||
|
++env->firmwareStats->stat_err_write;
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((portion_size_tail > 0) && (env->portion_step == portion_full - 1)) {
|
||||||
|
env->offset += portion_size;
|
||||||
|
limit = portion_size_tail;
|
||||||
|
} else {
|
||||||
|
env->offset += portion_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
++env->firmwareStats->stat_err_read;
|
||||||
|
++connection_step;
|
||||||
|
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN, "Ошибка получения данных от сервера. Попытка: %d из %d",
|
||||||
|
connection_step, connect_http_retry);
|
||||||
|
|
||||||
|
SystemDelayMs(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
++env->firmwareStats->stat_err_open;
|
||||||
|
++connection_step;
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Получение данных прошивки. Ошибка соединения с сервером. Попытка: %d из %d",
|
||||||
|
connection_step, connect_http_retry);
|
||||||
|
SystemDelayMs(3000);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((connection_step == connect_http_retry) || (env->firmwareStats->stat_err_write != 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetDoGsmFirmware(tGsmFirmware *env) {
|
||||||
|
bool isLoadFirmware = getFileBodyFirmware(env, true);
|
||||||
|
|
||||||
|
return isLoadFirmware;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetGsmFirmware(tGsmFirmware *env) {
|
||||||
|
|
||||||
|
bool isLoadFirmware = getFileBodyFirmware(env, false);
|
||||||
|
|
||||||
|
return isLoadFirmware;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartUpdateFirmware(tGsmFirmware *env) {
|
||||||
|
env->doUpdateFirmware = false;
|
||||||
|
env->startUpdateFirmware = true;
|
||||||
|
env->isAbortOld = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _Noreturn FirmwareProcessingTask(tGsmFirmware *env) {
|
||||||
|
// uint32_t attempts;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware) {
|
||||||
|
|
||||||
|
if (env->doUpdateFirmware) {
|
||||||
|
bool result = GetDoGsmFirmware(env);
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход из режима обновления УВЭОС");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
env->startUpdateFirmware = false;
|
||||||
|
env->doUpdateFirmware = false;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Успех. Обновление завершено без ошибок");
|
||||||
|
env->eventUpdateFunc(env->envUpdateFunc, true, env->isAbortOld);
|
||||||
|
} else {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Обновление не завершено");
|
||||||
|
--env->attempts;
|
||||||
|
|
||||||
|
env->eventUpdateFunc(env->envUpdateFunc, false, env->isAbortOld);
|
||||||
|
|
||||||
|
|
||||||
|
if (env->attempts > 0) {
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Обновление будет завершено позже, через %d сек. Осталось попыток %d из %d",
|
||||||
|
env->attempts_period,
|
||||||
|
env->attempts,
|
||||||
|
env->attemptsAll);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < env->attempts_period; ++i) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SystemDelayMs(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход из режима обновления УВЭОС");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
env->startUpdateFirmware = false;
|
||||||
|
env->doUpdateFirmware = false;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN,
|
||||||
|
"Попытки исчерпаны. Обновление будет завершено после получения команды на обновление");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
bool result = GetGsmFirmware(env);
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход из режима обновления УВЭОС");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result) {
|
||||||
|
env->startUpdateFirmware = false;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Успех. Обновление завершено без ошибок");
|
||||||
|
env->eventUpdateFunc(env->envUpdateFunc, true, env->isAbortOld);
|
||||||
|
} else {
|
||||||
|
// attempts = env->attempts;
|
||||||
|
env->doUpdateFirmware = true;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Обновление не завершено");
|
||||||
|
env->eventUpdateFunc(env->envUpdateFunc, false, env->isAbortOld);
|
||||||
|
|
||||||
|
if (env->attempts > 0) {
|
||||||
|
LoggerStrFormatInfo(LOGGER, LOG_SIGN,
|
||||||
|
"Обновление будет завершено позже, через %d сек. Осталось попыток %d из %d",
|
||||||
|
env->attempts_period,
|
||||||
|
env->attempts,
|
||||||
|
env->attemptsAll);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < env->attempts_period; ++i) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SystemDelayMs(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход из режима обновления УВЭОС");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Дополнительные 100 попыток");
|
||||||
|
env->attempts = 100;
|
||||||
|
*/
|
||||||
|
for (uint32_t i = 0; i < env->attempts_period; ++i) {
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
SystemDelayMs(1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (env->startUpdateFirmware == false) {
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход из режима обновления УВЭОС");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
env->startUpdateFirmware = false;
|
||||||
|
env->doUpdateFirmware = false;
|
||||||
|
LoggerInfoStatic(LOGGER, LOG_SIGN,
|
||||||
|
"Попытки исчерпаны. Обновление будет завершено после получения команды на обновление");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemDelayMs(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitGsmFirmware(tGsmFirmware *env,
|
||||||
|
tAtCmd *gsmAt,
|
||||||
|
eFirmwareType firmwareType,
|
||||||
|
uint8_t *firmware_buf,
|
||||||
|
tFirmwareStats *firmwareStats,
|
||||||
|
tString64 *Apn,
|
||||||
|
tString64 *Server,
|
||||||
|
uint32_t attempts,
|
||||||
|
uint32_t attempts_period,
|
||||||
|
osMutexId_t access,
|
||||||
|
bool isExaminationFirmware,
|
||||||
|
EventUpdateFunc *eventUpdateFunc,
|
||||||
|
void *envUpdateFunc,
|
||||||
|
tLoggerToSerialPort *log) {
|
||||||
|
|
||||||
|
|
||||||
|
if (firmwareType == FIRMWARE_UVEOS) {
|
||||||
|
FirmwareLoader_Init(&FIRMWARE_UVEOS_LOADER, FIRMWARE_MAIN_AREA_LENGTH, FIRMWARE_MAIN_ADDR,
|
||||||
|
FIRMWARE_MAIN_RECOVERY_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firmwareType == FIRMWARE_TELE) {
|
||||||
|
FirmwareLoader_Init(&FIRMWARE_UVEOS_LOADER, FIRMWARE_TELE_AREA_LENGTH, FIRMWARE_TELE_MAIN_ADDR,
|
||||||
|
FIRMWARE_MAIN_RECOVERY_ADDR);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mainFwOk = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main);
|
||||||
|
|
||||||
|
env->isExaminationFirmware = isExaminationFirmware;
|
||||||
|
|
||||||
|
env->access = access;
|
||||||
|
|
||||||
|
env->firmwareType = firmwareType;
|
||||||
|
|
||||||
|
env->doUpdateFirmware = false;
|
||||||
|
env->startUpdateFirmware = false;
|
||||||
|
|
||||||
|
env->eventUpdateFunc = eventUpdateFunc;
|
||||||
|
env->envUpdateFunc = envUpdateFunc;
|
||||||
|
|
||||||
|
env->attemptsAll = attempts;
|
||||||
|
env->attempts = attempts;
|
||||||
|
env->attempts_period = attempts_period;
|
||||||
|
|
||||||
|
env->gsmAt = gsmAt;
|
||||||
|
env->firmware_buf = firmware_buf;
|
||||||
|
env->firmwareStats = firmwareStats;
|
||||||
|
|
||||||
|
memset(env->Apn.data, 0, sizeof(env->Apn.data));
|
||||||
|
env->Apn.length = Apn->length;
|
||||||
|
memcpy(&env->Apn.data, Apn->data, Apn->length);
|
||||||
|
|
||||||
|
memset(env->Server.data, 0, sizeof(env->Server.data));
|
||||||
|
env->Server.length = Server->length;
|
||||||
|
memcpy(&env->Server.data, Server->data, Server->length);
|
||||||
|
|
||||||
|
env->log = log;
|
||||||
|
|
||||||
|
InitThreadBlock(env->T_processing_Firmware, "Firmware", osPriorityNormal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GsmFirmware_Start(tGsmFirmware *env) {
|
||||||
|
ThreadBlock_Start(env->T_processing_Firmware, env, FirmwareProcessingTask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
//
|
||||||
|
// Created by cfif on 22.08.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GETGSMFIRMWARE_H
|
||||||
|
#define GETGSMFIRMWARE_H
|
||||||
|
|
||||||
|
#include "AtCmdBase.h"
|
||||||
|
#include "Gsm_HttpGet.h"
|
||||||
|
#include "FirmwareLoader.h"
|
||||||
|
#include "LoggerToSerialPort.h"
|
||||||
|
#include "CmsisRtosThreadUtils.h"
|
||||||
|
|
||||||
|
// Количество повторений до прерывания процедуры получения файла
|
||||||
|
#define connect_http_retry 5
|
||||||
|
// Размер порции для приема
|
||||||
|
//#define portion_size (1024 - 4)
|
||||||
|
#define portion_size (1024 - 4)
|
||||||
|
|
||||||
|
#define firmware_php_uveos_req "uveos.xfsb"
|
||||||
|
#define firmware_php_tele_req "tele.xfsb"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FIRMWARE_UVEOS = 0,
|
||||||
|
FIRMWARE_TELE = 1
|
||||||
|
} eFirmwareType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int stat_err_open;
|
||||||
|
int stat_err_read;
|
||||||
|
int stat_err_crc;
|
||||||
|
int stat_err_write;
|
||||||
|
int stat_err_file_crc;
|
||||||
|
} tFirmwareStats;
|
||||||
|
|
||||||
|
typedef void (EventUpdateFunc)(void *env, bool result, bool isAbortOld);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
tAtCmd *gsmAt;
|
||||||
|
uint8_t *firmware_buf;
|
||||||
|
tFirmwareStats *firmwareStats;
|
||||||
|
tString64 Apn;
|
||||||
|
tString64 Server;
|
||||||
|
tLoggerToSerialPort *log;
|
||||||
|
uint32_t portion_step;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t attemptsAll;
|
||||||
|
uint32_t attempts;
|
||||||
|
uint32_t attempts_period;
|
||||||
|
volatile bool startUpdateFirmware;
|
||||||
|
volatile bool doUpdateFirmware;
|
||||||
|
|
||||||
|
osMutexId_t access;
|
||||||
|
|
||||||
|
bool isExaminationFirmware;
|
||||||
|
|
||||||
|
EventUpdateFunc *eventUpdateFunc;
|
||||||
|
void *envUpdateFunc;
|
||||||
|
|
||||||
|
// Старая прошивка
|
||||||
|
bool isAbortOld;
|
||||||
|
|
||||||
|
eFirmwareType firmwareType;
|
||||||
|
|
||||||
|
tStaticThreadBlock(1024) T_processing_Firmware;
|
||||||
|
|
||||||
|
} tGsmFirmware;
|
||||||
|
|
||||||
|
void InitGsmFirmware(tGsmFirmware *env,
|
||||||
|
tAtCmd *gsmAt,
|
||||||
|
eFirmwareType firmwareType,
|
||||||
|
uint8_t *firmware_buf,
|
||||||
|
tFirmwareStats *firmwareStats,
|
||||||
|
tString64 *Apn,
|
||||||
|
tString64 *Server,
|
||||||
|
uint32_t attempts,
|
||||||
|
uint32_t attempts_period,
|
||||||
|
osMutexId_t access,
|
||||||
|
bool isExaminationFirmware,
|
||||||
|
EventUpdateFunc *eventUpdateFunc,
|
||||||
|
void *envUpdateFunc,
|
||||||
|
tLoggerToSerialPort *log);
|
||||||
|
|
||||||
|
void GsmFirmware_Start(tGsmFirmware *env);
|
||||||
|
void StartUpdateFirmware(tGsmFirmware *env);
|
||||||
|
|
||||||
|
#endif //GETGSMFIRMWARE_H
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
//
|
||||||
|
// Created by xemon on 10.07.23.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <AtGsmSimComA7600_Http.h>
|
||||||
|
#include "Gsm_HttpGet.h"
|
||||||
|
|
||||||
|
|
||||||
|
static size_t Gsm_HttpGet_Open_Dir(tAtCmd *env, char *url, size_t urlSize) {
|
||||||
|
AtCommandResult res;
|
||||||
|
|
||||||
|
res = AtGsmSimComA7600_HttpInit(env);
|
||||||
|
if (res != AT_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = AtGsmSimComA7600_HttpSetUrl(env, url, urlSize);
|
||||||
|
if (res != AT_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t responseCode;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
res = AtGsmSimComA7600_HttpMethodAction(env, eAtGsmSimComA7600_HttpMethod_GET, &responseCode, &len, 10000);
|
||||||
|
|
||||||
|
if (res != AT_OK) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (responseCode != 200) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t Gsm_HttpGet_Read_Dir(tAtCmd *env, uint8_t *data, size_t dataLimit) {
|
||||||
|
size_t read;
|
||||||
|
AtCommandResult res = AtGsmSimComA7600_HttpRead(env, data, 0, dataLimit, &read);
|
||||||
|
if (res != AT_OK) { return 0; }
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t Gsm_HttpGet_Open(tAtCmd *env, char *url, size_t urlSize) {
|
||||||
|
size_t res = 0;
|
||||||
|
if (osMutexAcquire(env->access, 2000) == osOK) {
|
||||||
|
res = Gsm_HttpGet_Open_Dir(env, url, urlSize);
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Gsm_HttpGet_Read(tAtCmd *env, uint8_t *data, size_t dataLimit) {
|
||||||
|
size_t res = 0;
|
||||||
|
if (osMutexAcquire(env->access, 2000) == osOK) {
|
||||||
|
res = Gsm_HttpGet_Read_Dir(env, data, dataLimit);
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Gsm_HttpGet_Close(tAtCmd *env) {
|
||||||
|
bool res = false;
|
||||||
|
if (osMutexAcquire(env->access, 2000) == osOK) {
|
||||||
|
res = AtGsmSimComA7600_HttpTerminate(env) == AT_OK;
|
||||||
|
osMutexRelease(env->access);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
//
|
||||||
|
// Created by cfif on 03.07.2024.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef SMART_COMPONENTS_UPDATE_GSM_HTTPGET_H
|
||||||
|
#define SMART_COMPONENTS_UPDATE_GSM_HTTPGET_H
|
||||||
|
|
||||||
|
size_t Gsm_HttpGet_Open(tAtCmd *env, char *url, size_t urlSize);
|
||||||
|
size_t Gsm_HttpGet_Read(tAtCmd *env, uint8_t *data, size_t dataLimit);
|
||||||
|
bool Gsm_HttpGet_Close(tAtCmd *env);
|
||||||
|
|
||||||
|
#endif //SMART_COMPONENTS_UPDATE_GSM_HTTPGET_H
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"cmake": {
|
||||||
|
"inc_dirs": [
|
||||||
|
"./"
|
||||||
|
],
|
||||||
|
"srcs": [
|
||||||
|
"./**.c"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue