4
4
* The MIT License (MIT)
5
5
*
6
6
* 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
8
8
*
9
9
* Permission is hereby granted, free of charge, to any person obtaining a copy
10
10
* of this software and associated documentation files (the "Software"), to deal
35
35
#include "py/obj.h"
36
36
#include "py/runtime.h"
37
37
#include "lib/oofatfs/ff.h"
38
+ #include "supervisor/shared/safe_mode.h"
38
39
39
40
typedef struct {
40
41
uint32_t base_address ;
@@ -46,7 +47,9 @@ typedef struct {
46
47
/* Internal Flash API
47
48
*------------------------------------------------------------------*/
48
49
49
- static const flash_layout_t flash_layout [] = {
50
+ #if defined(STM32F4 )
51
+
52
+ STATIC const flash_layout_t flash_layout [] = {
50
53
{ 0x08000000 , 0x04000 , 4 },
51
54
{ 0x08010000 , 0x10000 , 1 },
52
55
{ 0x08020000 , 0x20000 , 3 },
@@ -59,12 +62,45 @@ static const flash_layout_t flash_layout[] = {
59
62
{ 0x08120000 , 0x20000 , 7 },
60
63
#endif
61
64
};
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
62
77
63
78
#define NO_CACHE 0xffffffff
64
79
#define MAX_CACHE 0x4000
65
80
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
68
104
69
105
//Return the sector of a given flash address.
70
106
uint32_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) {
105
141
void supervisor_flash_flush (void ) {
106
142
if (_cache_flash_addr == NO_CACHE ) return ;
107
143
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
+
108
169
// 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 ) {
110
171
// unlock flash
111
172
HAL_FLASH_Unlock ();
112
173
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
174
// erase the sector
125
175
uint32_t SectorError = 0 ;
126
176
if (HAL_FLASHEx_Erase (& EraseInitStruct , & SectorError ) != HAL_OK ) {
127
177
// error occurred during sector erase
128
178
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 );
131
182
}
132
183
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
+ }
141
220
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 ) {
145
226
// error occurred during flash write
146
227
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 ) ;
149
230
}
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 ;
151
234
}
235
+ #endif
152
236
153
237
// lock the flash
154
238
HAL_FLASH_Lock ();
@@ -165,6 +249,9 @@ static int32_t convert_block_to_flash_addr(uint32_t block) {
165
249
}
166
250
167
251
mp_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
+
168
255
int32_t src = convert_block_to_flash_addr (block );
169
256
if (src == -1 ) {
170
257
// bad block number
@@ -174,103 +261,33 @@ mp_uint_t supervisor_flash_read_blocks(uint8_t *dest, uint32_t block, uint32_t n
174
261
return 0 ; // success
175
262
}
176
263
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
-
254
264
mp_uint_t supervisor_flash_write_blocks (const uint8_t * src , uint32_t block_num , uint32_t num_blocks ) {
255
265
while (num_blocks ) {
256
- int32_t dest = convert_block_to_flash_addr (block );
266
+ int32_t dest = convert_block_to_flash_addr (block_num );
257
267
if (dest == -1 ) {
258
268
// bad block number
269
+ __ASM volatile ("bkpt" );
259
270
mp_printf (& mp_plat_print , "BAD FLASH BLOCK ERROR" );
260
271
return false;
261
272
}
262
273
263
274
// unlock flash
264
275
HAL_FLASH_Unlock ();
265
276
277
+ uint32_t sector_size ;
278
+ uint32_t sector_start_addr ;
266
279
flash_get_sector_info (dest , & sector_start_addr , & sector_size );
267
280
268
281
// 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
+ }
270
287
271
288
// Find how many blocks are left in the sector
272
289
uint32_t count = (sector_size - (dest - sector_start_addr ))/FILESYSTEM_BLOCK_SIZE ;
273
- count = MIN (num_blocks , count ); `
290
+ count = MIN (num_blocks , count );
274
291
275
292
if (_cache_flash_addr != sector_start_addr ) {
276
293
// Write out anything in cache before overwriting it.
0 commit comments