145 lines
7.3 KiB
C++
145 lines
7.3 KiB
C++
#include "EEPROM.h"
|
|
#include "mik32_hal_eeprom.h"
|
|
|
|
#define EEPROM_OP_TIMEOUT 100000
|
|
#define EEPROM_PAGE_WORDS 32
|
|
#define EEPROM_PAGE_COUNT 8 // КОличество страниц пользовательской EEPROM
|
|
#define EEPROM_START_ADDR 0x1C00 // Адрес начала пользовательской EEPROM
|
|
#define EEPROM_WORD_SIZE 4 // Слово занимает 4 байта
|
|
#define EEPROM_PAGE_SIZE ( EEPROM_PAGE_WORDS * EEPROM_PAGE_WORDS ) // Страница занимает 32*4 = 128 байт
|
|
#define EEPROM_END 0x1FFF
|
|
#define EEPROM_LENGHT (EEPROM_PAGE_SIZE * EEPROM_PAGE_COUNT)
|
|
|
|
HAL_EEPROM_HandleTypeDef heeprom;
|
|
|
|
|
|
EEPtr 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);
|
|
return 0x00;
|
|
}
|
|
|
|
uint8_t EEPROMClass:: read( int idx )
|
|
{
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
return 0x00;
|
|
|
|
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, 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 EEPROMClass:: write( int idx, uint8_t val )
|
|
{
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
return;
|
|
|
|
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, 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);
|
|
// Вычленение и замена нужного байта из страницы
|
|
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, EEPROM_START_ADDR, write_data_buf, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
}
|
|
|
|
// Делает то же, что и write, но записывает только если новый байт отличается от уже записанного
|
|
void EEPROMClass:: update( int idx, uint8_t val )
|
|
{
|
|
if ((uint32_t)idx >= (uint32_t)EEPROM_LENGHT)
|
|
return;
|
|
|
|
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, 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);
|
|
// Проверка того, что записанный байт отличается от нового
|
|
if((write_data_buf[word_idx] & ((uint32_t)(0xFF) << ((EEPROM_WORD_SIZE - byte_idx - 1)) * 8)) != byte)
|
|
{
|
|
// Вычленение и замена нужного байта из страницы
|
|
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, EEPROM_START_ADDR, write_data_buf, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
uint16_t EEPROMClass:: length( void )
|
|
{
|
|
return EEPROM_LENGHT;
|
|
}
|
|
|
|
template< typename T >
|
|
const T& EEPROMClass:: put(int idx, const T &t) {
|
|
// Создание объекта EEPtr, который указывает на начальный адрес в EEPROM.
|
|
EEPtr e = idx;
|
|
|
|
// Указатель на данные, которые нужно записать в EEPROM.
|
|
const uint8_t *ptr = (const uint8_t*) &t;
|
|
|
|
// Количество байт данных для записи.
|
|
int count = sizeof(T);
|
|
|
|
// Цикл для записи данных побайтно в EEPROM.
|
|
for(; count ; --count, ++e) {
|
|
// Запись текущего байта данных в EEPROM.
|
|
(*e).update( *ptr++ );
|
|
}
|
|
|
|
// Возврат ссылки на записанный объект.
|
|
return t;
|
|
}
|
|
|
|
T& EEPROMClass:: get(int idx, T &t) {
|
|
EEPtr e = idx; // Указатель на адрес в EEPROM
|
|
uint8_t *ptr = (uint8_t*) &t; // Преобразуем ссылку на объект данных в указатель на байт
|
|
for (int count = sizeof(T); count; --count, ++e) {
|
|
*ptr++ = *e; // Читаем данные из EEPROM и записываем в объект
|
|
}
|
|
return t; // Возвращаем ссылку на переданный объект с прочитанными данными
|
|
}
|
|
|
|
|
|
|
|
// uint32_t* EEPROM_Read(uint16_t index)
|
|
// {
|
|
// uint32_t read_data_buf[];
|
|
// HAL_EEPROM_Read(&heeprom, 0x1C00 + index, read_data_buf, EEPROM_PAGE_WORDS, EEPROM_OP_TIMEOUT);
|
|
// return read_data_buf;
|
|
// }
|