36
36
#include "py/runtime.h"
37
37
#include "lib/oofatfs/ff.h"
38
38
39
- #include "stm32f4xx_hal.h"
40
-
41
39
typedef struct {
42
40
uint32_t base_address ;
43
41
uint32_t sector_size ;
@@ -62,7 +60,11 @@ static const flash_layout_t flash_layout[] = {
62
60
#endif
63
61
};
64
62
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 ;
66
68
67
69
//Return the sector of a given flash address.
68
70
uint32_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) {
101
103
}
102
104
103
105
void 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
+ }
104
156
}
105
157
106
158
static 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) {
189
241
return true;
190
242
}
191
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
+
192
254
mp_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 );
193
267
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 );
197
283
}
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 ;
198
292
}
293
+
199
294
return 0 ; // success
200
295
}
201
296
0 commit comments