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