diff options
author | Joel Challis <git@zvecr.com> | 2021-11-19 18:41:02 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-19 10:41:02 -0800 |
commit | 2728603fe6d73e805a539d337fd01051c46ca806 (patch) | |
tree | 5c83ffc7efa112da870bd5d8502a9d91d4792f35 /platforms/chibios/flash_stm32.c | |
parent | 43b9e23bae12916d5161f03700c9bfe46737324b (diff) | |
download | qmk_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.c | 208 |
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 | |||
37 | static 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 | */ | ||
65 | static 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 | */ | ||
77 | FLASH_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 | */ | ||
97 | FLASH_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 | */ | ||
119 | FLASH_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 | */ | ||
160 | FLASH_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 | */ | ||
192 | void 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 | */ | ||
205 | void FLASH_Lock(void) { | ||
206 | /* Set the Lock Bit to lock the FPEC and the FCR */ | ||
207 | FLASH->CR |= FLASH_CR_LOCK; | ||
208 | } | ||