servo/controller/fw/embed/bootloader/main.cpp
2025-03-17 15:43:34 +03:00

146 lines
No EOL
4.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <Arduino.h>
#include <STM32_CAN.h>
#include "flash.h"
STM32_CAN Can(CAN2, DEF);
volatile bool fw_update = false;
volatile uint32_t fw_size = 0;
volatile uint32_t fw_crc = 0;
volatile uint32_t write_ptr = APP_ADDRESS;
static FLASH_RECORD flash_record = {0};
// Прототипы функций
void jump_to_app();
void process_can_message(const CAN_message_t &msg);
void erase_flash_pages();
bool verify_firmware();
void send_ack(uint8_t status);
void setup() {
// Инициализация периферии
Serial.begin(115200);
Can.begin(1000000); // 1 Mbps
Can.setFilter(0,BOOT_CAN_ID,STD);
// Настройка GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
GPIOC->MODER |= GPIO_MODER_MODE10_0 | GPIO_MODER_MODE11_0;
GPIOC->ODR |= GPIO_ODR_OD11;
// Проверка флага обновления
/*erase_sector(6);
flash_program_word(FLAG_BOOT,0xDEADBEEF,0);
flash_record.data_id = addr_id;
flash_record.crc = 0x6933;
flash_record.value = 0x69;
flash_record.write_ptr_now = SECTOR_6;*/
flash_write(SECTOR_6, &flash_record);
flash_record = load_params();
/* Добавить проверку адреса, т.е во время отправки запроса прошивки по CAN
мы сохраняем как флаг, так и аддрес устройства к которому будет обращатлься во
время прошивки */
if(*(volatile uint32_t*)(FLAG_BOOT) == UPDATE_FLAG) {
fw_update = true;
GPIOC->ODR |= GPIO_ODR_OD10; // Индикация обновления
erase_flash_pages();
} else {
jump_to_app();
}
}
void loop() {
if(fw_update) {
CAN_message_t msg;
if(Can.read(msg)) {
process_can_message(msg);
}
}
}
void process_can_message(const CAN_message_t &msg) {
switch(msg.id) {
case BOOT_CAN_ID:
if(msg.buf[0] == 0x01) { // Старт передачи
fw_size = *(uint32_t*)&msg.buf[1]; //размер прошивки тип 4 байта
fw_crc = *(uint32_t*)&msg.buf[5]; //crc
write_ptr = APP_ADDRESS;
send_ack(0x01);
}
break;
case DATA_CAN_ID: // Пакет данных
if(write_ptr < (APP_ADDRESS + fw_size)) {
write_flash_page((const uint8_t*)msg.buf, msg.len);
write_ptr += msg.len;
send_ack(0x02);
}
break;
case BOOT_CAN_END: // Завершение передачи
if(verify_firmware()) {
erase_sector(7); // Сброс флага
send_ack(0xAA);
NVIC_SystemReset();
} else {
send_ack(0x55);
}
break;
}
}
void jump_to_app() {
typedef void (*app_entry_t)(void);
auto app_entry = (app_entry_t)(*(volatile uint32_t*)(APP_ADDRESS + 4));
// SCB->VTOR = APP_ADDRESS;
__set_MSP(*(volatile uint32_t*)APP_ADDRESS);
app_entry();
}
void erase_flash_pages() {
FLASH_EraseInitTypeDef erase;
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
erase.Sector = FLASH_SECTOR_1;
erase.NbSectors = 5;
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
uint32_t error;
flash_unlock();
HAL_FLASHEx_Erase(&erase, &error);
flash_lock();
}
// CRC16 implementation for STM32
uint16_t CalculateCRC16(const uint8_t* data, uint32_t length) {
uint16_t crc = 0xFFFF;
while (length--) {
crc ^= (uint16_t)(*data++) << 8;
for(uint8_t i = 0; i < 8; i++) {
crc = crc & 0x8000 ? (crc << 1) ^ 0x8005 : crc << 1;
}
}
return crc;
}
bool verify_firmware() {
uint32_t calculated_crc = 0;
calculated_crc = CalculateCRC16((uint8_t*)fw_crc,fw_size);
if(calculated_crc != (uint16_t)fw_crc)
return false;
// Реализация проверки CRC
// ...
// return (calculated_crc == fw_crc);
return true;
}
void send_ack(uint8_t status) {
CAN_message_t ack;
ack.id = BOOT_CAN_ID + 2;
ack.len = 1;
ack.buf[0] = status;
Can.write(ack);
}