2 * This file is part of Betaflight.
4 * Betaflight is free software. You can redistribute this software
5 * and/or modify this software under the terms of the GNU General
6 * Public License as published by the Free Software Foundation,
7 * either version 3 of the License, or (at your option) any later
10 * Betaflight is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public
17 * License along with this software.
19 * If not, see <http://www.gnu.org/licenses/>.
25 #include "drivers/system.h"
26 #include "config/config_streamer.h"
28 #if defined(CONFIG_IN_FLASH)
30 #if !defined(FLASH_PAGE_SIZE)
31 #error "Flash page size not defined for STM (or clone) target."
34 #if defined(STM32F745xx) || defined(STM32F746xx) || defined(STM32F765xx)
36 Sector 0 0x08000000 - 0x08007FFF 32 Kbytes
37 Sector 1 0x08008000 - 0x0800FFFF 32 Kbytes
38 Sector 2 0x08010000 - 0x08017FFF 32 Kbytes
39 Sector 3 0x08018000 - 0x0801FFFF 32 Kbytes
40 Sector 4 0x08020000 - 0x0803FFFF 128 Kbytes
41 Sector 5 0x08040000 - 0x0807FFFF 256 Kbytes
42 Sector 6 0x08080000 - 0x080BFFFF 256 Kbytes
43 Sector 7 0x080C0000 - 0x080FFFFF 256 Kbytes
45 F7X5XI device with 2M flash
46 Sector 8 0x08100000 - 0x0813FFFF 256 Kbytes
47 Sector 9 0x08140000 - 0x0817FFFF 256 Kbytes
48 Sector 10 0x08180000 - 0x081BFFFF 256 Kbytes
49 Sector 11 0x081C0000 - 0x081FFFFF 256 Kbytes
52 uint32_t getFLASHSectorForEEPROM(void)
54 if ((uint32_t)&__config_start
<= 0x08007FFF)
55 return FLASH_SECTOR_0
;
56 if ((uint32_t)&__config_start
<= 0x0800FFFF)
57 return FLASH_SECTOR_1
;
58 if ((uint32_t)&__config_start
<= 0x08017FFF)
59 return FLASH_SECTOR_2
;
60 if ((uint32_t)&__config_start
<= 0x0801FFFF)
61 return FLASH_SECTOR_3
;
62 if ((uint32_t)&__config_start
<= 0x0803FFFF)
63 return FLASH_SECTOR_4
;
64 if ((uint32_t)&__config_start
<= 0x0807FFFF)
65 return FLASH_SECTOR_5
;
66 if ((uint32_t)&__config_start
<= 0x080BFFFF)
67 return FLASH_SECTOR_6
;
68 if ((uint32_t)&__config_start
<= 0x080FFFFF)
69 return FLASH_SECTOR_7
;
70 #if defined(STM32F765xx)
71 if ((uint32_t)&__config_start
<= 0x0813FFFF)
72 return FLASH_SECTOR_8
;
73 if ((uint32_t)&__config_start
<= 0x0817FFFF)
74 return FLASH_SECTOR_9
;
75 if ((uint32_t)&__config_start
<= 0x081BFFFF)
76 return FLASH_SECTOR_10
;
77 if ((uint32_t)&__config_start
<= 0x081FFFFF)
78 return FLASH_SECTOR_11
;
83 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
87 #elif defined(STM32F722xx)
89 Sector 0 0x08000000 - 0x08003FFF 16 Kbytes
90 Sector 1 0x08004000 - 0x08007FFF 16 Kbytes
91 Sector 2 0x08008000 - 0x0800BFFF 16 Kbytes
92 Sector 3 0x0800C000 - 0x0800FFFF 16 Kbytes
93 Sector 4 0x08010000 - 0x0801FFFF 64 Kbytes
94 Sector 5 0x08020000 - 0x0803FFFF 128 Kbytes
95 Sector 6 0x08040000 - 0x0805FFFF 128 Kbytes
96 Sector 7 0x08060000 - 0x0807FFFF 128 Kbytes
99 uint32_t getFLASHSectorForEEPROM(void)
101 if ((uint32_t)&__config_start
<= 0x08003FFF)
102 return FLASH_SECTOR_0
;
103 if ((uint32_t)&__config_start
<= 0x08007FFF)
104 return FLASH_SECTOR_1
;
105 if ((uint32_t)&__config_start
<= 0x0800BFFF)
106 return FLASH_SECTOR_2
;
107 if ((uint32_t)&__config_start
<= 0x0800FFFF)
108 return FLASH_SECTOR_3
;
109 if ((uint32_t)&__config_start
<= 0x0801FFFF)
110 return FLASH_SECTOR_4
;
111 if ((uint32_t)&__config_start
<= 0x0803FFFF)
112 return FLASH_SECTOR_5
;
113 if ((uint32_t)&__config_start
<= 0x0805FFFF)
114 return FLASH_SECTOR_6
;
115 if ((uint32_t)&__config_start
<= 0x0807FFFF)
116 return FLASH_SECTOR_7
;
120 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
124 #elif defined(STM32F4)
126 Sector 0 0x08000000 - 0x08003FFF 16 Kbytes
127 Sector 1 0x08004000 - 0x08007FFF 16 Kbytes
128 Sector 2 0x08008000 - 0x0800BFFF 16 Kbytes
129 Sector 3 0x0800C000 - 0x0800FFFF 16 Kbytes
130 Sector 4 0x08010000 - 0x0801FFFF 64 Kbytes
131 Sector 5 0x08020000 - 0x0803FFFF 128 Kbytes
132 Sector 6 0x08040000 - 0x0805FFFF 128 Kbytes
133 Sector 7 0x08060000 - 0x0807FFFF 128 Kbytes
134 Sector 8 0x08080000 - 0x0809FFFF 128 Kbytes
135 Sector 9 0x080A0000 - 0x080BFFFF 128 Kbytes
136 Sector 10 0x080C0000 - 0x080DFFFF 128 Kbytes
137 Sector 11 0x080E0000 - 0x080FFFFF 128 Kbytes
140 uint32_t getFLASHSectorForEEPROM(void)
142 if ((uint32_t)&__config_start
<= 0x08003FFF)
143 return FLASH_Sector_0
;
144 if ((uint32_t)&__config_start
<= 0x08007FFF)
145 return FLASH_Sector_1
;
146 if ((uint32_t)&__config_start
<= 0x0800BFFF)
147 return FLASH_Sector_2
;
148 if ((uint32_t)&__config_start
<= 0x0800FFFF)
149 return FLASH_Sector_3
;
150 if ((uint32_t)&__config_start
<= 0x0801FFFF)
151 return FLASH_Sector_4
;
152 if ((uint32_t)&__config_start
<= 0x0803FFFF)
153 return FLASH_Sector_5
;
154 if ((uint32_t)&__config_start
<= 0x0805FFFF)
155 return FLASH_Sector_6
;
156 if ((uint32_t)&__config_start
<= 0x0807FFFF)
157 return FLASH_Sector_7
;
158 if ((uint32_t)&__config_start
<= 0x0809FFFF)
159 return FLASH_Sector_8
;
160 if ((uint32_t)&__config_start
<= 0x080DFFFF)
161 return FLASH_Sector_9
;
162 if ((uint32_t)&__config_start
<= 0x080BFFFF)
163 return FLASH_Sector_10
;
164 if ((uint32_t)&__config_start
<= 0x080FFFFF)
165 return FLASH_Sector_11
;
169 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
173 #elif defined(STM32H743xx) || defined(STM32G4) || defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H723xx) || defined(STM32H725xx)
175 MCUs with uniform array of equal size sectors, handled in two banks having contiguous address.
176 (Devices with non-contiguous flash layout is not currently useful anyways.)
179 2 bank * 8 sector/bank * 128K/sector (2MB)
180 Bank 1 0x08000000 - 0x080FFFFF 128KB * 8
181 Bank 2 0x08100000 - 0x081FFFFF 128KB * 8
184 1 bank * 8 sector/bank * 128K/sector (1MB)
185 Bank 1 0x08000000 - 0x080FFFFF 128KB * 8
188 2 bank * 128 sector/bank * 8KB/sector (2MB)
189 Bank 1 0x08000000 - 0x080FFFFF 8KB * 128
190 Bank 2 0x08100000 - 0x081FFFFF 8KB * 128
192 G473/474 in dual bank mode
193 2 bank * 128 sector/bank * 2KB/sector (512KB)
194 Bank 1 0x08000000 - 0x0803FFFF 2KB * 128
195 Bank 2 0x08040000 - 0x0807FFFF 2KB * 128
197 Note that FLASH_BANK_SIZE constant used in the following code changes depending on
198 bank operation mode. The code assumes dual bank operation, in which case the
199 FLASH_BANK_SIZE constant is set to one half of the available flash size in HAL.
202 #if defined(STM32H743xx) || defined(STM32H723xx) || defined(STM32H725xx)
203 #define FLASH_PAGE_PER_BANK 8
204 #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ)
205 #define FLASH_PAGE_PER_BANK 128
206 #elif defined(STM32G4)
207 #define FLASH_PAGE_PER_BANK 128
208 // These are not defined in CMSIS like H7
209 #define FLASH_BANK1_BASE FLASH_BASE
210 #define FLASH_BANK2_BASE (FLASH_BANK1_BASE + FLASH_BANK_SIZE)
213 void getFLASHSectorForEEPROM(uint32_t address
, uint32_t *bank
, uint32_t *sector
)
215 #if defined(FLASH_BANK2_BASE)
216 if (address
>= FLASH_BANK1_BASE
&& address
< FLASH_BANK2_BASE
) {
217 *bank
= FLASH_BANK_1
;
218 } else if (address
>= FLASH_BANK2_BASE
&& address
< FLASH_BANK2_BASE
+ FLASH_BANK_SIZE
) {
219 *bank
= FLASH_BANK_2
;
220 address
-= FLASH_BANK_SIZE
;
223 if (address
>= FLASH_BANK1_BASE
&& address
< FLASH_BANK1_BASE
+ FLASH_BANK_SIZE
) {
224 *bank
= FLASH_BANK_1
;
230 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
234 address
-= FLASH_BANK1_BASE
;
235 *sector
= address
/ FLASH_PAGE_SIZE
;
237 #elif defined(STM32H750xx)
239 The memory map supports 2 banks of 8 128k sectors like the H743xx, but there is only one 128K sector so we save some code
240 space by using a smaller function.
243 Sector 0 0x08000000 - 0x0801FFFF 128 Kbytes
247 void getFLASHSectorForEEPROM(uint32_t *bank
, uint32_t *sector
)
250 uint32_t start
= (uint32_t)&__config_start
;
252 if (start
== FLASH_BANK1_BASE
) {
253 *sector
= FLASH_SECTOR_0
;
254 *bank
= FLASH_BANK_1
;
258 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
262 #elif defined(APM32F4)
264 Sector 0 0x08000000 - 0x08003FFF 16 Kbytes
265 Sector 1 0x08004000 - 0x08007FFF 16 Kbytes
266 Sector 2 0x08008000 - 0x0800BFFF 16 Kbytes
267 Sector 3 0x0800C000 - 0x0800FFFF 16 Kbytes
268 Sector 4 0x08010000 - 0x0801FFFF 64 Kbytes
269 Sector 5 0x08020000 - 0x0803FFFF 128 Kbytes
270 Sector 6 0x08040000 - 0x0805FFFF 128 Kbytes
271 Sector 7 0x08060000 - 0x0807FFFF 128 Kbytes
272 Sector 8 0x08080000 - 0x0809FFFF 128 Kbytes
273 Sector 9 0x080A0000 - 0x080BFFFF 128 Kbytes
274 Sector 10 0x080C0000 - 0x080DFFFF 128 Kbytes
275 Sector 11 0x080E0000 - 0x080FFFFF 128 Kbytes
278 uint32_t getFLASHSectorForEEPROM(void)
280 if ((uint32_t)&__config_start
<= 0x08003FFF)
281 return FLASH_SECTOR_0
;
282 if ((uint32_t)&__config_start
<= 0x08007FFF)
283 return FLASH_SECTOR_1
;
284 if ((uint32_t)&__config_start
<= 0x0800BFFF)
285 return FLASH_SECTOR_2
;
286 if ((uint32_t)&__config_start
<= 0x0800FFFF)
287 return FLASH_SECTOR_3
;
288 if ((uint32_t)&__config_start
<= 0x0801FFFF)
289 return FLASH_SECTOR_4
;
290 if ((uint32_t)&__config_start
<= 0x0803FFFF)
291 return FLASH_SECTOR_5
;
292 if ((uint32_t)&__config_start
<= 0x0805FFFF)
293 return FLASH_SECTOR_6
;
294 if ((uint32_t)&__config_start
<= 0x0807FFFF)
295 return FLASH_SECTOR_7
;
296 if ((uint32_t)&__config_start
<= 0x0809FFFF)
297 return FLASH_SECTOR_8
;
298 if ((uint32_t)&__config_start
<= 0x080DFFFF)
299 return FLASH_SECTOR_9
;
300 if ((uint32_t)&__config_start
<= 0x080BFFFF)
301 return FLASH_SECTOR_10
;
302 if ((uint32_t)&__config_start
<= 0x080FFFFF)
303 return FLASH_SECTOR_11
;
307 failureMode(FAILURE_CONFIG_STORE_FAILURE
);
312 void configUnlock(void)
314 #if defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
316 #elif defined(APM32F4)
318 #elif defined(AT32F4)
325 void configLock(void)
327 #if defined(STM32F7) || defined(STM32H7) || defined(STM32G4)
329 #elif defined(AT32F4)
331 #elif defined(APM32F4)
338 void configClearFlags(void)
341 FLASH_ClearFlag(FLASH_FLAG_EOP
| FLASH_FLAG_OPERR
| FLASH_FLAG_WRPERR
| FLASH_FLAG_PGAERR
| FLASH_FLAG_PGPERR
| FLASH_FLAG_PGSERR
);
342 #elif defined(STM32F7)
344 #elif defined(STM32H7)
346 #elif defined(STM32G4)
348 #elif defined(AT32F4)
349 flash_flag_clear(FLASH_ODF_FLAG
| FLASH_PRGMERR_FLAG
| FLASH_EPPERR_FLAG
);
350 #elif defined(APM32F4)
351 __DAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP
| FLASH_FLAG_OPERR
| FLASH_FLAG_WRPERR
| FLASH_FLAG_PGAERR
| FLASH_FLAG_PGPERR
| FLASH_FLAG_PGSERR
);
352 #elif defined(UNIT_TEST) || defined(SIMULATOR_BUILD)
355 # error "Unsupported CPU"
359 configStreamerResult_e
configWriteWord(uintptr_t address
, config_streamer_buffer_type_t
*buffer
)
362 if (address
% FLASH_PAGE_SIZE
== 0) {
363 FLASH_EraseInitTypeDef EraseInitStruct
= {
364 .TypeErase
= FLASH_TYPEERASE_SECTORS
,
365 #if !(defined(STM32H7A3xx) || defined(STM32H7A3xxQ))
366 .VoltageRange
= FLASH_VOLTAGE_RANGE_3
, // 2.7-3.6V
370 getFLASHSectorForEEPROM(address
, &EraseInitStruct
.Banks
, &EraseInitStruct
.Sector
);
371 uint32_t SECTORError
;
372 const HAL_StatusTypeDef status
= HAL_FLASHEx_Erase(&EraseInitStruct
, &SECTORError
);
373 if (status
!= HAL_OK
) {
374 return CONFIG_RESULT_FAILURE
;
379 // HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint32_t DataAddress);
380 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint32_t) * FLASH_NB_32BITWORD_IN_FLASHWORD
, "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
381 const HAL_StatusTypeDef status
= HAL_FLASH_Program(FLASH_TYPEPROGRAM_FLASHWORD
, address
, (uint32_t)buffer
);
382 if (status
!= HAL_OK
) {
383 return CONFIG_RESULT_ADDRESS_INVALID
;
385 #elif defined(STM32F7)
386 if (address
% FLASH_PAGE_SIZE
== 0) {
387 FLASH_EraseInitTypeDef EraseInitStruct
= {
388 .TypeErase
= FLASH_TYPEERASE_SECTORS
,
389 .VoltageRange
= FLASH_VOLTAGE_RANGE_3
, // 2.7-3.6V
392 EraseInitStruct
.Sector
= getFLASHSectorForEEPROM();
393 uint32_t SECTORError
;
394 const HAL_StatusTypeDef status
= HAL_FLASHEx_Erase(&EraseInitStruct
, &SECTORError
);
395 if (status
!= HAL_OK
) {
396 return CONFIG_RESULT_FAILURE
;
400 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint32_t), "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
402 // HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data);
403 const HAL_StatusTypeDef status
= HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD
, address
, *buffer
);
404 if (status
!= HAL_OK
) {
405 return CONFIG_RESULT_INCOMPLETE
;
407 #elif defined(STM32G4)
408 if (address
% FLASH_PAGE_SIZE
== 0) {
410 FLASH_EraseInitTypeDef EraseInitStruct
= {
411 .TypeErase
= FLASH_TYPEERASE_PAGES
,
414 getFLASHSectorForEEPROM(address
, &EraseInitStruct
.Banks
, &EraseInitStruct
.Page
);
415 uint32_t SECTORError
;
416 const HAL_StatusTypeDef status
= HAL_FLASHEx_Erase(&EraseInitStruct
, &SECTORError
);
417 if (status
!= HAL_OK
) {
418 return CONFIG_RESULT_FAILURE
;
422 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint64_t), "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
423 const HAL_StatusTypeDef status
= HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD
, address
, *buffer
);
424 if (status
!= HAL_OK
) {
425 return CONFIG_RESULT_ADDRESS_INVALID
;
427 #elif defined(AT32F4)
428 if (address
% FLASH_PAGE_SIZE
== 0) {
429 const flash_status_type status
= flash_sector_erase(address
);
430 if (status
!= FLASH_OPERATE_DONE
) {
431 return CONFIG_RESULT_FAILURE
;
435 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint32_t), "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
436 const flash_status_type status
= flash_word_program(address
, *buffer
);
437 if (status
!= FLASH_OPERATE_DONE
) {
438 return CONFIG_RESULT_ADDRESS_INVALID
;
440 #elif defined(APM32F4)
441 if (address
% FLASH_PAGE_SIZE
== 0) {
442 FLASH_EraseInitTypeDef EraseInitStruct
= {
443 .TypeErase
= FLASH_TYPEERASE_SECTORS
,
444 .VoltageRange
= FLASH_VOLTAGE_RANGE_3
, // 2.7-3.6V
447 EraseInitStruct
.Sector
= getFLASHSectorForEEPROM();
448 uint32_t SECTORError
;
449 const DAL_StatusTypeDef status
= DAL_FLASHEx_Erase(&EraseInitStruct
, &SECTORError
);
450 if (status
!= DAL_OK
) {
451 return CONFIG_RESULT_FAILURE
;
455 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint32_t), "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
456 const DAL_StatusTypeDef status
= DAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD
, address
, *buffer
);
457 if (status
!= DAL_OK
) {
458 return CONFIG_RESULT_ADDRESS_INVALID
;
460 #elif defined(STM32F4)
461 if (address
% FLASH_PAGE_SIZE
== 0) {
462 const FLASH_Status status
= FLASH_EraseSector(getFLASHSectorForEEPROM(), VoltageRange_3
); //0x08080000 to 0x080A0000
463 if (status
!= FLASH_COMPLETE
) {
464 return CONFIG_RESULT_FAILURE
;
468 STATIC_ASSERT(CONFIG_STREAMER_BUFFER_SIZE
== sizeof(uint32_t), "CONFIG_STREAMER_BUFFER_SIZE does not match written size");
469 const FLASH_Status status
= FLASH_ProgramWord(address
, *buffer
);
470 if (status
!= FLASH_COMPLETE
) {
471 return CONFIG_RESULT_ADDRESS_INVALID
;
474 #error "MCU not catered for in configWriteWord for config_streamer"
476 return CONFIG_RESULT_SUCCESS
;
479 #endif // CONFIG_IN_FLASH