add fs entry replace/cache functions

This commit is contained in:
Michele Balistreri 2018-06-25 21:50:13 +02:00
parent 7bb38a7f12
commit c7b26fb270
5 changed files with 152 additions and 7 deletions

View File

@ -58,7 +58,7 @@ int flash_erase(uint8_t page, uint8_t page_count);
* Copies `size` words from `src` to `dst`. Since this function is only called using constant values and previously checked values, the input parameters are not validated. The addresses must be aligned according
* to the rules specified in the ST DM00083560 document.
*/
int flash_copy(uint32_t* src, __IO uint32_t* dst, uint32_t size);
int flash_copy(const uint32_t* src, __IO uint32_t* dst, uint32_t size);
/**
* Locks the flash again, preventing writing.

View File

@ -105,4 +105,16 @@ uint32_t* fs_swap_get_free();
*/
uint32_t* fs_cache_get_free(uint32_t cache_start, int page_count, int entry_size);
/**
* Finds the first free entry and writes the new value. If all pages are full, they are all erased and the new value is written at the beginning
* of the first page.
*/
int fs_replace_entry(uint32_t page_num, int page_count, int entry_size, const uint32_t *entry);
/**
* Similar to fs_replace_entry but applicable to caches. In case the cache is full, only the oldest page is erased and the new entry is placed at
* the beginning of the erased page.
*/
int fs_cache_entry(uint32_t cache_start, int page_count, int entry_size, const uint32_t *entry);
#endif /* FS_H_ */

View File

