aboutsummaryrefslogtreecommitdiff
path: root/platforms/chibios/flash_stm32.c
diff options
context:
space:
mode:
authorJoel Challis <git@zvecr.com>2021-11-19 18:41:02 +0000
committerGitHub <noreply@github.com>2021-11-19 10:41:02 -0800
commit2728603fe6d73e805a539d337fd01051c46ca806 (patch)
tree5c83ffc7efa112da870bd5d8502a9d91d4792f35 /platforms/chibios/flash_stm32.c
parent43b9e23bae12916d5161f03700c9bfe46737324b (diff)
downloadqmk_firmware-2728603fe6d73e805a539d337fd01051c46ca806.tar.gz
qmk_firmware-2728603fe6d73e805a539d337fd01051c46ca806.zip
Move tmk_core/common/<plat> (#13918)
Diffstat (limited to 'platforms/chibios/flash_stm32.c')
-rw-r--r--platforms/chibios/flash_stm32.c208
1 files changed, 208 insertions, 0 deletions
diff --git a/platforms/chibios/flash_stm32.c b/platforms/chibios/flash_stm32.c
new file mode 100644
index 000000000..72c41b8b7
--- /dev/null
+++ b/platforms/chibios/flash_stm32.c
@@ -0,0 +1,208 @@
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 <hal.h>
20#include "flash_stm32.h"
21
22#if defined(STM32F1XX)
23# define FLASH_SR_WRPERR FLASH_SR_WRPRTERR
24#endif
25
26#if defined(MCU_GD32V)
27/* GigaDevice GD32VF103 is a STM32F103 clone at heart. */
28# include "gd32v_compatibility.h"
29#endif
30
31#if defined(STM32F4XX)
32# define FLASH_SR_PGERR (FLASH_SR_PGSERR | FLASH_SR_PGPERR | FLASH_SR_PGAERR)
33
34# define FLASH_KEY1 0x45670123U
35# define FLASH_KEY2 0xCDEF89ABU
36
37static uint8_t ADDR2PAGE(uint32_t Page_Address) {
38 switch (Page_Address) {
39 case 0x08000000 ... 0x08003FFF:
40 return 0;
41 case 0x08004000 ... 0x08007FFF:
42 return 1;
43 case 0x08008000 ... 0x0800BFFF:
44 return 2;
45 case 0x0800C000 ... 0x0800FFFF:
46 return 3;
47 }
48
49 // TODO: bad times...
50 return 7;
51}
52#endif
53
54/* Delay definition */
55#define EraseTimeout ((uint32_t)0x00000FFF)
56#define ProgramTimeout ((uint32_t)0x0000001F)
57
58#define ASSERT(exp) (void)((0))
59
60/**
61 * @brief Inserts a time delay.
62 * @param None
63 * @retval None
64 */
65static void delay(void) {
66 __IO uint32_t i = 0;
67 for (i = 0xFF; i != 0; i--) {
68 }
69}
70
71/**
72 * @brief Returns the FLASH Status.
73 * @param None
74 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
75 * FLASH_ERROR_WRP or FLASH_COMPLETE
76 */
77FLASH_Status FLASH_GetStatus(void) {
78 if ((FLASH->SR & FLASH_SR_BSY) == FLASH_SR_BSY) return FLASH_BUSY;
79
80 if ((FLASH->SR & FLASH_SR_PGERR) != 0) return FLASH_ERROR_PG;
81
82 if ((FLASH->SR & FLASH_SR_WRPERR) != 0) return FLASH_ERROR_WRP;
83
84#if defined(FLASH_OBR_OPTERR)
85 if ((FLASH->SR & FLASH_OBR_OPTERR) != 0) return FLASH_ERROR_OPT;
86#endif
87
88 return FLASH_COMPLETE;
89}
90
91/**
92 * @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
93 * @param Timeout: FLASH progamming Timeout
94 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
95 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
96 */
97FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout) {
98 FLASH_Status status;
99
100 /* Check for the Flash Status */
101 status = FLASH_GetStatus();
102 /* Wait for a Flash operation to complete or a TIMEOUT to occur */
103 while ((status == FLASH_BUSY) && (Timeout != 0x00)) {
104 delay();
105 status = FLASH_GetStatus();
106 Timeout--;
107 }
108 if (Timeout == 0) status = FLASH_TIMEOUT;
109 /* Return the operation status */
110 return status;
111}
112
113/**
114 * @brief Erases a specified FLASH page.
115 * @param Page_Address: The page address to be erased.
116 * @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
117 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
118 */
119FLASH_Status FLASH_ErasePage(uint32_t Page_Address) {
120 FLASH_Status status = FLASH_COMPLETE;
121 /* Check the parameters */
122 ASSERT(IS_FLASH_ADDRESS(Page_Address));
123 /* Wait for last operation to be completed */
124 status = FLASH_WaitForLastOperation(EraseTimeout);
125
126 if (status == FLASH_COMPLETE) {
127 /* if the previous operation is completed, proceed to erase the page */
128#if defined(FLASH_CR_SNB)
129 FLASH->CR &= ~FLASH_CR_SNB;
130 FLASH->CR |= FLASH_CR_SER | (ADDR2PAGE(Page_Address) << FLASH_CR_SNB_Pos);
131#else
132 FLASH->CR |= FLASH_CR_PER;
133 FLASH->AR = Page_Address;
134#endif
135 FLASH->CR |= FLASH_CR_STRT;
136
137 /* Wait for last operation to be completed */
138 status = FLASH_WaitForLastOperation(EraseTimeout);
139 if (status != FLASH_TIMEOUT) {
140 /* if the erase operation is completed, disable the configured Bits */
141#if defined(FLASH_CR_SNB)
142 FLASH->CR &= ~(FLASH_CR_SER | FLASH_CR_SNB);
143#else
144 FLASH->CR &= ~FLASH_CR_PER;
145#endif
146 }
147 FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
148 }
149 /* Return the Erase Status */
150 return status;
151}
152
153/**
154 * @brief Programs a half word at a specified address.
155 * @param Address: specifies the address to be programmed.
156 * @param Data: specifies the data to be programmed.
157 * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
158 * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
159 */
160FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data) {
161 FLASH_Status status = FLASH_BAD_ADDRESS;
162
163 if (IS_FLASH_ADDRESS(Address)) {
164 /* Wait for last operation to be completed */
165 status = FLASH_WaitForLastOperation(ProgramTimeout);
166 if (status == FLASH_COMPLETE) {
167 /* if the previous operation is completed, proceed to program the new data */
168
169#if defined(FLASH_CR_PSIZE)
170 FLASH->CR &= ~FLASH_CR_PSIZE;
171 FLASH->CR |= FLASH_CR_PSIZE_0;
172#endif
173 FLASH->CR |= FLASH_CR_PG;
174 *(__IO uint16_t*)Address = Data;
175 /* Wait for last operation to be completed */
176 status = FLASH_WaitForLastOperation(ProgramTimeout);
177 if (status != FLASH_TIMEOUT) {
178 /* if the program operation is completed, disable the PG Bit */
179 FLASH->CR &= ~FLASH_CR_PG;
180 }
181 FLASH->SR = (FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR);
182 }
183 }
184 return status;
185}
186
187/**
188 * @brief Unlocks the FLASH Program Erase Controller.
189 * @param None
190 * @retval None
191 */
192void FLASH_Unlock(void) {
193 if (FLASH->CR & FLASH_CR_LOCK) {
194 /* Authorize the FPEC Access */
195 FLASH->KEYR = FLASH_KEY1;
196 FLASH->KEYR = FLASH_KEY2;
197 }
198}
199
200/**
201 * @brief Locks the FLASH Program Erase Controller.
202 * @param None
203 * @retval None
204 */
205void FLASH_Lock(void) {
206 /* Set the Lock Bit to lock the FPEC and the FCR */
207 FLASH->CR |= FLASH_CR_LOCK;
208}