diff --git a/libraries/.vscode/settings.json b/libraries/.vscode/settings.json new file mode 100644 index 0000000..a6c7df7 --- /dev/null +++ b/libraries/.vscode/settings.json @@ -0,0 +1,10 @@ +{ + "files.associations": { + "cstdint": "cpp", + "compare": "cpp", + "array": "cpp", + "string": "cpp", + "string_view": "cpp", + "initializer_list": "cpp" + } +} \ No newline at end of file diff --git a/libraries/EEPROM/src/EEPROM.cpp b/libraries/EEPROM/src/EEPROM.cpp index c07e7a0..4ff50a0 100644 --- a/libraries/EEPROM/src/EEPROM.cpp +++ b/libraries/EEPROM/src/EEPROM.cpp @@ -2,15 +2,6 @@ #include "mik32_hal_eeprom.h" #include "mik32_hal.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_WORD_SIZE ) // Страница занимает 32*4 = 128 байт -#define EEPROM_END 0x1FFF -#define EEPROM_LENGHT (EEPROM_PAGE_SIZE * EEPROM_PAGE_COUNT) - HAL_EEPROM_HandleTypeDef heeprom; @@ -27,8 +18,9 @@ void EEPROMClass:: begin() uint8_t EEPROMClass:: read( int idx ) { + // Проверка адекватности адреса idx if (((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) || (idx < 0)) - return 0x0; + return 0x0; // #TODO Добавить сообщение об ошибке uint32_t read_data_buf[EEPROM_PAGE_WORDS] = {}; @@ -48,8 +40,9 @@ uint8_t EEPROMClass:: read( int idx ) void EEPROMClass:: write( int idx, uint8_t val ) { + // Проверка адекватности адреса idx if (((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) || (idx < 0)) - return; + return; // #TODO Добавить сообщение об ошибке uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; @@ -77,15 +70,16 @@ void EEPROMClass:: write( int idx, uint8_t val ) // Делает то же, что и write, но записывает только если новый байт отличается от уже записанного void EEPROMClass:: update( int idx, uint8_t val ) { + // Проверка адекватности адреса idx if (((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) || (idx < 0)) - return; + return; // #TODO Добавить сообщение об ошибке 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); + 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 за вычетом адреса начала страницы @@ -110,25 +104,41 @@ uint16_t EEPROMClass:: length( void ) return (uint16_t)EEPROM_LENGHT; } -template< typename T > -const T& EEPROMClass:: put(int idx, const T &t) { - uint16_t ee_idx = (uint16_t)idx; +// // template< typename T > +// void* EEPROMClass:: put(int idx, void* dataPointer) +// { +// // Проверка адекватности адреса idx +// if (((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) || (idx < 0)) +// return dataPointer; // #TODO Добавить сообщение об ошибке +// // Проверка того, что данные влезут в eeprom, если начинать с текущего адреса +// if (sizeof(dataPointer) > ((int)EEPROM_LENGHT - idx)) +// return dataPointer; // #TODO Добавить сообщение об ошибке + +// uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; - // Указатель на данные, которые нужно записать в EEPROM. - const uint8_t *ptr = (const uint8_t*) &t; +// // Вычисление адресы начала нужной страницы +// 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); +// uint8_t size = sizeof(dataPointer); +// memcpy((void *)((uint8_t *)write_data_buf + idx), (void *)&size, 20); - // Количество байт данных для записи. - int count = sizeof(T); +// HAL_EEPROM_Erase(&heeprom, (uint16_t)addr, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT); +// HAL_EEPROM_Write(&heeprom, (uint16_t)addr, write_data_buf, EEPROM_PAGE_WORDS, HAL_EEPROM_WRITE_SINGLE, EEPROM_OP_TIMEOUT); - // Цикл для записи данных побайтно в EEPROM. - for(uint16_t i = 0; i < sizeof(T); i++) { - // Запись текущего байта данных в EEPROM. - EEPROM.update(ee_idx + i, *ptr++ ); - } +// // Количество байт данных для записи. +// // int count = sizeof(T); - // Возврат ссылки на записанный объект. - return t; -} +// // Цикл для записи данных побайтно в EEPROM. +// // for(uint16_t i = 0; i < sizeof(T); i++) { +// // // Запись текущего байта данных в EEPROM. +// // EEPROM.update(ee_idx + i, *ptr++ ); +// // } + +// // Запись данных в eeprom +// // Возврат ссылки на записанный объект. +// return dataPointer; +// } template< typename T > T& EEPROMClass:: get(int idx, T &t) { // EEPtr e = idx; // Указатель на адрес в EEPROM @@ -137,4 +147,19 @@ T& EEPROMClass:: get(int idx, T &t) { // *ptr++ = *e; // Читаем данные из EEPROM и записываем в объект // } return t; // Возвращаем ссылку на переданный объект с прочитанными данными +} + +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); } \ No newline at end of file diff --git a/libraries/EEPROM/src/EEPROM.h b/libraries/EEPROM/src/EEPROM.h index bca64a2..ca1116d 100644 --- a/libraries/EEPROM/src/EEPROM.h +++ b/libraries/EEPROM/src/EEPROM.h @@ -22,6 +22,20 @@ #define EEPROM_h #include +#include "string.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_WORD_SIZE ) // Страница занимает 32*4 = 128 байт +#define EEPROM_END 0x1FFF +#define EEPROM_LENGHT (EEPROM_PAGE_SIZE * EEPROM_PAGE_COUNT) + +void HAL_read(uint16_t addr, uint32_t * data); +void HAL_write(uint16_t addr, uint32_t * data); +void HAL_erase(uint16_t addr); /*** EERef class. @@ -124,8 +138,73 @@ struct EEPROMClass{ uint16_t end() { return length(); } //Standards requires this to be the item after the last valid entry. The returned pointer is invalid. uint16_t length(); - template - const T& put(int address, const T& data); + template< typename T > + T& put(int idx, T& dataPointer) + { + // Проверка адекватности адреса idx + if (((uint32_t)idx >= (uint32_t)EEPROM_LENGHT) || (idx < 0)) + return dataPointer; // #TODO Добавить сообщение об ошибке + // Проверка того, что данные влезут в eeprom, если начинать с текущего адреса + if (sizeof(dataPointer) > ((int)EEPROM_LENGHT - idx)) + return dataPointer; // #TODO Добавить сообщение об ошибке + + uint32_t write_data_buf[EEPROM_PAGE_WORDS] = {}; + // Размер данных под запись + uint32_t dataSize = sizeof(dataPointer); + // Сдвиг начала записи данных + uint32_t dataShift = 0; + uint32_t writeSize = dataSize; + + // Вычисление адресы начала нужной страницы + uint32_t addr = EEPROM_START_ADDR + (((uint32_t)idx) / EEPROM_PAGE_SIZE) * EEPROM_PAGE_SIZE; + // Адрес начала данных на странице + uint32_t byte_addr = (uint32_t)idx % EEPROM_PAGE_SIZE; + // Чтение первой страницы + HAL_read((uint16_t)addr, write_data_buf); + // Если данные не влезут на первую страницу, то записываем только то, что влезло + if (EEPROM_PAGE_SIZE - byte_addr < dataSize) + { + writeSize = EEPROM_PAGE_SIZE - byte_addr; + } + dataSize -= writeSize; + // Копирование данных в буфер для записи в три этапа: первый - копирование того, что идёт до первого целого слова, + // второй - копирование целых слов, третий - копирование того, что идёт после последнего целого слова + memcpy((void *)((uint8_t *)write_data_buf + byte_addr), (void*)dataPointer, writeSize); + + HAL_erase((uint16_t)addr); + HAL_write((uint16_t)addr, write_data_buf); + // Если данные остались после записи первой страницы, то пишем их постранично, пока не закончатся + while (dataSize > 0) + { + addr += EEPROM_PAGE_SIZE; + HAL_read((uint16_t)addr, write_data_buf); + dataShift += writeSize; + writeSize = dataSize; + if (EEPROM_PAGE_SIZE < dataSize) + { + writeSize = EEPROM_PAGE_SIZE; + dataShift += writeSize; + } + dataSize -= writeSize; + memcpy((void *)((uint8_t *)write_data_buf), (void*)(dataPointer + dataShift), writeSize); + + HAL_erase((uint16_t)addr); + HAL_write((uint16_t)addr, write_data_buf); + } + + // Количество байт данных для записи. + // int count = sizeof(T); + + // Цикл для записи данных побайтно в EEPROM. + // for(uint16_t i = 0; i < sizeof(T); i++) { + // // Запись текущего байта данных в EEPROM. + // EEPROM.update(ee_idx + i, *ptr++ ); + // } + + // Запись данных в eeprom + // Возврат ссылки на записанный объект. + return dataPointer; + } template T& get(int address, T& data);