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

155 lines
No EOL
3.8 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 "flash.h"
#include <stdbool.h>
static uint32_t write_ptr = SECTOR_6;
void flash_unlock(){
// Check if flash is locked
if(!(FLASH->CR & FLASH_CR_LOCK)) {
return; // Already unlocked
}
// Write flash key sequence to unlock
FLASH->KEYR = 0x45670123; // First key
FLASH->KEYR = 0xCDEF89AB; // Second key
}
void flash_lock() {
if(FLASH->CR & FLASH_CR_LOCK) {
return; // Already locked
}
FLASH->CR |= FLASH_CR_LOCK; // Lock flash memory
}
void erase_sector(uint8_t sector){
// Wait if flash is busy
while(FLASH_BUSY);
// Check if flash is locked and unlock if needed
if(FLASH->CR & FLASH_CR_LOCK) {
flash_unlock();
}
// Set sector erase bit and sector number
FLASH->CR |= FLASH_CR_SER;
FLASH->CR &= ~FLASH_CR_SNB;
FLASH->CR |= (sector << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk;
// Start erase
FLASH->CR |= FLASH_CR_STRT;
// Wait for erase to complete
while(FLASH_BUSY);
// Clear sector erase bit
FLASH->CR &= ~FLASH_CR_SER;
}
void flash_program_word(uint32_t address,uint32_t data,uint32_t byte_len){
// Wait if flash is busy
while(FLASH_BUSY);
// Check if flash is locked and unlock if needed
if(FLASH->CR & FLASH_CR_LOCK) {
flash_unlock();
}
// Set program bit 32bit programm size and Write data to address
if(byte_len == 1) {
FLASH_8BYTE;
FLASH->CR |= FLASH_CR_PG;
*(volatile uint8_t*)address = (uint8_t)data;
} else {
FLASH_32BYTE;
FLASH->CR |= FLASH_CR_PG;
*(volatile uint32_t*)address = data;
}
// Wait for programming to complete
while(FLASH_BUSY);
// Clear program bit
FLASH->CR &= ~FLASH_CR_PG;
}
void flash_write(uint32_t addr, FLASH_RECORD* record){
uint32_t* data = (uint32_t*)record;
uint32_t size = FLASH_RECORD_SIZE / 4; //count words in struct
// Wait if flash is busy
while(FLASH_BUSY);
// Check if flash is locked and unlock if needed
if(FLASH->CR & FLASH_CR_LOCK) {
flash_unlock();
}
// Set program bit and write data to flash
FLASH_32BYTE;
FLASH->CR |= FLASH_CR_PG;
for(int i = 0;i < size;i++){
*(volatile uint32_t*)(addr + i * 4) = data[i];
}
// Clear program bit
FLASH->CR &= ~FLASH_CR_PG;
flash_lock();
}
// Wait if flash
bool validate_crc(FLASH_RECORD* crc){
if(crc->crc == 0x6933)
return true;
return false;
}
/* read struct from FLASH */
void flash_read(uint32_t addr,FLASH_RECORD* ptr){
uint32_t* flash_ptr = (uint32_t*)addr;
uint32_t* dest = (uint32_t*)ptr;
for (int i = 0; i < FLASH_RECORD_SIZE / 4; i++) {
dest[i] = flash_ptr[i];
}
}
/* Поиск актуального адреса во флэш памяти */
FLASH_RECORD load_params(){
__disable_irq();
FLASH_RECORD latest = {0};
FLASH_RECORD res;
for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) {
flash_read(addr,&res);
if (!validate_crc(&res))
break;
else if(res.data_id == addr_id) {
latest = res;
}
}
__enable_irq();
return latest;
}
/**
* @brief Записывает страницу данных во флеш-память
* @param data: Указатель на буфер с данными
* @param len: Длина данных в байтах (должна быть кратна 4)
* @retval bool: true - успех, false - ошибка
*/
void write_flash_page(const uint8_t* data, uint16_t len) { // Добавлен const
flash_unlock();
for (uint16_t i = 0; i < len; i += 4) {
uint32_t word;
memcpy(&word, &data[i], 4); // Безопасное копирование
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, write_ptr + i, word);
}
flash_lock();
}