#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; // }