]> git.donarmstrong.com Git - qmk_firmware.git/blob - tmk_core/common/chibios/flash_stm32.c
stm32f1xx EEPROM emulation (#3914)
[qmk_firmware.git] / tmk_core / common / chibios / flash_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 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 #if defined(EEPROM_EMU_STM32F303xC)
20     #define STM32F303xC
21     #include "stm32f3xx.h"
22 #elif defined(EEPROM_EMU_STM32F103xB)
23     #define STM32F103xB
24     #include "stm32f1xx.h"
25 #else
26     #error "not implemented."
27 #endif
28
29 #include "flash_stm32.h"
30
31 #if defined(EEPROM_EMU_STM32F103xB)
32     #define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
33 #endif
34
35 /* Delay definition */
36 #define EraseTimeout        ((uint32_t)0x00000FFF)
37 #define ProgramTimeout      ((uint32_t)0x0000001F)
38
39 #define ASSERT(exp) (void)((0))
40
41 /**
42   * @brief  Inserts a time delay.
43   * @param  None
44   * @retval None
45   */
46 static void delay(void)
47 {
48     __IO uint32_t i = 0;
49     for(i = 0xFF; i != 0; i--) { }
50 }
51
52 /**
53   * @brief  Returns the FLASH Status.
54   * @param  None
55   * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
56   *   FLASH_ERROR_WRP or FLASH_COMPLETE
57   */
58 FLASH_Status FLASH_GetStatus(void)
59 {
60     if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY)
61         return FLASH_BUSY;
62
63     if ((FLASH->SR & FLASH_SR_PGERR) != 0)
64         return FLASH_ERROR_PG;
65
66     if ((FLASH->SR & FLASH_SR_WRPERR) != 0 )
67         return FLASH_ERROR_WRP;
68
69     if ((FLASH->SR & FLASH_OBR_OPTERR) != 0 )
70         return FLASH_ERROR_OPT;
71
72     return FLASH_COMPLETE;
73 }
74
75 /**
76   * @brief  Waits for a Flash operation to complete or a TIMEOUT to occur.
77   * @param  Timeout: FLASH progamming Timeout
78   * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
79   *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
80   */
81 FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
82 {
83     FLASH_Status status;
84
85     /* Check for the Flash Status */
86     status = FLASH_GetStatus();
87     /* Wait for a Flash operation to complete or a TIMEOUT to occur */
88     while ((status == FLASH_BUSY) && (Timeout != 0x00))
89     {
90         delay();
91         status = FLASH_GetStatus();
92         Timeout--;
93     }
94     if (Timeout == 0)
95         status = FLASH_TIMEOUT;
96     /* Return the operation status */
97     return status;
98 }
99
100 /**
101   * @brief  Erases a specified FLASH page.
102   * @param  Page_Address: The page address to be erased.
103   * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
104   *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
105   */
106 FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
107 {
108     FLASH_Status status = FLASH_COMPLETE;
109     /* Check the parameters */
110     ASSERT(IS_FLASH_ADDRESS(Page_Address));
111     /* Wait for last operation to be completed */
112     status = FLASH_WaitForLastOperation(EraseTimeout);
113
114     if(status == FLASH_COMPLETE)
115     {
116         /* if the previous operation is completed, proceed to erase the page */
117         FLASH->CR |= FLASH_CR_PER;
118         FLASH->AR = Page_Address;
119         FLASH->CR |= FLASH_CR_STRT;
120
121         /* Wait for last operation to be completed */
122         status = FLASH_WaitForLastOperation(EraseTimeout);
123         if(status != FLASH_TIMEOUT)
124         {
125             /* if the erase operation is completed, disable the PER Bit */
126             FLASH->CR &= ~FLASH_CR_PER;
127         }
128         FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
129     }
130     /* Return the Erase Status */
131     return status;
132 }
133
134 /**
135   * @brief  Programs a half word at a specified address.
136   * @param  Address: specifies the address to be programmed.
137   * @param  Data: specifies the data to be programmed.
138   * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
139   *   FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
140   */
141 FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
142 {
143     FLASH_Status status = FLASH_BAD_ADDRESS;
144
145     if (IS_FLASH_ADDRESS(Address))
146     {
147         /* Wait for last operation to be completed */
148         status = FLASH_WaitForLastOperation(ProgramTimeout);
149         if(status == FLASH_COMPLETE)
150         {
151             /* if the previous operation is completed, proceed to program the new data */
152             FLASH->CR |= FLASH_CR_PG;
153             *(__IO uint16_t*)Address = Data;
154             /* Wait for last operation to be completed */
155             status = FLASH_WaitForLastOperation(ProgramTimeout);
156             if(status != FLASH_TIMEOUT)
157             {
158                 /* if the program operation is completed, disable the PG Bit */
159                 FLASH->CR &= ~FLASH_CR_PG;
160             }
161             FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
162         }
163     }
164     return status;
165 }
166
167 /**
168   * @brief  Unlocks the FLASH Program Erase Controller.
169   * @param  None
170   * @retval None
171   */
172 void FLASH_Unlock(void)
173 {
174     /* Authorize the FPEC Access */
175     FLASH->KEYR = FLASH_KEY1;
176     FLASH->KEYR = FLASH_KEY2;
177 }
178
179 /**
180   * @brief  Locks the FLASH Program Erase Controller.
181   * @param  None
182   * @retval None
183   */
184 void FLASH_Lock(void)
185 {
186     /* Set the Lock Bit to lock the FPEC and the FCR */
187     FLASH->CR |= FLASH_CR_LOCK;
188 }