44 * The MIT License (MIT)
55 *
66 * Copyright (c) 2013, 2014 Damien P. George
7- * Copyright (c) 2019 Lucian Copeland for Adafruit Industries
7+ * Copyright (c) 2020 Lucian Copeland for Adafruit Industries
88 *
99 * Permission is hereby granted, free of charge, to any person obtaining a copy
1010 * of this software and associated documentation files (the "Software"), to deal
3535#include "py/obj.h"
3636#include "py/runtime.h"
3737#include "lib/oofatfs/ff.h"
38+ #include "supervisor/shared/safe_mode.h"
3839
3940typedef struct {
4041 uint32_t base_address ;
@@ -46,7 +47,9 @@ typedef struct {
4647/* Internal Flash API
4748 *------------------------------------------------------------------*/
4849
49- static const flash_layout_t flash_layout [] = {
50+ #if defined(STM32F4 )
51+
52+ STATIC const flash_layout_t flash_layout [] = {
5053 { 0x08000000 , 0x04000 , 4 },
5154 { 0x08010000 , 0x10000 , 1 },
5255 { 0x08020000 , 0x20000 , 3 },
@@ -59,12 +62,45 @@ static const flash_layout_t flash_layout[] = {
5962 { 0x08120000 , 0x20000 , 7 },
6063 #endif
6164};
65+ STATIC uint8_t _flash_cache [0x4000 ] __attribute__((aligned (4 )));
66+
67+ #elif defined(STM32H7 )
68+
69+ STATIC const flash_layout_t flash_layout [] = {
70+ { 0x08000000 , 0x20000 , 16 },
71+ };
72+ STATIC uint8_t _flash_cache [0x20000 ] __attribute__((aligned (4 )));
73+
74+ #else
75+ #error Unsupported processor
76+ #endif
6277
6378#define NO_CACHE 0xffffffff
6479#define MAX_CACHE 0x4000
6580
66- static uint8_t _flash_cache [0x4000 ] __attribute__((aligned (4 )));
67- static uint32_t _cache_flash_addr = NO_CACHE ;
81+
82+ STATIC uint32_t _cache_flash_addr = NO_CACHE ;
83+
84+ #if defined(STM32H7 )
85+ // get the bank of a given flash address
86+ STATIC uint32_t get_bank (uint32_t addr ) {
87+ if (READ_BIT (FLASH -> OPTCR , FLASH_OPTCR_SWAP_BANK ) == 0 ) {
88+ // no bank swap
89+ if (addr < (FLASH_BASE + FLASH_BANK_SIZE )) {
90+ return FLASH_BANK_1 ;
91+ } else {
92+ return FLASH_BANK_2 ;
93+ }
94+ } else {
95+ // bank swap
96+ if (addr < (FLASH_BASE + FLASH_BANK_SIZE )) {
97+ return FLASH_BANK_2 ;
98+ } else {
99+ return FLASH_BANK_1 ;
100+ }
101+ }
102+ }
103+ #endif
68104
69105//Return the sector of a given flash address.
70106uint32_t flash_get_sector_info (uint32_t addr , uint32_t * start_addr , uint32_t * size ) {
@@ -105,50 +141,98 @@ uint32_t supervisor_flash_get_block_count(void) {
105141void supervisor_flash_flush (void ) {
106142 if (_cache_flash_addr == NO_CACHE ) return ;
107143
144+ #if defined(STM32H7 )
145+ __HAL_FLASH_CLEAR_FLAG (FLASH_FLAG_ALL_ERRORS_BANK1 | FLASH_FLAG_ALL_ERRORS_BANK2 );
146+ #else
147+ __HAL_FLASH_CLEAR_FLAG (FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
148+ FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR );
149+ #endif
150+
151+ // set up for erase
152+ FLASH_EraseInitTypeDef EraseInitStruct ;
153+ EraseInitStruct .TypeErase = TYPEERASE_SECTORS ;
154+ EraseInitStruct .VoltageRange = VOLTAGE_RANGE_3 ; // voltage range needs to be 2.7V to 3.6V
155+ // get the sector information
156+ uint32_t sector_size ;
157+ uint32_t sector_start_addr ;
158+ #if defined(STM32H7 )
159+ EraseInitStruct .Banks = get_bank (_cache_flash_addr );
160+ #endif
161+ EraseInitStruct .Sector = flash_get_sector_info (_cache_flash_addr , & sector_start_addr , & sector_size );
162+ EraseInitStruct .NbSectors = 1 ;
163+ if (sector_size > sizeof (_flash_cache )) {
164+ __ASM volatile ("bkpt" );
165+ mp_printf (& mp_plat_print , "FLASH ERR: invalid sector\n" );
166+ reset_into_safe_mode (FLASH_WRITE_FAIL );
167+ }
168+
108169 // Skip if data is the same
109- if (memcmp (_flash_cache , (void * )_flash_page_addr , FLASH_PAGE_SIZE ) != 0 ) {
170+ if (memcmp (_flash_cache , (void * )_cache_flash_addr , sector_size ) != 0 ) {
110171 // unlock flash
111172 HAL_FLASH_Unlock ();
112173
113- // set up for erase
114- FLASH_EraseInitTypeDef EraseInitStruct ;
115- EraseInitStruct .TypeErase = TYPEERASE_SECTORS ;
116- EraseInitStruct .VoltageRange = VOLTAGE_RANGE_3 ; // voltage range needs to be 2.7V to 3.6V
117- // get the sector information
118- uint32_t sector_size ;
119- uint32_t sector_start_addr ;
120- EraseInitStruct .Sector = flash_get_sector_info (_cache_flash_addr , & sector_start_addr , & sector_size );
121- EraseInitStruct .NbSectors = 1 ;
122- if (sector_size > 0x4000 ) return false;
123-
124174 // erase the sector
125175 uint32_t SectorError = 0 ;
126176 if (HAL_FLASHEx_Erase (& EraseInitStruct , & SectorError ) != HAL_OK ) {
127177 // error occurred during sector erase
128178 HAL_FLASH_Lock (); // lock the flash
129- mp_printf (& mp_plat_print , "FLASH SECTOR ERASE ERROR" );
130- return false;
179+ __ASM volatile ("bkpt" );
180+ mp_printf (& mp_plat_print , "FLASH ERR: erase failure\n" );
181+ reset_into_safe_mode (FLASH_WRITE_FAIL );
131182 }
132183
133- __HAL_FLASH_DATA_CACHE_DISABLE ();
134- __HAL_FLASH_INSTRUCTION_CACHE_DISABLE ();
135-
136- __HAL_FLASH_DATA_CACHE_RESET ();
137- __HAL_FLASH_INSTRUCTION_CACHE_RESET ();
138-
139- __HAL_FLASH_INSTRUCTION_CACHE_ENABLE ();
140- __HAL_FLASH_DATA_CACHE_ENABLE ();
184+ // __HAL_FLASH_DATA_CACHE_DISABLE();
185+ // __HAL_FLASH_INSTRUCTION_CACHE_DISABLE();
186+
187+ // __HAL_FLASH_DATA_CACHE_RESET();
188+ // __HAL_FLASH_INSTRUCTION_CACHE_RESET();
189+
190+ // __HAL_FLASH_INSTRUCTION_CACHE_ENABLE();
191+ // __HAL_FLASH_DATA_CACHE_ENABLE();
192+
193+ // // reprogram the sector
194+ // for (uint32_t i = 0; i < sector_size; i++) {
195+ // if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_BYTE, sector_start_addr, (uint64_t)_flash_cache[i]) != HAL_OK) {
196+ // // error occurred during flash write
197+ // HAL_FLASH_Lock(); // lock the flash
198+ // mp_printf(&mp_plat_print, "FLASH WRITE ERROR");
199+ // }
200+ // sector_start_addr += 1;
201+ // }
202+
203+ uint32_t * cache_addr = (uint32_t * )_flash_cache ;
204+
205+ #if defined(STM32H7 )
206+ for (uint32_t i = 0 ; i < (sector_size / 32 ); i ++ ) {
207+ // Note that the STM32H7 HAL interface differs by taking an address, not 64 bit data
208+ // This is because ST's code is written by a large room of chimpanzees
209+ if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_FLASHWORD , sector_start_addr ,
210+ (uint32_t )cache_addr ) != HAL_OK ) {
211+ // error occurred during flash write
212+ HAL_FLASH_Lock (); // lock the flash
213+ __ASM volatile ("bkpt" );
214+ reset_into_safe_mode (FLASH_WRITE_FAIL );
215+ }
216+ // RAM memory is by word (4 byte), but flash memory is by byte
217+ cache_addr += 8 ;
218+ sector_start_addr += 32 ;
219+ }
141220
142- // reprogram the sector
143- for (uint32_t i = 0 ; i < sector_size ; i ++ ) {
144- if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_BYTE , sector_start_addr , (uint64_t )_flash_cache [i ]) != HAL_OK ) {
221+ #else // STM32F4
222+ // program the flash word by word
223+ for (uint32_t i = 0 ; i < sector_size / 4 ; i ++ ) {
224+ if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_WORD , sector_start_addr ,
225+ (uint64_t )* cache_addr ) != HAL_OK ) {
145226 // error occurred during flash write
146227 HAL_FLASH_Lock (); // lock the flash
147- mp_printf ( & mp_plat_print , "FLASH WRITE ERROR " );
148- return false ;
228+ __ASM volatile ( "bkpt " );
229+ reset_into_safe_mode ( FLASH_WRITE_FAIL ) ;
149230 }
150- sector_start_addr += 1 ;
231+ // RAM memory is by word (4 byte), but flash memory is by byte
232+ cache_addr += 1 ;
233+ sector_start_addr += 4 ;
151234 }
235+ #endif
152236
153237 // lock the flash
154238 HAL_FLASH_Lock ();
@@ -165,6 +249,9 @@ static int32_t convert_block_to_flash_addr(uint32_t block) {
165249}
166250
167251mp_uint_t supervisor_flash_read_blocks (uint8_t * dest , uint32_t block , uint32_t num_blocks ) {
252+ // Must write out anything in cache before trying to read.
253+ supervisor_flash_flush ();
254+
168255 int32_t src = convert_block_to_flash_addr (block );
169256 if (src == -1 ) {
170257 // bad block number
@@ -174,103 +261,33 @@ mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t n
174261 return 0 ; // success
175262}
176263
177- bool supervisor_flash_write_block (const uint8_t * src , uint32_t block ) {
178- int32_t dest = convert_block_to_flash_addr (block );
179- if (dest == -1 ) {
180- // bad block number
181- mp_printf (& mp_plat_print , "BAD FLASH BLOCK ERROR" );
182- return false;
183- }
184-
185- // unlock flash
186- HAL_FLASH_Unlock ();
187-
188- // set up for erase
189- FLASH_EraseInitTypeDef EraseInitStruct ;
190- EraseInitStruct .TypeErase = TYPEERASE_SECTORS ;
191- EraseInitStruct .VoltageRange = VOLTAGE_RANGE_3 ; // voltage range needs to be 2.7V to 3.6V
192- // get the sector information
193- uint32_t sector_size ;
194- uint32_t sector_start_addr ;
195- EraseInitStruct .Sector = flash_get_sector_info (dest , & sector_start_addr , & sector_size );
196- EraseInitStruct .NbSectors = 1 ;
197- if (sector_size > 0x4000 ) return false;
198-
199- // copy the sector
200- memcpy (sector_copy ,(void * )sector_start_addr ,sector_size );
201-
202- // // overwrite sector data
203- memcpy (sector_copy + (dest - sector_start_addr ),src ,FILESYSTEM_BLOCK_SIZE );
204-
205- // find end address, subtract for number of sectors
206- // Shouldn't be required since blocks will always fit in a single sector, they should never overlap
207- //EraseInitStruct.NbSectors = flash_get_sector_info(dest + FILESYSTEM_BLOCK_SIZE - 1, NULL, NULL) - EraseInitStruct.Sector + 1;
208-
209- // erase the sector
210- uint32_t SectorError = 0 ;
211- if (HAL_FLASHEx_Erase (& EraseInitStruct , & SectorError ) != HAL_OK ) {
212- // error occurred during sector erase
213- HAL_FLASH_Lock (); // lock the flash
214- mp_printf (& mp_plat_print , "FLASH SECTOR ERASE ERROR" );
215- return false;
216- }
217-
218- __HAL_FLASH_DATA_CACHE_DISABLE ();
219- __HAL_FLASH_INSTRUCTION_CACHE_DISABLE ();
220-
221- __HAL_FLASH_DATA_CACHE_RESET ();
222- __HAL_FLASH_INSTRUCTION_CACHE_RESET ();
223-
224- __HAL_FLASH_INSTRUCTION_CACHE_ENABLE ();
225- __HAL_FLASH_DATA_CACHE_ENABLE ();
226-
227- // reprogram the sector
228- for (uint32_t i = 0 ; i < sector_size ; i ++ ) {
229- if (HAL_FLASH_Program (FLASH_TYPEPROGRAM_BYTE , sector_start_addr , (uint64_t )sector_copy [i ]) != HAL_OK ) {
230- // error occurred during flash write
231- HAL_FLASH_Lock (); // lock the flash
232- mp_printf (& mp_plat_print , "FLASH WRITE ERROR" );
233- return false;
234- }
235- sector_start_addr += 1 ;
236- }
237-
238- // lock the flash
239- HAL_FLASH_Lock ();
240-
241- return true;
242- }
243-
244- // mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t block_num, uint32_t num_blocks) {
245-
246- // for (size_t i = 0; i < num_blocks; i++) {
247- // if (!supervisor_flash_write_block(src + i * FILESYSTEM_BLOCK_SIZE, block_num + i)) {
248- // return 1; // error
249- // }
250- // }
251- // return 0; // success
252- // }
253-
254264mp_uint_t supervisor_flash_write_blocks (const uint8_t * src , uint32_t block_num , uint32_t num_blocks ) {
255265 while (num_blocks ) {
256- int32_t dest = convert_block_to_flash_addr (block );
266+ int32_t dest = convert_block_to_flash_addr (block_num );
257267 if (dest == -1 ) {
258268 // bad block number
269+ __ASM volatile ("bkpt" );
259270 mp_printf (& mp_plat_print , "BAD FLASH BLOCK ERROR" );
260271 return false;
261272 }
262273
263274 // unlock flash
264275 HAL_FLASH_Unlock ();
265276
277+ uint32_t sector_size ;
278+ uint32_t sector_start_addr ;
266279 flash_get_sector_info (dest , & sector_start_addr , & sector_size );
267280
268281 // Fail for any sector outside the 16k ones for now
269- if (sector_size > 0x4000 ) return false;
282+ if (sector_size > sizeof (_flash_cache )) {
283+ __ASM volatile ("bkpt" );
284+ mp_printf (& mp_plat_print , "FLASH ERR: invalid sector\n" );
285+ reset_into_safe_mode (FLASH_WRITE_FAIL );
286+ }
270287
271288 // Find how many blocks are left in the sector
272289 uint32_t count = (sector_size - (dest - sector_start_addr ))/FILESYSTEM_BLOCK_SIZE ;
273- count = MIN (num_blocks , count ); `
290+ count = MIN (num_blocks , count );
274291
275292 if (_cache_flash_addr != sector_start_addr ) {
276293 // Write out anything in cache before overwriting it.
0 commit comments