servo/controller/fw/bootloader/src/main.cpp
2025-06-16 00:31:26 +03:00

171 lines
No EOL
4.7 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 bool app_valid = false;
volatile uint32_t fw_size = 0;
volatile uint16_t fw_crc = 0;
volatile uint32_t jump;
static FLASH_RECORD *flash_record = {0};
static uint32_t ptr_flash;
volatile uint32_t msg_id;
volatile uint16_t id_x;
volatile uint8_t msg_ch;
// Прототипы функций
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);
bool is_app_valid();
void setup() {
Serial.setRx(HARDWARE_SERIAL_RX_PIN);
Serial.setTx(HARDWARE_SERIAL_TX_PIN);
Serial.begin(115200);
Can.begin();
Can.setBaudRate(1000000);
TIM_TypeDef *Instance = TIM2;
HardwareTimer *SendTimer = new HardwareTimer(Instance);
SendTimer->setOverflow(100, HERTZ_FORMAT); // 50 Hz
SendTimer->resume();
Can.setFilter(0, 0, STD);
// Настройка GPIO
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
GPIOC->MODER |= GPIO_MODER_MODE10_0 | GPIO_MODER_MODE11_0;
GPIOC->ODR &= ~GPIO_ODR_OD11;
GPIOC->ODR |= GPIO_ODR_OD10;
flash_record = load_params();
if(flash_record[firmw].value == UPDATE_FLAG) {
fw_update = true;
for(int i = 0; i < 5;i++){
GPIOC->ODR ^= GPIO_ODR_OD10; // Indecate message
delay(100);
}
// write_param(firmw,0); //reset flasg
erase_flash_pages();
}
else{
// for st-link update, because he doesnt reset flag_update
if(is_app_valid()) jump_to_app(); //firmware exist
else fw_update = true; //firmware doesnt exist, but we in bootloader
}
GPIOC->ODR |= GPIO_ODR_OD10;
}
void process_can_message(const CAN_message_t &msg) {
msg_id = msg.id;
/* 0x697
69 - slave addr
7 || 8 - REG_READ or REG_WRITE */
id_x = (msg_id >> 4) & 0xFFFF; // saved address
msg_ch = msg_id & 0xF; // saved id
if(id_x == flash_record[addr_id].value){
switch(msg_ch) {
case BOOT_CAN_ID:
if(msg.buf[0] == 0x01) { // start transfer
fw_size = *(uint32_t*)&msg.buf[1]; //size of firmware
fw_crc = *(uint16_t*)&msg.buf[5]; //crc
ptr_flash = APP_ADDRESS;
send_ack(0x01);
}
break;
case DATA_CAN_ID: // Data packet
if(ptr_flash < (APP_ADDRESS + fw_size)) {
write_flash_page((const uint8_t*)msg.buf, msg.len);
ptr_flash += msg.len;
send_ack(0x02);
}
break;
case BOOT_CAN_END: // End of transfer
if(verify_firmware()) {
send_ack(0xAA);
write_param(firmw,0); //reset flag set 0
fw_update = false; //reset flag
// erase_sector(7);
delay(500);
NVIC_SystemReset();
} else {
send_ack(0x55);
erase_flash_pages(); //if error
}
break;
}
}
}
void jump_to_app() {
__disable_irq();
jump = *(volatile uint32_t*)(APP_ADDRESS + 4);
void (*app_entry)(void);
app_entry = (void (*)(void))jump;
for (uint32_t i = 0; i < 8; i++) {
NVIC->ICPR[i] = 0xFFFFFFFF;
}
__set_MSP(*(volatile uint32_t*)APP_ADDRESS);
// SCB->VTOR = (uint32_t)0x08008004;
app_entry();
}
bool verify_firmware() {
uint16_t calculated_crc = 0;
calculated_crc = validate_crc16((uint8_t*)APP_ADDRESS,fw_size);
return (calculated_crc == fw_crc);
}
void send_ack(uint8_t status) {
CAN_message_t ack;
ack.id = ACK_CAN_ID;
ack.len = 1;
ack.buf[0] = status;
Can.write(ack);
}
bool is_app_valid() {
volatile uint32_t* app_vector = (volatile uint32_t*)APP_ADDRESS;
// Check stack pointer
bool sp_valid = (app_vector[0] >= 0x20000000) &&
(app_vector[0] <= (0x20000000 + 128*1024)); // Для STM32 с 128K RAM
// check reset_handler
bool pc_valid = (app_vector[1] >= 0x08000000) &&
(app_vector[1] <= (0x08000000 + 1024*1024)); // Для 1MB Flash
// check two words on reset value
bool not_erased = (app_vector[0] != 0xFFFFFFFF) &&
(app_vector[1] != 0xFFFFFFFF);
return sp_valid && pc_valid && not_erased;
}
void loop() {
if(fw_update) {
CAN_message_t msg;
while(Can.read(msg))
process_can_message(msg);
}
}