183 lines
5.7 KiB
C
183 lines
5.7 KiB
C
//
|
||
// Created by cfif on 22.09.2025.
|
||
//
|
||
#include "Clock.h"
|
||
#include "LoggerToSerialPort.h"
|
||
#include "LoggerInterface.h"
|
||
#include "StorageOnFlash.h"
|
||
#include "Rtcs.h"
|
||
#include "SerialPorts.h"
|
||
#include "CmsisRtosThreadUtils.h"
|
||
#include "SystemDelayInterface.h"
|
||
#include "DeviceStorage.h"
|
||
#include "BootJump.h"
|
||
#include "FirmwareLoader.h"
|
||
|
||
#define BOOT_AREA_LENGTH (256 * 1024) // Размер загрузчика
|
||
#define FIRMWARE_MAIN_AREA_LENGTH (512 * 1024) // Размер основной программы
|
||
#define FIRMWARE_MAIN_ADDR (0x01000000 + BOOT_AREA_LENGTH) // Адрес основной программы
|
||
#define FIRMWARE_MAIN_UPDATE_ADDR 0x01100000 // Адрес основной программы (обновление)
|
||
|
||
typedef struct {
|
||
tLoggerToSerialPort slog;
|
||
tDeviceStorage storage;
|
||
tFirmwareLoader FIRMWARE_HVAC;
|
||
|
||
struct {
|
||
osThreadId_t id;
|
||
uint32_t stack[2048];
|
||
StaticTask_t controlBlock;
|
||
osThreadAttr_t attr;
|
||
} thread;
|
||
|
||
} tBootMma;
|
||
|
||
tBootMma MAIN_BOOT_ENV;
|
||
|
||
#define LOGGER &MAIN_ENV.slog.logger
|
||
#define LOG_SIGN "Boot"
|
||
|
||
_Noreturn void stop() {
|
||
while (1) {
|
||
asm("nop");
|
||
}
|
||
}
|
||
|
||
#define STOP stop();
|
||
|
||
#if (configCHECK_FOR_STACK_OVERFLOW > 0)
|
||
|
||
void vApplicationStackOverflowHook(TaskHandle_t xTask, const char *pcTaskName) {
|
||
PROCESS_UNUSED_VAR(xTask);
|
||
PROCESS_UNUSED_VAR(pcTaskName);
|
||
STOP
|
||
}
|
||
|
||
#endif
|
||
|
||
const DMA_InitType dmaInitCfg =
|
||
{
|
||
.eArbitrationAlgorithm = DMA_ARBITRATION_ALGORITHM_FIXED_PRIORITY,
|
||
.bHaltOnError = false
|
||
};
|
||
|
||
static _Noreturn void MainTransmitter_Thread(tBootMma *env) {
|
||
|
||
DMA_Init(DMA_INSTANCE_0, &dmaInitCfg);
|
||
Rtcs_Init();
|
||
|
||
// Настройка таймера реального времени
|
||
time_t set_timestamp = 0;
|
||
RtcSet(&RTCS.rtcI0, &set_timestamp);
|
||
|
||
SerialPorts_Init();
|
||
|
||
LoggerToSerialPort_Init(
|
||
&env->slog,
|
||
0,
|
||
&SERIAL_PORTS.cliVirtualPortOut_Io,
|
||
&SERIAL_PORTS.SerialPortLog_IO,
|
||
&RTCS.rtcI0,
|
||
SERIAL_LOGGER_SHOW_TIME | SERIAL_LOGGER_SHOW_AUTHOR | SERIAL_LOGGER_SHOW_LOG_LEVEL,
|
||
5
|
||
);
|
||
|
||
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Start logging")
|
||
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Initialization of subsystems")
|
||
|
||
// StorageOnFlash_Init(&env->slog.logger);
|
||
|
||
// NVM_STORAGE.nf_storage_param.logger = &env->slog.logger;
|
||
// NVM_STORAGE.nf_storage_calib.logger = &env->slog.logger;
|
||
// bool result = DeviceStorage_Init(&env->storage, true, &NVM_STORAGE.interface_calib, &NVM_STORAGE.interface_param,
|
||
// &env->slog.logger);
|
||
|
||
|
||
FirmwareLoader_Init(&env->FIRMWARE_HVAC, FIRMWARE_MAIN_AREA_LENGTH, FIRMWARE_MAIN_ADDR,
|
||
FIRMWARE_MAIN_UPDATE_ADDR);
|
||
|
||
bool isMain = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.main);
|
||
|
||
if (isMain) {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum is correct")
|
||
} else {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum is not correct")
|
||
|
||
if (*env->FIRMWARE_HVAC.main.metadata.crc == 0) {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware: Checksum not found (The program may have been flashed using JTAG ?)")
|
||
}
|
||
}
|
||
|
||
bool isUpdate = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.update);
|
||
|
||
if (isUpdate) {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Recovery firmware: Checksum is correct")
|
||
} else {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Recovery firmware: Checksum is not correct")
|
||
}
|
||
|
||
// Есть обновление
|
||
if (isUpdate) {
|
||
|
||
// Если текущая прошивка (isMain) неисправна (не загружена) или в секции обновления находится отличная от текущей прошивка
|
||
bool isNewFirmware = FirmwareLoader_IsUpdateAndMainAreDifferent(&env->FIRMWARE_HVAC);
|
||
|
||
// !isMain - Не совпадает crc основной прошивки isNewFirmware - есть рабочая прошивка в обновлении, которая отличается от основной (main)
|
||
if ((!isMain) || (isNewFirmware)) {
|
||
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Update detected")
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Starting the update process")
|
||
|
||
// Обновление
|
||
FirmwareLoader_CopyUpdateToMain(&env->FIRMWARE_HVAC);
|
||
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Update complete")
|
||
|
||
// Проверка crc
|
||
isMain = FirmwareLoader_CheckBlock(&env->FIRMWARE_HVAC, &env->FIRMWARE_HVAC.main);
|
||
|
||
if (isMain) {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware (after update): Checksum is correct")
|
||
} else {
|
||
LoggerInfoStatic(&env->slog.logger, LOG_SIGN, "Main firmware (after update): Checksum is not correct")
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
SystemDelayMs(10);
|
||
|
||
BootJumpToAddress(FIRMWARE_MAIN_ADDR);
|
||
|
||
for (;;) {
|
||
SystemDelayMs(1000);
|
||
}
|
||
}
|
||
|
||
|
||
void MainTransmitter_StartThread(tBootMma *env) {
|
||
if (!env->thread.id) {
|
||
env->thread.id = osThreadNew((osThreadFunc_t) (MainTransmitter_Thread), (void *) (env), &env->thread.attr);
|
||
}
|
||
}
|
||
|
||
int main(void) {
|
||
Bsp_CLOCK_Init();
|
||
|
||
NVIC_SetPriorityGrouping(NVIC_PRIORITY_GROUP_4);
|
||
|
||
osKernelInitialize();
|
||
|
||
tBootMma *env = &MAIN_BOOT_ENV;
|
||
|
||
InitThreadAtrStatic(&env->thread.attr, "BootMma", env->thread.controlBlock, env->thread.stack,
|
||
osPriorityNormal);
|
||
|
||
MainTransmitter_StartThread(env);
|
||
|
||
osKernelStart();
|
||
|
||
STOP
|
||
} |