3636#include "py/runtime.h"
3737#include "lib/oofatfs/ff.h"
3838
39- #include "stm32f4xx_hal.h"
40-
4139typedef struct {
4240 uint32_t base_address ;
4341 uint32_t sector_size ;
@@ -62,7 +60,11 @@ static const flash_layout_t flash_layout[] = {
6260 #endif
6361};
6462
65- static uint8_t sector_copy [0x4000 ] __attribute__((aligned (4 )));
63+ #define NO_CACHE 0xffffffff
64+ #define MAX_CACHE 0x4000
65+
66+ static uint8_t _flash_cache [0x4000 ] __attribute__((aligned (4 )));
67+ static uint32_t _cache_flash_addr = NO_CACHE ;
6668
6769//Return the sector of a given flash address.
6870uint32_t flash_get_sector_info (uint32_t addr , uint32_t * start_addr , uint32_t * size ) {
@@ -101,6 +103,56 @@ uint32_t supervisor_flash_get_block_count(void) {
101103}
102104
103105void supervisor_flash_flush (void ) {
106+ if (_cache_flash_addr == NO_CACHE ) return ;
107+
108+ // Skip if data is the same
109+ if (memcmp (_flash_cache , (void * )_flash_page_addr , FLASH_PAGE_SIZE ) != 0 ) {
110+ // unlock flash
111+ HAL_FLASH_Unlock ();
112+
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+
124+ // erase the sector
125+ uint32_t SectorError = 0 ;
126+ if (HAL_FLASHEx_Erase (& EraseInitStruct , & SectorError ) != HAL_OK ) {
127+ // error occurred during sector erase
128+ HAL_FLASH_Lock (); // lock the flash
129+ mp_printf (& mp_plat_print , "FLASH SECTOR ERASE ERROR" );
130+ return false;
131+ }
132+
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 ();
141+
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 ) {
145+ // error occurred during flash write
146+ HAL_FLASH_Lock (); // lock the flash
147+ mp_printf (& mp_plat_print , "FLASH WRITE ERROR" );
148+ return false;
149+ }
150+ sector_start_addr += 1 ;
151+ }
152+
153+ // lock the flash
154+ HAL_FLASH_Lock ();
155+ }
104156}
105157
106158static int32_t convert_block_to_flash_addr (uint32_t block ) {
@@ -189,13 +241,56 @@ bool supervisor_flash_write_block(const uint8_t *src, uint32_t block) {
189241 return true;
190242}
191243
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+
192254mp_uint_t supervisor_flash_write_blocks (const uint8_t * src , uint32_t block_num , uint32_t num_blocks ) {
255+ while (num_blocks ) {
256+ int32_t dest = convert_block_to_flash_addr (block );
257+ if (dest == -1 ) {
258+ // bad block number
259+ mp_printf (& mp_plat_print , "BAD FLASH BLOCK ERROR" );
260+ return false;
261+ }
262+
263+ // unlock flash
264+ HAL_FLASH_Unlock ();
265+
266+ flash_get_sector_info (dest , & sector_start_addr , & sector_size );
193267
194- for (size_t i = 0 ; i < num_blocks ; i ++ ) {
195- if (!supervisor_flash_write_block (src + i * FILESYSTEM_BLOCK_SIZE , block_num + i )) {
196- return 1 ; // error
268+ // Fail for any sector outside the 16k ones for now
269+ if (sector_size > 0x4000 ) return false;
270+
271+ // Find how many blocks are left in the sector
272+ uint32_t count = (sector_size - (dest - sector_start_addr ))/FILESYSTEM_BLOCK_SIZE ;
273+ count = MIN (num_blocks , count ); `
274+
275+ if (_cache_flash_addr != sector_start_addr ) {
276+ // Write out anything in cache before overwriting it.
277+ supervisor_flash_flush ();
278+
279+ _cache_flash_addr = sector_start_addr ;
280+
281+ // Copy the current contents of the entire page into the cache.
282+ memcpy (_flash_cache , (void * )sector_start_addr , sector_size );
197283 }
284+
285+ // Overwrite part or all of the sector cache with the src data.
286+ memcpy (_flash_cache + (dest - sector_start_addr ), src , count * FILESYSTEM_BLOCK_SIZE );
287+
288+ // adjust for next run
289+ block_num += count ;
290+ src += count * FILESYSTEM_BLOCK_SIZE ;
291+ num_blocks -= count ;
198292 }
293+
199294 return 0 ; // success
200295}
201296
0 commit comments