elbear_arduino_bsp/libraries/EEPROM/src/EEPROM.cpp

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);
}