Rev 9 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 9 | Rev 10 | ||
|---|---|---|---|
| Line 17... | Line 17... | ||
| 17 | #define NVRAM_PAGESIZE (1024 / sizeof(nvram_info_t)) |
17 | #define NVRAM_PAGESIZE (1024 / sizeof(nvram_info_t)) |
| 18 | 18 | ||
| 19 | // decided to allocate 2 pages of Flash as NVRAM |
19 | // decided to allocate 2 pages of Flash as NVRAM |
| 20 | #define NVRAM_WORDS (2 * NVRAM_PAGESIZE) |
20 | #define NVRAM_WORDS (2 * NVRAM_PAGESIZE) |
| 21 | 21 | ||
| 22 | // NVRAM hardware erases to all 0x |
22 | // Flash hardware erases to all 0 |
| 23 | nvram_info_t const HARDWARE_ERASED = {.u16 = 0UL}; |
23 | nvram_info_t const HARDWARE_ERASED = {.u16 = (uint16_t)~0U}; |
| 24 | // Marked as erased change to all 1 |
24 | // Marked as erased change to all 1 |
| 25 | nvram_info_t const MARKED_ERASED = {.u16 = ~0UL}; |
25 | nvram_info_t const MARKED_ERASED = {.u16 = (uint16_t)0U}; |
| 26 | 26 | ||
| 27 | // allocate the memory for storing the NVRAM data |
27 | // allocate the memory for storing the NVRAM data |
| 28 | nvram_info_t NVRAM_Base[NVRAM_WORDS] __attribute__((section(".nvram"))); // set by linker |
28 | nvram_info_t NVRAM_Base[NVRAM_WORDS] __attribute__((section(".nvram"))) = { [0 ... NVRAM_WORDS-1].u16 = (uint16_t)~0U}; // set by linker |
| 29 | 29 | ||
| 30 | static void |
30 | static void |
| 31 | WriteNVRAM(nvram_info_t *Address, nvram_info_t data) |
31 | WriteNVRAM(nvram_info_t *Address, nvram_info_t data) |
| 32 | { |
32 | { |
| 33 | HAL_FLASH_Unlock(); |
33 | HAL_FLASH_Unlock(); |
| Line 36... | Line 36... | ||
| 36 | } |
36 | } |
| 37 | 37 | ||
| 38 | static void |
38 | static void |
| 39 | EraseNVRAM(nvram_info_t *Address) |
39 | EraseNVRAM(nvram_info_t *Address) |
| 40 | { |
40 | { |
| 41 | FLASH_EraseInitTypeDef erase = {.TypeErase = FLASH_TYPEERASE_PAGES, .PageAddress = Address, .NbPages = 1}; |
41 | FLASH_EraseInitTypeDef erase = {.TypeErase = FLASH_TYPEERASE_PAGES, .PageAddress = (uint32_t)Address, .NbPages = 1}; |
| 42 | uint32_t err; |
42 | uint32_t err; |
| 43 | HAL_FLASH_Unlock(); |
43 | HAL_FLASH_Unlock(); |
| 44 | HAL_FLASHEx_Erase(&erase, &err); |
44 | HAL_FLASHEx_Erase(&erase, &err); |
| 45 | HAL_FLASH_Lock(); |
45 | HAL_FLASH_Lock(); |
| 46 | } |
46 | } |
| Line 51... | Line 51... | ||
| 51 | static uint8_t _write_nvram_data(nvram_info_t data, int *pIndex) |
51 | static uint8_t _write_nvram_data(nvram_info_t data, int *pIndex) |
| 52 | { |
52 | { |
| 53 | int base = *pIndex; |
53 | int base = *pIndex; |
| 54 | uint8_t pageCrossed = 0; |
54 | uint8_t pageCrossed = 0; |
| 55 | 55 | ||
| 56 | /* search blank */ |
56 | // search for correct data |
| 57 | for (int ptr = 0; ptr < NVRAM_WORDS; ptr++) |
57 | for (int ptr = 0; ptr < NVRAM_WORDS; ptr++) |
| 58 | { |
58 | { |
| 59 | int index = (ptr + base) % NVRAM_WORDS; |
59 | int index = (ptr + base) % NVRAM_WORDS; |
| 60 | // erase the entry just found |
60 | // erase the entry just found |
| 61 | if (NVRAM_Base[index].data.tag == data.data.tag) |
61 | if (NVRAM_Base[index].data.tag == data.data.tag) |
| 62 | { |
62 | { |
| - | 63 | // is this the same data as we are writing ? if so return immediately |
|
| - | 64 | if(NVRAM_Base[index].u16 == data.u16) |
|
| - | 65 | return 0; |
|
| - | 66 | // different data |
|
| 63 | // erase previous data |
67 | // erase previous data |
| 64 | WriteNVRAM(&NVRAM_Base[index], MARKED_ERASED); |
68 | WriteNVRAM(&NVRAM_Base[index], MARKED_ERASED); |
| 65 | base = ptr; |
69 | base = index+1; // look at next element |
| 66 | break; |
70 | break; |
| 67 | } |
71 | } |
| 68 | } |
72 | } |
| 69 | // search forward for next erased or empty element, use it |
73 | // search forward for next hardware erased element, use it |
| 70 | for (int offset = 1; offset < NVRAM_WORDS + 1; offset++) |
74 | for (int offset = 0; offset < NVRAM_WORDS; offset++) |
| 71 | { |
75 | { |
| 72 | int index = (base + offset) % NVRAM_WORDS; |
76 | int index = (base + offset) % NVRAM_WORDS; |
| 73 | 77 | ||
| 74 | if (NVRAM_Base[index].u16 == HARDWARE_ERASED.u16) |
78 | if (NVRAM_Base[index].u16 == HARDWARE_ERASED.u16) |
| 75 | { |
79 | { |
| Line 79... | Line 83... | ||
| 79 | 83 | ||
| 80 | WriteNVRAM(&NVRAM_Base[index], data); |
84 | WriteNVRAM(&NVRAM_Base[index], data); |
| 81 | // now check to see if it actually wrote correctly |
85 | // now check to see if it actually wrote correctly |
| 82 | if (NVRAM_Base[index].u16 != data.u16) |
86 | if (NVRAM_Base[index].u16 != data.u16) |
| 83 | { |
87 | { |
| 84 | WriteNVRAM(&NVRAM_Base[index], MARKED_ERASED); // Set to all 1 if the data did not write properly |
88 | WriteNVRAM(&NVRAM_Base[index], MARKED_ERASED); // Set to all erased if the data did not write properly |
| 85 | continue; |
89 | continue; |
| 86 | } |
90 | } |
| 87 | // record where the data was written |
91 | // record where the data was written |
| 88 | *pIndex = index; |
92 | *pIndex = index; |
| 89 | return pageCrossed; |
93 | return pageCrossed; |
| Line 110... | Line 114... | ||
| 110 | int base = i; |
114 | int base = i; |
| 111 | // copy data forwards |
115 | // copy data forwards |
| 112 | _write_nvram_data(NVRAM_Base[i], &base); |
116 | _write_nvram_data(NVRAM_Base[i], &base); |
| 113 | } |
117 | } |
| 114 | // erase the page we just copied out of |
118 | // erase the page we just copied out of |
| 115 | EraseNVRAM(&NVRAM_Base[oldPageBase]); |
- | |
| 116 | } |
119 | } |
| - | 120 | EraseNVRAM(&NVRAM_Base[oldPageBase]); |
|
| 117 | } |
121 | } |
| 118 | 122 | ||
| 119 | nvram_info_t *find_nvram_data(uint8_t searchTag) |
123 | nvram_info_t *find_nvram_data(uint8_t searchTag) |
| 120 | { |
124 | { |
| 121 | for (int ptr = 0; ptr < NVRAM_WORDS; ptr++) |
125 | for (int ptr = 0; ptr < NVRAM_WORDS; ptr++) |