]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/chibios/eeprom_stm32.c
Remove more commented out MCUs
[qmk_firmware.git] / tmk_core / common / chibios / eeprom_stm32.c
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 http://engsta.com/stm32-flash-memory-eeprom-emulator/ by
14  * Artur F.
15  *
16  * Modifications for QMK and STM32F303 by Yiancar
17  */
18
19 #include <stdio.h>
20 #include <string.h>
21 #include "eeprom_stm32.h"
22 /*****************************************************************************
23  * Allows to use the internal flash to store non volatile data. To initialize
24  * the functionality use the EEPROM_Init() function. Be sure that by reprogramming
25  * of the controller just affected pages will be deleted. In other case the non
26  * volatile data will be lost.
27 ******************************************************************************/
28
29 /* Private macro -------------------------------------------------------------*/
30 /* Private variables ---------------------------------------------------------*/
31 /* Functions -----------------------------------------------------------------*/
32
33 uint8_t DataBuf[FEE_PAGE_SIZE];
34 /*****************************************************************************
35 *  Delete Flash Space used for user Data, deletes the whole space between
36 *  RW_PAGE_BASE_ADDRESS and the last uC Flash Page
37 ******************************************************************************/
38 uint16_t EEPROM_Init(void) {
39     // unlock flash
40     FLASH_Unlock();
41
42     // Clear Flags
43     //FLASH_ClearFlag(FLASH_SR_EOP|FLASH_SR_PGERR|FLASH_SR_WRPERR);
44
45     return FEE_DENSITY_BYTES;
46 }
47 /*****************************************************************************
48 *  Erase the whole reserved Flash Space used for user Data
49 ******************************************************************************/
50 void EEPROM_Erase (void) {
51
52     int page_num = 0;
53
54     // delete all pages from specified start page to the last page
55     do {
56         FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page_num * FEE_PAGE_SIZE));
57         page_num++;
58     } while (page_num < FEE_DENSITY_PAGES);
59 }
60 /*****************************************************************************
61 *  Writes once data byte to flash on specified address. If a byte is already
62 *  written, the whole page must be copied to a buffer, the byte changed and
63 *  the manipulated buffer written after PageErase.
64 *******************************************************************************/
65 uint16_t EEPROM_WriteDataByte (uint16_t Address, uint8_t DataByte) {
66
67     FLASH_Status FlashStatus = FLASH_COMPLETE;
68
69     uint32_t page;
70     int i;
71
72     // exit if desired address is above the limit (e.G. under 2048 Bytes for 4 pages)
73     if (Address > FEE_DENSITY_BYTES) {
74         return 0;
75     }
76
77     // calculate which page is affected (Pagenum1/Pagenum2...PagenumN)
78     page = FEE_ADDR_OFFSET(Address) / FEE_PAGE_SIZE;
79
80     // if current data is 0xFF, the byte is empty, just overwrite with the new one
81     if ((*(__IO uint16_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) == FEE_EMPTY_WORD) {
82
83         FlashStatus = FLASH_ProgramHalfWord(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address), (uint16_t)(0x00FF & DataByte));
84     } else {
85
86         // Copy Page to a buffer
87         memcpy(DataBuf, (uint8_t*)FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE), FEE_PAGE_SIZE); // !!! Calculate base address for the desired page
88
89         // check if new data is differ to current data, return if not, proceed if yes
90         if (DataByte == *(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address))) {
91             return 0;
92         }
93
94         // manipulate desired data byte in temp data array if new byte is differ to the current
95         DataBuf[FEE_ADDR_OFFSET(Address) % FEE_PAGE_SIZE] = DataByte;
96
97         //Erase Page
98         FlashStatus = FLASH_ErasePage(FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE));
99
100         // Write new data (whole page) to flash if data has been changed
101         for(i = 0; i < (FEE_PAGE_SIZE / 2); i++) {
102             if ((__IO uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]) != 0xFFFF) {
103                 FlashStatus = FLASH_ProgramHalfWord((FEE_PAGE_BASE_ADDRESS + (page * FEE_PAGE_SIZE)) + (i * 2), (uint16_t)(0xFF00 | DataBuf[FEE_ADDR_OFFSET(i)]));
104             }
105         }
106     }
107     return FlashStatus;
108 }
109 /*****************************************************************************
110 *  Read once data byte from a specified address.
111 *******************************************************************************/
112 uint8_t EEPROM_ReadDataByte (uint16_t Address) {
113
114     uint8_t DataByte = 0xFF;
115
116     // Get Byte from specified address
117     DataByte = (*(__IO uint8_t*)(FEE_PAGE_BASE_ADDRESS + FEE_ADDR_OFFSET(Address)));
118
119     return DataByte;
120 }
121
122 /*****************************************************************************
123 *  Wrap library in AVR style functions.
124 *******************************************************************************/
125 uint8_t eeprom_read_byte (const uint8_t *Address)
126 {
127     const uint16_t p = (const uint32_t) Address;
128     return EEPROM_ReadDataByte(p);
129 }
130
131 void eeprom_write_byte (uint8_t *Address, uint8_t Value)
132 {
133     uint16_t p = (uint32_t) Address;
134     EEPROM_WriteDataByte(p, Value);
135 }
136
137 void eeprom_update_byte (uint8_t *Address, uint8_t Value)
138 {
139     uint16_t p = (uint32_t) Address;
140     EEPROM_WriteDataByte(p, Value);
141 }
142
143 uint16_t eeprom_read_word (const uint16_t *Address)
144 {
145     const uint16_t p = (const uint32_t) Address;
146     return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8);
147 }
148
149 void eeprom_write_word (uint16_t *Address, uint16_t Value)
150 {
151     uint16_t p = (uint32_t) Address;
152     EEPROM_WriteDataByte(p, (uint8_t) Value);
153     EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
154 }
155
156 void eeprom_update_word (uint16_t *Address, uint16_t Value)
157 {
158     uint16_t p = (uint32_t) Address;
159     EEPROM_WriteDataByte(p, (uint8_t) Value);
160     EEPROM_WriteDataByte(p + 1, (uint8_t) (Value >> 8));
161 }
162
163 uint32_t eeprom_read_dword (const uint32_t *Address)
164 {
165     const uint16_t p = (const uint32_t) Address;
166     return EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
167         | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
168 }
169
170 void eeprom_write_dword (uint32_t *Address, uint32_t Value)
171 {
172     uint16_t p = (const uint32_t) Address;
173     EEPROM_WriteDataByte(p, (uint8_t) Value);
174     EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
175     EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
176     EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
177 }
178
179 void eeprom_update_dword (uint32_t *Address, uint32_t Value)
180 {
181     uint16_t p = (const uint32_t) Address;
182     uint32_t existingValue = EEPROM_ReadDataByte(p) | (EEPROM_ReadDataByte(p+1) << 8)
183         | (EEPROM_ReadDataByte(p+2) << 16) | (EEPROM_ReadDataByte(p+3) << 24);
184     if(Value != existingValue){
185       EEPROM_WriteDataByte(p, (uint8_t) Value);
186       EEPROM_WriteDataByte(p+1, (uint8_t) (Value >> 8));
187       EEPROM_WriteDataByte(p+2, (uint8_t) (Value >> 16));
188       EEPROM_WriteDataByte(p+3, (uint8_t) (Value >> 24));
189     }
190 }
191
192 void eeprom_read_block(void *buf, const void *addr, uint32_t len) {
193     const uint8_t *p = (const uint8_t *)addr;
194     uint8_t *dest = (uint8_t *)buf;
195     while (len--) {
196         *dest++ = eeprom_read_byte(p++);
197     }
198 }
199
200 void eeprom_write_block(const void *buf, void *addr, uint32_t len) {
201     uint8_t *p = (uint8_t *)addr;
202     const uint8_t *src = (const uint8_t *)buf;
203     while (len--) {
204         eeprom_write_byte(p++, *src++);
205     }
206 }
207
208 void eeprom_update_block(const void *buf, void *addr, uint32_t len) {
209     uint8_t *p = (uint8_t *)addr;
210     const uint8_t *src = (const uint8_t *)buf;
211     while (len--) {
212         eeprom_write_byte(p++, *src++);
213     }
214 }