@ -73,7 +73,7 @@ int flash_erase(uint8_t page, uint8_t page_count) {
return 0;
}
int flash_copy(uint32_t *src, __IO uint32_t *dst, uint32_t size) {
int flash_copy(const uint32_t *src, __IO uint32_t *dst, uint32_t size) {
_flash_wait();
_flash_clear_errors();
int ret = 0;

View File

@ -195,10 +195,10 @@ uint32_t* _fs_find_free_entry(uint32_t* page, int entry_size) {
uint32_t* fs_find_free_entry(uint32_t page_num, int page_count, int entry_size) {
for (int i = 0; i < page_count; i++) {
uint32_t* page = _fs_find_free_entry(FS_PAGE_IDX_ADDR(page_num, i), entry_size);
uint32_t* free = _fs_find_free_entry(FS_PAGE_IDX_ADDR(page_num, i), entry_size);
if (page) {
return page;
if (free) {
return free;
}
}
@ -277,11 +277,13 @@ uint32_t * _fs_cache_free_oldest(uint32_t cache_start, int page_count) {
if (flash_erase(FS_ABS_IDX_PAGE(cache_start, page_idx), 1) || flash_copy(header, addr, 2)) {
addr = NULL;
goto ret;
} else {
addr = &addr[2];
}
ret:
flash_lock();
return &addr[2];
return addr;
}
uint32_t* fs_cache_get_free(uint32_t cache_start, int page_count, int entry_size) {
@ -293,3 +295,58 @@ uint32_t* fs_cache_get_free(uint32_t cache_start, int page_count, int entry_size
return free_addr;
}
int _fs_write_entry(uint32_t* addr, const uint32_t* entry, int entry_size) {
int res = 0;
if(flash_unlock() || flash_copy(entry, addr, entry_size)) res = -1;
flash_lock();
return res;
}
int _fs_rewrite_entry(uint32_t page_num, int page_count, int entry_size, const uint32_t *entry) {
uint32_t *free = fs_swap_get_free();
if (!free) return -1;
int res = -1;
if (flash_unlock()) goto ret;
uint32_t header[2];
uint32_t* page = FS_PAGE_IDX_ADDR(page_num, 0);
FS_HEADER(header, page[0], (page[1] + 1));
if (flash_copy(entry, &free[2], entry_size)) goto ret;
if (flash_copy(header, free, 2)) goto ret;
for (int i = 1; i < page_count; i++) {
free = fs_swap_get_free();
if (!free) goto ret;
page = FS_PAGE_IDX_ADDR(page_num, i);
FS_HEADER(header, page[0], (page[1] + 1));
if (flash_copy(header, free, 2)) goto ret;
}
res = 0;
ret:
flash_lock();
return res;
}
int fs_replace_entry(uint32_t page_num, int page_count, int entry_size, const uint32_t *entry) {
uint32_t* free = fs_find_free_entry(page_num, page_count, entry_size);
if (free) {
return _fs_write_entry(free, entry, entry_size);
} else {
return _fs_rewrite_entry(page_num, page_count, entry_size, entry) || fs_commit();
}
}
int fs_cache_entry(uint32_t cache_start, int page_count, int entry_size, const uint32_t *entry) {
uint32_t* free = fs_cache_get_free(cache_start, page_count, entry_size);
if (!free) return -1;
return _fs_write_entry(free, entry, entry_size);
}

View File

@ -33,7 +33,7 @@ int flash_erase(uint8_t page, uint8_t page_count) {
return 0;
}
int flash_copy(uint32_t* src, __IO uint32_t* dst, uint32_t size) {
int flash_copy(const uint32_t* src, __IO uint32_t* dst, uint32_t size) {
TEST_CHECK(!(flash_locked || (((uintptr_t) dst) % 4) || (size % 2)));
for(int i = 0; i < size; i += 2) {
@ -250,6 +250,80 @@ void test_fs_cache_get_free(void) {
TEST_CHECK(page[1] == (FS_KEY_CACHE_COUNT + 1));
}
void test_fs_replace_entry(void) {
TEST_CHECK(!fs_init());
uint32_t entry[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0X10 };
uint32_t* page = FS_PAGE_IDX_ADDR(FS_COUNTERS_PAGE, 0);
TEST_CHECK(!fs_replace_entry(FS_COUNTERS_PAGE, FS_COUNTERS_PAGE, 4, entry));
TEST_CHECK(!memcmp(entry, &page[2], 16));
for (int i = 0; i < FS_KEY_CACHE_COUNT; i++) {
page = FS_PAGE_IDX_ADDR(FS_COUNTERS_PAGE, i);
for (int j = 2; j < FLASH_PAGE_SIZE/4; j++) {
page[j] = 0xeeeeeeee;
}
}
page = FS_PAGE_IDX_ADDR(FS_COUNTERS_PAGE, 0);
TEST_CHECK(!fs_replace_entry(FS_COUNTERS_PAGE, FS_COUNTERS_PAGE, 4, entry));
TEST_CHECK(!memcmp(entry, &page[2], 16));
TEST_CHECK(page[0] == FS_V1_PAGE_ID(FS_COUNTERS_ID, 0));
TEST_CHECK(page[1] == 1);
for (int j = 6; j < FLASH_PAGE_SIZE/4; j++) {
TEST_CHECK(page[j] == 0xffffffff);
}
for (int i = 1; i < FS_COUNTERS_PAGE; i++) {
page = FS_PAGE_IDX_ADDR(FS_COUNTERS_PAGE, i);
TEST_CHECK(page[0] == FS_V1_PAGE_ID(FS_COUNTERS_ID, i));
TEST_CHECK(page[1] == 1);
for (int j = 2; j < FLASH_PAGE_SIZE/4; j++) {
TEST_CHECK(page[j] == 0xffffffff);
}
}
}
void test_fs_cache_entry(void) {
TEST_CHECK(!fs_init());
uint32_t entry[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0X10 };
uint32_t* page = FS_PAGE_IDX_ADDR(FS_KEY_CACHE_PAGE, 0);
TEST_CHECK(!fs_cache_entry(FS_KEY_CACHE_PAGE, FS_KEY_CACHE_COUNT, 4, entry));
TEST_CHECK(!memcmp(entry, &page[2], 16));
for (int i = 0; i < FS_KEY_CACHE_COUNT; i++) {
page = FS_PAGE_IDX_ADDR(FS_KEY_CACHE_PAGE, i);
for (int j = 2; j < FLASH_PAGE_SIZE/4; j++) {
page[j] = 0xeeeeeeee;
}
}
page = FS_PAGE_IDX_ADDR(FS_KEY_CACHE_PAGE, 0);
TEST_CHECK(!fs_cache_entry(FS_KEY_CACHE_PAGE, FS_KEY_CACHE_COUNT, 4, entry));
TEST_CHECK(!memcmp(entry, &page[2], 16));
for (int j = 6; j < FLASH_PAGE_SIZE/4; j++) {
TEST_CHECK(page[j] == 0xffffffff);
}
for (int i = 1; i < FS_KEY_CACHE_COUNT; i++) {
page = FS_PAGE_IDX_ADDR(FS_KEY_CACHE_PAGE, i);
for (int j = 2; j < FLASH_PAGE_SIZE/4; j++) {
TEST_CHECK(page[j] == 0xeeeeeeee);
}
}
}
TEST_LIST = {
{ "fs_init", test_fs_init },
{ "fs_commit", test_fs_commit },
@ -257,5 +331,7 @@ TEST_LIST = {
{ "fs_find_last_entry", test_fs_find_last_entry },
{ "fs_swap_get_free", test_fs_swap_get_free },
{ "fs_cache_get_free", test_fs_cache_get_free },
{ "fs_replace_entry", test_fs_replace_entry },
{ "fs_cache_entry", test_fs_cache_entry },
{ 0 }
};