421 lines
14 KiB
C
421 lines
14 KiB
C
#include "cmsis_os.h"
|
||
#include "at32f435_437_clock.h"
|
||
#include "FirmwareLoader.h"
|
||
#include "FirmwareMetadataSection.h"
|
||
#include "StorageOnFlash.h"
|
||
#include "DeviceStorage.h"
|
||
#include "string.h"
|
||
#include "stdlib.h"
|
||
#include "SystemDelayInterface.h"
|
||
#include "ld_adr.h"
|
||
#include "BootJump.h"
|
||
#include "BaseTypes.h"
|
||
|
||
/*
|
||
#include "Gpios.h"
|
||
#include "Rtcs.h"
|
||
#include "SerialPorts.h"
|
||
#include "CmsisRtosThreadUtils.h"
|
||
#include "LoggerToSerialPort.h"
|
||
#include "EgtsProcessing.h"
|
||
#include "ComInt.h"
|
||
#include "aes.h"
|
||
#include "ext_telematica.h"
|
||
*/
|
||
|
||
#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;
|
||
tFirmwareLoader FIRMWARE_TELE_LOADER;
|
||
tFirmwareLoader FIRMWARE_UPDATE_LOADER;
|
||
|
||
|
||
tDeviceStorage deviceStorage;
|
||
bool resultStorage;
|
||
|
||
uint8_t findDelimiter(tString32 *address, char ch) {
|
||
|
||
for (uint8_t i = 0; i < address->length; ++i) {
|
||
if (address->data[i] == ch)
|
||
return i;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void run() {
|
||
|
||
// if (FirmwareLoader_IsLoadUpdate(&FIRMWARE_UVEOS_LOADER)) {
|
||
// bool result = FirmwareLoader_CheckAndUpdate(&FIRMWARE_UVEOS_LOADER);
|
||
// }
|
||
|
||
// if (!FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main)) {
|
||
// Сбой прошивки
|
||
// asm("nop");
|
||
// }
|
||
// FirmwareLoader_RunFirmware(&FIRMWARE_UVEOS_LOADER);
|
||
BootJumpToAddress(FIRMWARE_MAIN_ADDR);
|
||
|
||
}
|
||
|
||
/*
|
||
_Noreturn void stop() {
|
||
while (1) {
|
||
asm("nop");
|
||
}
|
||
}
|
||
|
||
#define STOP stop();
|
||
|
||
tStaticThreadBlock(1024) mainThread;
|
||
|
||
tLoggerToSerialPort slog;
|
||
tDeviceStorage deviceStorage;
|
||
tEgtsProcessing EgtsProcessing;
|
||
tGsmWithGnss gsm;
|
||
tComInt comInt;
|
||
|
||
#define LOG_SIGN "BOOT"
|
||
#define LOGGER &slog.logger
|
||
|
||
struct {
|
||
uint8_t gsmRx[1024];
|
||
uint8_t gsmTx[1024];
|
||
} mem;
|
||
|
||
tAtCmd gsmAt;
|
||
|
||
void run() {
|
||
|
||
// if (FirmwareLoader_IsLoadUpdate(&FIRMWARE_UVEOS_LOADER)) {
|
||
// bool result = FirmwareLoader_CheckAndUpdate(&FIRMWARE_UVEOS_LOADER);
|
||
// }
|
||
|
||
// if (!FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main)) {
|
||
// Сбой прошивки
|
||
// asm("nop");
|
||
// }
|
||
// FirmwareLoader_RunFirmware(&FIRMWARE_UVEOS_LOADER);
|
||
BootJumpToAddress(FIRMWARE_MAIN_ADDR);
|
||
|
||
}
|
||
|
||
bool GsmWithGnssWaitStartup(tGsmWithGnss *env) {
|
||
volatile AtCommandResult res = AT_ERROR;
|
||
if (osMutexAcquire(env->gsmAt->access, 1000) == osOK) {
|
||
res = AtCmdWaitOk(env->gsmAt, 1000, 20000);
|
||
osMutexRelease(env->gsmAt->access);
|
||
return res;
|
||
}
|
||
return res;
|
||
}
|
||
|
||
tStringStatic teDeviceModesNames[] = {
|
||
StringStaticInit("Загрузчик")
|
||
};
|
||
|
||
#define timeOutWaitConnect 30
|
||
#define timeOutWaitLoading (5 * 60)
|
||
|
||
bool resultStorage;
|
||
|
||
_Noreturn void MainThread(void *env) {
|
||
for (;;) {
|
||
|
||
LoggerToSerialPort_Init(
|
||
&slog,
|
||
0,
|
||
&SERIAL_PORTS.cliVirtualInIo,
|
||
&RTCS.rtcI0,
|
||
SERIAL_LOGGER_SHOW_AUTHOR | SERIAL_LOGGER_SHOW_LOG_LEVEL |
|
||
SERIAL_LOGGER_SHOW_TIME// | SERIAL_LOGGER_SHOW_TIME
|
||
);
|
||
|
||
tStringLink currentModeName = StringStaticGetLink(&teDeviceModesNames[0]);
|
||
tString16 alertId;
|
||
String16CopyStatic(&alertId, "BOOT");
|
||
|
||
ComInt_Init(
|
||
&comInt,
|
||
&SERIAL_PORTS.Rs485_HalfDuplexIo,
|
||
&alertId,
|
||
&SERIAL_PORTS.Modem_snif_IO,
|
||
&SERIAL_PORTS.cliVirtualOutIo,
|
||
¤tModeName
|
||
);
|
||
|
||
ComInt_StartThread(&comInt);
|
||
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Загрузчик. Начало логирования")
|
||
|
||
// bool resultStorage = DeviceStorage_Init(&deviceStorage, &NVM_STORAGE.interface);
|
||
|
||
if (!resultStorage) {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Первый запуск. Не введен адрес сервера")
|
||
}
|
||
|
||
|
||
if ((deviceStorage.nvm.SettingsServerConnection.EGTS_SERVER_ADDRESS.length == 0) ||
|
||
(deviceStorage.nvm.SettingsServerConnection.EGTS_GPRS_APN.length == 0)) {
|
||
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход. Не введен адрес сервера или apn")
|
||
|
||
run();
|
||
}
|
||
|
||
if (deviceStorage.nvm.SettingsServerConnection.EGTS_FLEET_ON == 0) {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход. Телематика отключена")
|
||
run();
|
||
}
|
||
|
||
uint32_t timeOutWaitAuth = 30;
|
||
|
||
if (deviceStorage.nvm.SettingsServerConnection.EGTS_TIME_WAIT_FIRMWARE > timeOutWaitAuth)
|
||
timeOutWaitAuth = deviceStorage.nvm.SettingsServerConnection.EGTS_TIME_WAIT_FIRMWARE;
|
||
|
||
GpioPinEnable(&GPIOS.standby);
|
||
GpioPinEnable(&GPIOS.enable);
|
||
GpioPinEnable(&GPIOS.PowerRS485);
|
||
|
||
AtCmdInit(
|
||
&gsmAt, &SERIAL_PORTS.Modem_IO,
|
||
mem.gsmTx, sizeof(mem.gsmTx),
|
||
mem.gsmRx, sizeof(mem.gsmRx),
|
||
2000, 2000
|
||
);
|
||
|
||
GsmWithGnssInit(&gsm,
|
||
&slog,
|
||
&gsmAt,
|
||
&RTCS.rtcI0);
|
||
|
||
EgtsProcessing_Init(
|
||
&EgtsProcessing,
|
||
&gsm,
|
||
&deviceStorage,
|
||
&RTCS.rtcI0,
|
||
&slog
|
||
);
|
||
|
||
PwmSim7600e_Startup(&GPIOS.sim7600);
|
||
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ожидание загрузки модема")
|
||
bool result = GsmWithGnssWaitStartup(&gsm);
|
||
if (result) {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ответ от модема получен")
|
||
} else {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Ошибка. Нет ответа от модема")
|
||
run();
|
||
}
|
||
|
||
|
||
GsmWithGnss_start(&gsm);
|
||
|
||
EgtsProcessing_Start(&EgtsProcessing);
|
||
|
||
uint32_t timeWaitConnect = SystemGetMs() + timeOutWaitConnect * 1000;
|
||
uint32_t timeWaitAuth = SystemGetMs() + timeOutWaitAuth * 1000;
|
||
uint32_t timeWaitLoad = SystemGetMs() + timeOutWaitLoading * 1000;
|
||
|
||
for (;;) {
|
||
|
||
// Если не было соединения
|
||
if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_INIT) {
|
||
uint32_t time = SystemGetMs();
|
||
if (timeWaitConnect < SystemGetMs()) {
|
||
LoggerFormatInfo(LOGGER, LOG_SIGN,
|
||
"Выход по таймеру: Не было соединения с сервером в течении %d сек",
|
||
timeOutWaitConnect)
|
||
run();
|
||
}
|
||
}
|
||
|
||
// Если не было соединения
|
||
if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_ERR_CON) {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN,
|
||
"Выход: Не было соединения с сервером. Все попытки соединения были исчерпаны")
|
||
run();
|
||
}
|
||
|
||
|
||
// Если не было обновления после соединения
|
||
if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_AUTH) {
|
||
if (timeWaitAuth < SystemGetMs()) {
|
||
LoggerFormatInfo(LOGGER, LOG_SIGN,
|
||
"Выход по таймеру: Не было обновления после соединения с сервером в течении %d сек",
|
||
timeOutWaitAuth)
|
||
EgtsProcessingCloseConnection(&EgtsProcessing);
|
||
run();
|
||
}
|
||
}
|
||
|
||
// Если в процессе обновления больше
|
||
if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_LOADING) {
|
||
if (timeWaitLoad < SystemGetMs()) {
|
||
LoggerFormatInfo(LOGGER, LOG_SIGN, "Выход по таймеру: Процесс обновления занял больше, %d сек",
|
||
timeOutWaitLoading)
|
||
EgtsProcessingCloseConnection(&EgtsProcessing);
|
||
run();
|
||
}
|
||
}
|
||
|
||
if (EgtsProcessing.egtsLoaderUpdate == EGTS_LOADER_END_LOADING) {
|
||
LoggerInfoStatic(LOGGER, LOG_SIGN, "Выход по обновлению")
|
||
|
||
SystemDelayMs(1000);
|
||
|
||
EgtsProcessingCloseConnection(&EgtsProcessing);
|
||
run();
|
||
}
|
||
|
||
SystemDelayMs(1000);
|
||
}
|
||
}
|
||
}
|
||
*/
|
||
int main(void) {
|
||
system_clock_config();
|
||
crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
|
||
crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
|
||
/*
|
||
gpio_init_type GPIOInit;
|
||
|
||
gpio_default_para_init(&GPIOInit);
|
||
GPIOInit.gpio_mode = GPIO_MODE_OUTPUT;
|
||
GPIOInit.gpio_pull = GPIO_PULL_NONE;
|
||
GPIOInit.gpio_pins = GPIO_PINS_3;
|
||
gpio_init(GPIOD, &GPIOInit);
|
||
gpio_bits_reset(GPIOD, GPIO_PINS_3);
|
||
|
||
gpio_default_para_init(&GPIOInit);
|
||
GPIOInit.gpio_mode = GPIO_MODE_OUTPUT;
|
||
GPIOInit.gpio_pull = GPIO_PULL_NONE;
|
||
GPIOInit.gpio_pins = GPIO_PINS_7;
|
||
gpio_init(GPIOB, &GPIOInit);
|
||
gpio_bits_reset(GPIOB, GPIO_PINS_7);
|
||
*/
|
||
// osKernelInitialize();
|
||
|
||
// Gpios_Init();
|
||
|
||
// SerialPorts_Init(&GPIOS.comIntDir);
|
||
StorageOnFlash_Init();
|
||
// Rtcs_Init();
|
||
|
||
resultStorage = DeviceStorage_Init(&deviceStorage, &NVM_STORAGE.interface);
|
||
|
||
if (deviceStorage.nvm.SettingsServerConnection.REGION_SIZE_UPDATE <= FIRMWARE_MAIN_AREA_LENGTH) {
|
||
|
||
FirmwareLoader_Init(&FIRMWARE_UVEOS_LOADER, FIRMWARE_MAIN_AREA_LENGTH, FIRMWARE_MAIN_ADDR,
|
||
FIRMWARE_TELE_RECOVERY_ADDR);
|
||
|
||
FirmwareLoader_Init(&FIRMWARE_TELE_LOADER, FIRMWARE_TELE_AREA_LENGTH, FIRMWARE_TELE_MAIN_ADDR,
|
||
FIRMWARE_TELE_RECOVERY_ADDR);
|
||
|
||
bool is_FW_UVEOS_main = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main);
|
||
bool is_FW_TELE_main = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.main);
|
||
|
||
|
||
FirmwareLoader_Init(&FIRMWARE_UPDATE_LOADER, deviceStorage.nvm.SettingsServerConnection.REGION_SIZE_UPDATE, 0,
|
||
FIRMWARE_TELE_RECOVERY_ADDR);
|
||
bool is_update = FirmwareLoader_CheckBlock(&FIRMWARE_UPDATE_LOADER, &FIRMWARE_UVEOS_LOADER.update);
|
||
|
||
// Есть обновление
|
||
if (is_update) {
|
||
|
||
tString32 FW_NAME;
|
||
FW_NAME.length = *FIRMWARE_UVEOS_LOADER.update.metadata.nameLength;
|
||
memcpy(FW_NAME.data, FIRMWARE_UVEOS_LOADER.update.metadata.name, FW_NAME.length);
|
||
|
||
uint8_t posDel = findDelimiter(&FW_NAME, '_') + 1;
|
||
|
||
// Получена прошивка телематики
|
||
if (memcmp(&FW_NAME.data[posDel], "TELE", 4) == 0) {
|
||
|
||
bool is_FW_TELE_update = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.update);
|
||
|
||
// Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка
|
||
bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&FIRMWARE_TELE_LOADER);
|
||
|
||
if ((!is_FW_TELE_main) || (isNewFirmware)) {
|
||
FirmwareLoader_CopyUpdateToMain(&FIRMWARE_TELE_LOADER);
|
||
is_FW_TELE_main = FirmwareLoader_CheckBlock(&FIRMWARE_TELE_LOADER, &FIRMWARE_TELE_LOADER.main);
|
||
|
||
if (is_FW_TELE_main == false) {
|
||
// Ошибка обновления Телематики
|
||
}
|
||
|
||
asm("nop");
|
||
|
||
}
|
||
|
||
asm("nop");
|
||
|
||
// Получена прошивка УВЭОС
|
||
} else if (memcmp(&FW_NAME.data[posDel], "UVEOS", 5) == 0) {
|
||
|
||
bool is_FW_UVEOS_update = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.update);
|
||
|
||
// Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка
|
||
bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&FIRMWARE_UVEOS_LOADER);
|
||
|
||
// Если текущая прошивка неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка
|
||
if ((!is_FW_UVEOS_main) || (isNewFirmware)) {
|
||
FirmwareLoader_CopyUpdateToMain(&FIRMWARE_UVEOS_LOADER);
|
||
is_FW_UVEOS_main = FirmwareLoader_CheckBlock(&FIRMWARE_UVEOS_LOADER, &FIRMWARE_UVEOS_LOADER.main);
|
||
|
||
if (is_FW_UVEOS_main == false) {
|
||
// Ошибка обновления УВЭОС
|
||
}
|
||
|
||
asm("nop");
|
||
}
|
||
|
||
asm("nop");
|
||
|
||
// Получена прошивка ключей
|
||
} else if (memcmp(&FW_NAME.data[0], "CERT", 4) == 0) {
|
||
asm("nop");
|
||
// Получена неизвестная прошивка
|
||
} else {
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
run();
|
||
|
||
/*
|
||
if (deviceStorage.nvm.SettingsServerConnection.EGTS_FLEET_ON == true) {
|
||
|
||
bool isTelematica = loadMetaTelematica();
|
||
|
||
if (isTelematica) {
|
||
run();
|
||
} else {
|
||
|
||
}
|
||
|
||
} else {
|
||
run();
|
||
}
|
||
|
||
|
||
// Если включен модуль телематики, пытаемся загрузить телематику из загрузчика
|
||
|
||
FirmwareLoader_Init(&FIRMWARE_TELE_LOADER, FIRMWARE_TELE_AREA_LENGTH, FIRMWARE_TELE_MAIN_ADDR,
|
||
FIRMWARE_TELE_RECOVERY_ADDR);
|
||
|
||
InitThreadBlock(mainThread, "main", osPriorityNormal);
|
||
ThreadBlock_Start(mainThread, 0, MainThread);
|
||
|
||
osKernelStart();
|
||
*/
|
||
}
|