servo/controller/fw/embed/bootloader/flash.cpp

156 lines
3.9 KiB
C++
Raw Normal View History

#include "flash.h"
2025-03-17 15:43:34 +03:00
#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;
}
2025-03-17 15:43:34 +03:00
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
2025-03-17 15:43:34 +03:00
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];
}
2025-03-17 15:43:34 +03:00
}
2025-03-17 15:43:34 +03:00
/* Поиск актуального адреса во флэш памяти */
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;
/* нашли адрес */
2025-03-17 15:43:34 +03:00
else if(res.data_id == addr_id) {
latest = res;
}
}
2025-03-17 15:43:34 +03:00
__enable_irq();
return latest;
}
2025-03-17 15:43:34 +03:00
/**
* @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();
}