155 lines
No EOL
3.8 KiB
C++
155 lines
No EOL
3.8 KiB
C++
#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();
|
||
} |