125 lines
5.5 KiB
C++
125 lines
5.5 KiB
C++
#include "EEPROM.h"
|
|
#include "mik32_hal_eeprom.h"
|
|
#include "mik32_hal.h"
|
|
|
|
HAL_EEPROM_HandleTypeDef heeprom;
|
|
|
|
|
|
void EEPROMClass:: begin()
|
|
{
|
|
heeprom.Instance = EEPROM_REGS;
|
|
heeprom.Mode = HAL_EEPROM_MODE_TWO_STAGE;
|
|
heeprom.ErrorCorrection = HAL_EEPROM_ECC_ENABLE;
|
|
heeprom.EnableInterrupt = HAL_EEPROM_SERR_DISABLE;
|
|
|
|
HAL_EEPROM_Init(&heeprom);
|
|
HAL_EEPROM_CalculateTimings(&heeprom, OSC_SYSTEM_VALUE);
|
|
}
|
|
|
|
uint8_t read_byte( int idx )
|
|
{
|
|
// Проверка адекватности адреса idx
|
|
if (idx < 0)
|
|
{
|
|
idx = -idx;
|
|
ErrorMsgHandler("EEPROM.read(): The eeprom cell address must be non-negative");
|
|
}
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
{
|
|
idx = (int)((uint32_t)idx % EEPROM_LENGHT);
|
|
ErrorMsgHandler("EEPROM.read(): The address of the eeprom cell goes beyond the eeprom");
|
|
}
|
|
|
|
uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {};
|
|
|
|
// Вычисление адреса начала нужной страницы
|
|
uint32_t addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_PAGE_SIZE) * EEPROM_PAGE_SIZE;
|
|
// Чтение нужной страницы
|
|
HAL_EEPROM_Read(&heeprom, (uint16_t)addr, read_data_buf, EEPROM_PAGE_WORDS, EEPROM_OP_TIMEOUT);
|
|
// Адрес искомого слова в eeprom: EEPROM_START_ADDR + (uint32_t)idx
|
|
uint32_t word_addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_WORD_SIZE) * EEPROM_WORD_SIZE;
|
|
// Индекс искомого слова в массиве read_data_buf: адрес слова в eeprom за вычетом адреса начала страницы
|
|
uint32_t word_idx = (word_addr - addr) / EEPROM_WORD_SIZE;
|
|
// Номер байта в составе слова
|
|
uint32_t byte_idx = ((uint32_t)idx) % EEPROM_WORD_SIZE;
|
|
// Вычленение нужного байта из страницы
|
|
return (uint8_t)(( read_data_buf[word_idx] & (((uint32_t)0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)) ) >> ((EEPROM_WORD_SIZE - byte_idx - 1) * 8));
|
|
}
|
|
|
|
void write_byte( int idx, uint8_t val )
|
|
{
|
|
// Проверка адекватности адреса idx
|
|
if (idx < 0)
|
|
{
|
|
idx = -idx;
|
|
ErrorMsgHandler("EEPROM.write(): The eeprom cell address must be non-negative");
|
|
}
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
{
|
|
idx = (int)((uint32_t)idx % EEPROM_LENGHT);
|
|
ErrorMsgHandler("EEPROM.write(): The address of the eeprom cell goes beyond the eeprom");
|
|
}
|
|
update_byte(idx, val);
|
|
}
|
|
|
|
// Делает то же, что и write, но записывает только если новый байт отличается от уже записанного
|
|
void update_byte( int idx, uint8_t val )
|
|
{
|
|
// Проверка адекватности адреса idx
|
|
if (idx < 0)
|
|
{
|
|
idx = -idx;
|
|
ErrorMsgHandler("EEPROM.update(): The eeprom cell address must be non-negative");
|
|
}
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
{
|
|
idx = (int)((uint32_t)idx % EEPROM_LENGHT);
|
|
ErrorMsgHandler("EEPROM.update(): The address of the eeprom cell goes beyond the eeprom");
|
|
}
|
|
|
|
uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {};
|
|
|
|
// Вычисление адреса начала нужной страницы
|
|
uint32_t addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_PAGE_SIZE) * EEPROM_PAGE_SIZE;
|
|
// Читаем нужную страницу
|
|
HAL_EEPROM_Read(&heeprom, (uint16_t)addr, write_data_buf, EEPROM_PAGE_WORDS, EEPROM_OP_TIMEOUT);
|
|
// Адрес искомого слова в eeprom: EEPROM_START_ADDR + (uint32_t)idx
|
|
uint32_t word_addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_WORD_SIZE) * EEPROM_WORD_SIZE;
|
|
// Индекс искомого слова в массиве write_data_buf: адрес слова в eeprom за вычетом адреса начала страницы
|
|
uint32_t word_idx = (word_addr - addr) / EEPROM_WORD_SIZE;
|
|
// Номер байта в составе слова
|
|
uint32_t byte_idx = ((uint32_t)idx) % EEPROM_WORD_SIZE;
|
|
// Извлечение нужного байта
|
|
uint32_t byte = ((uint32_t)val) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8);
|
|
uint8_t oldVal = (uint8_t)(*((uint8_t*)write_data_buf + word_idx * EEPROM_WORD_SIZE + (EEPROM_WORD_SIZE - byte_idx - 1)));
|
|
// Проверка того, что записанный байт отличается от нового
|
|
if(oldVal != val)
|
|
{
|
|
// Очистка нужной страницы
|
|
HAL_EEPROM_Erase(&heeprom, (uint16_t)addr, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
// Вычленение и замена нужного байта из страницы
|
|
write_data_buf[word_idx] = (write_data_buf[word_idx] & (~((uint32_t)(0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1) * 8)))) | byte;
|
|
|
|
HAL_EEPROM_Write(&heeprom, (uint16_t)addr, write_data_buf, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
// uint16_t EEPROMClass:: length( void )
|
|
// {
|
|
// return (uint16_t)EEPROM_LENGHT;
|
|
// }
|
|
|
|
void HAL_read(uint16_t addr, uint32_t * data)
|
|
{
|
|
HAL_EEPROM_Read(&heeprom, (uint16_t)addr, data, EEPROM_PAGE_WORDS, EEPROM_OP_TIMEOUT);
|
|
}
|
|
|
|
void HAL_write(uint16_t addr, uint32_t * data)
|
|
{
|
|
HAL_EEPROM_Write(&heeprom, (uint16_t)addr, data, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
}
|
|
|
|
void HAL_erase(uint16_t addr)
|
|
{
|
|
HAL_EEPROM_Erase(&heeprom, (uint16_t)addr, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
} |