diff options
-rw-r--r-- | tmk_core/common.mk | 7 | ||||
-rwxr-xr-x | tmk_core/common/chibios/eeprom_stm32.c | 673 | ||||
-rwxr-xr-x | tmk_core/common/chibios/eeprom_stm32.h | 89 | ||||
-rw-r--r-- | tmk_core/common/chibios/eeprom_teensy.c (renamed from tmk_core/common/chibios/eeprom.c) | 0 | ||||
-rwxr-xr-x | tmk_core/common/chibios/flash_stm32.c | 180 | ||||
-rwxr-xr-x | tmk_core/common/chibios/flash_stm32.h | 53 | ||||
-rw-r--r-- | tmk_core/common/eeconfig.c | 11 | ||||
-rw-r--r-- | tmk_core/common/eeconfig.h | 16 | ||||
-rw-r--r-- | tmk_core/protocol/chibios/main.c | 7 |
9 files changed, 1035 insertions, 1 deletions
diff --git a/tmk_core/common.mk b/tmk_core/common.mk index fd91d29dc..319d196ae 100644 --- a/tmk_core/common.mk +++ b/tmk_core/common.mk | |||
@@ -31,7 +31,12 @@ endif | |||
31 | 31 | ||
32 | ifeq ($(PLATFORM),CHIBIOS) | 32 | ifeq ($(PLATFORM),CHIBIOS) |
33 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c | 33 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/printf.c |
34 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom.c | 34 | ifeq ($(MCU_SERIES), STM32F3xx) |
35 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom_stm32.c | ||
36 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/flash_stm32.c | ||
37 | else | ||
38 | TMK_COMMON_SRC += $(PLATFORM_COMMON_DIR)/eeprom_teensy.c | ||
39 | endif | ||
35 | ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) | 40 | ifeq ($(strip $(AUTO_SHIFT_ENABLE)), yes) |
36 | TMK_COMMON_SRC += $(CHIBIOS)/os/various/syscalls.c | 41 | TMK_COMMON_SRC += $(CHIBIOS)/os/various/syscalls.c |
37 | endif | 42 | endif |
diff --git a/tmk_core/common/chibios/eeprom_stm32.c b/tmk_core/common/chibios/eeprom_stm32.c new file mode 100755 index 000000000..3c1945122 --- /dev/null +++ b/tmk_core/common/chibios/eeprom_stm32.c | |||
@@ -0,0 +1,673 @@ | |||
1 | /* | ||
2 | * This software is experimental and a work in progress. | ||
3 | * Under no circumstances should these files be used in relation to any critical system(s). | ||
4 | * Use of these files is at your own risk. | ||
5 | * | ||
6 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
7 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
8 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
9 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
11 | * DEALINGS IN THE SOFTWARE. | ||
12 | * | ||
13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | ||
14 | * https://github.com/leaflabs/libmaple | ||
15 | * | ||
16 | * Modifications for QMK and STM32F303 by Yiancar | ||
17 | */ | ||
18 | |||
19 | #include "eeprom_stm32.h" | ||
20 | |||
21 | FLASH_Status EE_ErasePage(uint32_t); | ||
22 | |||
23 | uint16_t EE_CheckPage(uint32_t, uint16_t); | ||
24 | uint16_t EE_CheckErasePage(uint32_t, uint16_t); | ||
25 | uint16_t EE_Format(void); | ||
26 | uint32_t EE_FindValidPage(void); | ||
27 | uint16_t EE_GetVariablesCount(uint32_t, uint16_t); | ||
28 | uint16_t EE_PageTransfer(uint32_t, uint32_t, uint16_t); | ||
29 | uint16_t EE_VerifyPageFullWriteVariable(uint16_t, uint16_t); | ||
30 | |||
31 | uint32_t PageBase0 = EEPROM_PAGE0_BASE; | ||
32 | uint32_t PageBase1 = EEPROM_PAGE1_BASE; | ||
33 | uint32_t PageSize = EEPROM_PAGE_SIZE; | ||
34 | uint16_t Status = EEPROM_NOT_INIT; | ||
35 | |||
36 | // See http://www.st.com/web/en/resource/technical/document/application_note/CD00165693.pdf | ||
37 | |||
38 | /** | ||
39 | * @brief Check page for blank | ||
40 | * @param page base address | ||
41 | * @retval Success or error | ||
42 | * EEPROM_BAD_FLASH: page not empty after erase | ||
43 | * EEPROM_OK: page blank | ||
44 | */ | ||
45 | uint16_t EE_CheckPage(uint32_t pageBase, uint16_t status) | ||
46 | { | ||
47 | uint32_t pageEnd = pageBase + (uint32_t)PageSize; | ||
48 | |||
49 | // Page Status not EEPROM_ERASED and not a "state" | ||
50 | if ((*(__IO uint16_t*)pageBase) != EEPROM_ERASED && (*(__IO uint16_t*)pageBase) != status) | ||
51 | return EEPROM_BAD_FLASH; | ||
52 | for(pageBase += 4; pageBase < pageEnd; pageBase += 4) | ||
53 | if ((*(__IO uint32_t*)pageBase) != 0xFFFFFFFF) // Verify if slot is empty | ||
54 | return EEPROM_BAD_FLASH; | ||
55 | return EEPROM_OK; | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * @brief Erase page with increment erase counter (page + 2) | ||
60 | * @param page base address | ||
61 | * @retval Success or error | ||
62 | * FLASH_COMPLETE: success erase | ||
63 | * - Flash error code: on write Flash error | ||
64 | */ | ||
65 | FLASH_Status EE_ErasePage(uint32_t pageBase) | ||
66 | { | ||
67 | FLASH_Status FlashStatus; | ||
68 | uint16_t data = (*(__IO uint16_t*)(pageBase)); | ||
69 | if ((data == EEPROM_ERASED) || (data == EEPROM_VALID_PAGE) || (data == EEPROM_RECEIVE_DATA)) | ||
70 | data = (*(__IO uint16_t*)(pageBase + 2)) + 1; | ||
71 | else | ||
72 | data = 0; | ||
73 | |||
74 | FlashStatus = FLASH_ErasePage(pageBase); | ||
75 | if (FlashStatus == FLASH_COMPLETE) | ||
76 | FlashStatus = FLASH_ProgramHalfWord(pageBase + 2, data); | ||
77 | |||
78 | return FlashStatus; | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | * @brief Check page for blank and erase it | ||
83 | * @param page base address | ||
84 | * @retval Success or error | ||
85 | * - Flash error code: on write Flash error | ||
86 | * - EEPROM_BAD_FLASH: page not empty after erase | ||
87 | * - EEPROM_OK: page blank | ||
88 | */ | ||
89 | uint16_t EE_CheckErasePage(uint32_t pageBase, uint16_t status) | ||
90 | { | ||
91 | uint16_t FlashStatus; | ||
92 | if (EE_CheckPage(pageBase, status) != EEPROM_OK) | ||
93 | { | ||
94 | FlashStatus = EE_ErasePage(pageBase); | ||
95 | if (FlashStatus != FLASH_COMPLETE) | ||
96 | return FlashStatus; | ||
97 | return EE_CheckPage(pageBase, status); | ||
98 | } | ||
99 | return EEPROM_OK; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * @brief Find valid Page for write or read operation | ||
104 | * @param Page0: Page0 base address | ||
105 | * Page1: Page1 base address | ||
106 | * @retval Valid page address (PAGE0 or PAGE1) or NULL in case of no valid page was found | ||
107 | */ | ||
108 | uint32_t EE_FindValidPage(void) | ||
109 | { | ||
110 | uint16_t status0 = (*(__IO uint16_t*)PageBase0); // Get Page0 actual status | ||
111 | uint16_t status1 = (*(__IO uint16_t*)PageBase1); // Get Page1 actual status | ||
112 | |||
113 | if (status0 == EEPROM_VALID_PAGE && status1 == EEPROM_ERASED) | ||
114 | return PageBase0; | ||
115 | if (status1 == EEPROM_VALID_PAGE && status0 == EEPROM_ERASED) | ||
116 | return PageBase1; | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | /** | ||
122 | * @brief Calculate unique variables in EEPROM | ||
123 | * @param start: address of first slot to check (page + 4) | ||
124 | * @param end: page end address | ||
125 | * @param address: 16 bit virtual address of the variable to excluse (or 0XFFFF) | ||
126 | * @retval count of variables | ||
127 | */ | ||
128 | uint16_t EE_GetVariablesCount(uint32_t pageBase, uint16_t skipAddress) | ||
129 | { | ||
130 | uint16_t varAddress, nextAddress; | ||
131 | uint32_t idx; | ||
132 | uint32_t pageEnd = pageBase + (uint32_t)PageSize; | ||
133 | uint16_t count = 0; | ||
134 | |||
135 | for (pageBase += 6; pageBase < pageEnd; pageBase += 4) | ||
136 | { | ||
137 | varAddress = (*(__IO uint16_t*)pageBase); | ||
138 | if (varAddress == 0xFFFF || varAddress == skipAddress) | ||
139 | continue; | ||
140 | |||
141 | count++; | ||
142 | for(idx = pageBase + 4; idx < pageEnd; idx += 4) | ||
143 | { | ||
144 | nextAddress = (*(__IO uint16_t*)idx); | ||
145 | if (nextAddress == varAddress) | ||
146 | { | ||
147 | count--; | ||
148 | break; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | return count; | ||
153 | } | ||
154 | |||
155 | /** | ||
156 | * @brief Transfers last updated variables data from the full Page to an empty one. | ||
157 | * @param newPage: new page base address | ||
158 | * @param oldPage: old page base address | ||
159 | * @param SkipAddress: 16 bit virtual address of the variable (or 0xFFFF) | ||
160 | * @retval Success or error status: | ||
161 | * - FLASH_COMPLETE: on success | ||
162 | * - EEPROM_OUT_SIZE: if valid new page is full | ||
163 | * - Flash error code: on write Flash error | ||
164 | */ | ||
165 | uint16_t EE_PageTransfer(uint32_t newPage, uint32_t oldPage, uint16_t SkipAddress) | ||
166 | { | ||
167 | uint32_t oldEnd, newEnd; | ||
168 | uint32_t oldIdx, newIdx, idx; | ||
169 | uint16_t address, data, found; | ||
170 | FLASH_Status FlashStatus; | ||
171 | |||
172 | // Transfer process: transfer variables from old to the new active page | ||
173 | newEnd = newPage + ((uint32_t)PageSize); | ||
174 | |||
175 | // Find first free element in new page | ||
176 | for (newIdx = newPage + 4; newIdx < newEnd; newIdx += 4) | ||
177 | if ((*(__IO uint32_t*)newIdx) == 0xFFFFFFFF) // Verify if element | ||
178 | break; // contents are 0xFFFFFFFF | ||
179 | if (newIdx >= newEnd) | ||
180 | return EEPROM_OUT_SIZE; | ||
181 | |||
182 | oldEnd = oldPage + 4; | ||
183 | oldIdx = oldPage + (uint32_t)(PageSize - 2); | ||
184 | |||
185 | for (; oldIdx > oldEnd; oldIdx -= 4) | ||
186 | { | ||
187 | address = *(__IO uint16_t*)oldIdx; | ||
188 | if (address == 0xFFFF || address == SkipAddress) | ||
189 | continue; // it's means that power off after write data | ||
190 | |||
191 | found = 0; | ||
192 | for (idx = newPage + 6; idx < newIdx; idx += 4) | ||
193 | if ((*(__IO uint16_t*)(idx)) == address) | ||
194 | { | ||
195 | found = 1; | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | if (found) | ||
200 | continue; | ||
201 | |||
202 | if (newIdx < newEnd) | ||
203 | { | ||
204 | data = (*(__IO uint16_t*)(oldIdx - 2)); | ||
205 | |||
206 | FlashStatus = FLASH_ProgramHalfWord(newIdx, data); | ||
207 | if (FlashStatus != FLASH_COMPLETE) | ||
208 | return FlashStatus; | ||
209 | |||
210 | FlashStatus = FLASH_ProgramHalfWord(newIdx + 2, address); | ||
211 | if (FlashStatus != FLASH_COMPLETE) | ||
212 | return FlashStatus; | ||
213 | |||
214 | newIdx += 4; | ||
215 | } | ||
216 | else | ||
217 | return EEPROM_OUT_SIZE; | ||
218 | } | ||
219 | |||
220 | // Erase the old Page: Set old Page status to EEPROM_EEPROM_ERASED status | ||
221 | data = EE_CheckErasePage(oldPage, EEPROM_ERASED); | ||
222 | if (data != EEPROM_OK) | ||
223 | return data; | ||
224 | |||
225 | // Set new Page status | ||
226 | FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_VALID_PAGE); | ||
227 | if (FlashStatus != FLASH_COMPLETE) | ||
228 | return FlashStatus; | ||
229 | |||
230 | return EEPROM_OK; | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * @brief Verify if active page is full and Writes variable in EEPROM. | ||
235 | * @param Address: 16 bit virtual address of the variable | ||
236 | * @param Data: 16 bit data to be written as variable value | ||
237 | * @retval Success or error status: | ||
238 | * - FLASH_COMPLETE: on success | ||
239 | * - EEPROM_PAGE_FULL: if valid page is full (need page transfer) | ||
240 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
241 | * - EEPROM_OUT_SIZE: if EEPROM size exceeded | ||
242 | * - Flash error code: on write Flash error | ||
243 | */ | ||
244 | uint16_t EE_VerifyPageFullWriteVariable(uint16_t Address, uint16_t Data) | ||
245 | { | ||
246 | FLASH_Status FlashStatus; | ||
247 | uint32_t idx, pageBase, pageEnd, newPage; | ||
248 | uint16_t count; | ||
249 | |||
250 | // Get valid Page for write operation | ||
251 | pageBase = EE_FindValidPage(); | ||
252 | if (pageBase == 0) | ||
253 | return EEPROM_NO_VALID_PAGE; | ||
254 | |||
255 | // Get the valid Page end Address | ||
256 | pageEnd = pageBase + PageSize; // Set end of page | ||
257 | |||
258 | for (idx = pageEnd - 2; idx > pageBase; idx -= 4) | ||
259 | { | ||
260 | if ((*(__IO uint16_t*)idx) == Address) // Find last value for address | ||
261 | { | ||
262 | count = (*(__IO uint16_t*)(idx - 2)); // Read last data | ||
263 | if (count == Data) | ||
264 | return EEPROM_OK; | ||
265 | if (count == 0xFFFF) | ||
266 | { | ||
267 | FlashStatus = FLASH_ProgramHalfWord(idx - 2, Data); // Set variable data | ||
268 | if (FlashStatus == FLASH_COMPLETE) | ||
269 | return EEPROM_OK; | ||
270 | } | ||
271 | break; | ||
272 | } | ||
273 | } | ||
274 | |||
275 | // Check each active page address starting from begining | ||
276 | for (idx = pageBase + 4; idx < pageEnd; idx += 4) | ||
277 | if ((*(__IO uint32_t*)idx) == 0xFFFFFFFF) // Verify if element | ||
278 | { // contents are 0xFFFFFFFF | ||
279 | FlashStatus = FLASH_ProgramHalfWord(idx, Data); // Set variable data | ||
280 | if (FlashStatus != FLASH_COMPLETE) | ||
281 | return FlashStatus; | ||
282 | FlashStatus = FLASH_ProgramHalfWord(idx + 2, Address); // Set variable virtual address | ||
283 | if (FlashStatus != FLASH_COMPLETE) | ||
284 | return FlashStatus; | ||
285 | return EEPROM_OK; | ||
286 | } | ||
287 | |||
288 | // Empty slot not found, need page transfer | ||
289 | // Calculate unique variables in page | ||
290 | count = EE_GetVariablesCount(pageBase, Address) + 1; | ||
291 | if (count >= (PageSize / 4 - 1)) | ||
292 | return EEPROM_OUT_SIZE; | ||
293 | |||
294 | if (pageBase == PageBase1) | ||
295 | newPage = PageBase0; // New page address where variable will be moved to | ||
296 | else | ||
297 | newPage = PageBase1; | ||
298 | |||
299 | // Set the new Page status to RECEIVE_DATA status | ||
300 | FlashStatus = FLASH_ProgramHalfWord(newPage, EEPROM_RECEIVE_DATA); | ||
301 | if (FlashStatus != FLASH_COMPLETE) | ||
302 | return FlashStatus; | ||
303 | |||
304 | // Write the variable passed as parameter in the new active page | ||
305 | FlashStatus = FLASH_ProgramHalfWord(newPage + 4, Data); | ||
306 | if (FlashStatus != FLASH_COMPLETE) | ||
307 | return FlashStatus; | ||
308 | |||
309 | FlashStatus = FLASH_ProgramHalfWord(newPage + 6, Address); | ||
310 | if (FlashStatus != FLASH_COMPLETE) | ||
311 | return FlashStatus; | ||
312 | |||
313 | return EE_PageTransfer(newPage, pageBase, Address); | ||
314 | } | ||
315 | |||
316 | /*EEPROMClass::EEPROMClass(void) | ||
317 | { | ||
318 | PageBase0 = EEPROM_PAGE0_BASE; | ||
319 | PageBase1 = EEPROM_PAGE1_BASE; | ||
320 | PageSize = EEPROM_PAGE_SIZE; | ||
321 | Status = EEPROM_NOT_INIT; | ||
322 | }*/ | ||
323 | /* | ||
324 | uint16_t EEPROM_init(uint32_t pageBase0, uint32_t pageBase1, uint32_t pageSize) | ||
325 | { | ||
326 | PageBase0 = pageBase0; | ||
327 | PageBase1 = pageBase1; | ||
328 | PageSize = pageSize; | ||
329 | return EEPROM_init(); | ||
330 | }*/ | ||
331 | |||
332 | uint16_t EEPROM_init(void) | ||
333 | { | ||
334 | uint16_t status0 = 6, status1 = 6; | ||
335 | FLASH_Status FlashStatus; | ||
336 | |||
337 | FLASH_Unlock(); | ||
338 | Status = EEPROM_NO_VALID_PAGE; | ||
339 | |||
340 | status0 = (*(__IO uint16_t *)PageBase0); | ||
341 | status1 = (*(__IO uint16_t *)PageBase1); | ||
342 | |||
343 | switch (status0) | ||
344 | { | ||
345 | /* | ||
346 | Page0 Page1 | ||
347 | ----- ----- | ||
348 | EEPROM_ERASED EEPROM_VALID_PAGE Page1 valid, Page0 erased | ||
349 | EEPROM_RECEIVE_DATA Page1 need set to valid, Page0 erased | ||
350 | EEPROM_ERASED make EE_Format | ||
351 | any Error: EEPROM_NO_VALID_PAGE | ||
352 | */ | ||
353 | case EEPROM_ERASED: | ||
354 | if (status1 == EEPROM_VALID_PAGE) // Page0 erased, Page1 valid | ||
355 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
356 | else if (status1 == EEPROM_RECEIVE_DATA) // Page0 erased, Page1 receive | ||
357 | { | ||
358 | FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); | ||
359 | if (FlashStatus != FLASH_COMPLETE) | ||
360 | Status = FlashStatus; | ||
361 | else | ||
362 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
363 | } | ||
364 | else if (status1 == EEPROM_ERASED) // Both in erased state so format EEPROM | ||
365 | Status = EEPROM_format(); | ||
366 | break; | ||
367 | /* | ||
368 | Page0 Page1 | ||
369 | ----- ----- | ||
370 | EEPROM_RECEIVE_DATA EEPROM_VALID_PAGE Transfer Page1 to Page0 | ||
371 | EEPROM_ERASED Page0 need set to valid, Page1 erased | ||
372 | any EEPROM_NO_VALID_PAGE | ||
373 | */ | ||
374 | case EEPROM_RECEIVE_DATA: | ||
375 | if (status1 == EEPROM_VALID_PAGE) // Page0 receive, Page1 valid | ||
376 | Status = EE_PageTransfer(PageBase0, PageBase1, 0xFFFF); | ||
377 | else if (status1 == EEPROM_ERASED) // Page0 receive, Page1 erased | ||
378 | { | ||
379 | Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
380 | if (Status == EEPROM_OK) | ||
381 | { | ||
382 | FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); | ||
383 | if (FlashStatus != FLASH_COMPLETE) | ||
384 | Status = FlashStatus; | ||
385 | else | ||
386 | Status = EEPROM_OK; | ||
387 | } | ||
388 | } | ||
389 | break; | ||
390 | /* | ||
391 | Page0 Page1 | ||
392 | ----- ----- | ||
393 | EEPROM_VALID_PAGE EEPROM_VALID_PAGE Error: EEPROM_NO_VALID_PAGE | ||
394 | EEPROM_RECEIVE_DATA Transfer Page0 to Page1 | ||
395 | any Page0 valid, Page1 erased | ||
396 | */ | ||
397 | case EEPROM_VALID_PAGE: | ||
398 | if (status1 == EEPROM_VALID_PAGE) // Both pages valid | ||
399 | Status = EEPROM_NO_VALID_PAGE; | ||
400 | else if (status1 == EEPROM_RECEIVE_DATA) | ||
401 | Status = EE_PageTransfer(PageBase1, PageBase0, 0xFFFF); | ||
402 | else | ||
403 | Status = EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
404 | break; | ||
405 | /* | ||
406 | Page0 Page1 | ||
407 | ----- ----- | ||
408 | any EEPROM_VALID_PAGE Page1 valid, Page0 erased | ||
409 | EEPROM_RECEIVE_DATA Page1 valid, Page0 erased | ||
410 | any EEPROM_NO_VALID_PAGE | ||
411 | */ | ||
412 | default: | ||
413 | if (status1 == EEPROM_VALID_PAGE) | ||
414 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); // Check/Erase Page0 | ||
415 | else if (status1 == EEPROM_RECEIVE_DATA) | ||
416 | { | ||
417 | FlashStatus = FLASH_ProgramHalfWord(PageBase1, EEPROM_VALID_PAGE); | ||
418 | if (FlashStatus != FLASH_COMPLETE) | ||
419 | Status = FlashStatus; | ||
420 | else | ||
421 | Status = EE_CheckErasePage(PageBase0, EEPROM_ERASED); | ||
422 | } | ||
423 | break; | ||
424 | } | ||
425 | return Status; | ||
426 | } | ||
427 | |||
428 | /** | ||
429 | * @brief Erases PAGE0 and PAGE1 and writes EEPROM_VALID_PAGE / 0 header to PAGE0 | ||
430 | * @param PAGE0 and PAGE1 base addresses | ||
431 | * @retval Status of the last operation (Flash write or erase) done during EEPROM formating | ||
432 | */ | ||
433 | uint16_t EEPROM_format(void) | ||
434 | { | ||
435 | uint16_t status; | ||
436 | FLASH_Status FlashStatus; | ||
437 | |||
438 | FLASH_Unlock(); | ||
439 | |||
440 | // Erase Page0 | ||
441 | status = EE_CheckErasePage(PageBase0, EEPROM_VALID_PAGE); | ||
442 | if (status != EEPROM_OK) | ||
443 | return status; | ||
444 | if ((*(__IO uint16_t*)PageBase0) == EEPROM_ERASED) | ||
445 | { | ||
446 | // Set Page0 as valid page: Write VALID_PAGE at Page0 base address | ||
447 | FlashStatus = FLASH_ProgramHalfWord(PageBase0, EEPROM_VALID_PAGE); | ||
448 | if (FlashStatus != FLASH_COMPLETE) | ||
449 | return FlashStatus; | ||
450 | } | ||
451 | // Erase Page1 | ||
452 | return EE_CheckErasePage(PageBase1, EEPROM_ERASED); | ||
453 | } | ||
454 | |||
455 | /** | ||
456 | * @brief Returns the erase counter for current page | ||
457 | * @param Data: Global variable contains the read variable value | ||
458 | * @retval Success or error status: | ||
459 | * - EEPROM_OK: if erases counter return. | ||
460 | * - EEPROM_NO_VALID_PAGE: if no valid page was found. | ||
461 | */ | ||
462 | uint16_t EEPROM_erases(uint16_t *Erases) | ||
463 | { | ||
464 | uint32_t pageBase; | ||
465 | if (Status != EEPROM_OK) | ||
466 | if (EEPROM_init() != EEPROM_OK) | ||
467 | return Status; | ||
468 | |||
469 | // Get active Page for read operation | ||
470 | pageBase = EE_FindValidPage(); | ||
471 | if (pageBase == 0) | ||
472 | return EEPROM_NO_VALID_PAGE; | ||
473 | |||
474 | *Erases = (*(__IO uint16_t*)pageBase+2); | ||
475 | return EEPROM_OK; | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * @brief Returns the last stored variable data, if found, | ||
480 | * which correspond to the passed virtual address | ||
481 | * @param Address: Variable virtual address | ||
482 | * @retval Data for variable or EEPROM_DEFAULT_DATA, if any errors | ||
483 | */ | ||
484 | /* | ||
485 | uint16_t EEPROM_read (uint16_t Address) | ||
486 | { | ||
487 | uint16_t data; | ||
488 | EEPROM_read(Address, &data); | ||
489 | return data; | ||
490 | }*/ | ||
491 | |||
492 | /** | ||
493 | * @brief Returns the last stored variable data, if found, | ||
494 | * which correspond to the passed virtual address | ||
495 | * @param Address: Variable virtual address | ||
496 | * @param Data: Pointer to data variable | ||
497 | * @retval Success or error status: | ||
498 | * - EEPROM_OK: if variable was found | ||
499 | * - EEPROM_BAD_ADDRESS: if the variable was not found | ||
500 | * - EEPROM_NO_VALID_PAGE: if no valid page was found. | ||
501 | */ | ||
502 | uint16_t EEPROM_read(uint16_t Address, uint16_t *Data) | ||
503 | { | ||
504 | uint32_t pageBase, pageEnd; | ||
505 | |||
506 | // Set default data (empty EEPROM) | ||
507 | *Data = EEPROM_DEFAULT_DATA; | ||
508 | |||
509 | if (Status == EEPROM_NOT_INIT) | ||
510 | if (EEPROM_init() != EEPROM_OK) | ||
511 | return Status; | ||
512 | |||
513 | // Get active Page for read operation | ||
514 | pageBase = EE_FindValidPage(); | ||
515 | if (pageBase == 0) | ||
516 | return EEPROM_NO_VALID_PAGE; | ||
517 | |||
518 | // Get the valid Page end Address | ||
519 | pageEnd = pageBase + ((uint32_t)(PageSize - 2)); | ||
520 | |||
521 | // Check each active page address starting from end | ||
522 | for (pageBase += 6; pageEnd >= pageBase; pageEnd -= 4) | ||
523 | if ((*(__IO uint16_t*)pageEnd) == Address) // Compare the read address with the virtual address | ||
524 | { | ||
525 | *Data = (*(__IO uint16_t*)(pageEnd - 2)); // Get content of Address-2 which is variable value | ||
526 | return EEPROM_OK; | ||
527 | } | ||
528 | |||
529 | // Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) | ||
530 | return EEPROM_BAD_ADDRESS; | ||
531 | } | ||
532 | |||
533 | /** | ||
534 | * @brief Writes/upadtes variable data in EEPROM. | ||
535 | * @param VirtAddress: Variable virtual address | ||
536 | * @param Data: 16 bit data to be written | ||
537 | * @retval Success or error status: | ||
538 | * - FLASH_COMPLETE: on success | ||
539 | * - EEPROM_BAD_ADDRESS: if address = 0xFFFF | ||
540 | * - EEPROM_PAGE_FULL: if valid page is full | ||
541 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
542 | * - EEPROM_OUT_SIZE: if no empty EEPROM variables | ||
543 | * - Flash error code: on write Flash error | ||
544 | */ | ||
545 | uint16_t EEPROM_write(uint16_t Address, uint16_t Data) | ||
546 | { | ||
547 | if (Status == EEPROM_NOT_INIT) | ||
548 | if (EEPROM_init() != EEPROM_OK) | ||
549 | return Status; | ||
550 | |||
551 | if (Address == 0xFFFF) | ||
552 | return EEPROM_BAD_ADDRESS; | ||
553 | |||
554 | // Write the variable virtual address and value in the EEPROM | ||
555 | uint16_t status = EE_VerifyPageFullWriteVariable(Address, Data); | ||
556 | return status; | ||
557 | } | ||
558 | |||
559 | /** | ||
560 | * @brief Writes/upadtes variable data in EEPROM. | ||
561 | The value is written only if differs from the one already saved at the same address. | ||
562 | * @param VirtAddress: Variable virtual address | ||
563 | * @param Data: 16 bit data to be written | ||
564 | * @retval Success or error status: | ||
565 | * - EEPROM_SAME_VALUE: If new Data matches existing EEPROM Data | ||
566 | * - FLASH_COMPLETE: on success | ||
567 | * - EEPROM_BAD_ADDRESS: if address = 0xFFFF | ||
568 | * - EEPROM_PAGE_FULL: if valid page is full | ||
569 | * - EEPROM_NO_VALID_PAGE: if no valid page was found | ||
570 | * - EEPROM_OUT_SIZE: if no empty EEPROM variables | ||
571 | * - Flash error code: on write Flash error | ||
572 | */ | ||
573 | uint16_t EEPROM_update(uint16_t Address, uint16_t Data) | ||
574 | { | ||
575 | uint16_t temp; | ||
576 | EEPROM_read(Address, &temp); | ||
577 | if (Address == Data) | ||
578 | return EEPROM_SAME_VALUE; | ||
579 | else | ||
580 | return EEPROM_write(Address, Data); | ||
581 | } | ||
582 | |||
583 | /** | ||
584 | * @brief Return number of variable | ||
585 | * @retval Number of variables | ||
586 | */ | ||
587 | uint16_t EEPROM_count(uint16_t *Count) | ||
588 | { | ||
589 | if (Status == EEPROM_NOT_INIT) | ||
590 | if (EEPROM_init() != EEPROM_OK) | ||
591 | return Status; | ||
592 | |||
593 | // Get valid Page for write operation | ||
594 | uint32_t pageBase = EE_FindValidPage(); | ||
595 | if (pageBase == 0) | ||
596 | return EEPROM_NO_VALID_PAGE; // No valid page, return max. numbers | ||
597 | |||
598 | *Count = EE_GetVariablesCount(pageBase, 0xFFFF); | ||
599 | return EEPROM_OK; | ||
600 | } | ||
601 | |||
602 | uint16_t EEPROM_maxcount(void) | ||
603 | { | ||
604 | return ((PageSize / 4)-1); | ||
605 | } | ||
606 | |||
607 | |||
608 | uint8_t eeprom_read_byte (const uint8_t *Address) | ||
609 | { | ||
610 | const uint16_t p = (const uint32_t) Address; | ||
611 | uint16_t temp; | ||
612 | EEPROM_read(p, &temp); | ||
613 | return (uint8_t) temp; | ||
614 | } | ||
615 | |||
616 | void eeprom_write_byte (uint8_t *Address, uint8_t Value) | ||
617 | { | ||
618 | uint16_t p = (uint32_t) Address; | ||
619 | EEPROM_write(p, (uint16_t) Value); | ||
620 | } | ||
621 | |||
622 | void eeprom_update_byte (uint8_t *Address, uint8_t Value) | ||
623 | { | ||
624 | uint16_t p = (uint32_t) Address; | ||
625 | EEPROM_update(p, (uint16_t) Value); | ||
626 | } | ||
627 | |||
628 | uint16_t eeprom_read_word (const uint16_t *Address) | ||
629 | { | ||
630 | const uint16_t p = (const uint32_t) Address; | ||
631 | uint16_t temp; | ||
632 | EEPROM_read(p, &temp); | ||
633 | return temp; | ||
634 | } | ||
635 | |||
636 | void eeprom_write_word (uint16_t *Address, uint16_t Value) | ||
637 | { | ||
638 | uint16_t p = (uint32_t) Address; | ||
639 | EEPROM_write(p, Value); | ||
640 | } | ||
641 | |||
642 | void eeprom_update_word (uint16_t *Address, uint16_t Value) | ||
643 | { | ||
644 | uint16_t p = (uint32_t) Address; | ||
645 | EEPROM_update(p, Value); | ||
646 | } | ||
647 | |||
648 | uint32_t eeprom_read_dword (const uint32_t *Address) | ||
649 | { | ||
650 | const uint16_t p = (const uint32_t) Address; | ||
651 | uint16_t temp1, temp2; | ||
652 | EEPROM_read(p, &temp1); | ||
653 | EEPROM_read(p + 1, &temp2); | ||
654 | return temp1 | (temp2 << 16); | ||
655 | } | ||
656 | |||
657 | void eeprom_write_dword (uint32_t *Address, uint32_t Value) | ||
658 | { | ||
659 | uint16_t temp = (uint16_t) Value; | ||
660 | uint16_t p = (uint32_t) Address; | ||
661 | EEPROM_write(p, temp); | ||
662 | temp = (uint16_t) (Value >> 16); | ||
663 | EEPROM_write(p + 1, temp); | ||
664 | } | ||
665 | |||
666 | void eeprom_update_dword (uint32_t *Address, uint32_t Value) | ||
667 | { | ||
668 | uint16_t temp = (uint16_t) Value; | ||
669 | uint16_t p = (uint32_t) Address; | ||
670 | EEPROM_update(p, temp); | ||
671 | temp = (uint16_t) (Value >> 16); | ||
672 | EEPROM_update(p + 1, temp); | ||
673 | } | ||
diff --git a/tmk_core/common/chibios/eeprom_stm32.h b/tmk_core/common/chibios/eeprom_stm32.h new file mode 100755 index 000000000..d06d30266 --- /dev/null +++ b/tmk_core/common/chibios/eeprom_stm32.h | |||
@@ -0,0 +1,89 @@ | |||
1 | /* | ||
2 | * This software is experimental and a work in progress. | ||
3 | * Under no circumstances should these files be used in relation to any critical system(s). | ||
4 | * Use of these files is at your own risk. | ||
5 | * | ||
6 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
7 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
8 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
9 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
11 | * DEALINGS IN THE SOFTWARE. | ||
12 | * | ||
13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | ||
14 | * https://github.com/leaflabs/libmaple | ||
15 | * | ||
16 | * Modifications for QMK and STM32F303 by Yiancar | ||
17 | */ | ||
18 | |||
19 | // This file must be modified if the MCU is not defined below. | ||
20 | // This library also assumes that the pages are not used by the firmware. | ||
21 | |||
22 | #ifndef __EEPROM_H | ||
23 | #define __EEPROM_H | ||
24 | |||
25 | #include "ch.h" | ||
26 | #include "hal.h" | ||
27 | #include "flash_stm32.h" | ||
28 | |||
29 | // HACK ALERT. This definition may not match your processor | ||
30 | // To Do. Work out correct value for EEPROM_PAGE_SIZE on the STM32F103CT6 etc | ||
31 | #define MCU_STM32F303CC | ||
32 | |||
33 | #ifndef EEPROM_PAGE_SIZE | ||
34 | #if defined (MCU_STM32F103RB) | ||
35 | #define EEPROM_PAGE_SIZE (uint16_t)0x400 /* Page size = 1KByte */ | ||
36 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) || defined (MCU_STM32F103RD) || defined (MCU_STM32F303CC) | ||
37 | #define EEPROM_PAGE_SIZE (uint16_t)0x800 /* Page size = 2KByte */ | ||
38 | #else | ||
39 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." | ||
40 | #endif | ||
41 | #endif | ||
42 | |||
43 | #ifndef EEPROM_START_ADDRESS | ||
44 | #if defined (MCU_STM32F103RB) | ||
45 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 128 * 1024 - 2 * EEPROM_PAGE_SIZE)) | ||
46 | #elif defined (MCU_STM32F103ZE) || defined (MCU_STM32F103RE) | ||
47 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 512 * 1024 - 2 * EEPROM_PAGE_SIZE)) | ||
48 | #elif defined (MCU_STM32F103RD) | ||
49 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 384 * 1024 - 2 * EEPROM_PAGE_SIZE)) | ||
50 | #elif defined (MCU_STM32F303CC) | ||
51 | #define EEPROM_START_ADDRESS ((uint32_t)(0x8000000 + 250 * 1024 - 2 * EEPROM_PAGE_SIZE)) | ||
52 | #else | ||
53 | #error "No MCU type specified. Add something like -DMCU_STM32F103RB to your compiler arguments (probably in a Makefile)." | ||
54 | #endif | ||
55 | #endif | ||
56 | |||
57 | /* Pages 0 and 1 base and end addresses */ | ||
58 | #define EEPROM_PAGE0_BASE ((uint32_t)(EEPROM_START_ADDRESS + 0x000)) | ||
59 | #define EEPROM_PAGE1_BASE ((uint32_t)(EEPROM_START_ADDRESS + EEPROM_PAGE_SIZE)) | ||
60 | |||
61 | /* Page status definitions */ | ||
62 | #define EEPROM_ERASED ((uint16_t)0xFFFF) /* PAGE is empty */ | ||
63 | #define EEPROM_RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */ | ||
64 | #define EEPROM_VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */ | ||
65 | |||
66 | /* Page full define */ | ||
67 | enum uint16_t | ||
68 | { | ||
69 | EEPROM_OK = ((uint16_t)0x0000), | ||
70 | EEPROM_OUT_SIZE = ((uint16_t)0x0081), | ||
71 | EEPROM_BAD_ADDRESS = ((uint16_t)0x0082), | ||
72 | EEPROM_BAD_FLASH = ((uint16_t)0x0083), | ||
73 | EEPROM_NOT_INIT = ((uint16_t)0x0084), | ||
74 | EEPROM_SAME_VALUE = ((uint16_t)0x0085), | ||
75 | EEPROM_NO_VALID_PAGE = ((uint16_t)0x00AB) | ||
76 | }; | ||
77 | |||
78 | #define EEPROM_DEFAULT_DATA 0xFFFF | ||
79 | |||
80 | uint16_t EEPROM_init(void); | ||
81 | uint16_t EEPROM_format(void); | ||
82 | uint16_t EEPROM_erases(uint16_t *); | ||
83 | uint16_t EEPROM_read (uint16_t address, uint16_t *data); | ||
84 | uint16_t EEPROM_write(uint16_t address, uint16_t data); | ||
85 | uint16_t EEPROM_update(uint16_t address, uint16_t data); | ||
86 | uint16_t EEPROM_count(uint16_t *); | ||
87 | uint16_t EEPROM_maxcount(void); | ||
88 | |||
89 | #endif /* __EEPROM_H */ | ||
diff --git a/tmk_core/common/chibios/eeprom.c b/tmk_core/common/chibios/eeprom_teensy.c index 9061b790c..9061b790c 100644 --- a/tmk_core/common/chibios/eeprom.c +++ b/tmk_core/common/chibios/eeprom_teensy.c | |||
diff --git a/tmk_core/common/chibios/flash_stm32.c b/tmk_core/common/chibios/flash_stm32.c new file mode 100755 index 000000000..e7199ac7b --- /dev/null +++ b/tmk_core/common/chibios/flash_stm32.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * This software is experimental and a work in progress. | ||
3 | * Under no circumstances should these files be used in relation to any critical system(s). | ||
4 | * Use of these files is at your own risk. | ||
5 | * | ||
6 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
7 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
8 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
9 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
11 | * DEALINGS IN THE SOFTWARE. | ||
12 | * | ||
13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | ||
14 | * https://github.com/leaflabs/libmaple | ||
15 | * | ||
16 | * Modifications for QMK and STM32F303 by Yiancar | ||
17 | */ | ||
18 | |||
19 | #define STM32F303xC | ||
20 | |||
21 | #include "stm32f3xx.h" | ||
22 | #include "flash_stm32.h" | ||
23 | |||
24 | #define FLASH_KEY1 ((uint32_t)0x45670123) | ||
25 | #define FLASH_KEY2 ((uint32_t)0xCDEF89AB) | ||
26 | |||
27 | /* Delay definition */ | ||
28 | #define EraseTimeout ((uint32_t)0x00000FFF) | ||
29 | #define ProgramTimeout ((uint32_t)0x0000001F) | ||
30 | |||
31 | #define ASSERT(exp) (void)((0)) | ||
32 | |||
33 | /** | ||
34 | * @brief Inserts a time delay. | ||
35 | * @param None | ||
36 | * @retval None | ||
37 | */ | ||
38 | static void delay(void) | ||
39 | { | ||
40 | __IO uint32_t i = 0; | ||
41 | for(i = 0xFF; i != 0; i--) { } | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * @brief Returns the FLASH Status. | ||
46 | * @param None | ||
47 | * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, | ||
48 | * FLASH_ERROR_WRP or FLASH_COMPLETE | ||
49 | */ | ||
50 | FLASH_Status FLASH_GetStatus(void) | ||
51 | { | ||
52 | if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) | ||
53 | return FLASH_BUSY; | ||
54 | |||
55 | if ((FLASH->SR & FLASH_SR_PGERR) != 0) | ||
56 | return FLASH_ERROR_PG; | ||
57 | |||
58 | if ((FLASH->SR & FLASH_SR_WRPERR) != 0 ) | ||
59 | return FLASH_ERROR_WRP; | ||
60 | |||
61 | if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 ) | ||
62 | return FLASH_ERROR_OPT; | ||
63 | |||
64 | return FLASH_COMPLETE; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * @brief Waits for a Flash operation to complete or a TIMEOUT to occur. | ||
69 | * @param Timeout: FLASH progamming Timeout | ||
70 | * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, | ||
71 | * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. | ||
72 | */ | ||
73 | FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) | ||
74 | { | ||
75 | FLASH_Status status; | ||
76 | |||
77 | /* Check for the Flash Status */ | ||
78 | status = FLASH_GetStatus(); | ||
79 | /* Wait for a Flash operation to complete or a TIMEOUT to occur */ | ||
80 | while ((status == FLASH_BUSY) && (Timeout != 0x00)) | ||
81 | { | ||
82 | delay(); | ||
83 | status = FLASH_GetStatus(); | ||
84 | Timeout--; | ||
85 | } | ||
86 | if (Timeout == 0) | ||
87 | status = FLASH_TIMEOUT; | ||
88 | /* Return the operation status */ | ||
89 | return status; | ||
90 | } | ||
91 | |||
92 | /** | ||
93 | * @brief Erases a specified FLASH page. | ||
94 | * @param Page_Address: The page address to be erased. | ||
95 | * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG, | ||
96 | * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. | ||
97 | */ | ||
98 | FLASH_Status FLASH_ErasePage(uint32_t Page_Address) | ||
99 | { | ||
100 | FLASH_Status status = FLASH_COMPLETE; | ||
101 | /* Check the parameters */ | ||
102 | ASSERT(IS_FLASH_ADDRESS(Page_Address)); | ||
103 | /* Wait for last operation to be completed */ | ||
104 | status = FLASH_WaitForLastOperation(EraseTimeout); | ||
105 | |||
106 | if(status == FLASH_COMPLETE) | ||
107 | { | ||
108 | /* if the previous operation is completed, proceed to erase the page */ | ||
109 | FLASH->CR |= FLASH_CR_PER; | ||
110 | FLASH->AR = Page_Address; | ||
111 | FLASH->CR |= FLASH_CR_STRT; | ||
112 | |||
113 | /* Wait for last operation to be completed */ | ||
114 | status = FLASH_WaitForLastOperation(EraseTimeout); | ||
115 | if(status != FLASH_TIMEOUT) | ||
116 | { | ||
117 | /* if the erase operation is completed, disable the PER Bit */ | ||
118 | FLASH->CR &= ~FLASH_CR_PER; | ||
119 | } | ||
120 | FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR); | ||
121 | } | ||
122 | /* Return the Erase Status */ | ||
123 | return status; | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * @brief Programs a half word at a specified address. | ||
128 | * @param Address: specifies the address to be programmed. | ||
129 | * @param Data: specifies the data to be programmed. | ||
130 | * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, | ||
131 | * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. | ||
132 | */ | ||
133 | FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) | ||
134 | { | ||
135 | FLASH_Status status = FLASH_BAD_ADDRESS; | ||
136 | |||
137 | if (IS_FLASH_ADDRESS(Address)) | ||
138 | { | ||
139 | /* Wait for last operation to be completed */ | ||
140 | status = FLASH_WaitForLastOperation(ProgramTimeout); | ||
141 | if(status == FLASH_COMPLETE) | ||
142 | { | ||
143 | /* if the previous operation is completed, proceed to program the new data */ | ||
144 | FLASH->CR |= FLASH_CR_PG; | ||
145 | *(__IO uint16_t*)Address = Data; | ||
146 | /* Wait for last operation to be completed */ | ||
147 | status = FLASH_WaitForLastOperation(ProgramTimeout); | ||
148 | if(status != FLASH_TIMEOUT) | ||
149 | { | ||
150 | /* if the program operation is completed, disable the PG Bit */ | ||
151 | FLASH->CR &= ~FLASH_CR_PG; | ||
152 | } | ||
153 | FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR); | ||
154 | } | ||
155 | } | ||
156 | return status; | ||
157 | } | ||
158 | |||
159 | /** | ||
160 | * @brief Unlocks the FLASH Program Erase Controller. | ||
161 | * @param None | ||
162 | * @retval None | ||
163 | */ | ||
164 | void FLASH_Unlock(void) | ||
165 | { | ||
166 | /* Authorize the FPEC Access */ | ||
167 | FLASH->KEYR = FLASH_KEY1; | ||
168 | FLASH->KEYR = FLASH_KEY2; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * @brief Locks the FLASH Program Erase Controller. | ||
173 | * @param None | ||
174 | * @retval None | ||
175 | */ | ||
176 | void FLASH_Lock(void) | ||
177 | { | ||
178 | /* Set the Lock Bit to lock the FPEC and the FCR */ | ||
179 | FLASH->CR |= FLASH_CR_LOCK; | ||
180 | } | ||
diff --git a/tmk_core/common/chibios/flash_stm32.h b/tmk_core/common/chibios/flash_stm32.h new file mode 100755 index 000000000..cc065cbca --- /dev/null +++ b/tmk_core/common/chibios/flash_stm32.h | |||
@@ -0,0 +1,53 @@ | |||
1 | /* | ||
2 | * This software is experimental and a work in progress. | ||
3 | * Under no circumstances should these files be used in relation to any critical system(s). | ||
4 | * Use of these files is at your own risk. | ||
5 | * | ||
6 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, | ||
7 | * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
8 | * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||
9 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||
10 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
11 | * DEALINGS IN THE SOFTWARE. | ||
12 | * | ||
13 | * This files are free to use from https://github.com/rogerclarkmelbourne/Arduino_STM32 and | ||
14 | * https://github.com/leaflabs/libmaple | ||
15 | * | ||
16 | * Modifications for QMK and STM32F303 by Yiancar | ||
17 | */ | ||
18 | |||
19 | #ifndef __FLASH_STM32_H | ||
20 | #define __FLASH_STM32_H | ||
21 | |||
22 | #ifdef __cplusplus | ||
23 | extern "C" { | ||
24 | #endif | ||
25 | |||
26 | #include "ch.h" | ||
27 | #include "hal.h" | ||
28 | |||
29 | typedef enum | ||
30 | { | ||
31 | FLASH_BUSY = 1, | ||
32 | FLASH_ERROR_PG, | ||
33 | FLASH_ERROR_WRP, | ||
34 | FLASH_ERROR_OPT, | ||
35 | FLASH_COMPLETE, | ||
36 | FLASH_TIMEOUT, | ||
37 | FLASH_BAD_ADDRESS | ||
38 | } FLASH_Status; | ||
39 | |||
40 | #define IS_FLASH_ADDRESS(ADDRESS) (((ADDRESS) >= 0x08000000) && ((ADDRESS) < 0x0807FFFF)) | ||
41 | |||
42 | FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout); | ||
43 | FLASH_Status FLASH_ErasePage(uint32_t Page_Address); | ||
44 | FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data); | ||
45 | |||
46 | void FLASH_Unlock(void); | ||
47 | void FLASH_Lock(void); | ||
48 | |||
49 | #ifdef __cplusplus | ||
50 | } | ||
51 | #endif | ||
52 | |||
53 | #endif /* __FLASH_STM32_H */ | ||
diff --git a/tmk_core/common/eeconfig.c b/tmk_core/common/eeconfig.c index 3e5987ee3..35de574a9 100644 --- a/tmk_core/common/eeconfig.c +++ b/tmk_core/common/eeconfig.c | |||
@@ -3,12 +3,20 @@ | |||
3 | #include "eeprom.h" | 3 | #include "eeprom.h" |
4 | #include "eeconfig.h" | 4 | #include "eeconfig.h" |
5 | 5 | ||
6 | #ifdef STM32F303xC | ||
7 | #include "hal.h" | ||
8 | #include "eeprom_stm32.h" | ||
9 | #endif | ||
10 | |||
6 | /** \brief eeconfig initialization | 11 | /** \brief eeconfig initialization |
7 | * | 12 | * |
8 | * FIXME: needs doc | 13 | * FIXME: needs doc |
9 | */ | 14 | */ |
10 | void eeconfig_init(void) | 15 | void eeconfig_init(void) |
11 | { | 16 | { |
17 | #ifdef STM32F303xC | ||
18 | EEPROM_format(); | ||
19 | #endif | ||
12 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); | 20 | eeprom_update_word(EECONFIG_MAGIC, EECONFIG_MAGIC_NUMBER); |
13 | eeprom_update_byte(EECONFIG_DEBUG, 0); | 21 | eeprom_update_byte(EECONFIG_DEBUG, 0); |
14 | eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0); | 22 | eeprom_update_byte(EECONFIG_DEFAULT_LAYER, 0); |
@@ -43,6 +51,9 @@ void eeconfig_enable(void) | |||
43 | */ | 51 | */ |
44 | void eeconfig_disable(void) | 52 | void eeconfig_disable(void) |
45 | { | 53 | { |
54 | #ifdef STM32F303xC | ||
55 | EEPROM_format(); | ||
56 | #endif | ||
46 | eeprom_update_word(EECONFIG_MAGIC, 0xFFFF); | 57 | eeprom_update_word(EECONFIG_MAGIC, 0xFFFF); |
47 | } | 58 | } |
48 | 59 | ||
diff --git a/tmk_core/common/eeconfig.h b/tmk_core/common/eeconfig.h index 1397a90c7..fa498df48 100644 --- a/tmk_core/common/eeconfig.h +++ b/tmk_core/common/eeconfig.h | |||
@@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
25 | #define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED | 25 | #define EECONFIG_MAGIC_NUMBER (uint16_t)0xFEED |
26 | 26 | ||
27 | /* eeprom parameteter address */ | 27 | /* eeprom parameteter address */ |
28 | #if !defined(STM32F303xC) | ||
28 | #define EECONFIG_MAGIC (uint16_t *)0 | 29 | #define EECONFIG_MAGIC (uint16_t *)0 |
29 | #define EECONFIG_DEBUG (uint8_t *)2 | 30 | #define EECONFIG_DEBUG (uint8_t *)2 |
30 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)3 | 31 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)3 |
@@ -38,6 +39,21 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
38 | // EEHANDS for two handed boards | 39 | // EEHANDS for two handed boards |
39 | #define EECONFIG_HANDEDNESS (uint8_t *)14 | 40 | #define EECONFIG_HANDEDNESS (uint8_t *)14 |
40 | 41 | ||
42 | #else | ||
43 | /* STM32F3 uses 16byte block. Reconfigure memory map */ | ||
44 | #define EECONFIG_MAGIC (uint16_t *)0 | ||
45 | #define EECONFIG_DEBUG (uint8_t *)1 | ||
46 | #define EECONFIG_DEFAULT_LAYER (uint8_t *)2 | ||
47 | #define EECONFIG_KEYMAP (uint8_t *)3 | ||
48 | #define EECONFIG_MOUSEKEY_ACCEL (uint8_t *)4 | ||
49 | #define EECONFIG_BACKLIGHT (uint8_t *)5 | ||
50 | #define EECONFIG_AUDIO (uint8_t *)6 | ||
51 | #define EECONFIG_RGBLIGHT (uint32_t *)7 | ||
52 | #define EECONFIG_UNICODEMODE (uint8_t *)9 | ||
53 | #define EECONFIG_STENOMODE (uint8_t *)10 | ||
54 | // EEHANDS for two handed boards | ||
55 | #define EECONFIG_HANDEDNESS (uint8_t *)11 | ||
56 | #endif | ||
41 | 57 | ||
42 | /* debug bit */ | 58 | /* debug bit */ |
43 | #define EECONFIG_DEBUG_ENABLE (1<<0) | 59 | #define EECONFIG_DEBUG_ENABLE (1<<0) |
diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index f2abc438d..568c1edb2 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c | |||
@@ -44,6 +44,9 @@ | |||
44 | #ifdef MIDI_ENABLE | 44 | #ifdef MIDI_ENABLE |
45 | #include "qmk_midi.h" | 45 | #include "qmk_midi.h" |
46 | #endif | 46 | #endif |
47 | #ifdef STM32F303xC | ||
48 | #include "eeprom_stm32.h" | ||
49 | #endif | ||
47 | #include "suspend.h" | 50 | #include "suspend.h" |
48 | #include "wait.h" | 51 | #include "wait.h" |
49 | 52 | ||
@@ -109,6 +112,10 @@ int main(void) { | |||
109 | halInit(); | 112 | halInit(); |
110 | chSysInit(); | 113 | chSysInit(); |
111 | 114 | ||
115 | #ifdef STM32F303xC | ||
116 | EEPROM_init(); | ||
117 | #endif | ||
118 | |||
112 | // TESTING | 119 | // TESTING |
113 | // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); | 120 | // chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL); |
114 | 121 | ||