2424 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2525 * THE SOFTWARE.
2626 */
27+
2728#include "supervisor/internal_flash.h"
2829
2930#include <stdint.h>
3233
3334#include "extmod/vfs.h"
3435#include "extmod/vfs_fat.h"
36+
3537#include "py/mphal.h"
3638#include "py/obj.h"
3739#include "py/runtime.h"
38- #include "lib/oofatfs/ff.h"
3940
4041#include "esp_ota_ops.h"
4142#include "esp_partition.h"
4243
44+ #include "supervisor/filesystem.h"
4345#include "supervisor/flash.h"
4446#include "supervisor/usb.h"
4547
46- #if CIRCUITPY_STORAGE_EXTEND
47- #define PARTITION_NUM (2)
48- #else
49- #define PARTITION_NUM (1)
50- #endif
51-
52- STATIC const esp_partition_t * _partition [PARTITION_NUM ];
48+ #define OP_READ 0
49+ #define OP_WRITE 1
5350
5451// TODO: Split the caching out of supervisor/shared/external_flash so we can use it.
5552#define SECTOR_SIZE 4096
5653STATIC uint8_t _cache [SECTOR_SIZE ];
5754STATIC uint32_t _cache_lba = 0xffffffff ;
5855
56+ #if CIRCUITPY_STORAGE_EXTEND
57+ #if FF_MAX_SS == FF_MIN_SS
58+ #define SECSIZE (fs ) (FF_MIN_SS)
59+ #else
60+ #define SECSIZE (fs ) ((fs)->ssize)
61+ #endif // FF_MAX_SS == FF_MIN_SS
62+ STATIC DWORD fatfs_bytes (void ) {
63+ FATFS * fatfs = filesystem_circuitpy ();
64+ return (fatfs -> csize * SECSIZE (fatfs )) * (fatfs -> n_fatent - 2 );
65+ }
66+ STATIC bool storage_extended = true;
67+ STATIC const esp_partition_t * _partition [2 ];
68+ #else
69+ STATIC const esp_partition_t * _partition [1 ];
70+ #endif // CIRCUITPY_STORAGE_EXTEND
71+
5972void supervisor_flash_init (void ) {
73+ if (_partition [0 ] != NULL ) {
74+ return ;
75+ }
6076 _partition [0 ] = esp_partition_find_first (ESP_PARTITION_TYPE_DATA ,
6177 ESP_PARTITION_SUBTYPE_DATA_FAT ,
6278 NULL );
@@ -71,38 +87,60 @@ uint32_t supervisor_flash_get_block_size(void) {
7187
7288uint32_t supervisor_flash_get_block_count (void ) {
7389 #if CIRCUITPY_STORAGE_EXTEND
74- return (_partition [0 ]-> size + _partition [1 ]-> size ) / FILESYSTEM_BLOCK_SIZE ;
90+ return (( storage_extended ) ? ( _partition [0 ]-> size + _partition [1 ] -> size ) : _partition [ 0 ]-> size ) / FILESYSTEM_BLOCK_SIZE ;
7591 #else
7692 return _partition [0 ]-> size / FILESYSTEM_BLOCK_SIZE ;
7793 #endif
7894}
7995
8096void port_internal_flash_flush (void ) {
81-
8297}
8398
84- mp_uint_t supervisor_flash_read_blocks (uint8_t * dest , uint32_t block , uint32_t num_blocks ) {
85- uint32_t offset = block * FILESYSTEM_BLOCK_SIZE ;
86- uint32_t read_total = num_blocks * FILESYSTEM_BLOCK_SIZE ;
99+ STATIC void single_partition_rw (const esp_partition_t * partition , uint8_t * data ,
100+ const uint32_t offset , const uint32_t size_total , const bool op ) {
101+ if (op == OP_READ ) {
102+ esp_partition_read (partition , offset , data , size_total );
103+ } else {
104+ esp_partition_erase_range (partition , offset , size_total );
105+ esp_partition_write (partition , offset , _cache , size_total );
106+ }
107+ }
87108
88- #if CIRCUITPY_STORAGE_EXTEND
109+ #if CIRCUITPY_STORAGE_EXTEND
110+ STATIC void multi_partition_rw (uint8_t * data ,
111+ const uint32_t offset , const uint32_t size_total , const bool op ) {
89112 if (offset > _partition [0 ]-> size ) {
90- // only read from partition 1
91- esp_partition_read (_partition [1 ], (offset - _partition [0 ]-> size ), dest , read_total );
92- } else if ((offset + read_total ) > _partition [0 ]-> size ) {
93- // first read from partition 0, then partition 1
94- uint32_t read_0 = _partition [0 ]-> size - offset ;
95- uint32_t read_1 = read_total - read_0 ;
96- esp_partition_read (_partition [0 ], offset , dest , read_0 );
97- esp_partition_read (_partition [1 ], 0 , (dest + read_0 ), read_1 );
98- } else
99- #endif
100- {
101- // only read from partition 0
102- esp_partition_read (_partition [0 ], offset , dest , read_total );
113+ // only r/w partition 1
114+ single_partition_rw (_partition [1 ], data , (offset - _partition [0 ]-> size ), size_total , op );
115+ } else if ((offset + size_total ) > _partition [0 ]-> size ) {
116+ // first r/w partition 0, then partition 1
117+ uint32_t size_0 = _partition [0 ]-> size - offset ;
118+ uint32_t size_1 = size_total - size_0 ;
119+ if (op == OP_READ ) {
120+ esp_partition_read (_partition [0 ], offset , data , size_0 );
121+ esp_partition_read (_partition [1 ], 0 , (data + size_0 ), size_1 );
122+ } else {
123+ esp_partition_erase_range (_partition [0 ], offset , size_0 );
124+ esp_partition_write (_partition [0 ], offset , _cache , size_0 );
125+ esp_partition_erase_range (_partition [1 ], 0 , size_1 );
126+ esp_partition_write (_partition [1 ], 0 , (_cache + size_0 ), size_1 );
127+ }
128+ } else {
129+ // only r/w partition 0
130+ single_partition_rw (_partition [0 ], data , offset , size_total , op );
103131 }
132+ }
133+ #endif
104134
105- return 0 ;
135+ mp_uint_t supervisor_flash_read_blocks (uint8_t * dest , uint32_t block , uint32_t num_blocks ) {
136+ const uint32_t offset = block * FILESYSTEM_BLOCK_SIZE ;
137+ const uint32_t read_total = num_blocks * FILESYSTEM_BLOCK_SIZE ;
138+ #if CIRCUITPY_STORAGE_EXTEND
139+ multi_partition_rw (dest , offset , read_total , OP_READ );
140+ #else
141+ single_partition_rw (_partition [0 ], dest , offset , read_total , OP_READ );
142+ #endif
143+ return 0 ; // success
106144}
107145
108146mp_uint_t supervisor_flash_write_blocks (const uint8_t * src , uint32_t lba , uint32_t num_blocks ) {
@@ -112,12 +150,10 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
112150 uint32_t block_address = lba + block ;
113151 uint32_t sector_offset = block_address / blocks_per_sector * SECTOR_SIZE ;
114152 uint8_t block_offset = block_address % blocks_per_sector ;
115-
116153 if (_cache_lba != block_address ) {
117154 supervisor_flash_read_blocks (_cache , sector_offset / FILESYSTEM_BLOCK_SIZE , blocks_per_sector );
118155 _cache_lba = sector_offset ;
119156 }
120-
121157 for (uint8_t b = block_offset ; b < blocks_per_sector ; b ++ ) {
122158 // Stop copying after the last block.
123159 if (block >= num_blocks ) {
@@ -128,31 +164,34 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32
128164 FILESYSTEM_BLOCK_SIZE );
129165 block ++ ;
130166 }
131-
132167 #if CIRCUITPY_STORAGE_EXTEND
133- if (sector_offset > _partition [0 ]-> size ) {
134- // only write to partition 1
135- esp_partition_erase_range (_partition [1 ], sector_offset - _partition [0 ]-> size , SECTOR_SIZE );
136- esp_partition_write (_partition [1 ], sector_offset - _partition [0 ]-> size , _cache , SECTOR_SIZE );
137- } else if ((sector_offset + SECTOR_SIZE ) > _partition [0 ]-> size ) {
138- // first write to partition 0, then partition 1
139- uint32_t write_0 = _partition [0 ]-> size - sector_offset ;
140- uint32_t write_1 = SECTOR_SIZE - write_0 ;
141- esp_partition_erase_range (_partition [0 ], sector_offset , write_0 );
142- esp_partition_write (_partition [0 ], sector_offset , _cache , write_0 );
143- esp_partition_erase_range (_partition [1 ], 0 , write_1 );
144- esp_partition_write (_partition [1 ], 0 , _cache + write_0 , write_1 );
145- } else
168+ multi_partition_rw (_cache , sector_offset , SECTOR_SIZE , OP_WRITE );
169+ #else
170+ single_partition_rw (_partition [0 ], _cache , sector_offset , SECTOR_SIZE , OP_READ );
146171 #endif
147- {
148- // only write to partition 0
149- esp_partition_erase_range (_partition [0 ], sector_offset , SECTOR_SIZE );
150- esp_partition_write (_partition [0 ], sector_offset , _cache , SECTOR_SIZE );
151- }
152172 }
153-
154173 return 0 ; // success
155174}
156175
157176void supervisor_flash_release_cache (void ) {
158177}
178+
179+ void supervisor_flash_set_extended (bool extended ) {
180+ #if CIRCUITPY_STORAGE_EXTEND
181+ storage_extended = extended ;
182+ #endif
183+ }
184+
185+ bool supervisor_flash_get_extended (void ) {
186+ #if CIRCUITPY_STORAGE_EXTEND
187+ return storage_extended ;
188+ #else
189+ return false;
190+ #endif
191+ }
192+
193+ void supervisor_flash_update_extended (void ) {
194+ #if CIRCUITPY_STORAGE_EXTEND
195+ storage_extended = (_partition [0 ]-> size < fatfs_bytes ());
196+ #endif
197+ }
0 commit comments